schema_version
(e.g. dispute_packet.v1), is frozen. A packet
built today that verifies against verify.py today will
still verify against a future verify.py that still
understands dispute_packet.v1 -- new fields get added
additively, in a new schema version, never by silently changing what
an existing version's fields mean.
schema_version field is
checked, not assumed. `verify.py`'s verify_events
function rejects a packet whose schema_version doesn't
match the specific version this verifier build understands
(MANIFEST_SCHEMA_MISMATCH) -- see SPEC.md and
`verify.py`'s own SCHEMA_VERSION constant. This is what
makes "frozen per version" an enforced property, not just a promise: a
verifier build can never silently apply the wrong version's rules to a
packet.manifest.json's receipt_public_key_hex means
no external key registry or live service lookup is ever required to
verify a packet -- a decade-old packet verifies exactly the same way a
today packet does, with nothing to have gone stale in the meantime
except your own confidence that the embedded key really is the
signer's (a comparison you make once, out of band, same as any public
key).verify.py needs only the cryptography package
-- a decades-old packet still verifies as long as SOME version of that
one library, or a compatible re-implementation, is available. This is
a real, if narrow, dependency-continuity risk, stated honestly rather
than glossed over: "verify forever" assumes Ed25519/ECDSA verification
itself remains implementable, not that this exact file survives
unchanged forever.A breaking change to what a field means, or to which fields are
required, gets a NEW schema_version string (e.g. eventually
dispute_packet.v2) -- never a silent redefinition of
dispute_packet.v1. A verifier that understands both
versions can check either kind of packet correctly; a verifier that
only understands v1 will cleanly reject a v2 packet (rather than
silently mis-verifying it) because the schema_version check fails
closed.