Security
What is secret, what is public, and how Yebo protects execution.
What You Need to Keep Secret
| Credential | Where it lives | What it does |
|------------|---------------|--------------|
| ent_... API key | Server only — never client-side | Routes requests to your enterprise policy backend |
| STRIPE_SECRET_KEY | Server only — environment variable | Real payment execution |
| YEBO_RP_ID / YEBO_RP_ORIGIN | Server config | WebAuthn relying party — must match your domain |
| Signing key private material | Managed by Yebo gateway — never exposed | Signs PAIs and CARs |
None of the cryptographic signing keys are accessible to your application code. The gateway manages all key material internally. You receive receipts and signatures — you never handle keys.
What Is Public and Safe to Share
| Item | Why it is safe |
|------|---------------|
| signer_public_key in receipts | Public key — needed for independent verification |
| GET /authorization-receipt/keys | Public key registry — intentionally public |
| mandate_id | A hash — reveals nothing about the action |
| receipt_id | A random UUID |
| CAR bundles | Designed for sharing with partners, auditors, regulators |
| pai_token | A signed proof — reveals no secrets, safe to log |
The Authorization Chain
Every executed action in Yebo carries a chain of five interlocking proofs. Removing or forging any one breaks the chain.
Passkey Session
→ AP2 Mandate (sealed, immutable)
→ Proof of Authorized Intent (PAI, ECDSA-signed)
→ Sentinel (12 invariant checks)
→ Enterprise Policy
→ Execution
→ CAR Receipt (ECDSA-signed)
No action can skip any step. Sentinel enforces this at the code level — it is not a policy, it is a cryptographic invariant enforcer.
AP2 Mandate
The mandate is the atomic authorization unit. It is:
- Sealed at creation with
Object.freeze()— no fields can be modified - Content-addressed —
mandate_idis a SHA-256 hash of its fields; tampering changes the ID - Time-limited — expires 5 minutes after issuance
- Nonce-protected — each mandate contains a 128-bit random nonce that prevents replay
mandate_hash = SHA-256(
mandate_id + subject_identity + capability + policy_hash +
amount + currency + nonce + issued_at + expires_at
)
This hash is embedded in the PAI and re-verified by Sentinel before every execution.
Proof of Authorized Intent (PAI)
The PAI is an ECDSA P-256 signed token that proves:
- A specific human authorized a specific action
- The mandate was not tampered with
- The authorization happened at a specific time
- The authorization has not been replayed
pai_payload = {
mandate_id, mandate_hash, identity_id,
policy_hash, nonce, issued_at, expires_at
}
pai_token = "PAI." + base64url(payload) + "." + base64url(ECDSA_sign(SHA256(payload)))
PAI tokens are safe to log, share with partners, and store alongside transaction records. The signature proves authenticity; there is no secret embedded in the token itself.
Sentinel — 12 Invariant Checks
Sentinel runs before every execution. All 12 must pass. If any fails, execution stops unconditionally.
| # | Invariant | What it checks |
|---|-----------|----------------|
| INV-01 | mandate_integrity | mandate_id matches the hash of mandate contents |
| INV-02 | mandate_not_expired | mandate expires_at has not passed |
| INV-03 | capability_authorized | capability matches the PAI's declared scope |
| INV-04 | policy_hash_consistent | policy_hash in mandate matches policy_hash in PAI |
| INV-05 | agent_cannot_self_authorize | agent DID ≠ authorizing identity DID |
| INV-06 | nonce_uniqueness | this nonce has never been used before (replay prevention) |
| INV-07 | pai_signature_valid | PAI ECDSA signature verifies against the orchestration key |
| INV-08 | mandate_hash_in_pai | mandate_hash embedded in PAI matches computed hash |
| INV-09 | subject_identity_consistent | identity_id in session matches identity_id in mandate |
| INV-10 | execution_requires_human | execution path was initiated from an authenticated session |
| INV-11 | pai_not_expired | PAI expires_at has not passed |
| INV-12 | integrity_threshold_met | identity integrity score meets minimum threshold for the capability |
Any SENTINEL_BLOCK response from the gateway means one of these invariants failed. Do not retry. Log the event and investigate.
Cryptographic Authorization Receipts (CAR)
Every completed action produces a CAR. It is:
- ECDSA P-256 signed using the gateway's persisted signing key
- Portable — contains the signing public key, so anyone can verify without contacting Yebo
- Tamper-evident — any field modification invalidates the signature
- Chain-linkable — can reference prior receipts, disputes, and settlements
Offline Verification
Anyone with the CAR can verify it using only standard cryptographic primitives:
# Using the Yebo CLI verifier
npx car-verify verify receipt.json
# Output:
# ✓ Structure valid
# ✓ Signature valid (ECDSA-P256-SHA256)
# ✓ Key ID: skey-abc123
# ✓ Authorized by: did:yebo:user-abc
# ✓ Capability: payment
# RESULT: VALID
Or verify a portable bundle:
npx car-verify verify-bundle bundle.json
Key Rotation
Signing keys are rotated periodically. When a key is rotated:
- The old key is kept in the registry indefinitely — old receipts remain verifiable
- New receipts are signed with the new key
- Rotated keys are still returned by
GET /authorization-receipt/keyswithstatus: "rotated"
Old receipts never become unverifiable due to key rotation.
Challenge & Continuation Tokens
When the capability kernel returns decision: "challenge", a continuation token is required to resume execution.
Continuation tokens:
- Are ECDSA P-256 signed using the same signing infrastructure as CARs
- Cover all action parameters —
amount,merchant,capability,policy_hash - Are tamper-evident — any field modification invalidates the signature
- Expire after 15 minutes
- Cannot be replayed — each token has a unique
token_id - Require a valid passkey session from the approving human
An attacker cannot inflate a $10 approved payment into a $10,000 execution — the amount is cryptographically bound in the token signature.
Integrity Score
Every identity has an integrity score (0–1000) that reflects their behavioral history:
| Tier | Score | What it enables | |------|-------|----------------| | Bronze | 0–399 | Basic actions, low amounts | | Silver | 400–649 | Standard commerce, moderate amounts | | Gold | 650–849 | High-value actions, enterprise workflows | | Platinum | 850–1000 | Unrestricted within policy |
The integrity score is calculated from the audit ledger — Sentinel violations, successful executions, session patterns. It is read-only — your application cannot set it; it is derived from behavior.
What Yebo Cannot Do
These guarantees are architectural, not just policy:
- Cannot execute without a human session — Sentinel INV-10 enforces this
- Cannot bypass Sentinel — invariants are checked in-process before any adapter call
- Cannot replay a mandate — nonce registry is append-only, INV-06
- Cannot tamper with a receipt after signing — ECDSA signature covers all fields
- Cannot recover a private key — key material is managed by the gateway process, never returned via API
Security Contact
For vulnerability reports or security questions: security@yebo.dev
We operate a responsible disclosure policy. Do not publish vulnerabilities publicly before notifying us.
Get Started
npx create-yebo # see Yebo's authorization control in action