From 696ea76a6227b3fce35209d6c652dda54a6294ef Mon Sep 17 00:00:00 2001 From: Koishore Roy Date: Thu, 4 Jun 2026 03:45:07 +0530 Subject: [PATCH] =?UTF-8?q?Normalise=20versions=20to=20the=200.x=20scheme;?= =?UTF-8?q?=20correct=20the=20=C2=A78.1=20truncation=20claim?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Version notation: spec/protocol is two-component 0.x everywhere (header, §2.1 matrix, §10, CHANGELOG, README badge/status). Only the reference *package* is 0.x.y. conformance.py now parses a two-component spec version (the regex required three components and would have failed on "0.3"). - §8.1: the chain does NOT detect truncation of the most recent receipts (a truncated prefix verifies clean), nor a holder of the local signing key. Added a normative caveat requiring the head be anchored externally for rollback detection, and corrected the false "deleting any receipt breaks a check" line. Matches the honest wording now in the reference's README/SECURITY. validate.py and conformance.py both green; reference 0.2 <= spec 0.3. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 19 ++++++++++++++----- README.md | 11 ++++++----- conformance.py | 3 ++- spec.md | 34 +++++++++++++++++++++++----------- 4 files changed, 45 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5abcac..4e21d43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,16 @@ versioned independently of the reference implementation and **leads** it: a behaviour is specified (marked *draft — not yet in reference*) before the reference implements it. See [`spec.md` §2.1](spec.md) for the version matrix. -## [0.3.0-draft] — Unreleased +## [0.3-draft] — Unreleased + +### Fixed +- §8.1 corrected: hash-chaining does **not** detect truncation of the most recent + receipts (a truncated prefix verifies clean), nor a holder of the local signing + key. Added a normative caveat requiring external head anchoring for rollback + detection — the prior "deleting any receipt breaks a check" claim was wrong. +- Version notation normalised to the `0.x` scheme everywhere (spec/protocol is + `0.x`; the reference *package* is `0.x.y`). `conformance.py` now parses a + two-component spec version. ### Added (0.3, draft — not yet in reference) - §4.2 — the URL **query string** is folded into the `action_fingerprint` @@ -34,9 +43,9 @@ reference implements it. See [`spec.md` §2.1](spec.md) for the version matrix. ### Changed - §6 — the determinism requirement now names *evaluation time* as an input (the `rate_limit` window), rather than implying a time-independent function. -- Document version → 0.3.0-draft. +- Document version → 0.3-draft. -## [0.1.0-draft] — initial specification +## [0.1-draft] — initial specification ### Added - §3 canonical JSON; §4 intent hash + action fingerprint; §5–§6 deterministic @@ -45,5 +54,5 @@ reference implements it. See [`spec.md` §2.1](spec.md) for the version matrix. §9 authorization-token draft. - JSON Schemas (`schema/`), CTK vectors (`ctk/`), and `validate.py`. -[0.3.0-draft]: https://github.com/Delego-Dev/specification -[0.1.0-draft]: https://github.com/Delego-Dev/specification/releases/tag/v0.1.0 +[0.3-draft]: https://github.com/Delego-Dev/specification +[0.1-draft]: https://github.com/Delego-Dev/specification/releases/tag/v0.1 diff --git a/README.md b/README.md index a75903c..c43a194 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Contributions welcome](https://img.shields.io/badge/contributions-welcome-green.svg)](CONTRIBUTING.md) [![License](https://img.shields.io/badge/license-Apache--2.0-blue.svg)](LICENSE) -[![Spec](https://img.shields.io/badge/spec-v0.1.0--draft-orange.svg)](spec.md) +[![Spec](https://img.shields.io/badge/spec-v0.3--draft-orange.svg)](spec.md) The open specification for **delego** — a deterministic **authorization & audit protocol for AI-agent actions**. It defines how an action proposed by an agent @@ -69,10 +69,11 @@ reproduce them; see [§10 Conformance](spec.md#10-conformance). ## Status & versioning -**v0.1.0 — draft.** §3–§8 formalize the reference implementation; §9 -(Authorization Token) defines the next protocol increment and is not yet -implemented. The wire format is versioned with the spec — a breaking change to -the receipt fields bumps the version together (see [§8.2](spec.md#82-schema-versioning)). +**v0.3 — draft.** The spec/protocol is versioned `0.x` (the reference *package* +is `0.x.y`). 0.1–0.2 are reference-backed; 0.3 (query-string fingerprint §4.2, +authorization token §9) is specified but not yet in the reference. See the +[§2.1 version matrix](spec.md#21-protocol-versions). A breaking change to the +receipt fields bumps the version (see [§8.2](spec.md#82-schema-versioning)). ## Contributing diff --git a/conformance.py b/conformance.py index 28ffee5..01c805d 100644 --- a/conformance.py +++ b/conformance.py @@ -44,7 +44,8 @@ def ok(msg: str) -> None: def spec_version() -> tuple[int, ...]: text = (ROOT / "spec.md").read_text(encoding="utf-8") - m = re.search(r"\*\*Version:\*\*\s*([0-9]+\.[0-9]+\.[0-9]+)", text) + # Spec/protocol versions are two-component (0.x); tolerate a patch too. + m = re.search(r"\*\*Version:\*\*\s*([0-9]+\.[0-9]+(?:\.[0-9]+)?)", text) return tuple(int(x) for x in m.group(1).split(".")) diff --git a/spec.md b/spec.md index 351bd5d..f558a72 100644 --- a/spec.md +++ b/spec.md @@ -1,6 +1,6 @@ # delego Wire Specification -**Version:** 0.3.0 (draft) · **Status:** Draft · **License:** Apache-2.0 +**Version:** 0.3 (draft) · **Status:** Draft · **License:** Apache-2.0 This document specifies the **delego protocol**: how an *action proposed by an agent* is authorized — deterministically, with no LLM in the decision path — @@ -48,12 +48,12 @@ of this document. | Version | Status | Adds | |---------|--------|------| -| **0.1.0** | reference-complete, CTK-backed | Canonical JSON (§3); intent hash + action fingerprint (§4); deterministic policy & decision, first-match-wins, fail-closed (§5–§6); fingerprint-bound approval / confused-deputy guard (§7); append-only, hash-linked, Ed25519-signed audit chain + verification (§8). | -| **0.2.0** | reference-complete, CTK-backed | Approval & audit hardening. Approvals are additionally bound to the `intent_hash` and made **single-use** (§7); an approved action's `execution` receipt carries the rule it was parked under, so `rate_limit` counts it (§5, §8); verification treats a malformed or partial receipt as a *failure* rather than aborting the walk (§8.1). | -| **0.3.0** | **draft — not yet in reference** | Query-string-bound fingerprint (§4.2); signed authorization token (§9, §9.1). | +| **0.1** | reference-complete, CTK-backed | Canonical JSON (§3); intent hash + action fingerprint (§4); deterministic policy & decision, first-match-wins, fail-closed (§5–§6); fingerprint-bound approval / confused-deputy guard (§7); append-only, hash-linked, Ed25519-signed audit chain + verification (§8). | +| **0.2** | reference-complete, CTK-backed | Approval & audit hardening. Approvals are additionally bound to the `intent_hash` and made **single-use** (§7); an approved action's `execution` receipt carries the rule it was parked under, so `rate_limit` counts it (§5, §8); verification treats a malformed or partial receipt as a *failure* rather than aborting the walk (§8.1). | +| **0.3** | **draft — not yet in reference** | Query-string-bound fingerprint (§4.2); signed authorization token (§9, §9.1). | -This document is at **0.3.0 (draft)**; the reference implements **0.2.0**. Clauses -introduced after 0.1.0 are tagged inline — *(since 0.2)* for reference-backed +This document is at **0.3 (draft)**; the reference implements **0.2**. Clauses +introduced after 0.1 are tagged inline — *(since 0.2)* for reference-backed behaviour, *(0.3, draft)* for the not-yet-implemented frontier. ## 3. Canonicalization (NORMATIVE) @@ -311,7 +311,19 @@ An Auditor verifies a chain by walking it in `seq` order. For each receipt it 3. **Signature** — `Ed25519_verify(pubkey, signature, UTF8(entry_hash))` succeeds. The chain is valid iff every check passes for every receipt. Editing, -reordering, inserting, or deleting any receipt breaks at least one check. +reordering, inserting, or deleting a receipt **from anywhere but the end** breaks +at least one check. + +**Truncation is not detected by chaining alone (NORMATIVE caveat).** Removing the +most recent receipts leaves a shorter but internally consistent prefix that +verifies clean — the chain commits each receipt to its predecessor, not to the +*length* of the log. Likewise, an Auditor that only holds the Authorizer's public +key cannot detect this, and an attacker who holds the (local) signing key can +re-sign an arbitrary rewrite. To detect truncation or rollback, the head **MUST** +be anchored outside the log: persist the latest `(seq, entry_hash)` somewhere the +writer can't unilaterally rewrite (a remote store, a second host, a transparency +log) and reject a chain whose last receipt doesn't match it. High-assurance +deployments **SHOULD** also keep the signing key in an HSM/KMS. *(since 0.2)* A **structurally invalid** receipt — one not parseable as JSON, or missing any of the eleven signed fields — **MUST** be treated as a verification @@ -381,15 +393,15 @@ See [`examples/authorization-token.md`](examples/authorization-token.md) and An implementation declares the highest protocol version (§2.1) it implements, and **MUST** satisfy every clause at or below that version and reproduce that version's -CTK vectors. The reference implements **0.2.0**. +CTK vectors. The reference implements **0.2**. -**0.1.0** +**0.1** - A conformant **Authorizer** MUST implement §3–§8 and reproduce the CTK `hashing` and `decisions` vectors, and produce chains that verify per §8.1. - A conformant **Auditor** MUST implement §8.1 and agree with the CTK `chain` expectations (valid and tampered). -**0.2.0** (additionally) +**0.2** (additionally) - An **Authorizer** MUST implement the §7 intent guard and single-use semantics and reproduce the CTK `resolve` vectors; MUST attribute an approved action's `allow` receipt to its parking rule (§5, §8); MUST `deny` a `rate_limit` it @@ -397,7 +409,7 @@ CTK vectors. The reference implements **0.2.0**. - An **Auditor** MUST treat a malformed or partial receipt as a verification failure, not an error (§8.1). -**0.3.0** (draft — not yet in reference) +**0.3** (draft — not yet in reference) - An **Authorizer** binds the query string into the fingerprint (§4.2) and MAY mint authorization tokens (§9). - A **Broker** that participates in §9 MUST implement §9.1.