|
| 1 | +<!-- SPDX-License-Identifier: PMPL-1.0-or-later --> |
| 2 | + |
| 3 | +# ECHIDNA Wire Schema Versioning Policy (`crates/echidna-wire`) |
| 4 | + |
| 5 | +Every root message MUST carry `schemaVersion :UInt16`. Current: **1**. |
| 6 | +File-level capnp IDs (`@0x…;`) are generated once and NEVER changed. |
| 7 | + |
| 8 | +## Compatibility model |
| 9 | + |
| 10 | +Cap'n Proto is structurally forward/backward-compatible within a major |
| 11 | +version provided the rules below are respected. Major version bumps are |
| 12 | +breaking and require a coordinated rollout across Rust core, Julia, |
| 13 | +Chapel, and UI peers. |
| 14 | + |
| 15 | +## Adding a field (SAFE — no version bump) |
| 16 | + |
| 17 | +- Append new fields at the next unused `@N`. |
| 18 | +- New fields MUST either: |
| 19 | + - (a) have a default value (e.g. `@N :Bool = false`), OR |
| 20 | + - (b) be paired with a `has<Name> :Bool` sibling for optional semantics. |
| 21 | +- New union variants may be appended at the end of an existing union. |
| 22 | +- New nested structs may be added freely. |
| 23 | + |
| 24 | +## Removing / changing a field (UNSAFE — major bump) |
| 25 | + |
| 26 | +- Reordering `@N` IDs of existing fields. |
| 27 | +- Changing a field's wire type (e.g. `UInt32` → `UInt64`). |
| 28 | +- Removing a non-optional field. |
| 29 | +- Reordering union discriminants. |
| 30 | +- Changing the stable `ProverKind` discriminant mapping |
| 31 | + (mirrored in `src/rust/ffi/mod.rs`). |
| 32 | + |
| 33 | +## Deprecation flow |
| 34 | + |
| 35 | +1. Mark the field obsolete in this file and in a comment on the `.capnp` |
| 36 | + line. Add a new replacement field at the next `@N`. |
| 37 | +2. Wait ONE minor version before removal candidacy (L1.0 → L1.1). |
| 38 | +3. Field removal = major bump (L1.x → L2.0). Must ship an |
| 39 | + `echidna-wire v2` alongside v1 for at least one release cycle. |
| 40 | + |
| 41 | +## Connection-time negotiation |
| 42 | + |
| 43 | +Every transport session opens with a `Hello` exchange (schema deferred |
| 44 | +to L1.1 in `version.capnp`): |
| 45 | + |
| 46 | +``` |
| 47 | +client → server : Hello { supportedMajors :List(UInt16); preferredMajor :UInt16; } |
| 48 | +server → client : HelloAck { agreedMajor :UInt16; agreedMinor :UInt16; } |
| 49 | +``` |
| 50 | + |
| 51 | +If no overlap: server returns `HelloAck { agreedMajor = 0 }` and closes. |
| 52 | + |
| 53 | +## ProverKind discriminant governance |
| 54 | + |
| 55 | +Appending a new variant to `ProverKind` (`src/rust/provers/mod.rs`) is |
| 56 | +SAFE iff: |
| 57 | + |
| 58 | +- the next contiguous `u16` is used (currently 105), |
| 59 | +- `kind_from_u8` / `kind_to_u8` are updated in lockstep |
| 60 | + (`src/rust/ffi/mod.rs`), |
| 61 | +- this file records the assignment. |
| 62 | + |
| 63 | +Holes in the discriminant space are FORBIDDEN — the invertibility test |
| 64 | +at `src/rust/ffi/mod.rs` (see `kind_to_u8_injective` / round-trip tests) |
| 65 | +must keep passing. |
| 66 | + |
| 67 | +## Current assignments |
| 68 | + |
| 69 | +- Schema major: **1**. Minor: **0**. |
| 70 | +- File IDs: |
| 71 | + - `common.capnp` = `@0xf2f7187fddaa9139` |
| 72 | + - `proof.capnp` = `@0xfa73f2ec7415f450` |
| 73 | + - `prover.capnp` = `@0xf1841ae6bbc44651` |
| 74 | + - `gnn.capnp` = `@0xfbb66b8481def8a0` |
| 75 | +- Deprecations in flight: none. |
0 commit comments