11# MXC Version-Specific Config Parsers
22
33Status: implementation plan; Phases 1-4 merged in PRs #807 , #816 , #835 , and
4- #838 . Phase 4.1 and Phase 4.2 merged in PRs #907 and #912 . Phase 5 is complete:
5- Phase 5A merged in PR #909 , Phase 5B in PR #910 , Phase 5C in PR #929 , Phase 5D
6- in PR #941 , and the Phase 5A review follow-up in PR #949 . One stacked pull
7- request remains open and unreviewed: the capabilities parity remediation in
8- PR #966 , now based on ` main ` . Phase 6 is implemented in 11 commits on the local
9- branch ` user/gudge/version_specific_config_parsers_phase6 ` , branched from #949 ;
10- it has not been pushed and has no pull request, so it is unreviewed. Phase 7.1
11- is renamed Phase 7a: it is squashed onto ` main ` as
12- ` user/gudge/version_specific_config_parsers_phase7a ` , has no pull request, and
13- is therefore also unreviewed. Phases 7.2-7.5 and Phases 8-11 remain. The
14- parser-parity remediation that paused Phase 7 is addressed by PR #966 ; Phase 7
15- resumes when that PR merges.
4+ #838 . Phase 4.1 and Phase 4.2 merged in PRs #907 and #912 . Phase 5 is complete
5+ and merged: Phase 5A in PR #909 , Phase 5B in PR #910 , Phase 5C in PR #929 ,
6+ Phase 5D in PR #941 , the Phase 5A review follow-up in PR #949 , and the
7+ capabilities parity remediation in PR #966 . Phase 6 is complete and awaiting a
8+ final signoff in PR #968 , which also carries the directional networking the
9+ exact ` 0.8 ` contract had been missing. Phase 6.5 — publication of
10+ ` 0.8.0-alpha ` and the move of development to ` 0.9.0-alpha ` — is a single commit
11+ on ` user/gudge/version_specific_config_parsers_phase6.5 ` , rebased onto #968 ,
12+ with no pull request yet. Phase 7.1 is renamed Phase 7a and is open as PR #969 .
13+ Phases 7.2-7.5 and Phases 8-11 remain.
1614
1715Base: ` origin/main ` at ` 692275b84eaa3f83cd8582dc774bc5f354f46ccf `
1816(2026-08-14)
@@ -44,7 +42,7 @@ Base: `origin/main` at `692275b84eaa3f83cd8582dc774bc5f354f46ccf`
4442- Reject positional JSON arrays that Serde can deserialize into structs. That
4543 object-root hardening is out of scope for this work in every phase.
4644- Introduce another development version as part of the initial parser
47- conversion. ` 0.9.0-dev ` is selected when ` 0.8.0-alpha ` is published;
45+ conversion. ` 0.9.0-alpha ` is selected when ` 0.8.0-alpha ` is published;
4846 ` 1.0.0 ` remains a later milestone.
4947
5048## Contract reconstruction policy
@@ -210,7 +208,7 @@ will be added.
210208** Superseded by the revised publication sequence below.** ` 0.8.0-alpha ` is
211209being published early, so the table above describes the state up to that point
212210only: after publication ` 0.8.0-alpha ` is a published contract carrying the
213- stable-candidate one-shot surface, and ` 0.9.0-dev ` becomes the development
211+ stable-candidate one-shot surface, and ` 0.9.0-alpha ` becomes the development
214212contract holding experimental and state-aware. The exclusion list immediately
215213above therefore applies to ` 0.8.0-alpha ` as well.
216214
@@ -223,16 +221,48 @@ model ahead of this work. It replaces the implicit ordering in Phases 8 through
223221The order is:
224222
2252231 . PRs #961 and #962 land: directional networking and its backend validation,
226- on the rolling wire model, version-gated to ` 0.8 ` .
224+ on the rolling wire model, version-gated to ` 0.8 ` . ** Done. **
2272252 . Port the same fields into ` mxc_config_contract::dev ` and its adapters —
228226 ` network.egress ` , ` network.ingress ` , and
229227 ` processContainer.network.allowedProxyPeer ` . ** This is a prerequisite, not
230228 an option:** publishing a ` 0.8.0-alpha ` contract that cannot express a
231- feature the same version ships to customers would be incoherent.
229+ feature the same version ships to customers would be incoherent. ** Done, in
230+ PR #968 rather than separately:** a review of that pull request identified
231+ the same gap, so the port landed there alongside a ` NonEmptyVec ` primitive
232+ that restores the shipped schema's ` minItems ` constraint on a rule's ` to `
233+ and ` ports ` .
2322343 . Land Phase 6, so the generated artifacts derive from the contract crate.
235+ ** Awaiting a final signoff in PR #968 .**
2332364 . Publish ` 0.8.0-alpha ` from the contract crate, forking the published module,
234237 the frozen adapter, and (when it exists) the per-version policy builder.
235- 5 . Move the remaining development work to ` 0.9.0-dev ` .
238+ ** Implemented on the Phase 6.5 branch, rebased onto #968 .**
239+ 5 . Move the remaining development work to ` 0.9.0-alpha ` . ** Implemented on the
240+ same branch;** note the suffix is ` -alpha ` , not the ` -dev ` this plan
241+ originally wrote — see "Two coexisting versioning models".
242+
243+ ### Phase 6.5 as rebased
244+
245+ Phase 6.5 is one commit on top of #968 , adding roughly 7,700 lines across 130
246+ files. It:
247+
248+ - forks ` published/v0_8_0_alpha ` from the development contract, carrying the
249+ directional network surface, ` RuntimeConfig ` , ` ProcessContainerNetwork ` ,
250+ ` NonEmptyVec ` , and the ` ProcessContainerCapability ` newtype
251+ - adds the frozen ` config_contract_adapters::v0_8 ` adapter
252+ - renames the development contract to ` 0.9.0-alpha ` , moving its tests and
253+ fixtures to ` tests/v0_9_0_alpha `
254+ - registers both versions and commits the generated ` 0.9.0-alpha ` schema and
255+ TypeScript oracle
256+
257+ Two consequences of the rebase are worth recording, because both were found by
258+ a failing test rather than by inspection. The 0.8 test suite inherited from
259+ #968 assumed ` 0.8 ` was still the development contract, so it listed
260+ ` "experimental": {} ` as an acceptable empty optional object; under publication
261+ that document must be rejected. And the adapter and one-shot tests added to
262+ #968 for ` runtimeConfig ` carried ` 0.8.0-alpha ` version markers into the renamed
263+ ` 0.9 ` suites, where the exact version marker rejects them. Both are the same
264+ class of error: a version-specific test moving between contracts without its
265+ version string moving with it.
236266
237267### Why the stable schema is generated from the contract
238268
@@ -265,7 +295,7 @@ stable-surface fields, so they publish with the rest of the one-shot contract.
265295
266296The corpus cost is small and entirely predictable. Of the thirty configs
267297declaring ` 0.8.0-alpha ` today, twenty-four are stable-candidate only and stay;
268- six move to ` 0.9.0-dev ` , and they are the same six documents — every one is a
298+ six move to ` 0.9.0-alpha ` , and they are the same six documents — every one is a
269299WSLC config that uses both the development-only ` wslc ` containment and an
270300` experimental ` block:
271301
@@ -278,7 +308,7 @@ wslc_filesystem_object.json wslc_port_mapping_tcp.json
278308No corpus config declares ` 0.8.0-alpha ` together with a ` phase ` , so excluding
279309state-aware costs nothing in the corpus. It does, however, decide where
280310state-aware lives: with no published version to declare, state-aware requests
281- move from the ` 0.6.0-alpha ` they hard-code today onto ` 0.9.0-dev ` , so the
311+ move from the ` 0.6.0-alpha ` they hard-code today onto ` 0.9.0-alpha ` , so the
282312lifecycle ships only against a development contract until it is promoted. That
283313is the intended consequence of the Phase 11 rule, recorded here as a choice.
284314
@@ -309,7 +339,7 @@ coexist.
309339 contracts. Deliberate is fine; accidental is not.
310340- Phase 8's "state-aware producers must stop hard-coding ` 0.6.0-alpha ` " moves
311341 up: that constant is more obviously wrong once ` 0.8.0-alpha ` is published,
312- and the scope decision sends state-aware to ` 0.9.0-dev ` rather than to the
342+ and the scope decision sends state-aware to ` 0.9.0-alpha ` rather than to the
313343 newly published version. ` schemas/schema-version.json ` 's ` stateAware ` field
314344 moves with it.
315345- Phase 6's branch must be rebased and its artifacts ** regenerated** rather
@@ -381,12 +411,15 @@ disagree about the same version numbers rather than merely duplicating them.
381411 for the rolling family being retired. An audit on 2026-08-21 found the
382412 contract stack already compliant — ` registry.rs ` and ` mxc_schema_gen ` contain
383413 no ` -dev ` reference — with a single exception: the ` $schema ` string in
384- ` tests/v0_9_0_alpha/fixtures/one_shot/valid/annotations.json ` points at a
385- nonexistent ` 0.9.0-dev ` file. It is inert, since ` $schema ` is a free string
386- the contract does not resolve, which is why no gate catches it.
414+ ` tests/v0_9_0_alpha/fixtures/one_shot/valid/annotations.json ` pointed at a
415+ nonexistent ` 0.9.0-dev ` file. It was inert, since ` $schema ` is a free string
416+ the contract does not resolve, which is why no gate caught it. ** Fixed on the
417+ Phase 6.5 branch.**
387418- Move the published ` 0.8 ` artifact to ` schemas/stable/ ` and make ` schema_id `
388419 and ` schema_path ` agree. A ` Published ` descriptor writing into ` schemas/dev/ `
389- is what makes contradiction 4 possible.
420+ is what makes contradiction 4 possible. ** The registry now names the stable
421+ path on the Phase 6.5 branch; the artifact itself is created by whoever
422+ publishes ` 0.8 ` through the old stack, not by this work.**
390423
391424** Medium.** Split the three jobs "version" currently conflates: what the
392425runtime accepts, what shape is frozen, and what artifact is generated. Narrow
@@ -1189,7 +1222,7 @@ published `0.6.0-alpha` or `0.7.0-alpha` requests.
11891222Extend ` mxc_schema_gen ` with the publication command:
11901223
11911224``` text
1192- mxc_schema_gen publish --version 0.8.0-alpha --next-dev 0.9.0-dev
1225+ mxc_schema_gen publish --version 0.8.0-alpha --next-dev 0.9.0-alpha
11931226```
11941227
11951228Publication copies only the development stable-candidate request;
0 commit comments