diff --git a/CHANGELOG.md b/CHANGELOG.md index f7c4c6d..af3142e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ The "resource-bound authority" release: delegations can now name *where* a scope - **`resource_path` constraint** (SPEC §5.7.2, §5.7.3): binds a delegation to an opaque `resource_id` (exact byte equality, never dereferenced or normalized) and an optional `path_prefix` under segment-boundary matching — deliberately a prefix, not a glob. Absolute logical POSIX-style path model with dot-segments, backslashes, and empty interior segments rejected outright; percent-encoding does not exist in the path model, and post-verification path transformation is forbidden. NFC pre-normalization is the issuer's obligation; the verifier compares bytes exactly (a mixed-form pair fails closed; byte identity, not visual identity, is the boundary). Chain evaluation is conjunctive: effective authority can stay the same or narrow but never widen (a child may carry a broader prefix on the same resource and still verify, gaining nothing because every upstream constraint still applies), and jointly unsatisfiable constraint sets — different resources, or same-resource prefixes that don't nest — must be rejected at issuance (decoders still accept them; verification fails closed). - **Resource-identifier profiles** (SPEC §5.7.4, `docs/RESOURCE_PROFILES.md`): the shared recipes that make an opaque `resource_id` interoperable. Git profile v1 (repository identity — never a branch, commit, or checkout; renames and transfers fail closed) with known-answer and negative vectors. Profiles for platform-owned resources are authored by the platforms themselves and linked when published. - **Extension-constraint `params`** (SPEC §5.7.1, §17.7): parameterized extension constraints are now representable in signed certificates under a restricted, cross-language-deterministic value model. Type-only extension constraints serialize exactly as before; existing signed certs remain byte-stable. Closes the wire-format limitation documented in alpha.15. -- **Input bounds** (SPEC §5.1): `MAX_PROOF_BUNDLE_BYTES` (128 KiB, enforced before parsing), `MAX_JSON_NESTING_DEPTH`, and per-cert scope/constraint count and length limits. Violations route to the existing `invalid` status. +- **Input bounds** (SPEC §5.1): `MAX_PROOF_BUNDLE_BYTES` (128 KiB, applied to the received wire representation and enforced before parsing), `MAX_JSON_NESTING_DEPTH`, and per-cert scope/constraint count and length limits. Violations route to the existing `invalid` status. §5.1 also notes that the byte ceiling and `MAX_DELEGATION_CHAIN_DEPTH` are independent and can bind near the same point: a chain within the depth limit can still be rejected by the wire decoder for exceeding `MAX_PROOF_BUNDLE_BYTES` before depth is evaluated, so operational depth choices should budget for the deployment's maximum expected per-certificate content. - **Conformance suite** grows from 63 to 79 canonical vectors: 16 new verify-kind fixtures (14 `resource_path` accept/deny/unverifiable/narrowing/escape/traversal/percent-literal/root/trailing-slash/whole-resource/unsatisfiable-pair, 1 extension-`params`, 1 depth-8), with `reject_chain_too_deep` regenerated at depth 9. Byte-identical across all five SDKs. - **`VerifierContext` resource fields** (SPEC §5.16): `RequestedResourceID`, `RequestedPath`, `HasResource`, with the standard fail-closed absence semantics. - **Confinement guidance** (SPEC §15.7): a verified `resource_path` is lexical authorization, not filesystem confinement. Stated as normative properties rather than a prescribed mechanism: the deployment states its concurrent-mutation attacker model; a confinement or policy refusal leaves no operation-created effect inside or outside the boundary (with identity-safe cleanup that never touches objects a concurrent principal substituted); execution causes no effect outside the boundary; write atomicity is a separate contract; and refusal tests must attribute effects to the operation rather than assert blanket snapshot equality. Descriptor-relative traversal is the illustrative mechanism, not a mandate. diff --git a/SPEC.md b/SPEC.md index 6427f0f..4ad238c 100644 --- a/SPEC.md +++ b/SPEC.md @@ -107,6 +107,8 @@ All structures are JSON objects serialized in canonical form (see §6). **Depth ceiling semantics.** `MAX_DELEGATION_CHAIN_DEPTH` is the protocol ceiling — a wire-determinism and denial-of-service bound, not a cryptographic limit. Principals who want shorter chains bound them per-delegation; a future canonical `max_delegation_depth` constraint is planned for that purpose. (The ceiling was 3 through v1.0.0-alpha.15; multi-hop agent topologies motivated raising it to 8.) +**Interaction of size and depth limits (guidance).** `MAX_PROOF_BUNDLE_BYTES` and `MAX_DELEGATION_CHAIN_DEPTH` are independent ceilings. The byte limit applies to the received wire representation and is enforced before parsing or verification. Bundle size grows with both chain depth and per-certificate content, including scopes and constraints, so a chain within the depth ceiling can still exceed the byte ceiling. In that case, the wire decoder rejects the bundle for exceeding `MAX_PROOF_BUNDLE_BYTES` before chain depth is evaluated. A wire-facing verification surface that represents decode failures as a verification result uses the existing `invalid` status, not `chain_too_deep`. Deployments choosing an operational chain-depth limit SHOULD budget for their maximum expected per-certificate content, not depth alone. + ### 5.2 HybridPublicKey Every public key in the protocol is a pair: one Ed25519 component and one ML-DSA-65 component. Canonical JSON form (keys in lex order):