Skip to content

delego 0.3.0 — implement wire protocol 0.3 (query-fold) - #12

Merged
koishore merged 3 commits into
mainfrom
feat/protocol-0.3
Jun 10, 2026
Merged

delego 0.3.0 — implement wire protocol 0.3 (query-fold)#12
koishore merged 3 commits into
mainfrom
feat/protocol-0.3

Conversation

@koishore

Copy link
Copy Markdown
Member

What

Implements wire protocol 0.3 (__protocol_version__ = "0.3", package 0.3.0).

Breaking — the URL query is folded into the action_fingerprint preimage (spec §4.2)

  • ProposedAction.canonical_query implements the spec's canonicalization steps mechanically (split on &, first-= split, RFC 3986 percent-decoding with + as space, sort by name then value by code point, duplicates preserved, fragment excluded).
  • The preimage always carries "query" ([] for a bare URL) — every fingerprint changes. /orders?to=me and /orders?to=attacker are now different actions, so an approval for one cannot release the other (the last structural confused-deputy gap).
  • Approvals parked by ≤ 0.2.x no longer match (deny, fail-closed); re-propose them.
  • Brokers forward the now-fingerprint-bound query (fingerprinted_url = scheme+host+path+query) and refuse only a #fragment (BrokerRefusal, never a silent strip). New has_fragment / canonical_query; has_query kept for 0.2-era adapters.

Fixed

  • Audit completeness (spec §7/§8): resolve() with an unknown approval id and broker refusals/failures during execution now leave execution/deny receipts (previously both were invisible in the ledger).
  • Rate limits hold under concurrency: the 0.2.3 changelog claimed the evaluate→execute→append sequence was serialized, but engine.propose never used audit.transaction(). Rate-limited policies now run the whole sequence under the ledger lock — cap exact on one host; consistency class documented in SECURITY.md. Regression test: 8 concurrent proposes vs max: 2 → exactly 2 allows.

Added

  • delego verify prints the chain head, accepts --expected-head SEQ:HASH, and — with no anchor — states that truncation cannot be ruled out (spec §8.3 auditor obligation).
  • Policy.has_rate_limit; server.json bumped to 0.3.0.

Not included

The §9 authorization token (optional profile; separate roadmap item).

Verification

  • 43 tests green (new: spec-exact query canonicalization, query confused-deputy at resolve, rate-limit cap under 8-way concurrency, broker-refusal receipt, unknown-id receipt).
  • examples/demo.py end-to-end green; CLI verify smoke-tested (anchor match + truncation detection).
  • The specification repo's full conformance suite passes against this branch locally (regenerated hashing/resolve vectors land in a follow-up spec PR — merge this PR first, the spec repo's conformance CI installs delego@main).

koishore added 3 commits June 10, 2026 08:00
…rprint

The action_fingerprint preimage now carries the canonicalized query (spec
$4.2): split on '&', first-'=' split, RFC 3986 percent-decoding with '+' as
space, sorted by name then value by code point, duplicates preserved, fragment
excluded; a bare URL contributes "query": []. Every fingerprint changes —
breaking; protocol bumps to 0.3, package to 0.3.0. /orders?to=me and
/orders?to=attacker are now different actions, so an approval for one cannot
release the other.

Brokers forward the (now fingerprint-bound) query and refuse only a #fragment.
Rate-limited policies run propose's count->decide->execute->append inside the
ledger transaction lock, making the cap exact on one host — the 0.2.3
changelog claimed this but engine.propose never used audit.transaction().
'delego verify' prints the chain head, accepts --expected-head, and states
that truncation cannot be ruled out when no anchor is given (spec $8.3).
Two paths violated 'every decision and execution is recorded as a receipt'
(spec $7/$8): resolve() with an unknown approval id denied without writing
to the ledger (approval-id probing left no evidence), and a broker
refusal/failure during execution propagated with nothing written — including
the broker's own BrokerRefusal guard. Both are now recorded as
execution/deny receipts; the broker exception is still re-raised.
@koishore
koishore merged commit 82a384c into main Jun 10, 2026
3 checks passed
@koishore
koishore deleted the feat/protocol-0.3 branch June 10, 2026 11:17
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.

1 participant