Skip to content

Schema codegen: generate the dev schema from the Rust wire model#543

Open
MGudgin wants to merge 2 commits into
mainfrom
user/gudge/versioning_phase2a
Open

Schema codegen: generate the dev schema from the Rust wire model#543
MGudgin wants to merge 2 commits into
mainfrom
user/gudge/versioning_phase2a

Conversation

@MGudgin

@MGudgin MGudgin commented Jun 19, 2026

Copy link
Copy Markdown
Member

📖 Description

This PR changes the committed dev JSON Schema to be generated from the Rust wire model (wxc_common::wire) instead of hand-authored, so the schema can no longer drift from the type definitions that form the parser's trust boundary.

Details:

  • Extend the wire model to cover the full config surface (one-shot + state-aware: a Phase enum, top-level phase/sandboxId, per-phase isolation_session nesting). Stable surface stays strict (deny_unknown_fields); experimental stays permissive.
  • Post-process the generated output: inject the canonical $id, normalize schemars' non-standard integer formats to draft-07 (minimum:0 for unsigned), and float the root metadata ($schema/$id/title/description) to the top via render_root_ordered (self-contained, no serde_json feature, so nested objects stay alphabetical and the schema diff stays minimal).
  • Set title via #[schemars(title)] and description via the MxcConfig doc comment (replacing the stale "one-shot request" wording).
  • Add scripts/versioning/check-schema-codegen.js: a regenerate + diff CI gate (line-ending-insensitive) wired into the Versioning Checks job.
  • Cross-field allOf rules are intentionally left out of the schema; the parser enforces them. Document the architecture + a schema-equivalence analysis in docs/schema-codegen.md, and note in copilot-instructions that the dev schema is generated (do not hand-edit).

🔗 References

Part of the schema-versioning remediation effort (follows the phase 0/1 work in #508 and #509). A follow-up rewires the parser to deserialize directly into the wire model and deletes the Raw* structs.

🔍 Validation

  • 167/167 corpus configs validate against the generated schema.
  • Codegen + schema-version + config-sync CI gates green.
  • wxc_common 338 tests pass; clippy (incl. --features schema-gen) + fmt clean.
  • Verified the generated schema is semantically identical to the prior hand-written one via a deep-sorted comparison (differences are encoding — definitions/$ref — intentionally-closed nested objects, and added documentation).

Copilot AI review requested due to automatic review settings June 19, 2026 20:24
@MGudgin MGudgin requested a review from a team as a code owner June 19, 2026 20:24
@MGudgin MGudgin force-pushed the user/gudge/versioning_phase2a branch from e181a70 to 75930ab Compare June 19, 2026 20:27
This PR changes the committed dev JSON Schema to be generated from the Rust wire
model (`wxc_common::wire`) instead of hand-authored, so the schema can no longer
drift from the type definitions that form the parser's trust boundary.

Details:
- Extend the wire model to cover the full config surface (one-shot + state-aware:
  a Phase enum, top-level phase/sandboxId, per-phase isolation_session nesting).
  Stable surface stays strict (deny_unknown_fields); experimental stays permissive.
- Post-process the generated output: inject the canonical $id, normalize schemars'
  non-standard integer formats to draft-07 (minimum:0 for unsigned), and float the
  root metadata ($schema/$id/title/description) to the top via render_root_ordered
  (self-contained, no serde_json feature, so nested objects stay alphabetical and
  the schema diff stays minimal).
- Set title via #[schemars(title)] and description via the MxcConfig doc comment
  (replacing the stale "one-shot request" wording).
- Add scripts/versioning/check-schema-codegen.js: a regenerate + diff CI gate
  (line-ending-insensitive) wired into the Versioning Checks job.
- Cross-field allOf rules are intentionally left out of the schema; the parser
  enforces them. Document the architecture + a schema-equivalence analysis in
  docs/schema-codegen.md, and note in copilot-instructions that the dev schema is
  generated (do not hand-edit).

Tests:
- 167/167 corpus configs validate against the generated schema.
- Codegen + schema-version + config-sync CI gates green.
- wxc_common 338 tests pass; clippy (incl. --features schema-gen) + fmt clean.
- Verified the generated schema is semantically identical to the prior
  hand-written one via a deep-sorted comparison.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MGudgin MGudgin force-pushed the user/gudge/versioning_phase2a branch from 75930ab to 227691d Compare June 19, 2026 20:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes wxc_common::wire the single source of truth for the dev MXC config JSON Schema by generating schemas/dev/mxc-config.schema.0.8.0-dev.json from a dedicated Rust wire model, and adds a CI gate to prevent schema drift.

Changes:

  • Add a wxc_common::wire Rust wire model (behind a schema-gen feature) plus a mxc_schema_gen tool to emit the dev schema from the model.
  • Add scripts/versioning/check-schema-codegen.js and wire it into the GitHub Actions “Versioning Checks” job to regenerate-and-diff the committed schema (line-ending-insensitive).
  • Update the committed dev schema and adjust macOS example configs to match the new schema surface (e.g., removing the old seatbelt.mode).
Show a summary per file
File Description
tests/examples/15_mac_hello_world.json Removes legacy seatbelt block fields to align examples with the current seatbelt config surface.
tests/examples/16_mac_deny_network.json Same as above for the deny-network example.
tests/examples/17_mac_deny_filesystem.json Same as above for the deny-filesystem example.
tests/examples/18_mac_filesystem_access.json Same as above for filesystem allow example.
tests/examples/19_mac_network_restricted.json Same as above for restricted network example.
tests/examples/20_mac_combined_restrictions.json Same as above for combined restrictions example.
tests/examples/21_mac_python_info.json Same as above for python-info example.
tests/examples/22_mac_network_allow_all.json Same as above for allow-all network example.
tests/examples/23_mac_blocked_hosts_unsupported.json Same as above for blocked-hosts example.
tests/examples/24_mac_ui_disabled.json Same as above for UI-disabled example.
tests/examples/25_mac_ui_clipboard_enabled.json Same as above for clipboard-enabled example.
src/tools/mxc_schema_gen/src/main.rs New CLI tool that calls wxc_common::wire::generate_config_schema_json() and writes the schema to stdout/file.
src/tools/mxc_schema_gen/Cargo.toml Adds the schema generator tool crate and depends on wxc_common with schema-gen.
src/core/wxc_common/src/wire.rs Introduces the dedicated wire model and schema post-processing (inject $id, normalize integer formats, root key ordering).
src/core/wxc_common/src/lib.rs Exposes wire behind the schema-gen feature.
src/core/wxc_common/Cargo.toml Adds the schema-gen feature and optional schemars dependency.
src/Cargo.toml Adds tools/mxc_schema_gen to the Rust workspace.
src/Cargo.lock Records new dependencies for schema generation tooling (schemars, etc.).
scripts/versioning/check-schema-codegen.js New gate script that regenerates the schema and diffs against the committed dev schema.
schemas/dev/mxc-config.schema.0.8.0-dev.json Updated dev schema artifact to the code-generated output.
docs/schema-codegen.md New documentation describing the schema codegen architecture, gates, and equivalence notes.
.github/workflows/Versioning.Checks.Job.yml Adds the schema codegen check to the Versioning Checks workflow.

Copilot's findings

  • Files reviewed: 22/23 changed files
  • Comments generated: 7

Comment thread src/core/wxc_common/src/wire.rs
Comment thread src/core/wxc_common/src/wire.rs
Comment thread src/core/wxc_common/src/wire.rs
Comment thread scripts/versioning/check-schema-codegen.js Outdated
Comment thread docs/schema-codegen.md Outdated
Comment thread src/tools/mxc_schema_gen/src/main.rs Outdated
Comment thread src/tools/mxc_schema_gen/src/main.rs Outdated
…sage)

This PR addresses Copilot review feedback on the schema-codegen change.

Details:
- Advertise the 1..=65535 port range on the wire model's port fields
  (PortMapping.windowsPort/containerPort, Proxy.localhost) via
  #[schemars(range)], so the generated schema matches the parser (which rejects
  port 0) instead of allowing minimum:0.
- Fix the regeneration command everywhere it appears (mxc_schema_gen usage,
  check-schema-codegen.js failure message, docs/schema-codegen.md,
  copilot-instructions): use `cargo run --manifest-path src/Cargo.toml ...`
  since the Cargo workspace is src/ and the repo root has no Cargo.toml.
- Print the generator's "wrote schema" status to stdout instead of stderr so the
  CI codegen gate (which suppresses stdout, inherits stderr for build errors)
  stays quiet on success.

Tests:
- 167/167 corpus configs still validate; port fields now show minimum:1/maximum:65535.
- Codegen gate green; wxc_common 338 tests; clippy (incl. --features schema-gen) + fmt clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MGudgin

MGudgin commented Jun 19, 2026

Copy link
Copy Markdown
Member Author

Thanks for the review. Addressed in c166225:

  • Port rangesPortMapping.windowsPort/containerPort and Proxy.localhost now advertise 1..=65535 via #[schemars(range)], so the generated schema matches the parser (which rejects port 0).
  • Run-from-root usage — the regeneration command now uses cargo run --manifest-path src/Cargo.toml ... in the tool usage string, the codegen-gate failure message, docs/schema-codegen.md, and copilot-instructions (the Cargo workspace is src/).
  • Quiet CI — the generator's "wrote schema" status now prints to stdout (which the codegen gate suppresses) instead of stderr; build errors stay on stderr.

Declined the process.commandLine "required" suggestion (replied inline) — it's conditionally required (state-aware non-exec phases and CLI overrides omit it), which the schema can't express; the parser enforces it.

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.

2 participants