Skip to main content
Version: v0.12.11

Provisioning Lifecycle Profile

The Provisioning Lifecycle profile (org.peacprotocol/provisioning-lifecycle) provides observer-scope signed records for infrastructure provisioning events: credential issuance, secret rotation, service authorization, key lifecycle, and access management. Introduced in v0.14.2 as the 16th PEAC extension group.

Package: @peac/schema (validator) — use with @peac/protocol to issue records.


Observer scope

Provisioning lifecycle records describe what provisioning systems reported. PEAC does not issue credentials, rotate secrets, or authorize services. Your provisioning infrastructure owns those decisions. PEAC provides portable, offline-verifiable signed evidence of what was reported at each provisioning boundary.


Install

Terminal
pnpm add @peac/schema @peac/protocol

Type URIs

10 *-observed type URIs are registered under the org.peacprotocol/provisioning-lifecycle extension group (Section 31, PROV-LIFE-001..010):

Type URIDescription
org.peacprotocol/provisioning-credential-issuance-observedA credential was issued by an external provider
org.peacprotocol/provisioning-credential-rotation-observedAn existing credential was rotated
org.peacprotocol/provisioning-secret-rotation-observedA secret was rotated in a secrets manager
org.peacprotocol/provisioning-service-authorization-observedA service was authorized to access another service
org.peacprotocol/provisioning-access-grant-observedAn access grant was issued
org.peacprotocol/provisioning-access-revocation-observedAn access grant was revoked
org.peacprotocol/provisioning-key-creation-observedA cryptographic key was created
org.peacprotocol/provisioning-key-deletion-observedA cryptographic key was deleted or archived
org.peacprotocol/provisioning-service-binding-observedA service binding was created (e.g., database credential injection)
org.peacprotocol/provisioning-lifecycle-complete-observedA provisioning lifecycle workflow completed

Quick start

provisioning-record.ts
import { validateProvisioningLifecycle } from '@peac/schema';
import { issue } from '@peac/protocol';

// Build the extension object
const provisioningExt = {
'org.peacprotocol/provisioning-lifecycle': {
event_kind: 'credential-issuance',
provider_ref: 'urn:provider:vault.corp.example.com',
credential_ref: 'ref:credential/db-svc-account',
storage_surface: {
kind: 'external_secret_store',
provider_ref: 'ref:provider/hashicorp-vault',
surface_ref: 'ref:path/secret/data/myapp/db',
},
observed_at: new Date().toISOString(),
},
};

// Validate before issuing
const result = validateProvisioningLifecycle(provisioningExt);
if (!result.success) {
console.error(result.error);
process.exit(1);
}

// Issue the signed record
const jws = await issue({
sub: 'ref:credential/db-svc-account',
iss: 'https://provisioning.corp.example.com',
type: 'org.peacprotocol/provisioning-credential-issuance-observed',
extensions: provisioningExt,
}, signingKey);

console.log(jws); // Compact JWS -- verifiable offline

Core fields

FieldRequiredTypeDescription
event_kindYesstringEvent kind identifier (see type URIs above)
provider_refYesopaque refReference to the provisioning provider
observed_atYesISO 8601When the provisioning event was observed
credential_refNoopaque refReference to the credential being issued/rotated
storage_surfaceNoobjectWhere the credential is stored (see below)
authorization_refNoopaque refReference to the authorization grant
expires_atNoISO 8601When the provisioned credential expires
sub_eventNostringSub-state within the event kind (e.g., requested, granted)

Opaque reference grammar

All *_ref fields use the opaque reference grammar. Raw values (API keys, tokens, emails, paths) are not allowed inline. Use one of these prefixes:

PrefixUse
urn:URN-style identifier
ref:Logical path reference
did:DID identifier
sha256:SHA-256 content digest
https:URL reference
// Correct: opaque reference
provider_ref: 'ref:provider/hashicorp-vault'
provider_ref: 'urn:provider:vault.corp.example.com'
provider_ref: 'did:web:vault.corp.example.com'

// Incorrect: inline value (rejected)
provider_ref: 'hvs.CAESIJ...' // token value -- rejected
provider_ref: '/secret/data/myapp' // raw path -- rejected

Storage surface object

The storage_surface object describes where a credential is stored without exposing the credential itself:

storage_surface: {
kind: 'external_secret_store', // see kind values below
provider_ref: 'ref:provider/hashicorp-vault', // opaque ref
surface_ref: 'ref:path/secret/data/myapp/db', // opaque ref
material_redaction: 'sha256_ref', // how credential material is redacted
}

Storage surface kind values:

KindDescription
external_secret_storeExternal secrets manager (Vault, AWS Secrets Manager, etc.)
local_encrypted_fileLocally encrypted credential file
local_plaintext_fileLocal plaintext file (flag for audit)
environment_file.env or environment variable file
runtime_secret_bindingInjected at runtime (e.g., Kubernetes secret mount)
noneNo persistent storage
unknownStorage surface not determinable

Credential material scanner

validateProvisioningLifecycle() includes a recursive credential material scanner that rejects records containing inline secrets. The scanner checks all string values for patterns matching JWTs, Bearer tokens, PEM private keys, .env-style assignments, and connection strings with credentials.

This is a hard gate: if your extension object contains inline credential material in any nested field, validation will fail with provisioning.token_material_blocked or provisioning.inline_credential_blocked.

// This will fail validation
const bad = {
'org.peacprotocol/provisioning-lifecycle': {
event_kind: 'credential-issuance',
provider_ref: 'ref:provider/vault',
// Do NOT put actual token values in any field
note: 'eyJhbGciOiJIUzI1NiIs...', // JWT -- blocked
observed_at: new Date().toISOString(),
},
};
const result = validateProvisioningLifecycle(bad);
// result.success === false
// result.error.issues[0].code === 'provisioning.token_material_blocked'

Error codes (21 stable codes)

CodeMeaning
provisioning.inline_credential_blockedForbidden top-level key with inline credential value
provisioning.token_material_blockedInline token material detected in a string field
provisioning.forbidden_key_nameField name is on the forbidden key list
provisioning.field_too_largeField value exceeds byte limit
provisioning.replacement_character_in_stringString contains Unicode replacement character
provisioning.structure_too_deepNesting depth exceeds maximum
provisioning.structure_too_largeTotal node count exceeds maximum
provisioning.opaque_ref_grammar_violationReference field does not match opaque ref grammar
provisioning.invalid_storage_surfacestorage_surface.kind is not a valid enum value
provisioning.invalid_material_redactionmaterial_redaction is not a valid value
provisioning.invalid_event_kindTop-level event_kind is not a known value
provisioning.invalid_sub_eventsub_event is not valid for this event_kind
provisioning.invalid_scheme_idscheme_id violates the bounded grammar
provisioning.invalid_amount_minoramount_minor is not a valid non-negative decimal string
provisioning.invalid_observed_atobserved_at is not a valid ISO 8601 timestamp
provisioning.invalid_retrieved_atretrieved_at is not a valid ISO 8601 timestamp
provisioning.invalid_expires_atexpires_at is not a valid ISO 8601 timestamp
provisioning.invalid_currencycurrency is not a valid ISO 4217 code
provisioning.unrecognized_fieldUnknown field in the extension object
provisioning.missing_required_fieldRequired field is absent
provisioning.invalid_utf8String contains invalid UTF-8 sequences (fixture loader)

Conformance

Section 31 (PROV-LIFE-001..010) covers the 10 normative conformance requirements for provisioning lifecycle records. These are part of the 290 conformance requirements across 32 sections in PEAC v0.14.4.


Non-goals

Provisioning lifecycle records do not:

  • Issue or provision credentials themselves
  • Rotate secrets on your behalf
  • Connect to or authenticate against any secrets manager
  • Guarantee that the reported provisioning event occurred correctly
  • Replace audit logs from your provisioning infrastructure