Provisioning Lifecycle Profile
Portable signed records for agent provisioning events. PEAC records what your system reported happened during credential issuance, secret storage, access grants, and certificate provisioning — observable evidence, not authorization.
Extension namespace: org.peacprotocol/provisioning-lifecycle (16th extension group). Profile 0.1. New in v0.14.2.
Observer scope
PEAC records what the caller system reports happened. Upstream authorization, validation, settlement, vault management, and lifecycle enforcement belong to the upstream system. A provisioning record proves what your code reported observing — not that the underlying provisioning system authorized or completed it.
Install
pnpm add @peac/schema @peac/protocol
Event Types
Ten registered type URIs cover the provisioning event surface. All use the *-observed suffix to make the observer-scope semantics explicit.
| Type URI suffix | What it records |
|---|---|
api_key_provisioning_observed | API key or token issued to an agent or service account |
oauth_client_provisioning_observed | OAuth 2.x client registration or credential grant observed |
certificate_provisioning_observed | TLS/mTLS certificate issuance or rotation observed |
service_account_provisioning_observed | Service account or workload identity created or modified |
secret_storage_observed | Secret or credential material stored in a vault or secret store |
access_grant_observed | Access grant, permission assignment, or policy binding observed |
access_revocation_observed | Access revocation or permission removal observed |
payment_authorization_observation | Payment authorization scheme credential provisioned or rotated |
credential_rotation_observed | Credential rotation or key rollover cycle observed |
resource_quota_observed | Resource quota allocation or limit adjustment observed |
Sub-states (requested, provisioned, granted, revoked, cancelled) go in the sub_event field inside the extension object, not as separate type URIs.
Basic Usage
import { issue } from '@peac/protocol';
import { validateProvisioningLifecycle } from '@peac/schema';
// Build the provisioning lifecycle extension object
const provisioningExtension = {
event_kind: 'api_key_provisioning_observed',
sub_event: 'provisioned',
provider_ref: 'urn:provider:acme-vault:v1', // opaque ref — no raw IDs
storage_surface: {
kind: 'external_secret_store',
provider_ref: 'urn:vault:acme:prod',
surface_ref: 'urn:vault:acme:prod:slot:api-key-42',
material_redaction: 'full',
},
observed_at: new Date().toISOString(),
};
// Validate before issuing — fails closed on credential material
const validation = validateProvisioningLifecycle(provisioningExtension);
if (!validation.success) {
throw new Error(validation.error.issues[0].message);
}
// Issue the signed record
const result = await issue({
sub: 'agent:ci-runner:prod',
iss: 'https://platform.example.com',
type: 'org.peacprotocol/provisioning-lifecycle/api_key_provisioning_observed',
pillars: ['provenance', 'compliance'],
extensions: {
'org.peacprotocol/provisioning-lifecycle': provisioningExtension,
},
signingKey: myKey,
});
// result.jws is a portable signed Wire 0.2 recordCredential Material Safety
The provisioning lifecycle validator includes a recursive credential-material scanner. It inspects every string field for patterns that suggest live credential material and rejects them with structured error codes.
provisioning.token_material_blockedBearer token / JWT compact pattern
provisioning.inline_credential_blockedInline credential in value field
provisioning.forbidden_key_nameForbidden top-level key (e.g. raw_key, secret_value)
provisioning.field_too_largeField exceeds byte limit (64 KB)
provisioning.opaque_ref_grammar_violationReference does not match opaque ref grammar
provisioning.invalid_storage_surfacestorage_surface.kind not in allowed enum
All sensitive references use the opaque reference grammar: urn:, ref:, did:, sha256:, peac:, or https:. Raw identifiers, inline secrets, and bearer tokens are always rejected.
Error Codes
21 stable error codes under the provisioning.* namespace. All are stable across patch versions.
inline_credential_blocked token_material_blocked forbidden_key_name field_too_large replacement_character_in_string structure_too_deep structure_too_large opaque_ref_grammar_violation invalid_storage_surface invalid_material_redaction invalid_event_kind invalid_sub_event invalid_scheme_id invalid_amount_minor invalid_observed_at invalid_retrieved_at invalid_expires_at invalid_currency unrecognized_field missing_required_field invalid_utf8 (fixture-loader only)
Conformance
| Requirement | Detail |
|---|---|
| PROV-LIFE-001 | event_kind MUST be one of the 10 registered provisioning event kinds |
| PROV-LIFE-002 | provider_ref MUST match opaque reference grammar |
| PROV-LIFE-003 | Recursive credential-material scanner MUST reject inline token material |
| PROV-LIFE-004 | storage_surface.kind MUST be one of the 7 allowed surface kinds |
| PROV-LIFE-005 | observed_at MUST be a valid RFC 3339 timestamp |
| PROV-LIFE-006..010 | Amount minor units, currency, sub_event, scheme_id, and material redaction invariants |
Conformance Section 31 (PROV-LIFE-001..010) — 260 total requirement IDs across 29 sections in v0.14.2.
Links
Start recording provisioning events
Add portable signed records to your agent provisioning pipeline in minutes. The provisioning lifecycle profile integrates with any provisioning system — PEAC records what your code reports, without becoming the authorization layer.