# 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) ```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_digest` eller tilsvarende for å forhindre timing-angrep. ### 3.2 Anti-Tampering - En SHA-256 hash av `proposed_action.parameters` **skal** 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_hash` i 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 > 300` sekunder 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 1. Motta ticket-payload fra en autorisert intern agent (f.eks. TYR). 2. Valider payloaden mot en Pydantic-modell basert på schemaet over. 3. Beregn `parameter_hash` server-side. 4. Lagre ticketen i en Firestore-collection (`a2h2a_tickets`) med status `PENDING`. 5. 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=` - 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) ```json { "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) ```json { "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 } } ```