core.attestation
core.attestation
Attestation layer — the runtime proof layer (design-notes/attestation-layer.md).
Complements the STATIC proof layer (import-lint / FSM checks / typed firewalls, which prove what the code cannot do) with a RUNTIME record of what each agent actually did: signed (Step 3+), content-addressed, chained back to authored content. Step 2 is records-only — unsigned.
GATE_ACTIONS = frozenset({'gate_approve', 'gate_reject'})
module-attribute
AttestationKeyMissing
Bases: RuntimeError
Signing was enabled ([attestation] enabled = true) but no signing key is placed.
Fail-closed: rather than silently emit UNSIGNED attestations when the owner asked for signed ones, construction stops. Place the key (Keychain/Vault) before enabling — see the runbook.
Attestor
Bases: Protocol
emit(*, agent_role, action, input_hashes=(), output_hashes=(), derived_from_ids=None, vault_token_accessor='')
StoreAttestor
dataclass
Builds, links, signs, and appends an attestation per agent action.
store
instance-attribute
fingerprint = constitution_fingerprint
class-attribute
instance-attribute
clock = _utcnow
class-attribute
instance-attribute
signer = None
class-attribute
instance-attribute
emit(*, agent_role, action, input_hashes=(), output_hashes=(), derived_from_ids=None, vault_token_accessor='')
Ed25519Signer
dataclass
A private key + a signer name ("supervisor" | "owner"). The key never leaves this object: callers hand it a payload and get a base64 signature back. (Code attests; the model — and any agent — only ever sees the signature, never the key. attestation-layer.md §4.)
name
instance-attribute
from_seed(seed, name)
classmethod
sign(payload)
public_b64()
Attestation
dataclass
id
instance-attribute
timestamp
instance-attribute
agent_role
instance-attribute
action
instance-attribute
constitution_fingerprint
instance-attribute
input_hashes
instance-attribute
output_hashes
instance-attribute
derived_from_ids
instance-attribute
vault_token_accessor = ''
class-attribute
instance-attribute
signature = ''
class-attribute
instance-attribute
signer = ''
class-attribute
instance-attribute
signing_payload()
The exact bytes the id is SHA-256'd from and the signature (Step 3) signs.
create(*, timestamp, agent_role, action, constitution_fingerprint, input_hashes=(), output_hashes=(), derived_from_ids=(), vault_token_accessor='', signature='', signer='')
classmethod
Build an attestation with its content-addressed id computed (never set by hand).
to_dict()
from_dict(d)
classmethod
AttestationChain
dataclass
The transitive closure of an attestation and the prior attestations it derived from.
root_id
instance-attribute
attestations
instance-attribute
complete
instance-attribute
is_complete()
No broken links AND the root itself was found.
leaves()
Attestations with no parents — the bottom of the chain (e.g. ingest attestations, whose inputs are authored content digests).
leaf_input_hashes()
roles()
constitution_fingerprints()
verify_signatures(verify)
Step-3 hook: True iff verify(att) holds for every link. The caller supplies the
verifier appropriate to the phase (unsigned records have no signature to check).
AttestationStore
dataclass
path
instance-attribute
append(att)
Insert one attestation. Append-only: an id already present is left untouched (INSERT OR IGNORE), never overwritten. Ids are content-addressed, so a collision is a re-emission of the identical record — a no-op, not a conflict.
get(att_id)
all()
by_role(role)
producers_of(hashes)
Ids of attestations whose output_hashes intersect hashes — the attestations that
PRODUCED any of those outputs. This is the chain-linking lookup: an action consuming
hash h derives from whatever attested producing h (attestation-layer.md §2).
chain_for(att_id)
Assemble the transitive closure following derived_from_ids. complete is False if
any referenced parent (or the root) is absent — a broken link.
count()
close()
build_attestor(config=None)
Wire a StoreAttestor against the configured append-only attestation store.
Signing is owner-gated: only when [attestation] enabled = true is a supervisor signer
attached, and only if the private seed is actually placed (else fail-closed, never silently
unsigned). Default (enabled = false) is records-only — the Step-2 behavior.
generate_seed()
A fresh base64 Ed25519 private seed (32 bytes).
open_attestation_store(config=None)
build_verifier(config=None)
Wire a verifier from the configured public-key paths ([attestation]).
load_public_keys(supervisor_pub, owner_pub)
Load the committed public keys (non-secret) into a {signer: key} map. A missing file is simply absent from the map (verification of that signer then fails closed).
make_verifier(public_keys, *, require_owner_for=GATE_ACTIONS)
Return verify(att) -> bool over the given {signer_name: public_key} map.
attestor
The Attestor seam — agents emit attestations through this, not by touching store or crypto.
Keeping emission behind a small interface means the agents (dreamer, curator, vault watcher)
never learn about signing keys or the store schema: they describe what they did (role, action,
input/output hashes) and the attestor stamps the Constitution fingerprint + timestamp, links the
chain, (later) signs, and appends. Step 3 adds the signing step INSIDE emit — the agents do
not change. (Model advises; code attests — the agent never holds the key.)
AttestationKeyMissing
Bases: RuntimeError
Signing was enabled ([attestation] enabled = true) but no signing key is placed.
Fail-closed: rather than silently emit UNSIGNED attestations when the owner asked for signed ones, construction stops. Place the key (Keychain/Vault) before enabling — see the runbook.
Attestor
Bases: Protocol
emit(*, agent_role, action, input_hashes=(), output_hashes=(), derived_from_ids=None, vault_token_accessor='')
StoreAttestor
dataclass
Builds, links, signs, and appends an attestation per agent action.
store
instance-attribute
fingerprint = constitution_fingerprint
class-attribute
instance-attribute
clock = _utcnow
class-attribute
instance-attribute
signer = None
class-attribute
instance-attribute
emit(*, agent_role, action, input_hashes=(), output_hashes=(), derived_from_ids=None, vault_token_accessor='')
build_attestor(config=None)
Wire a StoreAttestor against the configured append-only attestation store.
Signing is owner-gated: only when [attestation] enabled = true is a supervisor signer
attached, and only if the private seed is actually placed (else fail-closed, never silently
unsigned). Default (enabled = false) is records-only — the Step-2 behavior.
crypto
Ed25519 signing primitives for attestations (attestation-layer.md §4).
Thin wrappers over cryptography's Ed25519. Keys are handled as base64 of the 32-byte raw seed
(private) / 32-byte raw point (public) — compact, copy-pasteable into Keychain, no PEM ceremony.
Signatures are base64 of the 64-byte raw signature.
cryptography is a crypto library, not a networking one — the import-lint network allowlist does
not flag it, so it is permitted in the sealed core (it opens no socket).
Ed25519Signer
dataclass
A private key + a signer name ("supervisor" | "owner"). The key never leaves this object: callers hand it a payload and get a base64 signature back. (Code attests; the model — and any agent — only ever sees the signature, never the key. attestation-layer.md §4.)
name
instance-attribute
from_seed(seed, name)
classmethod
sign(payload)
public_b64()
generate_seed()
A fresh base64 Ed25519 private seed (32 bytes).
seed_b64(priv)
public_b64(priv)
private_from_seed(seed)
public_from_b64(pub)
sign(priv, payload)
verify(pub, payload, signature_b64)
True iff signature_b64 is a valid Ed25519 signature of payload under pub. Any
failure mode — bad signature, malformed base64, wrong length — returns False, never raises.
record
The attestation record — a content-addressed (eventually signed) claim about one action.
A Vault token already attests "role X was authorized for resource Y at time T"; this record is
the analogue for the ACTION itself: "agent X performed action A on inputs I (by hash),
producing outputs O (by hash), under Constitution F, derived from the prior attestations whose
outputs it consumed." Chaining records by derived_from_ids gives every derived artifact a
verifiable lineage back to authored content (design-notes/attestation-layer.md §0–2).
Step 2 builds the RECORDS only — signature/signer stay empty. The id and (later) the
signature are both computed over signing_payload(), so the id is stable and the signature is
verifiable independently of the id (attestation-layer.md §2, §8: "start without signatures").
Attestation
dataclass
id
instance-attribute
timestamp
instance-attribute
agent_role
instance-attribute
action
instance-attribute
constitution_fingerprint
instance-attribute
input_hashes
instance-attribute
output_hashes
instance-attribute
derived_from_ids
instance-attribute
vault_token_accessor = ''
class-attribute
instance-attribute
signature = ''
class-attribute
instance-attribute
signer = ''
class-attribute
instance-attribute
signing_payload()
The exact bytes the id is SHA-256'd from and the signature (Step 3) signs.
create(*, timestamp, agent_role, action, constitution_fingerprint, input_hashes=(), output_hashes=(), derived_from_ids=(), vault_token_accessor='', signature='', signer='')
classmethod
Build an attestation with its content-addressed id computed (never set by hand).
to_dict()
from_dict(d)
classmethod
store
Append-only store for attestation records + chain assembly (attestation-layer.md §4–5).
APPEND-ONLY IS STRUCTURAL: this class exposes append and reads, and deliberately NO delete
or update. There is no API to mutate or remove a record — the gate's purge-raw action appends
a deletion attestation rather than erasing history (attestation-layer.md §4). That makes the
audit trail tamper-evident-by-construction even before signatures land (Step 3).
Thread-safety mirrors the JobQueue fix (PROGRESS 2026-06-27): the vault watcher emits ingest
attestations from a spawned thread, so the connection is opened check_same_thread=False and
every method is guarded by a reentrant lock.
AttestationChain
dataclass
The transitive closure of an attestation and the prior attestations it derived from.
root_id
instance-attribute
attestations
instance-attribute
complete
instance-attribute
is_complete()
No broken links AND the root itself was found.
leaves()
Attestations with no parents — the bottom of the chain (e.g. ingest attestations, whose inputs are authored content digests).
leaf_input_hashes()
roles()
constitution_fingerprints()
verify_signatures(verify)
Step-3 hook: True iff verify(att) holds for every link. The caller supplies the
verifier appropriate to the phase (unsigned records have no signature to check).
AttestationStore
dataclass
path
instance-attribute
append(att)
Insert one attestation. Append-only: an id already present is left untouched (INSERT OR IGNORE), never overwritten. Ids are content-addressed, so a collision is a re-emission of the identical record — a no-op, not a conflict.
get(att_id)
all()
by_role(role)
producers_of(hashes)
Ids of attestations whose output_hashes intersect hashes — the attestations that
PRODUCED any of those outputs. This is the chain-linking lookup: an action consuming
hash h derives from whatever attested producing h (attestation-layer.md §2).
chain_for(att_id)
Assemble the transitive closure following derived_from_ids. complete is False if
any referenced parent (or the root) is absent — a broken link.
count()
close()
open_attestation_store(config=None)
verify
Attestation signature verification + the gate-action owner-key policy (attestation-layer.md §3).
make_verifier(public_keys) returns a verify(att) -> bool suitable for
AttestationChain.verify_signatures(...). An attestation verifies iff:
- it carries a non-empty signature and a known signer,
- the signature is valid over att.signing_payload() under that signer's public key (so the id
can stay stable while the signature is checked independently — §2), and
- gate-decision attestations are signed by the OWNER key (§3): a gate_approve/gate_reject
record signed by anything other than "owner" is rejected, making gate decisions
non-repudiable. (Gate-attestation emission lands with the Phase-10 gate loop; this is the
verification half, enforced now.)
GATE_ACTIONS = frozenset({'gate_approve', 'gate_reject'})
module-attribute
make_verifier(public_keys, *, require_owner_for=GATE_ACTIONS)
Return verify(att) -> bool over the given {signer_name: public_key} map.
load_public_keys(supervisor_pub, owner_pub)
Load the committed public keys (non-secret) into a {signer: key} map. A missing file is simply absent from the map (verification of that signer then fails closed).
build_verifier(config=None)
Wire a verifier from the configured public-key paths ([attestation]).