Kieran, all — Kieran asked me (Oct 27, on the WIMSE thread) to repost the tally description here so the design record is public. Doing that now, and taking on his mode-marker point in the same pass. He's right that several of the thirteen negative cases read differently depending on which mode governs the cumulative key, so each case below gets both readings.
THE TALLY, RESTATED The delegate maintains the tally: the running account of value consumed under the grant's spend ceilings. It carries the tally with each request. The verifier cross-checks the presented tally against its own records, and on any disagreement resolves against the higher figure, in favor of denial (my draft's Section 7.1, check 8). The composed chain needs no new shared writer. The honest limit is the one Kieran named: a delegate that understates its tally across two verifiers can double-spend the cumulative total where neither verifier sees the other's records. That exposure is bounded in value by the per-transaction cap per action, bounded in time by expiry, and noisy by construction — denial logs are how cap-probing becomes visible (Sections 7.2, 10.4). Short version: the delegate holds the total, and every verifier distrusts it. TWO MODES Kieran's framing, which I accept. There are two coherent modes for a cumulative key, and composition has to say which one governs: 1. delegate-tally-with-distrust — the delegate holds the running total; verifiers distrust it, cross-check locally, and fail toward denial. Exactness is not guaranteed; inexactness is tolerated and bounded (per-transaction caps, expiry, denial logs). 2. single-writer-exact — one writer, typically a custody server, maintains the authoritative total. Every exercise goes through it, and the ceiling is exact. The rule: every cumulative key in a composed chain declares its mode. The hazard Kieran named is real: a custody server that accepts a user-issued root and starts enforcing a spend ceiling has silently flipped that key from mode 1 to mode 2 unless the chain says otherwise. A design analyzed as bounded-inexact does not get to be deployed as supposedly-exact without anyone declaring the change. The marker has to travel with the key, and every hop that enforces the bound restates the mode it enforces under. I'll leave the encoding to the -03 composition work — the requirement is just this: no cumulative key without a declared mode, and no hop enforces a bound under a mode it hasn't declared. THE THIRTEEN, UNDER EACH MODE R1 (human-readable intent). Mode-independent. The ceremony states intent in human language at issuance; the tally doesn't change what the user must understand. An opaque scope string approved blind fails the same under both modes. R2 (least-privilege bounds). Nearly mode-independent. Both modes reject the creative interpreter. The only difference is where enforcement lives: each verifier locally (mode 1) versus the server (mode 2). Under mode 1, a verifier that interprets broadly is itself the failure point, and nothing in the tally saves it. R3 (tiered action classes). Mode-independent in outcome. Under mode 1, a Send-only grant carries no spend ceiling in the tally at all, so a spend attempt fails the tier check before the tally is even consulted. The ladder is strict in both modes; the tally never authorizes what the tier didn't grant. R4 (mandatory expiry). This one reads differently, and it's the case Kieran was pointing at. Under mode 2, a missing expiry is a forever key: bad, but the ledger stays exact. Under mode 1, expiry is load-bearing for the entire bounded-inexactness argument — it is one of the three bounds on the tally error, alongside the per-transaction cap and the denial logs. Strip expiry and the double-spend exposure isn't just long-lived, it's unbounded in time. So under mode 1, R4 isn't a backstop, it's structural. A mode-1 deployment without enforced expiry hasn't weakened a control; it has voided the error bound the design was analyzed under. R5 (amortized authentication). Mode-independent. The grant carries the authentication in both modes; per-action re-auth breaks the deal either way. The tally doesn't touch this. R6 (atomic revocation). Same requirement, different difficulty. Under mode 2, revocation is structurally simple: flip the writer and every exercise stops. Under mode 1, revocation has to reach every verifier, and each verifier has to actually check — the distributed version of the problem. The test still demands one action, effective everywhere, immediately. Mode 1 just has more places to get it wrong, which is why the requirement is stated absolutely. R7 (local verifiability). The sharpest difference, and it's Kieran's silent-flip hazard stated as a test. Under mode 1, the requirement holds as written: the verifier evaluates locally, no per-action callbacks, and the carried tally is exactly what makes that possible. Under mode 2, the custody server is in the path of every exercise by design, so the requirement as written doesn't apply the same way — a mode-2 reading of R7 has to be restated, with the server as trusted infrastructure rather than a per-action oracle, and the properties R7 protects (offline operation, no tracking beacon, no per-action single point of failure) re-examined against a server-in-the-path architecture. Composing a user-issued root into custody enforcement without restating R7 is where the silent flip happens. R8 (audience binding). Outcome mode-independent: mismatch rejected in both. One second-order note under mode 1: the tally is per-grant, so a successful cross-service replay would corrupt the books as well as the door — audience binding protects the accounting, not just access. The test itself reads the same. R9 (delegate binding). Outcome mode-independent: the artifact alone confers nothing in both modes. Under mode 1 there is one extra load on this requirement: the whole distrust model anchors on the presenter authenticating as the named delegate. If presenter authentication fails, verifiers have nothing to distrust correctly — the tally becomes numbers without an owner. So R9 is load-bearing for mode 1 in a way it isn't for mode 2, where the server authenticates each exercise itself. R10 (spend ceilings). The central case, and the one where "the cap holds" means two different things. Scenario A ($32 order against a $25 cap): under mode 2 the cap holds exactly — the server sees every exercise and the 26th dollar never clears. Under mode 1 the cap holds within bounded error: each verifier enforces the cap against the presented tally, but a delegate understating across two verifiers can clear up to the cap at each. The exposure stays bounded per action by the per-transaction cap and in time by expiry, but it is not zero. The negative test still must fail the silent over-cap order in both modes; what differs is the guarantee behind "holds": exact versus bounded-inexact. Scenario B (the delegate raising its own cap): identical in both modes — caps are fixed at issuance, and the tally can report but never authorize. R11 (no self-escalation). Mode-independent. Conversational assent is not issuance under either mode. The tally can't create new tiers and the server won't honor unissued ones. R12 (attributable audit). Same requirement, different shape of the answer. Under mode 2, attribution is centralized: the server's ledger is the ordered, exact record, and "which grant did this" has one place to ask. Under mode 1, attribution is distributed: each verifier's records plus the carried tally, correlated after the fact, with the denial logs (7.2) as part of the machinery. The test still fails the unattributable action in both modes, but "attributable" is structurally harder under mode 1 — which is why the grant identifier has to travel with every action and every tally presentation. There is no central ledger to reconstruct from. R13 (informed consent at issuance). Mode-independent, like R1. The ceremony presents the exact authority being granted; the accounting mode doesn't change what the user must be told. A vague prompt granting specific powers fails in both modes. That's the repost, with the distinction carried through as Kieran asked. Five cases genuinely change reading between modes (R4, R6, R7, R10, R12); the rest don't, and I'm not going to pretend otherwise. Kieran — the marker-per-key requirement is yours to carry into the -03 composition language; the encoding is your call. And my answer on placement: both. The key declares the mode it was issued under; each hop declares the mode it enforces under. No silent changes — if a custody server takes a delegate-tally root and starts enforcing it as single-writer-exact, that transition is declared in the chain or the chain is non-conformant. Any mode disagreement without a declared transition gets the same treatment as any tally disagreement: resolve against the higher figure, in favor of denial. — Caleb Dyer _______________________________________________ OAuth mailing list -- [email protected] To unsubscribe send an email to [email protected]
