test(versioning): pin supported compatibility matrix

req: abi/001

req: abi/003

req: v1_release/007
This commit is contained in:
slhx agent
2026-07-14 01:09:07 +02:00
parent 6f58453aae
commit 90e8c3ced5
3 changed files with 50 additions and 3 deletions
+3 -1
View File
@@ -71,8 +71,10 @@ encryption, retention, backup, and deployment policy remain host concerns.
## Slice 7 — v1 compatibility and closure ## Slice 7 — v1 compatibility and closure
- [ ] **User value:** maintainers and adopters receive a reproducible, migration-aware v1 with no known material contradiction and no hidden publication side effect. - [ ] **User value:** maintainers and adopters receive a reproducible, migration-aware v1 with no known material contradiction and no hidden publication side effect.
- **State:** Active; Slices 1-6 are complete, and publishing remains separately authorized. - **State:** In progress — the compatibility audit now names the actually supported matrix, replaces the vague migration-fixture gate with checked-in ABI-v1 bytes plus the real legacy durable-record browser migration, and proves all four canonical example packages together.
- **Build:** freeze the supported Rust/browser/WASM/integration matrix; reconcile public/generated/Surface/symbol/wire/runtime/persisted-schema compatibility; add migration fixtures; make canonical examples compatibility tests; update the progressive tutorial path; run all local release gates and disposition every P0/P1, advisory, unsafe-code, license, performance, accessibility, and documentation finding. - **Build:** freeze the supported Rust/browser/WASM/integration matrix; reconcile public/generated/Surface/symbol/wire/runtime/persisted-schema compatibility; add migration fixtures; make canonical examples compatibility tests; update the progressive tutorial path; run all local release gates and disposition every P0/P1, advisory, unsafe-code, license, performance, accessibility, and documentation finding.
- **Refusals:** no publish, deploy, upload, store submission, speculative feature, or weakening a gate to make it pass. - **Refusals:** no publish, deploy, upload, store submission, speculative feature, or weakening a gate to make it pass.
- **Requirements:** `v1_release/001-010`, `versioning/*`, `test/*`, `diag/*`, `performance/*`, `security/008`, and all requirements changed by the preceding slices. - **Requirements:** `v1_release/001-010`, `versioning/*`, `test/*`, `diag/*`, `performance/*`, `security/008`, and all requirements changed by the preceding slices.
- **Proof:** clean-tree formatting, workspace tests, strict all-target Clippy, compile-fail, browser/WASM/offline/multiplayer scenarios, benchmark budgets, approved pinned lockfile audit, requirements proof audit, docs/examples checks, and independent contradiction review all pass with no unresolved P0/P1. - **Proof:** clean-tree formatting, workspace tests, strict all-target Clippy, compile-fail, browser/WASM/offline/multiplayer scenarios, benchmark budgets, approved pinned lockfile audit, requirements proof audit, docs/examples checks, and independent contradiction review all pass with no unresolved P0/P1.
`cargo test -p hemx-core --test effect_batch compatibility_fixture_accepts_only_the_declared_v1_wire_version -- --exact`, `cargo test -p hemx-wasm --test browser flat_patch_persists_offline_then_uploads_with_same_operation_identity -- --exact`, and `cargo test -p hemx-v0-examples -p hemx-client-local-example -p hemx-kanban-example -p hemx-saas-example --lib --bins` prove the first compatibility gate. Execution cursor: run the remaining Slice 7 release audit gates from the canonical `hemx-xtask test` entry point, resolve only genuine local failures, and record exact blocked external audit tools instead of inventing substitutes.
+25 -2
View File
@@ -39,6 +39,22 @@ An incompatible wire/runtime change must bump the relevant ABI version and cause
old pages or old runtimes to refuse partial updates rather than silently applying old pages or old runtimes to refuse partial updates rather than silently applying
wrong effects. req: abi/002 req: abi/003 req: abi/004 req: failure/005 wrong effects. req: abi/002 req: abi/003 req: abi/004 req: failure/005
### Supported compatibility matrix
The v1 support claim is deliberately narrow:
| Boundary | Supported | Fails closed when |
|---|---|---|
| Rust toolchain | stable Rust, workspace edition 2021 | an unsupported compiler cannot build the workspace |
| Browser/WASM | Firefox browser suite plus the generated real-WASM path | WASM/bootstrap cannot load or bind |
| Effect wire | ABI `1` only | decoding preserves the version, `is_compatible()` is false, and runtimes refuse application |
| Generated resources | one matching build fingerprint | a stale fingerprint receives reload recovery instead of mutation |
| Durable sync | schema `1`; legacy flat schema-1 records upgrade in place | unknown schema or malformed projection is rejected |
| Runtime set | same-tree `hemx-js`, `hemx-wasm`, generated bindings, and framework sync runtime | mismatched assets have no compatibility guarantee |
| Canonical examples | `v0`, Kanban, client-local, and SaaS workspace packages | an example no longer builds or its focused proof fails |
No support claim is made for untested browser engines, future wire/schema versions, or arbitrary cross-release runtime mixing. req: abi/001 req: abi/003 req: public_api/003 req: v1_release/007
### Advanced escape hatches ### Advanced escape hatches
These are public but advanced. They may evolve faster, but every change still These are public but advanced. They may evolve faster, but every change still
@@ -126,15 +142,22 @@ redgate health --strict
Before tagging a v1-compatible release: Before tagging a v1-compatible release:
- `examples/v0` and `examples/saas` compile and test without raw ids, raw effects, - `examples/v0`, `examples/client_local`, `examples/kanban`, and `examples/saas`
compile and their package tests pass; v0 and SaaS remain the canonical public
surface examples without raw ids, raw effects,
selector targeting, manual registries, raw render/lower calls, or user-authored selector targeting, manual registries, raw render/lower calls, or user-authored
UI JavaScript in the normal path. req: examples/004 req: examples/005 UI JavaScript in the normal path. req: examples/004 req: examples/005
- `docs/diagnostics.md` describes any new common error class in user language. - `docs/diagnostics.md` describes any new common error class in user language.
req: diagnostics/001 req: diagnostics/002 req: diag/001 req: diag/002
- The canonical local release gate is `cargo run -p hemx-xtask -- test`; there
are no separate `public-api` or `ownership-check` xtask subcommands.
- `docs/recipes/deploy-versioning.md` remains accurate for runtime asset and - `docs/recipes/deploy-versioning.md` remains accurate for runtime asset and
fingerprint behavior. fingerprint behavior.
- Any incompatible generated ABI/runtime change bumps the relevant ABI/fingerprint - Any incompatible generated ABI/runtime change bumps the relevant ABI/fingerprint
inputs and has tests for fail-closed behavior. req: abi/005 inputs and has tests for fail-closed behavior. req: abi/005
- The checked-in ABI-v1 byte fixture in `hemx-core/tests/effect_batch.rs`, the
legacy flat durable-record browser migration, and canonical example package
tests all pass. req: abi/001 req: abi/003 req: v1_release/007
- Advanced APIs touched by the release are still named as escape hatches in docs. - Advanced APIs touched by the release are still named as escape hatches in docs.
- Upgrade notes state whether users must regenerate code, redeploy the - Upgrade notes state whether users must regenerate code, redeploy the
helper-provided runtime asset, or change app code. helper-provided runtime asset, or change app code.
+22
View File
@@ -30,6 +30,28 @@ fn effect_batch_wire_round_trips() {
assert!(decoded.is_compatible()); assert!(decoded.is_compatible());
} }
#[test]
fn compatibility_fixture_accepts_only_the_declared_v1_wire_version() {
// test req: abi/001 req: abi/003 req: v1_release/007
const V1_EMPTY_BATCH: &[u8] = &[
72, 69, 77, 88, // HEMX
1, 0, // ABI v1
0, 0, // reserved
7, 0, 0, 0, 0, 0, 0, 0, // fingerprint
0, 0, 0, 0, // zero operations
];
assert_eq!(
EffectBatch::from_wire(V1_EMPTY_BATCH).unwrap().to_wire(),
V1_EMPTY_BATCH
);
let mut future = V1_EMPTY_BATCH.to_vec();
future[4] = 2;
let future = EffectBatch::from_wire(&future).unwrap();
assert_eq!(future.abi_version, 2);
assert!(!future.is_compatible());
}
#[test] #[test]
fn encoded_len_covers_every_effect_shape() { fn encoded_len_covers_every_effect_shape() {
let unscoped = ResourceRef::unscoped(ResourceId::new(ResourceKind::Slot, 1)); let unscoped = ResourceRef::unscoped(ResourceId::new(ResourceKind::Slot, 1));