# AI Codex — Principal Binding v1 (FROZEN)

> **Minimal** extension to the core (SPEC-identity-v0.1), sister of SPEC-succession-v1. Breaks nothing in place: new Verifiable Credential type + append-only endpoint. AI Codex **issues/serves/verifies, never executes**. Normative contract, non-modifiable in place: any change = `principal-binding-v2`.

## 1. Role & boundary (frozen)

- A **Principal Binding** is a VC **signed by an accountable principal** (human or company) declaring that an agent DID acts on behalf of that principal.
- This is AI Codex's **differentiator**: payment rails (x402, AP2, cards) say *how* an agent pays. No one says **WHO** is responsible behind the agent. The binding to the principal makes identity **accountable** and forms the **anti-Sybil** foundation (an accountable principal cannot duplicate itself for free).
- AI Codex **stores in append-only** fashion and **serves** the binding at a resolvable URL. It neither judges the legitimacy of the principal nor the off-platform relationship. It **verifies** only the principal's signature (cryptography), exactly the philosophy of "we issue, we do not settle".
- The **consumer** decides how much weight to give a verified binding (anti-Sybil, allowlist, KYA). AI Codex exposes the verifiable fact, not a decision.
- **No reputation transfer**, **no rail**, **no inverse dependency**: removing the binding invalidates neither the agent's identity nor its reputation.

## 2. The principal (frozen)

The **principal** is a DID resolvable outside the platform:

- **Company (strong case)**: `did:web:sa-societe.com`. The public key is served by the company itself at `https://sa-societe.com/.well-known/did.json` (W3C did:web). The company thereby **proves** it controls the agent, under a domain it owns.
- **Human / raw key**: `did:key:z6Mk…` Ed25519. Verifiable without any network call (key derived from the DID).

The principal **does not need to be registered** in the AI Codex registry (it is an external accountable entity). Only the **agent** (the subject) must be registered.

## 3. Principal Binding (frozen structure)

```json
{
  "@context": [
    "https://www.w3.org/ns/credentials/v2",
    "https://maxiaworld.app/contexts/aicodex-reputation-v1.json"
  ],
  "type": ["VerifiableCredential", "AICodexPrincipalBinding"],
  "issuer": "did:web:sa-societe.com",
  "validFrom": "2026-06-28T00:00:00Z",
  "credentialSubject": {
    "id": "did:key:z6Mk<agent>",
    "controlledBy": "did:web:sa-societe.com"
  },
  "proof": {
    "type": "DataIntegrityProof",
    "cryptosuite": "eddsa-jcs-2022",
    "verificationMethod": "did:web:sa-societe.com#key-1",
    "proofValue": "z..."
  }
}
```

- **Signed by the principal**: `issuer` == `credentialSubject.controlledBy` == principal. The `proof` is produced by the **principal's private key** (not the reputation issuer, not the agent). Verifiable outside the platform using only the principal's public key.
- `credentialSubject.id`: `did:key` Ed25519 DID of the **agent**, bound to the principal. **Distinct** from the principal (`id` != `controlledBy`): a self-binding carries no accountability.
- `verificationMethod`: must **reference the issuer** (`<issuer>#…`), otherwise the proof is not attributable to the principal.
- **No `validUntil`**: a control declaration does not expire on its own. **Revocable/replaceable** by a new signed binding (append-only, the most recent by `validFrom` governs).
- Bidirectional (read): the principal can publish the list of agents it controls (`GET /v1/principal/{agent}` on the agent side; the inverse on the principal side is derivable from the bindings registry).

## 4. Signature eddsa-jcs-2022 (reused, frozen)

Identical to SPEC-identity §3: `hashData = SHA256(JCS(proofConfig)) || SHA256(JCS(document_without_proof))`, Ed25519 with the **principal**'s key, `proofValue` multibase base58btc. No new cryptographic primitive.

## 5. Principal key resolution (frozen)

- `did:key:z6Mk…` → public key derived directly from the DID (zero network).
- `did:web:host[:path…]` → DID Document resolution:
  - `did:web:host` → `https://host/.well-known/did.json`
  - `did:web:host:a:b` → `https://host/a/b/did.json`
  - **HTTPS only**, bounded response (size ≤ 64 KiB, short timeout), `did.json.id` must == the DID. The key is the first valid Ed25519 `verificationMethod[].publicKeyMultibase`.
- Any other DID method → `E_PRINCIPAL_MALFORMED`. did:web resolution failure → `E_PRINCIPAL_UNRESOLVABLE`.

## 6. Submission (frozen)

Two projections of the same contract (same validations):
- MCP: `declare_principal` tool (adapter **mcp-v2**, does not alter frozen tools).
- REST: `POST /v1/principal`.

Input: the signed Principal Binding (§3). Server-side validation, **frozen order**:
1. `issuer` == `credentialSubject.controlledBy` (the principal declares itself), otherwise `E_PRINCIPAL_MALFORMED`.
2. `credentialSubject.id` (agent) is a conformant `did:key` Ed25519, otherwise `E_DID_MALFORMED`.
3. Agent resolvable in the registry, otherwise `E_DID_NOT_FOUND`.
4. Agent != principal, otherwise `E_PRINCIPAL_MALFORMED`.
5. Principal public key resolved (§5), otherwise `E_PRINCIPAL_MALFORMED` (method) / `E_PRINCIPAL_UNRESOLVABLE` (did:web unreachable).
6. `proof` valid for the §4 chain under the principal's key, and `verificationMethod` references the issuer, otherwise `E_BAD_SIGNATURE`.
7. **Append-only**: insertion of a new row. Never an UPDATE. Identical binding already present → idempotent return. The most recent by `validFrom` is the active one.

## 7. Resolution (public, frozen)

`GET /v1/principal/{did}` (where `{did}` = the agent) →
`{ "binding": <latest valid binding or null>, "principal": <principal DID or null>, "verified": <bool> }`,
or `404 E_DID_NOT_FOUND` if the agent is unknown, `E_DID_MALFORMED` if the DID is malformed.
`verified` is `true` if and only if a signed binding is stored (every stored binding was verified at declaration time). This is the anti-Sybil signal the consumer reads. Read-only, non-mutating. The DID Document and §2.2 metadata remain **W3C-pure and unchanged** (the binding lives alongside, never inside).

## 8. Error codes (frozen)

| Code | Meaning |
|---|---|
| `E_DID_MALFORMED` | agent (`subject.id`) not conformant `did:key` Ed25519 |
| `E_DID_NOT_FOUND` | agent unknown to the registry |
| `E_PRINCIPAL_MALFORMED` | principal not `did:key`/`did:web`, or `issuer` != `controlledBy`, or agent == principal |
| `E_PRINCIPAL_UNRESOLVABLE` | did:web DID Document unreachable / no Ed25519 key / non-HTTPS |
| `E_BAD_SIGNATURE` | proof not valid under the principal's key, or VM not referencing the issuer |
| `E_RATE_LIMITED` | quota / size exceeded |
| `E_INTERNAL` | server error, no detail disclosed |

No other code in v1. Generic messages (no state leak).

## 9. Quotas (frozen)

`declare_principal` / `POST /v1/principal`: 10 / min / IP, 100 / day / IP. Resolution: 120 / min / IP. Payload ≤ 8 KiB. Exceeded → `E_RATE_LIMITED`.

## 10. Conformance

A Principal Binding is conformant if and only if: (a) VC `AICodexPrincipalBinding` signed by the principal (`issuer` == `subject.controlledBy`, proof by its key, VM referencing the issuer), (b) `subject.id` (agent) is a DID **distinct** from the principal, (c) stored **append-only** (the most recent governs), (d) **no rail** referenced, (e) AI Codex performs **no transfer or automation**. All five are necessary and sufficient.

## 11. Storage

Dedicated table `principal_bindings` (agent, principal, valid_from, binding_json, created_at), **append-only**, distinct from `agents` and `successions`. The `agents` table (immutable metadata) is not touched.

## 12. Out of scope for v1 (locked)

- **KYC / eIDAS / legal identity verification of the principal**: external layer. AI Codex proves only **cryptographic control** of a DID, not the legal existence or honesty of the principal. Extension point: a consumer may overlay its own KYA on the resolved principal. Not built in v1.
- Automatic transfer, chained revocation to reputation, score weighting: **excluded** in v1 (the actual score = task A2; the binding exposes `verified`, the consumer weights). Any reintroduction = new versioned profile, never in place.
