OSVauco/docs/A2H2A_TICKETING_SPEC.md
Chris Christiansen 3b6e4e4890 docs/code: clarify A2H2A prototype status and disable execution
- 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
2026-09-04 12:00:07 +00:00

213 lines
7.8 KiB
Markdown

# 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=<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)
```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
}
}
```