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]

Reply via email to