# AS2 Protocol Reference

Requires feature flag: `as2`

## Overview

AS2 (RFC 4130) support in `asx-rs` is exposed through free functions in `asx_rs::as2`.

Primary flows:

1. Outbound send with optional compression, signing, and encryption.
2. Inbound receive with trust verification/decryption.
3. MDN generation and parse/classification.
4. Reliability and dedup integration for MDN-linked receive paths.

## Public Entry Points

### Send

```rust
pub fn send_sync(
    session: &SessionContext,
    event_bus: &EventBus,
    request: As2SendRequest,
) -> Result<As2SendOutput>
```

Async-safe wrapper for Tokio services:

```rust
pub async fn send_async(
    session: &SessionContext,
    event_bus: &EventBus,
    request: As2SendRequest,
) -> Result<As2SendOutput>
```

Behavior notes:

1. RFC 5402 order is enforced for compression-enabled messages: `compress -> sign -> encrypt`.
2. MIC is computed over the exact octet sequence `Content-Type: ...\r\n\r\n<payload>` (RFC 4130 section 7.3.1).
3. MIC canonicalization does not trim, normalize, or transfer-decode bytes before hashing; both `Content-Type` and payload bytes are hashed exactly as supplied to send/ingress paths (RFC 4130 §7.3.1 / §7.4.2 alignment).
4. Policy-controlled protocol events are emitted via `EventBus`.

### Receive (owned payload)

```rust
pub fn receive_sync(
    session: &SessionContext,
    payload: Vec<u8>,
    verifier: &dyn As2TrustVerifier,
) -> Result<DomainReady<Arc<[u8]>>>
```

Async-safe wrapper for Tokio services:

```rust
pub async fn receive_async(
    session: &SessionContext,
    payload: Vec<u8>,
    verifier: Arc<dyn As2TrustVerifier + Send + Sync>,
) -> Result<DomainReady<Arc<[u8]>>>
```

### Token-enforced strict runtime sessions

For regulated deployments that require explicit startup proof, bind validated
session context once and then use standard AS2 entry points:

```rust
let strict_session = asx_rs::presets::session_with_strict_runtime_bootstrap_token(
    "as2_receive_sync",
    &bootstrap_token,
    &session,
)?;

let received = asx_rs::as2::receive_sync(&strict_session, payload, verifier)?;
```

In non-testing builds, strict interop AS2 entry points fail closed unless the
session is startup-validated with
`asx_rs::presets::session_with_strict_runtime_bootstrap_token(...)`.

### Receive (streaming ingress)

```rust
pub async fn receive_stream<R: tokio::io::AsyncRead + Unpin>(
    session: &SessionContext,
    policy: &As2ReceivePolicy,
    reader: R,
    verifier: &dyn AsyncAs2TrustVerifier,
    limits: StreamLimits,
) -> Result<DomainReady<Arc<[u8]>>>
```

```rust
pub async fn receive_stream_with_metrics<R: tokio::io::AsyncRead + Unpin>(
    session: &SessionContext,
    policy: &As2ReceivePolicy,
    reader: R,
    verifier: &dyn AsyncAs2TrustVerifier,
    limits: StreamLimits,
) -> Result<(DomainReady<Arc<[u8]>>, StreamReadMetrics)>
```

### Receive + MDN + reliability

```rust
pub fn receive_with_mdn_with_reliability(
    session: &SessionContext,
    event_bus: &EventBus,
    request: As2ReceiveMdnRequest,
    reconciliation_hook: &dyn ReconciliationStorage,
    dedup_backend: &dyn DedupStorage,
    verifier: &dyn As2TrustVerifier,
) -> Result<As2ReceiveMdnOutput>
```

Borrowed variant:

```rust
pub fn receive_with_mdn_with_reliability_mdn_ref(
    session: &SessionContext,
    event_bus: &EventBus,
    request: As2ReceiveMdnRefRequest<'_>,
    reconciliation_hook: &dyn ReconciliationStorage,
    dedup_backend: &dyn DedupStorage,
    verifier: &dyn As2TrustVerifier,
) -> Result<As2ReceiveMdnOutput>
```

### MDN generation

```rust
pub fn generate_mdn(
    session: &SessionContext,
    event_bus: &EventBus,
    request: As2GenerateMdnRequest,
) -> Result<As2MdnOutput>
```

## Core Types

1. `As2SendPolicy`: outbound cryptographic/interop behavior.
2. `As2SendCredentials`: PEM signing/encryption material.
3. `As2SendOutput`: transport headers/body/MIC for HTTP send.
4. `As2ReceiveMdnRequest`: payload + MDN + policy input for reliability path.
5. `ParsedAs2Mdn`: parsed disposition/MIC/signature metadata.

## Interop Notes

1. Strict mode is the default profile.
2. Relaxed mode remains feature-gated (`interop-relaxed`) and should be used only with scoped, audit-visible exception policies.
3. Production deployments should keep strict mode unless exceptions are explicitly governed.

## Audit Events

AS2 flows emit protocol events through `EventBus` (for example: outbound prepared, MIC computed, message signed/encrypted, MDN received, duplicate detected).

EventBus constructors are strict by default. Use fail-closed mode in regulated deployments and opt into best-effort explicitly via `EventBus::new_with_config_and_mode(..., EventEmissionMode::BestEffort)` only where transport progress must not depend on subscriber liveness.
