Skip to content

ADR 0042 — Application-hosted evidence tools

Status: accepted design for the user-authorized next implementation cycle; feature acceptance remains ticket-specific.

V2 public API review: retain diagnostics in Tooling and add the small provider Prepare()/PreparedCypherQuery<T> adapter to bind the original compiler command and materializer to execution. No new EF service, compiler, transport, dependency or package. Prepared handles retain their original context and shallow parameter snapshot; trusted application parameter objects must remain immutable. Tooling's optional typed row projection is execution-only and preserves declared columns/nulls/duplicates. Compile-only registrations remain valid for V0/V1 but cannot become V2 passes.

GraphVerify.SemanticAsync takes a trusted fresh-context factory, required catalog, explicit disposable-fixture acknowledgment and independently written native reads with fixed expectations. It reuses Doctor capture and V1 planning without recompiling, then verifies unique owner and recipe markers before result reads. All result reads use one owned transaction with rollback/disposal even after cancellation. The runner never provisions or repairs markers/schema/data; the harness owns that separate lifecycle. Marker fingerprints describe deterministic fixture recipes, not database content hashes or authentication. Exclusive fixture use is required; read-committed transactions do not establish universal snapshot isolation. Fixed expectations additionally prevent a corrupted fixture or bad native reference from silently validating the Fluent query. Native controls are trusted reviewed code, not a sandbox; no automatic retries. Cleanup failure prevents a pass. A supplied context with an active transaction or tracked entities is rejected and left caller-owned.

V2 exports preserve prerequisite compilation/planning separately from native-to-fixed and Fluent-to-native result evidence, with fingerprint/versions and sanitized differences. Ownership tokens, raw values, parameters and native statements are excluded. Query/reference row budgets and cooperative deadlines do not bound server work or individual value payload sizes. Nine protocol cases currently validate binding, marker ambiguity, wrong reference results, projection failure, row budgets, missing registrations, precancellation, borrowed ownership and failed cleanup; three-case live acceptance remains separate until executed.

The V2 scalar comparer accepts explicit ordered columns and validates nullability/types before comparing ordered sequences or multisets. Distinct policy is a checked expectation, never a repair. Length-prefixed ordinal UTF-16 keys avoid delimiter collisions and JSON replacement of malformed surrogate sequences. Signed 64-bit integer normalization, exact finite float/double comparison, nulls and duplicate counts are explicit; opaque/decimal/non-finite values cannot silently coerce. Row/string/combined working-key budgets fail conservatively. Returned differences contain no raw values. Six focused cases pass, but this helper is not the V2 runner and cannot attest input provenance. The runner must bind the actual executed Fluent command/reader to its evidence and independent native control, with explicit fixture ownership. Avoid claiming that an independently recompiled snapshot is necessarily the command whose rows were observed.

Verify V0/V1 builds on the same capture adapter, retaining short-lived commands outside the serialized report so each trusted factory is invoked once and V1 plans exactly that compiled statement. Every registered contract is required; an empty catalog is not-run and exits nonzero. Model/schema failure skips planning. Unknown required-feature vocabulary and unavailable identified-relationship capability block the contract. EXPLAIN uses existing provider transport, never PROFILE or result execution. Deadlines are cooperative between operations, not hard server timeouts. Plan evidence keeps a bounded operator tree and fingerprints, excludes all arguments/identifiers/timings, strips database suffixes from recognized operator names and redacts unknown names. Shape hashes describe only that redacted tree, not complete plan identity or performance. Planning failure stops subsequent plans with not-run records and no retries. V2 semantic evidence remains a separate gate.

Doctor, Verify and Query Lab reuse the optional GraphBridge.Tooling package. No standalone package, generic application assembly loader, new transport, model compiler or provider service is introduced. The application supplies an already-created context or an explicit context factory and registered compiled queries. Public API changes are reviewed here before implementation; provider dependency direction and package notices remain unchanged.

The first increment is a versioned evidence envelope with immutable snapshots, explicit pass/fail/unsupported/blocked/not-run states and deterministic serialization. Missing observations cannot be success. Query snapshots capture existing CypherCommand output, not a second rendering. Default exports retain only statement/model fingerprints and parameter type/count summaries; actual statement text requires disclosure because mapped identifiers or native literals can be sensitive. Parameter values and exception messages are never retained in this first schema. Existing explicit ToCommand remains the application-owned sensitive inspection path. Arbitrary exception ToString/getters, parameter enumeration and custom value serialization must not run while redacting.

Use fixed diagnostic codes/messages/actions, with operation phase and severity separate from outcome. Unknown connection/permission observations are blocked, not healthy. Report provenance captures actual loaded provider/EF/driver/tooling versions; unobserved server/version/edition remain absent. No timestamp is injected into otherwise deterministic offline evidence. Later connected tools add actual profile observations through the same schema; V2 uses separately provisioned marker-verified fixtures and independent native controls.

The shared envelope is data, not certification. A passing compile observation is not a passing semantic query or database profile. Query Lab escapes all report content and never evaluates registered source text. Typed graph snapshots and opt-in EXPLAIN are later independent gates. Public signatures stay small and capability-specific; no generic plugin framework, cache or query rewrite is introduced.

The shared catalog uses immutable definitions plus trusted application-owned Fluent factories. Its initial query kind is explicitly Fluent Cypher; EF/native factory adapters are not falsely advertised. Three registrations reuse the existing sample methods, with declared output fields, nullable columns, duplicate policy, ordered/multiset comparison, native reference/fixture identifiers, feature requirements and per-query row/deadline/path budgets. These declarations are not observations or enforcement: only the later execution adapters can establish capability and semantic outcomes. Optional results use multiset comparison because the sample orders only by actor name, leaving same-name rows tied. The existing compiler alone produces statement/parameter snapshots.

Offline Doctor is also the shared offline inspection adapter: it derives a redacted storage fingerprint/counts from GetGraphSchemaManifest, compiles each registration, associates failures with the exact contract and preserves not-run records after model failure/cancellation. It leaves context disposal, state and driver ownership with the application. Compilation is synchronous; cancellation is checked between steps and cannot interrupt a delegate. Factories are trusted code and must only construct queries; this API is not a sandbox or arbitrary assembly loader. Default reports may include explicitly declared public contract metadata, never closure parameter values. Model/statement identifiers still require explicit text disclosure. An empty catalog can validate the model only; that does not imply query or database acceptance.

Connected Doctor calls the existing InspectGraphSchemaAsync without introducing another inspector or driver session path. It retains only completed observations: selected public profile ID, numeric server version, recognized edition, numeric advertised dialects, existing inferred schema capabilities and grouped fixed finding codes/categories/counts. Database/schema names, original observation messages, graph-type text and proposed DDL are omitted. Unknown version/edition text is normalized to unrecognized, not retained as potential sensitive content. A missing required schema condition fails; unknown capability, permission/transport failure, cancellation or row overflow cannot pass. Schema warnings have a separate warning severity and remain visible even when required conditions pass. The returned pass concerns selected metadata expectations only: no data scan, query execution, planability or semantic/capability certification. Owned read transaction cleanup and borrowed transaction preservation are delegated unchanged to the provider.

Acceptance for the connected increment: 23 focused reporting/Doctor unit cases pass, including seven new connected protocol cases; three real Community fixture cases pass for state/schema preservation, borrowed rollback ownership, missing constraints, bounded metadata, cancellation, actual authentication denial and unreachable transport. Metadata-grant denial is protocol coverage, not a new live Enterprise grant-profile claim. The actual --doctor-inspect host produces redacted real-profile evidence, exits 1 for missing movie constraints and 2 for missing configuration; offline mode remains independent. Fixture/container/network and generated credentials removed after acceptance.

V2 acceptance (12 October 2026): 246 Tooling units pass, including 12 runner/ownership/cancellation/bounds cases. The earlier prepared-reader increment has 28 focused native passes. All three actual movie factories pass independent native/fixed comparisons on the owned Community fixture. Fluent null coalescing and accidental DISTINCT lose the contracted semantics and fail; a native direction mutant fails fixed expectations before Fluent execution. Recipe mismatch blocks. Native accidental-write control is rolled back and state/schema remain unchanged. Actual sample JSON/text commands and exits 0/1/2 pass; retained reports are under .artifacts/next-roadmap/verify-semantic.*. Scoped graph/schema data and the entire owned container/network/credentials were removed. V1 live and offline gallery host regressions pass. No V3 or immutable-candidate acceptance is inferred.