Skip to main content

WAI Extension: Cache Authority

Mirrored from the canonical text at commit 260cbd09 ().

Status: Draft. Registers the record wai.delivery.cache: who served what a node holds, and on whose authority. A neighbourhood cache or a peer that serves, from what it holds, objects of groups another key signed changes no byte: the publisher’s receipts verify whatever it serves (jwp-receipts §3), and a receiver’s acknowledgement of it (settlement §3) is already the signed word that it served. What was missing is the authority to place such a node and a statement for a bearer instance of its own with no path back. This extension adds two authorities a node’s operator gives in its key log — the role cache/serve and the class authority cache-transmission (§4) — and one claim, a jwp-receipts claim of class cache-transmission (jwp-receipts §2.4.18, §5 here), by which a node declares a multicast or unidirectional instance of its own and the objects of a group it sent over it, with a root under the publisher’s tree checked without the bytes. A verifier places a server key by the key logs its relying party names, in jwp-receipts’ three levels (§4.4); derives the bearer verdict with the caches’ instances beside the publisher’s, crediting a cache per instance and only for what it says it sent (§7); and counts, of a population of receiver keys stated for a region, how many held an object by a deadline on their own signed word, with a miss rate in parts per million held to a target (§8). A node states its plan for its own instance in a carousel schedule claim signed by its own key (§5.6). WAI defines no transport. The reference implementation is the cache_authority module of wai-rs (feature cache_authority), with the class’s body in claim_receipt::bearer; the corpus is live-conformance/cache-authority/, and its second implementation is live-conformance/cache_authority_verify.py. Keywords MUST, MUST NOT, SHOULD, MAY are RFC 2119/8174.

Texts read for this revision: draft-ietf-moq-transport-23 (MOQT) §2.1, §7.1 and §7.9; RFC 9421 §2.3, §2.5, §3.3.6, §4.3 and §7.2.8; RFC 9211 §2, §2.1, §2.2, §2.5 and §6; RFC 7574 §3.2, §9.2 and §11.2.4; RFC 8006 §4.3.8 and RFC 9388 §2.1.1.1 and §4.1. A clause number of one of them in this text is that text’s.

1. Scope

In scope: the authorities a node that serves from what it holds signs under, who gives them, and how a verifier places a server key (§4); the cache-transmission claim and a node’s schedule of its own instance (§5); what a receiver of a peer-served object does (§6); the bearer verdict with a cache’s instances and their schedules (§7); and the count of a stated population’s receivers that held an object by a deadline (§8).

Out of scope: a transport; how a node chooses what to keep, or an asker whom to fetch from, which are holdings §5.4’s; a record of service beside settlement’s acknowledgement and declaration (settlement §3, §4), which this extension does not add; where a receiver is, which is its own state (§8.1); a price, which is rung-price’s; and which settlement object class carries an object a node serves on request from what it holds outside a room (§9).

Relationship to the core spec: wai.delivery.cache is a record (SPEC §5): the cache-transmission claim is a signed record a WAI tool emits and verifies. It names no payload format and is not dispatchable.

2. Terms

3. Why two authorities and one claim

4. Authorities

4.1 What cache/serve lets a key do

A key that holds cache/serve acts as a node that serves, from what it holds, objects of groups another key signed. Under it the key signs its holdings records (holdings §4) and its declarations of what it served (settlement §4), and is the upstream of the acknowledgements its receivers sign (settlement §3). A key that also holds cache-transmission signs cache-transmission claims (§5), each declaring a bearer instance of its own and the objects of one group it sent over it, and one that holds schedule as well schedules those instances (§5.6). That is all either covers.

4.2 What neither lets a key claim

A node’s class under jwp-receipts §4 is set by what it does, not by these authorities: a §4.1 relay when it reads the receipts it forwards (jwp-receipts §4.5), an HTTP cache under jwp-receipts §4.5 when it stores and serves byte for byte. jwp-receipts §4.3 binds it either way.

4.3 Who gives them

The node’s operator’s origin lists, in its key log, the nodes it runs with cache/serve, with cache-transmission those that declare instances of their own, and with schedule those that schedule them, as it lists its relays with live/relay and delivery-gap:

A publisher that runs its own nodes lists them under its own origin, which is then the operator’s. An origin SHOULD NOT give cache/serve or cache-transmission to a key it also gives delivery: such a key’s sending of its own groups is the publisher’s (bearer-receipts §4), and its cache-transmission claim over them is refused (cache_transmission_by_publisher, §5.3 step 2). Neither authority is pinned-only: nothing a sink presents or obeys depends on it.

4.4 Placing a server key

Inputs. A 32-byte Ed25519 key K; an instant at_ms, the time of the item the key is placed for; and the heads the relying party names, each a JSON text keyed by its origin (as deriving-edge §7.1 holds them). A JSON object cannot hold one origin twice (jwp-receipts §3.1 step 1), so there is one head per origin. No randomness and no clock.

Serving roles, in this order: cache/serve, live/relay, live/compositor, live/ingest (the last three the roles settlement §13 places).

Steps. Heads are read in increasing byte order of their origins (jwp-receipts §7.1); “least” below is first in that order. A retired entry’s until is read as seconds since 1970, and at_ms is later than it when at_ms > until × 1000, as jwp-receipts §7.4 step 5 compares times. The placement is the first of these that holds:

  1. refused key_revoked, with the least such origin and the entry’s compromised_since: a held head has an entry whose key is K and whose status is revoked, whatever its may_sign. A revocation attests that another party may hold the key (jwp-receipts §7.2), so no role outlives it.
  2. unconfirmed key_log_not_held, with the least such origin: a head is not held. It might revoke K, so nothing is confirmed while it cannot be read.
  3. confirmed, with the least such origin, the entry’s id, the first serving role in the order above that its may_sign holds and, for a retired entry, its until: a held head has an entry whose key is K, whose may_sign holds a serving role, and which is active, or retired with at_ms not later than its until.
  4. refused key_retired, with the least such origin and its until: a held head has an entry whose key is K and whose may_sign holds a serving role, and every such entry is retired with at_ms later than its until.
  5. refused authority_not_granted, with the least such origin: a held head lists K with no serving role.
  6. unconfirmed server_not_listed: no head lists K, including when no head is given.

A placement is written confirmed origin=… key_id=… role=…, followed by until=… for a retired entry; unconfirmed reason=server_not_listed; unconfirmed reason=key_log_not_held origin=…; refused reason=key_revoked origin=… compromised_since=…; refused reason=key_retired origin=… until=…; or refused reason=authority_not_granted origin=….

The levels are jwp-receipts §7’s, never reported as one another. A key that claims no origin contradicts nothing by being absent from a head, so step 6 is unconfirmed; a head that lists the key and withholds the role, or revokes or retires it, speaks against it, so steps 1, 4 and 5 are refused. A placement is not jwp-receipts §7.4’s confirmation: it uses the heads the relying party names, held under rules 1 to 3, with no anchor (jwp-receipts §7.3), as deriving-edge §8 checks edge/derive. A cache-transmission claim’s own confirmation of its signer_id (with cache-transmission) is reported beside it, as for any claim; neither changes the other.

Which instant. For a cache instance (§7.2 step 4), the latest instant any of its claims’ issued_at allows (§8.3). For a server in a tally (§8.4), the latest on-time evidence instant that credits it. For any other item, its own signed time.

A placement never changes a verdict (§7) or a hit (§8). It decides only how a server is reported, and which keys a payer may honour (settlement §13). A placement is never an error: no head makes a verdict or a tally fail.

4.5 The holdings key and the service key

Holdings §9 lets a node sign each record with a fresh key, for privacy; settlement §13 pays only keys it can place. A node whose service is to be placed signs its holdings records, its declarations and its claims with the key its operator lists. An asker names, as upstream, the key it found the object under (holdings §5.4), and a payer places that key. A node that signs with fresh keys has chosen not to be linked, and privacy wins where the holder chooses it: its askers still verify what it serves (§6), its service still counts as hits (§8), and it is reported unconfirmed server_not_listed, paid as no one’s.

5. The cache-transmission claim (class: "cache-transmission")

A node that sent, from what it held, objects of a group another key signed, over a multicast or unidirectional bearer instance of its own, MAY declare it in a cache-transmission claim, one per instance and group, after it has sent what it declares. Its subject_type is receipt and its subject the group receipt’s link hash (jwp-receipts §3 step 3). It is signed by the node’s key, never the group’s. signer_id is the node’s operator’s origin-bound did:web where its log lists the key, or its did:key otherwise; the second form is unconfirmed under jwp-receipts §7.4 step 1 and still placeable by §4.4, which matches the key’s bytes.

5.1 Body

membertypemeaning
bearerstringThe instance’s class, one of bearer-receipts §2’s; another string is field_type at jwp-receipts §3.1 step 2.
bearer_idabsolute URIThe node’s own instance. WAI reads nothing from it and compares it byte for byte.
leaf_countintegerThe group’s leaf count.
senthexA bitmap of ⌈leaf_count / 8⌉ bytes. The bit of object i is set exactly when the node sent object i over the instance, from what it held, as the bytes the group’s receipts commit to.
sent_root32 B hexjwp-receipts §2.2’s root over the leaves of the sent objects, in increasing position, each leaf in the form its object receipt takes (legacy or labelled). With every bit set it is the group’s root_hash.
energyobject or nullAs bearer-receipts §4.1 energy: what the instance spent sending these objects, every repetition included. null when not metered, never a figure of 0.
attestsstringMUST be "transmitted".

One meaning has one form: the bitmap sets at least one bit and none at or past leaf_count (§5.2 rule 3), hex is lowercase (jwp-receipts §2.4.3), and energy is null or an object, never absent.

{"body":{"attests":"transmitted","bearer":"multicast","bearer_id":"https://bearer.example/mesh-c1",
"energy":null,"leaf_count":4,"sent":"50","sent_root":"<32 B hex>"},"class":"cache-transmission",
"issued_at":"2026-11-03T11:00:05Z","kind":"claim","parent_receipt_hash":null,"seq":0,
"sig":"<64 B hex>","signer_id":"did:web:operator.example#c1","signer_pubkey":"<32 B hex>",
"subject":"<group link hash>","subject_type":"receipt"}

("50" holds objects 1 and 3 of four.)

5.2 Rules

At jwp-receipts §3.1 step 4, in order:

  1. attests is "transmitted": otherwise cache_transmission_not_transmitted. A declaration that says it attests more is refused, never read as a weaker one.
  2. bearer is not bidirectional: otherwise cache_transmission_on_bidirectional. Over a path back the receiver acknowledges what it received (settlement §3), and a second statement of the same service would count it twice.
  3. leaf_count is at least 1, sent holds exactly ⌈leaf_count / 8⌉ bytes, no bit at or past leaf_count is set, and at least one bit is set: otherwise cache_transmission_bitmap_malformed. A node that sent nothing has nothing to declare.
  4. Where energy is not null: bearer-receipts §4.2 rule 2 (energy_zero_figure, energy_unknown_acquisition, energy_legacy_acquisition, energy_acquisition_evidence).

5.3 Against the group

At jwp-receipts §3.1 step 6, against the group receipt the verifier holds, which passes jwp-receipts §3 steps 1 and 2 (context_invalid otherwise; a receipt of another kind is context_mismatch), and the object receipts it holds under that group, each of which passes jwp-receipts §3 step 5 (inclusion at least), in order:

  1. the group’s link hash is subject: otherwise cache_transmission_subject_mismatch;
  2. signer_pubkey is not the group’s: otherwise cache_transmission_by_publisher. A publisher’s own sending is a transmission (bearer-receipts §4);
  3. leaf_count is the group’s: otherwise cache_transmission_leaf_count_mismatch;
  4. with every bit set, sent_root is the group’s root_hash. Otherwise the verifier holds an object receipt at every set position (cache_transmission_objects_not_held, recoverable by obtaining them, never accepted silently), and sent_root is the root over their leaves (cache_transmission_root_mismatch). A root over a leaf that is not the group’s at its position is refused here: the digests served are checked against a group the node did not author, without the bytes.

A claim checked without its group stops at step 5 and is counted nowhere (§7).

5.4 What it attests

The node says it sent those objects, from what it held, over its instance. It does not attest that any receiver received them (a reconciliation’s, bearer-receipts §5), that it authored or changed them, or that it had any right of the publisher’s to send them. A transmission is not a delivery, on any bearer (bearer-receipts §2).

Each of a node’s statements binds to the group by hash and none re-signs or re-roots anything (jwp-receipts §4.3): a cache-transmission claim by subject and by sent_root under the group’s root; a holdings record by its entry’s group; a settlement record by its items’ content hashes. A node’s claims chain per signer through parent_receipt_hash and seq (jwp-receipts §2.4.3), across every group it declares, so a verifier is given its earlier claims or reports parent_not_held. There is no hop bound: a peer served by a peer is two services, each checked against the publisher’s receipts at its own door (jwp-receipts §4.1).

5.5 Authority

Confirmed under jwp-receipts §7, the claim needs cache-transmission, which is neither pinned-only nor delivery. Where energy is not null, its figure is a second item that needs cache-transmission and energy/<class>, as a transmission’s does (bearer-receipts §4.4). The claim’s signer is placed as a server by §4.4, reported beside.

5.6 A schedule of a cache instance

A node that sends over a cache instance to a plan MAY state the plan in a schedule claim (carousel §4), so that a receiver of its instance plans as a receiver of the publisher’s does and turns its radio off between the passes that add nothing (carousel §7). Its subject is the group receipt’s link hash and its bearer_id the instance’s, and it is signed by the node’s key, never the group’s. Its body, rules and blocks are carousel §4.1, §4.2 and §5’s; a later schedule extends it as carousel §4.5 says; and its availability and the statements held to it are carousel §6.3 and §6.4’s. It attests that the node scheduled the passes it names. It does not attest that they were sent, which is its cache-transmission claim’s, that any receiver heard them, or that the node had any right of the publisher’s to send them (§5.4).

Against the group. At jwp-receipts §3.1 step 6 in the verdict of §7, a schedule signed by the group’s key is the publisher’s and is checked by carousel §4.3. One signed by another key is a node’s and is checked by carousel §4.3 but for its step 2, raising that text’s codes at its other steps. Carousel’s verdict and timeliness’ plan read the publisher’s schedules alone.

Where it stands. At §7.2 step 4, in this order:

  1. every node’s schedule of an instance is set aside bearer_contradicted when an accepted transmission claim has that bearer_id, whether its declarations stand or were set aside, or when the instance is a contradicted cache instance: it is not the node’s to plan;
  2. every node’s schedule of an instance is set aside bearer_not_declared when no cache instance stands with that bearer_id;
  3. a schedule whose signer is not the instance’s server is set aside cache_schedule_signer_mismatch: a node schedules only the instance it declares, and another key’s schedule of it contradicts nothing;
  4. of the server’s schedules, in the order of its chain, when one does not extend the one before it (carousel §4.5) every one of them is set aside schedule_contradicted, and the instance itself stands. A node that withdraws, moves or changes a pass has stated neither plan.

Otherwise the last of them stands, and each before it with another body is extended.

A cache-transmission claim says what was sent and comes after it (§5), and a schedule says what will be sent and may come before, so either may come first in the node’s chain. A schedule may name objects the node’s claim does not. It credits nothing: a cache is credited only for what its claim says it sent (§7.2 step 6), and a schedule changes no count, no status and no placement.

Authority. Confirmed under jwp-receipts §7, the claim needs schedule (carousel §4.4), which the node’s operator gives beside cache-transmission (§4.3).

6. A peer-served object at the receiver

7. The verdict

7.1 Inputs

Bearer-receipts §6.1’s — the group receipt, the object receipts with envelopes where held, the claims in each signer’s chain order, optionally a sink’s own class and instance, a statement offered and count_only — with cache-transmission and schedule claims among the claims, the heads of §4.4, and optionally a statement of carousel §6.4 with its loss bound and overhead (§7.3).

A verifier that implements bearer-receipts and not this extension refuses a cache-transmission claim (unknown_class before this registration, context_mismatch at bearer-receipts §6.2 step 3 after it) and sets aside a reconciliation over a cache instance as bearer_not_declared: the unknown class is reported, as jwp-receipts §2.4.4 requires, never counted.

7.2 Steps

  1. The group and its objects: bearer-receipts §6.2 steps 1 and 2. A group that fails is refused with its reason, and nothing is derived from it.

  2. The claims, in order: jwp-receipts §3.1 steps 1 to 5, then step 6: a transmission claim by bearer-receipts §4.3, a reconciliation by bearer-receipts §5.3, a cache-transmission claim by §5.3 here, a schedule by carousel §4.3 or §5.6 here. A claim of any other class is context_mismatch. A refused claim takes no further part.

  3. The publisher’s declarations: bearer-receipts §6.2 step 4.

  4. The caches’ instances: the accepted cache-transmission claims, by bearer_id. Every claim of an instance is set aside bearer_contradicted when:

    • an accepted transmission claim has that bearer_id, whether its declarations stand or were set aside at step 3: the instance is the publisher’s, and a party that names it as its own contradicts the publisher, whose declarations keep what step 3 gave them; or
    • two of them differ in signer or in body: one instance is one party’s transmission, and a node that changes its account of it has stated neither. Such an instance is contradicted.

    Two with the same signer and body are one, whatever their issued_at and seq. Otherwise the instance stands; its server is the claims’ signer, placed by §4.4.

    Then the schedules: those signed by the group’s key by carousel §6.2 step 4, over step 3’s declarations, and a node’s by §5.6.

  5. The reconciliations, each accepted one in order, are counted as bearer-receipts §6.2 step 5 counts them, over the publisher’s declarations and the caches’ instances that stand. One is set aside, and counted nowhere, at the first of these that holds:

    • step 3 set aside the declarations of its bearer_id, or its bearer_id is a contradicted cache instance (bearer_contradicted);
    • neither a declaration nor a cache instance that stands has its bearer_id (bearer_not_declared);
    • that declaration or instance names another bearer (bearer_contradicted);
    • it is over a cache instance and signed by its server (self_acknowledged, settlement §3.6): a party’s statement that it received what it sent;
    • count_only is given and its signer is not among it (sink_not_confirmed).

    Otherwise it is counted for its instance. A second counted reconciliation of one key for one instance adds no sink (reconciliation_duplicate_sink); its bits are joined to the first’s.

  6. The counts:

    • bearer-receipts §6.2 step 6 over every counted reconciliation, of either kind of instance: sinks, whole and received_by, each key’s bits joined across all instances;
    • for each publisher’s declaration that stands, its sinks, as bearer-receipts gives them;
    • for each cache instance that stands, in increasing byte order of bearer_id: its bearer_id, bearer, server, placement and the objects it sent; its sinks, the distinct keys counted for it; and, for each object it sent, the distinct keys whose bits over this instance’s counted reconciliations alone hold it. A cache is never credited for an object it does not say it sent, nor for one a key received over another instance.
  7. Energy per receiver (§7.4).

A claim’s label is bearer-receipts §6.2’s (declared, counted, joined reason=reconciliation_duplicate_sink, set-aside reason=…, reject step=N reason=…), cache-declared for a cache-transmission claim whose instance stands, and stands or extended for a schedule.

7.3 Status, statements and a sink’s own instance

Never delivered on the publisher’s word (bearer-receipts §6.3) holds unchanged, and never delivered on a node’s.

7.4 Energy per receiver

Bearer-receipts §7 for each cache instance that stands whose energy is not null: ⌈joules_micro / max(1, n)⌉, n its counted keys. It is an upper bound, stated with the figure’s class, and never added to another instance’s or class’s. A null figure gives no bound, never 0.

8. Held by a deadline

8.1 The population

The relying party states a population: a region and the receiver keys it counts there. The keys are the bearer verdict’s count_only set (bearer-receipts §6.1): the tally runs the verdict with count_only the population’s keys, replacing any given.

The population is the relying party’s word. Nothing here places a key in a region: a receiver’s location is its own state, and “a sink can lie about its own state” (unidirectional-delivery §2). A key is not a receiver (bearer-receipts §7).

8.2 Inputs and checks

The verdict’s inputs (§7.1), and: the acknowledgements, each a WDA1 record’s bytes with the item list of each of its entries; the holdings records, each a WHD1 record’s bytes (holdings §4); the object’s position i; the deadline; the population; and miss_target_ppm.

The deadline is either deadline_ms, an instant the relying party states, or a timeliness claim (its text) whose entry for object i stands (timeliness §4, §6.2 steps 2 and 3, against the same group): deadline_ms is then that entry’s by_ms, and the tally reports the claim’s link hash beside it.

The tally is refused at the first of these that holds, and derives nothing:

  1. the population breaks §8.1: population_invalid;
  2. a stated deadline_ms is past the last instant, or miss_target_ppm is above 999,999: target_invalid;
  3. the group fails: its reason (§7.2 step 1); or its group_start is not an RFC 3339 date-time (jwp-receipts §2.4.3): context_invalid, as carousel §4.3 refuses a schedule’s group;
  4. i is at or past the group’s leaf count: object_out_of_range (holdings §7);
  5. the verifier does not hold object i delivered-verified (§7.2 step 1, with its envelope): object_not_verified. Object receipts carry no length (jwp-receipts §2.4.2), and without the envelope’s length ℓ a whole object cannot be told from part of one. The envelope gives ℓ and the content hash h;
  6. the deadline is a timeliness claim that is refused at jwp-receipts §3.1 steps 1 to 6 against this group, the object receipts the verifier holds under it and their envelopes where it holds them (timeliness §4.3, its steps 6 and 8 among them), with no claim of its signer held before it, or that has no entry for i: deadline_not_stated (timeliness §9). An object with no deadline is never on time.

A head that is not held refuses nothing: it leaves placements unconfirmed (§4.4 step 2).

8.3 Evidence

Each piece of evidence is a held-at statement of timeliness §2, whose instant is the latest the signed word allows, in milliseconds, rounded up where the word is finer. This text adds two kinds to the one timeliness derives from holdings records, and restates neither the form nor the rule:

Before the group. By timeliness §2’s rule, a statement whose whole seconds are below the seconds jwp-receipts §2.4.3 reads from the group’s group_start is before its group, and is set aside held_before_group: it gives no evidence. For an acknowledgement, that is an end at or below the group’s start in microseconds. A receiver whose clock was never set signs instants near 1970, and they are never on time.

Only a population key’s evidence is read. For each population key k:

k is a hit when some held-at statement of k for object i has an instant at or before deadline_ms, and a miss otherwise. For an acknowledgement, that is end − 1 ≤ deadline_ms × 1000, with no overflow in 64 bits. A line of §9 for object i and a hit read the same statements, so a key on_time in such a line by by_ms is a hit at that deadline in a tally of object i whose population holds it.

8.4 The count

8.5 Outcome

Met when miss_ppm ≤ miss_target_ppm; otherwise refused miss_target_exceeded. Reported either way: the region, the population digest, deadline_ms and a timeliness claim’s link hash, n, hits, misses, miss_ppm, missing, set_aside, the servers, unattributed, each acknowledgement’s label, each holdings record’s label, and each claim’s label under §7.2.

A met tally says that, of the stated keys, the share given held the object, by their own signed word, by the deadline. It does not say that they presented it, that the population is everyone in the region, that any key is one receiver, or that the population was chosen before the deadline (§13). It is not carousel §6.4’s “held by t”, which is the publisher’s plan for a receiver within a loss bound; a relying party may hold both. The asker’s plan of whom to fetch from stays holdings §5.4’s, and the operator’s plan of whom to repair is missing.

9. Composition

10. Mappings

standardbinding
MOQT, draft-ietf-moq-transport-23 §7.1 (Caching Relays: “Relays MAY cache Objects, but are not required to”), §7.9 (Relay Object Handling: a relay “MUST treat the object payload as opaque” and “MUST NOT combine, split, or otherwise modify object payloads”), §2.1 (“The Original Publisher is solely responsible for the content of the object payload”)A node with cache/serve serving over MoQ is a §7.1 caching relay held to §7.9 and to jwp-receipts §4.1 and §4.3.
HTTP Message Signatures, RFC 9421 §3.3.6 (ed25519), §2.3 (keyid, tag), §2.5, §4.3 (“Multiple distinct signatures MAY be included”), §7.2.8A node serving over HTTP MAY sign each response with alg="ed25519", keyid its key’s did:key (jwp-receipts §7.1) and tag="wai-cache", covering content-digest (RFC 9530 §2). A downstream that verifies signature and digest learns the key it names as upstream. An RFC 9421 signature base begins with " (§2.5), and every WAI signing input begins with its ASCII domain, so one key’s two kinds of signature never sign the same bytes.
Cache-Status, RFC 9211 §2, §2.1 (hit), §2.2 (fwd), §2.5 (stored)A member with hit is HTTP’s own unsigned “served from what it held” (settlement §9.1); fwd with stored is a fill. RFC 9211 defines no signature, so its identifier is not a key and places nothing.
CTA-5006 CMSD-Dynamic, as delivery-telemetry §6, its paragraph 6.3, maps itA node MAY write its did:key as its entry’s server string; a player that reads it learns a key it may name as upstream, unsigned, and SHOULD prefer an RFC 9421 signature where one is present.
PPSPP, RFC 7574 §3.2 (HAVE), §5, §9.2 (“reciprocity enforcement is the sole responsibility of the sending peer”), §11.2.4Informative: a holdings record is close to HAVE, and jwp-receipts §3 to PPSPP’s content integrity. PPSPP leaves reciprocity and accounting local; this extension gives their portable form.
DVB-NIP, ETSI TS 103 876 §6.2.2 and §6.5A gateway that stores broadcast assets and serves them to home clients is a node: its key holds cache/serve, its holdings record advertises, its clients acknowledge it.
CDNI footprints, RFC 8006 §4.3.8 and RFC 9388 §2.1.1.1Through rung-price §2, which binds them: a region is ISO’s capital form.

11. Reasons

The codes this extension adds, each with where it is raised:

reasonraised at
server_not_listed§4.4
cache_transmission_not_transmitted§5.2 rule 1
cache_transmission_on_bidirectional§5.2 rule 2
cache_transmission_bitmap_malformed§5.2 rule 3
cache_transmission_subject_mismatch§5.3 step 1
cache_transmission_by_publisher§5.3 step 2
cache_transmission_leaf_count_mismatch§5.3 step 3
cache_transmission_objects_not_held§5.3 step 4
cache_transmission_root_mismatch§5.3 step 4
cache_schedule_signer_mismatch§5.6
population_invalid§8.2
target_invalid§8.2
object_not_verified§8.2
miss_target_exceeded§8.5

The extension also raises key_revoked, key_retired and authority_not_granted (jwp-receipts §7.7), at the levels §4.4 gives them, and key_log_not_held (deriving-edge §9), at §4.4; bearer_contradicted, bearer_not_declared, sink_not_confirmed, reconciliation_duplicate_sink, delivery_not_reconciled and delivery_exceeds_reconciled (bearer-receipts §10) at §7.2 and §7.3; a schedule’s codes of carousel §4.2 and §4.3 at jwp-receipts §3.1 steps 4 and 6, schedule_contradicted and schedule_on_bidirectional (carousel §9) at §7.2 step 4, and carousel §9’s statement and bound codes at §7.3; self_acknowledged (settlement §11) at §7.2 step 5; object_out_of_range (holdings §7), context_invalid (jwp-receipts §3.1) and deadline_not_stated (timeliness §9) at §8.2; settlement §3.6’s codes and record_missing for an acknowledgement, holdings §7’s codes for a holdings record, and held_before_group (timeliness §9) for any held-at statement, at §8.3; for a group or object the codes of jwp-receipts §3.3; and for a claim every code of jwp-receipts §3.1 steps 1 to 5, bearer-receipts §4.2 rule 2’s energy codes, and those of step 6 named in §5.3.

12. Conformance

live-conformance/cache-authority/ holds the corpus, written from fixed seeds by wai_cache_authority_vectors gen as vectors.json. Every key comes from a published seed of one byte repeated 32 times (jwp-receipts §7.8), both key logs are test logs, and regions are ISO 3166-1’s user-assigned codes. It has:

The population bound of 220 keys is carried by no case; both implementations check it themselves.

A conforming verifier gives every case the outcome, the reason and everything else the corpus states. wai_cache_authority_vectors verify and the test tests/cache_authority.rs check that the file regenerates byte for byte, that wai-rs gives every case its outcome, that every reason of §11 appears, and that §11 lists exactly the reference’s codes. live-conformance/cache_authority_verify.py is the second implementation, written from this text: it shares no code with wai-rs; it verifies groups and objects with the JWP corpus’s second implementation (jwp-conformance/jwp_verify.py), claims through steps 1 to 5 with the claim corpus’s (claim-conformance/claim_verify.py), schedules against their group and their extensions and availability with the carousel corpus’s (live-conformance/carousel_verify.py), reconciliations with the bearer corpus’s (live-conformance/bearer_verify.py), acknowledgements with the settlement corpus’s (live-conformance/settlement_verify.py), key logs with the signer corpus’s (signer-conformance/signer_verify.py), held-at statements with the timeliness corpus’s (live-conformance/timeliness_verify.py) and regions with the rung price corpus’s (live-conformance/rung_price_verify.py); it writes §4.4, §5.3, §7 and §8 itself, reads §11 from this text, mutates copies of the corpus and requires every copy to fail, and drops each of its own checks in turn and requires the corpus to catch the weakened verifier.

13. Security and privacy considerations