Skip to content

ADR-0017: Storage witnesses and explicit schema comparison

Date: 2026-10-11. Status: accepted; local and hosted verification passed.

M5.1 derives a versioned, immutable storage manifest from the finalized EF model and existing GraphBindingCompiler. Canonical UTF-8 JSON and its SHA-256 fingerprint describe nodes, native relationship identity, endpoint roles, stored property types/requiredness, concurrency/generation, deletion behavior and schema intent. CLR names and declaration order are excluded so generated and handwritten mappings can be compared. Opaque conversion code is explicitly caveated: equal fingerprints do not prove arbitrary converter equivalence. Index direction/provider-specific facets unavailable in EF's runtime model are also caveated.

Database.GetGraphSchemaManifest() performs no database operation. Database.InspectGraphSchemaAsync() reads component facts, constraints and indexes from the configured database and returns the manifest, observed facts, capability profile and categorized comparison. It performs no DDL or data scan. An active EF transaction remains caller-owned; otherwise inspection owns a read session/transaction and rolls it back during cleanup. EF's concurrency detector and a scoped operation lease cover the complete multi-query inspection. Driver calls are awaited; cancellation is checked between operations. A metadata row cap fails explicitly rather than returning a truncated success report. Row size/server work are not bounded by that cap, and sequential reads do not establish snapshot isolation.

Capabilities describe documented availability inferred conservatively from observed version/edition and advertised dialects. They do not certify untested server releases or permissions. The default Cypher dialect is never guessed. The optional Graph Type read uses explicit CYPHER 25 only with recognized Enterprise 2026.06-or-later and advertised 25; otherwise it is omitted. Graph Type text is returned as evidence with a warning that its semantics are not parsed. Older servers without the propertyType SHOW column use a query omitting that column. Permission and transport failures propagate.

Comparison separates exact uniqueness from property existence and type enforcement. Required key gaps fail; optional index/hardening gaps and unmanaged objects produce warnings. Known incompatible requirements fail. Proposals contain validated identifiers, deterministic names and CREATE-only Cypher for explicit review. Existing-name/index conflicts are reported without dropping or replacing objects. Pair-edge uniqueness remains application-enforced, and shared relationship types suppress unsafe type-wide proposals. No proposal is an executable migration or a guarantee that existing data will satisfy it.

The Community fixture verifies emitted uniqueness constraints and range indexes plus drift, actual EF CRUD, transaction borrowing and error cleanup. The complete local run passes 378 unit and 111 live tests (98 new unit/five new live), with a clean solution build. Review findings added alternate-key contracts to the witness, recognized incompatible temporal/spatial/UUID types, and aligned runtime constraint names with actual Cypher 5/25 metadata. Enterprise existence/type/Graph Type support remains capability/parser/unit evidence until a separate live profile is tested. Regular runtime key guards continue their existing primary-key/edge-ID scope; schema inspection does not automatically deploy additional EF index or alternate-key intent.

GB-015 implements the separate M5.2 migration plan/history/lease/recovery contract after this witness gate and before M6. Inspection does not claim migration replay, EnsureCreated, dotnet ef migrations, graph-data integrity or full EF conformance.

Hosted run 38107296270 verifies implementation be57fa5: clean build, 378 unit/111 live tests, resource-policy checks and complete fixture cleanup. Local and hosted results agree within the documented Community scope.

Sources checked against current official documentation: constraint columns, Cypher 5 constraint columns, index columns, Graph Type observation, and explicit Cypher version selection.