Skip to main content

Signed Tickets

A signed ticket is an OpenSSH-signed authorization payload that ASF50 uses to gate high-stakes production operations. The design is offline-friendly: the owner signs on their workstation, the orchestrator verifies, and the private key never enters the ASF50 repository, runtime, evidence, chat, or documentation.

Deterministic payload

A signed ticket payload has the following canonical fields:

{
"ticket_id": "<uuid>",
"gate_id": "<uuid>",
"goal_id": "<GOAL_ID>",
"subject_sha": "<40-char commit SHA>",
"production_target": "<environment name or identifier>",
"issuer": "<human principal name>",
"namespace": "<namespace>",
"payload_digest": "<hex digest of the payload being authorized>",
"created_at": "<UTC ISO-8601>"
}

The payload_digest binds the ticket to the exact bytes of the operation payload (e.g., the production manifest). Changing a single byte invalidates the signature.

Trust model

The owner maintains an owner public trust file at agent-harness/governance/allowed_signers (one line per principal). The matching owner private key lives only on the owner's workstation — never in the repo. The orchestrator verifies with ssh-keygen -Y verify:

ssh-keygen -Y verify \
-f agent-harness/governance/allowed_signers \
-I <issuer> \
-n <namespace> \
-s <signature-file>

If verification succeeds against the principal in allowed_signers, the ticket is considered authentic.

Replay protection

Tickets are single-use. After the orchestrator consumes a ticket, the gate transitions to APPROVED. A second submission of the same ticket_id is rejected with a replay error.

Subject binding

The ticket's subject_sha must match the runtime's observed HEAD. A ticket signed for SHA abc123 is rejected if the runtime is at def456. This is the canonical stale-subject rejection.

What the private key is NOT

  • It is not in the ASF50 repo.
  • It is not in the runtime DB or evidence/.
  • It is not in chat history.
  • It is not in this documentation.

If you see a private key anywhere in the canonical ASF50 repository, that is a security incident. Open a REPAIR_GOAL and revoke the key immediately.

See Signed-Ticket Guide for the operator walkthrough.