Problem
Graph property routes are semantic identifiers, but several storage writers interpolate them directly into filesystem components. Valid routes such as CON, AUX, COM1, and LPT9 can be written on Unix and cannot be represented on Windows; portable graph-file inventory correctly rejects those components only after work has already been written. Other Windows-invalid punctuation is admitted by the same route boundary. The result is host-dependent publication and reopen behavior.
Objective
Encode every semantic node-label and edge-relation route into one reversible, collision-resistant, portable filesystem component while preserving the original semantic route through write, capture, publication, reopen, rewrite, export, and import.
Debt / regime
- Debt type: architecture and data portability
- Quality regime: A deterministic compute
Requirements
- Define one Rust-owned reversible route-component codec covering Windows reserved names, forbidden characters, trailing spaces/dots, Unicode normalization, case-insensitive collisions, and the codec escape prefix itself.
- Use the codec consistently in node-property and edge-property writers, readers, rewrites, inventory classification, portable export, and clean import.
- Preserve the original semantic route returned by public APIs; filesystem encoding must not leak into graph semantics.
- Admit existing authenticated Unix v1 trees containing raw reserved components through a bounded migration path, but never emit them into portable v2 inventory.
- Keep bindings thin and preserve path traversal, symlink, special-file, and collision rejection.
Acceptance Criteria
CON, AUX, COM1, LPT9, dotted aliases such as CON.foo, forbidden punctuation, trailing-dot/space names, mixed case, Unicode normalization variants, and literal escape-prefix routes round-trip without collision on every supported host.
- Node and edge properties written under those routes capture, publish, reopen, query, export, verify, clean-import, and reopen with the original semantic route.
- Distinct semantic routes never encode to the same portable path under case-insensitive or normalization-insensitive lookup.
- Existing authenticated Unix v1 raw routes either migrate losslessly or fail with a typed collision/ambiguity error before publication.
- Hosted Windows and macOS/Linux storage durability lanes pass at the exact PR head.
BDD Completion Scenarios
Portable reserved route
Given node label CON and edge relation AUX
When their properties are written and the graph is published and reopened
Then the original semantic routes and property values are returned exactly
And the persisted inventory contains only portable encoded components.
Collision-safe migration
Given an authenticated legacy Unix tree containing raw and escape-prefix-like route names
When it is migrated to portable inventory
Then every distinct semantic route remains distinct
And any ambiguous legacy pair fails closed without changing the authoritative generation.
Implementation Notes
Likely surfaces include graphforge-storage/src/writer.rs, property_overlay.rs, graph_files.rs, mutator/property rewrite helpers, and portable-v2 export/import. The codec belongs in one shared Rust module; do not scatter host-specific allowlists across callers.
Observability
Expose aggregate migrated/encoded route counts and typed collision failures only. Do not log semantic route values or filesystem paths.
Security And Privacy
Retain no-follow, containment, link-count, special-file, and exact-inventory checks. Decoding must be bounded and reject malformed or non-canonical encodings.
Testing
- Codec bijection and adversarial collision unit tests.
- Node/edge write-to-reopen integration tests.
- Legacy migration and malformed encoding tests.
- Portable export/verify/import round trip.
- Hosted Windows durability and ordinary changed-surface gates.
Documentation
Document semantic route ownership and the portable filename boundary in the storage architecture.
Non-Goals
- Relaxing portable inventory validation.
- Treating Windows reserved names as invalid graph labels or relations.
- A benchmark-only or host-specific workaround.
Related Issues
Open Questions
None.
Milestone and critical-path audit (2026-09-04)
Assigned to M5 hardened interchange and attached beneath canonical #735. This is an already documented portability defect, not a reason to reopen completed portable-v2 epics or create a duplicate issue.
The codec/migration and supported-platform round-trip criteria above are the close gate. Complete the repair before accepting final integrated #745/#735 portability certification; lower-scale diagnosis may proceed independently on valid fixtures. No evidence of this defect causing the current S18/S19 RSS failure is claimed.
Release ownership: this correctness repair belongs to M5 and blocks #735/#745. The full M5 completion graph blocks readiness #1096 and M13/#1095 publication; one repair issue serves both product and release acceptance without duplicate direct edges.
Problem
Graph property routes are semantic identifiers, but several storage writers interpolate them directly into filesystem components. Valid routes such as
CON,AUX,COM1, andLPT9can be written on Unix and cannot be represented on Windows; portable graph-file inventory correctly rejects those components only after work has already been written. Other Windows-invalid punctuation is admitted by the same route boundary. The result is host-dependent publication and reopen behavior.Objective
Encode every semantic node-label and edge-relation route into one reversible, collision-resistant, portable filesystem component while preserving the original semantic route through write, capture, publication, reopen, rewrite, export, and import.
Debt / regime
Requirements
Acceptance Criteria
CON,AUX,COM1,LPT9, dotted aliases such asCON.foo, forbidden punctuation, trailing-dot/space names, mixed case, Unicode normalization variants, and literal escape-prefix routes round-trip without collision on every supported host.BDD Completion Scenarios
Portable reserved route
Given node label
CONand edge relationAUXWhen their properties are written and the graph is published and reopened
Then the original semantic routes and property values are returned exactly
And the persisted inventory contains only portable encoded components.
Collision-safe migration
Given an authenticated legacy Unix tree containing raw and escape-prefix-like route names
When it is migrated to portable inventory
Then every distinct semantic route remains distinct
And any ambiguous legacy pair fails closed without changing the authoritative generation.
Implementation Notes
Likely surfaces include
graphforge-storage/src/writer.rs,property_overlay.rs,graph_files.rs, mutator/property rewrite helpers, and portable-v2 export/import. The codec belongs in one shared Rust module; do not scatter host-specific allowlists across callers.Observability
Expose aggregate migrated/encoded route counts and typed collision failures only. Do not log semantic route values or filesystem paths.
Security And Privacy
Retain no-follow, containment, link-count, special-file, and exact-inventory checks. Decoding must be bounded and reject malformed or non-canonical encodings.
Testing
Documentation
Document semantic route ownership and the portable filename boundary in the storage architecture.
Non-Goals
Related Issues
Open Questions
None.
Milestone and critical-path audit (2026-09-04)
Assigned to M5 hardened interchange and attached beneath canonical #735. This is an already documented portability defect, not a reason to reopen completed portable-v2 epics or create a duplicate issue.
The codec/migration and supported-platform round-trip criteria above are the close gate. Complete the repair before accepting final integrated #745/#735 portability certification; lower-scale diagnosis may proceed independently on valid fixtures. No evidence of this defect causing the current S18/S19 RSS failure is claimed.
Release ownership: this correctness repair belongs to M5 and blocks #735/#745. The full M5 completion graph blocks readiness #1096 and M13/#1095 publication; one repair issue serves both product and release acceptance without duplicate direct edges.