[kafka pr-1 · 03/6] Slice 03 — Default-private KAs with --public override#392
Open
zsculac wants to merge 12 commits intofeat/kafka-walking-skeletonfrom
Open
[kafka pr-1 · 03/6] Slice 03 — Default-private KAs with --public override#392zsculac wants to merge 12 commits intofeat/kafka-walking-skeletonfrom
zsculac wants to merge 12 commits intofeat/kafka-walking-skeletonfrom
Conversation
…pter
Route adapter at packages/cli/src/daemon/routes/kafka.ts now resolves the
privacy posture (default: private: true) from the request body and wraps
the bare KA in either {private: KA} or {public: KA} before calling
agent.publish(). The response echoes the resolved `private` boolean.
New daemon-routes-kafka.test.ts unit-tests all three envelope-selection cases.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- api-client.registerKafkaEndpoint accepts optional private?: boolean and returns private: boolean in the response - CLI adds --public flag (default is private; --public flips to private: false) - CLI stdout now prints 'Private: <boolean>' for unambiguous confirmation - Smoke tests updated: assert default omits private field (route defaults to private), --public sends private: false, and stdout echoes resolved value Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… test Split the single e2e scenario into: - public (--public): asserts stdout shows 'Private: false' and SPARQL returns KA - private (default): asserts stdout shows 'Private: true' and HTTP 200; SPARQL behavior for encrypted KAs is documented as out-of-scope for single-node devnet (encryption-to-CG-participants requires multi-node setup) Both tests are gated on DKG_KAFKA_E2E=1 and skip by default in CI. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…onse shape The api-client.test.ts mock for registerKafkaEndpoint omitted the `private` field from the response body. Since the api-client return type now declares `private: boolean` as required, the mock no longer matched the real wire shape. Adding `private: true` (the default-private posture matching this test's omitted-field request) keeps the fixture in sync. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…leniency Previously the route silently coerced non-boolean values for `private` (e.g. the string "false") to private via the `!== false` predicate. Now the route explicitly rejects non-booleans with 400, matching the strict type-checking already applied to broker/topic/messageFormat in the same handler. The remaining `!== false` predicate is preserved for the omitted-defaults-to-private semantic, with a comment warning future readers not to "tighten" it to `=== true` (which would silently break the default). Adds a rejection-case unit test in daemon-routes-kafka.test.ts. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The kafka route had a local `isNonEmptyString` guard that future routes (slice 02, slice 07) will need. Moves it to http-utils.ts next to the other validators so the wider daemon can reuse a single guard rather than copy-pasting the predicate. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The kafka route adapter built the { public }/{ private } envelope inline
with an `as Record<string, unknown>` cast. The same pattern recurs in
epcis.ts and is the load-bearing publish-time decision for slice 07's
subscription work. Extracts the wrap into a small typed helper so:
- The cast at the call site disappears (the helper returns JsonLdContent,
which is exactly what DKGAgent.publish() accepts).
- Future routes adopt the helper instead of re-deriving envelope shape.
- The privacy semantics live in one documented location.
Adds JsonLdContent / JsonLdDocument re-exports to the agent package
barrel so consumers don't reach into deep import paths. Adds a 4-case
unit test for the helper. epcis.ts is intentionally left untouched.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Slice 02's useLocalCg flag and slice 07's subscription privacy flag both need the same strict-boolean-or-undefined validation that kafka.ts shipped inline in slice 03. Promotes the validator into http-utils so future routes adopt one helper instead of copy-pasting the predicate. The "safe failure mode" comment on the !== false predicate is preserved because that semantic isn't captured by the validator's docstring. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Slices 02 (local-vs-shared CG) and 07 (subscription) both touch the kafka route and will need exactly the same in-process mocks for IncomingMessage / ServerResponse / RequestContext that slice 03 wrote. Extracting now establishes the shared module before those tickets land. makeFakeRequest gains optional method/url overrides; makeRequestContext generalizes the agent-publish capture so callers can either rely on the default capturing mock or supply an onPublish hook to drive custom behavior. The 6 existing kafka route tests are unchanged in semantics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The makeRequestContext docstring did not capture the load-bearing detail that publish capture is unconditional — supplying onPublish drives the return value to the route handler but does NOT silence publishCalls. Future test authors needed this contract spelled out. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Trim multi-line JSDoc that re-stated what function names and signatures already say. Keep only load-bearing rationale: the "do not write a response" half-line on isNonEmptyString (distinguishes from validate* helpers), the "do NOT tighten to === true" warning on the privacy predicate, the next-tick emit detail on makeFakeRequest, and the publishCalls/onPublish contract on makeRequestContext. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…--public help
The walking-skeleton e2e test explicitly notes that the participant-encryption
behavior of V10's `{private: ...}` envelope was out of scope to verify on a
single-node devnet. The simpler "default: private" tells the user the only
thing they need to know to use the flag correctly; ADR-0004 carries the
semantic detail.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack position
Sub-PR stacking on the kafka foundation branch (PR #390).
```
main
└── feat/kafka-walking-skeleton (foundation rollup, PR #390 — draft)
└── feat/kafka-default-private ← THIS PR
```
Independent siblings (no merge order requirement):
Mechanical rebase conflict in `routes/kafka.ts` after a sibling lands.
What slice 03 adds
Endpoint KAs default to `private: true`. Override with `--public` /
`"private": false`. Implements the default-private half of ADR-0004.
The kafka package itself stays privacy-agnostic — the boolean lives entirely
in the route adapter. `KafkaEndpointPublisher.publish` still receives the
bare KA from slice-01; the adapter chooses `{public: ka}` vs `{private: ka}`
envelope before calling `agent.publish`. `packages/kafka/src/` diff against
the foundation should be empty or near-empty.
Test plan
Related