Skip to content

fix: preserve unsigned metadata in canonical surface contracts - #248

Open
patrickleet wants to merge 2 commits into
fix/aggregate-replay-event-versionfrom
fix/surface-contract-unsigned-integer-20260912
Open

fix: preserve unsigned metadata in canonical surface contracts#248
patrickleet wants to merge 2 commits into
fix/aggregate-replay-event-versionfrom
fix/surface-contract-unsigned-integer-20260912

Conversation

@patrickleet

Copy link
Copy Markdown
Collaborator

Typed application manifests with unsigned command fields fail NonCanonical("surface contract material"): the Surface emitter includes unsigned_integer, but manifest reconstruction dropped it. Preserve that optional metadata recursively for command inputs and outputs. Unrefined fields retain their existing JSON shape and fingerprints.

The regression uses the same Service::application path as Forge, with intentionally unsorted derived fields, all unsigned widths, optional/list/nested types, ordinary signed/string fields, canonical byte round trips, and rejection of altered unsigned metadata. The unsigned-input documentation now describes canonical manifest retention.

Validation:

  • Baseline fd58eeb reproduces NonCanonical("surface contract material").
  • cargo test --all-features --lib: 1,075 passed, 4 ignored.
  • cargo test --all-features --test application_composition --test application_plans: 35 passed.
  • cargo test -p distributed_cli: 293 passed, 11 ignored.
  • cargo test -p distributed_cli --test cli_manifest -- --ignored: 6 passed, including existing fingerprint assertions.
  • Changed Rust files pass rustfmt --check; git diff --check passes.

This branch starts at #247 and targets its same base, fix/aggregate-replay-event-version; the incremental fix is commit be009bd. The inherited #247 unsigned-input changes are breaking for manually constructed command type fields and require service/client regeneration. This follow-up adds no further API or wire-version change. No Forge source or dependency workaround is included.

Separate finding: direct Module composition can reject unsorted authored command fields because its ownership comparison sees declaration order versus Surface order. Forge's Service path already calls with_surface_binding, replacing those shapes with the canonical Surface versions, and the regression verifies that path with unsorted source fields. The direct-Module finding is recorded separately in GitKB unsigned-surface-metadata-breaks-canonical-typed-m; it is outside this fix.

Preserve typed nonnegative integer ranges through command derives, portable metadata, generated codecs and U64 projection proofs. Reject inexact browser numbers before optimism or dispatch while preserving native unsigned range and signed codecs.

BREAKING CHANGE: manually constructed command/surface fields require unsigned_integer metadata; the protocol fingerprint changes and services and generated clients must be rebuilt together.
Refs [[unsigned-surface-metadata-breaks-canonical-typed-m]]
@coderabbitai

coderabbitai Bot commented Sep 11, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 70dee8a7-0a61-4666-8d34-287b9464cac8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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