Version: 0.1 Since: v0.11.3 Design Decision: DD-149
This guide describes three tiers of receipt isolation for multi-tenant PEAC deployments. Each tier trades simplicity for stronger isolation between tenants.
Multi-tenant platforms that issue PEAC receipts on behalf of multiple tenants need to decide how to isolate receipt signing keys and issuer identities. The choice affects:
- Key compromise blast radius: How many tenants are affected if a signing key is compromised
- Cross-tenant receipt visibility: Whether one tenant's receipts can be correlated with another's
- Operational complexity: Key management overhead per tier
- Verifier requirements: What verifiers need to discover and validate receipts
All tenants share a single JWKS, a single signing key, and a single iss origin.
Issuer: https://platform.example
JWKS: https://platform.example/.well-known/jwks.json
Keys: 1 active key (kid: "prod-2026-03")
All tenant receipts are signed with the same key and carry the same iss:
{
"iss": "https://platform.example",
"sub": "agent:tenant-abc/service-v2",
"iat": 1709000000,
"jti": "rcpt_01HQXYZ123456789"
}Tenant isolation relies on the sub claim or an extension:
{
"ext": [
{
"key": "org.peacprotocol/tenant_ref",
"value": { "tenant_id": "tenant-abc" }
}
]
}| Property | Value |
|---|---|
| Key management | Single key to rotate |
| Blast radius | All tenants affected by key compromise |
| Cross-tenant correlation | Trivial (same iss and kid) |
| Verifier setup | Single issuer config to discover |
| Operational cost | Minimal |
- Internal multi-tenant services where tenants trust the platform
- Development and staging environments
- Low-sensitivity receipt types (non-financial, non-identity)
- A compromised key affects all tenants; emergency revocation requires rotating the shared key
- Tenants can observe each other's receipt volume and timing patterns via the shared
iss - No cryptographic boundary between tenants; isolation is purely logical
All tenants share a single JWKS and a single iss origin, but each tenant gets a dedicated signing key with a tenant-prefixed kid.
Issuer: https://platform.example
JWKS: https://platform.example/.well-known/jwks.json
Keys:
- kid: "tenant-abc/prod-2026-03" (active, for tenant-abc)
- kid: "tenant-def/prod-2026-03" (active, for tenant-def)
- kid: "tenant-abc/prod-2026-02" (deprecated, grace period)
Receipts carry the tenant-scoped kid in the JWS header:
{
"header": {
"alg": "EdDSA",
"kid": "tenant-abc/prod-2026-03"
},
"payload": {
"iss": "https://platform.example",
"sub": "agent:service-v2",
"iat": 1709000000,
"jti": "rcpt_01HQXYZ123456789"
}
}Tenant-prefixed kid values use the format:
{tenant_id}/{environment}-{date}
Examples:
tenant-abc/prod-2026-03acme-corp/staging-2026-03org-42/prod-2026-02(deprecated key in grace period)
| Property | Value |
|---|---|
| Key management | One key per tenant (more keys, single JWKS) |
| Blast radius | Single tenant affected by key compromise |
| Cross-tenant correlation | Moderate (same iss, different kid) |
| Verifier setup | Single issuer config; verifiers select key by kid |
| Operational cost | Moderate (key rotation per tenant) |
- SaaS platforms with moderate isolation requirements
- Multi-tenant APIs where each tenant needs independent key rotation
- Environments where a single
isssimplifies verifier configuration
- Key compromise affects only one tenant; revoke the tenant-specific key without affecting others
- Tenants share the same
iss; verifiers cannot distinguish tenants by issuer alone (must inspectkid) kidcollision risk: ensure tenant IDs are unique and stable; platforms MUST NOT reuse tenant IDs after deletion- JWKS document grows linearly with tenant count; enforce
maxJwksKeyslimits (default: 20 per VERIFIER-SECURITY-MODEL.md). Platforms with more than 20 active tenants SHOULD use Tier 3
Each tenant key rotates independently per KEY-ROTATION.md:
- Add new key:
kid: "tenant-abc/prod-2026-04"(PENDING) - Activate new key; deprecate old:
kid: "tenant-abc/prod-2026-03"(DEPRECATED) - After 30-day overlap: retire old key
The platform MUST coordinate Cache-Control max-age on the shared JWKS with the shortest tenant overlap period.
Each tenant gets a dedicated JWKS, a dedicated iss origin, and a dedicated peac-issuer.json configuration.
Tenant ABC:
Issuer: https://tenant-abc.platform.example
Config: https://tenant-abc.platform.example/.well-known/peac-issuer.json
JWKS: https://tenant-abc.platform.example/.well-known/jwks.json
Keys: kid: "prod-2026-03"
Tenant DEF:
Issuer: https://tenant-def.platform.example
Config: https://tenant-def.platform.example/.well-known/peac-issuer.json
JWKS: https://tenant-def.platform.example/.well-known/jwks.json
Keys: kid: "prod-2026-03"
Receipts carry the tenant-specific iss:
{
"iss": "https://tenant-abc.platform.example",
"sub": "agent:service-v2",
"iat": 1709000000,
"jti": "rcpt_01HQXYZ123456789"
}| Property | Value |
|---|---|
| Key management | Fully independent per tenant |
| Blast radius | Single tenant only |
| Cross-tenant correlation | Difficult (different iss origins) |
| Verifier setup | Separate discovery per tenant |
| Operational cost | High (per-tenant DNS, TLS certificates, JWKS hosting) |
- Enterprise deployments with strict isolation requirements
- Regulated environments (financial services, healthcare)
- Platforms where tenants need fully independent verifier discovery
- Compliance scenarios requiring per-tenant audit boundaries
Subdomain model (recommended):
https://{tenant}.platform.example
- Wildcard TLS certificate simplifies provisioning
- DNS-level isolation
- Each subdomain hosts its own
/.well-known/peac-issuer.json
Path-based model (NOT recommended):
https://platform.example/tenants/{tenant}
- Violates origin-only semantics (issuer
issshould be an origin, not a path) - Breaks
peac-issuer.jsondiscovery (which derives from origin only) - Creates ambiguity in issuer matching
- Strongest isolation: no shared keys, no shared issuer identity
- Key compromise is fully contained to the affected tenant
- Verifiers discover keys independently per tenant; no cross-tenant JWKS leakage
- Higher operational cost: TLS cert management, DNS provisioning, per-tenant monitoring
- Generate per-tenant keys with tenant-prefixed
kidvalues - Add new keys to the shared JWKS
- Update receipt signing to use the tenant-specific key
- After overlap period, remove the shared key
- No change to
issorpeac-issuer.json
- Provision per-tenant subdomains and TLS certificates
- Create per-tenant
peac-issuer.jsonat each subdomain - Create per-tenant JWKS at each subdomain
- Update receipt signing: change
issto tenant-specific origin - During migration: maintain old
issreceipts in the shared JWKS for the overlap period - After overlap: remove tenant keys from the shared JWKS
Breaking change warning: Changing iss invalidates all in-flight receipts. Verifiers that cached the old issuer will fail verification until they discover the new issuer. Plan a migration window and communicate with verifiers.
Not recommended. Merging isolated issuers into a shared issuer loses isolation guarantees and may confuse verifiers that cached the per-tenant configuration.
Receipts MAY include the org.peacprotocol/tenant_ref extension to carry explicit tenant metadata:
{
"ext": [
{
"key": "org.peacprotocol/tenant_ref",
"value": {
"tenant_id": "tenant-abc",
"environment": "production"
}
}
]
}This extension is informational: it helps downstream systems route and filter receipts by tenant. It does NOT replace cryptographic isolation (Tier 2/3 key separation provides the actual isolation boundary).
| Factor | Tier 1 (Shared) | Tier 2 (Scoped) | Tier 3 (Isolated) |
|---|---|---|---|
| Setup complexity | Low | Medium | High |
| Key compromise blast radius | All tenants | One tenant | One tenant |
| Cross-tenant correlation risk | High | Medium | Low |
| JWKS document size | Small (1 key) | Grows with tenants | Small (1 key each) |
| Verifier configuration | One issuer | One issuer, many kids | Many issuers |
| Key rotation independence | None | Per-tenant | Per-tenant |
| Regulatory suitability | Low | Medium | High |
| Max recommended tenants | Unlimited | ~20 (JWKS key limit) | Unlimited |
- KEY-ROTATION.md: Key Rotation Lifecycle Specification
- PEAC-ISSUER.md: Issuer Configuration Specification
- VERIFIER-SECURITY-MODEL.md: Verifier Security Model
- EVIDENCE-CARRIER-CONTRACT.md: Evidence Carrier Contract