Policy Artifact Specification
A Policy Artifact is a versioned, signed, time-bounded governance object. This specification defines the required fields, canonicalization rules, and signing process.
What are the required fields?
Every Policy Artifact must contain these fields. Missing or malformed fields cause rejection at the governance boundary.
{
// Version and identity
"policy_v": "1", // Schema version
"policy_version": 3, // Monotonic policy version
"policy_id": "sha256:a1b2c3...", // Content-addressed ID
// Time bounds
"created_at": "2024-01-15T10:00:00Z", // Issuance timestamp
"not_before": "2024-01-15T10:00:00Z", // Activation time
"not_after": "2024-07-15T10:00:00Z", // Expiration time
// Subject binding
"subject": {
"subject_type": "CONTAINER",
"subject_manifest_ref": "subject/subject_manifest.json"
},
// Governance rules
"selection_rules": [...], // Match conditions
"enforcement_mapping": {...}, // Action mappings
"measurement_set": [...], // What to measure
// Scheduling
"schedule": {
"interval_ms": 1000 // Measurement cadence
},
// Drift rules
"drift_rules": {
"mode": "STRICT_HASH_MATCH"
},
// Required receipts
"required_receipts": [
"POLICY_LOADED",
"MEASUREMENT_OK",
"DRIFT_DETECTED",
"ENFORCED",
"BUNDLE_EXPORTED"
],
// Issuer signature
"issuer": {
"public_key": "base64:...",
"key_id": "a1b2c3d4e5f67890",
"signature": "base64:..."
}
}How is policy_id computed?
The policy_id is a content-addressed hash that uniquely identifies the policy content. It must be computed deterministically so any verifier can recompute and verify.
// Step 1: Remove computed fields policy_for_hash = PolicyArtifact EXCLUDING issuer.signature EXCLUDING policy_id // Step 2: Canonicalize canonical_bytes = canonicalize(policy_for_hash) // Step 3: Hash policy_id = "sha256:" + HEX(SHA-256(canonical_bytes)) // Step 4: Set policy_id in artifact artifact.policy_id = policy_id
How is the signature computed?
The issuer signature covers the complete artifact except the signature itself. This includes the policy_id, creating a binding between content and identity.
// Step 1: Compute policy_id (see above) // Step 2: Prepare signing content signing_content = PolicyArtifact INCLUDING policy_id EXCLUDING issuer.signature // Step 3: Canonicalize canonical_bytes = canonicalize(signing_content) // Step 4: Sign issuer.signature = BASE64(Ed25519_sign(private_key, canonical_bytes)) // Step 5: Set key_id issuer.key_id = HEX(SHA-256(public_key_bytes))[0:16]
What are selection rules?
Selection rules determine which operations are subject to governance evaluation. They use a match-based syntax that the boundary evaluates deterministically.
"selection_rules": [
{
"rule_id": "match_all_executions",
"match": {
"operation_type": "EXECUTE",
"subject_pattern": "*"
},
"action": "EVALUATE"
},
{
"rule_id": "skip_healthchecks",
"match": {
"operation_type": "HEALTHCHECK"
},
"action": "PASS_THROUGH"
}
]What is the enforcement mapping?
The enforcement mapping defines what action to take for each drift condition. Every condition must have a defined action; the boundary must not guess.
"enforcement_mapping": {
"DRIFT_DETECTED": "BLOCK_EXECUTION",
"TTL_EXPIRED": "TERMINATE",
"SIGNATURE_INVALID": "TERMINATE",
"MEASUREMENT_FAILED": "CONTINUE",
"SUBJECT_MISSING": "BLOCK_EXECUTION"
}
// Valid actions:
// CONTINUE - Allow, log receipt
// BLOCK_EXECUTION - Prevent start
// TERMINATE - Stop running workloadHow does versioning work?
Policy versions are monotonically increasing integers. A new version references the previous version, creating an audit trail of policy evolution.
- ■policy_version: Integer, starts at 1, increments on each update
- ■previous_artifact_ref: Optional reference to prior policy_id
- ■Migration: Boundary validates new signature before accepting update
Frequently asked questions
Can I extend the schema with custom fields?
Yes, in the "extensions" object. Custom fields outside this object may break signature verification if canonicalization includes them.
What happens if not_after passes during a run?
The enforcement_mapping defines TTL_EXPIRED behavior. Typically TERMINATE, but configurable. Running workloads should check TTL and emit receipts accordingly.
Can multiple keys sign a policy?
The base spec supports single issuer. Enterprise extensions add multi-signature support with threshold requirements.