TG-EXECUTION-AUTH-01
Execution Authorization Protocol
Abstract
This document specifies the TrigGuard Execution Authorization Protocol (TG-EXECUTION-AUTH-01), a deterministic authorization mechanism for critical system actions. The protocol provides a standardized interface for requesting authorization before executing irreversible operations, with cryptographically verifiable decision receipts.
1. Overview
TrigGuard is an execution authorization layer that sits between automation systems and irreversible execution surfaces. Systems request authorization before performing critical operations and receive a deterministic decision with a cryptographically signed receipt.
1.1 Design Goals
- Deterministic: Every request produces a consistent, repeatable decision
- Fail-Closed: When evaluation is not possible, execution is blocked
- Verifiable: All decisions produce signed receipts that can be verified offline
- Stateless: The protocol does not require session state between requests
1.2 System Architecture
2. Authorization Flow
2.1 Request Phase
- Automation system initiates an irreversible operation
- Before execution, system sends
POST /executeto TrigGuard - Request includes surface identifier, action, and context
2.2 Evaluation Phase
- TrigGuard evaluates request against configured policies
- Decision is computed deterministically
- If evaluation fails, protocol returns SILENCE (fail-closed)
2.3 Response Phase
- TrigGuard returns decision: PERMIT, DENY, or SILENCE
- Response includes cryptographically signed receipt
- Receipt can be verified offline using public keys
2.4 Execution Phase
- If PERMIT: System proceeds with execution, storing receipt
- If DENY: System aborts execution, logs receipt
- If SILENCE: System aborts execution (fail-closed behavior)
3. POST /execute API
3.1 Endpoint
POST https://api.trigguardai.com/execute
3.2 Request Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer token: Bearer <api_key> |
Content-Type | Yes | Must be application/json |
X-Request-ID | No | Client-generated request identifier |
3.3 Request Body
{
"surface": "deploy.release",
"action": "promote-to-production",
"context": {
"commit": "a1b2c3d4",
"branch": "main",
"environment": "production",
"actor": "ci.github"
},
"idempotency_key": "deploy-2026-03-13-001"
}3.4 Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
surface | string | Yes | Execution surface identifier |
action | string | Yes | Specific action being authorized |
context | object | No | Additional context for policy evaluation |
idempotency_key | string | No | Unique key to prevent duplicate authorizations |
3.5 Response
{
"decision": "PERMIT",
"receipt_id": "rcpt_7f3a9c2b1d4e5f6a",
"timestamp": "2026-03-13T14:22:00.000Z",
"expires_at": "2026-03-13T14:32:00.000Z",
"surface": "deploy.release",
"context_hash": "sha256:e3b0c442...",
"signature": "ed25519:af39c8e7b2d1f4a6...",
"key_id": "tg_prod_01"
}4. Authorization Surfaces
Surfaces represent protected execution boundaries. Each surface corresponds to a category of irreversible operations.
4.1 Defined Surfaces
| Surface | Description |
|---|---|
deploy.release | Production deployments, release promotions |
infra.apply | Infrastructure changes (Terraform, Pulumi, CloudFormation) |
database.migrate | Schema changes, data migrations, DDL |
secrets.access | Credential retrieval, KMS decryption. TrigGuard authorizes the access event; the secret payload remains encrypted within your Vault/KMS. |
artifact.publish | Package publishing, container image tagging |
data.export | Production data exports, external transfers |
4.2 Custom Surfaces
Organizations MAY define custom surfaces following the pattern:
<domain>.<action>
Example: billing.refund, user.delete, config.update
5. Receipt Structure
Every authorization decision produces a signed receipt. Receipts are immutable records of authorization decisions.
5.1 Receipt Fields
| Field | Type | Description |
|---|---|---|
receipt_id | string | Unique receipt identifier |
decision | string | PERMIT, DENY, or SILENCE |
timestamp | string | ISO 8601 timestamp of decision |
expires_at | string | Receipt expiration (optional) |
surface | string | Execution surface |
context_hash | string | SHA-256 hash of request context |
signature | string | Ed25519 signature |
key_id | string | Signing key identifier |
5.2 Example Receipt
{
"receipt_id": "rcpt_92a71f",
"decision": "PERMIT",
"timestamp": "2026-03-13T14:22:00.000Z",
"expires_at": "2026-03-13T14:32:00.000Z",
"surface": "deploy.release",
"context_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"signature": "ed25519:af39c8e7b2d1f4a6c9d2e5f8a1b4c7d0e3f6a9b2...",
"key_id": "tg_prod_01"
}6. Signature Verification
Receipts are signed using Ed25519. Verification can be performed offline.
6.1 Signature Payload
The signature covers the canonical JSON representation of:
{
"receipt_id": "<receipt_id>",
"decision": "<decision>",
"timestamp": "<timestamp>",
"surface": "<surface>",
"context_hash": "<context_hash>"
}6.2 Verification Process
- Fetch public keys from
/.well-known/trigguard-keys.json - Parse receipt JSON
- Construct canonical payload
- Look up public key by
key_id - Verify Ed25519 signature
6.3 Example (Python)
# Verification example using PyNaCl
from nacl.signing import VerifyKey
import json
def verify_receipt(receipt, public_key_bytes):
payload = json.dumps({
"receipt_id": receipt["receipt_id"],
"decision": receipt["decision"],
"timestamp": receipt["timestamp"],
"surface": receipt["surface"],
"context_hash": receipt["context_hash"]
}, separators=(',', ':'), sort_keys=True)
signature = bytes.fromhex(receipt["signature"].replace("ed25519:", ""))
verify_key = VerifyKey(public_key_bytes)
verify_key.verify(payload.encode(), signature)7. Key Discovery
Public keys for signature verification are published at a well-known URL.
7.1 Endpoint
GET /.well-known/trigguard-keys.json
7.2 Response
{
"keys": [
{
"key_id": "tg_prod_01",
"algorithm": "Ed25519",
"public_key": "MCowBQYDK2VwAyEA...",
"status": "active",
"created_at": "2026-03-01T00:00:00Z",
"expires_at": "2026-06-01T00:00:00Z"
}
],
"issuer": "https://api.trigguardai.com",
"documentation": "https://trigguardai.com/protocol"
}7.3 Key Rotation
- Keys are rotated quarterly
- Deprecated keys remain valid for 90 days after rotation
- Clients SHOULD cache keys and refresh periodically
8. Security Model
8.1 Threat Model
TrigGuard mitigates:
- Unauthorized execution of irreversible operations
- Audit trail manipulation
- Replay attacks (via idempotency keys)
- Key compromise (via key rotation)
8.2 Fail-Closed Behavior
When TrigGuard cannot evaluate a request:
- Decision is SILENCE
- System MUST NOT proceed with execution
- This ensures safety under uncertainty
8.3 Receipt Integrity
- Receipts are immutable once issued
- Signatures prevent tampering
- Offline verification prevents dependency on TrigGuard availability
9. Conformance
Implementations conforming to this specification:
- MUST support all three decision types (PERMIT, DENY, SILENCE)
- MUST sign all receipts with Ed25519
- MUST publish keys at
/.well-known/trigguard-keys.json - MUST fail closed when evaluation is not possible
- SHOULD support idempotency keys
- SHOULD cache public keys client-side
Appendix A: Decision Types
| Decision | HTTP Status | Action |
|---|---|---|
| PERMIT | 200 | Proceed with execution |
| DENY | 403 | Abort execution |
| SILENCE | 503 | Abort execution (fail-closed) |
Appendix B: Error Codes
| Code | HTTP Status | Description |
|---|---|---|
invalid_request | 400 | Malformed request body |
unauthorized | 401 | Invalid or missing API key |
rate_limited | 429 | Too many requests |
internal_error | 500 | Server error |
References
Copyright © 2026 TrigGuard AI Limited. UK Company No. 16597262.