- Add Implementation Status section to A2H2A spec - Clarify Google Chat is notification-only - Add target approval architecture requirements - Add critical A2H2A safety principle to RUNBOOK.md - Remove unsafe approval/rejection endpoints from server.py - Enforce server-side parameter_hash calculation - Disable execution for all tools in A2H2A_TOOL_ALLOW_LIST
7.8 KiB
OSVxCC A2H2A Ticketing System Specification
1. Introduksjon
A2H2A (Agent-to-Human-to-Agent) er en uomgåelig Approval Gate mellom autonome observatører/analytikere og operative eksekveringsagenter. Ingen destruktive eller privilegerte handlinger skal utføres i GCP-infrastrukturen uten at autorisert operatør eksplisitt har validert og godkjent handlingen via et kryptografisk signert grensesnitt.
Implementation Status
Current prototype — proposal recording only; approval and execution disabled.
- The prototype may accept an allow-listed ticket proposal and store it as
PENDING. - Google Chat is notification-only. It does not verify or prove the identity of an approver.
- The current
/a2h2a/review/{ticket_id}link is conceptual only. - No working approval or rejection endpoint currently exists.
- No one-time action token currently exists.
- No execution worker currently exists.
- No proposed tool is executable through A2H2A at this stage.
2. JSON Datamodell (a2h2a-ticket-v1.json)
{
"ticket_id": "A2H2A-20260904-8B3D",
"timestamp": "2026-09-04T14:20:05Z",
"severity": "CRITICAL",
"category": "SECURITY",
"source": {
"reporter": "tyr-compliance-agent",
"trigger": "Secret scanned in public repository",
"affected_service": "mcp-server-key",
"project_id": "propane-will-491900-m5",
"region": "global"
},
"context": {
"summary": "En aktiv Secret Manager-nøkkel ble funnet i en offentlig Gitea-commit.",
"evidence_logs": [
"gitea.commit.url: https://git.vauco.no/chris/OSVauco/commit/a1b2c3d4...",
"secret.name: projects/357036551735/secrets/mcp-server-key/versions/2"
]
},
"proposed_action": {
"action_type": "AUTOMATED_REMEDIATION",
"runbook_reference": "docs/RUNBOOK.md#hendelse-eksponert-hemmelighet",
"execution_tool": "opax.secrets.rotate",
"parameters": {
"secret_name": "mcp-server-key",
"disable_old_versions": true,
"notify_channel": "#security-alerts"
},
"parameter_hash": "sha256:f4a2...d8e0",
"rollback_plan": "Manuell re-aktivering av forrige hemmelighetsversjon via `gcloud secrets versions enable` etter verifisering."
},
"governance": {
"approval_status": "PENDING",
"authorized_approver": "chris.christiansen@vauco.no",
"requires_mfa": true,
"timeout_minutes": 15
}
}
The ticket model is a proposal model. Fields required for secure human approval—such as approval_token_hash, verified_approver_identity, approval timestamp, token_used_at, and immutable audit-event references—are target-design fields and are not implemented in the current prototype.
3. Sikkerhetsgarantier
3.1 Constant-Time Authentication
- Sammenligning av alle signaturer og tokens skal utføres med
secrets.compare_digesteller tilsvarende for å forhindre timing-angrep.
3.2 Anti-Tampering
- En SHA-256 hash av
proposed_action.parametersskal beregnes før ticketen sendes til operatør. - Før eksekvering skal OPAX verifisere at hashen av parameterne den mottok for eksekvering stemmer overens med
parameter_hashi den godkjente ticketen.
3.3 Replay-Beskyttelse
- Hver callback fra Slack/Discord skal inneholde et timestamp.
- Serveren skal avvise callbacks hvor
current_time - callback_timestamp > 300sekunder for å forhindre gjenbruk av gamle godkjenninger.
3.4 Time-To-Live (TTL)
- Ubehandlede tickets utløper automatisk basert på alvorlighetsgrad:
- CRITICAL: 15 minutter
- HIGH: 60 minutter
- MEDIUM/LOW: 24 timer
4. API-Endepunkter (Prototype)
4.1 POST /api/v1/a2h2a/tickets
- Motta ticket-payload fra en autorisert intern agent (f.eks. TYR).
- Valider payloaden mot en Pydantic-modell basert på schemaet over.
- Beregn
parameter_hashserver-side. - Lagre ticketen i en Firestore-collection (
a2h2a_tickets) med statusPENDING. - Formater og send en Google Chat-melding med et konseptuelt link til en fremtidig godkjennings-UI.
Google Chat delivers a notification and review link only; it must never be used as evidence of the approver's identity or as the authority to execute a tool.
Target Approval Architecture — Required Before Production
The eventual review URL may use:
/a2h2a/review/{ticket_id}?token=<opaque-random-token>
- The token is generated with a cryptographically secure random generator.
- The raw token is returned once in the notification link and is never persisted.
- Only the SHA-256 token hash is stored server-side.
- Approval/rejection backend verifies IAP-verified identity, PENDING state, TTL, unused matching token hash, authorized approver, server-side canonical parameter hash, and tool allow-list.
- Approval only updates the ticket state.
- A separate worker later executes only server-stored, immutable, approved actions.
- Every audit event is a target requirement; do not claim it is already implemented.
Target audit requirements
Immutable audit events for proposal, approval, rejection, expiry, execution start, execution success, execution failure, and rollback are required before production activation; they are not implemented in the current prototype.
5. Google Chat / Slack Block Kit Payload (Konseptuelt Eksempel)
{
"blocks": [
{
"type": "header",
"text": {
"type": "plain_text",
"text": "🚨 A2H2A Godkjenning Kreves: CRITICAL"
}
},
{
"type": "section",
"fields": [
{"type": "mrkdwn", "text": "*Kategori:*
SECURITY"},
{"type": "mrkdwn", "text": "*Tjeneste:*
mcp-server-key"},
{"type": "mrkdwn", "text": "*Handling:*
`opax.secrets.rotate`"},
{"type": "mrkdwn", "text": "*Tidsfrist:*
15 minutter"}
]
},
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*Sammendrag:*
En aktiv Secret Manager-nøkkel ble funnet i en offentlig Gitea-commit."
}
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "✅ Godkjenn",
"emoji": true
},
"style": "primary",
"value": "approve_A2H2A-20260904-8B3D"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "❌ Avvis",
"emoji": true
},
"style": "danger",
"value": "reject_A2H2A-20260904-8B3D"
}
]
}
]
}
6. Eksempel-Ticket (SECRET_EXPOSURE)
{
"ticket_id": "A2H2A-20260904-1C4F",
"timestamp": "2026-09-04T18:05:10Z",
"severity": "CRITICAL",
"category": "SECURITY",
"source": {
"reporter": "tyr-scanner-agent",
"trigger": "Audit log anomaly: Unexpected access to mcp-server-key v2",
"affected_service": "mcp-server-key",
"project_id": "propane-will-491900-m5",
"region": "global"
},
"context": {
"summary": "Mistenkelig tilgang til mcp-server-key v2 fra en ukjent IP-adresse (35.22.88.101) utenfor GCP-nettverket.",
"evidence_logs": [
"log_explorer_link: https://console.cloud.google.com/logs/query;query=..."
]
},
"proposed_action": {
"action_type": "AUTOMATED_REMEDIATION",
"runbook_reference": "docs/RUNBOOK.md#hendelse-eksponert-hemmelighet",
"execution_tool": "opax.secrets.rotate",
"parameters": {
"secret_name": "mcp-server-key",
"disable_old_versions": true,
"notify_channel": "#security-alerts"
},
"parameter_hash": "sha256:f4a26901a511e6cb716b5a86552631521a0e71383921034293739886313ad8e0",
"rollback_plan": "Manuell re-aktivering av forrige hemmelighetsversjon (v3) via `gcloud secrets versions enable` etter verifisering."
},
"governance": {
"approval_status": "PENDING",
"authorized_approver": "chris.christiansen@vauco.no",
"requires_mfa": true,
"timeout_minutes": 15
}
}