Implements Spec 075 (V1.5) on top of Spec 074. Highlights - Deterministic report fingerprint (sha256) + previous_report_id linkage - Viewer change indicator: "No changes" vs "Changed" when previous exists - Check acknowledgements (fail|warn|block) with capability-first auth, confirmation, and audit event - Verify-step UX polish (issues-first, primary CTA) Testing - Focused Pest coverage for fingerprint, previous resolver, change indicator, acknowledgements, badge semantics, DB-only viewer guard. Notes - Viewing remains DB-only (no external calls while rendering). Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Reviewed-on: #93
148 lines
4.2 KiB
JSON
148 lines
4.2 KiB
JSON
{
|
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
"$id": "https://tenantpilot.local/contracts/verification-report.v1_5.schema.json",
|
|
"title": "VerificationReportV1_5",
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"schema_version",
|
|
"flow",
|
|
"generated_at",
|
|
"fingerprint",
|
|
"previous_report_id",
|
|
"summary",
|
|
"checks"
|
|
],
|
|
"properties": {
|
|
"report_id": {
|
|
"description": "Canonical report identifier. In v1.5 this is the OperationRun id.",
|
|
"type": ["string", "integer"]
|
|
},
|
|
"schema_version": {
|
|
"type": "string",
|
|
"description": "Version of the verification report schema (SemVer, major 1).",
|
|
"pattern": "^1\\.[0-9]+\\.[0-9]+$"
|
|
},
|
|
"flow": {
|
|
"type": "string",
|
|
"description": "Verification flow identifier (v1 aligns with OperationRun.type)."
|
|
},
|
|
"previous_report_id": {
|
|
"description": "Previous report id for the same identity (nullable).",
|
|
"type": ["string", "integer", "null"]
|
|
},
|
|
"generated_at": {
|
|
"type": "string",
|
|
"format": "date-time"
|
|
},
|
|
"identity": {
|
|
"type": "object",
|
|
"description": "Scope identifiers for what is being verified.",
|
|
"additionalProperties": true
|
|
},
|
|
"fingerprint": {
|
|
"description": "Deterministic SHA-256 hash (lowercase hex) of normalized check outcomes.",
|
|
"type": "string",
|
|
"pattern": "^[a-f0-9]{64}$"
|
|
},
|
|
"summary": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["overall", "counts"],
|
|
"properties": {
|
|
"overall": {
|
|
"type": "string",
|
|
"enum": ["ready", "needs_attention", "blocked", "running"],
|
|
"description": "Overall state derived from check results."
|
|
},
|
|
"counts": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["total", "pass", "fail", "warn", "skip", "running"],
|
|
"properties": {
|
|
"total": { "type": "integer", "minimum": 0 },
|
|
"pass": { "type": "integer", "minimum": 0 },
|
|
"fail": { "type": "integer", "minimum": 0 },
|
|
"warn": { "type": "integer", "minimum": 0 },
|
|
"skip": { "type": "integer", "minimum": 0 },
|
|
"running": { "type": "integer", "minimum": 0 }
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"checks": {
|
|
"type": "array",
|
|
"minItems": 0,
|
|
"items": {
|
|
"$ref": "#/$defs/CheckResult"
|
|
}
|
|
}
|
|
},
|
|
"$defs": {
|
|
"CheckResult": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": [
|
|
"key",
|
|
"title",
|
|
"status",
|
|
"severity",
|
|
"blocking",
|
|
"reason_code",
|
|
"message",
|
|
"evidence",
|
|
"next_steps"
|
|
],
|
|
"properties": {
|
|
"key": { "type": "string" },
|
|
"title": { "type": "string" },
|
|
"status": {
|
|
"type": "string",
|
|
"enum": ["pass", "fail", "warn", "skip", "running"]
|
|
},
|
|
"severity": {
|
|
"description": "Must be included for fingerprint determinism; may be empty string.",
|
|
"type": "string",
|
|
"enum": ["", "info", "low", "medium", "high", "critical"]
|
|
},
|
|
"blocking": { "type": "boolean" },
|
|
"reason_code": { "type": "string" },
|
|
"message": { "type": "string" },
|
|
"evidence": {
|
|
"type": "array",
|
|
"items": { "$ref": "#/$defs/EvidencePointer" }
|
|
},
|
|
"next_steps": {
|
|
"type": "array",
|
|
"description": "Navigation-only CTAs (links) in v1.",
|
|
"items": { "$ref": "#/$defs/NextStep" }
|
|
}
|
|
}
|
|
},
|
|
"EvidencePointer": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["kind", "value"],
|
|
"properties": {
|
|
"kind": { "type": "string" },
|
|
"value": {
|
|
"description": "Safe pointer value (ID/masked string/hash).",
|
|
"oneOf": [
|
|
{ "type": "integer" },
|
|
{ "type": "string" }
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"NextStep": {
|
|
"type": "object",
|
|
"additionalProperties": false,
|
|
"required": ["label", "url"],
|
|
"properties": {
|
|
"label": { "type": "string" },
|
|
"url": { "type": "string" }
|
|
}
|
|
}
|
|
}
|
|
}
|