Skip to content

Surface HPKE parameter disclosure on receipts; bump sdk-ts to ^0.11.1#153

Open
ojongerius wants to merge 4 commits into
mainfrom
claude/hpke-openclaw-plugin-kuLWP
Open

Surface HPKE parameter disclosure on receipts; bump sdk-ts to ^0.11.1#153
ojongerius wants to merge 4 commits into
mainfrom
claude/hpke-openclaw-plugin-kuLWP

Conversation

@ojongerius

@ojongerius ojongerius commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Now that the daemon emits HPKE parameters_disclosure envelopes (--parameter-disclosure), this makes the plugin's read path first-class for them. The migration itself was already done in 0.9.0 (rename + daemon-owned no-op + envelope shape); nothing was broken, since the daemon owns the crypto and the Ed25519 signature canonicalizes the whole receipt body. This closes the remaining gaps so the plugin properly supports daemon-emitted envelopes.

Changes

  • ar_query_receipts gains a disclosed boolean (src/tools.ts) — set when the daemon attached an envelope, so operators/agents can see which receipts carry recoverable parameters without exporting full JSON-LD. The plugin never decrypts — recovery needs the forensic X25519 private key, which lives with the responder, not the agent host.
  • Bump @agnt-rcpt/sdk-ts to ^0.11.1 (package.json, pnpm-lock.yaml), superseding the ^0.10.0 dependabot bump (chore(deps): bump the node-deps group across 1 directory with 5 updates #152) that landed on main. As of 0.11.0 the SDK replaced @hpke/core with an in-tree node:crypto RFC 9180 base-mode implementation (tracked in chore(sdk/ts): replace @hpke/core with hand-rolled HPKE from node:crypto built-ins ar#473); a 0.x caret on ^0.10.0 cannot reach it, so ^0.10.0 still pulled @hpke/core transitively while ^0.11.1 drops it. @hpke/core and @hpke/common are gone from the lockfile. Envelope shape and on-wire format are unchanged.
  • Cross-engine read-path tests (src/tools.test.ts) — a new block pinning that a daemon-shaped envelope is accepted by the strict TS schema on query/verify, that the signature commits to it (chain stays valid), and that the ciphertext round-trips back to plaintext only with the forensic private key. These wire up the read path the static disclosure-envelope vectors didn't cover.

Why bump (dependency justification)

The bump's primary motivation is supply-chain: removing @hpke/core/@hpke/common from a crypto/audit plugin's tree in favour of the SDK's in-tree implementation. No public API or wire-format change.

Verification

pnpm typecheck, pnpm build, and pnpm test all pass (198 tests; 3 new) against the merged main (sdk-ts 0.11.1 + the node-deps group bumps from #152).

Out of scope (by decision)

No forensic-decrypt capability is added to the plugin — keeping the forensic private key off the agent host is the point of the threat model. Recovery stays with the daemon CLI / dashboard.

Related doc fix

The companion daemon-side doc correction landed as agent-receipts/ar#741 (merged) — it aligned the disclosure spec and OpenClaw installation docs with the daemon-owned model.

Revive note

Rebased onto current main via merge: resolved the package.json / pnpm-lock.yaml conflict with #152 by taking its devDep bumps and lifting sdk-ts past ^0.10.0 to ^0.11.1.

Now that the daemon emits HPKE parameters_disclosure envelopes
(--parameter-disclosure), make the plugin's read path first-class for them:

- ar_query_receipts results gain a `disclosed` boolean, set when the daemon
  attached an envelope. The plugin never decrypts — recovery needs the forensic
  private key, which lives with the responder, not the agent host.
- Bump @agnt-rcpt/sdk-ts ^0.9.0 -> ^0.11.0. The caret on 0.9.x pinned the plugin
  to a tree that still dragged @hpke/core transitively; 0.11.0 replaced it with
  an in-tree node:crypto RFC 9180 implementation, dropping a third-party crypto
  package from the supply chain. Envelope shape and wire format are unchanged.
- Add cross-engine read-path tests: a daemon-shaped envelope is accepted by the
  strict TS schema on query/verify, the Ed25519 signature commits to it, and the
  ciphertext round-trips back to plaintext only with the forensic private key.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Makes the plugin’s receipt read path explicitly surface daemon-emitted HPKE parameters_disclosure envelopes, and updates dependencies/tests so daemon-shaped envelopes are accepted and chain verification remains valid.

Changes:

  • Add a disclosed boolean to ar_query_receipts result rows based on presence of action.parameters_disclosure.
  • Add tests that exercise query + verify behavior with receipts containing HPKE disclosure envelopes, including recoverability with a forensic private key.
  • Bump @agnt-rcpt/sdk-ts to ^0.11.0 (and update the lockfile accordingly), removing transitive @hpke/* deps.

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
src/tools.ts Adds disclosed flag to ar_query_receipts summaries based on parameters_disclosure presence.
src/tools.test.ts Adds tests covering querying/verifying chains that include HPKE disclosure envelopes and recovery using a forensic key.
package.json Bumps @agnt-rcpt/sdk-ts to ^0.11.0.
pnpm-lock.yaml Updates lock to @agnt-rcpt/sdk-ts@0.11.0 and removes @hpke/* entries.
CHANGELOG.md Documents the dependency bump and the new disclosed result field.
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread src/tools.test.ts Outdated
Comment on lines +656 to +661
const [receipt] = store.query({});
const envelope = receipt!.credentialSubject.action.parameters_disclosure;
expect(envelope).toBeDefined();
// The forensic key holder (off-host) recovers the plaintext; the plugin
// never performs this step.
const recovered = await decryptDisclosure(envelope!, forensic.privateKey);
Address review feedback on the disclosure round-trip test: drop the
`receipt!` / `envelope!` non-null assertions in favour of an explicit
toBeDefined() check and a narrowing guard, so a failure reports clearly
and the test stays within the repo's no-assertions posture.
…plugin-kuLWP

# Conflicts:
#	package.json
#	pnpm-lock.yaml
@ojongerius ojongerius changed the title Surface HPKE parameter disclosure on receipts; bump sdk-ts to ^0.11.0 Surface HPKE parameter disclosure on receipts; bump sdk-ts to ^0.11.1 Jun 9, 2026
- Assert exclusivity: decryption with an unrelated forensic key rejects,
  so the "recoverable only with the forensic private key" property is
  actually verified, not just the happy path.
- Assert sequence_valid in the disclosed-chain verification, matching the
  non-disclosure sibling test.
- Centralise the forensic kid derivation in a forensicKid() helper and
  assert the stored envelope carries it, so the fingerprint convention
  lives in one place.
- Fold insertDisclosedReceipt into the generalised insertReceiptAt
  (optional disclosure envelope) instead of duplicating the
  build/sign/hash/insert pipeline.
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.

3 participants