Skip to content

Latest commit

 

History

142 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

                    ╭──────────────────────────────────────╮
                    │   ╦╦ ╦╔═╗╔╦╗╔═╗╔╗ ╦╔╦╗               │
                    │   ║║ ║╚═╗ ║ ╠═╣╠╩╗║ ║                │
                    │  ╚╝╚═╝╚═╝ ╩ ╩ ╩╚═╝╩ ╩                │
                    │                                      │
                    │   predicate + floor + nonce          │
                    │        ──→ one signed bit            │
                    ╰──╮───────────────────────────────────╯
                       ╰── network APIs that answer, not disclose

version (from release.json) status: filed / submitted, not adopted tracks: CAMARA + IETF license: Apache 2.0

"Just a bit. Never more, never less."

A standards effort to make telecom network APIs answer with exactly what the requester needs — a windowed, nonce-bound, expiring boolean — and nothing else, ever. Operators keep the revenue; aggregators stay blind carriage (designed and PoC-demonstrated; not yet in the filed CAMARA scope — see below); requesters get compliance-grade minimal answers; subscribers stop leaking.

CAMARA / GSMA Open Gateway network APIs answer useful questions (SIM swapped? number real? device roaming?) but the current lookup model ships identifiers on the wire, returns raw values (timestamps, countries, the phone number itself), lets the middle layer see everything, and leaves retainable data everywhere. Consent today is a string logged next to the query.

The fix is attested windowed disclosure: the requester states a predicate and a floor, supplies a nonce, and receives a signed boolean bound to that nonce, valid for the duration of the query — end-to-end encrypted past the aggregator, which fulfills and bills but cannot read. (That blind-hub encryption is designed and demonstrated in the PoC, but is held for a companion filing — the CAMARA enhancement as filed today does not yet cover it, so under the filed scope the aggregator can still read the identifier and the answer.)

Status: filed and submitted, not approved or adopted. CAMARA: APIBacklog issue #330 and PR #331 are filed and open, awaiting Working Group evaluation; the v2 rescope is filed as Commonalities issue #705, open and awaiting a maintainer label, discussed at the 2026-09-03 Technical Steering Committee. IETF: draft-hamr-oauth-agent-delegation-02 is submitted and live on the Datatracker as an individual draft — not a working-group document, not adopted. This repo is the staging ground for two tracks: CAMARA (operator/attestation side) and IETF (agent/delegation side).

Two modes

How much the response mode removes is the spine of the proposal, so it is the first thing an adopter chooses.

Mode A — attested query response. Today's rail unchanged: requester → aggregator → operator, same per-query billing and revenue share. Only the payload discipline changes. Removes over-disclosure, middle-layer visibility, and response retainability.

"Was this SIM swapped in the last 90 days?" → a signed true, nonce-bound, expiring.

Mode B — holder presentment. Attestations issued to the subscriber's device; the holder or agent presents proofs. Additionally removes the inbound identifier and the operator query log. Requires holder-side software.

"This device is in a licensed region" — proven without the operator being asked.

Claims discipline (inherited from zkagent: the name may be aspirational; the claims may not): Mode A is attested windowed disclosure — it must never be described as zero-knowledge. ZK language is reserved for Mode B. Mode A is the wedge; Mode B is the roadmap.

The profile

The primary deliverable is not a narrow new API but a horizontal profile — normative rules any API answering questions about a subscriber or device can adopt. An operation conforming to profile mode:

1. MUST return only the predicate result (boolean) or a declared band —
   never the underlying raw value (timestamp, country, number, address).
2. MUST echo the requester's nonce and the predicate being answered inside
   the signed response and MUST include an expiry; verifiers MUST reject
   wrong-predicate, replayed, or expired responses — and any payload with
   a duplicate claim key (one signed blob must never read true to one
   parser and false to another).
3. MUST sign with a key resolvable through the operator trust directory;
   verifiers MUST pin the expected operator key before verifying — an
   unsigned hint must never choose which key to trust.
4. MUST NOT carry a subscriber identifier derivable from the access token.
5. MUST treat floors as monotone — tightened downstream, never loosened.
6. MUST be end-to-end encrypted requester↔operator through an aggregator;
   the hub handles metering envelopes only and MUST NOT be able to read —
   envelopes MUST NOT expose payload size (fixed-length or padded).
7. SHOULD offer banded responses only as a transition from raw values.
8. Widening the window beyond one bit MUST be an explicit, distinct
   operation the consent flow can see — never a parameter default.

Full text with definitions, the per-API adoption checklist, and the residuals stated honestly: camara/v1/docs/camara-attested-windowed-disclosure.md §3 (v1, as filed).

Why a profile, not one more API

CAMARA's own catalog is already halfway here and stopped. /retrieve-age-band (unreleased, main only — not in any tagged SimSwap release) coarsens a response because raw timestamps over-disclose. GET /device-phone-number already takes no request body at all — it derives the line from the 3-legged access token instead of asking for an identifier. kyc-age-verification already ships as a boolean predicate API in the catalog. Every one of those is the working group's own precedent.

So the ask is not "approve my API" but "finish what you started, catalog-wide". One issuance rail plus pluggable predicates means every new status API inherits the mode for free — and the existing APIs become the profile's examples rather than its casualties.

The agent-grade floor

Agents are why this is urgent: MWC26 demonstrated agents autonomously invoking network APIs, which means the query log scales to machine speed. A SIM cannot be an agent's principal root — prepaid SIMs are farmable — but subscription-quality predicates are near-free for real subscribers and expensive at farm scale. The reference consumer-agent floor, tightenable only:

simType  = voice+data      # excludes data-only IoT/M2M SIMs
tenure   ≥ 2 years         # aged subscriptions resist mass production
swapAge  ≥ 90 days         # kills swap-and-reset
class    = postpaid        # optional tightening

Machine agents (fleets, vehicles — no human document exists) get a separate profile that deliberately embraces M2M SIMs. The two must not be conflated.

Honest limit: floors price identity resets — economic scarcity. They do not create uniqueness. "One accountable human" still requires a document-rooted principal layer above this profile.

Repo map

docs/product/       prd.md — the PRD that leads everything: requirements,
                    sequence, no-go list
                    camara-attested-windowed-disclosure.md — stub: file
                    moved 2026-08-31, kept so the filed APIBacklog links
                    keep resolving (GitHub has no redirects)
docs/logs/          findings.md — dated evidence + decision log
docs/archive/       aaif-agent-auth.md — superseded 2026-08-25, dated
                    record only (agent side now lives at
                    ietf/v1/docs/ietf-agent-delegation.md)
camara/v1/docs/     frozen record of what was actually filed 2026-08-28:
                    camara-attested-windowed-disclosure.md (the CAMARA
                    proposal), camara-filing-issue.md (step 1: the GitHub
                    issue body), camara-filing-template.md (step 2: the
                    filled API-proposal template), plus the 2026-08-31
                    reviewer feedback
camara/v1/poc/      Mode A demo: mock backend by default, Orange Network
                    APIs Playground as a swappable live backend
camara/v1/spec/     carrier-attestation.yaml — OpenAPI sketch (CAMARA-style)
camara/v2/docs/     working copy being reshaped per the 2026-08-31 feedback
                    — not filed
camara/v2/poc/      working copy of camara/v1/poc/, copied unchanged
camara/v2/spec/     working copy of camara/v1/spec/, copied unchanged
ietf/v1/docs/       frozen record of draft-hamr-oauth-agent-delegation-00
                    as posted 2026-08-31 (agent/delegation side, OAuth WG
                    target); ietf-agent-delegation.md is the companion
                    prose proposal
ietf/v1/poc/        the actionClass floor axis spike (M7) this -00 record
                    was validated against; copied unchanged into v2
ietf/v2/docs/       FROZEN record of -01, SUBMITTED and posted 2026-09-02,
                    expires 2027-03-06: all four items and Appendix A
                    direction 4 drafted; two review rounds run and their
                    findings fixed; the PoC catch-up done
ietf/v2/poc/        FROZEN -01 record: DIVERGED from the frozen v1 copy at
                    the time -01 was drafted (m7-actionclass.mjs and
                    m7-check.mjs carry the -01 text's rules — verifier-
                    derived chain identifier, path-template menu
                    matching, origin binding, the link-to-link omitted-axis
                    rule), 40 cases against v1's 24 — v1 stays frozen as
                    the -00 record; spike-a/ holds the catalogue-survey
                    dataset (specs/ omitted, reproducible from its SHA
                    column), moved in 2026-09-01; copied unchanged into v3
ietf/v3/docs/       FROZEN record of -02, SUBMITTED and posted
                    2026-09-20, expires 23 March 2027 (Datatracker:
                    2027-03-24): Verifier Placement rewrite (boundary as
                    a role, per effect-capable path, plus the
                    system-wide closure/anti-bypass invariant) done,
                    then reduced 2592 -> 1695 lines per
                    reduction-plan-02.md, all 28 plan rows closed
                    2026-09-18; byte-identical to the posted bytes
ietf/v3/poc/        DIVERGED from the frozen v2 copy on 2026-09-06: added
                    `m7-check.mjs` cases 41-43 for -02 Verifier Placement
                    (40 -> 43, all passing) and updated both README.md
                    files to document it; `m3-check.mjs` and spike-a/
                    stay unchanged

The two tracks

Each track cites the other as its counterpart; neither depends on the other's approval.

  • CAMARA — the operator/attestation side (v1, as filed; v2 rescoping working copy at camara/v2/docs/). What the operator attests and how it travels. Profile to Commonalities, consent hooks to ICM, adoption PRs to sim-swap and roaming-status, new-case proposal to APIBacklog (template pre-filled in §10).
  • IETF — the agent/delegation side (v1, as posted; v2 -01 SUBMITTED and posted 2026-09-02, expires 2027-03-06, at ietf/v2/docs/; v3 -02 SUBMITTED and posted 2026-09-20, expires 23 March 2027, at ietf/v3/docs/). What the agent carries and how permissions flow: floor-gated SIM attestation, scoped monotone delegations, presentment via RFC 9421. The OAuth Working Group (oauth@ietf.org) is the target.

They meet at the RFC 9421 header.

The PoC

A Mode A demo proving four assertions — each shown with its negative: windowing (never a raw value on the wire), nonce + validity (replay fails, responses expire), blind hub (the hub's own log shown on screen — metering records only, reads yield ciphertext), and monotone floor (looser queries rejected, never silently widened).

Status: all six modules M1–M6 are built and user-validated at their current counts. Run the demo with node camara/v1/poc/demo.mjs — zero credentials, zero network, against a built-in mock operator with scriptable backstories; --backend orange re-proves the same code path live on the Network APIs Playground with a free Orange developer account. Each module also has its own check, negatives first, exit code 0 only if every case holds: m1-check.mjs (20 cases), m2-check.mjs (10), m3-check.mjs (26), m4-check.mjs (40), m5-check.mjs (60, an offline replay of live-captured responses; m5-check-live.mjs re-proves 19 cases against the real Playground) and m6-check.mjs (46, offline in both backend modes). The user ran the full validation suite on their own machine at code commit 4446517 / docs commit c921508 (2026-08-18 08:16): every suite clean, zero FAIL, zero TypeError, zero Error: lines in the entire log — m1-check.mjs 20/20, m2-check.mjs 10/10, m3-check.mjs 26/26, m4-check.mjs 40/40, m5-check.mjs 60/60, m6-check.mjs 46/46, demo.mjs (mock) 33/33, demo.mjs --backend orange (live, real Orange Playground) 33/33, m5-check-live.mjs (live, real Orange Playground) 19/19. Both gates are MET at 4446517 — G1 (M1–M4 + M6 all user-validated) and G2 (M5 user-validated live) — the first time in this project both have been met at the same commit, on a tree that had already been through two /code-review rounds with every fix mutation-proven. This record covers 4446517/c921508 only, per this repo's standing rule that a user record does not transfer to a later change. See docs/logs/findings.md, 2026-08-18 (latest). Requirements live in the PRD §4; status, setup and caveats in camara/v1/poc/README.md.

Lineage

  • zkagent — the window vocabulary (disclosure width, narrow by default, monotone tightening) and the delegation model agents carry.
  • 8een — the one-bit verifier pattern, trust-anchor handling, and the evidence discipline (claims pinned to file/line/commit; retractions kept).
  • CAMARA's own specs — /retrieve-age-band (unreleased, main only), GET /device-phone-number's no-body shape, kyc-age-verification: the catalog is already halfway here. This profile finishes the trajectory, catalog-wide.

License

Apache License, Version 2.0 (CAMARA-compatible) — see LICENSE.

About

Attested windowed disclosure for telecom network APIs — requesters state a predicate, floor and nonce; operators answer with a signed, nonce-bound, expiring boolean, never a raw value. Aggregators meter but cannot read. Standards staging for the CAMARA and IETF tracks.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages