Skip to content

feat(seismic-manifest): render and schema-check the network manifest - #269

Merged
samlaf merged 1 commit into
seismicfrom
sl/sei-211-feat-rust-manifest-tool-reusing-the-schema-crate
Aug 27, 2026
Merged

feat(seismic-manifest): render and schema-check the network manifest#269
samlaf merged 1 commit into
seismicfrom
sl/sei-211-feat-rust-manifest-tool-reusing-the-schema-crate

Conversation

@samlaf

@samlaf samlaf commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Closes SEI-211.

The deploy CLI re-implemented the manifest's canonical rendering and its network_id in Python, kept byte-for-byte in step with the Rust parser by a shared fixture and golden vectors on both sides. Two implementations of one security identifier is a standing split-brain risk, and the lockstep was held by hand.

seismic-manifest is the one implementation: a library with a thin CLI over the seismic-network-manifest schema crate. render takes a manifest document in any JSON formatting and writes the canonical network-manifest.json bytes; parse puts an existing manifest through the same strict v1 parser every node reads it with and answers with its exit code, writing nothing. Non-Rust callers shell out to the binary; Rust deploy tooling links the library.

The emitter lives apart from the schema crate on purpose. That crate implements Deserialize only, so no node build has a code path that re-serializes the file, and any re-rendering risks changing the bytes and therefore the network_id. A feature gate would not hold that line, since cargo unifies features across a --workspace build.

Two things the renderer does deliberately:

  • It sorts keys itself rather than leaning on serde_json::Map. Which order that map yields is set by preserve_order, a non-additive feature any crate in the graph can turn on — dcap-qvl does, so a --workspace build gets insertion order while a standalone cargo install gets sorted. Sorting explicitly keeps the bytes, and the network_id, independent of how the tool was built.
  • It destructures NetworkManifestV1 field by field, so a later schema change fails to compile until the rendering is updated with it.

network_id is not part of the tool's output. It is sha256 of the file bytes with no canonicalization step, so unlike the rendering and the schema it has nothing that could drift between implementations.

Closes SEI-211.

The deploy CLI re-implemented the manifest's canonical rendering and its
`network_id` in Python, kept byte-for-byte in step with the Rust parser by
a shared fixture and golden vectors on both sides. Two implementations of
one security identifier is a standing split-brain risk, and the lockstep
was held by hand.

`seismic-manifest` is the one implementation: a library with a thin CLI
over the `seismic-network-manifest` schema crate. `render` takes a manifest
document in any JSON formatting and writes the canonical
`network-manifest.json` bytes; `parse` puts an existing manifest through
the same strict v1 parser every node reads it with and answers with its
exit code, writing nothing. Non-Rust callers shell out to the binary; Rust
deploy tooling links the library.

The emitter lives apart from the schema crate on purpose. That crate
implements `Deserialize` only, so no node build has a code path that
re-serializes the file, and any re-rendering risks changing the bytes and
therefore the `network_id`. A feature gate would not hold that line, since
cargo unifies features across a `--workspace` build.

Two things the renderer does deliberately:

- It sorts keys itself rather than leaning on `serde_json::Map`. Which
  order that map yields is set by `preserve_order`, a non-additive feature
  any crate in the graph can turn on — `dcap-qvl` does, so a `--workspace`
  build gets insertion order while a standalone `cargo install` gets
  sorted. Sorting explicitly keeps the bytes, and the `network_id`,
  independent of how the tool was built.
- It destructures `NetworkManifestV1` field by field, so a later schema
  change fails to compile until the rendering is updated with it.

`network_id` is not part of the tool's output. It is `sha256` of the file
bytes with no canonicalization step, so unlike the rendering and the schema
it has nothing that could drift between implementations.
@samlaf
samlaf requested a review from cdrappi as a code owner August 27, 2026 16:52
@linear-code

linear-code Bot commented Aug 27, 2026

Copy link
Copy Markdown

SEI-211

@samlaf
samlaf merged commit 2422116 into seismic Aug 27, 2026
5 checks passed
@samlaf
samlaf deleted the sl/sei-211-feat-rust-manifest-tool-reusing-the-schema-crate branch August 27, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant