Skip to content

feat(node-message-broker): add E2E crypto adapter (ICryptoService)#11

Merged
tada5hi merged 6 commits into
masterfrom
feat/crypto-adapter
Jun 25, 2026
Merged

feat(node-message-broker): add E2E crypto adapter (ICryptoService)#11
tada5hi merged 6 commits into
masterfrom
feat/crypto-adapter

Conversation

@tada5hi

@tada5hi tada5hi commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Slice S1 of the node message-broker build-out (Plan 013 Track B). Adds the node-to-node end-to-end crypto port and its @privateaim/kit adapter so the broker can seal outbound and open inbound messages while the Hub only ever stores opaque ciphertext.

What's here

  • core/cryptoICryptoService port: seal(data, recipientPublicKey, info?) / open(payload, senderPublicKey, info?). The optional info is an HKDF-context passthrough for later analysis/message binding (S5/S6).
  • adapters/cryptoCryptoService wrapping the kit's sealMessage/openMessage (ECDH P-256 → per-message HKDF → AES-256-GCM). Holds the node's single private key (hex PKCS#8 PEM from config.nodePrivateKey), lazily imported and cached; peer public keys (hex SPKI PEM) imported with empty usages and cached by hex, evicting failed imports so a corrected key can retry. No AES/HKDF/nonce handling here.

Scope boundaries

  • No DI wiring into ComponentsModule — the onWakeup → pull → decrypt → deliver loop lands in S6.
  • No changes to config/build/package files.

Tests (16 crypto specs; 32 project-wide, all green)

A→B round-trip (bytes + string), per-message salt randomness, info match/mismatch, wrong-recipient, salt/IV and ciphertext/tag tampering, and the missing/invalid/non-hex key error paths.

Verification

build:types, ESLint (clean bar the pre-existing no-console warning), and nx test all pass.

Closes #4

Slice S1 of the node message-broker build-out (Plan 013 Track B): the
node-to-node end-to-end crypto port and its @privateaim/kit adapter, so the
broker can seal outbound and open inbound messages while the Hub only ever
stores opaque ciphertext.

- core/crypto: ICryptoService port (seal/open with an optional HKDF `info`
  context passthrough for later analysis/message binding).
- adapters/crypto: CryptoService wrapping the kit's sealMessage/openMessage
  (ECDH P-256 -> per-message HKDF -> AES-256-GCM). Holds the node's single
  private key (hex PKCS#8 PEM from config.nodePrivateKey), lazily imported and
  cached; peer public keys (hex SPKI PEM) imported with empty usages and cached
  by hex, evicting failed imports so a corrected key can retry.
- No AES/HKDF/nonce handling here and no DI wiring yet (that is S6).
- Tests: A->B round-trip (bytes + string), per-message salt randomness, info
  match/mismatch, wrong-recipient, salt/IV and ciphertext/tag tampering, and the
  missing/invalid/non-hex key error paths.

Closes #4
@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@tada5hi, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 33 minutes and 8 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 06d2af05-5400-4704-b70a-f9263160c06b

📥 Commits

Reviewing files that changed from the base of the PR and between a70591d and 30db250.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (8)
  • .agents/conventions.md
  • apps/node-message-broker/README.md
  • apps/node-message-broker/package.json
  • apps/node-message-broker/src/adapters/crypto/index.ts
  • apps/node-message-broker/src/adapters/crypto/service.ts
  • apps/node-message-broker/src/core/crypto/index.ts
  • apps/node-message-broker/src/core/crypto/types.ts
  • apps/node-message-broker/test/unit/adapters/crypto/service.spec.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/crypto-adapter

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

tada5hi added 5 commits June 25, 2026 12:16
…cache

- core/crypto no longer forwards `MessageSealInput` from @privateaim/kit;
  consumers import kit symbols directly from the package. New convention added
  to .agents/conventions.md: no third-party re-exports (local index.ts barrels
  for sibling modules stay).
- CryptoService.publicKeyCache is now a bounded LRU (configurable
  publicKeyCacheMax, default 1024) so a long-lived node can't grow it without
  limit; least-recently-used peers are evicted past the cap.
…cache

Replace the hand-rolled Map-based LRU in CryptoService with the lru-cache library; declare it as a runtime dependency.
…rypto

The Hub link (REST send/pull/ack + SSE wakeup) and the end-to-end crypto adapter are now implemented; mark them done and list the remaining Phase 4 work. Add crypto to the hexagonal layout sketch.
…inistic

Flip a whole byte on the base64-decoded frame (salt byte / GCM-tag byte) instead
of a single base64 character. A 1-bit flip on the last pre-padding char can land
in don't-care padding bits and decode to identical bytes, so the tamper went
undetected and the test passed spuriously (flaky with random-length plaintext).
Mirror the Hub sub-app README convention: centered icon + title, tagline, CI/node/license badges, nav row, and a License section.
@tada5hi tada5hi merged commit 9ab037d into master Jun 25, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

S1 — E2E crypto adapter (node-to-node seal/open)

1 participant