feat: phase c - AS2 transport #10

Merged
KofTwentyTwo merged 1 commits from feature/phase-c-as2 into develop 2026-10-14 13:27:25 +00:00
KofTwentyTwo commented 2026-10-14 13:10:03 +00:00 (Migrated from github.com)

Summary

Phase (c) of docs/DESIGN.md: AS2.

  • Send: As2Transport signs (SHA-256/384/512; SHA-1 only when set, flagged weakCrypto), encrypts (AES-128/256 CBC or GCM; 3DES only when set, flagged), optionally compresses, posts with AS2-From/To, Message-ID and MDN options. Sync MDN: signature verified against the partner certificate, Received-Content-MIC compared, processed gives DELIVERED. Async MDN: SENT until the receipt arrives; edi.mdn.overdue alert otherwise.
  • Receive: POST /qqq/hooks/edi/as2/{transport} (outside /qqq/v1): AS2-To/From checked, decrypt with ACTIVE or NEXT key, decompress, verify, MIC, store via the encrypted payload store, inbox row keyed by Message-ID; signed sync MDN or queued async MDN (retried). Decryption, authentication and integrity failures get failure MDNs and no inbox row; storage failures get unexpected-processing-error so the partner retries. A retransmitted Message-ID gets the original MDN byte for byte. POST .../mdn receives async receipts. Async receipt URLs must be HTTPS (loopback excepted) and, for unsigned partners, on the partner's host.
  • Certificates: PEM parsed on save (private keys refused); keys only from env vars (PEM PKCS#8 or base64 PKCS#12); ACTIVE/NEXT rollover with Promote Certificate and Export Public Certificate; expiry alerts for NEXT too.
  • edi_as2_mdn table (child of outbound messages and inbox rows), also the async MDN delivery queue. VAN over AS2 (shared transport, routing by ISA).
  • Implementation: as2-lib 5.1.8 supplies algorithm enums, MIC and disposition types and its S/MIME signer; BouncyCastle (bcpkix, bcjmail) does encryption, decryption, verification, compression and MDN build/parse in memory, because as2-lib's decrypt/verify stage content in temp files and its receive side needs servlets (owner rule: no files). Recorded in DESIGN 5.5.
  • Demo: Pacific Wholesale over AS2 against an in-process peer.

Limits: RSA keys only; TLS pinning tested at the trust-manager level.

Test plan

  • ./mvnw verify after rebasing on develop (phase d): all tests pass, Checkstyle, JaCoCo gate
  • Round trips with sync and async MDN across algorithm variants; an independent BouncyCastle peer in both directions; refusals (bad signature, wrong AS2-To/From, unknown transport); retransmit; rollover and Promote; expiry and MDN-overdue alerts; VAN; no key material in logs or rows; no temp files
  • CircleCI test_only

🤖 Generated with Claude Code

## Summary Phase (c) of `docs/DESIGN.md`: AS2. - **Send:** `As2Transport` signs (SHA-256/384/512; SHA-1 only when set, flagged `weakCrypto`), encrypts (AES-128/256 CBC or GCM; 3DES only when set, flagged), optionally compresses, posts with AS2-From/To, Message-ID and MDN options. Sync MDN: signature verified against the partner certificate, Received-Content-MIC compared, `processed` gives DELIVERED. Async MDN: SENT until the receipt arrives; `edi.mdn.overdue` alert otherwise. - **Receive:** `POST /qqq/hooks/edi/as2/{transport}` (outside `/qqq/v1`): AS2-To/From checked, decrypt with ACTIVE or NEXT key, decompress, verify, MIC, store via the encrypted payload store, inbox row keyed by Message-ID; signed sync MDN or queued async MDN (retried). Decryption, authentication and integrity failures get failure MDNs and no inbox row; storage failures get `unexpected-processing-error` so the partner retries. A retransmitted Message-ID gets the original MDN byte for byte. `POST .../mdn` receives async receipts. Async receipt URLs must be HTTPS (loopback excepted) and, for unsigned partners, on the partner's host. - **Certificates:** PEM parsed on save (private keys refused); keys only from env vars (PEM PKCS#8 or base64 PKCS#12); ACTIVE/NEXT rollover with Promote Certificate and Export Public Certificate; expiry alerts for NEXT too. - **`edi_as2_mdn`** table (child of outbound messages and inbox rows), also the async MDN delivery queue. VAN over AS2 (shared transport, routing by ISA). - **Implementation:** as2-lib 5.1.8 supplies algorithm enums, MIC and disposition types and its S/MIME signer; BouncyCastle (`bcpkix`, `bcjmail`) does encryption, decryption, verification, compression and MDN build/parse in memory, because as2-lib's decrypt/verify stage content in temp files and its receive side needs servlets (owner rule: no files). Recorded in DESIGN 5.5. - **Demo:** Pacific Wholesale over AS2 against an in-process peer. Limits: RSA keys only; TLS pinning tested at the trust-manager level. ## Test plan - [x] `./mvnw verify` after rebasing on develop (phase d): all tests pass, Checkstyle, JaCoCo gate - [x] Round trips with sync and async MDN across algorithm variants; an independent BouncyCastle peer in both directions; refusals (bad signature, wrong AS2-To/From, unknown transport); retransmit; rollover and Promote; expiry and MDN-overdue alerts; VAN; no key material in logs or rows; no temp files - [ ] CircleCI `test_only` 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Sign in to join this conversation.