Files
boc/QUIXZOOM_EVIDENCE_GRAPH.md
T

318 lines
8.9 KiB
Markdown
Raw Normal View History

# quiXzoom — Evidence Graph & Verified Claim
*Beslutad: 2026-06-17. Ägare: Erik Svensson.*
*Bygger på: QUIXZOOM_VISION.md, QUIXZOOM_VERIFIED_REALITY.md, QUIXZOOM_AVO_MASTERPROMPT_V2.md*
---
## Enheten är utsagan — inte bilden, inte evidenspaketet
Det ni säljer, lagrar, fakturerar och kan bli stämda över är **påståendet**:
> "Livbojen vid kaj 14B existerade och var i korrekt skick 2026-06-17 kl 12:22 UTC."
Det är en `verified_claim`. Allt annat — frames, OCR, gyrodata, liveness — är evidens *för* utsagan.
---
## Claim-schemat
```json
{
"claim_id": "clm_9f3a8c1b",
"claim_type": "object_existence_and_condition",
"claim_text": "Livbojen vid kaj 14B existerar och är i korrekt skick.",
"control_point": "lifebuoy_kaj14b",
"knowledge_pack_id": "maritime_safety_v2",
"trust_threshold": 0.92,
"trust_achieved": 0.961,
"decision": "verified",
"evidence_bundle_id": "evb_7d2f1a9e",
"evidence_bundle_hash": "sha256:a3f8b2...",
"zoomer_id": "z_9981",
"device_id": "dev_ios_xyz",
"session_id": "sess_abc123",
"geo": { "lat": 59.334, "lng": 18.063, "accuracy_m": 4 },
"timestamp_start": "2026-06-17T12:20:41Z",
"timestamp_decision": "2026-06-17T12:22:04Z",
"signature": "ed25519:9f3a...",
"immutable": true
}
```
`trust_threshold` ägs av kunskapspaketet — per claim-typ, aldrig globalt.
`decision` är append-only. Korrektion sker som ny claim som refererar bakåt.
---
## Sufficiency-funktionen — förtroende-ackumulator
Systemet samlar evidens tills `trust_achieved ≥ trust_threshold`. Sedan stannar det.
```
trust_achieved = Σ (weight_i × confidence_i × liveness_factor)
```
Varje evidenselement bidrar med viktad konfidens:
| Element | Vikt (example) | Bidrar till |
|---------|---------------|-------------|
| Visual coverage frame | 0.15 | Objekt existerar |
| OCR serial match | 0.25 | Objekt identifierat |
| Liveness Score >90 | 0.20 | Observation äkta |
| GPS match ±15m | 0.15 | Objekt på rätt plats |
| App Attest valid | 0.10 | Enhet omodifierad |
| Challenge passed (per st) | 0.08 | Anti-spoofing |
| Reference match | 0.07 | Korrekt skick |
**Vikterna och trösklarna ägs av kunskapspaketet**, inte av AVO-koden.
### Konsekvensen
Ibland räcker 4 frames och 2 challenges. Ibland krävs 40 frames och 5 challenges.
Systemet vet när det är klart — Zoomern vet det aldrig förrän det är grönt.
### Sufficiency kan misslyckas
Om systemet inte når tröskeln inom:
- Max scan-tid (konfigurerbart, default 120s)
- Max challenges (default 5)
- Max frames (default 600)
`decision: insufficient_evidence` → eskalera till manuell granskning.
**Aldrig:** tvinga fram ett svagt godkännande för att undvika eskalering.
```json
{
"claim_id": "clm_4b2e9d7a",
"decision": "insufficient_evidence",
"trust_achieved": 0.71,
"trust_threshold": 0.92,
"limiting_factor": "liveness_score_too_low",
"escalation": "manual_review",
"photographer_directive": null
}
```
---
## Evidence Bundle — schemat
Det fullständiga, signerade paketet som claim:en refererar till:
```json
{
"bundle_id": "evb_7d2f1a9e",
"claim_id": "clm_9f3a8c1b",
"created_at": "2026-06-17T12:22:04Z",
"liveness": {
"score": 97,
"signals": {
"gyro_natural": true,
"parallax_verified": true,
"focus_changes": 4,
"gps_match": true,
"app_attest": true,
"stream_continuous": true,
"challenges_issued": 3,
"challenges_passed": 3
}
},
"evidence_elements": [
{
"element_id": "e1",
"type": "visual_frame",
"frame_index": 142,
"timestamp_ms": 3820,
"confidence": 0.97,
"weight": 0.15,
"contribution": 0.1455,
"hash": "sha256:f1a2b3..."
},
{
"element_id": "e2",
"type": "ocr_extraction",
"frame_index": 198,
"timestamp_ms": 5180,
"confidence": 0.94,
"weight": 0.25,
"contribution": 0.2350,
"extracted_value": "SE-4821-9938-01",
"hash": "sha256:c4d5e6..."
},
{
"element_id": "e3",
"type": "challenge_response",
"challenge_issued_at_ms": 6200,
"challenge_directive": "Gå ett steg bakåt",
"challenge_class": "liveness",
"response_detected_at_ms": 8100,
"confidence": 0.96,
"weight": 0.08,
"contribution": 0.0768
}
],
"trust_accumulation": [
{ "after_element": "e1", "trust_so_far": 0.1455 },
{ "after_element": "e2", "trust_so_far": 0.3805 },
{ "after_element": "e3", "trust_so_far": 0.4573 }
],
"bundle_hash": "sha256:a3f8b2...",
"signature": "ed25519:9f3a...",
"immutable": true
}
```
`trust_accumulation` loggar hur förtroendet byggdes upp steg för steg.
Vid återgranskning kan man se exakt varför beslutet fattades — och vid vilken evidens tröskeln passerades.
---
## Challenge-direktivets vokabulär
**Designkrav:** Zoomern kan aldrig avgöra om ett direktiv är guidning eller liveness-challenge.
```
"Flytta kameran 30 cm åt vänster." ← kan vara guidning (framing_ok)
eller challenge (liveness, kräver parallax)
"Höj kameran lite." ← kan vara guidning (angle_ok)
eller challenge (liveness, kräver rörelse)
"Visa objektets nedre del." ← kan vara guidning (coverage)
eller challenge (liveness, kräver ny vinkel)
```
Samma fras, samma röst, samma UI. Challenge-klassen är intern — aldrig exponerad.
```json
{
"directive": "Gå ett steg bakåt",
"directive_class": "liveness_challenge", INTERN, visas aldrig för Zoomer
"expected_signal": "zoom_out + parallax_change",
"timeout_ms": 8000
}
```
---
## Korrektion av en verified_claim
En verifierad utsaga är immutable. Korrektion sker som ny claim som refererar bakåt:
```json
{
"claim_id": "clm_4c7f2b8d",
"claim_type": "correction",
"corrects_claim_id": "clm_9f3a8c1b",
"correction_reason": "Manuell granskning: serienummer OCR-fel, korrekt värde SE-4821-9938-02",
"corrected_by": "reviewer_human_012",
"timestamp": "2026-06-17T15:33:11Z",
"signature": "ed25519:7b2c...",
"immutable": true
}
```
Originalclaim:en finns kvar. Granskningskedjan är komplett.
---
## Kunskapspaketet äger tröskeln
```json
{
"object": "lifebuoy",
"claim_type": "existence_and_condition",
"trust_threshold": 0.92,
"evidence_weights": {
"visual_frame": 0.15,
"ocr_serial": 0.25,
"liveness_score_component": 0.20,
"gps_match": 0.15,
"app_attest": 0.10,
"challenge_response": 0.08,
"reference_match": 0.07
},
"min_liveness_score": 80,
"max_scan_seconds": 120,
"compliance": "maritime_safety"
}
```
```json
{
"object": "passport",
"claim_type": "identity_document_authenticity",
"trust_threshold": 0.97,
"evidence_weights": {
"mrz_validation": 0.30,
"photo_match": 0.25,
"tamper_detection": 0.20,
"liveness_score_component": 0.15,
"challenge_response": 0.10
},
"min_liveness_score": 95,
"max_scan_seconds": 60,
"compliance": "regulated"
}
```
Passet kräver 97% förtroende och minst 95 i liveness.
Livbojen kräver 92% och minst 80 i liveness.
Samma motor — olika parametrar. Aldrig hårdkodad logik.
---
## Persistens och juridisk hållbarhet
| Krav | Implementation |
|------|---------------|
| Immutability | Append-only storage (S3 Object Lock / DynamoDB Streams) |
| Signering | Ed25519 per claim och per bundle |
| Återgranskningsbarhet | `trust_accumulation`-log i varje bundle |
| Temporal binding | Timestamp signerat med bundle-hash — kan inte backdateras |
| Separation | Bundle sparas separat från claim — kan granskas oberoende |
**Samma mönster som ledger:** en post ändras aldrig. Korrektion = ny post med bakåtreferens.
---
## Vad AVO v2-kontraktet fortfarande styr
Evidence Graph och Verified Claim är ett lager *ovanpå* AVO v2 — inte en ersättning.
```
Smart Scan (insamling)
AVO Fas A — Liveguidning (on-device, per frame)
AVO Fas B — Slutanalys (server, per exponering)
Sufficiency-funktion (ackumulerar trust mot claim-tröskel)
Evidence Bundle (signerat paket)
Verified Claim (persisterad, immutable utsaga)
QuickSum (summary till uppdragsgivare)
```
---
## Öppna frågor
1. **Vem äger kunskapspaketen?** quiXzoom sätter defaults — kan uppdragsgivare överskriva? Sätt ett golv.
2. **Juridisk beviskraft** — ed25519-signatur + immutable storage: räcker det i EU-rätt för försäkringsärenden? Behöver vi en ackrediterad tidsstämpel (RFC 3161)?
3. **RFC 3161 trusted timestamp** — binds claim-hashen till en extern tidsstämpelserver ger oberoende temporalt bevis. Troligtvis nödvändigt för regulated-klassen.
4. **Liveness-score för offline** — App Attest kräver nät. Offline-scanning ger lägre liveness-score. Accepteras av knowledge_pack?
5. **Granskningsgränssnitt** — hur ser det ut när en försäkringshandläggare öppnar ett bundle 6 månader senare? UI behöver designas för människa, inte för AVO.