# H33-CANONICAL-AUTH-v1

**Conceptual status:** Locked. Ratified 2026-06-01.
**Operational status:** NOT READY. See "Readiness criteria" section. Until the enforcement chain is implemented and tested end-to-end (Bearer JWT → princ_* → replay_until(now) → pctl_* → receipt), this standard is a design, not a deployment.
**Scope:** Every service-to-service call inside H33 and every adjacent integration (V101, Agent Zero, Q-Sign, HATS, future products).
**One-line summary:** Bearer token with JWT-encoded claims. The JWT identifies the actor; replay determines authority.

---

## The core principle (load-bearing — quote-worthy)

> **Identity is not authority.**
> **Auth1 identifies who is calling. Authority Infrastructure determines what they are allowed to do.**

This is the single sentence that protects the platform from drift. Six months from now someone will be tempted to put permissions, roles, scopes, or entitlements into JWTs. The moment that happens, Auth1 starts answering authority questions and replay's answer competes with it. **That is exactly the parallel-authority drift this standard exists to prevent.** The principle above is the test every change to the auth layer must clear.

## The six locks (Eric, 2026-06-01)

These are the rules that must hold for as long as this version of the standard is in force. Numbered for explicit reference in code review, design docs, and future re-litigation attempts.

1. **Bearer is canonical network auth.** Every service-to-service call inside H33 carries an Auth1-issued Bearer JWT.
2. **API keys become bootstrap credentials, not authority credentials.** API keys are exchanged at Auth1 for short-lived Bearer JWTs; they never reach receipt-issuing services.
3. **JWT identifies actors; replay determines authority.** The `sub` claim names the calling principal; `replay_until(now)` decides what they can do.
4. **JWT scopes are optimization hints only.** Routing and prefiltering are allowed; granting capability is forbidden.
5. **No service may authorize based solely on JWT claims.** Every receipt-issuing service runs the six-step discipline rule below.
6. **Every receipt-producing service must perform replay + pctl_* evaluation before issuance.** No shortcuts. No caching that bypasses canonical event log. No "the token is fresh" excuses.

If any of the six are violated in code review, the change blocks until corrected.

## The decision

**Bearer token with JWT-encoded claims is the canonical service-to-service authentication mechanism across H33.**

Every product authenticates the same way. Every receipt-issuing service validates Bearer tokens the same way. No per-product re-litigation.

## Two decisions, not one

The original writeup of this standard conflated two distinct decisions. The correction:

| Decision | Mechanism |
|---|---|
| **Canonical network auth** (everything inside H33) | Bearer token from Auth1 |
| **Customer programmatic auth** (SDK / API entry point) | Customer API key → exchanged for Auth1 Bearer → H33 services |

**Everything inside H33 sees only Bearer tokens.** The API key is an issuance/bootstrap mechanism, not an authorization mechanism. This is the same distinction the rest of the platform makes: identity at the edge, authority in the engine.

## The three caller archetypes

Every caller H33 ever sees fits into one of three patterns. All three converge on the same thing once they cross into the H33 network: a Bearer JWT carrying `sub = princ_*`.

### Archetype A — Humans

```
Human signs into Auth1 (web, native, MFA-step-up)
       ↓
Auth1 issues a session
       ↓
Session exchanges for an Auth1 Bearer JWT (per-request or short-lived)
       ↓
Bearer JWT → H33 services
```

### Archetype B — Services (internal + external service principals)

```
Service principal authenticates to Auth1 (machine credentials, mTLS to Auth1, HSM-backed key, etc.)
       ↓
Auth1 issues a Bearer JWT for the service principal
       ↓
Bearer JWT → H33 services
```

### Archetype C — Customers (SDK / programmatic)

```
Customer API key (long-lived, bootstrap credential)
       ↓
Exchange call to Auth1 (API key in → short-lived Bearer JWT out)
       ↓
Bearer JWT → H33 services
```

**The API key does not cross into H33 services.** It only ever reaches Auth1's token exchange endpoint. Every other surface inside H33 sees Bearer tokens and only Bearer tokens.

This is the architectural symmetry: same `princ_*` model, same Bearer transport, same six-step discipline rule for every receipt-issuing service.

## Why bearer

H33 is a network, not a collection of point integrations.

| Option | Network-shaped? | Carries identity claims? | Cross-org? | Ops burden | Maps to principal model? |
|---|---|---|---|---|---|
| **Bearer (JWT)** | ✓ | ✓ via claims | ✓ | low | ✓ — `sub` = `princ_*` |
| X-API-Key | partial | no — identifies, doesn't claim | partial | low | no — opaque, no scope |
| mTLS | weak across orgs | identity at network layer | hard — cert exchange friction | high — cert lifecycle | indirect |
| Internal trusted network | ✗ | ✗ | ✗ | n/a | no |

Three of the four alternatives assume a topology that breaks the moment a regulator's verifier, a third-party processor, or an adversarial implementation enters the picture. Bearer + JWT works identically across internal, partner, and third-party callers.

## The wire shape

```
Authorization: Bearer <jwt>

JWT claims:
  sub   = princ_*               ← calling principal (event-log ID)
  iss   = auth1                 ← issuer, public-key-rotatable
  aud   = substrate-receipts    ← per-issuer audience (or attestations / anchors / etc.)
  exp   = <unix ts>             ← short-lived (5–15 min recommended)
  scope = [...]                 ← OPTIMIZATION HINTS ONLY (see HC-1; never authoritative)
  jti   = <uuid>                ← replay protection
```

## The discipline rule

Every receipt-issuing service MUST:

1. Verify the JWT signature against Auth1's current public key
2. Extract `sub` as the `princ_*`
3. Run `replay_until(now)` against the canonical event log
4. Confirm the principal's active grants cover the requested operation via standard pctl_* lookup
5. Emit the receipt with the principal recorded as the actor
6. Anchor via H33-74

**No service shortcuts the replay step.** The JWT identifies the actor; the engine decides.

## Two hard constraints

### HC-1 — JWT scopes are optimization hints, never authoritative

The strongest possible statement of this rule:

> **JWT scopes are optimization hints.**
> **JWT scopes are never authoritative.**
> **If replay and pctl_* disagree with JWT scope: replay wins. Every time.**

Concretely:

- `scope` MAY be used to route a request to the correct receipt-issuing service before any expensive work happens
- `scope` MAY be used to prefilter handlers / reject obvious nonsense at the edge before invoking replay
- `scope` MAY be cached at the edge for routing decisions only
- `scope` MUST NOT grant any capability
- `scope` MUST NOT short-circuit `replay_until()`
- `scope` MUST NOT be relied on as authorization in any code path

If a request's JWT claims scope `approve_treasury_transfer` and the principal's active grants from replay do not cover `approve_treasury_transfer` at the request timestamp, the request is **denied**. Always. The denial reason is the replay verdict (`capability_missing` or `AUTHORITY_CHAIN_BROKEN`), never "scope ok" — because scope is not what's being checked.

This is the failure mode that produces a JWT-based parallel authority surface — exactly the drift this standard exists to prevent.

### HC-2 — API keys exist only as bootstrap credentials

An API key may mint or request a short-lived Bearer JWT, but it cannot itself be presented as authority to a receipt-issuing service. API keys are out-of-band material for obtaining tokens; they are never the thing exercising authority directly. This keeps the authority chain intact for every actual operation.

## The final policy chain (canonical, network-wide)

```
Auth1 issues identity
     ↓
Bearer JWT carries sub = princ_*
     ↓
H33 replay determines authority
     ↓
pctl_* determines whether the operation is allowed
     ↓
H33-74 anchors the receipt
```

Every product (V101, Agent Zero, Q-Sign, HATS, future) follows this chain unchanged. Any product that needs to deviate must clear the same five-questions discipline that classified Privacy as drift, not architecture.

## SDK shape — five lines, everywhere

Pseudocode (real implementation is Rust per platform-wide default):

```rust
let principal = h33_auth::verify_bearer(req.headers())?;
let result    = astate_replay::replay_until(events, now, tenant, root);
require_capability(&result, principal, requested_capability)?;
let receipt   = build_receipt(principal, ...);
anchor::submit(receipt);
```

V101, Agent Zero, Q-Sign, HATS, and every future product write the same five lines.

## What is permitted (defense in depth)

The Bearer-token-on-HTTP layer is the canonical identity-claim mechanism. The following layers MAY exist beneath it, and are encouraged as defense in depth:

- **mTLS at the TLS layer** — provides network-layer mutual auth before the Bearer token is even seen
- **IP allowlists** — for service-to-service within tightly-controlled VPC boundaries
- **Network policies / mesh authentication** — for east-west traffic inside a cluster
- **HSM-backed signing for the JWT issuer (Auth1)** — protects the private key behind hardware

None of these replace Bearer + JWT as the canonical identity-claim. They harden the surface beneath it.

## What is forbidden

- Treating JWT `scope` as authoritative
- Presenting an API key directly to a receipt-issuing service
- Skipping `replay_until()` because "the JWT looks fine"
- Trusting an unsigned JWT for any reason
- Long-lived Bearer tokens (> 1 hour)
- Custom auth schemes that compete with this one

If any of these appear in code review, they block until removed.

## Readiness criteria

The standard is conceptually correct. It is NOT operationally ready until every piece below exists, ships, and passes the test path. "Ready" means the full enforcement chain works end-to-end: **Bearer JWT → princ_* → replay_until(now) → pctl_* → receipt.**

### Missing pieces — must exist before any product calls this standard "deployed"

#### 1. Auth1 JWT validation middleware

A canonical Rust module that every receipt-issuing service imports. Validates the incoming Bearer token:

- [ ] Verify the JWT signature against Auth1's current public key
- [ ] Enforce `iss = auth1`
- [ ] Enforce `aud` matches this service's audience
- [ ] Enforce `exp > now` with no clock skew permitted past a small bound
- [ ] Enforce the signing algorithm is on the allowlist (no `alg=none`, no algorithm substitution)
- [ ] Extract `sub` and surface it as the `princ_*` to downstream code
- [ ] Return a clear typed error for each failure mode so callers can map to verdict classes

#### 2. Principal mapping

The `sub` extracted from the JWT must map cleanly to a `princ_*` in the canonical event log.

- [ ] No email-only identity (email is not a stable principal ID; it changes, gets transferred, gets typo'd)
- [ ] No tenant-name leakage (the principal ID is internal; customer-facing surfaces never expose it)
- [ ] One-to-one mapping between Auth1 subject and `princ_*`, documented and enforceable
- [ ] Mapping is replayable: if a principal is renamed in Auth1, the change shows up as an event in the canonical log

#### 3. Replay enforcement at the service surface

Every receipt-issuing service must call `replay_until(now)` before accepting any operation.

- [ ] No endpoint relies on JWT `scope` as authority
- [ ] No endpoint short-circuits replay because "the token is fresh"
- [ ] No endpoint caches a stale snapshot in a way that bypasses the canonical event log
- [ ] Every denial caused by replay carries a clear reason (verdict class + explanation) so the customer can act on it

#### 4. pctl_* capability lookup

The requested operation maps to the four axes (WHO / WHAT / LIMITS / ESCALATION) of the active pctl_* policy.

- [ ] WHO check: the `princ_*` matches the policy's allowed_actor_kinds
- [ ] WHAT check: the requested operation is in `allowed_operations`
- [ ] LIMITS check: amounts / windows / jurisdictions / data categories all satisfied
- [ ] ESCALATION check: kind=never → allowed; threshold → check amount; always → conditional; exception_only → check whether limits would be exceeded
- [ ] Response can explain YES / NO / CONDITIONAL with the axis that fired

#### 5. End-to-end integration tests

The whole chain wired together, exercised against every meaningful failure mode.

### Test path — six cases that must pass before "ready"

| # | Scenario | Expected outcome |
|---|---|---|
| 1 | Valid token + valid authority | Allowed (YES) — receipt issued |
| 2 | Valid token + missing authority (capability not in any active grant) | Denied (NO — capability_missing) |
| 3 | Expired token (`exp < now`) | Denied (auth failure — not even reach replay) |
| 4 | Wrong audience (`aud` mismatch) | Denied (auth failure — not even reach replay) |
| 5 | Forged token (signature invalid against Auth1 public key) | Denied (auth failure — not even reach replay) |
| 6 | JWT `scope` claim says yes but replay says no | **Denied** (replay wins; scope is advisory only) |

Case 6 is the most important. It is the test that proves HC-1 ("scope is never authoritative") is actually enforced.

### What "ready" looks like

When all five missing pieces ship and all six test cases pass, this standard's operational status flips from `NOT READY` to `READY`. At that moment — and not before — products may declare themselves compliant with the standard.

Until then, the standard is a design document. Useful for alignment. Not useful as a deployment claim.

## Cross-links

- `/agent-zero/replay-engine/` — the replay engine that determines authority
- `/agent-zero/pctl/v1/schema.json` — the policy schema that determines allowed operations
- `/agent-zero/authority-state/v1/schema.json` — the snapshot shape replay produces
- Auth1 documentation (TBD — link from this page when published)
- H33-74 anchor documentation (TBD)

## Origin

- 2026-06-01: Eric question — "What is the canonical service-to-service authentication mechanism for substrate receipt issuance?"
- 2026-06-01: Recommendation accepted (Bearer + JWT) for the network-shaped reasoning
- 2026-06-01: Two hard constraints added — `scope` never authoritative; API keys bootstrap only
- 2026-06-01: Final policy chain locked. This document published.
- 2026-06-01: Eric distinguishes "conceptually ready" (yes) from "operationally ready" (no, not yet). Five missing pieces + six test cases added as Readiness criteria. Standard's operational status remains `NOT READY` until the enforcement chain is implemented and the test path passes end-to-end.
- 2026-06-01: Eric corrects the writeup — Canonical Network Auth (Bearer from Auth1) and Customer Programmatic Auth (API key → exchanged for Auth1 Bearer) are two separate decisions, not one. Three caller archetypes documented (humans / services / customers). API key never crosses into H33 services; it only reaches Auth1's exchange endpoint. The core principle locked: **"Identity is not authority. Auth1 identifies who is calling. Authority Infrastructure determines what they are allowed to do."** Six explicit locks numbered for future-proof reference. Document renamed to canonical filename `H33-CANONICAL-AUTH-v1.md`.

## Sign-off

This standard is locked. Re-litigation requires the same five-questions discipline applied to Privacy:

1. Does the new mechanism answer one phase of the Decision Lifecycle?
2. Does it consume pctl_*?
3. Does it emit standard verdict classes?
4. Does it surface Decision / Authority / Evidence / Verification?
5. Does it make the platform feel more like one machine?

If any answer is "no," the proposal does not advance.
