diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md new file mode 100644 index 0000000000..3dbdb31123 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-finish.md @@ -0,0 +1,45 @@ +# Claude Opus 5 High — Immediate Architecture Report Synthesis + +Resume native Claude Code session `f79af5bb-e953-4aae-9585-a1c83e73a00d` at Opus 5, effort high. +This is the terminal synthesis turn for the independent architecture lane. + +The original and resumed workflow produced extensive specialist evidence. Multiple agents completed +NetScript current-state, doctrine/process, generated-pipeline, documentation-claim, git-history/LOC, +Prisma control/runtime, migration, contract, and adversarial fact-check work; a few children were +lost or killed at process boundaries. The interactive background parent then exited at a bridge +boundary before replacing its report placeholder. + +Do not launch or resume any Agent, Task, Workflow, Team, monitor, or child session. Do not repeat +the broad research. Use the completed specialist results preserved in the current conversation plus +the three committed research documents. Perform only a narrowly targeted read if a claim would +otherwise be unsupported. + +Replace exactly this file: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +with the complete decision-grade independent architecture report required by the original brief. It +must include: + +1. requested/observed provider, model, effort, parent session/handle chain, workflow roles, and + observable specialist identifiers/statuses; +2. verdict and architectural thesis; +3. target package/ownership graph with NetScript doctrine/archetype assignment; +4. target/config/schema-space/migration/runtime identities and invariants; +5. concrete TypeScript public API, definition DSL, contribution DSL, factory/port, and generated + composition-root sketches; +6. plugin contribution/extensibility protocol, ownership/conflict/dependency/version/removal rules; +7. typed plan/apply/result/progress/error command lifecycle, locks, concurrency, recovery, CI, + offline determinism, and agent-facing manifest/surface; +8. Prisma 8 adopt/wrap/reject/defer decisions and a volatility-containment boundary; +9. provider matrix and multi-target/multi-schema/multi-engine behavior without false portability; +10. clean-break migration/cutover and parallel-branch strategy with data safety but no runtime + compatibility shims; +11. conformance, generated-project, journey, negative-path, migration, release, and GA gates; +12. risks, rejected alternatives, unresolved questions, explicit decision checkpoints, and exact + local/primary source references. + +Correct known precision issues: the root catalog entries are `^7.8.0`, generated templates use +`^7.4.2`, and the generated workspace currently emits 30 database tasks. Separate RC-tag facts from +post-RC-main churn. Be comprehensive but write in one bounded synthesis turn. Do not edit any other +file. End only after the report is complete. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md new file mode 100644 index 0000000000..b6c380b8f1 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture-resume.md @@ -0,0 +1,36 @@ +# Claude Opus 5 High — Resume Independent Architecture Synthesis + +Resume session `3f8a9a69-5589-4b91-9a32-91f7770fe7c2` in the same worktree and continue the +already-started independent database architecture deep dive. You have already completed a broad +Claude workflow/subagent fan-out and began the report, but the background parent paused immediately +after creating its placeholder. + +Do not restart the research. Consume the specialist results already present in this session, resolve +their disagreements, and finish the synthesis. You may resume or add focused Claude subagents only +when a specific evidence gap genuinely remains. Stay Claude Opus 5 at high effort. + +Write exactly one substantive artifact: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +Replace the placeholder with the complete decision-grade report required by the original brief. It +must include: + +- requested and observed model/provider/effort/session identity; +- workflow/subagent roles and observable identifiers; +- independent verdict and architectural thesis; +- a complete target package/ownership graph and doctrine/archetype alignment; +- target/config/schema-space/migration/runtime identity semantics; +- concrete TypeScript API and DSL sketches; +- plugin contribution and extensibility protocol; +- control-plane command lifecycle, typed plan/apply/result/progress/error contracts, concurrency, + locking, recovery, and deterministic CI/offline behavior; +- Prisma 8 adopt/wrap/reject/defer decisions and volatility containment; +- provider matrix and multi-engine/multi-schema/multi-target behavior; +- no-backward-compatibility migration/cutover plan with data safety and parallel-branch strategy; +- conformance, generated-project, journey, negative-path, migration, and release gates; +- risks, rejected alternatives, unresolved questions, and explicit decision checkpoints; +- exact primary-source/local-source paths for load-bearing claims. + +Do not author or edit the canonical RFC, plan, worklog, supervisor, drift log, production code, or +any other repository file. When the report is complete, end with a concise completion summary. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md new file mode 100644 index 0000000000..552d7f13c2 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-architecture.md @@ -0,0 +1,122 @@ +# Claude Code Opus 5 High — Independent Database Architecture Deep Dive + +## Role + +Use the NetScript harness. You are a subordinate architecture/research lane in an active RFC run, +not the supervisor and not the formal PLAN-EVAL. Work independently from the Codex framing, +challenge it, and return decision-grade evidence. You may use native Claude Workflows or focused +Claude subagents when they materially improve coverage; if you do, record the workflow/subagent +roles and observable identifiers in your report. + +Requested route: native Claude Code, Opus 5, effort high. + +## Worktree and run + +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Branch: `docs/database-architecture-rfc` +- Run: `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` +- Baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` +- Prisma RC clone: `.llm/tmp/prisma-v8-rc1` +- Prisma RC pin: `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` +- Prisma current-main pin observed by the supervisor: `71e2e0d9ee1f306b5a11435cd1973023cb33866a` + +Read `AGENTS.md` and the complete `.agents/skills/netscript-harness/SKILL.md` first. Follow its +retrieval order for any doctrine/archetype decisions you make. This is a docs-only RFC research +slice describing future Archetype 1/2/4/5/6 surfaces. + +## Owner intent + +This is a clean-break architectural redesign of NetScript's database story around Prisma 8 / Prisma +Next. It is not a 1:1 Prisma migration. Backward compatibility must not constrain the design. Data +migration safety and a mechanical migration path are required, but runtime compatibility facades, +old generated clients, aliases, and hand-maintained shims are forbidden. + +The architecture must eliminate manual schema/type generation, generated-source patching, manual +adapter assembly, Prisma-related CI instability, and copied plugin fragments while supporting +multiple schemas, multiple databases (including two targets of the same provider), provider/runtime +capability differences, plugin contributions, deterministic tooling, and an excellent human/CI/ +agent experience. + +## Required reading + +Read these completely before forming conclusions: + +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md` +- `rfcs/PROCESS.md` and the RFC template it points to +- relevant source paths cited by the current-state audit +- Prisma RC source/scorecard/ADRs/control/runtime/skills in the local clone + +Do not accept the existing research's proposed conclusions merely because they are written. Verify +load-bearing claims against source and flag any error, overreach, or missed alternative. + +## Independent questions + +1. What is the smallest durable NetScript database kernel, and what must remain Prisma-specific? +2. Is a `DatabaseGraph` actually the right central abstraction? If so, define its identities, + invariants, compilation phases, and failure behavior. If not, propose a superior abstraction. +3. What are the exact package boundaries and dependency directions? Assign the smallest fitting + NetScript archetype to each. +4. Design implementation-grade TypeScript APIs for: + - application target definition and selection; + - runtime acquisition/scoping; + - schema/contract-space contributions; + - provider/driver/runtime adapters and capability negotiation; + - migration plan/apply/verify operations; + - validation artifact providers; + - testkit/conformance certification; and + - generated agent manifest/command context. +5. How should same-provider multi-target, same-database multi-schema, cross-space relations, + replicas, serverless/request scope, and externally managed schemas differ in the type/domain + model? +6. How should plugin upgrade, dependency ordering, collision, version skew, uninstall, retained + data, and external drift behave? +7. Where can the design accidentally create a proprietary second ORM, an over-broad generic + repository, a service locator, or a lowest-common-denominator portability layer? +8. Which Prisma 8 ideas should NetScript adopt, wrap, replace, or reject? Which exact upstream seams + are mature enough to integrate, and what must be gated? +9. Design the zero-manual-step development loop and the deterministic CI/deployment protocol, + including atomic artifacts, stale-output detection, plan approval, cross-target partial failure, + resume, receipts, locks, and offline/Aspire classification. +10. Design the clean-break migration and temporary parallel-branch strategy without reintroducing + compatibility into the product architecture. +11. Produce a failure-mode analysis and an implementation/conformance test matrix that would catch + the incidents in the NetScript audit and the open Prisma 8 issues/PRs. +12. Identify any decision that the RFC must leave conditional on Prisma 8 final rather than + pretending the RC has settled it. + +## Output contract + +Write exactly one file: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +Do not edit any other file. Do not commit, push, comment on GitHub, change labels, or author the +canonical RFC. + +The report must contain: + +- requested and observed model/effort/session identity; +- whether workflows/subagents were used and their roles/identifiers; +- independent executive verdict; +- corrected or missing research findings with evidence; +- explicit architecture decision table with alternatives and rejection reasons; +- package/dependency graph; +- concrete API/DSL sketches (not merely nouns); +- graph compilation/runtime/control lifecycle; +- plugin contribution and removal protocol; +- capability/ownership/error models; +- multi-target transaction/failure semantics; +- dev/CI/agent experience; +- clean-break migration/parallel-branch strategy; +- threat/failure-mode analysis; +- implementation waves and per-wave proof gates; +- unresolved decisions and upstream maturity gates; +- severity-tagged adversarial findings against the current research/plan; and +- a primary-source register. + +Distinguish observed fact, inference, and proposal. Prefer source and tests over stale prose. The +result should be suitable for direct use by the supervisor when locking the Plan-Gate. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md new file mode 100644 index 0000000000..0ff433d849 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-1.md @@ -0,0 +1,38 @@ +# Claude Opus 5 High — Architecture Report Part 1 of 3 + +Resume the existing Opus architecture session. Do not reason from scratch, run commands, read more +files, or invoke any agent/task/workflow. You already completed the evidence work and attempted one +oversized final write that the transport interrupted before the tool envelope persisted. + +Use exactly one `Write` call to replace: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md` + +Write a polished, self-contained first third (roughly 3,500–5,000 words; bounded enough to complete +within this turn) containing: + +1. title, run/route identity, requested and observed Opus 5 high evidence, parent handle/session + chain, and a table of workflow/subagent roles/identifiers/statuses with truthful + incomplete/killed disclosures; +2. independent verdict, architectural thesis, non-negotiable invariants, and what the redesign is + explicitly not; +3. target package/ownership/dependency graph with one doctrine archetype per future package; +4. complete identity model: target, connection/provisioning profile, namespace/schema, contribution + space, contract snapshot, migration lineage/head, runtime session, operation plan and receipt; +5. concrete TypeScript public API sketches for the manifest/definition DSL, typed target refs, + composition factory, session/runtime access, generated app composition root, and contract-derived + Standard Schema input/output validation. + +Resolve rather than obscure the minimal-kernel tension: explain which data/protocol concepts are +durable NetScript public contracts and which graph/factory/port machinery remains internal or +consumer-owned. The owner-provided Prisma-maintainer exchange establishes a particularly important +design hypothesis: the contract has enough runtime data to derive validation without another +generation step. Treat this as primary exploratory evidence, not an upstream commitment. Make the +default runtime-derived and contract-identity-cached; any AOT form is only an equivalent optional +optimization. Do not make unsupported exact-count claims. + +End the file with exactly: + +`` + +Do not edit any other file. After the single Write succeeds, end the turn immediately. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md new file mode 100644 index 0000000000..d2d9ab0b4c --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-2.md @@ -0,0 +1,42 @@ +# Claude Opus 5 High — Architecture Report Part 2 of 3 + +Resume the same Opus architecture session. Do not run commands, read more files, or invoke any +agent/task/workflow. Part 1 already exists and ends with ``. + +Use exactly one `Edit` call replacing that marker with a polished second third (roughly 3,500–5,000 +words) containing: + +6. contribution/plugin DSL and protocol: provenance, dependency ordering, capabilities, + ownership/conflict/augmentation, version skew, install/upgrade/removal/retention, migrations, + uninstall safety, conformance kit, upstream extension coexistence; +7. control-plane operation lifecycle and concrete types for classify/compose/plan/apply/verify/ + status/emit, consent, dotted errors, progress, receipts, locks, concurrency, expiry, resume, + partial multi-target success, artifact postconditions, offline determinism, CI cacheability, and + generated agent surface; +8. Prisma 8 adopt/wrap/reject/defer table and volatility-containment boundary; +9. provider/engine/runtime matrix, Postgres-first implementation, multi-target/multi-schema + semantics, external/unmanaged schemas, Deno/serverless constraints, and non-Postgres contingency; +10. a first-class pure-TypeScript schema-authoring and end-to-end type-system subsystem based on + Prisma Next's architecture direction: exact upstream capability versus NetScript ownership; + schema-as-code composition/imports/namespaces; models, relations, constraints, indexes, native + types and defaults; plugin-owned augmentation and conflict policy; multi-schema/multi-target + boundaries; static inference versus stable runtime contract identity; deterministic migration + coupling; and propagation from schema to typed operations, validation, routes/RPC/forms/SSR, + generated projects, tooling and agents. Include concrete public API sketches and explicitly + assess whether NetScript should expose, wrap, or translate Prisma's TypeScript schema surface. +11. a deep runtime-validation subsystem based on the owner/Prisma-maintainer exchange: Standard + Schema boundary; mutation/query input validation; selection/projection-aware output validation + at API/SSR/external-service trust boundaries; runtime versus wire representations; codecs; + plugin spaces; cache identity/invalidation; structured failures; Fresh/forms/RPC integration; + and semantic equivalence for any optional atomic AOT projection. Explicitly reject + mirror-validator codegen as the default. + +Correct known precision points: `^7.8.0` root ranges, 30 generated DB tasks, TypeScript 5.9 optional +peer, 138 top-level `orm-postgres` export keys, and no fragile skill-count totals. Clearly separate +RC tag from post-RC main. + +End the inserted text with exactly: + +`` + +Do not edit any other file. After the single Edit succeeds, end the turn immediately. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md new file mode 100644 index 0000000000..055e3aa4de --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-report-part-3.md @@ -0,0 +1,25 @@ +# Claude Opus 5 High — Architecture Report Part 3 of 3 + +Resume the same Opus architecture session. Do not run commands, read more files, or invoke any +agent/task/workflow. Parts 1–2 already exist and end with ``. + +Use exactly one `Edit` call replacing that marker with the final polished third (roughly 3,500–5,000 +words) containing: + +12. clean-break migration/cutover strategy with no runtime compatibility, data preflight/safety, + mechanical migration tool/docs, rollback boundaries, parallel branch policy, and feature-parity + accounting. Before leaving the API architecture, add an explicit transfer analysis from + NetScript's existing oRPC extension/factory/composition pattern to Prisma's native + `defineContract` TypeScript schema builder: what should be reused to preserve native inference, + what must not become a wrapper/re-export, and what database-only ownership/migration/lifecycle + rules are additionally required; +13. implementation waves with package-by-package dependencies and acceptance gates; +14. exhaustive conformance matrix spanning type/plan/artifact/result/lifecycle, generated-project, + journey, negative paths, real PostgreSQL, multi-target, plugin lifecycle, migration failure, + deterministic/atomic emission, Deno/import purity, CI and publish/release gates; +15. failure-mode/risk ledger, rejected alternatives, unresolved/conditional decisions, kill/switch + criteria, explicit decision checkpoints for plan lock, and implementation blockers; +16. exact local/primary source register and a concise final recommendation. + +Finish cleanly with no continuation marker. Do not edit any other file. After the single Edit +succeeds, end the turn immediately. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md new file mode 100644 index 0000000000..1b15180f3f --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-author.md @@ -0,0 +1,631 @@ +# Lead-author briefing — canonical NetScript database architecture RFC + +You are the single lead author for NetScript's canonical database architecture RFC. Work in: + +`/home/codex/repos/netscript-db-rfc` + +Use native Claude Code Opus 5 with high effort. You own the RFC's structure, technical coherence, +prose, API design, and final internal consistency. Do not delegate RFC sections or merge +independently authored prose. You may use read-only search and analysis workflows, but the canonical +document must have one architectural voice. + +PLAN-EVAL cycle 2 passed. It is the final Plan-Gate cycle. The owner has ended pre-writing loops: do +not start, request, or simulate another PLAN-EVAL. Begin canonical RFC authorship now. Architecture +diversity happens against the completed draft, not before it. + +## Mission + +Write: + +`rfcs/0000-database-architecture.md` + +This is not a narrow Prisma 7→8 migration note. It is a clean-slate replacement for NetScript's +inherited database foundation, using Prisma Next where it is mature while introducing a genuine +NetScript database layer. + +The RFC must make the intended developer experience concrete: + +- Pure TypeScript, native Prisma contract authoring. +- A thin, inference-preserving NetScript layer analogous in spirit to NetScript's oRPC extension + approach. +- No hand-maintained schema mirrors, copied plugin fragments, repair scripts, provider-specific + workspace forests, manually synchronized validators, or CLI-only orchestration. +- Explicit multi-target, contract-space, ownership, migration, runtime, validation, plugin, and + operational semantics. +- A provider-neutral kernel with one first certified adapter: Prisma 8 PostgreSQL. +- A clean break with no compatibility API, Prisma 7 fallback, dual runtime, legacy adapter facade, + or in-application mixed stack. +- Mechanical adoption and data continuity without backwards compatibility. + +The RFC must be implementation-grade: an implementer should be able to derive package work, public +types, state transitions, test matrices, refusal behavior, and release gates without inventing +architecture. + +## Editing scope + +Edit only: + +- `rfcs/0000-database-architecture.md` + +The root owns all run bookkeeping. Do not edit `plan.md`, `research.md`, `worklog.md`, +`context-pack.md`, `drift.md`, `supervisor.md`, anything under `research/` or `briefs/`, +`plan-eval.md`, independent model reports, production packages, doctrine, or existing RFCs. Do not +commit or push. + +## Required source order + +Read these completely before drafting: + +1. `AGENTS.md`, `SCOPE-docs.md`, `rfcs/README.md`, and `rfcs/0000-template.md`. +2. Run-root `research.md`, `plan.md`, `worklog.md`, `context-pack.md`, `drift.md`, `supervisor.md`, + and the now-`PASS` cycle-2 `plan-eval.md`. +3. `research/architecture-plan-synthesis.md` as the reconciled decision source. +4. The two priority source audits, in full: + - `research/typescript-schema-orpc-audit.md` + - `research/runtime-validation-source-audit.md` +5. Every remaining supporting report: + - `research/netscript-current-state.md` + - `research/prisma-8-deep-dive.md` + - `research/runtime-validation-maintainer-exchange.md` + - `research/market-analysis.md` + - `research/market-gap-audit.md` + - `research/planned-jsr-audit.md` + - `research/qwen-prisma-risk-review.md` + - `research/claude-opus-architecture-review.md` + +Treat run-root `research.md` as the correction ledger. Independent model reports are adversarial +evidence, not factual authority. In particular: + +- The generated engine workspace has 42 `db:*` keys per workspace at the evaluated baseline, not 30. +- `@prisma/orm-postgres` has 138 audited top-level export keys, not approximately 275. +- The current-state report's “more than twenty” task statement was accurate. +- The live `DatabaseGraph` recommendation was rejected in favor of a durable plain + `DatabaseManifest`. +- Broad contract-derived validation claims were narrowed by the pinned source audit. +- Provider re-export proposals were rejected. +- Plugin contract spaces do not independently solve removal semantics. + +The TypeScript/validation acceptance sentence must appear explicitly in the RFC, in equivalent or +stronger language: + +> Accept the native integration only if it preserves Prisma's exact contract inference without +> private imports, copied overloads, casts, or declaration widening, and accept contract-derived +> validation only where the canonical contract plus contributed codec, operation, and selection +> metadata can produce sound fail-closed Standard Schema validators; otherwise narrow or kill the +> affected layer rather than pretending parity. + +## Evidence discipline + +Keep these evidence classes visibly distinct: + +- Current NetScript source fact. +- Prisma RC1 source fact. +- Post-RC Prisma source fact. +- Official primary-source fact. +- Owner/maintainer exchange as exploratory direction, not an upstream commitment. +- Architectural inference. +- NetScript proposal. +- Conditional or unproven implementation capability. + +Pin Prisma RC1 claims to `v8.0.0-rc.1@a76a6c5`. Label post-RC observations against the audited +post-RC object `71e2e0d9ee1f306b5a11435cd1973023cb33866a`. Never present post-RC code as RC1 +behavior or RC1 behavior as a GA guarantee. + +Source-link every material external, upstream, market, maturity, release, issue, and PR claim to +primary sources. Local research reports are a claim index, not substitutes for upstream citations. +Explicitly label unknowns and implementation-time decisions. Do not turn an attractive inference +into a supported capability. + +## Template and front matter + +Follow `rfcs/0000-template.md` completely. Preserve every required top-level section: + +- Summary +- Motivation +- Guide-level explanation +- Reference-level explanation +- Drawbacks +- Rationale and alternatives +- Breaking changes and migration +- Prior art +- Unresolved questions +- Future possibilities + +Use valid draft front matter consistent with repository conventions: + +- `rfc: 0000` +- `status: Draft` +- `authors: ['@rickylabs']` +- `created: 2026-08-13` +- A precise architecture title +- Issue #313 as historical/tracking context if consistent with `rfcs/README.md` +- `Backlog / Triage` if no milestone is yet committed + +Do not omit template sections because equivalent material appears elsewhere. Add structured +subsections and appendices under them. + +## Eight-slice trace + +Map the complete RFC to all eight planned slices: + +- Slices 0–2: provenance, research, plan lock, and the passing final Plan-Gate; summarize, do not + rewrite. +- Slice 3: vocabulary, package graph, public APIs, TypeScript/E2E types, validation, operations, + spaces, targets, state machines, and refusal boundaries. +- Slice 4: adoption, clean cutover, data safety, waves, conformance, CI/JSR/release gates, market + implications, risk register, and kill/switch criteria. +- Slice 5: leave an explicit review/disposition surface for Qwen 3.8 Max and Grok 4.6 high. +- Slice 6: implementation-grade completeness review may occur later inside the fixed post-draft + review sequence, but it is not another PLAN-EVAL and must not restart planning. +- Slice 7: reserve the one final substantive refinement for Fable 5 high. + +Include a decision-trace appendix mapping every D-01–D-47 decision to its definitive RFC section. +Nothing may be silently dropped or weakened. + +Group the decisions coherently: + +- D-01–D-05: clean break, data continuity, artifact separation, no query/repository abstraction. +- D-06–D-08 and D-36: native TypeScript contract authoring, Candidate A, inference preservation, + app-local binding. +- D-09–D-16: exact packages, provider boundary, target identity, explicit selection, replicas, + static capabilities. +- D-17–D-20 and D-38–D-40: contract spaces, ownership, extension bundles, pinned artifacts, plugin + lifecycle. +- D-21–D-25: bounded Standard Schema interpretation. +- D-26–D-33: pure operations, catalog projections, preview/plan separation, control ownership, + saga/receipts, artifact generation, agent surface. +- D-34–D-35: no legacy provider parity and signed production plans. +- D-37: namespace capability withheld pending sound type/runtime parity. +- D-41–D-42: W3/provider implementation-time pin, import, and lock choices. +- D-43–D-47: explicitly deferred optional capabilities. + +## Central design narrative + +The RFC should tell one continuous story: + +```text +native authored TypeScript contracts + NetScript definitions/contributions + → pure two-phase composition + → canonical ContractArtifacts + → deterministic DatabaseManifest + → generated app-local AppBinding + → runtime sessions + bounded validators + → inspected baseline + → bound ExecutablePlan + → provider apply/ledger + → immutable OperationReceipts + → verify/recovery +``` + +Do not conflate source definition, resolved manifest, speculative preview, executable plan, provider +ledger, or receipt. + +## Native Prisma TypeScript authoring and NetScript extension layer + +This is a primary RFC axis, not a small implementation detail. + +Use the current model-first native Prisma form: + +```ts +defineContract(scaffold, (helpers) => ({ + models: {/* native Prisma definitions */}, + types: {/* native Prisma definitions */}, + enums: {/* native Prisma definitions */}, +})); +``` + +The owner's screenshot showed a real historical target/table/column fluent API, but Prisma removed +it. Do not recreate it. Do not invent a NetScript schema DSL. Do not vendor or re-export Prisma as +though NetScript owns it. + +Candidate A is mandatory as the baseline: + +```ts +const contract = defineContract(scaffold, (p) => /* native value */); + +export default defineDatabase({ + targets: { main: /* explicit target */ }, + spaces: { + app: defineDatabaseSpace({ + ownership: "app", + contract, + // owner/version/dependencies/policy + }), + }, +}); +``` + +Define exact public signatures and inference behavior for: + +- `defineDatabase` +- `defineDatabaseTarget` +- `defineDatabaseSpace` +- `defineDatabaseExtension` +- App-owned native fragments +- Plugin-owned full spaces +- Two-phase extension collection +- Const-preserving generated composition roots +- `DatabaseDefinition` +- `NativeContract` +- `SpaceContribution` +- `DatabaseExtension` +- `AppBinding` +- `TargetRef` +- `TargetSession` + +Show the oRPC precedent precisely: preserve the native upstream authoring and inferred value, then +add NetScript policy, lifecycle, ownership, artifact, and orchestration around it. Do not transfer +oRPC-specific slow-type exceptions, global builder ownership, transport concepts, or re-export +patterns. + +An optional factory survives only if it forwards exact public Prisma helpers without copied +overloads, private imports, declaration widening, or cast workarounds. State the kill criterion +directly. + +Show end-to-end type propagation from native contract to generated application-local binding, +query/session use, Standard Schema consumers, route/procedure/form boundaries, and serialization. +Published kernel packages must remain declaration-safe and provider-neutral; application-specific +inferred Prisma types remain app-local. + +## Runtime Standard Schema interpretation + +This is the other primary axis. + +Define the public API and internal boundary for runtime contract-derived Standard Schema values. +Include examples for: + +- Whole-model runtime values. +- JSON/serialized model values. +- Mutation inputs only when exact operation metadata is explicitly contributed. +- Selection/results only when aliases, codecs, nullability, and representation are fully known. +- Two independent Standard Schema consumers. + +The only public representations are: + +- `runtime` +- `json` + +Driver-wire representation remains adapter-internal. + +Specify the supported `ValidationIR` algebra: registered scalar codecs, nullability, lists, +dictionaries, value objects, resolvable unions, enums/value sets/native enums, integrity-checked +cross-space relations, whole-model presence policy, and fully known direct-column projections. + +Specify construction-time `DB_VALIDATION_UNSUPPORTED` refusal for missing or ambiguous codecs, +packs, variants, cross-space metadata, Prisma operation grammar, raw/computed/subquery/aggregate/ +include results, opaque checks, database-state constraints, incompatible async predicates, and +unknown result shapes. + +Invalid values return Standard Schema issues; unsupported schemas fail during schema construction. +Custom codecs must contribute representation-specific value schemas—encode/decode functions are not +validation. + +Define cache identity using the full canonical contract digest, schema version, space, +target/family, operation or normalized selection, representation, interpreter ABI, codec/pack +identity and version, and execution identity where defaults matter. + +Do not claim full Prisma create/update/filter/nested-write/result parity from the contract. AOT is +optional and may ship only with corpus equivalence to runtime interpretation. + +## Exact package and ownership graph + +Specify the exact graph and one archetype per unit: + +- `@netscript/database-contract` — A1 +- `@netscript/database` — A4 +- `@netscript/database-runtime` — A3 +- `@netscript/database-control` — A2 +- `@netscript/database-prisma-postgres` — A2 +- `@netscript/database-testkit` — A6, conditional on a justified binary +- Existing `@netscript/plugin` — A4 +- First-party plugins — A5 +- Existing Aspire integration — A2 +- Existing CLI — A6 + +For every package, document: + +- Owned responsibilities. +- Forbidden responsibilities. +- Dependencies and import law. +- Public versus adapter-local types. +- Runtime permissions. +- JSR/publication status. +- Archetype gates. +- Kill or split criteria. + +No framework package re-exports Prisma. Only the PostgreSQL adapter owns Prisma runtime/control +imports. Controlled app/plugin build inputs may directly import Prisma's public authoring builder. +Production apply and runtime consume canonical verified artifacts, not arbitrary schema TypeScript. + +## Public contracts and artifacts + +Provide complete TypeScript examples and field-level contract tables for: + +- Stable IDs: target, role, namespace, space, object, contract snapshot, manifest, plan, run, + receipt. +- `DatabaseDefinition` +- `NativeContract` +- `SpaceContribution` +- `ContractArtifact` +- `DatabaseManifest` +- `AppBinding` +- `TargetRef` and `TargetSession` +- `SpeculativePreview` +- `ExecutablePlan` +- `ProviderMarker` +- `ProviderLedger` +- `OperationReceipt` +- `OperationCatalog` +- Public diagnostics and results +- Internal-only `ValidationIR` + +For every durable artifact, state producer, consumer, authority, version, identity, digest inputs, +canonical encoding, persistence, atomicity, provenance, redaction, and stale/mismatch behavior. + +Define the ports with cohesive three/four-method shapes: + +- `ContractArtifactSource` and atomic publisher +- `ProviderRuntimeFactory` +- `ProviderControl` +- `ConnectionSource` +- `MigrationLock` +- `ReceiptSink` +- Clock/ID/signature policy where justified + +Provider registries are immutable composition-root data, not global registries. + +## Formal behavior + +Include formal state-transition tables or Mermaid diagrams for: + +- Pure definition composition and manifest resolution. +- Runtime process/request session lifecycle. +- Inspection, preview, plan, policy, approval/signature, readiness, expiry/staleness/revocation. +- Lock, revalidation, apply, checkpoint, verification, cancellation, and recovery. +- `outcome_unknown` inspect-before-resume. +- Dependency-ordered multi-target saga and partial success. +- Plugin install, upgrade, version skew refusal, detach, retain, conditional archive/drop. +- Extension-bundle identity/version verification. + +Define legal transitions, forbidden transitions, persistent evidence, retry/idempotency rules, +cancellation semantics, and structured diagnostics. Preview must never be applicable. Cross-target +atomicity must never be implied. + +## Targets, providers, spaces, ownership + +Cover: + +- Multiple PostgreSQL targets of the same provider. +- Explicit target selection and dependency closure. +- Roles and writer/read replicas; replicas never migrate. +- Namespaces as a kernel identity axis, while Prisma multi-namespace certification remains withheld + until no-cast type/runtime parity passes. +- App space plus independently versioned plugin spaces. +- `managed`, `adopted`, `external`, and `ignored` ownership. +- One managed owner per `ObjectKey`. +- Owner-granted augmentation only. +- Pinned mirrors that allow apply/verify without installed plugin code. +- Detach-and-retain as the only guaranteed v1 removal. +- Explicit unsupported/refusal behavior for Prisma SQLite, MongoDB, MySQL, SQL Server, cross-target + relations, and cross-target transactions. + +Do not turn the provider-neutral kernel into false portable query semantics. Native provider query +surfaces remain app-local. + +## Programmatic control, CLI, agents, and CI + +Define a typed `OperationCatalog` as the source for classify/compose/emit/preview/plan/apply/verify/ +inspect/resume operations. CLI commands, help, documentation, and agent instructions are generated +projections. + +Show programmatic and CLI journeys with machine results, human rendering, diagnostics, exit +semantics, and next actions. Every example should be executable or explicitly pseudocode pending a +W3 import pin. + +Separate: + +- `pure` +- `live-read` +- `mutating` +- `resident` + +Pure operations must not resolve connections, Aspire, Docker, secrets, or network access. + +Explain how the architecture shortens and stabilizes CI through pure compilation, canonical digests, +atomic artifacts, bounded real-service stages, reusable structured receipts, and removal of +hand-patching/repair workflows. Do not promise unmeasured CI reductions; define measurements and +release thresholds. + +## Migration, clean break, and data safety + +No backwards compatibility is allowed. + +`netscript db adopt` is a temporary migration codemod/tool, not a compatibility layer. Specify the +complete adoption protocol: + +1. Read legacy config/layout. +2. Generate explicit target identities. +3. Introspect reachable databases. +4. Propose object ownership. +5. Hard-stop on unattributed or conflicting objects. +6. Compile and atomically emit canonical artifacts. +7. Establish one baseline/root per space. +8. Write provider marker metadata only, with zero table/data DDL/DML. +9. Verify live state and zero drift. +10. Delete legacy engine workspaces, the 42 per-workspace generated `db:*` task keys, copied plugin + fragments, repair scripts, adapters, and dependencies only after verified adoption. + +Separate-branch/release-line coexistence is allowed during development, but a single application may +never compose old and new stacks. Before the first new apply, rollback is repository-only plus safe +marker cleanup. After apply, recovery is forward through lineage, provider ledger, and receipts. + +Include rehearsal, backup, ownership, destructive-consent, partial-outcome, crash, marker, secret, +lock, and release-window safety gates. + +## Market and rationale + +Use the market reports to compare NetScript against: + +- Wasp +- RedwoodJS +- Payload +- Better Auth +- AdonisJS Lucid +- Drizzle/Drizzle Kit +- MikroORM +- Kysely +- Flyway +- Liquibase +- Terraform +- Pulumi +- Atlas +- Bytebase +- ZenStack v3 +- Django +- Rails Active Record + +Do not produce a feature-list dump. Derive the architectural lessons: + +- One resolved manifest. +- Contributor-owned migration spaces. +- Native authoring with framework policy around it. +- Apply-bound plans. +- Managed versus external ownership. +- Capability-specific behavior instead of false portability. +- Programmatic core with CLI/agent projections. +- Separate source, manifest, plan, ledger, and receipt. + +State clearly what a local meta-framework must not rebuild: hosted RBAC, organization/fleet +management, remote registry, policy SaaS, approval service, or continuous-drift control plane. + +Explain alternatives rejected: Prisma 7 compatibility, one-to-one migration, a proprietary schema +DSL, recreating the deleted fluent builder, live graph/service locator, global mutable provider +registry, provider re-export, portable query client, generated validator parity claims, plugin +fragment copying, CLI as business logic, and hosted-control-plane creep. + +## Implementation and release plan + +Carry W0–W11 into the RFC with dependencies and exit evidence: + +- W0 RFC/doctrine preparation +- W1 contract kernel +- W2 pure definition/compiler +- W3 experimental Prisma PostgreSQL spike +- W4 A3 runtime +- W5 A2 control +- W6 conformance testkit +- W7 plugin seam +- W8 CLI/agent/adoption +- W9 first-party spaces +- W10 clean cutover +- W11 second provider only with real demand and maturity + +Include the exhaustive conformance matrix: + +- Archetype F-1…F-19 requirements. +- A3 lifecycle/leak/cancellation/scope gates. +- Real PostgreSQL, Deno, provider import allowlist, and exact single Prisma component set. +- Literal-type preservation and no-cast/private-import checks. +- Namespace type/runtime parity. +- Standard Schema runtime/JSON corpus and two consumers. +- Extension facet identity. +- Target/space/namespace isolation. +- Failure injection, lock, crash, unknown-outcome, and resume. +- Ownership/removal. +- Deterministic/atomic artifact production. +- Generated example/catalog freshness. +- Generated-project and `scaffold.runtime` journeys. +- Windows/Linux and release-class adoption rehearsal. + +Reflect the prospective JSR result honestly: `PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`. The +packages do not exist, so dry-run, doc lint, packed install, canary, and remote consumer results are +currently N/A. + +Specify implementation-time: + +- Explicit export maps and include lists. +- Stable JSDoc/module docs/examples. +- Isolated declarations. +- No slow-types waiver. +- `deno doc --lint`. +- `deno publish --dry-run`. +- Publish-list inspection. +- Packed clean consumer. +- `quality:scan` and `arch:check`. +- Generated asset freshness. +- OIDC/SLSA canary and exact-version remote E2E at W10. + +## Risks, kill criteria, and unknowns + +Carry the complete risk register and mitigation/kill response into the RFC. Explicitly distinguish: + +- Locked semantics. +- W1/W3/W4/W5/W7/W10 implementation decisions. +- Conditional upstream blockers. +- Safe deferred capabilities. + +No must-resolve-now architecture question may be reintroduced casually. If source inspection reveals +a genuine contradiction, report it to the root, narrow the capability, and continue unless it +invalidates the package boundary. + +Never silently widen support. In particular, do not claim: + +- Prisma 8 GA stability from RC1. +- Non-PostgreSQL certification. +- Multi-namespace soundness. +- Full operation/result validation from contract data. +- Archive/drop safety. +- Cross-database relations or transactions. +- Runtime capability negotiation. +- AOT validation. +- Hosted control-plane behavior. +- Actual JSR publish readiness. + +Include decisive subsystem and provider kill/switch criteria. Preserve the provider-neutral kernel +if the Prisma adapter fails; narrow validation rather than recreating Prisma's type system; withhold +unsupported capabilities instead of casting around them. + +## Expected depth + +This must be a substantial architectural RFC, not a polished summary of the plan. Expect roughly +18,000–30,000 coherent words, or comparable implementation-grade depth. Word count is not a quota: +prefer one consistent model, precise tables, complete examples, explicit invariants, and +traceability over repetition. It should be materially deeper than a typical 5–10 page proposal while +remaining readable from guide-level DX through reference-level mechanics. + +Avoid copying the synthesis section-by-section. Re-author it as one narrative, eliminate +duplication, and use appendices for decision/source/conformance trace tables. + +## Fixed post-draft process + +After the complete draft, the sequence is exactly: + +1. Root performs a personal substantive source/doctrine/API review. +2. Qwen 3.8 Max performs the focused review across TypeScript inference, Standard Schema, + control/recovery, migration safety, package/JSR surfaces, and market claims. +3. Grok 4.6 high performs the whole-RFC adversarial review. +4. The author/editor explicitly dispositions findings and revises the RFC. +5. One Fable 5 high session performs the absolute final substantive review and refinement. + +There is no generic additional focused-review party and there are no more PLAN-EVAL loops. Nothing +substantive follows the final Fable 5 high refinement; only mechanical checks and publication +actions may follow. + +## Final checks for this authoring session + +Before handing back the draft: + +- Verify every template heading and valid front matter. +- Produce a D-01–D-47 section trace. +- Produce a requirement/source/claim trace for load-bearing facts. +- Search for contradictions between RC1, post-RC, and proposals. +- Search for accidental compatibility, Prisma 7 fallback, provider re-export, full-validation, + namespace, non-PostgreSQL, or hosted-control-plane overclaims. +- Check local links and referenced paths. +- Check for placeholders, invented import paths, unsupported capability claims, and stale + 30-task/~275-export claims. +- Run `deno fmt --check rfcs/0000-database-architecture.md`. +- Run `git diff --check`. +- Report the RFC size/line count, coverage, explicit unknowns, and check results. + +Do not commit or push. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md new file mode 100644 index 0000000000..ad23acb4ea --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-consolidate.md @@ -0,0 +1,161 @@ +# Claude Code Opus 5 high brief: consolidate the database architecture RFC + +use harness + +## SKILL + +Read and follow: + +1. `AGENTS.md` +2. `.agents/skills/netscript-harness/SKILL.md` +3. `.agents/skills/netscript-doctrine/SKILL.md` +4. `.llm/harness/workflow/activation.md` +5. `.llm/harness/workflow/run-loop.md` +6. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md` + +This is an RFC editor lane, not a new architecture-planning lane. PLAN-EVAL cycle 2 already passed. + +## Objective + +Rewrite the evidence-complete raw draft into a concise, decision-grade RFC. The owner will not read +an 18,000-word document, and the current draft is 28,194 words. Target **8,000–10,000 words** with a +hard ceiling of **12,000 words**. + +The RFC must focus on the end-state API surface, developer experience, end-to-end type safety, +contract-first architecture, plugin contribution model, bounded Standard Schema validation, and safe +operational control. Link the research rather than duplicating it. + +## Edit authority + +Edit exactly one file: + +- `rfcs/0000-database-architecture.md` + +Do not edit run artifacts, research, plans, worklogs, doctrine, source code, or any other file. Do +not commit or push. The root supervisor owns review, sign-off, commit, and publication. + +## Required reading + +Read completely before editing: + +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +- `rfcs/0000-database-architecture.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` + +Use the root review as the editing contract. Its ten technical corrections are blocking. + +## Reader promise + +The consolidated RFC should let a contributor understand, in one pass: + +- native Prisma TypeScript schema authoring without a cloned NetScript ORM DSL; +- the thin NetScript definition around native contracts; +- deterministic composition into a manifest and generated app-local inferred binding; +- native provider query types reaching application-owned ports without Prisma leaking through the + provider-neutral kernel; +- `StandardSchemaV1` input/output schemas derived from contract and operation/selection metadata, + with explicit fail-closed limits; +- plugin-owned spaces, controlled augmentation, and one extension registration fanning into + authoring/control/runtime/validation facets; +- explicit targets, ownership, artifacts, plan/apply/receipt/recovery, and safe multi-target saga + semantics; +- a clean break from the old stack plus a production-data-safe adoption path. + +## Editorial constraints + +- Preserve the repository RFC template headings: Summary, Motivation, Guide-level explanation, + Reference-level explanation, Drawbacks, Rationale and alternatives, Breaking changes and + migration, Prior art, Unresolved questions, and Future possibilities. +- Shorten the title. +- Lead with the outcome and end-state developer journey. Do not lead with harness process, + provenance, or evidence categories. +- Delete Appendices A–G. Link the approved plan and focused research artifacts instead. +- Remove inline evidence tokens such as `[PROPOSAL]`, `[RC1]`, `[NS-SRC]`, and `[INFERENCE]`. Retain + direct links near the small number of important upstream claims. +- Prefer one strong example over several variations. Every example must use one consistent proposed + import and naming surface. +- Keep only the interfaces necessary to lock public behavior. Do not reproduce every internal type, + state machine, gate, package permission, or operation catalog record. +- Keep at most one Mermaid diagram. +- Replace market feature matrices with a few lessons plus the market-analysis link. +- Avoid exact current-state counts unless they materially explain a decision. +- Avoid review-process, wave-gate, JSR-publish, and session details in the public RFC. Those remain + in run artifacts. +- Do not introduce compatibility, a dual runtime, a NetScript query DSL, runtime capability + negotiation, a hosted control plane, or unsupported multi-namespace claims. + +## Public API direction + +The examples should converge on a minimal and coherent surface, not preserve every raw-draft name. +Use the current native model-first Prisma `defineContract` builder as the schema foundation, and a +thin NetScript `defineDatabase` composition around native contract values. + +For validation, prefer this vocabulary unless source constraints force a better, equally small +alternative: + +```ts +const users = primaryBinding.ref({ space: 'app' }).model('User'); +const createUser = users.input('create', { representation: 'json' }); +const publicUser = users.output( + { select: { id: true, email: true } }, + { representation: 'json' }, +); +``` + +State the combined acceptance promise explicitly: exact native contract inference survives into the +app-local query binding, while runtime validation is intentionally bounded and fails closed whenever +the contract plus registered operation, selection, codec, or extension metadata cannot prove the +schema. + +## Technical corrections + +Apply every finding R1–R10 in `reviews/root-rfc-review.md`. In particular: + +- The first Prisma PostgreSQL adapter does not demonstrate or claim certified multi-namespace + support. Logical spaces do not magically prevent physical name collisions. +- Target-key checking occurs at `defineDatabase` composition unless a contextual API can actually + prove an earlier check. +- Pure compile/emit construction cannot receive live connection dependencies. +- Signing is not a database mutation. +- The generated binding uses one consistent generic/type association. +- Validation examples distinguish input schemas from selected output schemas. +- Persistent plugin tables default to full independent spaces; app-local native fragments and + published contribution mechanisms are not conflated. +- Transaction and import surfaces do not overclaim unproven types or package subpaths. +- Recovery has a receipt lookup path. +- Adoption never silently skips an intended target, and marker rollback is capability-qualified. + +## Evidence links to preserve + +Use relative links from the RFC to these artifacts instead of copying their contents: + +- approved architecture: `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +- Prisma source deep dive: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- native TypeScript schema/oRPC audit: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md` +- runtime-validation source audit: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md` +- market analysis: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` +- current-state audit: + `../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md` + +Keep primary GitHub/source links where they substantiate a load-bearing upstream fact. + +## Completion report + +Before returning: + +1. Run `deno fmt rfcs/0000-database-architecture.md`. +2. Run `deno fmt --check rfcs/0000-database-architecture.md`. +3. Run `git diff --check -- rfcs/0000-database-architecture.md`. +4. Report the final word count, line count, and changed file list. +5. Confirm all R1–R10 findings were applied, naming any disposition that was not a direct edit. + +Do not claim final acceptance. Qwen 3.8 Max, Grok 4.6 high, author/editor disposition, and the one +absolute-final Fable 5 high refinement still follow. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md new file mode 100644 index 0000000000..285480b5f6 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-disposition-consolidate.md @@ -0,0 +1,403 @@ +# use harness — Opus 5 RFC disposition and final consolidation + +You are the bounded author/editor for NetScript's database architecture RFC. Run as **native Claude +Code Opus 5, effort high**. This is the post-review disposition pass, not a new architecture pass +and not the absolute final substantive gate. + +## SKILL + +Use the NetScript harness discipline for this edit. Preserve the approved plan, reviewer separation, +route identity, edit scope, evidence boundaries, and final handoff contract. Do not invoke another +skill, model, agent, team, workflow, background worker, or review surface. + +## Frozen input and edit scope + +Work in `/home/codex/repos/netscript-db-rfc`. + +The sole editable file is: + +```text +rfcs/0000-database-architecture.md +``` + +The RFC input is frozen to commit `5dfc4e8eb3988818fc81c6f5dc2856d551443249`, RFC blob +`f46040d8b89f94809c61371da478aeeffb68c9db`, 11,205 words. HEAD may be newer because review and brief +artifacts were committed afterward; that does not authorize using a different RFC draft. + +Before editing, prove with read-only Git/hash inspection that the worktree RFC bytes equal the RFC +at `5dfc4e8eb`. If they differ, stop and return `BLOCKED_RFC_BASE_MISMATCH`; do not overwrite or +merge an unknown draft. + +Do not edit bookkeeping, reviews, briefs, research, plan, context pack, supervisor, worklog, drift, +doctrine, production code, generated files, or lock files. Do not commit, push, amend, open/update a +PR, or post comments. Do not use subagents or alternate models. + +## Required complete reading + +Read these files completely before editing: + +1. `AGENTS.md` +2. `.agents/skills/netscript-harness/SKILL.md` +3. `.llm/harness/workflow/lane-policy.md` +4. `rfcs/0000-database-architecture.md` +5. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +6. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +7. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md` +8. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md` + +If a focused Hono/DAL progressive-adoption precedent audit has appeared under this run's `research/` +directory by launch time, read it completely before editing and use its verified NetScript public- +surface lessons. If none exists, record that absence and continue; do not create the audit or launch +new research. + +The reviews already performed the source audit. Do not browse, launch new research, or expand the +research corpus. Consult an existing linked research file only to resolve an exact wording dispute. + +## Locked architecture and editorial law + +Decisions D-01–D-47 in the approved plan are locked except for the narrow, explicit owner override +`OWNER-DX-01` below. That override may refine or supersede D-07, D-08, D-36, and directly related +RFC prose only where the focused precedent evidence and a demonstrated type/runtime boundary support +it. All other decisions remain locked exactly in substance. Apart from this required correction, +this pass may repair examples, resolve contradictions, tighten authority/identity semantics, and +delete duplication; it may not add architecture. + +Do not introduce: + +- compatibility, Prisma 7 fallback, dual runtime, legacy facade, schema bridge, or migration-history + bridge; +- a NetScript model/field/relation/query DSL, repository layer, portable query facade, provider + switch, global registry/service locator, or hosted control plane; `OWNER-DX-01` requires a thin + NetScript orchestration recipe/DSL, not a parallel database language; +- new packages, new chapters, new public extension axes, private Prisma imports, copied overloads, + casts, slow-type waivers, or permissive validation; +- a merged Prisma contract across spaces, false multi-provider parity, non-default namespace claim, + cross-database relation/transaction, automatic rollback, or destructive plugin removal claim; +- review process, route/session metadata, exhaustive gates, or new research exposition in the public + RFC. + +The final RFC must be **at most 10,000 words**. Every addition must be offset by a larger deletion +in the same pass. Preserve the repository RFC headings; do not add a chapter or appendix. Prefer +local replacement and deletion over explanatory expansion. + +Keep the center of gravity on: + +1. the end-goal developer API and journey; +2. exact TypeScript inference from Prisma's current native model-first + `defineContract(scaffold, callback)` contract into sound app-local bindings, preferring source- + native inference over generated type code where it survives the proved package/declaration + boundary; +3. canonical provider artifacts and `DatabaseManifest` as the durable downstream join point; +4. bounded, fail-closed Standard Schema input/output validation; +5. plugin-owned spaces, app-local fragments, controlled augmentation, and single-registration + extension bundles; +6. explicit multi-target plan/apply/receipt/recovery semantics; +7. a clean break with marker-only, data-safe adoption. + +## `OWNER-DX-01` — three-level adoption and zero-manual-typegen correction + +This is an owner-authorized architectural correction, not editorial polish. The current RFC over- +indexes on “do not mirror Prisma's DSL” and does not expose NetScript's established progressive- +disclosure model. Correct the meaning everywhere: NetScript must not reproduce Prisma models, +fields, relations, native types, or query operations, but it **must** own a concise orchestration +surface for the framework seams around those native contracts. + +Do not add a chapter. Replace and compress the current verbose Step 1–3 prose/examples with one +concrete progressive-disclosure subsection. Show the **same small application and the same native +Prisma contract** side by side at all three levels, rather than presenting three unrelated designs: + +1. **Golden-path recipe/DSL.** A few-line normal-app surface covers a single target and shows the + minimal delta for multiple targets. It coordinates targets, connections, native contracts, + spaces/extensions, deterministic artifacts and bindings, runtime/control wiring, and Aspire and + agent projections. It delegates schema and query semantics to Prisma unchanged. +2. **Public factory builders.** The recipe lowers to the public NetScript factories/primitives that + application and plugin authors use for custom logic. Customization must not opt out of manifest + compilation, bindings, extension/plugin identity, validation, control, receipts, or safety + policy. Derive exact names and signatures from the focused Hono/DAL audit when present, the oRPC + precedent, the already-approved package graph, and existing database factory examples; do not + invent arbitrary syntax merely to fill the three boxes. +3. **Native foundation.** Advanced authors compose Prisma's public native + `defineContract(scaffold, callback)` value directly with NetScript kernel primitives/ports. This + remains unrestricted native Prisma authoring, not a NetScript schema facade, and reaches the same + compiler, manifest, artifact, validation, runtime, and control pipeline as the other two levels. + +Include a compact API-ownership map naming, for each shown surface, its owning package, source of +truth, value it produces/lowers to, and boundary it must not cross. At minimum distinguish Prisma- +owned contract authoring/query types, NetScript-owned recipe and factories, adapter/extension-owned +provider facets, app-local binding identity, and manifest-derived CLI/Aspire/agent projections. Do +not change the locked package graph just to make the table neat. + +Specify the normal development loop. A source contract or definition change must deterministically +and atomically refresh required compile artifacts and stale checks through the normal +dev/build/watch path. There may be an explicit CI emit/verify command, but a normal developer must +never discover a surprise manual “re-emit” or manual type-generation ritual. Automatic compilation +does **not** imply automatic migration planning or database mutation; plan/apply authority remains +explicit. + +### Binding decision hierarchy + +Challenge the current generated-binding premise instead of preserving it by inertia: + +1. First try to prove that app-local source-native `typeof contract`/definition inference can feed a + stable binding factory through type-only imports while runtime consumes only the durable manifest + and pinned provider artifacts. The proof must cover `isolatedDeclarations`, declaration emit, + package boundaries, plugin-owned spaces, per-target/per-space literal identity, and absence of + Prisma type leakage from public NetScript declarations. If sound, prefer it and remove generated + **type-code** as a required architecture step. +2. If source-native inference fails any boundary, show the minimal compile/type proof explaining + why. A generated module is then permitted only as an automatic implementation artifact: real + runtime values where runtime values are needed, deterministic and atomic output, + digest/provider/per-space identity, watch/build integration, and zero manual type-gen workflow. + It must never be the durable control authority; runtime still verifies against the manifest. + +Whichever branch wins, make the binding representation and stale-refusal semantics concrete in code, +and state why the rejected branch is unsound or needlessly generated. Do not force the frozen +draft's implementation merely because QF-01/GR-01 reviewed its example. + +## Mandatory dispositions + +Disposition every finding `QF-01` through `QF-05` and `GR-01` through `GR-08`. Several findings +overlap; one correction may close multiple IDs, but the final response must name every ID +separately. + +All corrections below are required. Do not silently decline or replace them with new architecture. + +### 1. Bindings are sound values, not ambient runtime fiction — QF-01 / GR-01 + +Remove `export declare const` from any module consumed for runtime binding. Apply the `OWNER-DX-01` +decision hierarchy first. If source-native type inference wins, show a real binding factory value +with type-only app-contract imports while runtime consumes and verifies the manifest. If generation +is proved necessary, both binding and manifest digest must be emitted runtime values, and the +generated value must carry the target identity, manifest digest, provider pin, and per-space +snapshot identity used by bind-time stale checks. + +Use the adapter-owned `/binding` seam for the provider-specific value factory. Do not expose that +factory as a provider-neutral query API, and do not hand-wave a `.d.ts` value into existence. Keep +the soundness rule: type identity, runtime construction, manifest, and provider artifacts resolve to +the same target/space identities, and bind refuses digest mismatch before the first query. + +### 2. Bindings are per target and per space; contracts remain disjoint — GR-03 + +Remove the single merged `AppContract` / single `cs:` implication. Prisma contract spaces remain +separate contracts and artifacts; the binding must not merge their Prisma values or query types. + +Show a target-level binding containing a literal, space-keyed type/value map, whether its types are +source-native or its module is automatically generated under the proved fallback. Each space entry +has its own contract declaration type and `ContractSnapshotId`; the target binding also carries the +`ManifestDigest` and provider pin. Query and validator lookup select an explicit `SpaceId`. + +The example may use a compact space-keyed type such as `PrimaryQueries['app']`, but it must preserve +each native contract's exact type and must not widen the map to a generic record. Update the session +query example coherently so it cannot imply that plugin and app contracts were combined into one +Prisma contract. Preserve separate per-target output roots, bindings, artifacts, lineages, locks, +and receipts. + +### 3. Multi-facet extension bundles are provider-owned opaque values — QF-02 / GR-02 + +The application must not construct a bundle by importing Prisma authoring, control, and runtime +facets. State and show that the Prisma adapter or the extension-pack publisher defines the complete +identity/version-checked bundle inside the controlled provider boundary. Consumers import one opaque +configured extension value; the provider fans it into authoring, control, runtime, and validation. + +The provider-neutral kernel sees only identity, version, provider/capability requirements, and +opaque facet handles. Preserve the dependency law: applications may import Prisma's public authoring +builder for native schema authoring, while only the adapter/extension publisher imports Prisma +runtime and control modules. + +### 4. Definition compilation and control execution have distinct owners — GR-04 + +Clarify that `compileDatabase`/composition is the pure A4 responsibility of `@netscript/database`. +The operation catalog may project a `compose` command, but `@netscript/database-control` does not +own the compiler and live control does not consume a `DatabaseDefinition`. + +The authored definition is consumed only by the pure compiler. Runtime, emit-after-compilation, +inspect, plan, apply, verify, and recovery consume the resolved manifest and pinned artifacts as +appropriate. Correct the authority table and operation-class prose without collapsing definition, +manifest, plan, ledger, or receipt. + +### 5. `adopted` management is not a detach tombstone — GR-05 + +Keep `adopted` as the manage-forward ownership policy established by reviewed `db adopt`: it may be +planned and mutated against its baseline. A detached-and-retained plugin space instead loses its +runtime binding and active migration owner while preserving data, provider marker, lineage, +ownership history, and a **verify-only tombstone**. It is not planned or mutated until a new +explicit space re-adopts it. + +Do not add a fifth ownership policy merely to encode lifecycle. Express the tombstone as retained +space lifecycle state/evidence, distinct from the active `adopted` policy. Preserve retain as the +only guaranteed removal behavior. + +### 6. Define space → target → run outcome rollup — GR-06 + +Add one compact deterministic rollup rule near the multi-target saga: + +- every selected space records a terminal outcome; +- a target is `succeeded` only when every selected space for that target succeeds; +- `outcome-unknown` and `cleanup-required` dominate target rollup, followed by failed/refused/ + cancelled according to the catalog's closed precedence; +- mixed space outcomes never make that target “partially successful”; +- run-level `partial-success` exists only when at least one target succeeds and at least one + selected target has a non-success terminal outcome; +- when no target succeeds, the run uses the deterministic non-success outcome, never + `partial-success`. + +Do not add a second state diagram or a large status catalog. + +### 7. Use one configured provider value and bind/mark every elision — QF-03 / GR-07 + +Use one unambiguous role for `prismaPostgres`: either name the factory and the configured immutable +provider descriptor separately, or show a single configured value reused by target definition, +runtime, and control. Do not alternate between `prismaPostgres({ minVersion: 15 })` and +`providers: [prismaPostgres]` as if they were the same value. + +Bind `connections`, `runId`, and `policy` through function parameters or explicit declarations, or +mark a snippet as an intentional excerpt. Do the same for application-owned `AccountStore` / +`PrismaAccountStore`. A snippet presented as a complete file cannot contain undeclared values. Keep +the API examples compact; do not add a framework helper merely to fill an example variable. + +### 8. Correct the two Prisma evidence sentences — QF-04 / QF-05 / GR-08 + +- Attribute `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121` explicitly to + the **Prisma RC1 checkout** or link the existing deep dive, so it is not mistaken for a NetScript + path. +- State separately that Prisma's Standard Schema `paramsSchema` validates codec **parameters**, not + model values, and that Prisma codecs define three **conversion representations**: application + runtime, driver wire, and target JSON. Only `runtime | json` are NetScript's public validation + representations; driver wire remains adapter-internal. Conversion success is not validation. + +Do not change the bounded-validation decision or reopen the audited fail-closed list. + +## Deletion ledger: apply, validate, and finish below 10,000 words — GR-08 + +Start at 11,205 words. The corrections above add some words, so delete **more than 1,205 plus every +added word**. Measure; do not rely on estimates. The primary funding source for `OWNER-DX-01` is +replacement of the current verbose Step 1–3 walkthrough with its smaller side-by-side three-level +surface—not a new chapter appended elsewhere. Then use the Qwen and Grok ledgers as one prioritized +ledger: + +| Priority | Candidate content | Preserve | +| -------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Motivation's `resolveTarget` mechanics and repair-pipeline enumeration | The two-target collision, non-atomic conclusion, and linked current-state audit | +| 2 | The six-item “Prisma 8 attacks the pain points” restatement | Contract/control/space opportunity and deep-dive link | +| 3 | “Three things NetScript will not do” paragraph | One short sentence preserving no obsolete fluent **schema/query** API or re-export, without forbidding the required orchestration recipe | +| 4 | “What you stop doing” eight-item repetition | Refusal table and one transition sentence | +| 5 | Five/six-value explanatory prose duplicated by the authority table | The authority table and all distinct artifact roles | +| 6 | Composition-validation laundry list | Determinism, diagnostics, and negative-test requirement | +| 7 | Prose that repeats edges already visible in the one Mermaid diagram | Never-replay, checkpoint granularity, lock scope, certified-lock refusal | +| 8 | Positive `ValidationIR` inventory duplicated by the schema-class table/fail-closed list | Bounded algebra, construction-time refusal, value issues, representations, cache identity | +| 9 | Refusal-boundary compatibility/re-export repetition | One canonical clean-break law, no arbitrary TS/text repair, no implicit/cross-target claims | +| 10 | Early-Access, indirection, and conformance-cost drawback repetition | Real costs and the adapter-boundary mitigation | +| 11 | “Why this shape” operational-gap lists already in the deep dive | Manifest join point, target identity, app-local type constraint | +| 12 | Market-lessons and Prior-art repetition | Direct official links, the adopted lessons once, and the oRPC transfer paragraph | +| 13 | Scope-law paragraph repeated by D-31/non-goals/alternatives | One local-kernel refusal | +| 14 | Unresolved-question implementation sweep already owned by the plan | Only the few genuinely reader-relevant W3/W5/W10/upstream gates | +| 15 | Future policy-factory bullet | Remove it; Candidate A is the v1 decision | +| 16 | Repeated target-default, target-isolation, two-phase, serverless-precedent, summary-withhold, and package-count prose | Each unique invariant once | + +Continue tightening only within those duplicate zones until `wc -w` reports **≤10,000**. If a line +range changed after earlier edits, follow the content, not stale line numbers. Do not delete unique +safety or public-contract content to make the number. + +### Must not cut + +Preserve, while updating only where a mandatory correction above requires it: + +- the native Prisma model-first authoring example and + current-builder/no-parallel-schema-or-query-DSL decision; +- the compact three-level adoption surface, same-app side-by-side examples, API-ownership map, + automated dev loop, one coherent factory/runtime/query example, validation example, + plugin-space/extension example, and plan/apply example; +- the refusal table and one canonical clean-break/no-compatibility law; +- authority and identity tables, inference rules, binding soundness seam, and package boundaries; +- the first-adapter namespace-withhold paragraph and physical-collision refusal; +- Standard Schema classes, bounded/fail-closed inventory, mandatory trust boundaries, codec/value + schema and cache/version identity; +- one-owner/object rule, space independence, augmentation grant, package-free pinned artifacts, and + corrected detach-and-retain semantics; +- the sole Mermaid lifecycle diagram, closed-target/no-silent-omission law, corrected rollup, + unknown-outcome/inspect-before-resume, locking, receipt lookup, and saga semantics; +- adoption steps, pre-cutover safety list, rollback-boundary table, marker-only zero-DDL/DML + guarantee, and explicit selected-target closure; +- alternatives table, incident table, structured JSON/stale-plan examples, and direct official + upstream/comparator links; +- unsupported-provider and no-false-portability statements. + +Do not copy D-01–D-47 or W0–W11 into the RFC; keep their direct plan link. + +## Claims already checked: no silent reopenings + +Do not alter these claims without new contradictory evidence, which this pass is not authorized to +seek: + +- RC1 exposes the current model-first `defineContract(scaffold, callback)` const-generic overload + and composed helpers. Whether NetScript needs generated type code around it is deliberately + reopened only by `OWNER-DX-01` and must be settled by the required type/package-boundary proof. +- RC1 Prisma spaces remain separate contracts; its aggregate does not merge them. +- RC1 namespace authoring type maps flatten into the default namespace; the capability remains + withheld with no cast/private-import workaround. +- `@prisma/orm-postgres` has 138 audited top-level export keys at the RC1 pin. +- Prisma operation/type maps needed for full runtime validation are phantom/erased. +- Public validation modes remain `runtime | json`; driver wire remains internal. +- Current NetScript target/workspace collapse, plugin-fragment doctrine, AP-24, and the oRPC-only + slow-types carve-out are source-verified. +- Root R1–R10 remain resolved. +- No database package receives a slow-types waiver, and no public NetScript declaration leaks Prisma + types. + +## Required checks + +After editing only the RFC, run: + +```bash +deno fmt rfcs/0000-database-architecture.md +deno fmt --check rfcs/0000-database-architecture.md +deno task docs:links +git diff --check -- rfcs/0000-database-architecture.md +wc -w rfcs/0000-database-architecture.md +``` + +Inspect the scoped diff against `5dfc4e8eb` and verify: + +- only `rfcs/0000-database-architecture.md` changed during this session; +- the word count is at most 10,000; +- every addition has a larger deletion; +- `OWNER-DX-01` is visibly satisfied with all three levels, the same-app comparison, an explicit API + ownership map, a no-surprise-manual-emit development loop, and a binding proof/decision; +- every QF/GR correction is visible; +- no decision outside the named D-07/D-08/D-36 owner-override envelope, must-not-cut contract, + direct link, or safety/refusal guarantee disappeared; +- no new chapter, compatibility path, architecture beyond `OWNER-DX-01`, unsupported claim, or + unresolved must-decide-now item was introduced. + +Do not commit or push after checks. + +## Final response contract + +Return a concise Markdown handoff containing: + +1. **Route receipt:** native Claude Code, requested/observed `claude-opus-5`, high effort, session + ID, frozen input commit/blob, and confirmation that no subagent/workflow/alternate model ran. +2. **Counts:** before and after words and lines, gross additions/deletions from the scoped Git diff, + and net word reduction. +3. **Stable disposition table:** one row for `OWNER-DX-01` and one row for each `QF-01`–`QF-05` and + `GR-01`–`GR-08`, with status `applied`, `merged-with `, or `declined`; exact RFC + section/line; and a one-sentence rationale. For `OWNER-DX-01`, name the selected binding branch, + the evidence supporting it, and any precise D-07/D-08/D-36 refinement. The required corrections + above should be applied or explicitly reported blocked, never silently omitted. +4. **Deletion ledger actually applied:** sections/content removed, approximate word savings, and the + resulting final count. +5. **Locked-content confirmation:** every decision except the explicitly dispositioned `OWNER-DX-01` + refinements to D-07/D-08/D-36 preserved, root R1–R10 preserved, must-not-cut content present, and + checked-sound claims not otherwise reopened. +6. **Files changed:** must list only `rfcs/0000-database-architecture.md`. +7. **Checks:** exact command and exit status for format, `docs:links`, diff check, and word-count + gate. +8. **Residual risks:** only genuine implementation/upstream gates already present in the RFC/plan; + do not create new architecture questions. + +End with `READY_FOR_FABLE_FINAL_REFINEMENT` only if every required correction is dispositioned, all +checks pass, the RFC is ≤10,000 words, and no out-of-scope file changed. Otherwise end with +`BLOCKED: `. + +Do not claim final RFC acceptance. The owner-directed Fable 5 high in-place refinement remains the +absolute last substantive gate; after that, only mechanical verification may follow. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md new file mode 100644 index 0000000000..98bf1e6b98 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/claude-opus-rfc-root-corrections.md @@ -0,0 +1,232 @@ +# Claude Opus 5 high — root semantic corrections + +You are the **single native Claude Code Opus 5 high lead author/editor** for a bounded correction of +NetScript's database architecture RFC. Continue in `/home/codex/repos/netscript-db-rfc`. + +Edit only: + +```text +rfcs/0000-database-architecture.md +``` + +Do not edit run bookkeeping, plans, research, reviews, briefs, doctrine, source code, generated +files, or locks. Do not use subagents, another model, browsing, or a new research workflow. Do not +commit or push. + +## This brief supersedes the old size gate + +This brief supersedes every instruction in `briefs/claude-opus-rfc-disposition-consolidate.md`, +reviews, worklogs, or messages that sets a word-count target, `<=10k` target, required net deletion, +deletion budget, or size-conditioned completion token. **There is no word-count acceptance gate.** +Do not delete unique evidence, API contracts, safety rules, examples, or explanation to reach a +number. + +The only editorial criteria are semantic completeness, correctness, clarity, useful detail, and +non-duplication. Remove or combine prose only when it says the same thing without adding precision. +Do not add a book: repair the existing sections locally and keep the current heading structure. + +The current worktree RFC is the correction base, not frozen commit `5dfc4e8eb`. At brief creation it +has Git blob `f0b87f19c117d6167ee2a7b2b623aa8aa6e149c7`; verify it before editing and stop rather +than overwrite a different concurrent draft. + +## Required reading and invariants + +Read completely before editing: `AGENTS.md`, the current RFC, `plan.md`, `research.md`, +`research/layered-dx-api-audit.md`, `research/typescript-schema-orpc-audit.md`, +`research/runtime-validation-source-audit.md`, and the existing Qwen/Grok/root reviews. Use the +pinned RC1 checkout under `.llm/tmp/prisma-v8-rc1` only to confirm exact API spelling already named +below; do not widen research. + +Preserve D-01–D-47 except the already-authorized `OWNER-DX-01` refinements to D-07, D-08, and D-36. +Preserve the exact six-package graph, native Prisma schema/query authority, provider-neutral kernel, +PostgreSQL-only first adapter, bounded fail-closed Standard Schema, separate contract spaces, +manifest/plan/ledger/receipt identities, explicit effects and recovery, clean break, and data-safe +adoption. Add no compatibility layer, schema/query mirror DSL, repository facade, provider switch, +global registry, private Prisma import, copied overload, cast workaround, or unsupported claim. + +## Required corrections + +### 1. Make L1 provider ownership and value flow real + +The current L1 imports `definePostgresDatabase` from neutral `@netscript/database`, silently chooses +a PostgreSQL provider, exports no configured provider value, and later claims the composition root +can import/reach that same value. This contradicts all of: the adapter-only provider boundary, the +neutral package's no-provider dependency, the rule that runtime does not consume +`DatabaseDefinition`, and the executable-example promise. + +Correct the same-app progression so: + +- the application creates **one** configured immutable provider value from + `@netscript/database-prisma-postgres` and exports/reuses it in L1/L2, runtime, and control; +- the L1 recipe owned by `@netscript/database` is provider-neutral and accepts that value; it + literally calls L2 and returns the same `DatabaseDefinition`; +- no hidden default, provider lookup, `database.providers` runtime read, or second provider instance + exists; +- the L1 name does not promise a provider-specific implementation from a neutral package. Choose a + concise provider-neutral name/signature consistent with `define` semantics; do not add a package; +- L3 receives the manifest, configured provider, connections, and binding—not the definition. + +Resolve `fromAspire` ownership at the same time. The actual Aspire `ConnectionSource` adapter and +resource projection belong to `@netscript/aspire`. Either import an Aspire-owned pure reference +constructor from that package, or state and type a neutral data-only reference constructor that has +no Aspire implementation/dependency. Do not let `@netscript/database` smuggle in Aspire IO. + +### 2. Register an extension once, early enough for authoring + +The current example first builds `appContract` with Prisma's raw pgvector pack, then separately +registers a NetScript `pgvector(...)` bundle after the contract exists. That is two registration +sites; the later value cannot retroactively provide the authoring facet. + +Show one configured extension value created before native contract construction and a real two-phase +flow: phase 1 collects and identity/version-checks the provider-owned opaque bundle; phase 2 invokes +the native Prisma model-first builder with its public authoring facet and then fans the same bundle +into control, runtime, and validation. The app never assembles/imports Prisma control or runtime +facets. NetScript may orchestrate `defineContract`; it may not mirror its model/field/ +relation/query vocabulary. Keep direct native Prisma authoring as an honest L3 escape hatch and say +precisely whether that escape hatch must pass the same configured bundle's public authoring +projection. + +### 3. Correct examples to the pinned RC1 API + +- Replace `field.timestamp().defaultNow()` with the pinned RC1 temporal helper actually demonstrated + by upstream, such as `field.temporal.createdAt()`. +- Replace Prisma-7-shaped lowercase `orm.post.findMany` / `orm.user.create` calls. Current RC1 ORM + is Pascal-case and fluent: examples use shapes such as + `db.Post.where(...).select(...).take(...).all()` and `db.User.create(...)`. Keep explicit space + selection, but let `space('app').orm` expose that native RC1 surface unchanged. +- Cite the pinned example/source beside claims whose spelling is RC1-specific; do not present a + proposed NetScript wrapper as an observed Prisma API. + +### 4. Make mixed source-native and artifact-only binding sound + +Keep erased `typeof definition` inference for app-authored contracts. A plugin-owned pinned space is +artifact-only at the consumer and TypeScript cannot infer its exact query type from JSON. Therefore +the target binding must explicitly combine: + +- source-native, type-only app contract evidence; and +- an automatically and atomically emitted provider declaration for each artifact-only queried space. + +Show the generated **declaration** imported into the hand-written/real adapter binding value, or +omit an artifact-only space from the typed query map. Do not claim `PrimaryQueries` contains `auth` +without showing its declaration evidence. Each space remains a separate contract type and +`ContractSnapshotId`; no merged Prisma contract or generic-record widening is allowed. The runtime +value is constructed by the adapter `/binding` factory from the manifest/provider identities and is +not an ambient `declare const`. + +Bound the fallback exactly. Automatic declaration emission is for publish/artifact-only boundaries +proved in W3. Do not incidentally say failure of the direct app fixture makes generation universal. +If direct app inference requires a private import, copied overload, cast, provider type in a neutral +package, or runtime authoring evaluation, record it as a W3 kill/rethink criterion. Runtime still +consumes manifest and pinned artifact values; a declaration is type evidence, never control +authority. + +### 5. Make L3 and all example status honest + +L3 must be a complete, coherent example of native Prisma `defineContract` plus NetScript +primitives/ports reaching the same compiler, manifest, adapter binding, runtime, and control—not an +L2 definition relabelled “native foundation.” It may be a compact excerpt, but label it as such. + +Across every snippet, either bind imports/values (`postgres`, `connections`, `runId`, `policy`, +`AccountStore`, plugin contribution factories, generated declarations) or label the code as a +focused excerpt and name the omitted prior value. Do not claim examples are executable exactly as +written while using ellipses, undeclared symbols, a callable constant, or a value exported only by +another layer. Keep examples useful; do not inflate them with irrelevant scaffolding. + +Use “generated declaration” or “generated provider type artifact” for the bounded fallback. Use +“binding” for the real adapter-created runtime value that carries/verifies target, manifest digest, +provider pin, and per-space snapshot ids. The manifest remains the durable runtime/control +authority. + +### 6. Demonstrate a valid validation happy path + +The contract alone does not contain full create/update operation grammar. Before showing +`users.input('create', ...)`, identify the exact registered operation contributor that makes +`create` supported, where it is registered through the single extension/provider flow, and how its +identity/version participates in manifest/cache identity. Do not invent contract-only parity. +Unsupported operations still fail at schema construction; invalid values still return Standard +Schema issues. + +Correct the leakage invariant: **provider-neutral NetScript packages** must never expose Prisma +types. The Prisma adapter's explicitly provider-specific `/binding` declaration necessarily maps +opaque contract evidence to Prisma query/transaction types; do not claim that no published NetScript +declaration anywhere can name Prisma. + +### 7. Repair package dependency and compile/effect wording + +Keep six packages, but state the actual dependency edges rather than an ambiguous chain. +`@netscript/database` depends on `-contract` and owns definitions plus deterministic resolution. +Runtime and control consume manifest/contract SPIs and must not depend on `@netscript/database` for +definition types they never consume. They do not import each other. The adapter implements the +published runtime/control SPIs; the app supplies it as a value. `@netscript/plugin` publishes plain +contributions without provider/runtime/control dependencies. Testkit is never a runtime dependency. + +Reserve mathematically **pure/deterministic** for in-memory resolution of a definition plus supplied +snapshots. Loading source artifacts and atomically publishing emitted artifacts are offline effects; +they may be classified `pure` in the operation catalog only if the RFC explicitly defines that class +as “no live database/network/connection,” not side-effect-free. `compileDatabase` must not be called +both pure/total and an implicit IO loader. Preserve the structural rule that live control never +receives a definition. + +### 8. Complete rollup and plugin artifact semantics + +Make space → target → run rollup a total deterministic function over every terminal status, +including `skipped` and the all-success case. Preserve: target success requires all selected spaces; +unknown/cleanup dominate; mixed space outcomes do not make a target partially successful; run-level +`partial-success` requires at least one successful target and another non-success target; when none +succeeds, use the closed non-success precedence. Do not add another diagram. + +Replace the plugin example's contract-JSON-only `pinnedArtifact(...)` with one coherent pinned-space +aggregate containing descriptor snapshot, canonical contract data **and declaration**, migration +lineage/graph, head, hashes, and provenance. Make the exported symbol's call/value shape consistent +with L1/L2 use. Production package-free apply consumes this aggregate; query typing uses its +automatically emitted consumer declaration without merging spaces. + +### 9. Tell the truth about marker mutation and rollback + +Marker-only adoption performs provider-metadata DML. Replace “zero table or data DDL/DML” with the +precise guarantee: no application-schema DDL and no application/user-data DML; only idempotent, +receipt-backed provider marker/ledger metadata writes occur. Use the same wording in summary, +adoption table, and safety claims. + +If marker removal is not certified safe during pre-apply rollback, do not leave the space actively +`adopted`. Preserve the marker and transition it to the retained, verify-only lifecycle/tombstone +state: no runtime binding, plan, or apply until explicit re-adoption. Keep post-first-apply recovery +forward-only. + +### 10. Add exact pinned source links + +Keep RC1 facts separate from post-RC facts. Add direct pinned GitHub source links—not only local +checkout paths—for the load-bearing current builder, temporal helper/example, phantom runtime +contract overload, fluent Pascal-case ORM example, separate-space aggregate, namespace type-map, and +bounded-validation claims. Reuse existing deep-dive links where they resolve exactly; do not link a +moving branch or marketing page for a source-level claim. + +## Completion standard and checks + +Read the full result once after editing. Confirm that the guide and reference sections add different +value; remove only genuine repetition. Confirm the same configured provider and extension values +flow through all three adoption layers, runtime, and control. Confirm there is no hidden provider, +second registration, merged contract, arbitrary production TypeScript evaluation, manual emit/type +generation ritual, or compatibility path. + +Run: + +```bash +deno fmt rfcs/0000-database-architecture.md +deno fmt --check rfcs/0000-database-architecture.md +deno task docs:links +git diff --check -- rfcs/0000-database-architecture.md +git status --short +``` + +Also inspect the scoped diff and search for the superseded invalid shapes: `defaultNow`, lowercase +Prisma-7 `findMany`, an implicit `definePostgresDatabase` provider, contract-JSON-only plugin +artifact, universal-generation fallback, “zero ... DDL/DML” wording that ignores marker DML, and +provider-neutral Prisma leakage. Do not run or report a word-count gate. + +Return a concise handoff with: native route/session receipt; one disposition row per numbered +correction above; exact RFC sections/lines; confirmation that only the RFC changed; check commands +and exit status; and genuine residual W3/W4/W5/W10/upstream risks. End +`READY_FOR_ROOT_SEMANTIC_REVIEW` only if every correction is applied and checks pass. Otherwise end +`BLOCKED: `. Do not claim final acceptance: root semantic review and the one final +Fable 5 high refinement remain. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md new file mode 100644 index 0000000000..691c2f7909 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-final-evaluator.md @@ -0,0 +1,102 @@ +use harness + +# Final Fable 5 high RFC evaluator and refinement gate + +Run one fresh native Claude Code session as the absolute-final substantive gate for the NetScript +database architecture RFC. The owner explicitly reinstated this single Fable 5 high launch on +2026-08-14; that instruction supersedes the earlier Claude/Fable freeze only for this gate. + +## SKILL + +- Read `AGENTS.md`, `.agents/skills/netscript-harness/SKILL.md`, + `.llm/harness/evaluator/protocol.md`, `.llm/harness/evaluator/verdict-definitions.md`, and + `.llm/harness/archetypes/SCOPE-docs.md`. +- This is an owner-authorized final **evaluation plus refinement** exception to the protocol's + read-only evaluator rule. It does not authorize package/plugin implementation or a broader + redesign. +- Do not spawn subagents, start workflows, resume an earlier Claude session, or use a fallback + model. If native Fable cannot run, record the failure and stop. + +## Target and authority + +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Branch: `docs/database-architecture-rfc` +- Draft PR: +- Canonical RFC: `rfcs/0000-database-architecture.md` +- Run: `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` +- The launcher fast-forwards to the exact remote branch before this session. Record that starting + commit in `evaluate.md`; evaluate the checked-out content, not a remembered draft. + +Read the complete RFC. Then read the compact governing evidence rather than reproducing the full +research corpus: + +1. `plan.md`, `plan-eval.md`, `worklog.md`, `context-pack.md`, and `drift.md`; +2. `reviews/root-semantic-closure.md`, `reviews/qwen-rfc-focused-review.md`, and + `reviews/grok-rfc-adversarial-review.md`; +3. `research/layered-dx-api-audit.md`, `research/typescript-schema-orpc-audit.md`, and + `research/runtime-validation-source-audit.md`; +4. pinned or official sources linked by the RFC when a claim needs verification. + +Do not restart the market study, duplicate source extracts into the RFC, or optimize for a word +count. Content, clarity, and implementability are the criteria. + +## Evaluation focus + +Judge whether an implementer can build the intended system without inventing missing architecture, +with special weight on the owner's end goal: + +1. A fantastic, low-ceremony developer experience built as one progressive surface: concise L1 + preset/DSL, public L2 factories, and unfenced L3 native Prisma plus NetScript primitives. +2. Prisma Next's current native TypeScript contract builder remains the schema authority. NetScript + adds adoption seams and policy; it does not mirror or fork Prisma's schema/query vocabulary. +3. Contract-first end-to-end type safety: source-native app inference by default, precise branded + values, and generated declarations only at proven publish/artifact boundaries. +4. One plugin contribution value registered once and fanning out authoring, runtime, control, + validation, CLI/docs/agent, ownership, and migration facets without a live service locator. +5. Runtime and JSON Standard Schema validation derived from the contract where metadata is + sufficient, with explicit operation/codec contributions and deterministic fail-closed refusal + elsewhere. +6. Coherent manifest -> plan -> receipt authority, locks, recovery, retained rollback, multi-space + identity, and honest PostgreSQL-first scope without pretending full multi-engine parity. +7. A clean break: no backward-compatibility requirement or compatibility shim. Migration guidance, + tests, and an optional parallel branch provide adoption safety instead. +8. API examples that are internally complete at their stated level and match pinned Prisma 8 RC + surfaces, package boundaries, emitted artifacts, and runtime value flow. + +Attack abstraction cost and manual steps particularly hard. A simple application must not pay +enterprise ceremony before it benefits from it, while advanced users and plugins must retain full +power. Verify that automated watch/compile/emit/staleness behavior makes the happy path feel native +rather than like a sequence of manual generators and adapters. + +## Refinement authority + +- If the RFC is already sound, do not rewrite it for style or manufacture findings. +- Correct factual contradictions, incomplete value/type flows, misleading API examples, or missing + DX commitments directly in the RFC when the repair stays within D-01–D-47 and `OWNER-DX-01`. +- Prefer clearer API contracts and links to evidence over duplicated explanation. Consolidate only + when it improves comprehension; there is no minimum, maximum, or target word count. +- Do not reopen the package graph, compatibility posture, native-Prisma authority, or fail-closed + validation boundary without a demonstrated blocker. A material architectural rescope receives + `FAIL_RESCOPE`; do not improvise it in this final pass. +- Do not edit `packages/**`, `plugins/**`, generated evidence, or the verbatim Qwen/Grok review + artifacts. + +## Required outputs and close gate + +1. Create `evaluate.md` from `.llm/harness/templates/evaluate.md`. Keep it decision-grade and cite + concrete file sections, commands, commits, or primary-source links for every substantive result. +2. If you refine the RFC, record each material disposition in `evaluate.md`; then reread the + affected end-to-end flows so a local correction does not create a cross-section contradiction. +3. Update `worklog.md`, `context-pack.md`, `supervisor.md`, and `drift.md` with the actual fresh + route, starting commit, verdict, refinements, and the fact that this one gate superseded the + earlier cancellation. Preserve the cancellation as historical provenance. +4. Run the docs-only mechanical gates: targeted `deno fmt --check` for the mutable Markdown files, + `deno task docs:links`, `git diff --check`, balanced-fence verification, and a clean status + check. Do not run package/runtime E2E for this RFC-only gate. +5. Use exactly one formal verdict: `PASS`, `FAIL_FIX`, `FAIL_RESCOPE`, or `FAIL_DEBT`. A `PASS` may + include evaluator-owned narrow refinements only when all resulting claims and gates are green. +6. Commit the complete final-evaluator gate with a message naming what it proves, push + `docs/database-architecture-rfc`, and comment on draft PR #1640 with the commit, verdict, + refinements, and command evidence. Keep the PR draft; do not merge or mark it ready. +7. Finish with a clean worktree whose local HEAD equals the remote branch. If any required step + fails, leave an honest failure receipt and do not claim the gate passed. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md new file mode 100644 index 0000000000..1ecd8047b4 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval-cycle-2.md @@ -0,0 +1,97 @@ +use harness + +# Formal PLAN-EVAL Cycle 2 — NetScript Database Architecture / Prisma 8 RFC + +You are the fresh, separate formal PLAN-EVAL evaluator for run +`docs-database-architecture-rfc--prisma-8-rfc`. You did not author the research, plan, or cycle 1 +correction. Be adversarial, evidence-led, and independent. This is PLAN-EVAL only: judge the locked +plan, never author the RFC, evaluate implementation that does not exist, or soften the harness +checklist. + +## Route and identity + +- Required route: native Claude Code, `claude-fable-5`, effort `medium`. +- Record the observed model, effort, fresh session ID, date, worktree, branch, and evaluated commit. +- Evaluated worktree: `/home/codex/repos/netscript-db-rfc`. +- Evaluated branch/head: `docs/database-architecture-rfc` at `383170bbc` + (`docs(rfc): record plan evaluation correction`). +- This session must be new and separate from cycle 1 (`dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`), the + Codex supervisor, Opus research lane, Qwen review, and every delegated research/synthesis agent. + +## Cycle 1 context — verify, do not assume + +Cycle 1 evaluated commit `3cbcfcec8` and returned `FAIL_PLAN`. Seven Plan-Gate boxes passed; the +only required fix was a copied claim that generated workspaces contained exactly 30 `db:*` task +keys. The evaluator executed `generateDatabaseDenoJson` for PostgreSQL, SQLite, MySQL, and MSSQL and +found 42 keys in every generated engine workspace. Commit `383170bbc` corrected the mutable +rebaseline, synthesis, and plan records; dispositioned Qwen F3 as an incorrect correction; and +preserved the cycle 1 artifact and independent model outputs as audit evidence. + +Read the current `plan-eval.md` before replacing it. Independently verify that the required fix is +complete and does not introduce ambiguity such as treating 42 as a cross-workspace total. Then run +the **entire** Plan-Gate again. A corrected cycle-1 finding is not by itself grounds for PASS. + +## Mandatory harness inputs, in this order + +1. `.llm/harness/gates/plan-gate.md` +2. `.llm/harness/evaluator/plan-protocol.md` +3. `.llm/harness/evaluator/verdict-definitions.md` +4. `.llm/harness/templates/plan-eval.md` +5. Run files: `research.md`, `plan.md`, `supervisor.md`, `drift.md`, and the complete `## Design` + section of `worklog.md` under `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/`. +6. Detailed synthesis and planned publish audit: `research/architecture-plan-synthesis.md` and + `research/planned-jsr-audit.md`. +7. Every other report linked by run-root `research.md`; challenge load-bearing claims and conflict + resolutions rather than trusting the synthesis. +8. `.llm/harness/archetypes/SCOPE-docs.md`, `.llm/harness/gates/archetype-gate-matrix.md`, the + applicable A1/A2/A3/A4/A5/A6 archetype profiles, and the doctrine files cited in the plan. +9. `.llm/harness/debt/arch-debt.md` entries relevant to database, Prisma, plugin schema, generation, + and Aspire coupling. +10. Repo `AGENTS.md`, `rfcs/README.md`, and `rfcs/0000-template.md` where they constrain the plan. + +## Mandatory procedure + +- Confirm run-root `research.md` is explicitly rebaselined to + `cd720529333328bcba5e1a308ce7632f4350efdf`. Fetch/inspect current `origin/main`: if it has + advanced, state the exact delta and independently decide whether it invalidates any research, + plan, archetype, gate, or RFC-authoring premise. Do not call drift irrelevant without evidence. +- Re-execute or otherwise independently prove the 42-per-workspace correction across all four + providers, and verify every mutable false-count occurrence was corrected while immutable evidence + was explicitly superseded. +- Spot-check at least three other load-bearing findings against the actual tree, including one + current NetScript fact, one pinned Prisma RC/current-source fact, and one doctrine/JSR/package- + boundary fact. Record exact paths/lines or commits. +- Walk every Plan-Gate checkbox individually and cite the exact plan/research/worklog location that + satisfies it, or mark it failed. +- Run your own open-decision sweep. Any decision still open that could force rework is an automatic + failed checkbox, even if the plan labels it deferred. +- Verify all D-01 through D-47 exist and classifications are coherent; specifically attack D-35, + D-37, D-41, and D-42 to decide whether their deferral is safe. +- Verify there are fewer than 30 ordered commit slices and each names proof, gate, and files. +- Verify the exact future package graph assigns one archetype per unit, includes A3 runtime gates, + and does not allow a provider/query/slow-type dependency leak. +- Apply the planned JSR requirement honestly: planned packages do not exist, so dry-run/doc/packed + results must be N/A now; decide whether the prospective audit names sufficient implementation + mitigations. +- Challenge the clean-break/data-safety boundary, native Prisma TypeScript builder strategy, + app-local E2E inference, bounded fail-closed runtime validation, plugin ownership/removal, + multi-target/provider claims, operation/receipt recovery, implementation waves, and absolute-final + Fable ordering. +- Confirm the canonical RFC file `rfcs/0000-database-architecture.md` is absent. Its absence is + correct before PASS. + +## Verdict and output contract + +Replace exactly one evaluator artifact using the harness template at: + +`/home/codex/repos/netscript-db-rfc/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md` + +The cycle 1 version is preserved in commit `383170bbc`; summarize its disposition in the cycle 2 +artifact. Emit exactly one verdict: + +- `PASS` only if every Plan-Gate box is satisfied and no rework-forcing decision remains. +- `FAIL_PLAN` otherwise, with numbered, severity-tagged, actionable required fixes and exact + file/line evidence. This is the second allowed failure cycle, so be especially explicit. + +Do not edit any other file. Do not create the RFC. Do not commit or push. End the artifact with +exactly `PLAN-EVAL: PASS` or `PLAN-EVAL: FAIL_PLAN`, and end your turn immediately after writing it. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md new file mode 100644 index 0000000000..8065ee8fd3 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/fable-plan-eval.md @@ -0,0 +1,77 @@ +use harness + +# Formal PLAN-EVAL — NetScript Database Architecture / Prisma 8 RFC + +You are the fresh, separate formal PLAN-EVAL evaluator for run +`docs-database-architecture-rfc--prisma-8-rfc`. You did not author the research or plan. Be +adversarial, evidence-led, and independent. This is PLAN-EVAL only: judge the locked plan, never +author the RFC, evaluate implementation that does not exist, or soften the harness checklist. + +## Route and identity + +- Required route: native Claude Code, `claude-fable-5`, effort `medium`. +- Record the observed model, effort, session ID, date, worktree, branch, and evaluated commit. +- Evaluated worktree: `/home/codex/repos/netscript-db-rfc`. +- Evaluated branch/head: `docs/database-architecture-rfc` at `3cbcfcec8` + (`docs(rfc): lock database architecture plan`). +- This session is separate from the Codex supervisor, Opus research lane, Qwen review, and all + delegated research/synthesis agents. + +## Mandatory harness inputs, in this order + +1. `.llm/harness/gates/plan-gate.md` +2. `.llm/harness/evaluator/plan-protocol.md` +3. `.llm/harness/evaluator/verdict-definitions.md` +4. `.llm/harness/templates/plan-eval.md` +5. Run files: `research.md`, `plan.md`, `supervisor.md`, `drift.md`, and the complete `## Design` + section of `worklog.md` under `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/`. +6. Detailed synthesis and planned publish audit: `research/architecture-plan-synthesis.md` and + `research/planned-jsr-audit.md`. +7. Every other report linked by run-root `research.md`; use them to challenge load-bearing claims + and conflict resolutions rather than merely trusting the synthesis. +8. `.llm/harness/archetypes/SCOPE-docs.md`, `.llm/harness/gates/archetype-gate-matrix.md`, the + applicable A1/A2/A3/A4/A5/A6 archetype profiles, and the doctrine files cited in the plan. +9. `.llm/harness/debt/arch-debt.md` entries relevant to database, Prisma, plugin schema, generation, + and Aspire coupling. +10. Repo `AGENTS.md`, `rfcs/README.md`, and `rfcs/0000-template.md` where they constrain the plan. + +## Mandatory procedure + +- Confirm run-root `research.md` is current and explicitly rebaselined to current main baseline + `cd720529333328bcba5e1a308ce7632f4350efdf`. +- Spot-check at least three load-bearing findings against the actual tree, including one current + NetScript fact, one pinned Prisma RC/current-source fact, and one doctrine/JSR/package-boundary + fact. Record exact paths/lines or commits. +- Walk every Plan-Gate checkbox individually and cite the exact plan/research/worklog location that + satisfies it, or mark it failed. +- Run your own open-decision sweep. Any decision still open that could force rework is an automatic + failed checkbox, even if the plan labels it deferred. +- Verify all D-01 through D-47 exist and classifications are coherent; specifically attack D-35, + D-37, D-41, and D-42 to decide whether their deferral is safe. +- Verify there are fewer than 30 ordered commit slices and each names proof, gate, and files. +- Verify the exact future package graph assigns one archetype per unit, includes A3 runtime gates, + and does not allow a provider/query/slow-type dependency leak. +- Apply the planned JSR requirement honestly: planned packages do not exist, so dry-run/doc/packed + results must be N/A now; decide whether the prospective audit names sufficient implementation + mitigations. +- Challenge the clean-break/data-safety boundary, native Prisma TypeScript builder strategy, + app-local E2E inference, bounded fail-closed runtime validation, plugin ownership/removal, + multi-target/provider claims, operation/receipt recovery, implementation waves, and absolute-final + Fable ordering. +- Confirm the canonical RFC file `rfcs/0000-database-architecture.md` is absent. Its absence is + correct before PASS. + +## Verdict and output contract + +Write exactly one evaluator artifact using the harness template to the absolute path: + +`/home/codex/repos/netscript-db-rfc/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md` + +Emit exactly one verdict: + +- `PASS` only if every Plan-Gate box is satisfied and no rework-forcing decision remains. +- `FAIL_PLAN` otherwise, with numbered, severity-tagged, actionable required fixes and exact + file/line evidence. Do not edit the plan yourself. + +Do not edit any other file. Do not create the RFC. Do not commit or push. End the artifact with +exactly `PLAN-EVAL: PASS` or `PLAN-EVAL: FAIL_PLAN`, and end your turn immediately after writing it. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md new file mode 100644 index 0000000000..2ad72b6c53 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/grok-rfc-adversarial-review.md @@ -0,0 +1,219 @@ +# use harness — Grok 4.6 whole-RFC adversarial review + +You are an independent, bounded adversarial reviewer of NetScript's database architecture RFC. You +are not its author, editor, implementer, or final acceptance gate. + +## SKILL + +Use the NetScript harness discipline for this review. Preserve generator/reviewer separation, +requested-versus-observed route identity, read-only scope, evidence-backed findings, and a bounded +output. Do not invoke another skill, workflow, model, agent, or reviewer. + +## Route and checkpoint + +- Requested route: OpenCode via OpenRouter, model `openrouter/x-ai/grok-4.6`, variant `high`. +- Review the compact RFC checkpoint `5dfc4e8eb` + (`docs(rfc): consolidate database architecture + draft`). This is a post-draft adversarial review, + not final acceptance. +- Verify the evaluated RFC bytes against `5dfc4e8eb`. If the worktree RFC differs, review the exact + checkpoint with read-only Git inspection and report the mismatch; do not review an uncommitted + replacement silently. +- If the requested route cannot be observed or the observed model/variant differs, return + `ROUTE_BLOCKED` with the requested and observed identity. Do not simulate Grok or continue on an + alternate model. + +## Hard boundaries + +- Do not edit, create, delete, or format any repository file. +- Do not commit, push, open or update a PR, post comments, or mutate external state. +- Do not spawn subagents, child sessions, teams, workflows, background agents, or alternate models. +- Do not ask another agent to verify claims. Work as one Grok parent session. +- Read-only shell and focused source inspection are allowed. Do not run mutation, generation, + migration, database, network-deployment, or broad test commands. +- Do not turn this into a new research report or redesign the whole framework. Test whether the RFC + is coherent, safe, implementable, and economical on its own terms. +- Return the complete review in the final response. The supervisor will persist and disposition it. +- Maximum output: **2,500 words**, including tables and receipt. + +## Required complete reading + +Read these files completely, not summaries or selected line ranges: + +1. `rfcs/0000-database-architecture.md` +2. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +3. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +4. If present at launch time, + `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md`; if + the expected path is absent, read any single `reviews/qwen*rfc*review*.md` artifact that exists + and record its exact path. If no Qwen focused-review result exists, record `not present` and + continue independently. + +The plan is the locked decision and implementation-gate context. The root and optional Qwen reviews +are attack maps, not authority: independently verify their relevant claims and do not echo findings +without confirming that the checkpoint still contains the problem. + +For a disputed, load-bearing statement only, you may inspect the already available research corpus +or pinned Prisma RC source. Distinguish Prisma 8 RC1 fact, post-RC observation, current NetScript +fact, and RFC proposal. Do not browse broadly or restate source audits. + +## Review objective + +Attempt to falsify the RFC as one architecture. Look for contradictions between examples, +interfaces, invariants, provider claims, artifact roles, operation states, ownership rules, and +implementation waves. A finding is actionable only when it identifies a concrete RFC correction, +deletion, clarification, or implementation gate. Do not manufacture findings to appear adversarial. + +Review all seven axes below. + +### 1. Abstraction integrity + +- Is there exactly one coherent path from native schema authoring through definition, contract + artifact, manifest, generated binding, runtime, validation, operation plan, ledger, and receipt? +- Do definition, artifact, manifest, plan, provider ledger/marker, and immutable receipt retain + distinct authority and identity? +- Does any example make a downstream stage consume an upstream authoring value that the reference + architecture says it must not consume? +- Are pure compilation, live inspection, mutation, verification, and recovery structurally separated + rather than distinguished only by convention? + +### 2. Provider-neutral kernel versus Prisma leakage + +- Does the kernel express only provider-neutral identities, capabilities, ports, operation states, + and artifacts while the first certified adapter remains Prisma 8/PostgreSQL? +- Does native Prisma `defineContract(scaffold, callback)` remain the schema authority without a + NetScript schema/query DSL, copied overloads, private imports, re-exported builder, or + type-erasing wrapper? +- Are provider-specific query, transaction, codec, migration, and contract types confined to the + adapter/generated app-local boundary? +- Does “provider-neutral” describe an extensible kernel rather than falsely claiming portable query + semantics or feature parity across providers? + +### 3. Artifact authority, control, and recovery safety + +- Can every mutating operation identify its closed target set, exact manifest/contract inputs, + inspected baseline, executable plan, signature/expiry/staleness state, lock/fencing ownership, + provider ledger transition, and immutable receipt? +- Are partial success, no-success, unknown outcome, resume, idempotency, lookup, and verification + representable without guessing? +- Can recovery work after the original process and plugin package are absent? +- Does adoption preserve data and avoid silent target omission, accidental DDL/DML, unproved marker + removal, or rollback promises that a provider cannot guarantee? + +### 4. Plugin, multi-space, and multi-database extensibility + +- Is one owner responsible for every persistent object and migration history? +- Are plugin-owned spaces independently versioned and deployable from pinned artifacts, while + application-local fragments remain const-preserving native values composed in two phases? +- Are augmentation permissions explicit and collision/ownership checked? +- Do extension authoring, control, runtime, and validation facets share one verified identity and + version? +- Are `TargetId`, `SpaceId`, physical namespace, provider, resource, contract hash, and migration + head distinct? Are cross-space and cross-database references treated differently? +- Does the first adapter refuse uncertified multi-namespace behavior and physical collisions rather + than masking them? + +### 5. Public API, developer experience, and type safety + +- Can an implementer reconcile all imports, symbol roles, generics, generated files, lifecycle + calls, and error behavior into one implementable API? +- Does exact native contract inference survive into the app-local binding without casts, widening, + private imports, or phantom NetScript mirrors? +- Are transaction types honest, target-key checking placed at the composition point, and extension + helper availability target/pack-sensitive? +- Is Standard Schema validation selection-aware, `runtime | json`, bounded by explicit metadata, and + fail-closed at construction without pretending full Prisma operation parity? +- Does the normal path eliminate manual copying, generation repair, repeated extension wiring, and + Aspire-dependent pure work? + +### 6. Implementation feasibility and release gates + +- Do package boundaries and dependency directions permit the shown API without circular or forbidden + dependencies? +- Are W0–W11 ordered so each wave has the inputs and proof needed by the next? +- Are Prisma RC volatility, contract decoding, multi-namespace type gaps, custom codec predicates, + operation metadata, type-check performance, and prospective JSR constraints gated rather than + wished away? +- Are kill/switch criteria strong enough to narrow or stop an unsound implementation? +- Can the proposed conformance suite prove the public claims without relying on the implementation's + own types or permissive decoders? + +### 7. Editorial economy + +- Does each section make or constrain a decision, API, invariant, refusal, migration guarantee, or + unresolved gate? +- Identify duplicated proof, repeated refusals, process detail, speculative future work, oversized + declarations, and market/upstream prose that can become links. +- Prefer correction by replacement or deletion. Any proposed addition must name an equal or larger + deletion. +- The RFC is 11,205 words at the checkpoint. Propose a **net reduction**, targeting at most 10,000 + words without deleting public APIs, safety invariants, explicit refusals, or clean-break/data-safe + adoption guarantees. + +## Severity and disposition law + +Use stable finding IDs `GR-01`, `GR-02`, and so on, ordered by severity. + +- **blocker**: permits data loss/corruption, breaks an authority or ownership invariant, makes the + public API/type promise unimplementable, introduces hidden Prisma coupling into the neutral + kernel, contradicts the clean break, or makes apply/recovery unsafe. +- **refinement**: improves precision, coherence, implementability, DX, or economy without changing + the accepted architecture. + +Do not upgrade editorial preference to a blocker. Do not recommend backward compatibility, Prisma 7 +fallback, dual runtime, a second schema/query DSL, a global registry/service locator, hosted control +plane, casts/private imports, permissive validation, false provider parity, destructive uninstall, +or silent target subsets. + +## Required output contract + +Return one concise Markdown document in this order: + +### Route receipt + +Include requested and observed provider/model/variant, OpenCode session identifier if exposed, +evaluated commit and RFC byte identity, every required file actually read, optional Qwen artifact +status/path, any extra source path inspected, and explicit confirmation that no subagent was used. + +### Verdict + +Use exactly one: + +- `PASS` — no actionable blocker or refinement remains; +- `PASS_WITH_REFINEMENTS` — no blocker; bounded corrections/deletions remain; +- `REVISE_BLOCKERS` — one or more blockers must be dispositioned before final refinement; +- `ROUTE_BLOCKED` — requested route identity could not be proved. + +Give a two-sentence rationale and counts by class. + +### Findings + +Provide one table with: + +| ID | Class | Axis | RFC lines | Violated invariant/decision | Consequence | Smallest correction | Offset deletion | +| -- | ----- | ---- | --------- | --------------------------- | ----------- | ------------------- | --------------- | + +Use only `blocker` or `refinement` in `Class`. Every addition must identify an equal-or-larger +offset deletion. If there are no findings, say so; do not invent one. + +### Axis verdicts + +For all seven axes, give `PASS` or `FAIL`, the strongest negative evidence tested, and the result. +Do not fill this section with praise. + +### Net deletion ledger + +Name concrete RFC sections/line ranges, estimated removable words, and why removal preserves the +decision. Sum additions and deletions and report the expected **net word change**. The proposal must +be net negative; target at least 1,205 words of net reduction when this can be done without +weakening the architecture or safety contract. Also list content that must not be cut. + +### Sound claims not to reopen + +List only claims you actively checked and found sound. This prevents later editors from reopening +settled architecture without new evidence. + +### Final gate statement + +End with one line stating whether the RFC may proceed to author/editor disposition. Do not claim +final acceptance; the owner-directed Fable 5 high refinement remains the last substantive gate. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md new file mode 100644 index 0000000000..55fd982c7b --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-finish.md @@ -0,0 +1,30 @@ +# Qwen 3.8 Max — Immediate Final Synthesis + +Resume session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` on OpenRouter `qwen/qwen3.8-max`, effort +`max`. + +Your single-parent recovery successfully re-verified the NetScript load-bearing claims and began the +Prisma package audit, then the local PTY supervisor terminated the transport with signal 15 / exit +143. There was no additional evaluator-model policy violation, and all of your reasoning and tool +results are preserved in the resumed conversation. + +Do not perform another broad audit. Do not invoke Agent, Task, TaskCreate, Workflow, Team, or any +child-session facility. Synthesize the final report **now** from: + +- the evidence already in this resumed conversation; +- the committed current-state, Prisma deep-dive, and market-analysis research documents; +- at most a few narrowly targeted read-only checks needed to avoid an unsupported correction. + +Write exactly one artifact and no others: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md` + +Retain the original required structure: observed route/interruptions, verdict, corrected-fact +ledger, minimum viable architecture, ownership/boundary table, Prisma adopt/wrap/reject/defer +decisions, multi-provider/GA contingency, adversarial risk ledger, conformance/release matrix, +conditional decisions/kill criteria, and source register. Explicitly correct the root catalog to +`^7.8.0`, state that the generated workspace has 30 DB tasks, and separate RC-tag evidence from +post-RC-main evidence. Be concise enough to complete this turn but decision-grade enough to +influence plan lock. + +End only after the report file has been fully written. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md new file mode 100644 index 0000000000..7f321b62fd --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review-resume.md @@ -0,0 +1,38 @@ +# Qwen 3.8 Max — Recover and Finish Prisma Risk Review + +Resume session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` using the same requested and observed route: +OpenRouter `qwen/qwen3.8-max`, effort `max`. + +The parent review was interrupted because an automatically spawned child requested `claude-opus-5`; +the evaluator model guard denied that cross-model request. This is a route-policy failure, not a +finding about the architecture. + +Hard constraint for this resumed turn: do **not** invoke Agent, Task, TaskCreate, Workflow, Team, or +any subagent/child-session facility. Work as one Qwen parent. Use the evidence and completed child +results already in the resumed conversation; use only read-only file/search/shell tools if a small +gap remains. + +Finish the original independent falsification report. Correct any imprecise claims (including exact +versus caret Prisma catalog ranges), distinguish RC-tag proof from post-RC-main proof, and make +every load-bearing conclusion evidence-backed. + +Write exactly one repository artifact: + +`.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md` + +The report must contain: + +- requested/observed route and the guard-interruption disclosure; +- verdict on the architectural direction; +- corrected-fact ledger with exact sources; +- minimum viable NetScript-owned architecture; +- boundary table for NetScript vs Prisma vs providers/plugins/apps; +- Prisma adopt/wrap/reject/defer table; +- multi-provider and Prisma-GA contingency strategy; +- adversarial failure/risk ledger; +- conformance and release matrix; +- conditional decisions and kill/switch criteria; +- source register. + +Do not edit the canonical RFC, plan, worklog, supervisor, drift log, existing research, production +code, or any other file. End only after the report is complete. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md new file mode 100644 index 0000000000..e26721b924 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-prisma-risk-review.md @@ -0,0 +1,68 @@ +# Qwen 3.8 Max — Prisma 8 Integration and Abstraction Falsification + +Use the NetScript harness as an independent open-model research/review lane. This is not PLAN-EVAL, +not RFC authorship, and not permission to edit the repository. + +## Identity and scope + +- Requested provider/model: OpenRouter / `qwen/qwen3.8-max` +- Requested effort: `max` +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` +- Prisma RC source: `.llm/tmp/prisma-v8-rc1` at `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` +- Prisma current-main comparison pin: `71e2e0d9ee1f306b5a11435cd1973023cb33866a` + +Read `AGENTS.md`, `.agents/skills/netscript-harness/SKILL.md`, and these three research files +completely: + +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +- `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` + +Verify load-bearing claims against the local NetScript and Prisma sources. Do not trust the research +conclusions by default. + +## Assignment + +Falsify or strengthen the proposed direction from three angles: + +1. **Abstraction minimization:** determine whether a NetScript database graph, target descriptors, + contract spaces, capability negotiation, and consumer-owned ports are the minimum durable + concepts or an accidental second ORM/control plane. Propose a smaller superior alternative where + possible. +2. **Prisma integration risk:** identify every place Prisma 8 RC1/current-main churn, package + topology, migration semantics, runtime lifecycle, Deno behavior, contract versioning, extension + model, or agent surface could invalidate a NetScript public contract. Cite exact source paths, + commits, scorecard rows, issues, or PRs. +3. **Proof design:** specify negative-path conformance tests and adoption gates that distinguish + compile-time promises from actual plan/SQL/result/lifecycle behavior. Include two same-provider + targets, multi-schema, external ownership, plugin upgrade/removal, partial cross-target apply, + interrupted emission, version skew, stale plans, and Deno dependency graphs. + +Also answer: + +- Which provider strategy avoids blocking the architecture on Prisma 8's PostgreSQL-only GA target + without retaining Prisma 7 compatibility? +- Which proposed NetScript concepts must be public, internal, generated data, or adapter-local? +- What should be conditionally deferred until Prisma 8 final? +- What dangerous market analogy or missing competitor invalidates a conclusion in the market audit? +- What are the ten highest-risk RFC decisions, with severity, evidence, and required disposition? + +## Output + +Make no file edits and do not run mutation commands. Return one self-contained Markdown report in +your final response with: + +- requested/observed route caveat; +- independent verdict; +- corrected facts; +- minimum viable architecture; +- public/internal boundary table; +- Prisma adopt/wrap/reject/defer table; +- provider/parity strategy; +- adversarial finding ledger; +- conformance matrix; +- decisions that must remain conditional; +- source register. + +Label facts, inferences, and proposals. Do not write generic advice. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md new file mode 100644 index 0000000000..aa54fd3596 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/briefs/qwen-rfc-focused-review.md @@ -0,0 +1,92 @@ +# Qwen 3.8 Max — focused review of the consolidated database RFC + +You are the owner-directed focused reviewer, not the author. Work in +`/home/codex/repos/netscript-db-rfc` on branch `docs/database-architecture-rfc` at commit +`5dfc4e8eb`. + +Use one parent session only. Do not spawn children, subagents, teams, workflows, background agents, +or alternate models. Do not edit any file, commit, push, or comment on GitHub. Read-only shell and +source inspection are allowed. Return the complete review in your final response; the root will +persist it. + +## Required reading + +Read completely: + +1. `rfcs/0000-database-architecture.md` +2. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md` +3. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md` +4. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md` +5. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md` +6. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md` +7. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md` +8. `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md` + +Use the pinned Prisma checkout at `.llm/tmp/prisma-v8-rc1` only for a disputed load-bearing claim. +Distinguish RC1 evidence from post-RC evidence. Do not turn the review into another research report. + +## Owner's editorial law + +The owner will not read an 18,000-word book. The RFC is now 11,205 words after a 60% reduction. Its +final target is at most 10,000 words when cuts preserve the public API, safety invariants, and +explicit refusals. Prefer links to the research corpus over duplicated proof. Every suggested +addition must name an equal or larger deletion; otherwise recommend no addition. + +The center of gravity must remain: + +- end-goal API surface and developer journey; +- exact end-to-end TypeScript inference from native Prisma contract to app-local binding; +- contract-first canonical artifacts and the `DatabaseManifest` join point; +- bounded, fail-closed Standard Schema input/output validation; +- full plugin-space ownership, application-local fragments, controlled augmentation, and one + extension bundle fanning into authoring/control/runtime/validation; +- deterministic operations, plan/apply/receipt/recovery, and data-safe clean-break adoption. + +## Six review axes + +Review only these six axes. Falsify the examples and invariants rather than merely summarizing them. + +1. **TypeScript inference and API coherence** — native model-first Prisma surface, const/literal + preservation, target-key checking, generated `AppBinding`, transaction type honesty, import + subpaths, absence of type widening/private imports/re-export/query DSL, and whether every example + is one implementable API rather than pseudocode with incompatible symbol roles. +2. **Standard Schema and trust boundaries** — `input`/`output` semantics, `runtime | json`, exact + metadata requirements, codec/space/selection identity, fail-closed construction, path-rich value + issues, mandatory external boundaries, no claim of full Prisma operation parity, and no generated + validator repair pipeline in disguise. +3. **Control, recovery, and artifact authority** — pure/live/mutating separation, manifest as + durable downstream join point, provider ledger versus receipt, plan signing/expiry/staleness, + lock and fencing claims, unknown outcome, lookup/resume, multi-target aggregate outcomes, + explicit target closure, and CLI/docs/agent projection from one catalog. +4. **Migration and plugin safety** — one owner per object, space independence, plugin package-free + apply/verify, augmentation permissions, default-namespace collision refusal, detach-retain, + marker-only adoption, no silent target subset, rollback wording, no dual runtime or compatibility + path, and no accidental data mutation claim. +5. **Package and prospective JSR surface** — exact A1/A4/A3/A2/A2/A6 graph, dependency directions, + provider isolation, public subpaths, application-local generated typing, `isolatedDeclarations`, + no slow-type waiver, no unearned actual-publish-readiness claim, and whether any API example + forces a forbidden dependency or runtime authoring import. +6. **Market/upstream claims and reader economy** — only load-bearing claims, direct official links, + RC1 versus post-RC wording, no comparator straw man, no marketing overclaim, and concrete cuts to + reach at most 10,000 words without removing decisions. + +## Required output + +Return a concise Markdown review, maximum 2,500 words, with: + +- route receipt: requested model `qwen/qwen3.8-max`, requested effort `max`, evaluated commit, files + actually read, and whether any Prisma source path was inspected; +- verdict: `PASS`, `PASS_WITH_CHANGES`, or `REVISE`; +- findings table ordered by severity, each with stable id `QF-01...`, severity + `critical|high|medium|low`, exact RFC line(s), violated decision/invariant, why it matters, and + the smallest correction; +- a six-axis pass/fail table including negative evidence, not praise; +- a deletion ledger identifying at least 1,200 removable words by section/line range, while naming + any content that must not be cut; +- a final list of claims checked and found sound, so later editors do not reopen them without new + evidence. + +Do not propose backward compatibility, a second query/model DSL, a Prisma 7 fallback, a global +registry, a hosted control plane, false multi-provider parity, casts/private imports, or permissive +validation. A finding is actionable only if it can change the RFC or an explicit implementation +gate. Do not manufacture findings to appear adversarial. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md new file mode 100644 index 0000000000..8caf984853 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/context-pack.md @@ -0,0 +1,131 @@ +# Context Pack: NetScript Database Architecture and Prisma 8 RFC + +## Run Metadata + +| Field | Value | +| -------------- | ------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Current phase | `closed — final gate passed` | +| Archetype | Docs-only RFC describing future A1/A4/A3/A2/A2/A6 graph | +| Scope overlays | `SCOPE-docs.md` | + +## Current State + +The clean-break database architecture RFC has passed its absolute-final substantive gate. Issue #313 +remains historical evidence; its compatibility-first solution is superseded. PLAN-EVAL cycle 2 +passed, Opus authored and consolidated the draft, Qwen and Grok reviewed it, root closed the +remaining semantic findings at `d28d8e779`, and the owner-reinstated one-shot fresh native Fable 5 +high evaluator/refiner ran on 2026-08-15 from starting commit `a7a6887c2`. It returned **`PASS`** in +`evaluate.md` as fresh session `3517a6d2-b0b5-47ec-a207-b3533657a90c` after re-verifying the pinned +RC1 claims and applying one narrow example refinement (Step 1 `pgvector()` — upstream-false +extension-level `dimensions` removed). Gate `cc90ead70` is pushed. The earlier cancellation is +preserved as provenance; it was superseded for exactly this gate and all other Claude use stays +frozen. Draft PR #1640 awaits owner review and stays draft. + +## Completed + +- Loaded current repository, RFC process, harness, PR, doctrine-navigation, and docs-profile rules. +- Created an isolated worktree/branch from `origin/main` @ `cd7205293`. +- Read GitHub issue #313 and its comments through the connected GitHub surface. +- Selected and completed mandatory PLAN-EVAL. The owner's later Claude freeze temporarily cancelled + final refinement, then a subsequent directive reinstated exactly one fresh Fable gate; it ran and + passed. +- Completed the research corpus, D-01–D-47 lock, prospective JSR audit, and architecture synthesis. +- Preserved cycle 1 `FAIL_PLAN`, corrected the task finding to 42 keys per generated engine + workspace, and obtained cycle 2 `PASS`. +- Authored and pushed the evidence-complete raw RFC draft. +- Completed root personal source/doctrine/API review and wrote the Opus consolidation contract. +- Completed the Opus 5 high consolidation from 28,194 to 11,205 words and resolved R1–R10. +- Clarified that runtime consumes the manifest rather than `DatabaseDefinition`, kept artifact/value + authority explicit, and restricted `partial-success` to mixed target outcomes. +- Root read the complete compact RFC and accepted commit `5dfc4e8eb` for focused review after + targeted fmt, `docs:links`, and diff checks passed. +- Completed the 2,181-word Qwen focused review through requested/observed `qwen/qwen3.8-max`, effort + `max`, session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`. It made no edits and returned + `PASS_WITH_CHANGES` with QF-01 high, QF-02 medium, and QF-03–QF-05 low. +- Qwen passed architecture/type model, Standard Schema boundary, control/recovery, migration/plugin + safety, and market/upstream claims. Its narrow failures affect TypeScript/API examples and one + package/dependency example only. +- Completed the Grok whole-RFC review through requested/observed `x-ai/grok-4.6`, variant `high`, + session `ses_003644aeaffeSm3UCAW9xUqRIK`. It evaluated byte-identical blob `f46040d8...` from RFC + commit `5dfc4e8eb` at HEAD `be83301c6`, used no subagents, made no edits, and returned + `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. +- Grok passed axes 2, 3, 4, and 6. Abstraction, public API/DX/types, and economy failed narrowly; + the architecture stands. +- Completed `research/layered-dx-api-audit.md`: shipped service/Hono uses preset → factory → native + primitives; SDK and Fresh preserve inferred lower-layer values; pinned Prisma separates runtime + `contractJson` from its phantom compile-time contract generic. The audit recommends erased + `typeof definition` for app-owned contracts and automatic atomic launcher-integrated declarations + only for W3-proven publish/artifact-only boundaries. +- Completed author/editor dispositions and pushed `ad8effff9`. +- Root replaced the impossible extension and binding flows with one configured provider value and a + compiler-emitted, canonical-space/snapshot-bound target descriptor; split emission from runtime + module loading; unified `emit` authority; corrected branded IDs, examples, validation selection, + plugin aggregate transport, and durable retained rollback semantics. +- TypeScript/API, prospective JSR, and architecture closure lanes all returned `PASS`; root ran + targeted formatting, internal-link, whitespace, and fence checks and pushed `d28d8e779`. The + consolidated receipt is `reviews/root-semantic-closure.md`. + +- The final Fable 5 high gate ran 2026-08-15 as session `3517a6d2-b0b5-47ec-a207-b3533657a90c`: + starting commit `a7a6887c2`, verdict **`PASS`**, one narrow refinement, docs gates green + post-edit; recorded in `evaluate.md`, pushed as `cc90ead70`, and posted to PR #1640. + +## In Progress + +- Nothing. The run is closed pending owner review of draft PR #1640. + +## Next Steps + +1. Owner reviews draft PR #1640 and decides on RFC acceptance (W0). The PR stays draft; no merge or + ready transition is authorized from this run. + +## Key Decisions + +| Decision | Source | Notes | +| ------------------------------ | --------------- | -------------------------------------------------------------------------------------------------- | +| No backward compatibility | Owner directive | Migration safety is required; runtime compatibility shims are not. | +| NetScript owns its DB concepts | Initial plan | Prisma remains an adapter/engine target, not the framework-facing vocabulary. | +| Exact future package graph | Plan lock | A1 contract → A4 definition → A3 runtime → A2 control → A2 Prisma PostgreSQL adapter → A6 testkit. | +| Layered database adoption | Owner override | L1 preset/recipe uses L2 factories; L3 is native Prisma plus NetScript primitives/ports. | +| App type flow | Owner override | Erased `typeof definition` first; automatic atomic declaration only at a W3-proven boundary. | +| Single final Fable gate | Owner directive | Reinstates one fresh Fable 5 high evaluator/refiner; all other Claude usage remains frozen. | +| Content, not a word target | Owner directive | Consolidation serves clarity; length is not an acceptance metric. | + +## Files Changed + +| Path | Status | Notes | +| --------------------------------------------------------- | ------ | --------------------------------------------- | +| `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/` | new | Harness provenance and terminal receipts. | +| `rfcs/0000-database-architecture.md` | new | Canonical RFC; final Fable refinement pushed. | + +## Gates + +| Gate family | Current status | Evidence | +| ----------- | -------------- | --------------------------------------------------------------------- | +| Static | PASS | Final-gate RFC format, `docs:links`, diff, and 40 balanced fences. | +| Fitness | PASS | D-01–D-47, OWNER-DX-01, and three final closure audits. | +| Runtime | N/A | Docs-only RFC; future matrices are explicit implementation gates. | +| Consumer | PASS | TypeScript/API, JSR, and architecture closure all passed `d28d8e779`. | +| Evaluator | PASS | `evaluate.md`; session `3517a6d2-b0b5-47ec-a207-b3533657a90c`. | + +## Open Questions + +- No must-resolve-now architecture decision remains; pre-implementation decisions stay assigned to + their W1/W3/W4/W5/W7/W10 gates. W3 now includes direct-erasure and automatic-fallback proof. +- No review blocker/high remains. RFC implementation-time questions stay assigned to their + W1/W3/W4/W5/W7/W10 gates and do not reopen the architecture. + +## Drift and Debt + +- Drift: #313 compatibility-first architecture is superseded; the numeric length target remains + removed; the earlier final-Fable cancellation is historical and is superseded only for this one + scheduled gate. +- Debt: final evaluator reports zero new, resolved, deepened, or unrecorded doctrine violations; + designed future debt closure is not claimed as implemented. + +## Commits + +- Semantic review closure: `d28d8e779` (pushed). +- Final Fable gate + refinement: `cc90ead70` (pushed), from starting commit `a7a6887c2`. +- See the draft PR's commit list + per-slice PR comments (V3 retired `commits.md`). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md new file mode 100644 index 0000000000..fd38e1b37c --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/drift.md @@ -0,0 +1,219 @@ +# Drift Log: NetScript Database Architecture and Prisma 8 RFC + +Drift is append-only. Record facts that diverge from the plan, RFC, doctrine, or current-state +documentation. + +## 2026-08-13 — Issue #313 solution premise superseded + +- **What:** The carried-in plan preserves classic Prisma and adds Prisma Next as an opt-in Postgres + pilot. The owner now requires a clean architectural break with no backward-compatibility + constraint. +- **Source:** GitHub issue #313 body and the current owner directive. +- **Expected:** Reuse #313's additive migration architecture. +- **Actual:** Reuse only its evidence/problem inventory; redesign the target architecture from + current NetScript and Prisma 8 facts. +- **Severity:** architectural +- **Action:** rescope +- **Evidence:** + +## 2026-08-13 — Final refinement lane override + +- **What:** The final gate must use Fable 5 high and refine the RFC in place, not merely provide an + adversarial report. +- **Source:** Current owner directive. +- **Expected:** Ordinary docs/evaluator routing would use Fable medium for final polish or formal + evaluation. +- **Actual:** Owner-authorized Fable high is reserved as the absolute last substantive gate. +- **Severity:** significant +- **Action:** accept +- **Evidence:** `supervisor.md` routes and override record. + +## 2026-08-13 — Orchestration posture correction + +- **What:** The root session performed too much of the research directly instead of using the + harness as the orchestration layer. +- **Source:** Owner correction in the active session. +- **Expected:** Root research coordination followed by ordinary deep-analysis routing. +- **Actual:** The owner explicitly requires the root to orchestrate substantive independent work and + requests Claude Code Opus 5 high with its workflow capabilities. +- **Severity:** significant +- **Action:** correct +- **Evidence:** native background session `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, observed as Opus 5 + high in `/home/codex/repos/netscript-db-rfc`; exclusive briefing at + `briefs/claude-opus-architecture.md`. + +## 2026-08-13 — Qwen child-route guard interruption + +- **What:** The Qwen 3.8 Max falsification parent spawned read-only verification children; one child + request attempted to use `claude-opus-5`, which is outside the evaluator child-model allowlist. +- **Source:** Evaluator HTTP-boundary audit and parent stream result. +- **Expected:** Parent and all child requests remain on the approved OpenRouter evaluator model set. +- **Actual:** The parent was observed as `qwen/qwen3.8-max` from provider `Alibaba`, but the denied + child requested `claude-opus-5`; the guard aborted the run with exit code 78 before synthesis. +- **Severity:** significant +- **Action:** recover +- **Evidence:** `.llm/tmp/agentic/evaluator-policy/f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b.jsonl`; + parent session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b`; recovery brief forbids every child-agent + facility and requires single-parent synthesis on the same Qwen route. + +## 2026-08-13 — Qwen recovery transport termination + +- **What:** The single-parent Qwen recovery re-verified the NetScript claims and started the Prisma + source audit, then its local exec/PTTY transport ended with signal 15 / exit 143 before report + emission. +- **Source:** Unified exec session `30446` and the persisted recovery stream. +- **Expected:** One resumed turn completes the bounded falsification report. +- **Actual:** No second model-guard audit record exists; the run ended at a normal Qwen tool + boundary while still on `qwen/qwen3.8-max`. All completed reasoning/tool results remain in session + history. +- **Severity:** operational +- **Action:** recover +- **Evidence:** `.llm/tmp/qwen-prisma-risk-review-resume.jsonl`; evaluator audit remains a single + earlier `claude-opus-5` denial; finish brief requires immediate single-parent synthesis with no + broad re-audit. + +## 2026-08-13 — Opus background-parent bridge exit + +- **What:** The resumed native Opus background parent re-established specialist work, but the + background service exited at a bridge/task-notification boundary before synthesizing the report. +- **Source:** Native sessions `3f8a9a69-5589-4b91-9a32-91f7770fe7c2` and + `f79af5bb-e953-4aae-9585-a1c83e73a00d`, their subagent transcripts, and the unchanged placeholder. +- **Expected:** Parent remains attached after its read-only workflow fan-out and writes one report. +- **Actual:** Several specialist reports completed and are persisted, while several in-flight + children were killed; the parent disappeared from `claude agents` at the bridge boundary. +- **Severity:** operational +- **Action:** recover +- **Evidence:** Resume the same Opus 5 high evidence chain in non-background print mode, forbid all + further child facilities, and require immediate one-file synthesis. + +## 2026-08-13 — Grok 4.6 adversarial lane override + +- **What:** The owner requires Grok 4.6 high in the review loop. +- **Source:** Active owner directive and live OpenRouter model metadata. +- **Expected:** The initial optional-model note allowed Grok only if an observable compliant route + already existed; the checked-in catalog currently stops at `x-ai/grok-4.5`. +- **Actual:** OpenRouter's live `/api/v1/models` response exposes `x-ai/grok-4.6`, 500k context, and + `reasoning_effort`; the bounded OpenCode runner accepts an explicit model and high variant without + changing production harness configuration. +- **Severity:** significant +- **Action:** accept +- **Evidence:** Owner-directed post-draft adversarial lane using + `openrouter/x-ai/grok-4.6 --variant high`; capture raw route receipt and observed identity. It + runs before IMPL-EVAL and the absolute-final Fable refinement. + +## 2026-08-13 — Prisma evidence checkout moved to trash and restored + +- **What:** During terminal model synthesis, the untracked pinned Prisma source checkout was moved + from `.llm/tmp/prisma-v8-rc1` to the desktop trash. +- **Source:** Freedesktop trash metadata recorded the exact original path and deletion timestamp + `2026-08-13T18:43:58`; no matching explicit deletion command appears in the preserved lane + transcripts. +- **Expected:** The source checkout remains available through report reconciliation and evaluation. +- **Actual:** Tracked run/research files were unaffected. The checkout was immediately restored with + the recoverable trash restore operation and verified at RC tag commit + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`; post-RC main pin `71e2e0d...` remains present. +- **Severity:** operational +- **Action:** recover +- **Evidence:** `gio trash --list` original-path record; post-restore `git rev-parse HEAD` and + `git cat-file -t 71e2e0d9ee1f306b5a11435cd1973023cb33866a`. + +## 2026-08-13 — Opus monolithic report write interrupted + +- **What:** The attached non-background Opus synthesis reached “Writing the complete report now” but + the transport received signal 15 before the large `Write` tool call was emitted or persisted. +- **Source:** Native print session `f79af5bb-e953-4aae-9585-a1c83e73a00d`, exit 143 after 497845ms; + transcript ends before a report `Write` tool-use envelope. +- **Expected:** One bounded parent turn replaces the placeholder. +- **Actual:** Evidence and reasoning are preserved, but the all-or-nothing payload was not. The + placeholder remained unchanged. +- **Severity:** operational +- **Action:** recover +- **Evidence:** Resume the same Opus 5 high session for three strictly bounded single-tool writes to + one report, joined by explicit continuation markers; no additional research or subagents. + +## 2026-08-13 — Prisma evidence checkout moved to trash a second time + +- **What:** After the first safe restore, the same untracked pinned Prisma checkout was moved back + to the desktop trash at `2026-08-13T18:47:23` while delegated source audits were active. +- **Source:** `/home/codex/.local/share/Trash/info/prisma-v8-rc1.trashinfo`; the recorded original + path is `.llm/tmp/prisma-v8-rc1` and the intact checkout still resolves RC HEAD `a76a6c5...`. +- **Expected:** The restored evidence checkout remains at its run-local path. +- **Actual:** No tracked file was affected. Auditors can still read the intact recoverable trash + copy, so moving it again during their reads would create avoidable disruption. +- **Severity:** operational +- **Action:** recovered after both source audits finished. GIO no longer enumerated the intact trash + item despite its file and metadata being present, so it was moved directly back to the exact + recorded run-local path. +- **Evidence:** post-recovery `git -C .llm/tmp/prisma-v8-rc1 rev-parse HEAD` returned + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5`; `git cat-file` verified post-RC object + `71e2e0d9ee1f306b5a11435cd1973023cb33866a`. + +## 2026-08-13 — Opus bounded synthesis completed + +- **What:** The resumed native Opus report was successfully written in three bounded, marker-joined + sections after the monolithic write failure. +- **Source:** Native Claude Code session `f79af5bb-e953-4aae-9585-a1c83e73a00d`, observed model + `claude-opus-5`, effort `high`. +- **Expected:** One independent architecture report that preserves route/workflow provenance and + feeds plan lock without acting as PLAN-EVAL. +- **Actual:** `research/claude-opus-architecture-review.md` is complete at sixteen top-level + sections with no continuation marker. It records incomplete specialist lanes honestly and marks + carried Prisma claims that need the separate source-audit ledger. +- **Severity:** operational recovery +- **Action:** accept as a research input; reconcile its broader validation assumptions against the + later pinned-source validation audit before plan lock. +- **Evidence:** report section index and native turn receipts for parts 1–3. + +## 2026-08-13 — Raw RFC requires owner-directed consolidation + +- **What:** The evidence-complete authoring pass produced a 28,194-word RFC, while the owner + requires a short, specific decision document focused on API, DX, type safety, contract-first + composition, and plugin contribution. +- **Source:** Raw RFC commit `05e5fbac2`; owner direction in the active session; root review + `reviews/root-rfc-review.md`. +- **Expected:** The author brief required complete coverage but did not impose a reader-facing word + ceiling. +- **Actual:** The draft correctly preserves research and decisions but duplicates run evidence, + gates, process, and source traces that belong behind links. +- **Severity:** editorial/significant. +- **Action:** accept the raw document only as an evidence draft; resume Opus 5 high with a strict + 8,000–10,000-word target and 12,000-word hard ceiling, apply root findings R1–R10, then continue + Qwen → Grok → dispositions → final Fable review order. +- **Evidence:** `briefs/claude-opus-rfc-consolidate.md`; no architecture decision is reopened. + +## 2026-08-14 — Owner reinstated one final Fable refinement gate + +- **What:** The owner superseded the prior no-Claude/Fable directive for exactly one fresh final + Fable 5 high evaluation/refinement gate at the next midnight. +- **Expected:** The previous run-state override cancelled the originally planned Fable gate. +- **Actual:** A one-shot native Fable 5 high launch is scheduled for 2026-08-15 00:00 Europe/Zurich + through systemd user unit `netscript-db-rfc-final-fable-20260815`. +- **Severity:** significant owner override. +- **Action:** run only the persisted final-evaluator brief; prohibit subagents, workflows, resumes, + and fallback models; require a clean committed/pushed close gate. All other Claude use stays + frozen. +- **Evidence:** `briefs/fable-final-evaluator.md` and `workflows/launch-final-fable.sh`. + +## 2026-08-15 — Final Fable gate executed; verdict PASS with one refinement + +- **What:** The owner-reinstated one-shot fresh native Fable 5 high evaluator/refiner ran as the + absolute-final substantive gate, superseding the earlier Claude/Fable cancellation for exactly + this gate. The cancellation remains historical provenance; all other Claude use stays frozen. +- **Source:** Owner directive 2026-08-14; unit `netscript-db-rfc-final-fable-20260815`; + `briefs/fable-final-evaluator.md`; native session `3517a6d2-b0b5-47ec-a207-b3533657a90c`. +- **Expected:** Evaluate the checked-out RFC at the exact remote tip; refine only within D-01–D-47 + and `OWNER-DX-01`; no subagents, workflows, resumes, or fallback models. +- **Actual:** Starting commit `a7a6887c2` (verified equal to the fetched remote tip). The full RFC, + run artifacts, three reviews, and three audits were read; the load-bearing pinned RC1 claims were + independently re-verified (138 export keys, phantom type maps at `types.ts:207`, namespace + flattening, demo helper spellings). One example-level defect was found and repaired: Step 1's + `pgvector({ dimensions: 1536 })` invented an extension-level dimension option that pgvector and + the pinned demo do not have; the call is now `pgvector()` and the Step 6 declaration takes + `options?`. No decision was reopened. Verdict: **`PASS`** in `evaluate.md`; targeted fmt, + `docs:links` (103 docs, 0 broken), `git diff --check`, and fence balance all green post-edit. The + unit exited `Result=success`/status 0 with terminal reason `completed` and no permission denials; + stream receipt SHA-256 is `9939f19d8c66981eadb2589ffdce0f2a3025f24e92ebfb5982a6f24d115cdff3`; gate + `cc90ead70` was the pushed remote and live PR head at gate close. +- **Severity:** none — gate completed as authorized. +- **Action:** close the run; draft PR #1640 stays draft for owner review. +- **Evidence:** `evaluate.md`; this gate's commit on `docs/database-architecture-rfc`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md new file mode 100644 index 0000000000..dcdef85296 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/evaluate.md @@ -0,0 +1,176 @@ +# Evaluation: NetScript Database Architecture RFC — final Fable 5 high gate + +Final owner-authorized evaluation **plus refinement** gate. This session is the one-shot fresh +native Fable 5 high launch reinstated by the owner on 2026-08-14 (unit +`netscript-db-rfc-final-fable-20260815`); it supersedes the earlier Claude/Fable freeze for exactly +this gate. The evaluator read the complete RFC at the starting commit, the governing run artifacts, +the three review receipts, and the three research audits, and independently re-verified the +load-bearing pinned-source claims against the local RC1 checkout. + +## Metadata + +| Field | Value | +| --------------- | ---------------------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Target | `rfcs/0000-database-architecture.md` (canonical RFC), draft PR #1640 | +| Archetype | N/A — docs-only RFC describing the future A1/A4/A3/A2/A2/A6 graph | +| Scope overlays | `SCOPE-docs.md` | +| Evaluator | Native Claude Code · `claude-fable-5` · high · fresh session · 2026-08-15 | +| Starting commit | `a7a6887c228f2a908f8a5998129678c1f307e034` = remote tip (verified via fetch) | +| Route authority | Owner directive 2026-08-14; recorded in `drift.md` and `supervisor.md` | + +Constraints honored: no subagents, no workflows, no session resume, no fallback model. The evaluated +content is the checked-out worktree at the starting commit, not a remembered draft. + +## Process Verification + +| Check | Result | Evidence | +| -------------------------------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------- | +| Plan-Gate passed before implementation | PASS | `plan-eval.md` cycle 2 `PASS` (Fable 5 medium, session `f3286656…`, commit `383170bbc`); cycle 1 `FAIL_PLAN` preserved | +| Design section exists in worklog | PASS | `worklog.md` § Design — locked, evaluator-approved, `OWNER-DX-01` recorded as an explicit post-eval owner override | +| Commit slices match design plan | PASS | Slices 0–7 in `plan.md`/`worklog.md` match the branch history through `d28d8e779`/`a7a6887c2`; this gate is the terminal one | +| Each slice has a passing gate | PASS | `worklog.md` § Gate Results: bootstrap, compact-RFC, semantic-RFC, and final-schedule static gates all PASS with commands | +| Review chain honored | PASS | Root review → Qwen `PASS_WITH_CHANGES` → Grok `PASS_WITH_REFINEMENTS` (0 blockers) → dispositions → root semantic closure | +| Owner supersession provenance | PASS | `drift.md` 2026-08-14 entry preserves the cancellation and records this one reinstated gate | + +## Substantive Evaluation Against the Eight Focus Criteria + +1. **Layered DX as one progressive surface — PASS.** Step 2 shows L1 `defineSingleTargetDatabase` + literally calling the L2 `defineDatabase*` factories and returning the same `DatabaseDefinition`; + L3 is native Prisma plus kernel primitives with the emission/runtime module graphs honestly + split. "The normal loop has no manual type generation" commits `dev/start/test/build` to + content-hash compile, watch, verify, and atomic swap, with `db emit --verify` in CI and `db emit` + demoted to an escape hatch. A one-database app pays: one 3-line provider module, one native + contract, one L1 call — no enterprise ceremony before benefit. +2. **Prisma authority, no mirrored vocabulary — PASS.** Step 1 authors through the pinned RC1 + `defineContract(scaffold, callback)`; every helper spelling in the example was re-verified this + session against `examples/prisma-8-demo/prisma/contract.ts` in the pinned checkout + (`field.id.uuidv4String()`, `field.temporal.createdAt()`, `type.pgvector.Vector(1536)`, + `field.namedType(…).optional()`, `rel.hasMany/belongsTo` coordinates — all exact). No NetScript + schema/query DSL, no re-export, no copied overloads anywhere in the surface. +3. **Contract-first end-to-end type safety — PASS.** Erased `typeof definition` inference is the + default for app-authored spaces (backed by the phantom `_contract?: TContract` and no-emit + evidence, re-verified: `TypeMapsPhantomKey` at `2-sql/1-core/contract/src/types.ts:207`); + generated declarations are bounded to pinned artifact-only spaces and publishable exports, both + W3-proved; `FieldValueOf` keeps branded values (`Char<36>` UUID) honest at the boundary. The four + inference rules each name a conformance fixture; the one soundness seam at `runtime.bind` is + named, mitigated, and gated. +4. **One plugin contribution value fanning out — PASS.** `definePluginSpace` (Step 5) is one + callable descriptor carrying id/owner/version/capabilities/grants/policy plus a statically + imported aggregate; one `PostgresExtension` bundle registered once on the configured provider + (Step 6) fans authoring/control/runtime/validation, with `db.compose.extension.facet-mismatch` + refusing skew. Providers are composition-root values; no service locator or global registry. +5. **Validation derived where provable, fail-closed elsewhere — PASS.** Three schema classes with + distinct guarantees; operation grammar comes only from contributed packs (`ormCollection@1`) + whose identity/version enter manifest and cache key; `DB_VALIDATION_UNSUPPORTED` at construction + with coordinates; invalid values return Standard Schema issues, never throw; representations are + exactly `runtime`/`json` with driver wire internal — matching the runtime-validation source audit + §3/§4/§7 precisely (the earlier QF-05 conflation is fixed in the current text). +6. **Manifest → plan → receipt authority chain — PASS.** The six-value authority table is disjoint; + `DatabaseDefinition` is consumed only by `compileDatabase`; there is no `control.emit`; the apply + state machine, lock scope `(target, physical database)` with fencing, inspect-before-resume, and + the total two-level rollup function (mixed spaces never make a target "partially successful"; a + run with no succeeded target is never `partial-success`) are all explicit. Retained detach is a + receipt-backed, verify-only tombstone under the provider lock. PostgreSQL-first scope is honest: + SQLite/MongoDB/MySQL/MSSQL refuse with `db.target.unsupported`, and the namespace capability is + withheld on re-verified upstream evidence (`contract-types.ts:644+` flattening comment confirmed + in the pinned checkout). +7. **Clean break with adoption safety — PASS.** The no-compatibility law enumerates every banned + survival; `db adopt` is a seven-step marker-metadata-only protocol (zero application-schema DDL, + zero application-data DML) with per-target statuses, rehearsal/backup/preflight requirements, and + forward-only recovery after first apply; parallel branches without co-composition. +8. **Examples internally complete and RC1-faithful — PASS after one narrow repair.** The emitted + binding is now a real value module; `manifest`/`postgres`/`connections`/`runId`/`policy` are + bound or explicitly named across Steps 3 and 7; the configured-provider value is used + consistently at every call site. One residual defect found and fixed this session (below). The + 138-export claim was independently re-counted this session: `python3` over the pinned + `packages/9-public/@prisma/orm-postgres/package.json` returns exactly 138 export keys at + `a76a6c5` (`v8.0.0-rc.1`). + +### Prior-review disposition spot-audit + +QF-01/GR-01 (declare-only binding), QF-02/GR-02 (bundle authorship vs import law), GR-03 (per-space +evidence, no merged contract), GR-04 (emit authority), GR-05 (retained tombstone), GR-06 (rollup +totality), GR-07 (factory vs configured value), QF-04 (Prisma path attribution), and QF-05 +(paramsSchema vs conversion channels) were each re-checked in the current text and are genuinely +closed, consistent with `reviews/root-semantic-closure.md`. + +## Refinements Applied by This Gate + +| # | Location | Defect | Repair | +| - | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | +| 1 | Step 1 `database/provider.ts` | `pgvector({ dimensions: 1536 })` invented extension-level dimension configuration. pgvector has no such parameter — dimension is a per-column type modifier — and the pinned demo registers the pack with no configuration (`extensions: { pgvector }`). The duplicated `1536` invited implementing a conflicting config axis against `type.pgvector.Vector(1536)`. | `const vector = pgvector();` — dimensions now appear only in the per-column type call, as upstream. | +| 2 | Step 6 declaration | `pgvector(options: PgVectorOptions)` required an argument the corrected Step 1 call no longer passes. | `options?: PgVectorOptions` — declaration and flagship call site agree. | + +Affected end-to-end flow (Step 1 provider creation → Step 2 targets → Step 6 registration → +validation codec `pgvector.vector@1`) was reread after the edit; no cross-section contradiction was +introduced, and no prose anywhere referenced extension-level dimensions. No other correction was +warranted: no factual contradiction, incomplete value/type flow, or missing DX commitment survived +the full read. The package graph, compatibility posture, native-Prisma authority, and fail-closed +validation boundary were not reopened; D-01–D-47 and `OWNER-DX-01` are untouched. + +## Static Gates (docs-only mechanical set, run this session) + +| Gate | Command or check | Result | Evidence | +| --------------- | ----------------------------------------------------- | ------ | -------------------------------------------------------------- | +| Format | `deno fmt --check rfcs/0000-database-architecture.md` | PASS | "Checked 1 file", post-refinement | +| Link/path check | `deno task docs:links` | PASS | 103 docs, 0 broken links, 0 broken anchors, 0 enforced orphans | +| Diff hygiene | `git diff --check` | PASS | No whitespace errors | +| Fence balance | count of `` ``` `` lines | PASS | 40 fences, balanced | +| Run artifacts | `deno fmt --check` over mutated run Markdown | PASS | Recorded at commit time | +| Clean close | `git status` clean; local HEAD equals pushed remote | PASS | Recorded at commit time | + +Package/runtime E2E, publish dry-run, doc-lint, and F-1…F-19 fitness functions are **N/A** for this +docs-only RFC gate; they are named as future implementation gates in the RFC and `plan.md`, and the +RFC claims none of them have run. + +## Runtime Gates + +| Gate | Validation | Result | Evidence | +| ---------------- | ------------------- | ------ | --------------------------------------------------------------- | +| Runtime behavior | Docs-only Plan-Gate | N/A | Future A3/provider/control matrices remain explicit in the plan | + +## Consumer Gates + +| Consumer | Validation | Result | Evidence | +| ---------------------- | --------------------------------------------------- | ------ | ----------------------------------------------------------------- | +| RFC reader/implementer | Can build the system without inventing architecture | PASS | Eight-criteria evaluation above; every API/state machine is named | +| Pinned-source claims | Independent re-verification | PASS | 138 exports, phantom type maps, namespace flattening, demo shapes | + +## Anti-Pattern Check + +Docs-only scope: the RFC prescribes rejection of the applicable patterns rather than shipping code. +AP-3 (god ports — capped at 3–4 methods), AP-14 (re-export — banned with the 138-export evidence), +AP-24 (engine switch — the motivating counter-example), and AP-25 (side effects outside edges — +pure/offline split) are addressed in the text; all 25 are `N/A` as code checks for this changeset. + +## Arch-Debt Delta + +| Metric | Count | Evidence | +| --------------------- | ----- | ------------------------------------------------------------------------------- | +| New entries | 0 | Docs-only; no doctrine violation introduced | +| Resolved entries | 0 | `DB-GENERATE-ASPIRE-COUPLING` closure is _designed_ (structural), not yet coded | +| Deepened violations | 0 | — | +| Unrecorded violations | 0 | — | + +## Findings + +| Severity | Finding | Evidence | Required action | +| -------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------ | +| low | Step 1 pgvector example implied extension-level dimension configuration | Pinned demo `extensions: { pgvector }`; per-column `Vector(1536)` | Fixed this session (see above) | + +No high or medium finding. No `FAIL_RESCOPE` trigger: the package graph, clean-break posture, +native-Prisma authority, and fail-closed boundary are sound as written. + +## Lessons for Promotion + +| Lesson | Pattern | Applies to | Confidence | +| ---------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ---------- | ---------- | +| Flagship examples must not invent upstream config surfaces | Every option shown on a wrapper of a pinned upstream must exist upstream or be specified | docs runs | medium | + +## Verdict + +| Field | Value | +| --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Verdict | **PASS** | +| Rationale | The RFC is implementation-grade against all eight owner criteria: an implementer can build the layered surface, type flow, plugin fan-out, bounded validation, and control chain without inventing architecture. The single defect found was example-level, repaired within refinement authority, and all resulting docs gates are green. | diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md new file mode 100644 index 0000000000..75a68fee5b --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan-eval.md @@ -0,0 +1,195 @@ +# PLAN-EVAL — docs-database-architecture-rfc--prisma-8-rfc (cycle 2) + +- Plan evaluator session: native Claude Code, observed model `claude-fable-5`, effort `medium`, + session `f3286656-7d0f-4da2-a22d-32897a5e6482`, 2026-08-13 (UTC) +- Route: matches the required lane (`formal_plan_evaluation` — Anthropic · Fable 5 · medium); fresh + session, separate from cycle 1 (`dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`), the Codex supervisor, the + Opus research lane, the Qwen review, and every delegated research/synthesis agent +- Run: `docs-database-architecture-rfc--prisma-8-rfc` +- Worktree: `/home/codex/repos/netscript-db-rfc` +- Branch / evaluated commit: `docs/database-architecture-rfc` @ `383170bbc` + (`docs(rfc): record plan evaluation correction`) +- Surface / archetype: docs-only RFC plan under `SCOPE-docs.md`, describing future A1/A2/A3/A4/A5/A6 + surfaces +- Scope overlays: `SCOPE-docs.md`; future packages evaluated against + `gates/archetype-gate-matrix.md` +- Canonical RFC file `rfcs/0000-database-architecture.md`: **absent — correct** (verified by listing + `rfcs/`; only `0000-template.md`, `0001`–`0005`, `README.md` exist). The planned draft filename + matches the RFC process rule "keep `0000` while drafting" (`rfcs/README.md` § Lifecycle). + +## Cycle 1 disposition + +Cycle 1 (session `dd3cfbee`, evaluated commit `3cbcfcec8`) returned `FAIL_PLAN` with seven passing +boxes and one required fix: the load-bearing claim of exactly 30 generated `db:*` tasks, copied from +the Qwen independent report into `research.md`, the synthesis, and `plan.md`. The cycle 1 artifact +is preserved in commit `383170bbc` (which added it alongside the corrections) and remains audit +evidence; this file replaces it as the current verdict per the harness single-artifact contract. + +## Required-fix verification (independent) + +- **Re-executed the generator myself at head `383170bbc`.** A scratch Deno script imported + `generateDatabaseDenoJson` from + `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` and each of + `postgresProvider`, `sqliteProvider`, `mysqlProvider`, `mssqlProvider` from + `packages/cli/src/kernel/adapters/database/providers/database-providers.ts`, generated each + workspace `deno.json`, and counted keys starting with `db:`. Result: **postgres 42, sqlite 42, + mysql 42, mssql 42** — the corrected value is independently confirmed. +- **Every mutable occurrence is corrected, with no cross-workspace ambiguity.** Swept the run dir + for `exactly 30`/`30 db:`/`30 task`/`30 unique`: the only remaining occurrences are (a) the + immutable Qwen report (`research/qwen-prisma-risk-review.md:64,297`), (b) the immutable Opus + review (`claude-opus-architecture-review.md:1710,1978`) and brief + (`briefs/claude-opus-report-part-2.md:34`), and (c) the preserved cycle 1 artifact itself. The + mutable records all carry the executed result phrased per-workspace, not as a total: + `research.md:34-35` ("42 `db:*` task keys in every generated engine workspace"), + `architecture-plan-synthesis.md:70` and `:682` ("42 `db:*` task keys in every generated engine + workspace" / "the 42 per-workspace generated `db:*` task keys"), and `plan.md:310` ("the 42 + per-workspace generated `db:*` task keys"). +- **Qwen F3 is dispositioned as an incorrect correction** in `research.md:61-67` ("Corrections and + conflict resolutions"), the same way the ~275-export claim was dispositioned, and the copied + premise in the immutable Opus review/briefs is explicitly marked non-authoritative there. +- **The correction commit is properly scoped.** `383170bbc` modified only the mutable records + (`plan.md`, `research.md`, `architecture-plan-synthesis.md`, `supervisor.md`, `worklog.md`) and + added the preserved evaluator artifact/brief; no independent model report was edited + (`git show --name-status 383170bbc`). + +## Rebaseline and drift verification + +- `research.md:4-9` explicitly rebaselines to `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` + with Prisma pins RC1 `a76a6c5` and post-RC object `71e2e0d9…`. Verified: `cd720529` is an ancestor + of HEAD; the pinned checkout at `.llm/tmp/prisma-v8-rc1` resolves HEAD + `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` and `git cat-file -t 71e2e0d9…` returns `commit`. +- Fetched `origin/main`: it has advanced by **exactly one commit**, + `01e096049 ci: adopt structured check reports (#1639)`. I inspected its full file list and the + diffs to the two database-adjacent files it touches: + `packages/cli/e2e/src/application/gates/ + scaffold/database-gates.ts` changes only how the E2E + suite invokes generated-workspace type checks (gate mechanics, not scaffold output), and root + `deno.json` changes wrapper permission flags for structured check reports. It touches no + `packages/database`, no `packages/cli/src/kernel/adapters|templates/database`, no doctrine, no + `rfcs/`. It invalidates no research, plan, archetype, gate, or RFC-authoring premise; the plan's + committed "fresh pin check during RFC drafting" (plan.md § Dependencies and Drift Watch) covers + residual drift. **Non-blocking.** + +## Spot-checks of load-bearing findings (this cycle's independent set) + +1. **Current NetScript facts.** + - `resolveTarget` defaults only with exactly one enabled target and never consults + `PrimaryDatabase` — confirmed at + `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66-91` (matching on + `configKey`/`databaseName` only; zero `PrimaryDatabase` references in the file). + - Plugin schema contribution is file copy plus regex declaration scanning — confirmed: + `packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts:13` defines the + `model|enum|type|view` header regex; `prisma-schema-writer.ts:19,100-122` performs the + collision check by scanned declaration name (research finding 3). + - Generated templates pin `npm:prisma@^7.4.2` (`generate-db-deno-json.ts:36,56,59,61,67`) while + the root catalog pins `@prisma/*` at `^7.8.0` (`deno.json:231-236`) — the version-skew claim + holds. + - AP-17 debt is stale on its rename half — `packages/database/ports/` exists while + `.llm/harness/debt/arch-debt.md:316-324` still says "`interfaces/` should become `ports/`"; + `DB-GENERATE-ASPIRE-COUPLING` remains open at `arch-debt.md:1954` and describes + `DbOperationRunner.executeDetached` always booting Aspire — matching the plan's doctrine/debt + section and D-26. +2. **Pinned Prisma RC/current-source facts.** + - Model-first authoring (D-06/D-36): confirmed at + `.llm/tmp/prisma-v8-rc1/packages/3-extensions/postgres/src/contract/define-contract.ts:91-105` + — `defineContract(scaffold, factory)` with `const` generics preserving literal + types/models/enums; no fluent target/table/column chain. + - Namespace type-map flattening (D-37): confirmed at + `.llm/tmp/prisma-v8-rc1/packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-691` — + comments state the authoring path "lumps every model under the default storage namespace", and + non-default namespaces receive `entries.table: Record`. Withholding the + multi-namespace capability claim is well-founded. + - `@prisma/orm-postgres` export breadth: counted `Object.keys(exports)` of + `packages/9-public/@prisma/orm-postgres/package.json` at the pin — **138**, matching + `prisma-8-deep-dive.md:98` and the synthesis's correction of Qwen's ~275. +3. **Doctrine / JSR / package-boundary facts.** + - `isolatedDeclarations: true` at root `deno.json:174`. + - Slow-type exception is sanctioned only for oRPC-bound packages + (`docs/architecture/doctrine/02-public-surface.md:217-240`); the planned JSR audit's rule that + no database package inherits it (`planned-jsr-audit.md:41-45`) is consistent. + - Doctrine codifies plain `*.prisma` plugin fragments (`06-archetypes.md:209-211`) and contains + zero references to `database-contract|database-runtime|database-control` in `06-archetypes.md` + or `10-codebase-verdict-and-handoff.md` — the plan's W0 doctrine-amendment obligation is + correct and required. + +## Checklist results + +| Plan-Gate item | Result | Evidence / location | +| --------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Research present and current | PASS | `research.md` exists, rebaselined to `cd720529` with pinned Prisma sources; #313 carried as historical evidence only; the cycle 1 false count is corrected to the executed 42-per-workspace result in every mutable record, with Qwen F3 dispositioned (`research.md:61-67`); the one-commit main delta is CI/gate tooling and invalidates nothing. | +| Decisions locked | PASS | plan.md § Locked Decision Ledger D-01–D-47 with rationale; expanded rationale in `architecture-plan-synthesis.md` §13; the two tables are coherent (statuses match; no contradiction found). | +| Open-decision sweep | PASS | plan.md § Open-Decision Sweep (must-resolve-now: none; per-wave W1/W3/W4/W5/W7/W10 items; safe-to-defer list). My independent sweep (below) found no unflagged rework-forcing decision. | +| Commit slices (< 30, gate + files each) | PASS | plan.md § RFC Commit Slices: eight ordered slices (0–7), each naming what it proves, its gate, and its files; mirrored in `worklog.md` § Commit Slices. | +| Risk register | PASS | plan.md § Risk Register: 20 risks each with mitigation/kill response; § Kill and Switch Criteria adds adapter/subsystem/architecture kill tiers. | +| Gate set selected | PASS | plan.md § Gate Set: current docs/RFC gates match `SCOPE-docs.md` (source alignment, link integrity, terminology, drift log, fmt/diff); future units mapped to F-1…F-19 per `gates/archetype-gate-matrix.md`; A3 runtime gates required (matrix: F-13 + runtime/Aspire validation required for Arch 3); release-gate class at W10. | +| Deferred scope explicit | PASS | plan.md § Deferred Implementation Scope, § Open-Decision Sweep "Safe to defer", and the § Non-Scope refusal boundary. | +| jsr-audit surface scan (pkg/plugin) | PASS | `research/planned-jsr-audit.md`: verdict `PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS`; dry-run/doc-lint/packed/canary honestly **N/A** because the six packages do not exist; named risks (slow types, re-export, self-import, generated assets, duplicate Prisma components) each map to W1–W10 gates and kill criteria. | + +## Directed challenges (per evaluator brief) + +- **D-35 (production plan signatures, W5/W10).** Public semantics are locked: `ExecutablePlan` is a + signed/versioned value, the plan-status vocabulary includes approved/signature states, and + signature policy enters only through an explicit port ("Clock/ID/signature policy" in the + consumed-ports list). Only mechanism/algorithm/key custody is deferred, and W1 locks + manifest/digest format-versioning first, so a later custody choice cannot rewrite package + boundaries. **Deferral safe.** +- **D-37 (multi-namespace withheld).** Independently re-verified against the pinned source (above). + The kernel keeps `NamespaceRef` as a first-class identity axis; only the adapter capability claim + is withheld, with an explicit no-cast rule and a conformance parity gate. If upstream never fixes + the flattening, the kernel carries an unused axis — no rework. **Conditional classification + correct.** +- **D-41 (Prisma import allowlist/compat window, W3).** Adapter-local by construction: the + dependency law keeps every kernel package Prisma-free, the adapter stays experimental until W3 + gates pass, and the kill criteria keep W1–W2 valid if the adapter dies. Post-RC path churn is + documented (`prisma-8-deep-dive.md` § "Six days of post-RC churn"), which is exactly why pinning + the spelling now would design to a moving surface. **Deferral safe.** +- **D-42 (advisory vs fenced-row lock).** Public lock semantics (owner, nonce, fencing evidence + where used, timeout/force-unlock preconditions, refusal of uncertified adapters for + concurrent-safe apply) are locked; only the per-provider mechanism is conformance-driven. + **Deferral safe.** +- **D-01–D-47 existence/coherence.** All 47 present in plan.md § Locked Decision Ledger; + classifications match `architecture-plan-synthesis.md` §13 (Locked / Pre-implementation W3–W10 / + Conditional / Deferred) line for line. No contradiction between ledger, open-decision sweep, and + wave exits. +- **Package graph.** Each unit has exactly one archetype; runtime is explicitly A3 with required + runtime gates. The dependency law forbids kernel→provider imports; concrete Prisma types are + adapter-local; app-specific inferred bindings are generated app-local, consistent with + `isolatedDeclarations` and the oRPC-only slow-type exception. No provider/query/slow-type leak + path found. The testkit A6-vs-subpath question is explicitly bounded ("reconsider before W1"), + pre-publication, and cannot rework other units. +- **Clean-break/data-safety, builder strategy, validation, lifecycle, recovery, waves, ordering.** + Adoption is marker-only (zero DDL/DML) with hard-stop on unattributed objects, a seeded + production-shaped rehearsal gate, and forward-only recovery after first apply (synthesis §11); the + native-builder strategy matches the pinned source; validation is bounded with enumerated + fail-closed `DB_VALIDATION_UNSUPPORTED` cases and construction-time refusal; plugin removal + guarantees only detach-and-retain; multi-target apply is a saga with `outcome-unknown` and + inspect-before-resume; W0–W11 have explicit dependencies and exit evidence; slice 7 keeps + owner-directed Fable 5 high as the absolute last substantive gate with only mechanical checks + after. Coherent; no unstated open decision found. + +## Open-decision sweep (evaluator-run) + +No unflagged decision that would force rework if deferred. Candidates examined and dismissed: +testkit package-vs-subpath (flagged, bounded before W1, pre-publication); manifest/digest encoding +(W1-first, format-versioned); Grok 4.6 route availability for slice 5 (operational lane dependency +with live-route evidence in `supervisor.md`, not an architecture decision); RFC +tracking-issue/label/FCP mechanics from `rfcs/README.md` (implementation-time process owned by +`netscript-pr`; the planned `0000-database-architecture.md` filename already complies with the +draft-numbering rule); context-pack staleness (artifact hygiene, not a decision — see Notes). + +## Verdict + +`PASS` + +## Notes + +- Non-blocking hygiene: `context-pack.md` is stale (phase still `research`; its archetype line omits + A3). It is not a Plan-Gate box, but it should be refreshed with the next slice commit so the run + stays resumable, per the harness per-slice artifact rule. +- Non-blocking: `origin/main` advanced by one CI/gate-tooling commit (`01e096049`) after the + rebaseline; independently inspected and found to touch no premise of this plan. The plan's + committed fresh pin check during RFC drafting covers it. +- Per the hard stop: canonical RFC authorship (slice 3) may begin; slices must follow the locked + order, and Fable 5 high remains the final substantive gate. + +PLAN-EVAL: PASS diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md new file mode 100644 index 0000000000..e9d40d98b3 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md @@ -0,0 +1,548 @@ +# Plan: NetScript Database Architecture and Prisma 8 + +## Run Metadata + +| Field | Value | +| ------------------- | -------------------------------------------------------------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | +| Phase | `final-verification` | +| Target | `rfcs/0000-database-architecture.md` plus harness provenance; semantic closure is pushed at `d28d8e779` | +| Current changeset | Documentation/RFC under `SCOPE-docs.md` | +| Future architecture | A1 contract, A2 control/provider integrations, A3 runtime, A4 definition/plugin DSL, A5 thin plugins, A6 testkit/CLI | + +## Goal + +Produce an implementation-grade, clean-break database architecture RFC whose first certified +provider is Prisma 8 PostgreSQL, while NetScript owns a provider-neutral composition, contribution, +runtime-lifecycle, validation, and operations system. The experience must eliminate copied schemas, +manually synchronized types, hand-wired clients/adapters, textual generated-source repair, implicit +target selection, Aspire-coupled pure work, terminal-log contracts, and hand-maintained agent +instructions. Adoption must follow NetScript's established progression: an L1 preset/recipe for the +golden path, the L2 public factories it uses, and L3 native Prisma plus NetScript primitives/ports; +source-native app inference is preferred over generated TypeScript bindings. + +## Plan-Eval Disposition + +Cycle 1 (`dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22`, commit `3cbcfcec8`) returned `FAIL_PLAN` solely for +the copied claim of 30 generated `db:*` tasks. Executing the generator established the corrected +finding: **42 `db:*` keys per generated engine workspace** for each of PostgreSQL, SQLite, MySQL, +and MSSQL. Independent reports remain immutable; mutable planning records carry the correction. + +Fresh cycle 2 used native Fable 5 medium session `f3286656-7d0f-4da2-a22d-32897a5e6482` against +commit `383170bbc` and returned **`PASS`**. Canonical RFC authorship is therefore unblocked. No +additional PLAN-EVAL cycle is requested. `origin/main` has since advanced by one nonblocking +CI/gate-tooling commit (`01e096049`); the evaluator found no architecture, database, doctrine, or +RFC premise invalidated, and the existing fresh-pin drift watch remains sufficient. + +After that pass, the owner issued `OWNER-DX-01`: the accepted architecture must expose NetScript's +existing layered adoption pattern and must not assume generated app type bindings are inevitable. +This is an explicit owner override to D-07/D-08/D-36, not a new PLAN-EVAL cycle; no further +PLAN-EVAL will run. The completed author/editor pass selected the layered API and source-native +versus fallback type boundary. The owner subsequently removed every word-count acceptance target and +stopped all further Claude/Fable usage. Root applied the remaining semantic corrections, and three +non-Claude closure lanes passed the resulting RFC at `d28d8e779`. + +## Scope + +- Current-state, failure-history, doctrine/debt, Prisma RC/current-source, market, and agent-surface + evidence. +- Exact durable vocabulary, artifact taxonomy, package/archetype/dependency graph, public versus + adapter-local ownership, and refusal boundaries. +- Current model-first native Prisma TypeScript authoring, const-preserving app/plugin composition, + contract spaces, extension bundles, layered adoption, source-native app-local inference with a + bounded automatic declaration fallback, and an E2E type flow. +- Bounded contract-derived Standard Schema validation for runtime and JSON representations, + selection-aware results, codec contributions, fail-closed semantics, caching, and optional AOT + equivalence. +- Multiple explicitly named targets, same-provider isolation, namespaces with honest capability + gating, ownership policy, provider/runtime modes, and plugin lifecycle. +- Programmatic operation catalog, deterministic manifest, preview/plan/apply/verify state machines, + provider locking, receipts, partial/unknown outcomes, resume, CI determinism, and generated agent + surface. +- Clean adoption of populated databases, no-compat cutover, parallel branch/release-line strategy, + implementation waves, conformance/release gates, kill criteria, and migration documentation. +- Required doctrine and debt consequences for the future implementation program. + +## Non-Scope and Refusal Boundary + +- Production package, CLI, plugin, or provider implementation in this RFC PR. +- Any backward-compatible facade, Prisma 7 client, legacy generated module, alias barrel, dual + migration history, `setClient`, copied fragment, or runtime shim. +- A mirrored Prisma model/field/relation/query DSL, generic repository, ORM, or + lowest-common-denominator portability API. NetScript presets/factories may orchestrate identity, + policy, lifecycle, artifacts, extensions, and validation around the native contract. +- Recreating Prisma's obsolete target/table/column fluent builder, copying private types/overloads, + or re-exporting Prisma as though NetScript owns it. +- Runtime capability negotiation; capabilities are declared static data. +- Cross-database foreign keys, transparent joins, atomic transactions, or automatic rollback. +- Hosted control-plane products: RBAC, approval workflow, registries/promotion, fleet schedulers, + continuous drift agents, KMS/secrets, notifications, or permanent audit servers. +- Claims that Prisma SQLite, MongoDB, MySQL, SQL Server, multi-namespace E2E typing, plugin + archive/drop, AOT validation, or moving raw/prepared/aggregate conveniences are implemented. + +## Doctrine Verdict and Axioms + +The current `packages/database` is an A2 integration package marked Refactor. Its recorded AP-17 +`interfaces/` rename is stale because source now uses `ports/`; the composition-root question is +still relevant. `DB-GENERATE-ASPIRE-COUPLING` is open and is closed structurally when pure +operations cannot resolve Aspire. Auth roadmap R1 independently requires deterministic plugin-aware +schema/migration automation and must converge on contract spaces rather than an auth-only generator. + +Doctrine currently codifies plain `*.prisma` plugin fragments and does not register the proposed +packages in its gated denominator. The implementation program must amend +`docs/architecture/doctrine/06-archetypes.md` and `10-codebase-verdict-and-handoff.md` before new +packages land. This RFC records the target; it does not mutate doctrine before acceptance. + +| Axiom | Application | +| ----- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| A1 | Public data/types and README examples precede implementation. | +| A2 | NetScript's stable surface stays smaller than Prisma internals. | +| A3 | The common author/compose/emit/plan/apply path is one deterministic flow. | +| A5 | Targets, spaces, providers, extensions, runtime modes, and validators compose without inheritance. | +| A7 | Wrap Prisma and Standard Schema; do not rebuild an ORM or validator ecosystem. | +| A8 | Definition, runtime, control, provider, and tooling responsibilities live in separate role-named packages/folders. | +| A9 | Each future package has exactly one archetype; runtime is explicitly A3. | +| A10 | Application composition roots bind providers/targets; no global registry/service locator. | +| A11 | Extension axes are named as target, role, namespace, space, provider, capability, connection source, runtime scope, and validation representation. | +| A12 | Plan/apply/recovery, contribution lifecycle, and multi-target execution are explicit state machines. | +| A13 | Runtime/control crash boundaries, cancellation, unknown outcomes, and supervision are explicit. | +| A14 | Conformance, publish, generated-project, journey, and release gates preserve the design. | + +Applicable anti-patterns include AP-3 god ports, AP-4 cross-package implementation inheritance, AP-9 +premature abstraction, AP-14 upstream re-export, AP-17 stale folder/debt tracking, AP-18 giant +generated snapshots, AP-24 engine switches, and AP-25 side effects outside edges. The RFC must also +reject service-location, widened native-fragment registries, source-text repair, message-string gate +assertions, implicit fallback selection, and arbitrary schema TypeScript during production apply. + +## Locked Vocabulary and Artifact Taxonomy + +| Term | Locked meaning | +| ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Pure authored TypeScript composition of targets, spaces, connection-source references, policies, and native contracts. | +| `NativeContract` | Provider-owned authored value, initially Prisma's model-first `defineContract` result. | +| `SpaceContribution` | Declarative owner/version/dependency/capability/provenance/retention record for one contract space. | +| `ContractArtifact` | Canonical provider contract data/declaration, lineage, and provenance pinned per space. | +| `DatabaseManifest` | Deterministic, versioned, content-addressed resolved snapshot; the durable join point. A graph is private compiler IR only. | +| `AppBinding` | Application-local inferred bridge to sessions/validators: source-native by default; an atomic declaration is a bounded fallback. | +| `TargetRef` / `TargetSession` | Explicit target reference and process/request lifecycle shell; concrete provider query type is app-local. | +| `SpeculativePreview` | Advisory output that cannot be approved or applied. | +| `ExecutablePlan` | Expiring plan bound to manifest, target/space closure, live baseline, provider pins, policy, environment, and secret references. | +| `ProviderMarker` / `ProviderLedger` | Provider-owned authoritative applied migration state; not duplicated as NetScript mutable state. | +| `OperationReceipt` | Immutable evidence/checkpoints, not desired state or a shadow database. | +| `OperationCatalog` | Machine names/classes/request/result/diagnostic/next-action catalog; CLI/docs/agents are projections. | +| `ValidationIR` | Internal bounded value/selection algebra producing Standard Schema values; never a second entity/query model. | + +Declared identities are `TargetId`, `RoleRef`, `NamespaceRef`, `SpaceId`, `ObjectKey`, +`ContractSnapshotId`, `ManifestDigest`, `PlanId`, `RunId`, and `ReceiptId`. Provider names, engine +names, paths, config aliases, array order, traversal order, and discovery order are never identities +or dependency edges. + +## Exact Future Package and Dependency Graph + +| Unit | Archetype | Owns | Must not own | +| ------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------- | +| `@netscript/database-contract` | A1 | Plain identities, manifests/plans/receipts/diagnostics, capabilities, ownership, shared small SPIs. | IO, query types, provider imports. | +| `@netscript/database` | A4 | L1 database preset/recipe, L2 `defineDatabase`/target/space/policy factories, pure compiler/resolver, frozen definitions. | Connections, provider/Aspire imports, execution. | +| `@netscript/database-runtime` | A3 | Process/request lifecycle, binding, connection ownership, health/readiness, cancellation, validation coordination. | Migration orchestration, CLI, provider query vocabulary. | +| `@netscript/database-control` | A2 | Programmatic classify/compose/emit/preview/plan/apply/verify/inspect, provider ports, locks, receipts, recovery, cross-target saga. | Provider SQL/AST/types, terminal text, CLI rendering. | +| `@netscript/database-prisma-postgres` | A2 | Sole framework runtime/control Prisma boundary, capability descriptor, artifact/control/runtime/validation adapters, import allowlist. | Prisma re-export, private-type public surface, hand-written low-level driver. | +| `@netscript/database-testkit` | A6 | Runnable provider/space certification and machine reports if a binary is justified. | Application runtime dependency. Reconsider split before W1 if no binary exists. | +| `@netscript/plugin` | Existing A4 | Plain `defineDatabaseSpace` contribution seam and legacy-surface removal. | Provider/runtime/control dependency. | +| First-party `plugins/*` | Existing A5 | Thin descriptors and generated contract/lineage assets sourced from `-core`. | Copied app schema or convention-bearing DB implementation. | +| `@netscript/aspire` | Existing A2 | Narrow connection-source/provisioning adapter. | Requirement for pure/non-Aspire operations. | +| `@netscript/cli` | Existing A6 | Operation-catalog projection, adoption codemod, generated help/agent assets. | Database/provider business logic. | + +Dependency law: + +```text +@netscript/database-contract + <- @netscript/database + <- @netscript/database-runtime + <- @netscript/database-control + <- @netscript/plugin + +chosen provider implements runtime/control SPIs and is supplied by the app composition root +@netscript/database-testkit may depend on all public SPIs; no runtime package depends on it +application/plugin controlled-build schema modules may import Prisma's public authoring builder +``` + +No framework package re-exports Prisma. Runtime/control Prisma imports exist only inside the +PostgreSQL adapter. App/plugin native authoring imports are controlled build inputs; deployments use +their plain canonical artifacts. + +## Public Surfaces, Ports, and Closed Vocabularies + +### Public surfaces + +- Candidate A is the baseline: native current model-first Prisma `defineContract`, then thin + `defineDatabase({ contract, ... })` or `defineDatabaseSpace({ contract, ... })` preserving + `typeof contract` unchanged. +- The adoption surface is L1 preset/recipe → L2 public factories → L3 native Prisma plus NetScript + primitives/ports. L1 literally composes L2 and returns the same definition; neither layer mirrors + Prisma schema/query vocabulary. Exact API spelling is settled by the Opus author/editor pass. +- Any optional policy factory dies if it forwards/copies native helpers, needs private imports or + copied overloads, or widens inference. +- `ownership: app` fragments return const-preserved native builder values and are composed by an + explicit source root; generation is reserved for a proved artifact boundary. `ownership: space` + contributions own a full contract artifact and migration head; this is the default for + plugin-owned tables. +- One identity/version-checked `DatabaseExtension` bundle fans authoring, control, runtime, and + validation facets through two-phase collection. +- `TargetRef`/session handles expose lifecycle and a narrow query generic. Application-owned stores + receive concrete sessions at composition roots; NetScript does not generate repositories. +- Standard Schema is public. Schema classes are model value, explicitly contributed operation input, + and fully known selection/result. Public representations are `runtime` and `json`. +- Control requests/results/plans/receipts/diagnostics are plain NetScript data. Human CLI text is + never a contract. + +### Consumed ports + +Each port stays at three or four cohesive methods and has at least two exercised implementations or +a concrete external seam: + +- `ContractArtifactSource` / atomic artifact publisher for controlled native evaluation and pinned + mirrors. +- `ProviderRuntimeFactory` for scope-correct sessions and lifecycle. +- `ProviderControl` for emit/inspect/plan/apply/verify translation. +- `ConnectionSource` for environment/Aspire/secret-reference resolution. +- `MigrationLock`/provider lock capability with owner/nonce/fencing evidence. +- `ReceiptSink` for atomic immutable checkpoint evidence. +- `Clock`/ID/signature policy only where deterministic testing or production approval requires it. + +Provider registries are immutable composition-root values, not public global registries. Concrete +Prisma control/runtime/contract/codec/AST shapes stay adapter-local. + +### Closed vocabularies + +- Ownership: `managed`, `adopted`, `external`, `ignored`. +- Runtime scope: `process`, `request`. +- Validation representation: `runtime`, `json`; driver wire is internal. +- Operation class: `pure`, `live-read`, `mutating`, `resident`. +- Plan status: speculative, inspected, planned, policy-refused/allowed, approved, ready, expired, + stale, revoked. +- Receipt phases/outcomes: planned, acquiring-lock, locked, revalidating, started, applying, + applied, verifying, verified, succeeded, refused, skipped, failed, partial-success, + cleanup-required, outcome-unknown, cancelled. +- Ownership/removal initial guarantee: detach-and-retain; archive/drop are capability-conditional. +- Capabilities are open namespaced IDs but static declared data; no runtime negotiation protocol. + +## Locked Decision Ledger + +| ID | Decision | Status | +| ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | +| D-01 | Clean break; no backward-compatibility API/runtime surface. | Locked | +| D-02 | Data continuity and mechanical migration are mandatory. | Locked | +| D-03 | Durable join point is `DatabaseManifest`; live graph is private compiler IR. | Locked | +| D-04 | Definition, manifest, executable plan, provider ledger, and receipt remain separate values. | Locked | +| D-05 | NetScript defines no query DSL, repository, or portable client facade. | Locked | +| D-06 | Current native model-first Prisma TypeScript authoring is primary; obsolete fluent chaining is not recreated. | Locked; import spelling adapter-pinned | +| D-07 | Candidate A uses L1 preset/recipe → L2 public factories → L3 native Prisma + NetScript primitives; no mirrored Prisma schema/query DSL. | Owner override; locked | +| D-08 | App-owned contracts prefer erased `typeof definition` inference while runtime consumes artifacts; atomic launcher-integrated declarations are a W3-proven publish/artifact-only fallback. | Owner override; locked | +| D-09 | Package/archetype graph above is exact; runtime is A3. | Locked | +| D-10 | Kernel is provider-neutral; first certified adapter is Prisma 8 PostgreSQL only. | Locked | +| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | Locked | +| D-12 | Capabilities are static tags/requirements, never runtime negotiation. | Locked | +| D-13 | Provider registry is composition-root data, never global/public mutable state. | Locked | +| D-14 | Stable target ID owns connection, output, runtime, migrations, locks, and receipts. | Locked | +| D-15 | Target selection is explicit, dependency-closed, and records every omission/reason. | Locked | +| D-16 | Replicas are roles of a target, never migration targets. | Locked | +| D-17 | Provider-native contract spaces plus NetScript policy replace copied fragments. | Locked | +| D-18 | One managed owner per `ObjectKey`; augmentation requires owner grant. | Locked | +| D-19 | Pinned mirrors make apply/verify independent of installed plugin code. | Locked | +| D-20 | Detach-and-retain is guaranteed removal; archive/drop are conditional. | Locked | +| D-21 | Standard Schema is public; bounded runtime interpretation is default. | Locked | +| D-22 | Public validation representations are `runtime` and `json`; driver wire is internal. | Locked | +| D-23 | Complete Prisma operation validation is not contract-derived; exact operation contributors are required. | Locked | +| D-24 | Unknown validation metadata fails while constructing the schema. | Locked | +| D-25 | Optional AOT validation is corpus-equivalent only and never required. | Locked | +| D-26 | Pure operations cannot resolve connections, Aspire, Docker, or network. | Locked | +| D-27 | Programmatic operation catalog is primary; CLI/docs/agents are generated projections. | Locked | +| D-28 | Preview is not executable plan; apply accepts only bound/revalidated plans. | Locked | +| D-29 | NetScript owns policy/lock/recovery/receipts/cross-target saga; provider owns diff/lineage/marker mechanics. | Locked | +| D-30 | Cross-target apply is never atomic; partial and unknown outcomes are first-class. | Locked | +| D-31 | Local kernel does not rebuild hosted registry/RBAC/fleet/drift products. | Locked | +| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | Locked | +| D-33 | Agent instructions/catalogs are generated and every example executes. | Locked | +| D-34 | Existing MySQL/MSSQL/SQLite support is not carried through compatibility code. | Locked | +| D-35 | Production plans require signatures; mechanism/key custody is selected before production cutover. | Pre-implementation W5/W10 | +| D-36 | Prisma's model-first builder remains authority; progressive NetScript layers orchestrate seams without re-export, copied overloads, private types, or widening. | Owner override; exact RC/GA path W3 | +| D-37 | Multi-namespace adapter capability is withheld while Prisma type maps flatten runtime namespaces; no cast workaround. | Conditional upstream block | +| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin tables default to full space ownership. | Locked | +| D-39 | One extension bundle supplies identity-matched authoring/control/runtime/validation facets. | Locked | +| D-40 | CI/production migration and runtime consume canonical verified artifacts, not arbitrary schema TypeScript. | Locked | +| D-41 | Exact Prisma control/runtime import allowlist and compatibility window are selected in W3. | Pre-implementation W3 | +| D-42 | Native advisory versus fenced-row lock is certified per provider. | Pre-implementation provider detail | +| D-43 | Whether AOT validation ships is safe to defer. | Deferred | +| D-44 | A real second provider is safe to defer. | Deferred | +| D-45 | Public raw/prepared/aggregate conveniences are safe to defer/keep adapter-local. | Deferred | +| D-46 | Archive/drop plugin retirement in v1 is safe to defer. | Deferred | +| D-47 | Remote approval/registry/continuous-drift integrations are safe to defer. | Deferred | + +No must-resolve-now decision remains. Pre-implementation items have stable public semantics and +cannot force a package-boundary rewrite. D-37 withholds a capability claim rather than blocking the +provider-neutral architecture. `OWNER-DX-01` explicitly overrides D-07/D-08/D-36 after PLAN-EVAL; it +does not start another evaluator cycle or alter the other decisions or six-package graph. + +## Control and Contribution State Machines + +- Composition: authored → resolving → resolved(manifest, warnings) or refused(diagnostics), as a + pure total `Result`. +- Planning: resolved → speculative preview or baseline inspection → executable plan → policy → + approval/signature → ready, with expired/stale/revoked refusal branches. +- Apply: planned → lock → revalidate → start → checkpoint each irreversible step/group → applied → + verify → succeeded; refusal, skip, failure, partial-success, cleanup-required, cancellation, and + outcome-unknown are explicit. +- Resume always inspects live state/provider ledger and revalidates bindings before action; it never + blindly replays unknown non-idempotent work. +- Multi-target execution is a dependency-ordered saga with separate runners/locks and complete + per-target/per-space outcomes. +- Contribution lifecycle: install, upgrade, skew refusal, detach, retain, conditional archive/drop. + App-owned fragments compose into the app space; plugin-owned tables default to full spaces with + independent artifacts/heads. Extension facets install as one identity/version-checked bundle. + +## Runtime Validation Boundary + +The internal supported algebra is registered scalar codecs, nullability, lists, dictionaries, value +objects, resolvable unions, value sets/enums/native enums, integrity-checked cross-space relations, +whole-model values with explicit presence policy, and direct-column result projections with complete +alias/codec/nullability/representation metadata. + +Construction fails with stable `DB_VALIDATION_UNSUPPORTED` coordinates for unknown/missing codec +schemas, pack kinds, cross-space refs/heads, ambiguous unions/variants, missing Prisma operation +grammar, computed/subquery/raw/aggregate/include/unknown results, opaque checks, database-state +constraints, and incompatible async predicates. Invalid values return Standard Schema issues; they +do not throw. Cache identity includes canonical full-contract digest, schema version, space, +target/family, normalized operation/selection, representation, interpreter ABI, codec/pack +identity/version, and execution identity when defaults matter. + +## Provider and Target Matrix + +| Case | Architecture | First adapter claim | +| -------------------------------------- | -------------------------------------------------------------------- | --------------------------------------------------------- | +| Two PostgreSQL databases | Named targets with isolated artifacts/runtime/ledger/locks/receipts. | Required. | +| Multiple PostgreSQL namespaces | First-class kernel axis. | Withheld until no-cast Prisma type/runtime parity passes. | +| Writer/read replicas | Roles on one target. | Conditional runtime capability; readers cannot migrate. | +| App plus plugin spaces | Independent ownership/artifacts/heads/dependency order. | Required. | +| Managed/adopted/external/ignored | Ownership-aware plan/verify/drift. | Required. | +| Process/request scope | Distinct lifecycle/capability types. | Required. | +| Prisma SQLite/MongoDB/MySQL/SQL Server | Provider/family axis remains open. | Explicitly unsupported/deferred; no fallback. | +| Cross-target relation/transaction | Not representable. | Structured composition refusal. | +| Provider-specific queries | Native app-local provider surface. | No portable wrapper. | + +## Clean Cutover + +`netscript db adopt` is a temporary codemod/tool, not compatibility. It reads legacy config/layout, +generates explicit target definitions from config keys, introspects reachable databases, proposes +object ownership, hard-stops on unattributed objects, compiles/emits canonical artifacts, writes +baseline marker metadata only, verifies zero drift, and then deletes the old engine workspaces, the +42 per-workspace generated `db:*` task keys, copied fragments, repair scripts, adapters, and +dependencies. Baseline establishment performs zero table/data DDL/DML. + +Old/new stacks may coexist on separate branches/release lines while features are developed, but one +application never composes both. Before first new apply, rollback is repository-only plus idempotent +marker cleanup where supported. After apply, recovery is forward via lineage and receipts. + +## Implementation Waves + +| Wave | Scope | Dependency | Exit evidence | +| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | --------------------------------------------------------------------------------------------------------- | +| W0 | Accepted RFC, doctrine/verdict amendments planned, package/gate registration. | — | RFC gates and architecture acceptance. | +| W1 | A1 contract kernel. | W0 | Zero-provider-dependency publish/doc/consumer gates. | +| W2 | A4 definition/compiler and manifest invariants. | W1 | Pure deterministic property/negative tests; no IO. | +| W3 | Experimental Prisma PostgreSQL spike: native builder, layered API, source-native inference/fallback boundary, artifacts, spaces/extensions, validation, Deno/namespaces. | W1–W2 | Direct-erasure and fallback fixtures, real PostgreSQL, packed Deno, import allowlist, kill/switch review. | +| W4 | A3 runtime, manifest-only consumption, typed adapter binding, and Aspire connection adapter. | W1–W3 | Lifecycle/leak/cancellation/scope/validation and no-authoring-runtime-import gates. | +| W5 | A2 control, plans, locks, receipts, recovery, cross-target saga. | W1–W4 | Failure injection, atomic emit, pure path without Aspire. | +| W6 | A6 provider/space conformance testkit. | W1–W5 | Intentionally broken fixtures fail; real-service machine report. | +| W7 | `@netscript/plugin` contribution seam and first plugin-core fixture. | W1–W6 | Breaking surface and thinness/seam/package-free gates. | +| W8 | CLI/agent/adoption projection plus launcher-integrated atomic emit/watch/bind. | W2, W5–W7 | Golden-path examples, catalog freshness, stale auto-remediation, populated adoption preflight. | +| W9 | First-party auth/workers/sagas/triggers spaces. | W7–W8 | Each space certified; package-free apply/verify and runtime parity. | +| W10 | Clean cutover and legacy deletion. | W1–W9 | Full release class, Windows/Linux, production-shaped adoption, remote published E2E. | +| W11 | Second real provider only when demanded/mature. | W10 | Same provider/layer conformance; no kernel, manifest, or L1/L2 public rewrite. | + +## RFC Commit Slices + +| # | Slice and proof | Gate | Files | +| - | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | +| 0 | Harness bootstrap and draft review surface. | Artifact presence, scoped format/diff; already landed. | Run root artifacts. | +| 1 | Current research corpus and Plan-Gate lock are complete. | Research/source/claim index, planned JSR audit, scoped format/diff, PLAN-EVAL input completeness. | `research.md`, `research/*.md`, `plan.md`, `worklog.md`, `context-pack.md`, `drift.md`. | +| 2 | Independent PLAN-EVAL accepts the locked plan before RFC authorship. | Fresh separate-session evaluator `PASS`. | `plan-eval.md`, planning artifacts only. | +| 3 | Canonical RFC defines vocabulary, APIs, package graph, TypeScript/E2E types, validation, control, contributions, providers, and refusal boundary. | Source alignment, local-link/terminology/docs format, decision coverage. | `rfcs/0000-database-architecture.md`, run context/worklog. | +| 4 | RFC completes adoption/cutover, implementation waves, exhaustive conformance/release matrix, market implications, risks, and kill/switch criteria. | Requirement/decision trace, migration safety, claim/source audit, docs gates. | Same RFC plus run context/worklog. | +| 5 | Root personal review, Qwen 3.8 Max focused review, and Grok 4.6 high whole-RFC adversarial review complete. | Review receipts, source audit, and no undispositioned critical/high finding. | RFC plus review/run artifacts. | +| 6 | Author/editor dispositions resolve every actionable post-draft finding and preserve D-01–D-47. | Finding ledger closed or reasoned decline; contradiction and decision trace rerun. | RFC plus review/run artifacts. | +| 7 | Root closes the final semantic findings, obtains non-Claude TypeScript/JSR/architecture closure, and publishes the final review state. | Three closure verdicts `PASS`; docs static checks, commit/push/PR trail. | RFC and final run/handoff artifacts. | + +There are eight ordered slices, below the Plan-Gate limit. The canonical RFC did not exist before +Slice 2 passed. The owner superseded the planned Fable gate after Slice 6 and froze every Claude +route; Slice 7 therefore ends with root-authored corrections and independent non-Claude closure. +Only mechanical static verification and run-state bookkeeping follow. + +## Gate Set + +### Plan and research gates + +- Run-root `research.md` current-main rebaseline and complete report/source index. +- Every load-bearing numeric/factual claim is pinned to NetScript baseline, Prisma RC tag, post-RC + object, or official primary source; corrected claims are not copied from independent reports. +- Locked D-01–D-47, no must-resolve-now item, ordered slices, risks, gates, deferred scope, doctrine + implications, and implementation waves. +- Separate-session PLAN-EVAL using the harness plan protocol; hard stop until `PASS`. + +### Current docs/RFC gates + +- `SCOPE-docs.md`: source alignment, current/target scope separation, local-link/path integrity, + doctrine/glossary terminology, and drift recording. +- Targeted `deno fmt --check` and `git diff --check` for run/RFC Markdown. +- Claim/source ledger, contradiction scan, decision-to-section trace, migration-safety trace, and + generated/local example syntax review. +- Canonical RFC template/process/front matter and implementation-grade API/state-machine/matrix + coverage. +- No production package/runtime gate is claimed by a docs-only RFC. + +### Future archetype and source gates + +- Per future unit, required F-1…F-19 by the archetype matrix; A3 has required runtime gates, A5 + required plugin/runtime parity, A6 applicable F-CLI family. +- Scoped check/lint/fmt, `quality:scan`, `arch:check`, public surface/subpath audit, naming/folder/ + layering/inheritance/upstream-re-export/permission/test-shape gates. +- Provider import allowlist, exact single Prisma component set, Deno import purity, no toolchain in + runtime graphs, real PostgreSQL, lifecycle/leak/cancellation/transaction/error/redaction gates. +- Deterministic/atomic emission, stale digest refusal, canonical-artifact-only migration, target/ + namespace/space isolation, locks, crash/unknown/resume, ownership/removal, and negative diagnostic + matrices. +- App fragment literal-type preservation, extension-bundle facet identity, namespace type/runtime + parity, source-native `typeof definition` erasure, artifact-only/JSR fallback declarations, + 500-model editor/type-check budget, and no private/cast/copied-overload workaround. +- Standard Schema runtime/JSON corpus, two independent consumers, selection-aware outputs, + fail-closed unsupported cases, contract-space aggregation, and optional AOT equivalence. +- Generated project journeys, agent/help catalog freshness, executable examples, and full + `scaffold.runtime` when DB/scaffold/Aspire/plugin wiring changes. + +### Prospective JSR gates + +The planned JSR audit verdict is **PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS**. The six new +packages do not exist, so `deno publish --dry-run`, `deno doc --lint`, publish-file inspection, and +packed/remote install are **N/A now**, never recorded as PASS. + +At implementation each unit requires: scoped manifest metadata/license/description, explicit export +map and include whitelist, test/fixture exclusions, `@module` docs and runnable examples, 100% +stable symbol docs target, explicit public declarations, relative same-package imports, ESM/Deno +purity, no HTTP/CommonJS/top-level filesystem assumptions, generated-asset freshness, +`deno doc --lint` zero diagnostics, `deno publish --dry-run` without `--allow-slow-types`, inspected +publish list, public import tests, clean packed consumer install, `quality:scan`, and `arch:check`. + +Publishable generated assets are checked-in deterministic TypeScript constants unless an +authenticated registry canary proves JSON/import-attribute limitations resolved. W10 additionally +requires release preflight, GitHub OIDC/SLSA provenance, authenticated canary, registry settings +reconciliation, and production `e2e-cli-prod` against exact published JSR versions. Local dry-run or +packed install cannot substitute for the remote-graph verdict. + +### Review/evaluator order + +1. PLAN-EVAL: completed with fresh Fable 5 medium cycle 2 `PASS`; no further Plan-Eval cycle. +2. Root personal source/doctrine/architecture review of the complete draft. +3. Qwen 3.8 Max focused post-draft review. +4. Grok 4.6 high whole-RFC adversarial review. +5. Author/editor dispositions for every actionable finding. +6. Owner supersession: remove the length target and stop every further Claude/Fable route. +7. Root semantic closure, then independent TypeScript/API, prospective JSR, and architecture passes + through the existing non-Claude lanes. +8. Mechanical format/link/diff checks, commit/push, and PR handoff only. + +## Risk Register + +| Risk | Mitigation / kill response | +| ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | +| Designing to RC marketing or stale builder screenshots | Pin source; current model-first API; keep exact paths adapter-local; W3 spike. | +| Upstream changes during RFC/implementation | RC/current split, exact provider pin/allowlist, independent provider release, compatibility-window gate. | +| Replacing glue with a second ORM/control plane | No query/model DSL, no runtime negotiation, no hosted services, small SPIs and refusal boundary. | +| Published slow types or Prisma leakage | Source-native app inference; atomic fallback only across publish/artifact boundaries; no re-export/private imports or slow-types waiver. | +| Native fragment composition widens inference | Two-phase explicit const-preserving root; generate only at proved boundaries; compile-failure fixtures and editor budget. | +| False multi-schema claim | Withhold capability until Prisma type/runtime parity passes without casts. | +| Contract-derived validation overclaims full operations | Bounded algebra, explicit contributors, runtime/JSON split, fail at schema construction. | +| Custom codec accepts invalid values | Mandatory representation-specific value schemas; encode/decode is not validation. | +| Stale or half-published artifacts | Full canonical digest, atomic publish, facet identity, runtime/apply mismatch refusal. | +| Plugin removal destroys data | Retain default; archive/drop conditional destructive plan; no directory-delete semantics. | +| Provider spaces mistaken for complete portability | PostgreSQL-only certification; explicit unsupported targets; native capability surface. | +| Apply success/exit code masks partial work | Typed per-target/space outcomes, immutable checkpoints, `outcome-unknown`, inspect-before-resume. | +| Cross-target atomicity/rollback implied | Saga language only; no global transaction; complete partial-success receipt. | +| Mutable receipts become shadow state | Provider ledger remains authority; receipts are append-only evidence. | +| No-compat cutover causes data loss | Ownership preflight, marker-only adoption, zero-DDL rehearsal, forward recovery, parallel release line only. | +| JSR plan mistaken for actual readiness | Explicit N/A now; per-package dry-run/docs/packed/canary/remote E2E receipts required later. | +| RFC breadth becomes unimplementable | Exact packages, W0–W11 dependencies, per-wave exits, kill/switch criteria. | +| Agent/docs drift | Generate from operation catalog/manifest and execute every example. | +| CI remains long/flaky | Pure/offline paths, digest caching, real-service gates only at bounded stages, atomic structured receipts. | + +## Kill and Switch Criteria + +Do not publish/switch to Prisma 8 if Deno requires vendoring/text patching; public packages cannot +pass without slow types/private imports; native inference widens; controlled authoring is +non-deterministic; canonical emit is non-atomic; control cannot produce structured bound plans and +results; marker/ledger advancement is unsafe; contract spaces cannot prove disjoint/package-free +operation; real PostgreSQL lifecycle fails; or upstream contract churn lacks a migration path. + +Narrow validation rather than rebuild Prisma types; retain runtime interpretation if AOT equivalence +fails; delete capability abstractions that grow into queries; ship detach-and-retain if destructive +removal cannot be certified; defer a generic SPI change until a second real provider needs it. +Reopen the architecture only if a deterministic manifest depends on live state, app inference +necessarily becomes published slow types, target identity cannot remain provider-independent, or +ownership/ history cannot remain separate from query/runtime types. + +## Open-Decision Sweep + +### Must resolve now + +None. + +### Must resolve before implementation wave + +- W1: canonical manifest/digest encoding and public format-version evolution. +- W3: exact Prisma pin/import allowlist/public builder subpath, L1/L2 API spelling, direct-erasure + versus automatic declaration boundary, runtime/Deno matrix, extension facet mappings, namespace + capability result, and experimental publication status. +- W4: concrete request/process scope and transaction capability shapes. +- W5/W10: signature format/key custody, provider lock implementation, receipt storage/retention, and + crash-fault harness. +- W7: initial augmentation grant vocabulary and executable contribution phase allowlist. +- W10: migration window, parallel legacy branch end date, rollback/runbook, remote release evidence. + +These are mechanism/version/release decisions behind locked public semantics and cannot force a +package-boundary rewrite. + +### Safe to defer + +Second provider; Prisma SQLite/MongoDB/MySQL/SQL Server; runtime capability negotiation; AOT +validation; archive/drop removal; public raw/prepared/aggregate conveniences; hosted control-plane +services; cross-database relation/transaction support (explicitly unsupported rather than parity +debt). + +## Deferred Implementation Scope + +All W1–W11 production code, doctrine mutation, package publication, provider certification, plugin +migration, legacy deletion, release-line operation, and hosted integrations are deferred to +post-acceptance implementation programs. This RFC must specify them precisely but does not claim +their gates have run. + +## Dependencies and Drift Watch + +- Current NetScript baseline, issue/PR history, doctrine, debt, RFC process, and harness protocols. +- Prisma RC1/pinned current source, official release/ADRs/scorecard/issues/PRs, plus a fresh pin + check during RFC drafting and W3. +- Standard Schema and current NetScript service/Hono, SDK, Fresh, oRPC, and plugin composition + precedents, including the preset → factory → native-primitives progression. +- Drift watch: Prisma RC/API/contract changes; namespace typing; moving control/runtime paths; + NetScript DB changes merged to main; model route identity; any compatibility or hosted-control- + plane creep; any package surface requiring slow types. + +## Plan-Gate Readiness + +- Research is current and indexed in `research.md`. +- D-01–D-47 are locked/classified; no must-resolve-now decision remains. +- Eight ordered RFC slices name proof/gates/files. +- Risk, deferred scope, doctrine/debt, future package/JSR/source/consumer gates, and waves are + explicit. +- Prospective JSR audit is applied honestly as planning evidence, with actual dry runs N/A. +- PLAN-EVAL cycle 2 passed at commit `383170bbc`; canonical RFC authorship is unblocked but has not + yet completed. The next action is Slice 3 RFC drafting. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md new file mode 100644 index 0000000000..ca1793bd83 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research.md @@ -0,0 +1,127 @@ +# Research Index: NetScript Database Architecture and Prisma 8 + +## Rebaseline and evidence policy + +- Repository: `rickylabs/netscript` +- Current-main baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` +- Research date: 2026-08-13 +- Upstream Prisma pins: RC1 tag `v8.0.0-rc.1@a76a6c5`; post-RC comparison object + `71e2e0d9ee1f306b5a11435cd1973023cb33866a` +- Carried issue: #313 is rebaselined as historical problem evidence only. Its compatibility-first + solution is superseded by the owner's explicit clean-break directive. + +Evidence classes used by the reports: + +- **Current source fact:** directly inspected NetScript baseline or pinned Prisma source. +- **Primary external fact:** official source, release, ADR, issue, PR, or product documentation. +- **Exploratory evidence:** the owner/Prisma-maintainer exchange; directional, not an upstream + commitment. +- **Inference:** reconciliation of facts; not presented as an implemented capability. +- **Proposal:** future architecture to be gated by the RFC and conformance suite. +- **Conditional/unproven:** provider or release capability withheld until implementation evidence. + +The detailed synthesis is +[research/architecture-plan-synthesis.md](./research/architecture-plan-synthesis.md). This index is +the harness-required current research entrypoint; it does not duplicate the reports. + +## Load-bearing rebaseline findings + +1. NetScript currently has five overlapping database systems with no canonical join point: + appsettings/Aspire resources, a fixed CLI operation runner, generated engine workspaces, runtime + wrappers, and install-time plugin schema copying. +2. Target identity collapses into provider/engine paths. Two same-provider databases share + `database/`; operation target resolution ignores `PrimaryDatabase`; pure generation is + Aspire-coupled. Executing `generateDatabaseDenoJson` for PostgreSQL, SQLite, MySQL, and MSSQL at + the baseline produces 42 `db:*` task keys in every generated engine workspace. +3. Plugin schema is inferred from files and regex collisions rather than versioned ownership, + capability, migration history, provenance, or retention policy. +4. Prisma 8 is an architectural change: canonical contract data and declaration artifacts, + programmatic control, provider runtimes, migration graphs/markers/ledgers, and contract spaces. + RC1 is Early Access and PostgreSQL is the sole intended 8.0 GA database. +5. The current Prisma TypeScript authoring API is model-first `defineContract(scaffold, callback)`. + The screenshot's older target/table/column fluent API was real but was replaced and removed. +6. Prisma's canonical contract can support a bounded runtime Standard Schema interpreter, but it + does not retain the complete create/update/filter/nested-write/result type universe. Unsupported + operation/result/codec metadata must fail when a schema is constructed. +7. Prisma codecs distinguish application runtime, driver wire, and contract/database JSON. The + public validation representations are `runtime` and `json`; driver wire is adapter-internal. +8. Prisma runtime lowering supports namespaces, but RC1 and the inspected post-RC source flatten + namespaces in type maps. Sound multi-namespace E2E typing is an upstream-blocked capability, not + a current product claim. +9. NetScript's service/Hono surface already implements preset → public factory → native framework + plus NetScript primitives; SDK and Fresh preserve the same inferred lower-layer values through + progressively lower adoption surfaces. +10. Market evidence separates source definition, resolved manifest, executable plan, provider + ledger, and immutable receipt. It supports partial/unknown outcome recovery and rejects a local + reinvention of hosted RBAC, fleet, registry, and continuous-drift products. +11. Pinned Prisma separates compile-time `TContract` from runtime `contractJson` (including a + phantom contract type on the emitted path). App-owned contracts can therefore prefer an erased + source-native `typeof definition` binding while runtime consumes only manifest/artifact values. + Root `isolatedDeclarations` still requires an automatic atomic declaration fallback when exact + types cross a publish or artifact-only boundary. + +## Corrections and conflict resolutions + +- Root Prisma catalog entries are caret ranges `^7.8.0`; generated templates still use `^7.4.2`. +- Qwen finding F3 incorrectly “corrected” the current-state report's accurate “more than twenty” + wording to exactly 30 tasks by omitting twelve computed provider-specific task keys. The PLAN-EVAL + evaluator executed `generateDatabaseDenoJson` for all four providers and verified 42 `db:*` keys + for each. Qwen's report remains immutable independent audit evidence; its count is explicitly + superseded here. The same copied 30-task premise propagated into the immutable Opus review and + model briefs and is likewise non-authoritative. Mutable synthesis and plan records use the + executed-generator result. +- `@prisma/orm-postgres` has 138 audited top-level export keys, not the approximate 275 in the Qwen + independent report. +- The AP-17 `interfaces/` rename debt for `packages/database` is stale because `ports/` exists; its + composition-root question remains relevant. +- A live `DatabaseGraph` is rejected. Graphs may be internal compiler IR; the durable public join + point is a plain, content-addressed `DatabaseManifest`. +- Qwen's three minimum public responsibilities and the market audit's five artifact categories are + compatible: definition/manifest, operation protocol, and contribution record produce separate + definition, manifest, plan, ledger, and receipt values. +- Opus's broad runtime validation recommendation is narrowed by the pinned-source validation audit. +- Qwen's generated-validator recommendation is superseded by runtime interpretation plus optional + corpus-equivalent AOT. +- Opus's provider re-export sketch is rejected. Applications and controlled plugin authoring may + import Prisma's public builder directly; NetScript wraps the resulting native value and never + pretends to own or vendor the builder. +- `OWNER-DX-01` supersedes the earlier universal-generated-binding assumption after PLAN-EVAL. The + current model-first Prisma builder remains schema authority, while NetScript adopts its + established L1 preset/recipe → L2 public factories → L3 native Prisma plus primitives/ports + progression. This permits orchestration layers but still forbids a mirrored Prisma + model/field/relation/query DSL, re-export, copied overloads, private types, or inference widening. +- The prospective JSR audit's generated-app-binding statement was planning evidence, not an executed + impossibility proof. Source-native app inference is now the default; a same-compile, + launcher-integrated declaration is the bounded fallback for publish/artifact-only boundaries and + must be proved in W3. +- Plugin removal is not solved by contract spaces alone. Detach-and-retain is the initial guaranteed + lifecycle; archive/drop remain conditional. +- The kernel is provider-neutral while the first adapter is Prisma 8 PostgreSQL-only. Unsupported + targets fail explicitly; no Prisma 7 fallback remains. + +## Report index + +| Report | Evidence class and role | +| ------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [netscript-current-state.md](./research/netscript-current-state.md) | Current NetScript source/history/debt rebaseline and failure taxonomy. | +| [prisma-8-deep-dive.md](./research/prisma-8-deep-dive.md) | Pinned RC/current source, release, scorecard, issue/PR, runtime/control/migration/agent analysis. | +| [market-analysis.md](./research/market-analysis.md) | Official-source comparison across seventeen framework, ORM, migration, IaC, control-plane, and mature-framework products. | +| [market-gap-audit.md](./research/market-gap-audit.md) | Independent correction for Flyway, Liquibase, Terraform, Pulumi, Bytebase, ZenStack, and hosted/local scope. | +| [runtime-validation-maintainer-exchange.md](./research/runtime-validation-maintainer-exchange.md) | Owner-supplied exploratory primary evidence for runtime-derived validation direction. | +| [runtime-validation-source-audit.md](./research/runtime-validation-source-audit.md) | Pinned-source proof of bounded validation algebra, missing operation metadata, codec representations, cache identity, and fail-closed cases. | +| [typescript-schema-orpc-audit.md](./research/typescript-schema-orpc-audit.md) | Historical/current Prisma builder evolution, native fragment/space composition, oRPC transfer, extension bundles, namespace blocker, and artifact boundary. | +| [layered-dx-api-audit.md](./research/layered-dx-api-audit.md) | `OWNER-DX-01` repository-grounded service/Hono, SDK, Fresh, pinned-Prisma type-flow audit and proposed three-layer adoption API. | +| [qwen-prisma-risk-review.md](./research/qwen-prisma-risk-review.md) | Independent adversarial minimum-kernel, provider-contingency, risk, conformance, and kill review; factual conflicts corrected above. | +| [claude-opus-architecture-review.md](./research/claude-opus-architecture-review.md) | Independent package/archetype, identity, runtime, control, contribution, cutover, waves, and conformance architecture review. | +| [planned-jsr-audit.md](./research/planned-jsr-audit.md) | Prospective JSR verdict `PASS-AS-PLANNED`; explicitly not actual publish readiness because packages do not exist. | +| [architecture-plan-synthesis.md](./research/architecture-plan-synthesis.md) | Final decision-grade reconciliation and source for the formal Plan-Gate. | + +## Research verdict + +PLAN-EVAL cycle 2 passed with no must-resolve-now architecture decision. `OWNER-DX-01` is a later, +explicit owner override, not a new evaluator cycle. The exact Prisma RC/GA import spelling, provider +lock mechanism, signature/key custody, and other implementation details remain classified by wave; +the Opus author/editor pass will choose the exact layered API and state the W3 type-boundary proof +while consolidating the RFC to at most 10,000 words. The namespace mismatch continues to withhold a +capability claim rather than blocking the provider-neutral architecture. No further PLAN-EVAL will +run. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md new file mode 100644 index 0000000000..c2243616e2 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/architecture-plan-synthesis.md @@ -0,0 +1,975 @@ +# Architecture Plan Synthesis — NetScript Database Foundation + +> Status: Plan-Gate synthesis, not PLAN-EVAL and not the canonical RFC.\ +> Baseline: `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf`.\ +> Evidence date: 2026-08-13.\ +> Confidence labels: **[FACT]** is directly supported by a cited research/source artifact; +> **[INFERENCE]** reconciles facts; **[PROPOSAL]** is the architecture recommended for plan lock. + +## 1. Executive decision + +**[PROPOSAL]** NetScript should replace its database foundation with a clean-break, provider-neutral +composition and operations kernel whose first certified provider is Prisma 8 PostgreSQL. The kernel +owns identity, deterministic composition, schema-contributor ownership, runtime lifecycle, operation +state machines, policy, and evidence. Prisma owns its schema language, query language, contract +format, execution engine, migration semantics, and database-specific lowering. The application owns +domain ports and the final inferred query types. + +The durable center is not a live `DatabaseGraph`. It is a sequence of distinct values: + +```text +provider-native TypeScript contracts + NetScript database definition + | + v + content-addressed DatabaseManifest + | | + v v + app-local typed bindings speculative preview + | | + v v + lifecycle-owned sessions baseline-bound ExecutablePlan + | + v + provider marker / ledger + | + v + immutable OperationReceipt +``` + +**[INFERENCE]** This reconciles the two strongest independent findings: + +- the five current database systems need one NetScript-owned join point, but a live runtime graph + would become a service locator ([netscript-current-state.md](./netscript-current-state.md), + “Executive finding”; [claude-opus-architecture-review.md](./claude-opus-architecture-review.md), + §§2.1–2.2); and +- the manifest, plan, upstream ledger, and receipt must not collapse into Terraform-like mutable + state ([market-analysis.md](./market-analysis.md), “Artifact and control-plane boundary”; + [market-gap-audit.md](./market-gap-audit.md), “Plan-lock decisions affected”). + +The redesign has five refusal boundaries: + +1. **No NetScript query DSL or repository abstraction.** The provider's query surface remains intact + and application-local. +2. **No compatibility layer.** No Prisma 7 facade, legacy generated module, dual client, + `setClient`, alias barrel, copied schema, or textual generated-source repair survives. +3. **No false portability.** Provider capabilities are visible and statically checked. Unsupported + targets and operations fail explicitly. +4. **No local hosted control-plane clone.** RBAC, approvals, registries, fleet schedulers, + continuous drift agents, KMS, and permanent audit servers are optional integrations. +5. **No validation overclaim.** Standard Schema interpretation is deliberately bounded; unsupported + Prisma operations, result shapes, pack kinds, and codecs fail while constructing a schema. + +## 2. Reconciled evidence and corrections + +### 2.1 Facts that carry the architecture + +- **[FACT]** NetScript currently has five overlapping systems—configuration/Aspire resources, CLI + registry/runner, generated engine workspaces, runtime wrappers, and plugin fragment copying—with + no canonical join point. Target resolution ignores `PrimaryDatabase`; two same-provider targets + share `database/`; generation is Aspire-coupled; executing `generateDatabaseDenoJson` for + all four providers produces 42 `db:*` task keys in every generated engine workspace; plugin + contribution is source-layout discovery plus regex collision checking + ([netscript-current-state.md](./netscript-current-state.md); executed-generator correction in the + [run-root rebaseline](../research.md), “Corrections and conflict resolutions”). +- **[FACT]** Prisma 8 RC1 is Early Access, Node 24-primary, TypeScript 5.9 optional-peer, and + intends PostgreSQL as the only 8.0 GA database. MongoDB is EA, SQLite is proof-of-concept, MySQL + is later, and SQL Server is absent. Prisma's current direction is canonical contract data, a + separate control client, provider runtimes, contract spaces, and types-only emission + ([prisma-8-deep-dive.md](./prisma-8-deep-dive.md), “Research pin,” “Executive conclusion,” and + “Maturity scorecard”). +- **[FACT]** `@prisma/orm-postgres` has 138 top-level export keys at the audited pin, not the + approximate 275 stated in one independent report. This number is evidence of breadth, not a public + API requirement ([prisma-8-deep-dive.md](./prisma-8-deep-dive.md), “Public packages and coupling + risk”). +- **[FACT]** Prisma's public programmatic control direction is real but moving. The CLI/config + distribution, control routing, schema generation, PostgreSQL floor, numeric semantics, and output + channels changed after RC1. Public NetScript types therefore cannot name those option shapes or + package paths ([prisma-8-deep-dive.md](./prisma-8-deep-dive.md), “Six days of post-RC churn”). +- **[FACT]** NetScript builds with `isolatedDeclarations: true`; doctrine's slow-type exception is + intentionally restricted to oRPC-bound packages. Application-specific inferred Prisma contract + types must therefore terminate in generated app-local bindings unless publish conformance proves + an explicitly annotated provider surface + ([claude-opus-architecture-review.md](./claude-opus-architecture-review.md), §§2.1, 12.1; + `docs/architecture/doctrine/02-public-surface.md`). +- **[FACT]** The owner/maintainer exchange is evidence for a runtime-derived validation direction, + not an upstream commitment. The pinned source proves a useful bounded value algebra but disproves + full contract-only Prisma operation parity + ([runtime-validation-maintainer-exchange.md](./runtime-validation-maintainer-exchange.md); + [runtime-validation-source-audit.md](./runtime-validation-source-audit.md), “Bottom-line + decision”). + +### 2.2 Disagreements resolved + +| Disagreement | Resolution for plan lock | Reason | +| ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | +| Live `DatabaseGraph` versus manifest | **[PROPOSAL]** `DatabaseGraph` may exist only as a private compiler IR. `DatabaseManifest` is the durable resolved value. | A live graph invites lookup/service-location; a manifest is serializable, hashable, reviewable, and transportable. | +| Three artifacts versus five artifacts | **[PROPOSAL]** Three public responsibilities—definition/manifest, operation protocol, contribution record—produce five distinct artifact classes: definition, resolved manifest, executable plan, provider ledger, receipt. | Qwen correctly minimizes the public kernel; the market audit correctly separates operational artifacts. | +| Who owns migration/control semantics? | **[PROPOSAL]** Prisma owns provider plan/diff/lineage/marker semantics. NetScript owns target selection, classification, policy, locking orchestration, expiry, cross-target sequencing, recovery, receipts, and error translation. | NetScript must not reimplement Prisma's migration engine, but the missing cross-target and operational guarantees are framework concerns. | +| Capability negotiation | **[PROPOSAL]** Static manifest capability claims and requirements only. No runtime negotiation protocol. | Prevents a second ORM and makes unsupported composition deterministic. | +| Consumer-owned ports | **[PROPOSAL]** App architecture guidance, not a NetScript port framework. NetScript exposes typed target/session references; applications bind them to their own stores at composition roots. | Preserves domain boundaries without generating repositories. | +| Provider contingency backend | **[PROPOSAL]** Specify and test a narrow provider SPI, but do not pre-build a direct-SQL fallback solely to prove it. A second real provider certifies the SPI later. | A speculative fallback would recreate low-level database machinery and violate “wrap, do not reinvent.” | +| Validation generation | **[PROPOSAL]** Runtime Standard Schema interpretation is the default for a bounded algebra. Optional AOT is derived, atomic, and corpus-equivalent. | Qwen's generated-validator recommendation predates the source audit; the source audit supersedes broad generation assumptions. | +| Public representation name | **[PROPOSAL]** `runtime` and `json`. Driver wire is adapter-internal. | Prisma codecs have three channels; calling JSON “wire” is ambiguous. | +| Full mutation/query input validation | **[PROPOSAL]** Do not promise it from the contract alone. Model-value and explicitly contributed operation schemas are supported; missing operation grammar is an unsupported-construction error. | Prisma's phantom operation type maps are emitted to `.d.ts`, not retained as runtime validation data. | +| Plugin removal | **[PROPOSAL]** Detach-and-retain is the initial guaranteed operation. Archive/drop remain capability- and conformance-conditional. | Contract spaces solve ownership and history, not RC1 extension removal. | +| Provider breadth | **[PROPOSAL]** Provider-neutral kernel, Prisma 8 PostgreSQL-only first release. Other targets return structured unsupported diagnostics; no Prisma 7 fallback. | Honest match to upstream maturity while preserving the architecture. | + +## 3. Durable vocabulary and artifact taxonomy + +The RFC must use these terms consistently. Similar-looking values are intentionally distinct. + +| Term | Kind and owner | Meaning and invariant | +| ----------------------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Public TypeScript value, NetScript | Authored composition of targets, spaces, connection-source references, capability requirements, and policies. Pure; it performs no IO. It is not called a manifest. | +| `NativeContract` | Provider-native authored value, provider | A Prisma `defineContract` result or another provider's equivalent. NetScript does not translate its entity/query vocabulary. | +| `SpaceContribution` | Public declarative record, NetScript/plugin | Stable owner ID, version, target binding input, dependencies, ownership, capabilities, artifact references, provenance, and retention policy for one contract space. | +| `ContractArtifact` | Versioned generated data, provider | Canonical provider contract data plus its declaration/types and lineage artifacts. It is pinned and mirrored per space. | +| `DatabaseManifest` | Public versioned generated data, NetScript | Fully resolved, deterministic snapshot of target/space identity, ownership, capability proof, artifact digests, provider pins, topological order, output roots, and policies. It is the durable join point. | +| `ManifestDigest` | NetScript content address | Digest of the canonical full manifest, including provider/contributor identities. It is not any Prisma storage/profile hash. | +| `AppBinding` | App-local generated TypeScript | Minimal inferred bridge from native contract declarations to concrete target sessions, validators, and transport consumers. Never a published framework export. | +| `TargetRef` | Public narrow generic value, NetScript | Explicit stable reference to one target. It carries identity/capability/scope types but no query methods by itself. | +| `TargetSession` | Public lifecycle shell + app-local query generic, NetScript/application | Provider-created process/request-scoped binding. Query surface remains the provider's inferred type parameter. | +| `ConnectionSource` | Public consumed port, NetScript | Resolves credentials/allocation for one target/environment. Environment values never participate in manifest identity. Aspire is one adapter. | +| `SpeculativePreview` | Public structured value, NetScript control | Offline or live advisory preview. Cannot be approved or applied. | +| `ExecutablePlan` | Public signed/versioned value, NetScript control | Bound to manifest digest, exact target/space closure, provider pins, environment, live baseline, operations, policy decision, expiry, and secret references. | +| `ProviderMarker` / `ProviderLedger` | Provider-owned database state | Authoritative provider record of applied space heads/edges. NetScript reads and cites it; NetScript does not create a second mutable shadow state. | +| `OperationReceipt` | Immutable append-only evidence, NetScript control | What was attempted, observed, checkpointed, verified, skipped, failed, or left uncertain. It is not desired state. | +| `OperationCatalog` | Public machine-readable data, NetScript | Names, classes, request/result schemas, diagnostics, and next actions. CLI/help/docs/agent instructions are projections. | +| `ValidationIR` | Internal bounded value algebra, NetScript runtime | Provider-decoded scalar/value-object/union/list/dict/null/value-set/selection shape used to produce Standard Schema values. It never becomes a second entity or query model. | + +Identity is declared, never inferred from provider names or paths: + +- `TargetId` identifies one logical database (`primary`, `analytics`). +- `RoleRef` identifies writer/read-only roles of a target; a replica is not a migration target. +- `NamespaceRef` identifies a physical namespace inside one target. +- `SpaceId` identifies one schema owner (`app`, `plugin:@netscript/auth`). +- `ObjectKey` is `(target, namespace, entryKind, name)` and has one managed owner. +- `ContractSnapshotId` addresses one canonical provider contract artifact. +- `PlanId` binds a manifest, baseline, provider set, policy, and target/space closure. +- `RunId`/`ReceiptId` identify executions and evidence. + +**[PROPOSAL]** Paths, array order, package traversal order, provider discovery order, config +aliases, and engine names must never become identity or dependency edges. + +## 4. Exact package and dependency graph + +### 4.1 Package assignments + +One package receives exactly one doctrine archetype. This corrects the current plan's missing +Archetype 3 runtime surface. + +| Package | Archetype | Public responsibility | Forbidden responsibility | +| ------------------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `@netscript/database-contract` | **A1 Small Contract** | Identities, manifest/plan/receipt/diagnostic data shapes, capability and ownership vocabularies, provider pins, small public SPIs shared across packages. | IO, runtime lifecycle, query types, Prisma imports. | +| `@netscript/database` | **A4 Public DSL/Builder** | `defineDatabase`, target/space/policy composition, pure resolution/compilation to `DatabaseManifest`, frozen definitions, deterministic diagnostics. | Connections, Aspire, provider imports, migration execution. | +| `@netscript/database-runtime` | **A3 Runtime/Behavior** | Process/request lifecycle, target binding, connection ownership, close order, health/readiness, cancellation, validation cache/interpreter coordination, small session handles. | Migration orchestration, CLI, provider query vocabulary. | +| `@netscript/database-control` | **A2 Integration** | Programmatic operation protocol; provider/control ports; classify/preview/plan/apply/verify/inspect/emit; lock coordination; receipts; resume and cross-target saga. | Provider SQL/AST types, direct Prisma imports, CLI rendering. | +| `@netscript/database-prisma-postgres` | **A2 Integration** | The only **framework runtime/control** Prisma import boundary; PostgreSQL capability descriptor; native-contract/artifact adapter; control adapter; runtime factory; validation-IR decoder; upstream compatibility allowlist. | Re-exporting Prisma as NetScript's generic API; importing CLI into runtime; hand-written Prisma driver internals. | +| `@netscript/database-testkit` | **A6 CLI/Tooling** | Runnable provider and contribution conformance certification with machine receipts, negative fixtures, and real-service profiles. | Runtime dependency of an application. | +| `@netscript/plugin` (existing) | **A4 Public DSL/Builder** | `defineDatabaseSpace`/contribution seam using `@netscript/database-contract`; removal of hollow path/engine contribution abstracts in the clean break. | Provider, runtime, or control dependencies. | +| First-party `plugins/*` | **A5 Plugin** | Thin contribution records and pinned release artifacts sourced from their `-core`; provider requirements and lifecycle policy. | Copied application schema, migration ownership hidden in install scripts, framework conventions. | +| `@netscript/aspire` (existing) | **A2 Integration** | One `ConnectionSource`/provisioning adapter and resource projection from the manifest. | Mandatory dependency for pure or non-Aspire operations. | +| `@netscript/cli` (existing) | **A6 CLI/Tooling** | Thin rendering/projection of `OperationCatalog` and `@netscript/database-control`; adoption codemod and agent artifact emission. | Database orchestration logic or provider switches. | + +`@netscript/database-testkit` is deliberately A6 rather than a `./testing` subpath because +third-party provider certification is runnable automation that provisions real services, executes a +matrix, and emits a signed machine report. If implementation proves no binary is needed, this is the +only package split that may be revisited before Wave 1; it must not be folded after public release. + +### 4.2 Dependency direction + +```text + @netscript/database-contract (A1) + / | | \ + v v v v + @netscript/database(A4) -runtime(A3) -control(A2) @netscript/plugin(A4) + ^ ^ ^ + | \ | + +------\-----+ + v + @netscript/database-prisma-postgres(A2) + ^ + | + @netscript/database-testkit(A6) + + application composition root -> definition + runtime + control + chosen provider + app bindings + provider-native app/plugin schema source -> Prisma public authoring builder (controlled build only) + @netscript/aspire -> runtime/contract connection-source SPI only + @netscript/cli -> control/contract operation catalog only + first-party plugin -> plugin + database-contract only +``` + +The arrows denote “depends on” toward the top-level contract seam: kernel packages never import a +provider. The provider implements runtime/control SPIs and is selected as a value in the application +composition root. Only the testkit may fan across all public SPIs. + +### 4.3 Doctrine and publish obligations + +**[FACT]** Doctrine currently describes database schema contributions as plain `*.prisma` fragments, +and its verdict/gated-root tables do not contain the proposed packages +([claude-opus-architecture-review.md](./claude-opus-architecture-review.md), §§3.5, 15.1). + +**[PROPOSAL]** Wave 0 must amend `docs/architecture/doctrine/06-archetypes.md` and +`10-codebase-verdict-and-handoff.md`, register every new package in the gated denominator, replace +the plain-fragment rule, and ensure A9's archetype count is current. Every package must pass +F-1…F-19 as required by its archetype; A3 additionally has required runtime gates. Package/plugin +waves require JSR surface design, `deno doc --lint`, packed install, consumer imports, +`quality:scan`, and `arch:check`. No database package receives the oRPC slow-types exception by +assumption. + +## 5. Public versus adapter-local ownership + +| Surface | Public NetScript contract | Adapter-local/provider-owned detail | +| ----------------- | --------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | +| Authoring | Targets, spaces, ownership, policy, capability requirements, native-contract artifact references. | Prisma model/field/index/default helpers, scaffold shape, lowering and contract AST. | +| Types | Plain identities/artifacts plus generic `TargetRef`/`TargetSession`; concrete app bindings. | Prisma conditional/query/result types and contract generics. | +| Runtime | Scope, lifecycle, health, cancellation, transaction capability marker, validation requests. | `sql`, `orm`, `raw`, `prepare`, concrete transaction/runtime facade, driver/pool types. | +| Control | Operation classes, plan binding, policy, lock requirements, result/receipt/error catalog. | Exact `createControlClient` path/options, upstream plans/errors/progress, migration graph representation. | +| Contract identity | NetScript `ManifestDigest`, `ContractSnapshotId`, provider pin. | Prisma storage/execution/profile hashes and contract schema version, recorded as opaque attributes. | +| Contributions | Stable `SpaceId`, provenance, target/capability/dependency/ownership/removal policy, mirror digest. | Prisma contract-space artifact layout, marker/ledger tables, extension descriptors. | +| Validation | `StandardSchemaV1`, `runtime` and `json`, bounded supported/unsupported semantics, NetScript issue codes. | Prisma contract/AST decoding, driver-wire values, codec conversions, pack-specific metadata. | +| Operations UI | Machine catalog, JSON requests/results, `nextAction`; CLI/help/docs/agents generated from it. | Upstream command names, terminal text, config file layout. | + +No framework package re-exports Prisma. No public example imports a moving upstream control path. +Application and provider-specific plugin schema-authoring modules may import Prisma's **public +authoring builder** directly during the controlled build phase; that is provider-native authoring, +not a NetScript re-export. They may not import Prisma runtime/control internals, and their emitted +plain contribution descriptor/artifacts—not the schema module—are the deployment input. + +## 6. Native TypeScript schema extension and end-to-end typing + +### 6.1 Locked strategy + +**[FACT]** The fluent target/model/table/column chain shown in the owner's screenshot was real at +historical commit `fd88abf4`. Prisma redesign PR #261 / commit `27ccefc3` replaced it with the +model-first callback form, and PR #317 / commit `e1e5ab2c` removed the legacy implementation. RC1's +PostgreSQL API is `defineContract(scaffold, ({ field, model, rel, type }) => …)`: semantic models +first, `.sql(...)` storage overlay second, typed model tokens, and helper vocabulary composed from +family/target/extension packs. The callback preserves its literal return type +([typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md), §§1–3). + +**[PROPOSAL]** Use the same architectural pattern as NetScript's oRPC integration—preserve the +upstream inferred contract, add a NetScript-owned typed composition seam, and bind it at the +application root—but do not copy the mechanisms that would erase inference or publish slow types: + +1. **Candidate A is the baseline: native contract plus thin NetScript definition.** An application + or plugin author invokes Prisma's public `defineContract` directly, then passes the exact native + value to `defineDatabase({ contract, … })` or `defineDatabaseSpace({ contract, … })`. The + NetScript function retains `typeof contract` unchanged while adding identity and policy. + NetScript does not translate entity/model vocabulary and does not publish a shadow + `model()/column()` DSL. +2. **NetScript wraps the result, not the builder.** The frozen database/space definition records + target, ownership, migration head, capabilities, validation policy, and lifecycle around the + native value. It must not copy Prisma overloads or widen the value to a generic contract record. +3. **Composition uses contract spaces, not object spreading.** App and plugin contracts remain + separately owned snapshots with declared dependency edges. A “merged TypeScript contract” may be + an app-local inferred view only where Prisma publicly supports it; it is never the ownership + record. +4. **Plugin publication exports artifacts and plain contribution metadata.** A plugin's release + pipeline emits/pins its contract JSON, declaration artifact, lineage, provenance, and descriptor. + Consumer apply/verify works without importing the plugin package. +5. **Inferred binding stays application-local.** The app emitter writes a minimal binding module + from the manifest and provider declaration artifacts. This is automatic generated glue, never + hand-authored and never text-patched. +6. **A policy-applied native factory is optional, never foundational.** A + `createPrismaContractFactory(...).define(callback)` convenience is allowed only if it forwards + Prisma's exact composed helper surface without copied overloads, private imports, or inference + widening. Otherwise Candidate A remains the complete public API. + +This is “extend Prisma like oRPC” at the correct seam: +`native inferred contract → structurally +checked NetScript contribution → generated app-local binding`. +It does not mean wrapping `defineContract` with a parallel builder or re-exporting all upstream +helpers. + +### 6.2 End-to-end type flow + +```text +native defineContract() value + | typeof contract (editor/compiler inference) + +-----------------------> provider query/result types + | + v +defineDatabase()/defineDatabaseSpace(contract, ownership/capabilities) + | + v +DatabaseDefinition -> DatabaseManifest + pinned contract.d.ts/contract.json + | | + | +--> bounded ValidationIR -> StandardSchemaV1 + v +generated app-local TargetBinding + | + +--> process/request TargetSession> + +--> typed selection/result helper where provider metadata is complete + +--> oRPC/Fresh/form/SSR schemas at explicit trust boundaries + +--> application-owned AccountStore/BillingStore adapters at composition root +``` + +Static inference and durable identity are independent: + +- `typeof contract` is the DX track. It may contain complex provider generics and never crosses a + published framework boundary. +- `ContractSnapshotId`/`ManifestDigest` is the correctness track. It is plain data used by plans, + markers, receipts, validators, caches, agents, and stale-artifact checks. + +Every derived binding includes the manifest digest and exact provider pin. Runtime startup rejects a +binding/manifest/contract mismatch with a structured `db.artifact.stale` or +`db.contract.version-mismatch` diagnostic and a machine `nextAction`. + +### 6.3 Minimal illustrative shape + +This is an audited architectural sketch. The Prisma import subpath and exact RC overload remain +adapter-pin details, so the canonical RFC must label them version-specific rather than promise the +literal path. + +```ts +// Application-local provider-native authoring. +export const appContract = defineContract( + { extensions: {}, namespaces: ['app'] }, + ({ field, model }) => { + const User = model('User', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + }, + }); + return { models: { User } } as const; + }, +); + +// NetScript composition adds ownership/lifecycle, not model vocabulary. +export const appDatabase = defineDatabase({ + id: 'app', + contract: appContract, + target: 'primary', + migrations: { space: 'app' }, + validation: { profile: 'boundaries' }, +}); +``` + +The public RFC must explicitly state that the screenshot's deleted fluent syntax is not the target +API and must not be recreated by NetScript merely for aesthetic familiarity. + +### 6.4 Native fragments, ownership modes, and extension bundles + +There are two contribution modes, and the mode decides migration ownership: + +- `ownership: 'app'` is a native fragment function that receives Prisma's exact composed helpers and + returns const-preserved native `types/models/enums/entities`. A generated app-local root composes + fragments through explicit calls and object spreads. It must not use `Array.reduce()` or a + registry widened to `Record`. +- `ownership: 'space'` is a complete plugin-owned native contract, canonical artifact, migration + graph, and head. This is the default for plugin-owned tables. The consumer binds the space to a + target but does not acquire its migration ownership. + +Composition is necessarily two-phase because extension packs determine the static and runtime shape +of the helper object before Prisma invokes the callback: + +1. collect contribution manifests, required packs, dependencies, target/namespace requirements, + ownership, and extension facets; +2. resolve one scaffold, obtain the fully composed native helper surface, and then invoke app-owned + fragments in deterministic dependency order. + +A database extension is one NetScript contribution bundle with a single verified ID/version and four +phase facets: + +```ts +defineDatabaseExtension({ + id: 'pgvector', + version: '…', + authoring: pgvectorPack, + control: pgvectorControl, + runtime: pgvectorRuntime, + validation: pgvectorValidation, +}); +``` + +The generated root fans that bundle into Prisma's authoring, control, runtime, and validation +locations. A missing, mismatched, or half-installed facet is a composition error. This eliminates +the current class of manual registration where one logical extension must be repeated independently +per phase ([typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md), §§4, 10). + +### 6.5 Canonical artifact boundary + +Native no-emit development does not remove the production artifact boundary: Prisma itself +serializes/deserializes even an in-memory native contract before runtime use, and migration planning +is canonical-artifact-driven. The automated build therefore evaluates native authoring only in a +controlled deterministic phase, canonicalizes, atomically emits contract and declaration artifacts, +checks the migration head, validates or creates migration artifacts, attaches ownership/provenance, +and makes CI/production runtime consume the exact verified artifact. Migration apply never executes +arbitrary application or plugin TypeScript +([typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md), §9). + +## 7. Runtime validation subsystem + +### 7.1 Public boundary and algebra + +**[PROPOSAL]** Standard Schema is the only public validator protocol. NetScript returns +`StandardSchemaV1` from app-local typed bindings; it does not re-export Zod, Valibot, ArkType, or +Prisma's ArkType contract-document validators. + +The supported internal `ValidationIR` is deliberately closed per interpreter ABI: + +- registered scalar codec leaves; +- nullability; +- `many` lists and `dict` values; +- value objects; +- value sets, domain enums, and resolvable provider native enums; +- unions only when branch identity is deterministic; +- model fields/relations whose cross-space references resolve through a verified aggregate; +- whole-model values with explicit presence policy; and +- direct-column selection/returning projections whose alias, codec, nullability, and representation + are fully known. + +Public representations are: + +```ts +type ValidationRepresentation = 'runtime' | 'json'; +``` + +Prisma driver-wire values and schemas are adapter-internal. A built-in or custom codec is supported +only when its contributor supplies a deterministic value schema for every advertised public +representation. Conversion success is not validation. + +### 7.2 Three schema classes + +The RFC must not hide materially different guarantees behind one `input()` method. + +| Class | Supported initial guarantee | Refusal boundary | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | +| Model value schema | Validate a named model/value-object/enum in `runtime` or `json`, using explicit object-presence/default policy. | No inference that database uniqueness/FK/check constraints are locally satisfied. | +| Operation input schema | Available only when the provider/extension contributes a runtime operation grammar and typed binding for that exact operation. | Prisma create/update/filter/nested-write semantics absent from runtime contract data fail at construction. | +| Result schema | Validate whole-model or fully-known direct projections/selections with complete leaves. | Computed/subquery/raw/aggregate/include/unknown leaves require an explicit contributed result schema or fail at construction. | + +Candidate app-local shape: + +```ts +const users = database.primary.space('app').model('User'); + +const runtimeUser = users.value({ representation: 'runtime' }); +const createData = users.operation('create', { representation: 'runtime' }); +const publicUser = users.result(selection, { representation: 'json' }); +``` + +`operation()` and `result()` throw `DB_VALIDATION_UNSUPPORTED` while constructing a schema if the +requested metadata is incomplete. Invalid user values do not throw; they return Standard Schema +issues. + +### 7.3 Mandatory unsupported cases + +Schema construction fails closed for at least: + +- unknown codec or missing representation-specific codec value schema; +- unknown provider pack entity kind; +- corrupt/missing aggregate space, head, hash, cross-space reference, or value set; +- ambiguous unions or unresolved model variants/discriminators; +- Prisma operation types whose runtime grammar is absent: filters, relation traversal, nested + writes, polymorphic narrowing, and default/presence semantics without a contributor; +- SQL computed, subquery, raw, aggregate, or include results without an explicit result shape; +- Mongo `resultShape: unknown`, raw `Document`, or unknown leaves; +- opaque SQL index/check expressions and database-state constraints such as uniqueness, FK, or + exclusion checks; and +- async/non-deterministic value predicates where the requested Standard Schema mode promises sync. + +No unsupported case becomes `unknown`, pass-through, or a warning. + +### 7.4 Cache identity and AOT equivalence + +No existing Prisma section hash covers validator identity. Cache keys contain: + +```text +canonical full-contract digest + schema version + space id + target/family ++ operation or normalized selection + representation + interpreter ABI ++ codec/pack contributor id/version + execution identity when defaults matter +``` + +An optional AOT projection ships only if it passes the same semantic corpus as runtime +interpretation: successes, issue paths, representation behavior, unsupported-construction failures, +contract-space resolution, and invalidation. It is content-addressed, target-scoped, atomic, and +replaceable. It is never hand-maintained, repaired, or required for correctness. + +### 7.5 Trust-boundary policy + +- Input/model-value validation is mandatory at external mutation boundaries where a supported schema + exists. +- Output validation is mandatory for declared API/RPC responses, SSR/hydration payloads, and + external-service messages; it is opt-in for internal query loops. +- Failure issues include stable code, target, space, contract digest, model/operation/selection, + representation, field path, expected class, and observed value class. +- Contract-space plugin fields participate automatically after aggregate integrity verification. +- oRPC, Fresh, forms, and SSR consume the same Standard Schema values; adapters must not regenerate + library-specific mirrors. + +## 8. Control state machines + +### 8.1 Operation classes + +| Class | Examples | Allowed dependencies | +| ----------- | ------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | +| `pure` | compose, validate definition, emit, format, lineage integrity | Source/artifact readers and atomic writer only; never connection, Aspire, Docker, or network. | +| `live-read` | inspect, introspect, live preview, verify, status | Explicit target connection; no mutation lock. | +| `mutating` | initialize, seed, apply, sign, adopt baseline, retire | Explicit target; provider-native lock/fencing; executable plan where applicable. | +| `resident` | studio or connection available only inside an existing host | Explicit target and resident orchestration binding. | + +Aspire is a connection-source/provisioning adapter, never an operation class. + +### 8.2 Composition state machine + +```text +authored + -> resolving + -> resolved(manifest, warnings) + -> refused(diagnostics) +``` + +Resolution is pure and total as `Result`. It validates declared identities, output/root isolation, +provider pins, target binding, capability subsets, ownership disjointness, dependency +closure/cycles, cross-target reference refusal, contribution provenance, contract version, and +mirror integrity. + +### 8.3 Preview/plan state machine + +```text +resolved manifest + -> speculative-preview ----------------------> non-applicable + -> inspect baseline + -> executable-plan-created + -> policy-evaluated(allowed | refused) + -> approved/signed (required by environment) + -> ready + -> expired | stale | revoked +``` + +A speculative preview is never accepted by `apply`. An executable plan binds manifest digest, +target/space dependency closure, environment, live baseline, provider/package locks, ordered +operations, destructive findings, policy result, secret references, and expiry. Production requires +a signature, but signing/key custody is a pre-production decision rather than a Wave 1 blocker. + +### 8.4 Apply/receipt state machine + +```text +planned + -> acquiring-lock + -> locked + -> revalidating + -> started + -> applying(step checkpoint)* + -> applied + -> verifying + -> verified + -> succeeded + +terminal/interrupt branches: + refused | skipped(reason) | failed | partial_success + | cleanup_required | outcome_unknown | cancelled +``` + +Every irreversible operation or provider transaction group appends an atomic receipt checkpoint. +Loss of transport after dispatch produces `outcome_unknown`, never `failed`. Resume first inspects +the database and provider ledger, revalidates plan bindings, and then continues only operations +whose outcome is known and unfinished. It never blindly repeats non-idempotent DDL or data +transforms. + +Lock scope is target + physical database. Lock evidence includes provider capability, owner, nonce, +fencing token where used, start/expiry, timeout, and safe force-unlock preconditions. An adapter +that cannot provide a certified lock is refused for concurrent-safe apply. + +### 8.5 Cross-target saga + +Target and space selection always expands dependency closure. The plan records omitted items and +reason codes. Execution orders independent targets deterministically and may run them concurrently +only when policies and resource limits allow; each target has a separate runner and lock. + +There is no cross-database transaction and no automatic rollback claim. A second-target failure +returns complete per-target/per-space results and `partial_success`; resume continues after +inspection. Selective apply is recovery machinery, not the normal path, and it requires subsequent +whole-manifest verification. + +## 9. Plugin and contract-space lifecycle + +### 9.1 Contribution record + +Every contribution declares: + +- stable `SpaceId` and semantic version; +- provider contract-format range and contract artifact digest; +- target binding supplied by the application, never a default/fallback; +- namespace/object ownership and `managed | adopted | external | ignored` policy; +- static capability requirements; +- declared dependency edges; +- migration head/lineage artifact and data invariants; +- package/integrity/provenance/signature information; +- one identity/version-checked extension bundle fanning into authoring, control, runtime, and + representation-specific validation facets; +- representation-specific codec/operation/result validation contributions; +- allowed executable phases; and +- default retention/removal policy. + +The consumer pins a mirror containing descriptor, contract data/declaration, lineage, and +provenance. Production apply/verify reads the mirror, not `node_modules`. Half-installation—schema +contribution present without its runtime/codec half, or vice versa—is a composition error. + +### 9.2 Ownership and augmentation + +- Each `ObjectKey` has one managed owner. +- Equal text from two contributors is still conflicting ownership. +- Namespaces prevent lexical collisions but do not replace ownership checks. +- Cross-space references require the same target plus a declared dependency edge. +- Augmentation is an owner-granted closed permission, not implicit merge. Initial grant kinds are + deliberately narrow; unsupported modification asks the owner or uses an app-owned migration. +- `external` is not planned/mutated and is verified only against declared assertions. `adopted` has + an explicit reviewed baseline. `ignored` requires an auditable reason and participates in neither. + +### 9.3 Lifecycle + +| Transition | Guaranteed behavior | Refusal/conditional behavior | +| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | +| Install | Validate target/capability/dependency/ownership/provenance; pin mirror; recompile manifest; produce plan. | Refuse overlap, missing/cyclic dependency, contract skew, unsupported provider/codec. | +| Upgrade | Require lineage path from pinned head; pin new mirror; plan each changed edge. | Refuse ownership widening, incompatible contract format, capability regression, ambiguous branch. | +| Skew | Refuse mutation when installed package, mirror, manifest, and marker identities disagree. | Diagnostic names every observed identity and sync action. | +| Detach/uninstall | Remove runtime/package binding while retaining pinned space tombstone and data by default. | Refuse if dependents remain or contribution cannot be verified without package code. | +| Retain | Guaranteed initial removal mode; preserve data, marker, mirror/tombstone, and ownership history; downgrade future mutation authority to `adopted`. | Exact upstream extension-detach mechanics must pass conformance. | +| Archive | Provider-capability conditional; planned namespace/table relocation with restoration path. | Unsupported for v1 unless Prisma PostgreSQL conformance proves it. | +| Drop | Destructive-plan conditional; explicit policy/approval, dependent closure, and verified lineage. | Not claimed as a general RC1 capability; no delete-directory shortcut. | + +**[PROPOSAL]** The RFC defines the lifecycle vocabulary now but only marks detach-and-retain as a +first-release guarantee. Archive/drop do not block the architecture and may not be scored as +implemented until provider conformance succeeds. + +## 10. Multi-target and provider matrix + +| Axis/case | Kernel support | Prisma 8 PostgreSQL adapter v1 | Required behavior | +| ---------------------------------------- | ---------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Two PostgreSQL databases | Yes | Required | Distinct `TargetId`, connections, outputs, spaces, markers, runtimes, plans, locks, receipts. | +| Multiple PostgreSQL namespaces | Yes | **Upstream-blocked capability** | Runtime lowering supports per-model namespaces, but RC1/current-main type maps flatten them into the default namespace. The adapter must not claim `multiNamespace` until exact type/runtime parity passes without casts. | +| Writer/read replicas | Roles on one target | Runtime conditional | Reader session is read-only; no migration operation can address a reader. | +| App + multiple plugin spaces | Yes | Required | Independent artifacts/heads, dependency order, overlap refusal, package-free apply/verify. | +| Managed/adopted/external/ignored objects | Yes | Required | Ownership-aware plan and drift semantics. | +| Request/process scope | Yes | Required | Different types and lifecycle; serverless request handles disposable and capability-reduced. | +| Prisma 8 SQLite | Kernel-ready | Unsupported/deferred | Structured `db.target.unsupported`; no legacy fallback. | +| Prisma 8 MongoDB | Family axis ready | Unsupported/deferred | No production claim based on EA source presence. | +| Prisma 8 MySQL | Provider axis ready | Absent/deferred | Retire hand-rolled adapter; revisit after upstream or a separately certified provider. | +| SQL Server | Provider axis ready | Absent/deferred | Requires another provider implementation. | +| Cross-target relation/transaction | Explicitly unsupported | Unsupported | Composition error for relations; multi-target operations are sagas, never transactions. | +| Provider-specific query features | Capability-visible | Native Prisma surface | No lowest-common-denominator wrapper. | + +The provider-neutral kernel may ship independently of Prisma readiness. The Prisma adapter remains +experimental/unpublished until every release gate passes. A Prisma delay never reopens a Prisma 7 +path. + +## 11. Clean cutover and parallel development + +### 11.1 No-compatibility law + +The old and new systems may live on separate branches/release lines during implementation, but one +application composition may never load both. There are no runtime shims, aliases, deprecated +facades, dual migration histories, or copied schema bridges. + +### 11.2 Adoption workflow + +`netscript db adopt` is a temporary migration tool, not a compatibility layer: + +1. Read legacy config and generated layouts; report duplicate/ambiguous identities. +2. Generate a proposed TypeScript `DatabaseDefinition`, taking target IDs from config keys, never + providers. +3. Introspect every reachable target without mutation. +4. Propose one space per attributable owner plus app/external/adopted classifications. +5. Produce a complete ownership/capability/provenance preflight; unattributed objects hard-stop. +6. Compile the manifest and emit atomic provider/app-binding artifacts. +7. Establish one baseline/root per space and write provider marker metadata **only**—zero DDL/DML. +8. Verify the live target against the manifest and baseline. +9. Commit the new composition and delete old engine workspaces, the 42 per-workspace generated + `db:*` task keys, repair scripts, copied plugin fragments, old adapters, and dependencies only + after verification. + +After baseline and before the first new apply, rollback is repository-only plus idempotent removal +of new marker metadata where provider semantics permit. After first apply, recovery is forward +through lineage and receipts. There is no “run both clients” rollback. + +### 11.3 Safety and parity + +- A seeded/populated production-shaped rehearsal must prove adoption performs zero schema/data + mutation. +- Preflight is a committed CI artifact with target/provider versions, every object/owner, capability + proof, plugin provenance, and unresolved blockers. +- The fourteen legacy verbs receive explicit mapped/replaced/removed dispositions; implicit + target/default and silent first-target execution are deliberate removals. +- The parallel architecture branch merges only after feature-parity accounting, migration guide, + data-safety rehearsal, and full scaffold/runtime gates. This is branch strategy, not public API. + +## 12. Implementation waves and dependencies + +| Wave | Proves | Depends on | Primary surfaces | Exit gate | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| W0 RFC/doctrine lock | Vocabulary, package archetypes, refusal boundaries, acceptance matrix. | — | RFC + doctrine/gated-root amendments planned, not production code. | Accepted RFC; PLAN-EVAL/IMPL-EVAL complete; no unresolved must-resolve decision. | +| W1 Contract kernel | Plain identities, artifact schemas, capability/ownership vocabularies, diagnostic/operation types. | W0 | `@netscript/database-contract` | A1 gates; zero upstream deps; publish/doc/consumer proof. | +| W2 Definition/compiler | Pure native-contract wrapping, definition DSL, deterministic manifest resolution, ownership/dependency/capability checks. | W1 | `@netscript/database` | A4 gates; property/determinism tests; zero IO reachability. | +| W3 Prisma PostgreSQL spike | Validate public native builder, contract artifacts, ControlClient, runtime, spaces, extension bundles, Deno, bounded ValidationIR, and namespace parity behind adapter-local facade. | W1–W2 | Experimental `@netscript/database-prisma-postgres` | Kill/switch review; real PostgreSQL + packed Deno proof; no public stability claim; do not advertise `multiNamespace` while upstream types flatten namespaces. | +| W4 Runtime | Process/request sessions, lifecycle, connection sources, health/readiness, validation cache and trust-boundary adapters. | W1–W3 | `@netscript/database-runtime`, Aspire adapter | A3 gates; lifecycle/leak/cancellation/scope tests. | +| W5 Control | Operation catalog, preview/plan/apply/verify, lock/recovery/receipt state machines, atomic emission, cross-target saga. | W1–W4 | `@netscript/database-control` | A2 gates; exhaustive negative/failure injection; pure path no Aspire. | +| W6 Conformance testkit | Certify providers and spaces, generated-project fixtures, machine reports. | W1–W5 | `@netscript/database-testkit` | A6/F-CLI gates; intentionally broken fixtures fail; real PostgreSQL. | +| W7 Contribution seam | Replace hollow path/engine abstracts with space contributions and pinned artifacts. | W1–W6 | `@netscript/plugin`, first plugin-core fixture | Breaking surface accounting; plugin seam/thinness gates. | +| W8 CLI/agent/adoption | Thin command projection, generated docs/skill, adoption codemod/preflight. | W2, W5–W7 | `@netscript/cli`, generated app surface | Every example compiles/runs; codes/catalogs match; zero text-log assertions. | +| W9 First-party spaces | Auth/workers/sagas/triggers converted; capability and lineage artifacts published. | W7–W8 | Plugin core + thin A5 packages | Each space conformance suite; package-free apply/verify; runtime E2E parity. | +| W10 Clean cutover | Adopt populated fixtures; delete old database foundation and manual pipeline. | W1–W9 | Repo-wide DB wiring/scaffold/docs | Full release-gate class, Windows/Linux, production-shaped adoption, no compatibility remnants. | +| W11 Provider expansion | Prove SPI with a real second provider only when demanded and mature. | W10 | Separate provider package | Full provider conformance; no kernel/public manifest change. | + +W3 is intentionally a spike before public runtime/control stabilization. A failed Prisma adapter +must not invalidate W1–W2. No old package is deleted before W10; that temporary repository +coexistence does not authorize dual runtime composition. + +## 13. Exhaustive Plan-Gate decision table + +| ID | Decision | Status before PLAN-EVAL | Rationale / evidence | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| D-01 | Clean break; no backward compatibility surface. | **LOCK** | Owner directive; old constraints caused current architecture. | +| D-02 | Data continuity and mechanical migration are mandatory. | **LOCK** | No-compat does not authorize data loss. | +| D-03 | Durable join point is `DatabaseManifest`; live graph is private compiler IR. | **LOCK** | Opus/Qwen/market reconciliation. | +| D-04 | Definition, manifest, plan, provider ledger, and receipt are separate values. | **LOCK** | Terraform/Pulumi/Flyway/Liquibase corrections. | +| D-05 | NetScript defines no query DSL/repository/client facade. | **LOCK** | Avoid second ORM; native provider semantics remain available. | +| D-06 | Native model-first Prisma `defineContract` authoring is primary; obsolete fluent chaining is not recreated. PSL may remain provider input but is not NetScript's preferred E2E path. | **LOCK; exact import path adapter-pinned** | Owner directive plus historical/current source audit. | +| D-07 | Candidate A—direct native contract plus thin `defineDatabase`/space wrapper—is the baseline. Optional policy factory dies if it copies overloads, uses private imports, or widens inference. | **LOCK** | Preserves native values and ownership; exact oRPC transfer audit. | +| D-08 | App-specific inferred binding is generated app-local, never published from kernel packages. | **LOCK** | `isolatedDeclarations` and slow-type boundary. | +| D-09 | Exact package graph/archetypes are §4; runtime is A3. | **LOCK** | Doctrine gate correctness. | +| D-10 | Kernel is provider-neutral; first certified adapter is Prisma 8 PostgreSQL only. | **LOCK** | Upstream maturity matrix. | +| D-11 | Unsupported providers fail explicitly; no Prisma 7 fallback. | **LOCK** | Honest capability model and clean break. | +| D-12 | Capabilities are static declared tags, not runtime negotiation. | **LOCK** | Minimum kernel; prevents abstraction growth. | +| D-13 | Provider registry is composition-root data, never global/public mutable registry. | **LOCK** | A10 and service-locator refusal. | +| D-14 | Stable target ID, not engine/provider, owns connection/output/runtime/migrations/receipts. | **LOCK** | Repairs same-provider collision. | +| D-15 | Target selection is explicit; selection expands dependency closure and records omissions. | **LOCK** | No fallback/silent skip; market recovery lessons. | +| D-16 | Replicas are target roles, not migration targets. | **LOCK** | Prevents accidental mutation of readers. | +| D-17 | Provider-native contract spaces plus NetScript contribution policy replace copied fragments. | **LOCK** | Ownership/history/provenance. | +| D-18 | One managed owner per `ObjectKey`; augmentation requires owner grant. | **LOCK** | Text collision is not ownership. | +| D-19 | Pinned mirrors make production apply/verify independent of installed plugin packages. | **LOCK** | Contract-space deployment property. | +| D-20 | Detach-and-retain is guaranteed removal; archive/drop are conditional. | **LOCK** | RC extension removal gap. | +| D-21 | Standard Schema is public; runtime bounded interpretation is default. | **LOCK** | Maintainer direction plus source proof. | +| D-22 | Public validation representations are `runtime` and `json`; driver wire is internal. | **LOCK** | Three-channel codec source. | +| D-23 | Full Prisma operation validation is not contract-derived; explicit operation contributors are required. | **LOCK** | Phantom operation maps erased at runtime. | +| D-24 | Unknown validation metadata fails at schema construction. | **LOCK** | Fail-closed safety. | +| D-25 | Optional AOT validation is semantic-equivalence-only and never required. | **LOCK** | No second model universe. | +| D-26 | Pure operations cannot resolve connections or Aspire. | **LOCK** | Closes recorded architecture debt. | +| D-27 | Control API is programmatic; CLI/docs/agents project the operation catalog. | **LOCK** | Eliminates log parsing/drift. | +| D-28 | Preview differs from executable plan; apply accepts only bound, revalidated plans. | **LOCK** | Market plan/apply evidence. | +| D-29 | NetScript owns policy/lock/recovery/receipt/cross-target saga; provider owns diff/lineage/marker mechanics. | **LOCK** | Avoid both shell forwarding and migration-engine reinvention. | +| D-30 | Cross-target apply is never atomic; partial/unknown outcomes are first-class. | **LOCK** | Database reality and recovery prior art. | +| D-31 | Local kernel does not implement hosted registry/RBAC/fleet/drift services. | **LOCK** | Scope control. | +| D-32 | Generated artifacts are minimal, content-addressed, atomic, and never text-patched. | **LOCK** | Retires current repair pipeline. | +| D-33 | Agent instructions are generated and every example is executed. | **LOCK** | Upstream skill drift evidence. | +| D-34 | Existing MySQL/MSSQL/SQLite product support is not carried through compatibility code. | **LOCK** | Clean break; structured unsupported behavior. | +| D-35 | Production plan signing is required. | **PRE-IMPLEMENTATION** | Key custody/algorithm can be chosen before W10, not before kernel work. | +| D-36 | Exact provider-native builder strategy and extension collection. | **LOCK; import spelling PRE-IMPLEMENTATION W3** | Current model-first callback, Candidate A, two-phase composition, const-preserving generated root, and no-re-export rule are source-audited; exact RC/GA subpath remains adapter-local. | +| D-37 | Multi-namespace capability claim. | **CONDITIONAL / upstream-blocking** | RC1 and current main lower runtime namespaces but type maps flatten into default namespace; no cast workaround is allowed. | +| D-38 | App-owned fragments and plugin-owned spaces are distinct; plugin-owned tables default to full space ownership. | **LOCK** | Preserves literal native values while keeping migration history with the real owner. | +| D-39 | One database-extension bundle supplies identity-matched authoring/control/runtime/validation facets through two-phase collection. | **LOCK** | Prevents manual half-registration and helper-shape unsoundness. | +| D-40 | Migration/runtime in CI and production consume canonical verified artifacts, never arbitrary schema TypeScript. | **LOCK** | Prisma's migration system and even no-emit runtime cross the canonical artifact boundary. | +| D-41 | Exact Prisma control/runtime import allowlist and compatibility window. | **PRE-IMPLEMENTATION (W3)** | Adapter-local and intentionally version-pin dependent. | +| D-42 | Lock implementation strategy (native advisory vs fenced row). | **PRE-IMPLEMENTATION PER PROVIDER** | Public semantics are locked; mechanism is conformance-driven. | +| D-43 | AOT validator ships. | **SAFE TO DEFER** | Runtime is sufficient; ship only for measured cold-start need. | +| D-44 | Second provider identity. | **SAFE TO DEFER** | SPI is proven when a real requirement/mature provider exists. | +| D-45 | Raw/prepared/aggregate numeric public conveniences. | **SAFE TO DEFER / adapter-local** | Moving upstream semantics; native query surface remains accessible app-locally. | +| D-46 | Archive/drop plugin retirement in v1. | **SAFE TO DEFER** | Retain path supplies safe lifecycle; destructive paths require proof. | +| D-47 | Remote approval/registry/continuous-drift integration. | **SAFE TO DEFER** | Optional control-plane charter. | + +There is no open decision that would force a package-boundary rewrite after PLAN-EVAL. D-37 is an +honest capability block: it prevents a Prisma PostgreSQL adapter from advertising sound +multi-namespace E2E typing, but it does not alter the provider-neutral manifest or package graph. + +## 14. Conformance and release gates + +Every behavioral feature crosses **type → composition/plan → provider artifact/SQL → result → +lifecycle/evidence**. A type-only or exit-code-only pass is not evidence. + +### 14.1 Composition, typing, and artifacts + +- Native TypeScript contract preserves model/query/result inference through the app binding. +- App-owned fragment composition preserves literal model/field/relation names under reordering; a + widened registry fixture must fail its type-soundness gate. +- Plugin contribution compiles without slow-type erasure and publishes its plain descriptor plus + artifact set. +- One extension bundle proves identical ID/version across authoring/control/runtime/validation, and + a missing or mismatched facet fails composition. +- Same-provider targets have no shared paths, heads, connections, locks, bindings, or receipts. +- Every ownership/capability/dependency/contract-skew diagnostic has a negative test and structured + `nextAction`. +- Resolve/emit twice from clean inputs yields byte-identical manifest/artifacts; interruption shows + fully old or fully new roots only. +- Domain-only, extension-only, codec, provider, representation, selection, and default-sensitive + changes invalidate the appropriate app binding/validation cache. +- Packed clean-consumer install resolves one exact Prisma component set and no off-allowlist import. +- Migration apply succeeds from canonical JSON/operations artifacts with application/plugin source + TypeScript unavailable. +- Type-check/editor latency passes an agreed 500-model representative application budget. + +### 14.2 Runtime and validation + +- Real PostgreSQL (not only PGlite) proves connect/query/relation/transaction/cancel/stream/close, + request/process scope, external pool where supported, and leak-free repeated lifecycle. +- Deno import graph has no unintended Node/CLI/toolchain reachability; deployment/bundler profiles + named by the adapter pass. +- `runtime | json` corpus covers strings/numbers/booleans, Date, bigint, numeric string, bytes, + JSON, domain enum/value set/native enum, null/list/dict/value object/union, and one custom codec. +- Every unsupported case in §7.3 fails constructing the schema with stable coordinates; invalid + values return path-rich Standard Schema issues. +- Direct selection/result shapes are strict; computed/raw/unknown paths never pass through. +- App plus two extension spaces proves aggregate resolution and duplicate model names never collide. +- Standard Schema consumption is proven through at least two independent consumers (for example oRPC + plus a form/validator integration), without generated Zod mirror files. +- If AOT exists, the full semantic corpus and cache invalidation suite is identical. + +### 14.3 Control, migration, and recovery + +- Offline emit succeeds with no Aspire/.NET/Docker/network. +- Non-default namespace selectors are honored; a silently ignored selector is a failure. +- Greenfield, populated adoption (marker-only), drift, destructive refusal, stale/expired plan, + package/contract skew, lock contention/death, invariant transform, and external ownership pass. +- Connection loss after dispatch produces `outcome_unknown`; resume inspects marker/live state + before action. +- Cross-target failure records all target/space phases and resumes only known-unfinished steps. +- Target/space selective recovery proves dependency closure, omitted reasons, and subsequent full + verification. +- Plugin install/upgrade/dependency/skew/package-absent verify/detach-retain pass. Archive/drop are + excluded until individually certified. +- Windows and Linux migration gates run; no gate asserts human message strings. + +### 14.4 Doctrine, consumer, journey, and release + +- Each new package is doctrine-registered and passes archetype F-1…F-19, scoped check/lint/fmt, + `quality:scan`, `arch:check`, JSR audit, docs score, packed install, and public import tests. +- A3 lifecycle packages pass mandatory runtime/Aspire gates; A5 plugins pass thinness, base-seam, + golden emitter, doctor, contract-soundness, and `scaffold.runtime` parity. +- Generated CLI/help/agent catalogs exactly match machine operation/diagnostic schemas; every + example compiles and runs. +- Journeys: scaffold → second PostgreSQL target → two plugin spaces → plan/apply/deploy with no + manual generated edit; and populated legacy adoption → zero DDL → verify. +- Cutover runs the full release-gate class and proves no legacy Prisma adapter, generated task, + copied fragment, repair script, deep generated import, or compatibility alias remains. + +## 15. Kill and switch criteria + +### 15.1 Kill only the Prisma adapter + +Keep the provider-neutral kernel but do not publish/switch to Prisma 8 if any remains true at the +adoption pin: + +- Deno runtime/import purity requires vendoring or textual patching upstream. +- Packed provider artifacts cannot publish/install without unsupported slow-type or duplicate- + component failures. +- Native TypeScript authoring cannot preserve app-local inference through a stable public builder + seam. +- Contract emission cannot be deterministic and atomically installed. +- Programmatic control cannot produce enough structured information to bind plans, verify outcomes, + and avoid terminal-text parsing. +- PostgreSQL marker/ledger advancement cannot be proven safe with migration effects. +- Contract spaces cannot prove disjoint ownership/package-free apply for app plus plugins. +- Required runtime lifecycle/transaction/error/cancellation behavior fails against real PostgreSQL. +- Upstream changes contract format without a viable migration path more than once before NetScript's + first stable adapter release. + +Switch to a different provider adapter only after it passes the same SPI conformance. Do not reopen +Prisma 7 compatibility. + +### 15.2 Kill or narrow a subsystem + +- If full-operation Standard Schema derivation would require reproducing Prisma's phantom type + system, keep only model-value and known-result validation plus explicit contributors; this + narrowing is already the plan, not a failure. +- If runtime interpretation misses cold-start budgets, test AOT equivalence; if equivalence fails, + retain runtime and require explicit schemas at the affected boundary rather than shipping a + divergent mirror. +- If provider-generic capability types grow into query abstractions or negotiation, delete them and + keep literal static tags. +- If contribution archive/drop cannot be verified, ship detach-and-retain only. +- If the public provider SPI changes to accommodate hypothetical providers before a second adapter + exists, revert to the smallest Prisma-exercised seam and defer generalization. + +### 15.3 Architecture kill criteria + +Reopen the RFC—not merely the adapter—if implementation proves that: + +- a deterministic manifest cannot express one target/space composition without depending on live + state; +- app-local type binding necessarily becomes a published framework slow type; +- target identity cannot stay provider-independent; or +- ownership/history cannot remain distinct from query/runtime types. + +## 16. Unresolved items by gate + +### Must resolve before PLAN-EVAL + +None. The TypeScript/oRPC source audit closes the last package-boundary decision: current native +model-first `defineContract`, direct public authoring plus thin `defineDatabase`, two-phase +extension collection, const-preserving app-local fragment composition, plugin-owned full spaces by +default, and no provider re-export or copied overloads. PLAN-EVAL must verify these locks, not +reopen them from illustrative RC syntax. + +### Must resolve before implementation wave + +- W1: canonical manifest/digest encoding and public format-version policy. +- W3: exact Prisma import allowlist/version window, GA/RC pin, Deno/runtime matrix, native builder + conformance, namespace capability status, extension-bundle facets, and adapter experimental + status. +- W4: request/process lifecycle and transaction capability types. +- W5: plan signature schema, key custody before production, provider lock mechanism, receipt storage + location/retention, and crash-fault injection harness. +- W7: initial augmentation grant vocabulary and executable contribution phase allowlist. +- W10: migration window, legacy branch support end date, and release rollback runbook. + +### Safe to defer + +- Any second provider; Prisma SQLite/Mongo/MySQL/SQL Server support. +- Runtime capability negotiation (rejected until a concrete case exists). +- AOT validation. +- Archive/drop plugin removal beyond retain. +- Public raw/prepared/aggregate convenience APIs. +- Hosted approvals/RBAC/registry/promotion/fleet/continuous-drift/secret services. +- Cross-database relations and transactions (explicitly unsupported, not future parity debt). + +## 17. Conflict ledger and final recommendations + +| Source position | Finding | Final recommendation | +| ----------------------------------------------------------------------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Current-state audit: one database graph | Correct need, risky runtime noun. | Private compiler graph; public resolved manifest. | +| Qwen: three durable artifacts | Correct API-minimization pressure. | Three public responsibilities, five distinct artifact classes. | +| Opus: nine-node package graph | Correct doctrine separation, with one caution. | Adopt graph in §4; do not build speculative direct-SQL contingency backend. | +| Opus/Qwen: provider-neutral kernel, PostgreSQL-only implementation | Convergent. | Lock. | +| Opus: full input/output runtime validation | Too broad after pinned-source audit. | Bounded algebra, three schema classes, fail closed. | +| Opus: runtime/wire | Incorrect public naming after codec audit. | Use `runtime` and `json`; driver wire is internal. | +| Qwen: generated validator provider | Superseded by source proof and owner/maintainer direction. | Runtime interpreter default; optional equivalent AOT only. | +| Opus: provider re-export of Prisma builder | Conflicts with doctrine and moving exact surface. | Application imports native Prisma builder; provider adds wrapper/extension values only where publishable. | +| Owner: extend TypeScript schema like oRPC | Architecturally correct, mechanics differ. | Current native model-first builder + thin definition, const-preserving app-root composition, extension bundle fan-out; add DB-specific ownership/lineage/lifecycle. | +| TypeScript source: namespaces lower at runtime but flatten in type maps | Blocks a broad multi-schema claim. | Keep kernel axis, withhold adapter capability until no-cast type/runtime conformance passes. | +| Prisma contract spaces solve removal | Overclaim. | Ownership/history adopt; detach-retain first; archive/drop conditional. | +| Market analogies to Terraform/Atlas/Bytebase | Useful only with scope correction. | Import plan/recovery vocabulary; do not rebuild mutable/hosted control plane. | + +**[PROPOSAL] Final recommendation.** Lock the architecture described here, then submit it to the +separate-session PLAN-EVAL before creating the canonical RFC. The canonical RFC should optimize for +one extraordinary user journey: author provider-native TypeScript contracts and NetScript +target/space policy once; obtain query types, lifecycle-owned sessions, Standard Schema +trust-boundary validation, migrations, runtime wiring, CLI/CI evidence, plugin ownership, and agent +context automatically—without a copied schema, manually synchronized type, hand-written adapter, +textual repair, or implicit target choice. + +## 18. Local evidence register + +- Current NetScript reality: [netscript-current-state.md](./netscript-current-state.md). +- Prisma RC/current source, issues, PRs, and maturity: + [prisma-8-deep-dive.md](./prisma-8-deep-dive.md). +- Market comparators and corrected control-plane analogies: + [market-analysis.md](./market-analysis.md) and [market-gap-audit.md](./market-gap-audit.md). +- Owner/maintainer validation exchange: + [runtime-validation-maintainer-exchange.md](./runtime-validation-maintainer-exchange.md). +- Pinned-source validation feasibility/refusal boundary: + [runtime-validation-source-audit.md](./runtime-validation-source-audit.md). +- Native TypeScript builder evolution, oRPC transfer, extension bundles, namespace blocker, and + artifact boundary: [typescript-schema-orpc-audit.md](./typescript-schema-orpc-audit.md). +- Qwen adversarial minimal-kernel review: + [qwen-prisma-risk-review.md](./qwen-prisma-risk-review.md). +- Claude Opus package/runtime/control/contribution review: + [claude-opus-architecture-review.md](./claude-opus-architecture-review.md). +- Doctrine: `docs/architecture/doctrine/01-thesis-and-axioms.md`, `02-public-surface.md`, + `05-folder-structure.md`, `06-archetypes.md`, `07-composition-and-extension.md`, + `08-runtime-state-failure.md`, `09-anti-patterns-and-fitness-functions.md`, and + `11-plugin-thinness-and-base-seams.md`. +- Harness Plan-Gate: `.llm/harness/gates/plan-gate.md` and + `.llm/harness/gates/archetype-gate-matrix.md`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md new file mode 100644 index 0000000000..4401cc3f05 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/claude-opus-architecture-review.md @@ -0,0 +1,2004 @@ +# Independent Database Architecture Deep Dive — Claude Opus 5 High + +Subordinate architecture/research lane for run `docs-database-architecture-rfc--prisma-8-rfc`. This +is **not** PLAN-EVAL. It is an independent report intended to be consumed by the supervisor when +locking the Plan-Gate. + +Part 1 of 3. Continuation marker at end of file. + +--- + +## 1. Route identity, evidence provenance, and lane disclosures + +### 1.1 Requested versus observed identity + +| Field | Requested (brief) | Observed (this session) | +| ------------ | ------------------------------------------------------ | ---------------------------------------------------- | +| Provider | Anthropic | Anthropic | +| Surface | Native Claude Code | Native Claude Code CLI, `CLAUDE_CODE_ENTRYPOINT=cli` | +| Model | Opus 5 | `claude-opus-5` | +| Effort | high | `CLAUDE_EFFORT=high` | +| Client build | — | Claude Code `2.1.231` (`CLAUDE_CODE_EXECPATH`) | +| Host | `/home/codex/repos/netscript-db-rfc` | same; WSL2 Linux 6.18.33.2, user `codex` | +| Branch | `docs/database-architecture-rfc` | same | +| Baseline | `origin/main@cd720529333328bcba5e1a308ce7632f4350efdf` | same | + +**Session/handle chain.** This lane spanned three process boundaries. The original architecture +session was `3f8a9a69-5589-4b91-9a32-91f7770fe7c2` (`CLAUDE_CODE_CHILD_SESSION=1`, bridge handle +`session_01JusEvesoAn7Jjo2EDPPMcZ`, PID 1944525, job dir `/home/codex/.claude/jobs/3f8a9a69`). It +performed the required reading, the specialist fan-out, and the direct source verification recorded +below, then exited at a bridge boundary immediately after creating the report placeholder. The +resumed session is `f79af5bb-e953-4aae-9585-a1c83e73a00d`, which performed the targeted gap-closing +reads and authored this report. Model and effort are identical across both. + +### 1.2 Workflow and sub-agent disclosures + +No Claude dynamic **Workflow** was used. The Workflow tool was not invoked at any point in this +lane; CLAUDE.md scopes Claude workflows to a supervisor accelerator and this lane's work was +evidence extraction plus synthesis, which fan-out sub-agents served directly. Delegation used the +`Agent` tool only. + +| Identifier | Role | Model | Status | Consumed? | +| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------- | ------------------------------------------------------------------------------------ | +| `a1dc0e7df5546aa82` | NetScript doctrine, archetype definitions, gate matrix, Plan-Gate text, arch-debt scan, RFC process/template extraction | inherited (Opus 5) | **completed** | **Yes — fully.** Load-bearing for §3 and for every doctrine citation in this report. | +| `a37ac7656406f51bb` | Prisma 8 RC control-plane + runtime + contract-space API signature extraction | inherited (Opus 5) | **lost at process exit; no result returned** | No | +| `a34be5940cff46313` | Adversarial falsification of the Prisma deep-dive's numeric claims | inherited (Opus 5) | **lost at process exit; no result returned** | No | +| `a81f742dd6bc62971` | Adversarial fact-check of the NetScript current-state audit | inherited (Opus 5) | **lost at process exit; no result returned** | No | +| `a0529d68dcea25a85` | Relaunch: Prisma RC numeric + seam re-verification | Sonnet | **stopped at process exit; no result returned** | No | +| `a540186ffe4827b0e` | Relaunch: NetScript db CLI/resolver/installer re-verification | Sonnet | **stopped at process exit; no result returned** | No | + +**Truthful disclosure.** Five of six sub-agents returned nothing. One returned a complete result. +Everything in this report that is marked `[OBSERVED]` was therefore verified either by the completed +doctrine agent or by my own direct reads and greps in this worktree, cited by `path:line`. Claims +that originate only in the committed research documents and that I could **not** re-verify in this +session are explicitly marked `[CARRIED — NOT RE-VERIFIED]`. They must be re-proved before the +canonical RFC cites them; I flag this as a Plan-Gate obligation in Part 3. + +### 1.3 Evidence vocabulary used throughout + +- `[OBSERVED]` — I read the file or ran the command in this worktree; citation given. +- `[CARRIED — NOT RE-VERIFIED]` — asserted by `research/netscript-current-state.md`, + `research/prisma-8-deep-dive.md`, or `research/market-analysis.md`; plausible; not independently + confirmed here. +- `[INFERENCE]` — my reasoning from observed facts. +- `[PROPOSAL]` — my design recommendation. + +### 1.4 Precision corrections applied + +Per the supervisor's correction, and used consistently from here on: the root catalog pins Prisma at +`^7.8.0`; generated workspace templates encode `^7.4.2`; the generated database workspace currently +emits **30** database tasks (the current-state audit's "more than twenty" understates it). RC-tag +facts (`v8.0.0-rc.1`, `a76a6c5`) are kept strictly separate from post-RC `main` churn (`71e2e0d`) +everywhere in this report; where a claim depends on post-RC main it is labelled as moving, never as +a contract. + +--- + +## 2. Independent verdict and architectural thesis + +### 2.1 Verdict + +**The direction in the committed research is correct, and its central abstraction is named wrong in +a way that will produce the wrong package if it is carried into the RFC unchanged.** + +I agree with the research on the substance: five overlapping subsystems must collapse into one +NetScript-owned model; Prisma 8's contract/control/runtime split is the right shape to integrate +against; contract spaces are the right ownership primitive; engine-as-identity must die; generated +source must stop being textually patched; offline work must stop requiring Aspire. Those conclusions +survive independent scrutiny. + +I disagree on three points that change the design: + +1. **`DatabaseGraph` is correct as a compile-time intermediate representation and wrong as a runtime + object.** A "graph" that exists at runtime, that features can reach into to obtain a target, is a + service locator wearing a domain name. The durable artifact is not a graph — it is a **compiled, + content-addressed manifest**, which is a _value_: diffable, cacheable, signable, transportable to + CI, consumable by agents, and comparable across builds. A graph is how you build it, not what you + ship. Everything the research wants from `DatabaseGraph` — inspection, provenance, digests, agent + surface, deterministic CI — are properties of a manifest, not of a live object graph. + +2. **The plan's archetype set is incomplete and therefore its gate set is under-scoped.** The plan + names future Archetype 1/2/4/5/6 surfaces. The runtime half of this system owns connection + lifetime, per-request and per-process scope, graceful close ordering, health/readiness, and + `AbortSignal` propagation. That is Archetype 3 — "packages that own long-running behavior with + state, lifecycle, and supervised execution" (`docs/architecture/doctrine/06-archetypes.md:78-83`) + `[OBSERVED]`. Archetype 3 makes **all** fitness gates F-1 through F-19 required and makes + **runtime gates required**, not optional (`.llm/harness/gates/archetype-gate-matrix.md:20-65`) + `[OBSERVED]`. Omitting A3 silently omits a mandatory gate column. + +3. **A repo-wide constraint that no research document mentions determines the package boundary.** + NetScript compiles with `isolatedDeclarations: true` repo-wide (`deno.json` `compilerOptions`) + `[OBSERVED]`, and doctrine restricts the `--allow-slow-types` carve-out to oRPC-bound packages + only — `packages/contracts` and plugin `-core`/`services` packages extending the contract base + classes — with the explicit rule that "any other package that sets `--allow-slow-types` is a + finding and must carry a debt entry" (`docs/architecture/doctrine/02-public-surface.md:217-242`) + `[OBSERVED]`. A database package is not covered. Prisma 8's application-facing type is derived by + inference from the emitted contract. **Therefore no published `@netscript/*` package may export a + contract-typed runtime value.** This is not a stylistic preference; it is a hard publishability + constraint that decides where the typed binding lives. I develop the consequence in §3 and §5. + +### 2.2 Thesis + +> NetScript's durable database asset is a **compiled manifest plus a narrow provider port**, not a +> database abstraction. NetScript owns _identity, composition, ownership, lifecycle, and +> operations_. The provider owns _language, execution, and diffing_. NetScript never abstracts the +> query surface — it delivers a correctly-scoped, lifecycle-owned, target-typed handle and gets out +> of the way. + +The single most valuable rule in this design is a refusal: **NetScript does not define a query +API.** Every framework that has tried to sit above an ORM and normalise its query surface has +produced a second, worse ORM with a smaller feature set and a larger bug budget. The research names +this risk ("Replacing manual glue with a larger proprietary abstraction", `plan.md` risk register) +but does not convert it into a structural rule. The structural rule is: the kernel packages contain +**zero query types**. The query surface reaches the application as a generic type parameter that the +application's own generated code supplies. If a future provider replaces Prisma, the kernel does not +change shape; only the generic argument does. + +### 2.3 Non-negotiable invariants + +These are the properties I would refuse to trade in review. Each is stated so it can be mechanically +checked. + +- **I-1 Identity is declared, never derived.** A target's identity is a user-chosen stable key. No + artifact path, migration lineage, runtime binding, receipt, or output root may be derived from a + provider or engine name. +- **I-2 One owner per storage object.** Every owned object resolves to exactly one contribution + space. Overlapping ownership is a compile-time error, not a runtime collision. +- **I-3 Composition is pure.** Compiling a definition into a manifest performs no network, no + database, no Aspire, and no process spawn. It is a total function from source to + `Result`. +- **I-4 Determinism is content-addressed.** The same inputs produce the same manifest digest; every + emitted artifact root records the digest that produced it; a mismatch is detectable without a + database. +- **I-5 No generated source is ever textually repaired.** Artifacts are produced from an IR by a + provider and replaced atomically, or they are not produced. +- **I-6 Nothing reports success from an exit code.** Every operation returns a typed result and a + receipt with per-target, per-space phase outcomes. +- **I-7 Capability requirements fail early.** A space that needs a capability the target cannot + provide fails at composition or type-check, never at a late database call. +- **I-8 No published NetScript package re-exports upstream provider types.** Enforced by doctrine + AP-14 (`09-anti-patterns-and-fitness-functions.md:112-116`) `[OBSERVED]` and by the + slow-types/`isolatedDeclarations` constraint in §2.1(3). +- **I-9 Cross-target atomicity is never claimed.** Multi-target apply is a resumable saga with + explicit partial-success reporting. +- **I-10 Data is never destroyed implicitly.** Uninstall, removal, and destructive plan steps + require an explicit, environment-aware policy decision; the default is retention. + +### 2.4 What this redesign explicitly is not + +Stating the refusal boundary is as load-bearing as stating the design; +`rfcs/0003-command-composition-kit.md` carries a "Precise refusal boundary" subsection for exactly +this reason `[OBSERVED]`. + +- **Not a query abstraction.** No `Repository`, no portable `findMany`, no NetScript query DSL. +- **Not a portability layer.** NetScript will not make PostgreSQL and SQLite look identical. + Provider differences are surfaced as capabilities, not hidden behind a lowest common denominator. +- **Not a compatibility layer.** No Prisma 7 facade, no legacy generated module, no alias barrel, no + `setClient` lifecycle, no runtime shim. Data migration safety is required; API compatibility is + not. +- **Not a schema language.** NetScript does not invent a third model DSL. The application's data + contract stays in the provider's authoring language. NetScript's DSL composes _targets, spaces, + policy, capabilities, and lifecycle_ — never entities. +- **Not a control plane product.** Atlas-class semantic lint, promotion pipelines, and hosted policy + registries are out of scope; the plan/approve/apply/verify _state machine_ is in scope so that + such a backend could be added later as one more adapter. +- **Not an implementation.** This is a design report feeding an RFC. Nothing here authorises code. + +--- + +## 3. Target package, ownership, and dependency graph + +### 3.1 Doctrine constraints that decide the shape + +Four doctrine rules bind the partition, all `[OBSERVED]` via the completed doctrine agent: + +- **One archetype per package.** "If two archetypes apply, choose the larger one and fold the + smaller concerns inside it. Do not split one package across two archetypes" + (`.llm/harness/archetypes/README.md:23-26`). Where two archetypes genuinely apply and neither can + be folded without harming the other's gate profile, the correct move is **two packages**, not one + package with two shapes. That is the reasoning behind splitting definition from runtime below. +- **Ports are small.** AP-3 caps a port at three or four methods and names "a port with every + operation the backend can perform" as the integration-package failure mode + (`09-anti-patterns-and-fitness-functions.md:46-52`; `ARCHETYPE-2-integration.md:55`). The current + `DatabaseAdapter` — client lifecycle plus health plus status plus raw query plus + `setClient` — is a live AP-3 god interface and must be split, not renamed. +- **Engine selection is a typed registry, never a switch.** AP-24's canonical counter-example is + literally a database-engine switch over `'postgres' | 'mysql' | 'sqlite'` + (`09-anti-patterns-and-fitness-functions.md:167-198`). The current `mapEngine` switch in + `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:96+` is that anti-pattern in the + shipped code `[OBSERVED]`. +- **Surface size is capped.** F-5 caps a `mod.ts` at ~20 exported symbols and subpaths are semver + surface (`02-public-surface.md:111-138`). + +### 3.2 The packages + +Names are indicative; the archetype assignment and the dependency direction are the contribution. + +| Package | Archetype | Owns | Must not contain | +| ------------------------------------- | ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| `@netscript/database-contract` | **1 — Small Contract** | Branded identities, manifest schema, capability vocabulary, ownership policy vocabulary, diagnostic/error code catalog, operation request/result/receipt/progress types, the contribution-space descriptor type, and the port _interfaces_ shared by more than one consumer. Pure types and small invariants; no IO. | Any runtime, any provider, any query type, any Prisma import. | +| `@netscript/database` | **4 — Public DSL / Builder** | `defineTarget`, `defineSpace`, `defineDatabase`, and the pure compiler `compileDatabase(definition) → Result`. Frozen definition objects; one file per builder concern per `06-archetypes.md:127-155`. | IO, connections, provider packages, Aspire, filesystem access other than through an injected port. | +| `@netscript/database-runtime` | **3 — Runtime / Behavior** | Binding a manifest + provider to live connections; process and request scope; connection lifetime; graceful close ordering; health/readiness; `AbortSignal` propagation; `{ stop() }` handles; diagnostics normalisation. | Query types, migration logic, CLI presentation, Prisma imports. | +| `@netscript/database-control` | **2 — Integration** | The operation plane behind small ports: emit, plan, apply, verify, introspect. Owns locking, receipts, resume, plan expiry, destructive policy, and cross-target sequencing. | Provider-specific SQL, query surface, Aspire specifics. | +| `@netscript/database-prisma-postgres` | **2 — Integration** | The _only_ package permitted to import `@prisma/orm-*`. Supplies a capability descriptor, a contract emitter, a control adapter, and a runtime factory. Independently versioned and released. | Being imported by anything except an application composition root and the testkit. | +| `@netscript/database-testkit` | **6 — CLI / Tooling** | Provider conformance certification as user-run automation: a runnable suite that certifies a provider against the capability contract and emits a machine-readable conformance report. | Being a dependency of any runtime package. | +| `@netscript/cli` (existing, A6) | **6 — CLI / Tooling** | The `db` command surface as a _projection_ of the control operation catalog, plus generated agent-manifest emission. | Any database logic not reachable through `@netscript/database-control`. | +| `@netscript/aspire` (existing, A2) | **2 — Integration** | One `ConnectionSourcePort` adapter that resolves an allocated Aspire endpoint. | Being required by any package for non-Aspire connection sources. | +| `@netscript/plugin` (existing, A4) | **4 — DSL / Builder** | `defineDatabaseSpace`, typed **only** by `@netscript/database-contract`. | Depending on `-runtime`, `-control`, or any provider — otherwise every plugin drags a driver into its graph. | + +**Why definition and runtime are two packages.** They have incompatible gate profiles and +incompatible dependency needs. The definition/compiler package must be usable in a CI job with no +driver, no database, and no provider installed — that is what makes offline determinism and +stale-artifact detection cheap. The runtime package owns lifecycle and therefore carries Archetype +3's mandatory runtime-gate column. Folding them produces a package that is either over-gated when +used as a pure compiler or under-gated when used as a runtime. Doctrine's "do not split one package +across two archetypes" is satisfied by splitting the _packages_, which is the intended remedy. + +**Why control is separate from runtime.** Control operations are transactional, one-shot, and +frequently offline. Runtime operations are long-lived and connection-scoped. They share the manifest +and nothing else. Merging them reproduces the current failure in which a read-only database command +had to own the resident AppHost lifecycle. + +### 3.3 Dependency directions + +```text + @netscript/database-contract (A1, leaf, zero deps) + ^ ^ ^ ^ + | | | | + @netscript/database -runtime -control @netscript/plugin + (A4) (A3) (A2) (A4) + ^ ^ ^ + | | | + +--------+---------+ + | + @netscript/database-prisma-postgres (A2, leaf on the far side) + ^ + | + @netscript/database-testkit (A6) + + application composition root -> -database, -runtime, -control, one provider, emitted contract +``` + +Rules, each mechanically checkable: + +1. `-contract` imports nothing from this family. It is the only package every other member may + depend on. +2. `-database` (A4) depends on `-contract` only. It never imports a provider. +3. `-runtime` and `-control` depend on `-contract` and may depend on `-database` for manifest types + they do not redeclare. They never import each other, and never import a provider. +4. Provider packages depend on `-contract` and on upstream. **Nothing in the framework depends on a + provider.** Providers are selected by the application, passed in as a value. +5. `@netscript/plugin` depends on `-contract` only. This is the rule that keeps `pg` out of every + plugin's dependency graph. +6. The testkit may depend on everything; nothing may depend on the testkit. + +### 3.4 Ownership map — which concept is a durable public contract + +This resolves the minimal-kernel tension the brief asks about explicitly: not everything in this +design is public API, and conflating the two is how the current system grew five overlapping +subsystems. + +| Concept | Status | Rationale | +| ----------------------------------------------------------------------- | -------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | +| Target identity, space identity, namespace reference, object key | **Durable public data contract** (`-contract`) | These are the join keys for every artifact, receipt, and diagnostic. They must be stable across provider replacement. | +| Manifest schema and manifest digest | **Durable public data contract** | It is the CI/agent/runtime interchange format. Versioned with an explicit format version. | +| Capability vocabulary and ownership policy vocabulary | **Durable public data contract** | Plugins and providers both declare against it. | +| Diagnostic/error codes, operation request/result/receipt/progress types | **Durable public data contract** | The CLI, CI, and agent surfaces are projections of these; log parsing must become impossible. | +| Contribution-space descriptor | **Durable public data contract** | It is a third-party authoring surface. | +| `defineTarget` / `defineSpace` / `defineDatabase` | **Public API**, but a builder, not data | A4 surface; `defineX` returns a frozen definition per `02-public-surface.md:73-82`. | +| Provider ports (emitter, control, runtime factory, connection source) | **Public SPI**, small, each ≤4 methods | Third-party providers must be possible without forking. | +| The compiler's internal phases, graph structures, resolution order | **Internal** | Nobody outside needs them; publishing them freezes the implementation. | +| The provider registry instance | **Internal, constructed at the composition root** | Publishing a mutable registry is how a service locator is born. | +| The query surface | **Consumer-owned**, supplied as a generic argument | See §2.2 and §5.4. | +| The typed per-target binding | **Consumer-owned**, generated into the application | Forced by `isolatedDeclarations` + slow-types; see §2.1(3). | + +### 3.5 Doctrine registration obligations + +Two obligations follow that the plan does not currently carry `[OBSERVED]`, both from the doctrine +agent's extraction: + +- Every new package must be added to **both** `docs/architecture/doctrine/06-archetypes.md` + (archetype table, `:374-411`) and `docs/architecture/doctrine/10-codebase-verdict-and-handoff.md` + (verdict table, `:25-62`), because `discoverDoctrineRoots()` gates exactly the paths in that table + (`10:90-95`). An unregistered package is an ungated package. +- Doctrine currently **codifies the model this RFC removes**: Archetype 5 states that plugin schema + contributions "are plain `*.prisma` files referenced from `database/`. They do not contain a + private workspace" (`06-archetypes.md:209-211`). The RFC must amend doctrine, and amending + doctrine is itself an RFC trigger (`rfcs/README.md:14-32`). This is in scope for the same RFC, and + the plan should say so. + +--- + +## 4. The identity model + +Identity is where the current system fails first, so it is where the design must be most precise. +The current system collapses at least four distinct identities into the string `engine`. + +### 4.1 What is wrong today, observed + +- `workspaceDir` is computed as `join('database', provider.dirName)` where `provider` is looked up + from a closed engine enum (`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:50`) + `[OBSERVED]`. Two PostgreSQL targets therefore share one schema tree, one migration history, one + generated client, and one task set. The identity of a _logical database_ has no representation. +- `resolveTarget` defaults only when exactly one target is enabled: + `if (!dbFlag && enabled.length === 1) return { kind: 'single', database: enabled[0] }` + (`workspace-resolver.ts:71-77`) `[OBSERVED]`. With two or more enabled targets and no `--db`, the + lookup falls through and throws `Unknown database target: (default)`. `NetScript.PrimaryDatabase` + is never consulted here. The audit's claim is confirmed, and the failure is a throw rather than a + silent wrong-target selection, which is the better of the two failure modes. +- The plugin installer's target-selection chain is + `enabled.find(configKey === primaryDatabase) ?? enabled[0] ?? databases[0]` + (`packages/cli/src/kernel/adapters/plugin/db-integration.ts:101-105`) `[OBSERVED]`. The final + fallback drops out of the `enabled` filter, so a plugin can be installed into a **disabled** + target. The audit does not surface this. +- `--db` accepts either a config key or an engine name, resolved by + `explicitDb.toLowerCase() as DbEngine` after a config-key lookup fails + (`db-integration.ts:275-300`) `[OBSERVED]`. Two identity spaces share one flag and one string + type. +- The config schema accepts provider aliases — `postgresql|postgres`, `mssql|sqlserver` + (`packages/config/src/domain/schemas/database-schema.ts`) `[OBSERVED]` — and `mapEngine` + normalises `'Postgres'|'postgres'` (`workspace-resolver.ts:96+`) `[OBSERVED]`. Two normalisation + sites for one concept. + +### 4.2 The proposed identities + +Each is a branded primitive, which doctrine sanctions for non-interchangeable ids +(`02-public-surface.md:85-99`) `[OBSERVED]`. + +| Identity | Shape | Stability | Derived from | +| ------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------- | +| **TargetId** | `'primary'`, `'analytics'` | Permanent; renaming is a breaking migration | Author's choice. **Never** a provider name. | +| **ConnectionProfileId** | `'local'`, `'ci'`, `'production'` | Per environment | Author's choice; orthogonal to TargetId. | +| **RoleRef** | `(TargetId, 'writer' \| 'reader:')` | Derived | A replica is a _role of a target_, not a target. | +| **NamespaceRef** | `(TargetId, namespace)` | Permanent | Author's choice; a physical schema inside one database. | +| **SpaceId** | `'app'`, `'plugin:@netscript/plugin-auth'` | Permanent per contributor | Package identity for plugin spaces; fixed literal for the app. | +| **ObjectKey** | `(TargetId, namespace, entryKind, name)` | Derived | The unit of ownership; I-2 is stated over this key. | +| **ContractSnapshotId** | content hash of a space's canonicalised contract | Derived | Content-addressed. | +| **MigrationNodeRef** | `(SpaceId, ContractSnapshotId)` + optional human ref | Derived + author's label | Lineage nodes are content-addressed; names are labels, not identity. | +| **HeadRef** | `(SpaceId, TargetId) → MigrationNodeRef` | Mutable state | Recorded both in the manifest (intent) and in the database marker (fact). Divergence is drift. | +| **ManifestDigest** | content hash over the canonical manifest | Derived | The determinism anchor (I-4). | +| **PlanId** | `hash(ManifestDigest, TargetId, baselineFingerprint, providerPackageSet, policy)` | Derived | Binds a plan to everything that could invalidate it. | +| **RunId** / **ReceiptId** | ULID-like, supplied by the caller or generated at the edge | Per execution | Receipts are addressable and resumable. | +| **SessionScope** | `'process' \| 'request'` | Per binding | A _type-level_ discriminator, not a config flag. | + +Three deliberate consequences: + +1. **Provider is an attribute of a target, never its identity.** `primary` and `analytics` may both + be PostgreSQL and share nothing. This is the single change that makes + `db add postgres --name + analytics` mean what users already believe it means. +2. **A replica is not a target.** Modelling replicas as targets is how Rails users end up migrating + a read replica. A role is a binding-time choice with a read-only runtime type; migrations are + defined over targets and cannot address a reader role at all. +3. **Scope is a type, not a flag.** The request-scoped runtime and the process-scoped runtime are + different types with different capabilities. Prisma's serverless facade already demonstrates that + the asymmetry is real rather than cosmetic `[CARRIED — NOT RE-VERIFIED]`; making it a type + prevents the class of bug where a closure caches a per-request handle. + +### 4.3 Invariants over the identity model + +Compilation is the enforcement point. Each invariant maps to a diagnostic code (Part 2 carries the +catalog). + +- **V-1** Every `SpaceId` binds to exactly one `TargetId`. A space never spans databases. +- **V-2** Every `ObjectKey` has exactly one owning space with `ownership: 'managed'`. Two managed + owners is an error; a managed owner overlapping an `external` declaration is an error. +- **V-3** Cross-space references are legal only within one `TargetId` **and** only along a declared + `dependsOn` edge. A relation across targets is an error with a next-action that points at the + application-level composition pattern instead. +- **V-4** The space dependency graph is acyclic; execution order is its topological order, and the + order is recorded in the manifest so it is reviewable rather than emergent. +- **V-5** Every space's `requires` capability set is a subset of its target's provider capability + set, checked at compile time and, where expressible, at type-check time. +- **V-6** No two targets share an output root, a migration root, or a runtime binding key. +- **V-7** `ManifestDigest` is a pure function of the definition plus the resolved space contract + snapshots plus the provider package set. Nothing environmental participates. +- **V-8** Every emitted artifact root records the `ManifestDigest` that produced it. Runtime binding + refuses a mismatch with a diagnostic naming the exact command to run. + +--- + +## 5. Public API and DSL sketches + +These are implementation-grade sketches, not nouns. They are written to satisfy +`isolatedDeclarations` — every exported symbol has an explicit type — and to keep every published +type free of upstream generics. + +### 5.1 Identities and the manifest (`@netscript/database-contract`, A1) + +```ts +/** Author-chosen stable identity of one logical database. Never a provider name. */ +export type TargetId = string & { readonly __targetId: unique symbol }; +/** Author-chosen stable identity of one schema-contributing owner. */ +export type SpaceId = string & { readonly __spaceId: unique symbol }; +/** Content address of one space's canonicalised contract. */ +export type ContractSnapshotId = string & { readonly __snapshot: unique symbol }; +/** Content address of a compiled manifest. */ +export type ManifestDigest = string & { readonly __digest: unique symbol }; + +/** How much authority NetScript has over a set of storage objects. */ +export type OwnershipPolicy = 'managed' | 'adopted' | 'external' | 'ignored'; + +/** One capability a provider may offer and a space may require. */ +export type CapabilityId = string & { readonly __capability: unique symbol }; + +/** Fully-resolved, serialisable composition output. The CI/agent/runtime interchange format. */ +export interface DatabaseManifest { + readonly formatVersion: 1; + readonly digest: ManifestDigest; + readonly targets: readonly ManifestTarget[]; + readonly spaces: readonly ManifestSpace[]; + /** Topological execution order over spaces; recorded so review sees it. */ + readonly spaceOrder: readonly SpaceId[]; + readonly providerSet: readonly ProviderPin[]; +} + +export interface ManifestTarget { + readonly id: TargetId; + readonly family: string; + readonly provider: ProviderPin; + readonly namespaces: readonly string[]; + readonly capabilities: readonly CapabilityId[]; + readonly roles: readonly TargetRole[]; + readonly outputRoot: string; + readonly migrationRoot: string; + readonly policy: TargetPolicy; +} + +export interface ManifestSpace { + readonly id: SpaceId; + readonly version: string; + readonly target: TargetId; + readonly ownership: OwnershipPolicy; + readonly requires: readonly CapabilityId[]; + readonly dependsOn: readonly SpaceId[]; + readonly owns: readonly ObjectKey[]; + readonly snapshot: ContractSnapshotId; + readonly removal: RemovalPolicy; +} + +export interface ObjectKey { + readonly target: TargetId; + readonly namespace: string; + readonly entryKind: string; + readonly name: string; +} +``` + +Note what is absent: no provider types, no query types, no generics that could become slow types. +`DatabaseManifest` is plain data and can be serialised, hashed, diffed, and shipped to CI. + +### 5.2 The definition DSL (`@netscript/database`, A4) + +```ts +export interface TargetDefinition { + readonly id: TId; + readonly provider: ProviderDescriptor; + readonly connection: ConnectionSourceRef; + readonly namespaces: Readonly>; + readonly roles?: Readonly>; + readonly policy: TargetPolicy; +} + +/** Frozen definition; performs no runtime work. */ +export declare function defineTarget( + input: TargetInput, +): TargetDefinition; + +export declare function defineSpace( + input: SpaceInput, +): SpaceDefinition; + +export interface DatabaseDefinition< + TTargets extends Readonly>>, + TSpaces extends readonly SpaceDefinition>[], +> { + readonly targets: TTargets; + readonly spaces: TSpaces; +} + +export declare function defineDatabase< + TTargets extends Readonly>>, + TSpaces extends readonly SpaceDefinition>[], +>( + input: { readonly targets: TTargets; readonly spaces: TSpaces }, +): DatabaseDefinition; + +/** Pure. No network, no database, no Aspire, no process spawn. */ +export declare function compileDatabase( + definition: DatabaseDefinition, + sources: ContractSourceReader, +): Promise; + +export type CompileResult = + | { + readonly ok: true; + readonly manifest: DatabaseManifest; + readonly warnings: readonly Diagnostic[]; + } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] }; +``` + +Authoring, as a user would write it: + +```ts +// database.ts — the whole database story in one reviewable file +import { defineDatabase, defineSpace, defineTarget, prismaSchema } from '@netscript/database'; +import { postgres } from '@netscript/database-prisma-postgres'; +import { fromAspire, fromEnv } from '@netscript/database/connection'; +import { authDatabaseSpace } from '@netscript/plugin-auth/database'; + +const primary = defineTarget({ + id: 'primary', + provider: postgres({ minVersion: 15 }), + connection: fromAspire('netscript-db'), + namespaces: { app: 'public', auth: 'auth' }, + roles: { writer: {}, 'reader:reporting': { readOnly: true } }, + policy: { destructive: 'deny', defaultOwnership: 'managed' }, +}); + +const analytics = defineTarget({ + id: 'analytics', // same provider, different database, zero shared state + provider: postgres({ minVersion: 15 }), + connection: fromEnv('ANALYTICS_DATABASE_URL'), + namespaces: { warehouse: 'warehouse' }, + policy: { destructive: 'plan-only', defaultOwnership: 'adopted' }, +}); + +export const database = defineDatabase({ + targets: { primary, analytics }, + spaces: [ + defineSpace({ + id: 'app', + target: 'primary', // compile error if not a key of `targets` + namespace: 'app', + source: prismaSchema('./database/app'), + ownership: 'managed', + }), + authDatabaseSpace({ target: 'primary', namespace: 'auth' }), + ], +}); +export type AppDatabase = typeof database; +``` + +`target: 'primary'` is checked against `keyof typeof targets`. Misrouting a space is a type error at +the authoring site, not a runtime surprise at install time — which is precisely the class of failure +the plugin installer's `?? databases[0]` fallback produces today `[OBSERVED]`. + +### 5.3 Typed target references and composition (`@netscript/database-runtime`, A3) + +```ts +/** Scope is a type, not a flag: the two shapes are not interchangeable. */ +export type SessionScope = 'process' | 'request'; + +export interface TargetSession { + readonly id: TId; + readonly scope: TScope; + /** The provider's own surface, supplied by the application. NetScript never names it. */ + readonly query: TQuery; + health(signal: AbortSignal): Promise; +} + +/** Interactive transactions exist only on process scope. */ +export interface ProcessTargetSession + extends TargetSession { + transaction(fn: (tx: TQuery) => Promise, options?: TransactionOptions): Promise; +} + +/** Request scope is disposable and carries no cached collaborators. */ +export interface RequestTargetSession + extends TargetSession, AsyncDisposable {} + +/** Long-running handle, per Archetype 3 doctrine. */ +export interface DatabaseRuntime { + stop(): Promise; + health(signal: AbortSignal): Promise; +} + +export declare function createDatabaseRuntime( + options: DatabaseRuntimeOptions, +): Promise; +``` + +Two design points worth defending in review: + +- **`query` is a generic parameter, never a declared type.** This is what keeps every published + NetScript package free of upstream generics and therefore free of the slow-types problem in + §2.1(3). It also means replacing the provider changes one type argument, not the kernel. +- **`transaction` exists only on `ProcessTargetSession`.** The current `withTransaction` types its + callback parameter as the _full_ client — + `withTransaction(client: Client, fn: (tx: Client) => Promise, ...)` + with an unchecked cast (`packages/database/mod.ts:128-140`) `[OBSERVED]` — so + `tx.$transaction(...)` type-checks inside an interactive transaction. That is a type-level + correctness defect, not merely an unsafe cast; the current-state audit's phrase + "structurally-cast" understates it. + +### 5.4 The generated application composition root + +This is where the typed binding lives, and the reason is structural rather than stylistic: the +application is not published to JSR, so it may use inference freely; a framework package may not. + +```ts +// .netscript/database/primary.binding.ts — GENERATED. Do not edit. digest: +import contract from './primary/contract.json' with { type: 'json' }; +import type { PrimaryContract } from './primary/contract.d.ts'; +import { createPostgresQuery } from '@netscript/database-prisma-postgres/runtime'; +import type { ProcessTargetSession } from '@netscript/database-runtime'; + +export type PrimaryQuery = ReturnType>; +export type PrimarySession = ProcessTargetSession<'primary', PrimaryQuery>; +export const PRIMARY_MANIFEST_DIGEST = '' as const; +``` + +```ts +// composition-root.ts — hand-written, small, and the only place a target is looked up by name +const runtime = await createDatabaseRuntime({ + manifest, + definition: database, + providers: [postgresProvider], + targets: ['primary'], + scope: 'process', + connections, +}); +const primary: PrimarySession = runtime.bind('primary'); +const accounts: AccountStore = new PrismaAccountStore(primary); +``` + +**The service-locator boundary.** `runtime.bind()` is legal only in a composition root. Feature code +receives `AccountStore`, not the runtime — doctrine A10 requires exactly this +(`01-thesis-and-axioms.md:78-82`) `[OBSERVED]`, and a database handle reachable from anywhere is the +service locator the brief asks me to guard against. This is enforceable as an `arch:check` rule +(reachability of `bind`/`target` outside declared composition-root files), and Part 3 lists it as a +required fitness gate rather than a convention. + +### 5.5 Contract-derived validation + +The owner-provided Prisma-maintainer exchange establishes an important hypothesis: **the contract +carries enough runtime data to derive validation without a second generation step.** I treat this as +primary exploratory evidence and as a design hypothesis, **not** as an upstream commitment — Part 3 +records it as a decision checkpoint conditional on Prisma 8 final. + +The architectural consequence, if the hypothesis holds, is significant: the entire "generate Zod, +then rewrite its imports, then fix circular references, then rewrite getters, then patch decimals, +then emit an alias barrel, then fix it again" pipeline has no reason to exist. Validation becomes a +_derivation from data already present_, cached by contract identity. + +```ts +/** Standard Schema is the boundary contract; NetScript does not re-export a validator. */ +import type { StandardSchemaV1 } from '@standard-schema/spec'; + +export interface ContractSchemas { + input, TOp extends 'create' | 'update'>( + model: K, + op: TOp, + ): StandardSchemaV1>; + output>( + model: K, + ): StandardSchemaV1>; +} + +/** + * Default: derived at runtime from the contract, memoised by contract identity. + * No generation step, no emitted validator source, nothing to keep in sync. + */ +export declare function contractSchemas( + contract: ContractRuntime, + options?: { readonly cache?: SchemaCache }, +): ContractSchemas; +``` + +Three rules govern this surface: + +1. **Runtime-derived is the default.** Cached by contract identity (the emitted contract's own hash + plus model plus operation), so derivation happens once per process per shape. +2. **Any ahead-of-time form is an optional optimisation that must be observationally equivalent.** + An AOT emitter may exist for cold-start-sensitive deployments, but it is not the source of truth, + and a conformance case must assert that AOT and runtime-derived schemas accept and reject the + same corpus. If they can diverge, the AOT path is a second model universe and is rejected. +3. **NetScript exposes Standard Schema, not a validator.** `@standard-schema/spec` is already a + NetScript dependency (`packages/plugin/deno.json`, `packages/sdk/deno.json`) `[OBSERVED]`, and + doctrine AP-14 forbids re-exporting upstream packages + (`09-anti-patterns-and-fitness-functions.md:112-116`) `[OBSERVED]`. Consumers who want Zod import + Zod and adapt. + +This also removes a contradiction in the current core config contract: `DatabaseConfigSchema` +hardcodes a `zodGenerator` block with an `output` path and a `mode` enum +(`packages/config/src/domain/schemas/database-schema.ts`) `[OBSERVED]`, which bakes one validator +choice into the framework's configuration vocabulary. Under this design the config vocabulary +carries no validator at all. + +--- + +## 6. Contribution protocol: how a package owns part of a database + +### 6.1 What exists today, observed + +The current-state audit describes plugin schema contribution as "plugins declare schema by shipping +plain `database/**/*.prisma` files". That is true of the _runtime behaviour_, but it misses that +NetScript already publishes a contribution protocol which nothing implements: + +- `ContributionAxis` is a closed union that already contains `'database-schema'` and `'migration'` + (`packages/plugin/src/domain/constants.ts:16-26`) `[OBSERVED]`. +- `PluginDbSchemaContribution` is an exported abstract class with `axis = 'database-schema'`, an + abstract `path: string`, and an abstract `engine?: 'postgres' | 'mysql' | 'mssql' | 'sqlite'` + (`packages/plugin/src/abstracts/plugin-db-schema-contribution.ts`) `[OBSERVED]`. + `PluginMigrationContribution` adds `name` and `path` + (`packages/plugin/src/abstracts/plugin-migration-contribution.ts`) `[OBSERVED]`. Both are exported + from `@netscript/plugin/abstracts`. +- A repository-wide grep for implementations returns none: the only hits are the definitions, the + barrel re-exports, and an axis-list unit test `[OBSERVED]`. + +So the published contribution surface is hollow, and the four first-party plugins bypass it entirely +with plain fragments. Three consequences follow that the research does not state: + +1. **The clean break is a breaking change to `@netscript/plugin` (Archetype 4), not only to + `@netscript/database`.** Removing or replacing `PluginDbSchemaContribution`, + `PluginMigrationContribution`, and two members of the `ContributionAxis` union changes a + published package's public surface. The plan scopes future A1/A2/A4/A5/A6 surfaces but never + scopes this removal. +2. **The abstract already repeats the identity collapse.** + `engine?: 'postgres' | 'mysql' | 'mssql' | + 'sqlite'` is optional and names an engine, not a + target. Even the intended protocol could not express "this contribution belongs to the + `analytics` target". +3. **The fragments are already provider-locked while declaring nothing.** Across the four + first-party plugin schemas the native type attributes used are `@db.VarChar`, `@db.Text`, and + `@db.Uuid`, with `@db.Uuid` appearing in `plugins/triggers/database/triggers.prisma:13`, + `plugins/workers/database/workers.prisma:219`, and `plugins/sagas/database/sagas.prisma:57` and + `:179` `[OBSERVED]`. `@db.Uuid` is PostgreSQL-specific. Meanwhile the installer's + target-selection chain ends in `?? databases[0]`, which escapes the `enabled` filter + (`packages/cli/src/kernel/adapters/plugin/db-integration.ts:101-105`) `[OBSERVED]`. Today a + plugin whose schema only compiles on PostgreSQL can be copied into a disabled MySQL target, and + nothing in the pipeline objects until Prisma fails to parse. + +Model naming reinforces the point: `plugins/auth` and `plugins/sagas` prefix their declarations +(`AuthUser`, `SagaInstance`), while `plugins/workers` and `plugins/triggers` do not +(`JobDefinition`, `TaskDefinition`, `WrapperType`, `TriggerEvent`, `TriggerDefinition`) +`[OBSERVED]`. The namespacing remedy from the historical collision fix was applied where the +collision happened, not as a protocol. `JobDefinition` remains a globally-scoped name in a shared +declaration space. + +Finally, the contribution's _capability declaration_ today is a boolean: `scaffold.plugin.json` +carries `capabilities.hasDatabaseMigrations: true` (`plugins/workers/scaffold.plugin.json`) +`[OBSERVED]`. Plugin-level ordering exists (`officialSource.dependencies: ["streams"]`) but is not +connected to schema ordering. + +### 6.2 The contribution DSL + +A contribution is a **space**: a versioned owner of a disjoint set of storage objects, with its own +lineage. It is declared with types from `@netscript/database-contract` only, so a plugin that +contributes schema does not acquire a driver dependency. + +```ts +// plugins/auth/database/space.ts +import { defineDatabaseSpace, sql } from '@netscript/plugin/database'; +import { CAP } from '@netscript/database-contract/capabilities'; + +export const authDatabaseSpace = defineDatabaseSpace({ + id: 'plugin:@netscript/plugin-auth', + version: '0.0.7', + contractFormat: '>=1 <2', + + /** Declared, not inferred. Composition fails if the target cannot satisfy these. */ + requires: [CAP.sqlFamily, CAP.nativeUuid, CAP.caseInsensitiveText], + + /** Ordering is a declared edge, not install order. */ + dependsOn: [], + + /** Everything this space owns, and nothing else may own. */ + owns: { namespace: 'auth', entries: ['user', 'session', 'account', 'verification'] }, + + /** What another space may add to this space's objects, and what it may never touch. */ + augmentation: { + grants: [{ entry: 'user', kind: 'add-optional-column', prefix: 'x_' }], + denies: ['drop-column', 'change-type', 'add-required-column'], + }, + + ownership: 'managed', + + /** Uninstall is a plan, never a delete. */ + removal: { default: 'retain', allowed: ['retain', 'archive'], dropRequires: 'explicit-consent' }, + + source: sql.schema(import.meta.resolve('./contract.ts')), +}); +``` + +The consuming application binds it to a target explicitly: + +```ts +spaces: [authDatabaseSpace({ target: 'primary', namespace: 'auth' })]; +``` + +`target` is checked against `keyof targets` (§5.2). There is no primary-ish fallback, no +first-available fallback, and no engine string. If the author does not say where a contribution +goes, compilation fails with a diagnostic that lists the candidate targets — which is strictly +better than the current `?? databases[0]`. + +### 6.3 Provenance and the pinned mirror + +Installation never mutates another contributor's source and never copies declarations into the +application's schema tree. Instead, installation writes a **pinned mirror** under the application's +generated root: + +```text +.netscript/database/spaces/plugin--netscript--plugin-auth/ + space.json # descriptor snapshot: id, version, requires, dependsOn, owns, ownership + contract.json # the space's canonicalised contract at the pinned version + lineage/ # the space's own migration lineage nodes + PROVENANCE # package identity, resolved version, integrity hash, mirror digest +``` + +Three properties fall out. Production apply and verify read the mirror, not `node_modules`, so a +deployment does not need the plugin's package graph resolvable. The mirror digest is comparable +against the installed package's digest, which makes version skew detectable rather than latent. And +because the mirror is per-space, uninstalling a plugin removes a directory that owns nothing of the +application's. + +### 6.4 Lifecycle and its state machine + +| Transition | Precondition | Effect | Refusal conditions | +| -------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| **Install** | Target declared; `requires ⊆ target capabilities`; no `owns` overlap; `dependsOn` all present and acyclic | Mirror written; manifest recompiled; a plan is produced | Capability gap, ownership overlap, missing/cyclic dependency, contract-format mismatch | +| **Upgrade** | New version's `owns` diff is expressible; lineage from pinned head to new head resolvable | New mirror; lineage edges appended; plan produced | Non-linear lineage without an explicit resolve, ownership widening onto an object another space owns, capability regression | +| **Skew detected** | Installed package digest ≠ mirror digest | Refuse apply; emit `db.space.skew` with both digests and the sync command | — | +| **Uninstall** | Space is not a `dependsOn` of another installed space | Space unbound; retirement plan produced | A dependent space still installed; retention policy not satisfiable | +| **Retire (retain)** | Default | Objects remain; space marked orphaned; ownership downgraded `managed → adopted` so verify still notices drift instead of going blind | — | +| **Retire (archive)** | Allowed by policy | Objects moved to a quarantine namespace with a recorded reason and a restore path | Capability missing (e.g. no schema-move support) | +| **Retire (drop)** | Explicit consent + environment policy allows destructive | Destructive plan produced, requires approval like any destructive plan | CI without an approved plan; production without signed plan | + +The important asymmetry: **install is cheap and reversible; removal is a planned operation.** The +current removal path deletes the copied schema directory and plans nothing +`[CARRIED — NOT +RE-VERIFIED]`; under this protocol deleting a directory cannot be the removal, +because the directory was never the ownership record — the database marker and the manifest are. + +### 6.5 Ownership, conflict, and augmentation + +Conflict resolution today is byte comparison: identical normalised bodies are elided, and differing +bodies are rejected (`packages/cli/src/kernel/adapters/plugin/prisma-schema-writer.ts:133`) +`[OBSERVED]`. That is a _text_ policy standing in for an _ownership_ policy. It cannot express "this +plugin may add an optional column to that plugin's table", and it cannot distinguish "same +declaration, both owners" from "same name, different concept". + +The replacement is ownership-first: + +- **V-2 disjointness** (Part 1 §4.3) is checked over `ObjectKey`, not over text. Two managed owners + of one object is `db.space.ownership.conflict`, and the diagnostic names both spaces. +- **Augmentation is a grant, not a merge.** A space may only modify another space's objects along an + explicitly granted axis; the grant lives with the _owner_, which is the only party that can reason + about its own invariants. Denied axes are enumerated so the refusal is legible. +- **Namespaces make collisions structural rather than lexical.** `auth.user` and `app.user` are + different objects; no prefixing convention is required, and the `JobDefinition`-style unprefixed + global name stops being a hazard. +- **`external` and `ignored` are first-class.** An object marked `external` is excluded from + planning and diffing but still verifiable as assertions; `ignored` is excluded from everything + with a recorded reason. This is what makes hosted/managed databases workable rather than a + permanent source of false drift. + +### 6.6 Migrations, conformance, and coexistence with upstream extensions + +**Per-space lineage.** Each space carries its own lineage of content-addressed nodes; the database +holds one marker row per `(space, target)`. Applying a space advances only that space's marker. +Cross-space ordering is the topological order recorded in the manifest, so a reviewer can see it +before it runs. + +**Data transforms are edges, not a second folder.** The invariant-guarded transition model — a +precondition query that detects remaining work, a mutation plan, and a post-verification of the +invariant `[CARRIED — NOT RE-VERIFIED]` — is the right semantic model and NetScript should adopt it +rather than reinventing a timestamped data-migration directory. The historical failure mode in +comparable frameworks is exactly a second chronological sequence whose correctness depends on +invocation order. + +**A contributor conformance kit.** `@netscript/database-testkit` must certify a _space_, not only a +provider: given a space descriptor and an ephemeral target, it asserts that install → upgrade → +skew-detect → uninstall-retain → uninstall-archive all produce the declared outcomes, that `owns` is +truthful (nothing outside `owns` is touched), that `requires` is minimal-and-sufficient (removing +any capability makes composition fail; the declared set is enough to apply), and that augmentation +grants and denials are enforced. Without this, third-party contributions are a documentation +promise. + +**Coexistence with upstream extensions.** Prisma 8 extensions can themselves own contract spaces +`[CARRIED — NOT RE-VERIFIED]`. NetScript must not treat an upstream-owned space as unknown +territory: the manifest records it with `ownership: 'external'` and a provenance entry naming the +upstream extension, so verify accounts for its objects instead of reporting them as drift. NetScript +spaces and upstream extension spaces coexist under one disjointness check. + +--- + +## 7. Control plane: typed operations, receipts, and determinism + +### 7.1 What must be replaced, observed + +The current runner's entire result type is an exit code: `execute(request): Promise` +(`packages/cli/src/kernel/adapters/database/operation-runner.ts:85`) `[OBSERVED]`. Two behaviours +follow directly from that signature: + +```ts +if (request.operation === 'studio') { + return await this.executeOne(request, databases[0]); // silently the first target only +} +for (const database of databases) { + const code = await this.executeOne(request, database, controller.signal); + if (code !== 0) return code; // fail-fast, no per-target outcome +} +``` + +(`operation-runner.ts:90-105`) `[OBSERVED]` + +So `--db all` is sequential and fail-fast with no record of which targets succeeded, and `studio` +uses `databases[0]` regardless of the resolved target set. This is not a missing feature that +receipts would improve; **the return type makes structured reporting impossible.** Replacing it is +the load-bearing change, and it is why "add receipts" cannot be an incremental slice. + +The CLI surface itself is confirmed as fourteen verbs — `add`, `list`, `remove`, `init`, `generate`, +`migrate`, `seed`, `status`, `studio`, `introspect`, `reset`, `deploy`, `validate`, `resolve` +(`packages/cli/src/public/features/db/db-group.ts:32-53`) `[OBSERVED]`. + +### 7.2 Operation classification + +Classification is the mechanism that decouples pure work from orchestration, and it must be data on +the operation, not a convention. + +| Class | Examples | Requires connection | Requires Aspire | Requires lock | Produces receipt | +| ----------- | -------------------------------------------------------------------------------- | ------------------- | -------------------------------------------------- | ------------- | ---------------------- | +| `pure` | compose, validate, emit, format, lineage integrity check | No | **Never** | No | Yes (artifact receipt) | +| `live-read` | introspect, status, plan-against-live, verify | Yes | Only if the target's connection source _is_ Aspire | No | Yes | +| `mutating` | init, apply, seed, sign, retire | Yes | Only if the connection source is Aspire | **Yes** | Yes | +| `resident` | studio and any operation whose connection exists only inside a resident resource | Yes | Yes, explicitly selected | Advisory | Yes | + +The rule that matters: **Aspire is a property of a target's connection source, not of an operation +class.** The recorded architecture debt `DB-GENERATE-ASPIRE-COUPLING` documents the current inverse +— `DbOperationRunner.executeDetached` always runs `aspire start` before executing any database +operation, so pure codegen fails where the Aspire CLI or .NET is absent +(`.llm/harness/debt/arch-debt.md`, entry `DB-GENERATE-ASPIRE-COUPLING`) `[OBSERVED]`. Under +classification, `emit` cannot reach an orchestrator because a `pure` operation is not given a +connection resolver at all. + +### 7.3 Concrete operation types + +```ts +export type OperationClass = 'pure' | 'live-read' | 'mutating' | 'resident'; + +export interface OperationRequest { + readonly operation: TOp; + readonly manifestDigest: ManifestDigest; + /** Explicit target set. There is no implicit "all" and no implicit default. */ + readonly targets: readonly TargetId[]; + readonly spaces?: readonly SpaceId[]; + readonly policy: ExecutionPolicy; + readonly runId: RunId; + readonly signal: AbortSignal; +} + +export interface ExecutionPolicy { + readonly environment: 'development' | 'ci' | 'staging' | 'production'; + readonly destructive: 'deny' | 'plan-only' | 'allow-with-approval'; + readonly onPartialFailure: 'stop' | 'continue'; + readonly lockTimeoutMs: number; + readonly planMaxAgeMs: number; +} + +/** Every operation returns this. Nothing returns a number. */ +export interface OperationResult { + readonly runId: RunId; + readonly outcome: 'succeeded' | 'partially-succeeded' | 'failed' | 'refused'; + readonly perTarget: readonly TargetOutcome[]; + readonly diagnostics: readonly Diagnostic[]; + readonly receipt: Receipt; + /** Present iff outcome is 'partially-succeeded' or 'failed' and the run is resumable. */ + readonly resume?: ResumeToken; +} + +export interface TargetOutcome { + readonly target: TargetId; + readonly status: 'succeeded' | 'failed' | 'skipped' | 'not-attempted'; + /** Why a target was skipped or not attempted. No silent omissions. */ + readonly reason?: DiagnosticCode; + readonly spaces: readonly SpaceOutcome[]; + readonly value?: TOutcome; +} +``` + +**No silent skip.** Every target in the requested set appears in `perTarget` with a status, and +`skipped`/`not-attempted` carry a reason code. This is the direct answer to the market analysis's +strongest cross-product lesson — routing and filter mechanisms that silently omit work are the +recurring severe failure in Django-style multi-database systems. + +### 7.4 Plan, consent, expiry, and apply + +```ts +export interface MigrationPlan { + readonly planId: PlanId; + readonly target: TargetId; + readonly manifestDigest: ManifestDigest; + readonly baseline: BaselineFingerprint; // what the live database looked like when planned + readonly providerSet: readonly ProviderPin[]; + readonly spaceOrder: readonly SpaceId[]; + readonly steps: readonly PlanStep[]; + readonly destructive: readonly DestructiveOperation[]; + readonly capabilitiesUsed: readonly CapabilityId[]; + readonly createdAt: string; + readonly expiresAt: string; + readonly signature?: PlanSignature; // required in production +} + +export interface DestructiveOperation { + readonly kind: + | 'drop-entry' + | 'drop-column' + | 'narrow-type' + | 'add-required-without-default' + | 'unique-over-existing-data' + | 'namespace-drop'; + readonly object: ObjectKey; + readonly dataLossRisk: 'certain' | 'possible' | 'none'; + /** Present only when the provider proved it. Absence is not "safe". */ + readonly observedRowCount?: number; +} +``` + +Apply refuses a plan whose `manifestDigest`, `baseline`, `providerSet`, or target no longer match, +and refuses an expired plan. Consent is _not_ an interactive prompt: in `ci` and `production` the +policy must be `allow-with-approval` **and** the plan must carry a signature. An interactive "yes" +is a development affordance only. This is the ordering the research proposes and I endorse without +change. + +### 7.5 Progress, dotted diagnostics, and receipts + +```ts +export type DiagnosticCode = + | 'db.compose.ownership.conflict' + | 'db.compose.capability.missing' + | 'db.compose.dependency.cycle' + | 'db.space.skew' + | 'db.plan.stale' + | 'db.plan.expired' + | 'db.apply.destructive.refused' + | 'db.apply.lock.held' + | 'db.verify.drift' + | 'db.artifact.stale' + | 'db.target.ambiguous'; + +export interface Diagnostic { + readonly code: DiagnosticCode; + readonly severity: 'error' | 'warning' | 'info'; + readonly subject: ObjectKey | TargetId | SpaceId; + readonly message: string; // human text, never parsed by anything + readonly nextAction: NextAction; // structured: a command + args, not prose +} + +export type ProgressEvent = + | { readonly kind: 'span-start'; readonly span: SpanRef; readonly label: string } + | { readonly kind: 'span-end'; readonly span: SpanRef; readonly status: 'ok' | 'error' } + | { readonly kind: 'note'; readonly span: SpanRef; readonly diagnostic: Diagnostic }; + +export interface Receipt { + readonly receiptId: ReceiptId; + readonly runId: RunId; + readonly operation: OperationName; + readonly manifestDigest: ManifestDigest; + readonly startedAt: string; + readonly finishedAt: string; + readonly phases: readonly ReceiptPhase[]; // per target, per space, per step + readonly artifacts: readonly ArtifactAssertion[]; + readonly environment: string; + readonly toolVersions: readonly ProviderPin[]; +} + +/** A postcondition the operation proved, not a log line claiming it. */ +export interface ArtifactAssertion { + readonly path: string; + readonly expected: 'created' | 'unchanged' | 'replaced' | 'absent'; + readonly digestBefore?: string; + readonly digestAfter?: string; +} +``` + +`nextAction` being structured rather than prose is what lets the CLI, CI annotations, and the agent +surface all render the same remediation without any of them parsing text. This directly retires the +weakest link in the current gate: the merge-readiness migration fixture asserts on the literal +string `'created no migration artifact'` and refuses to run outside Linux +(`packages/cli/e2e/src/application/gates/scaffold/verify-db-migration-artifacts.ts`) `[OBSERVED]`. A +reworded message breaks the gate, and the platform where the historical schema-engine hangs occurred +is not covered by it at all. + +### 7.6 Locks, concurrency, resume, and CI determinism + +- **Lock scope is `(target, physical database)`,** acquired for `mutating` operations only, with an + owner identity, a heartbeat, and a TTL. A lock is a database-level advisory lock where the + provider has one and a ledger row with fencing otherwise; the capability is declared, so a + provider without either is refused for concurrent-safe apply rather than silently racing. +- **No shared stateful runner across targets.** Each target gets its own runner instance. This is + the concrete lesson from ORMs whose migration fan-out documents "shared instance parallel fan-out + is unsupported"; the architecture should make the unsupported configuration unrepresentable. +- **Resume is per `(runId, target, space, stepIndex)`.** A resumed run re-validates the plan against + the live baseline before continuing, so resume can refuse rather than compound a divergence. +- **Cross-target apply is a saga, never a transaction.** `partially-succeeded` is a first-class + outcome. Claiming atomicity across two databases would be a lie, and I-9 forbids it. +- **Offline determinism.** `pure` operations take a source reader and a clock port, never a network. + Emitting twice from a clean checkout must produce identical digests; emitting into distinct target + roots must be safe concurrently; artifacts are written to a temporary root and moved atomically so + an interrupted emit leaves either the old tree or the new tree, never a half-patched one. +- **CI cacheability.** The manifest digest is the cache key. A CI job that has already emitted for a + digest can skip emission and assert the recorded `ManifestDigest` in the artifact root instead + (I-4/V-8). Receipts are written as atomic JSON, which is the pattern this repository already uses + for gate evidence (`.llm/tools/gates/run-gate.ts` receipts under `.llm/tmp/gate-receipts/`) + `[OBSERVED]` — the database receipts should adopt that shape rather than invent a second one. + +### 7.7 The generated agent surface + +The agent surface is an _output_, not a maintained document: a generated manifest containing the +target/space inventory with capabilities and ownership, the command catalog with argument schemas +and result schemas, the diagnostic catalog with `nextAction` for each code, the +destructive/environment policy, the list of operations the resolved provider does **not** support, +and compile-checked import examples. Two rules keep it honest: it is regenerated from the manifest +plus the operation catalog on every emit, and a conformance case executes every generated example. A +generated skill that is not executed in CI decays exactly the way hand-maintained agent instructions +do. + +--- + +## 8. Prisma 8: adopt, wrap, defer, reject — and the volatility boundary + +### 8.1 Decisions + +| Upstream surface or idea | Decision | Reasoning | +| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Canonical contract artifact + type declaration ("types-only emission") | **Adopt** | Removes executable generated clients, which removes the entire textual-repair pipeline. This is the single highest-value upstream change for NetScript. | +| Domain/storage plane separation and per-plane hashes | **Adopt as internal identity; do not re-publish** | Excellent internal structure; the representation is explicitly still moving, so NetScript records its own manifest digest and treats upstream hashes as recorded attributes. | +| Family / target / adapter / driver / extension axis split | **Adopt conceptually** | Correct open-axis model; it is what makes "engine" stop being the only discriminator. | +| Contract spaces | **Adopt and extend** | The right ownership primitive. NetScript adds target binding, capability requirements, augmentation grants, removal/retention policy, and provenance — none of which upstream provides. | +| Migration lineage as content-addressed edges + per-space marker + ledger | **Adopt the semantics; own the operations** | See §8.2. | +| Invariant-guarded data transforms | **Adopt** | Correct model; NetScript generates the descriptor wiring rather than leaving planner placeholders for a human to fill. | +| Structured results, progress spans, dotted error codes | **Adopt and translate** | Enables §7 without log parsing. Translate into NetScript codes so upstream renaming is not a NetScript breaking change. | +| Programmatic control client | **Wrap behind a NetScript port, with a contingency backend** | See §8.3. This is where I diverge from the research. | +| PostgreSQL runtime facade | **Wrap; expose as a generic type argument** | Powerful, and far too upstream-specific to become NetScript-wide API. | +| Standard Schema for parameter validation | **Adopt** | Already a NetScript dependency; aligns the boundary. | +| Project-level agent skill | **Recreate from the NetScript manifest** | Direction is right; content generated from RC-era material is not trustworthy enough to consume. | +| CLI binary name and config file shape | **Do not bind** | RC-tag names are already not what post-RC `main` carries. Bind to the programmatic seam instead. | +| Public package re-exports | **Reject** | Doctrine AP-14, plus the slow-types constraint (Part 1 §2.1(3)). | +| Hand-written low-level driver adapters | **Reject by default** | The existing `@netscript/prisma-adapter-mysql` is the cautionary case. Require certification through the testkit if ever unavoidable. | +| Copied/merged schema fragments | **Reject** | No ownership, no lineage, no capability guard, no safe removal. | +| Generated-source text patching | **Reject** | I-5. | +| Universal lowest-common-denominator database API | **Reject** | Weakens every provider and hides real semantics. | +| Prisma 7 compatibility facade | **Reject** | Owner directive; also the source of the current architecture's shape. | +| MySQL / SQL Server as 8.0 targets | **Defer** | Not in the 8.0 target set. See §9.4. | +| Extension removal, shadow-database workflow, cross-target advisory locking, row-count-aware data-loss analysis | **Defer upstream; own in NetScript where required** | These are precisely the operational gaps §7 fills. | + +### 8.2 Where I diverge from the research: own the operational layer outright + +The research recommends adopting the migration graph "after conformance". I recommend a sharper +split. **Adopt the semantic layer** — content-addressed lineage nodes, per-space markers, +edge/ledger coupling, invariant-guarded transforms. **Own the operational layer outright** — +locking, receipts, resume, plan expiry and signing, destructive policy, cross-target sequencing, +partial-success reporting, and drift classification. + +The reason is that the operational gaps are not incidental: the absence of a mature +reset/resolve/diff/squash workflow, of a general shadow-database workflow, of a complete +advisory-lock story across targets, and of row-count-aware data-loss analysis +`[CARRIED — NOT RE-VERIFIED]` are all in the operational layer. If NetScript waits for upstream to +close them, adoption is gated on someone else's roadmap; if NetScript owns them, adoption is gated +only on the semantic layer, which is the part that is genuinely good. This also means these +operations are NetScript's to keep when a second provider arrives, rather than being re-acquired per +provider. + +### 8.3 Volatility containment + +The control API is the correct integration direction _and_ it is demonstrably moving: routing +migration and database commands through the control API, adding sectioned config diagnostics and a +control-client test double, and making command output channels explicit are all **post-RC `main`** +changes, not RC-tag facts `[CARRIED — NOT RE-VERIFIED]`. Pinning a moving seam inside a package that +must satisfy JSR publish gates is a real risk, so containment is structural rather than a version +pin: + +1. **One package may import upstream.** `@netscript/database-prisma-postgres` and nothing else. A + dependency-cruiser-style rule fails the build on any upstream import elsewhere. +2. **One module inside that package may name upstream symbols.** An `upstream.ts` facade module is + the sole import site; every other file imports from it. The blast radius of an upstream rename is + one file. +3. **An explicit import allowlist.** `@prisma/orm-postgres` publishes on the order of 138 top-level + export keys `[CARRIED — NOT RE-VERIFIED]`; the overwhelming majority are extension-author + surface. The allowlist enumerates the handful NetScript uses, and any newly-introduced deep + import fails a check. Without this, "we depend on Prisma" silently becomes "we depend on Prisma's + internals". +4. **The provider package is versioned and released independently of the kernel.** An upstream break + is then a provider patch release, not a framework break. This is the property that makes the + whole design survivable across an RC-to-GA transition. +5. **A contingency backend behind the same port.** The NetScript `ControlPort` must be satisfiable + by a second implementation that uses the emitted artifacts plus direct SQL, exercised in CI even + if it is never the default. A port with exactly one possible implementation is not containment; + it is a rename. +6. **Contract format version is a gate, not an assumption.** The manifest records the upstream + contract format version; a change is a deliberate migration with its own conformance run. + +--- + +## 9. Provider, engine, and runtime matrix + +### 9.1 Capability model, not a compatibility table + +Capabilities are an **open, provider-declared** set. The kernel never requires a capability; only +spaces do (I-7). This is the structural difference between a capability model and a portability +layer: adding a capability does not force every provider to implement it, and using one is a +compile-time decision. + +| Axis | Example capabilities | +| --------- | ------------------------------------------------------------------------------------------------ | +| Family | `sql`, `document` | +| Types | `nativeUuid`, `caseInsensitiveText`, `nativeEnum`, `jsonb`, `arrayColumn`, `vector` | +| Schema | `multiNamespace`, `namespaceMove`, `viewDefinition`, `checkConstraint`, `partialIndex` | +| Migration | `transactionalDdl`, `advisoryLock`, `shadowDatabase`, `rowCountEstimate` | +| Runtime | `interactiveTransaction`, `preparedStatement`, `streamingCursor`, `cancellation`, `externalPool` | + +Provider capability claims are not self-certified: they are what `@netscript/database-testkit` +proves against a live instance, and a claim without a passing conformance case is a conformance +failure. + +### 9.2 Target matrix and the PostgreSQL-first decision + +PostgreSQL is the only credible first implementation, and this is a decision rather than a +preference: it is the sole database intended for the 8.0 GA target set, with MongoDB earlier-stage, +SQLite proof-of-concept, MySQL later, and SQL Server absent `[CARRIED — NOT RE-VERIFIED]`. + +| Provider | Wave | Status | Notes | +| --------------------- | -------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| Prisma 8 · PostgreSQL | 1 | **Primary implementation** | Must pass the full conformance suite against a real PostgreSQL service, not an emulator. | +| Prisma 8 · SQLite | 3 | Candidate, capability-reduced | Useful for local/dev and for proving the capability model has teeth; must not be presented as production parity. | +| Prisma 8 · MongoDB | Deferred | Validates family abstraction | Proves the `family` axis is real; not a NetScript deliverable in the first waves. | +| MySQL | Deferred | Contingency, see §9.4 | | +| SQL Server | Deferred | Not in the upstream 8.0 target set | Requires a different provider entirely. | + +### 9.3 Multi-target, multi-schema, and external ownership semantics + +- **Same-provider multi-target** is the default case, not a special case. `primary` and `analytics` + may both be PostgreSQL; they share no output root, no lineage, no runtime binding, and no receipt + namespace (V-6). This is the concrete repair for `db add postgres --name analytics` resolving to + `database/postgres/` (`workspace-resolver.ts:50`) `[OBSERVED]`. +- **Same-database multi-schema** is namespaces within one target. Spaces own namespaces or object + sets inside them. +- **Cross-space relations** are legal within one target along a declared dependency edge (V-3). + Cross-_target_ relations are refused at composition with a diagnostic — the honest answer, since + no amount of framework code makes a foreign key work across two databases. +- **Replicas are roles** (Part 1 §4.2). A reader role yields a read-only session type and is not + addressable by any migration operation. +- **External/unmanaged** ownership is required, not optional. Hosted platforms evolve tables outside + the framework's knowledge; a framework that treats every visible object as its own reports + permanent false drift. `external` objects are excluded from plan and diff and included in verify + as assertions only. + +### 9.4 Runtime constraints: Deno, serverless, and the MySQL contingency + +NetScript is a Deno framework publishing to JSR, and the upstream posture is Node-primary with +Bun/Deno best-effort, a PostgreSQL facade that depends on `pg`, and TypeScript 5.9 as an +**optional** peer `[CARRIED — NOT RE-VERIFIED]`. "Deno is listed" is therefore not an adoption +argument. The platform gate must prove: a clean Deno import graph with no undeclared Node globals in +runtime paths; connect/query/transaction/stream/close/error-mapping behaviour against a real +service; no CLI or toolchain module reachable from a runtime graph; leak behaviour under repeated +start/stop and request lifecycles; and the supported bundler/deployment modes. + +Serverless is a _scope_, not a deployment flag: the request-scoped session type omits interactive +transactions and cached collaborators and is `AsyncDisposable` (Part 1 §5.3). The upstream +serverless facade's asymmetry is a precedent worth copying rather than smoothing over. + +**MySQL contingency.** The current `@netscript/prisma-adapter-mysql` implements Prisma's low-level +driver-adapter contracts directly `[CARRIED — NOT RE-VERIFIED]`; doctrine's verdict for it is _Keep_ +(`docs/architecture/doctrine/10-codebase-verdict-and-handoff.md:50`) `[OBSERVED]`, which reflects +its fit to the _current_ port, not its fit to this design. Under a clean break there are three +options: retire it and defer MySQL to an upstream target; port it to the new provider port and +certify it through the testkit; or keep it as an out-of-tree provider. I recommend **retire and +defer**, with the testkit path available if a MySQL requirement lands before upstream ships the +target. Carrying a hand-maintained low-level driver adapter through a clean break re-imports the +exact maintenance surface the redesign exists to remove. + +--- + +## 10. Pure-TypeScript schema authoring and the end-to-end type system + +### 10.1 The question, answered directly + +Prisma 8 supports both a schema language and a TypeScript contract builder, both lowering to the +same contract, with the TypeScript route giving immediate `typeof contract` inference +`[CARRIED — NOT +RE-VERIFIED]`. The brief asks whether NetScript should **expose**, **wrap**, or +**translate** that surface. + +**Answer: expose upstream authoring for entities; wrap at the composition seam; translate nothing.** + +- **Translate — rejected.** A NetScript model DSL that lowers to the upstream contract is a third + schema language. It would need to track every native type, index kind, constraint, and default the + provider supports, it would lag upstream permanently, and its error messages would be a + translation of a translation. This is the clearest instance of the "proprietary second ORM" + failure the brief asks me to guard against, and it should be rejected explicitly in the RFC rather + than left as an open option. +- **Bare expose — rejected.** Handing users the upstream builder with no NetScript layer leaves + exactly the gaps that produced the current situation: no target binding, no ownership, no + capability requirement, no augmentation policy, no provenance, no lineage ownership. +- **Wrap at the composition seam — chosen.** NetScript owns _which_ contracts exist, _where_ they + live, _who_ owns each object, _what capabilities_ they require, and _how_ they compose. Upstream + owns what a model, relation, index, constraint, native type, and default _are_. + +### 10.2 The seam in code + +```ts +// plugins/auth/database/contract.ts — entity authoring is upstream's job +import { model, ref, string, timestamp, uuid } from '@netscript/database-prisma-postgres/schema'; + +export const user = model('user', { + id: uuid().primaryKey(), + email: string().unique().citext(), // requires CAP.caseInsensitiveText + createdAt: timestamp().defaultNow(), +}); + +export const session = model('session', { + id: uuid().primaryKey(), + userId: ref(user).onDelete('cascade'), + expiresAt: timestamp(), +}).index(['userId']); +``` + +```ts +// NetScript's wrapper: composition, ownership, capability — no entity vocabulary at all +export declare function schemaSpace>>( + entries: TEntries, +): ContractSource; +``` + +The re-export in the first snippet is deliberate and is **not** an AP-14 violation: it is exported +from the _provider_ package, which is the one package permitted to name upstream symbols (§8.3), and +it is provider-specific by design — `citext()` exists on the PostgreSQL provider and nowhere else. +That is the capability model expressed as an import path, and it is the structural fix for the +observed `@db.Uuid` problem: today a PostgreSQL-only native type sits in a fragment declaring no +provider and gets copied into whatever target the installer picks `[OBSERVED]`; under schema-as-code +the PostgreSQL-only builder is only importable from the PostgreSQL provider, and the space that uses +it must declare `requires: [CAP.nativeUuid]`, which composition checks against the bound target +(V-5). + +### 10.3 Two-track identity: inference for DX, content hash for correctness + +Static inference and durable identity are different jobs and must not share a mechanism. + +- **Static inference** gives editor completion and compile-time errors. It flows from the authored + TypeScript through `typeof`, and it is _only_ valid within the application's own compilation. +- **Stable runtime identity** is the content hash of the canonicalised contract. It is what + receipts, markers, lineage nodes, plans, and caches key on. + +Conflating them is how a system ends up unable to answer "is this database consistent with this +build?" without type-checking. Keeping them separate is also what makes the `isolatedDeclarations` +constraint tractable: the inferred track never crosses a published package boundary (Part 1 §5.4), +while the hashed track is plain data that crosses every boundary freely. + +### 10.4 Propagation: one contract, many consumers + +The value of schema-as-code is that a single authored contract propagates without a second +generation step at each hop: + +| Consumer | What it derives | How | +| ------------------ | ---------------------------------------------- | ---------------------------------------------------------------------- | +| Typed operations | The query surface | Provider's contract-typed runtime, delivered as `TQuery` (Part 1 §5.3) | +| Validation | Input/output Standard Schemas | Runtime derivation from the contract (§11) | +| RPC / routes | Contract-bound procedure input/output | Standard Schema handed to the existing oRPC-bound surface | +| Forms / SSR | Field-level schemas and error paths | The same Standard Schema instances, per field path | +| Migrations | Lineage edges | Storage-plane diff between content-addressed snapshots | +| Generated projects | The typed binding module | Emitted per target (Part 1 §5.4) | +| Tooling / agents | Inventory, capabilities, commands, diagnostics | The manifest plus the operation catalog (§7.7) | + +Every one of those is a _derivation_, and none is a hand-maintained mirror. That is the property +that retires the current pipeline: the generated workspace today emits 30 database tasks and a +repair chain that rewrites Prisma and Zod output textually +`[OBSERVED for the task count; CARRIED — NOT +RE-VERIFIED for the step ordering]`. Derivations do not +need repair passes because there is no second artifact to keep in sync. + +--- + +## 11. Runtime validation subsystem + +### 11.1 The hypothesis and the default + +The owner-provided Prisma-maintainer exchange establishes the design hypothesis that **the contract +carries enough runtime data to derive validation without a second generation step**. I treat this as +primary exploratory evidence and as a hypothesis to be proven by NetScript's own conformance run — +not as an upstream commitment. Part 3 records it as an explicit decision checkpoint conditional on +Prisma 8 final. + +If it holds, the architectural consequence is large, and it is the reason to reject the obvious +approach: + +> **Mirror-validator code generation is rejected as the default.** Generating a parallel validator +> universe from the contract — a schema file per model, per input shape, per output shape — is what +> produces import rewriting, circular-reference repair, getter rewriting, decimal compatibility +> patches, alias barrels, and the split-module-instance class of failure. A mirror must be +> regenerated, re-patched, re-exported, and kept in sync forever, and it is stale the moment the +> schema changes without the pipeline running. + +The default is **runtime derivation, memoised by contract identity**. + +### 11.2 Why selection-awareness settles the argument + +The decisive technical argument against mirror codegen is not maintenance burden — it is +combinatorics. Output validation at a trust boundary must validate _the shape that was actually +selected_, not the full model. A query selecting three fields with one relation included produces a +different result shape from the same model selected wholly. + +A static mirror would need one schema per selection shape, which is unbounded. A runtime derivation +takes the selection as a parameter and produces the schema for exactly that shape: + +```ts +export interface ContractValidation { + /** Input validation for a mutation or query argument set. */ + input, TOp extends OperationKind>( + model: K, + op: TOp, + ): StandardSchemaV1>; + + /** Output validation for the exact projection that was requested. */ + output, TSel extends Selection>( + model: K, + selection: TSel, + representation: Representation, + ): StandardSchemaV1>; +} + +export type Representation = 'runtime' | 'wire'; +``` + +### 11.3 Runtime versus wire representations, and codecs + +One contract yields **two** schema families, and conflating them is a common source of subtle bugs: + +- **Runtime representation** — what the provider hands back in-process: decimal objects, `BigInt`, + `Date`, byte arrays, provider-specific enum values. +- **Wire representation** — what crosses an API, SSR boundary, or external-service call, after JSON + serialisation: strings for decimals and big integers, ISO-8601 for timestamps, base64 for bytes. + +`representation` is therefore a parameter of `output()`, not an afterthought. Codecs are the +bidirectional mapping between them, contributed by the provider or by a space; a codec registers +against a contract type and supplies encode, decode, and the two schemas. Because codecs can be +contributed, a space that introduces a custom column type also introduces its validation without any +framework change — and because codec ownership is checked the same way object ownership is (V-2), +two spaces cannot silently register conflicting codecs for the same type. + +### 11.4 Trust boundaries: where validation is mandatory + +Input validation is always applied at mutation and query boundaries. **Output** validation is +deliberately _not_ universal, because validating every row on every read is a real cost. It is +mandatory at three boundaries and optional elsewhere: + +1. **API/RPC responses** — the shape is a published contract; drift here is a consumer break. +2. **SSR/forms payloads** — the shape reaches a browser and is often user-visible. +3. **External-service calls** — data leaving the trust boundary must match what the recipient was + promised. + +Everywhere else, output validation is opt-in and defaults to off with the cost documented. A design +that validates everything by default gets disabled wholesale in production, which is worse than a +design that validates precisely at boundaries. + +### 11.5 Cache identity and invalidation + +```ts +type SchemaCacheKey = { + readonly contractIdentity: ContractSnapshotId; // changes ⇒ every derived schema invalid + readonly space: SpaceId; // plugin spaces cache independently + readonly model: string; + readonly operation: OperationKind | 'output'; + readonly selectionHash: string; // canonicalised selection shape + readonly representation: Representation; +}; +``` + +Invalidation is by construction: the key contains the contract identity, so a contract change cannot +produce a stale hit — there is nothing to invalidate, only new keys. Plugin spaces cache under their +own `SpaceId`, so upgrading one plugin does not evict the application's schemas. The cache is +bounded and per-process; a cold process pays derivation once per distinct shape it actually uses. + +### 11.6 Structured failures and framework integration + +Validation failures are Standard Schema issues enriched with NetScript's structured diagnostic +shape: a dotted code, the `ObjectKey` or model/field path, the boundary at which the failure +occurred, and whether the failure is an input rejection (client error) or an output mismatch +(server/contract error). The distinction matters operationally: an input failure is a 4xx with field +paths; an output failure is a 5xx _and_ a signal that the database and the contract have diverged, +which is drift, not a request problem. + +Integration follows NetScript's existing seams rather than new ones. `@standard-schema/spec` is +already a dependency of `@netscript/plugin` and `@netscript/sdk` `[OBSERVED]`, so contract-derived +schemas feed the existing oRPC-bound contract surface directly, and forms/SSR consume the same +schema instances per field path. NetScript does not re-export a validator library; a consumer +wanting Zod adapts from Standard Schema, which keeps doctrine AP-14 satisfied and keeps the +split-validator-module failure class out of the design entirely. + +### 11.7 The optional AOT projection + +An ahead-of-time projection may exist for cold-start-sensitive deployments, under three conditions +that make it an optimisation rather than a second source of truth: + +1. **Atomic and content-addressed.** Emitted into a target-scoped root, keyed by contract identity, + replaced atomically, never patched. +2. **Semantically equivalent.** A conformance case must assert that the AOT and runtime-derived + schemas accept and reject an identical corpus, across every representation and a representative + set of selection shapes. Divergence is a build failure, not a warning. +3. **Never the default and never required.** Any code path that works only with AOT artifacts + present is a design failure; the runtime derivation must remain sufficient. + +If condition (2) cannot be met mechanically, the AOT path is a mirror validator wearing a different +name and must be dropped. + +--- + +## 12. Clean-break cutover + +### 12.1 Transfer analysis: NetScript's oRPC pattern → Prisma's TypeScript contract builder + +Before leaving the API architecture, one question deserves a direct answer, because NetScript has +already solved a structurally identical problem once and the temptation to copy the solution +wholesale is strong. + +**The parallel.** NetScript's oRPC surface has exactly the shape the database contract surface will +have: a deeply-inferred upstream type system (`@orpc/contract`) that the framework composes, extends +per plugin, and binds at a composition root. `packages/contracts` (Archetype 1) exports `.`, +`./crud`, `./query`, and `./transform` over `@orpc/contract` and `zod` `[OBSERVED]`; +`packages/plugin` publishes a `./contract-base` subpath and depends on `@orpc/contract`, +`@orpc/server`, and `@standard-schema/spec` `[OBSERVED]`; `packages/service` and `packages/sdk` +consume the same axis `[OBSERVED]`; and `ContributionAxis` already carries a `'contract-version'` +member with a `PluginContractVersionContribution` abstract `[OBSERVED]`. Doctrine grants those +packages — and only those — the `--allow-slow-types` carve-out, precisely because deeply-inferred +contract types cannot be explicitly annotated +(`docs/architecture/doctrine/02-public-surface.md:217-242`) `[OBSERVED]`. + +**What should transfer.** + +1. **The `defineX` → frozen definition → composition-root binding pattern.** This is already + NetScript's entry-verb vocabulary (`02-public-surface.md:73-82`) `[OBSERVED]` and it is the right + shape for `defineTarget`/`defineSpace`/`defineDatabase`. Inference is preserved because the + definition is a `const` whose type flows through `typeof`, exactly as oRPC contracts do today. +2. **Versioned contribution with skew detection.** The `contract-version` axis is the precedent for + §6's pinned mirror and `db.space.skew`. NetScript has already accepted that a contribution + carries a version that can diverge from what the consumer pinned. +3. **Standard Schema as the interop boundary.** `@netscript/contracts` already bridges oRPC and Zod + through schema interop; the database contract's derived schemas plug into the same seam without + any new bridging concept (§11.6). +4. **Per-package subpath discipline.** oRPC concerns are split across `./crud`, `./query`, + `./transform` rather than one barrel. The database surface should split the same way, which F-5's + 20-symbol cap forces anyway. + +**What must not transfer.** + +1. **The slow-types carve-out must not be extended.** This is the most important line in this + subsection. The oRPC carve-out is defensible because the inferred contract _is the product_ of + those packages — consumers import `@netscript/contracts` specifically to obtain those types. The + database case is different in kind: the inferred type is derived from _the application's own_ + contract, so no framework package ever needs to export it. Extending the carve-out would convert + an application-local inference problem into permanent framework-wide publish debt, and doctrine + is explicit that any other package setting `--allow-slow-types` "is a finding and must carry a + debt entry" `[OBSERVED]`. The correct answer is the generated app-side binding (Part 1 §5.4), not + a second exception. +2. **No `BaseDatabaseContract`-style cross-package base class.** Plugin `-core` packages extending + `BaseContractRoute` sits in tension with AP-4, which forbids cross-package implementation + inheritance and prescribes "registration against an extension axis instead" + (`09-anti-patterns-and-fitness-functions.md:54-57`; `07-composition-and-extension.md:114-141`) + `[OBSERVED]`. The database design has no legacy reason to inherit that tension; spaces register, + they do not subclass. +3. **No wrapper around `defineContract` and no re-export of it from a kernel package.** Wrapping the + upstream builder to "make it NetScript-flavoured" destroys the native inference that motivates + using it, adds a translation layer with worse errors, and re-creates the second-DSL failure §10.1 + rejects. The builder is re-exported from the _provider_ package only, where provider-specific + vocabulary belongs. +4. **No mirror of `packages/contracts` for the database.** A `@netscript/database-contracts` package + holding CRUD/query/transform mirrors of database models would be the mirror-validator failure of + §11.1 in a different costume. + +**What is additionally required, because a database is not an RPC contract.** These have no analogue +in the oRPC pattern and are the reason the database surface needs its own machinery rather than a +copy: + +| Requirement | Why oRPC has no equivalent | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ | +| Ownership disjointness over `ObjectKey` (V-2) | Two RPC contracts declaring the same procedure name is a routing conflict caught at composition; two schemas owning one table is a silent data hazard. | +| Lineage coupling | An RPC contract version can be published freely; a schema change implies a _data_ transition that must be planned, ordered, and verified. | +| Physical identity separate from logical contract | An RPC contract has no target, namespace, or connection; a space must be bound to one target and one namespace. | +| Lifecycle and scope | An oRPC contract has no lifetime. A database binding owns connections, close ordering, and request-versus-process scope (Archetype 3). | +| Destructive policy and consent | There is no destructive operation in publishing a contract. | +| Drift against live state | A contract cannot drift from a running server the way a schema drifts from a live database that another system also writes to. | +| Capability requirements | Every oRPC contract is expressible on every transport; a schema using `citext` is not expressible on every provider. | + +**Conclusion of the transfer analysis.** Reuse the composition, contribution, and interop +_patterns_; reuse none of the type-escape _mechanisms_; and add ownership, lineage, physical +identity, lifecycle, consent, drift, and capability as genuinely new concerns. The oRPC pattern is +the right template for how NetScript composes upstream type systems and the wrong template for how +it publishes them. + +### 12.2 Cutover principles + +- **No runtime compatibility, ever.** No Prisma 7 facade, no `setClient` lifecycle, no alias barrel, + no dual client, no deprecated re-export. A compatibility shim would encode the old foundation's + limits into the new layer, which is precisely the outcome the owner directive exists to prevent. +- **Data continuity is absolute.** The database is adopted, never rebuilt. Cutover must be possible + on a production database with real data and no drop-and-recreate step anywhere in the sequence. +- **Parallel branching is a release-line concern, not a product-API concern.** The old and new + stacks may coexist in the repository during the waves; they must never coexist in one + application's composition. + +### 12.3 The mechanical migration path + +A one-shot importer, `netscript db adopt`, converts an existing project. It is a _tool_, not a +compatibility layer, and it is deleted after the migration window. + +| Step | Operation | Mutates the database? | Failure behaviour | +| ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- | --------------------------------------------------------------------------------------------------------------- | +| 1 | Read `appsettings.json` targets, engine mapping, and the generated workspace layout | No | Refuse on ambiguous or duplicate config keys | +| 2 | Emit a proposed `database.ts` with one `defineTarget` per config key — **target ids taken from config keys, never from engine names** | No | Refuse when two config keys resolved to the same engine directory; require the author to name them | +| 3 | Introspect each live target | No | Report unreachable targets; adoption can proceed offline for reachable ones only | +| 4 | Derive one space per detected owner: `app` for the base schema, one per installed plugin, inferred from the copied `schema/plugins//` directories | No | Objects that cannot be attributed are reported, not guessed | +| 5 | Emit the ownership proposal for review: every `ObjectKey` mapped to a space or to `external`/`adopted` | No | The author must resolve every unattributed object before continuing | +| 6 | Compile the manifest and emit artifacts | No | Standard composition diagnostics | +| 7 | Establish the baseline: write a lineage root node per space matching the _observed_ live state, and write the marker rows | **Yes — marker rows only** | Idempotent; re-runnable; produces a receipt | +| 8 | `verify` | No | Any diff at this point is a genuine finding: either an unattributed object or an incorrect ownership assignment | +| 9 | Cutover commit: delete `database//`, its 30 generated tasks, the repair scripts, and the old package dependencies | No | Reversible by reverting the commit | + +The critical property is **step 7 writes marker rows and nothing else**. No table is created, +altered, or dropped during adoption. That is what makes the migration safe on production data and +what makes step 9 the only irreversible-looking step — and it is reversible, because it touches only +the repository. + +### 12.4 Data preflight and safety + +Before step 7, a preflight report is mandatory and must be attached to the cutover PR: every target +with its reachability and provider version; every `ObjectKey` with its assigned owner and ownership +policy; every object the importer could not attribute; every capability the derived spaces require +against what each target actually provides; and every plugin whose copied fragment cannot be +attributed to an installed package. A preflight with unattributed objects is a hard stop — guessing +ownership is how a later `verify` proposes dropping a table someone else owns. + +### 12.5 Rollback boundaries + +| Point | Rollback | Cost | +| -------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------- | +| Before step 7 | Delete generated artifacts | None; nothing was written | +| After step 7, before step 9 | Delete marker rows for the adopted spaces | Trivial; markers are metadata | +| After step 9, before first apply | Revert the cutover commit | Repository-only; database untouched | +| After the first `apply` | Forward-only, using the lineage and the receipt | Ordinary migration rollback semantics; the receipt identifies exactly which steps ran | + +There is deliberately no "run both stacks" rollback. That option would require the compatibility +layer this design refuses, and it would double the failure surface during precisely the window when +the system is least understood. + +### 12.6 Feature-parity accounting + +The fourteen current verbs `[OBSERVED]` map as follows. Parity is claimed only where the new +operation is a superset; everything else is stated as a deliberate removal. + +| Current verb | Disposition | +| ------------ | -------------------------------------------------------------------------------------------------------------------------------- | +| `add` | Replaced by editing `database.ts`. Scaffolding becomes a code-mod, not a config rewrite plus helper regeneration. | +| `list` | `inventory` — superset: targets, spaces, ownership, capabilities, heads, drift status, as structured output. | +| `remove` | Replaced by the space retirement protocol (§6.4). **Behaviour change:** removal produces a plan; it no longer deletes and hopes. | +| `init` | `apply` against an empty baseline. | +| `generate` | `emit` — **now `pure`**; never touches an orchestrator. This closes `DB-GENERATE-ASPIRE-COUPLING`. | +| `migrate` | `plan` + `apply`, separated. **Behaviour change:** planning and applying are distinct operations with distinct policies. | +| `seed` | `mutating` operation with a receipt. | +| `status` | `verify` + `inventory`, structured. | +| `studio` | Retained as `resident`, but **must take an explicit target**; the `databases[0]` silent selection is removed. | +| `introspect` | `introspect`, feeding adoption. | +| `reset` | Retained, `mutating`, destructive-policy-gated; refused in `production` regardless of consent. | +| `deploy` | `apply` with a signed plan and `environment: production`. | +| `validate` | `compose` — a `pure` operation returning full diagnostics rather than first-error. | +| `resolve` | Replaced by explicit lineage operations against named nodes. | + +Two capabilities are removed on purpose and must be stated in the RFC as such: implicit target +defaulting (there is no primary-ish fallback anywhere), and silent single-target execution for +multi-target commands. + +--- + +## 13. Implementation waves + +Each wave lands independently and has a gate that can fail. No wave depends on a later wave. + +| Wave | Scope | Depends on | Acceptance gate | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **W0 — Doctrine and RFC** | Amend `06-archetypes.md` (Archetype 5 fragment rule; archetype table), add verdict rows in `10-codebase-verdict-and-handoff.md`, register the new packages in the gated denominator, land the RFC | — | RFC accepted; `arch:check` discovers the new roots; doctrine drift (A9 "six archetypes" vs seven) resolved or explicitly deferred with a debt entry | +| **W1 — `@netscript/database-contract` (A1)** | Identities, manifest schema, capability vocabulary, ownership vocabulary, diagnostic catalog, operation/receipt types, space descriptor, ports | W0 | A1 gate set; `deno publish --dry-run` **without** `--allow-slow-types`; `deno doc --lint`; F-5 ≤20 root exports; zero dependencies | +| **W2 — `@netscript/database` (A4)** | `defineTarget`/`defineSpace`/`defineDatabase`, the pure compiler, all composition invariants V-1…V-8, diagnostics | W1 | A4 gate set; property test: compile is deterministic and total; every invariant has a negative test producing the right code; no IO reachable (AP-25 scan) | +| **W3 — `@netscript/database-prisma-postgres` (A2)** | Capability descriptor, emitter, control adapter, runtime factory, `upstream.ts` facade, import allowlist | W1, W2 | A2 gate set + runtime gates; conformance suite green against a **real** PostgreSQL service; import-allowlist check; Deno import-purity check | +| **W4 — `@netscript/database-runtime` (A3)** | Binding, process/request scope, lifetimes, health, close ordering, `AbortSignal`, `{ stop() }` | W1, W3 | **All F-1…F-19** and **required runtime gates**; leak test under repeated start/stop and request lifecycles; scope-type test proving request scope cannot cache | +| **W5 — `@netscript/database-control` (A2)** | classify/compose/plan/apply/verify/emit, locks, receipts, resume, expiry, partial success | W1, W2, W3 | A2 gate set; negative-path matrix (§14); atomic-emission test; offline test proving `pure` never reaches an orchestrator | +| **W6 — `@netscript/database-testkit` (A6)** | Provider conformance suite, space conformance suite, machine-readable report | W1, W3, W5 | A6 gate set + F-CLI rules; certifies W3 provider; a deliberately broken provider fixture must fail | +| **W7 — `@netscript/plugin` contribution surface (A4)** | `defineDatabaseSpace`; remove `PluginDbSchemaContribution`/`PluginMigrationContribution`; adjust `ContributionAxis` | W1, W6 | A4 gate set; **breaking-change accounting for a published package**; consumer import validation | +| **W8 — CLI + agent surface (A6)** | `db` verbs as projections; generated agent manifest; adoption tool | W5, W6 | A6 gate set; every generated example compiles and runs; command/diagnostic catalogs match machine output | +| **W9 — First-party plugin migration (A5)** | Convert `auth`, `workers`, `sagas`, `triggers` to spaces; namespace their objects; declare capabilities | W7, W8 | A5 gate set + **required runtime gates**; each plugin passes the space conformance kit; `@db.Uuid`-class provider locks now declared | +| **W10 — Cutover** | Adoption tool applied; delete `database//`, the 30 tasks, the repair scripts, the old packages | W8, W9 | Release-gate class (DB wiring + scaffold output + Aspire helper generation all change); full `scaffold.runtime` E2E; production-shaped adoption rehearsal on a seeded database | + +Retirement of `@netscript/prisma-adapter-mysql` and `@netscript/database` happens in W10, not +earlier: they must keep working until the last consumer moves. + +--- + +## 14. Conformance matrix + +This is the artifact that makes "adoption is gated by NetScript proof, not by an upstream label" +operational. Each row is a required, independently-failing case. + +### 14.1 Type, plan, artifact, result, and lifecycle + +| # | Case | Passes when | +| ---- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | +| T-1 | Space requires a capability the bound target lacks | Composition fails, `db.compose.capability.missing`, names capability + space + target | +| T-2 | Space bound to an undeclared target id | **Type error** at the authoring site, not a runtime diagnostic | +| T-3 | Two spaces own one `ObjectKey` | `db.compose.ownership.conflict` naming both spaces | +| T-4 | Cyclic `dependsOn` | `db.compose.dependency.cycle` with the cycle path | +| T-5 | Cross-target relation declared | Refused at composition with a next-action, never emitted | +| T-6 | Type surface, plan, emitted SQL, and result agree for a non-trivial feature (e.g. null-ordering) | All four consistent — this is the case that catches "published type ignored at runtime" | +| T-7 | Request-scoped session used after disposal | Type-level prevention where possible; runtime error otherwise | +| T-8 | Interactive transaction handle escapes its callback | Rejected; `tx` must not expose transaction-opening members (repairs the observed `withTransaction` defect) | +| T-9 | Every operation returns a typed result | No code path returns a bare number or relies on an exit code | +| T-10 | Artifact postconditions asserted | Every receipt's `ArtifactAssertion` matches the filesystem | + +### 14.2 Deterministic and atomic emission + +| # | Case | Passes when | +| --- | ------------------------------------------------- | ------------------------------------------------------------------ | +| E-1 | Emit twice from a clean checkout | Byte-identical artifacts and identical `ManifestDigest` | +| E-2 | Emit two targets concurrently into distinct roots | Both succeed; no interleaving | +| E-3 | Emit interrupted mid-write (SIGKILL) | Artifact root is either fully old or fully new; never half-patched | +| E-4 | Schema edited without re-emitting | `db.artifact.stale` at bind time, naming the exact command | +| E-5 | Manifest digest recorded in every artifact root | Present and matching (V-8) | +| E-6 | CI re-run with an unchanged digest | Emission skipped; recorded digest asserted instead | + +### 14.3 Migration and failure + +| # | Case | Passes when | +| ---- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| M-1 | Greenfield apply | Succeeds with a full receipt | +| M-2 | Adoption of an existing populated database | Marker rows only; zero DDL; `verify` clean | +| M-3 | Drift introduced externally | `db.verify.drift` classifies managed vs adopted vs external correctly | +| M-4 | Destructive change under `destructive: 'deny'` | Refused with the destructive operation list | +| M-5 | Destructive change in `production` with an unsigned plan | Refused regardless of interactive consent | +| M-6 | Plan applied after the manifest changed | `db.plan.stale` | +| M-7 | Plan applied after `planMaxAgeMs` | `db.plan.expired` | +| M-8 | Apply fails mid-run | Receipt shows the exact failed step; `resume` continues and re-validates the baseline first | +| M-9 | Two concurrent applies on one target | Second gets `db.apply.lock.held` with owner and TTL; no interleaved DDL | +| M-10 | Lock holder dies | TTL/fencing releases; no permanent wedge | +| M-11 | Data transform with an unsatisfied invariant | Fails and reports remaining work; does not advance the head | +| M-12 | Non-default namespace | All operations honour it; a silently ignored schema selector is a failure | +| M-13 | Two same-provider targets | Fully isolated output, lineage, markers, receipts | +| M-14 | Migration on Windows | Runs — **explicitly required**, since the current fixture refuses non-Linux `[OBSERVED]` | + +### 14.4 Plugin lifecycle + +| # | Case | Passes when | +| ---- | ------------------------------------------------- | --------------------------------------------------------------------------- | +| P-1 | Two plugins, one target, declared ordering | Applied in topological order recorded in the manifest | +| P-2 | Plugin object-name collision across spaces | Namespaced and non-conflicting; no lexical prefix convention required | +| P-3 | Cross-space foreign key along a declared edge | Allowed; without the edge, refused | +| P-4 | Plugin upgrade with a lineage step | Head advances for that space only | +| P-5 | Installed package digest ≠ mirror digest | `db.space.skew` with both digests | +| P-6 | Apply/verify with **no plugin package installed** | Succeeds from the pinned mirror alone | +| P-7 | Uninstall with retention | Objects retained; ownership downgraded to `adopted`; verify still sees them | +| P-8 | Uninstall with a dependent space installed | Refused, naming the dependent | +| P-9 | Uninstall with `drop` | Requires explicit consent and produces a destructive plan | +| P-10 | Plugin declares a capability its target lacks | Install refused at composition (the `@db.Uuid`-class case) | +| P-11 | Augmentation outside a granted axis | Refused, naming the grant that would be required | +| P-12 | Upstream extension owning its own space | Recorded as `external`; not reported as drift | + +### 14.5 Real PostgreSQL, Deno/import purity, generated projects, journeys, CI/release + +| # | Case | Passes when | +| --- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| R-1 | Full runtime suite against a **real** PostgreSQL service | CRUD, relations, raw, codecs, transactions, prepared statements, streaming, cancellation all pass — not an emulator | +| R-2 | Connection injection and external pool | Behaves under concurrency; no query serialisation surprise | +| R-3 | Error mapping and secret redaction | Connection strings and passwords never appear in diagnostics, receipts, or logs | +| D-1 | Deno import graph of runtime paths | No undeclared Node globals; no CLI/toolchain module reachable | +| D-2 | Packed-artifact install into a blank fixture | Every used export and peer resolves exactly once | +| D-3 | Deep-import allowlist | Any new upstream deep import fails the build | +| D-4 | `deno publish --dry-run` on every new package | Passes **without** `--allow-slow-types` | +| G-1 | Generated project type-checks and starts | Scaffold → emit → apply → run, unattended | +| G-2 | `emit` in a container with no Aspire CLI, no .NET, no Docker | Succeeds | +| J-1 | Journey: scaffold → add second same-provider target → add two plugins → migrate → deploy | No manual step, no hand-edited generated file | +| J-2 | Journey: adopt an existing populated project (§12.3) | Preflight clean; zero DDL; verify clean | +| N-1 | Every diagnostic code has a negative test | Each code is reachable and carries a `nextAction` | +| N-2 | No gate asserts on human-readable message text | Gates assert on codes and structured results only (repairs the observed string-matching fixture) | +| C-1 | Release-gate class | Full `scaffold.runtime` E2E green on the cutover | +| C-2 | Agent surface | Every generated example compiles and executes; catalogs match machine output | + +--- + +## 15. Risks, findings, unresolved decisions, and checkpoints + +### 15.1 Severity-tagged findings against the current research and plan + +| # | Severity | Finding | Consequence if unaddressed | +| ---- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| F-1 | **Critical** | `isolatedDeclarations: true` is repo-wide `[OBSERVED]` and the `--allow-slow-types` carve-out covers only oRPC-bound packages `[OBSERVED]`. No research document mentions either. | The RFC would propose a package that cannot be published, discovered during implementation rather than at plan lock. | +| F-2 | **Critical** | The plan's archetype set (A1/A2/A4/A5/A6) omits Archetype 3, but the runtime half owns lifecycle and scope `[OBSERVED:`06-archetypes.md:78-83`]`. | All F-1…F-19 and _required_ runtime gates are silently dropped from the gate set. | +| F-3 | **High** | The clean break removes published surface from `@netscript/plugin`: `PluginDbSchemaContribution`, `PluginMigrationContribution`, and two `ContributionAxis` members `[OBSERVED]`, none of which has any implementation `[OBSERVED]`. Not scoped anywhere. | An unplanned breaking change to a second Archetype-4 package, discovered late. | +| F-4 | **High** | Doctrine currently _codifies_ the model being removed: plugin schema contributions "are plain `*.prisma` files… They do not contain a private workspace" (`06-archetypes.md:209-211`) `[OBSERVED]`. Amending doctrine is itself an RFC trigger `[OBSERVED]`. | The RFC contradicts doctrine it never amends; `arch:check` and the RFC disagree. | +| F-5 | **High** | Live defect the audit does not surface: plugin fragments use PostgreSQL-only `@db.Uuid` `[OBSERVED]` while the installer's target chain ends `?? databases[0]`, escaping the `enabled` filter `[OBSERVED]`. | The capability model is argued abstractly when a concrete reproducible defect could anchor it. | +| F-6 | **High** | `execute(): Promise` `[OBSERVED]` means receipts are not additive — the return type makes structured reporting impossible. The audit presents this as missing behaviour. | Sequencing error: "add receipts" is planned as a slice when it is a replacement of the operation contract. | +| F-7 | **Medium** | `withTransaction` types its callback parameter as the full `Client` `[OBSERVED]`, so `tx.$transaction` type-checks inside an interactive transaction. The audit's "structurally-cast" understates a type-level correctness defect. | A known-unsound signature is carried forward as merely inelegant. | +| F-8 | **Medium** | `packages/database` declares **zero** dependencies `[OBSERVED]` — upstream independence is achieved by duck typing, not by design. | The RFC must state how the provider obtains _real_ types without re-exporting them; otherwise the new design silently re-adopts structural typing. | +| F-9 | **Medium** | `DatabaseConfigSchema` hardcodes a `zodGenerator` block and accepts provider aliases (`postgresql\|postgres`, `mssql\|sqlserver`) `[OBSERVED]`, and `mapEngine` normalises again `[OBSERVED]`. | A validator choice is baked into the core config vocabulary, and there are two normalisation sites for one concept. | +| F-10 | **Medium** | `mapEngine`'s `switch` over the engine union selecting providers `[OBSERVED]` is doctrine AP-24, whose canonical counter-example is literally a database-engine switch `[OBSERVED]`. | A live doctrine violation goes uncited in the RFC's motivation. | +| F-11 | **Medium** | The merge-readiness migration fixture refuses to run outside Linux and asserts on the literal string `'created no migration artifact'` `[OBSERVED]`. | The gate proving the most expensive historical repair neither covers the platform where the schema-engine hangs occurred nor survives a reword. | +| F-12 | **Medium** | Five of six specialist sub-agents returned nothing (§1.2). The Prisma numeric claims, the ADR coverage, the 30-fix-commit count, the ~9,175-line figure, and the control/runtime signatures are `[CARRIED — NOT RE-VERIFIED]`. | The RFC would cite unverified figures as evidence. | +| F-13 | **Low** | The plan's validation table has no gate that re-proves numeric research claims. | Nothing catches F-12. | +| F-14 | **Low** | The plan's risk register lacks "the upstream seam moves during the RFC's own authoring window" — which has already happened (post-RC CLI/config unification) `[CARRIED — NOT RE-VERIFIED]`. | The mitigation (§8.3) is not tracked as a risk. | +| F-15 | **Low** | Doctrine drift: A9 says "six archetypes" while seven exist `[OBSERVED]`. | Minor, but the RFC touches this file and should not silently inherit it. | + +### 15.2 Failure-mode ledger + +| Failure mode | Structural prevention | Proven by | +| ----------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------ | +| Two logical databases collapsed into one directory | Target id is declared; V-6 forbids shared roots | T-3, M-13 | +| Wrong or ambiguous target selected implicitly | No fallback chain anywhere; explicit target sets | T-2, feature-parity removals (§12.6) | +| Client constructed in the wrong order | No `setClient`; the runtime owns construction | W4 gates | +| Stale generated types compiled against | Digest recorded in every artifact root; bind refuses a mismatch | E-4, E-5 | +| Success reported without artifacts or state | Typed results plus `ArtifactAssertion` postconditions | T-9, T-10 | +| Unversioned fragment copied without analysis | Spaces with capability requirements and ownership | P-10, P-11 | +| Adding an engine requires editing switches everywhere | Typed provider registry populated at the composition root | F-10 remediation | +| Aspire/Docker required for pure compilation | Operation classification; `pure` gets no connection resolver | G-2 | +| Generated text patched as a permanent shim | I-5; no repair step exists | E-1, E-3 | +| Plugin schema silently absent | Pinned mirror is the source; apply works with no package installed | P-6 | +| Read-only command kills the resident host | Only `resident` operations bind a resident graph | §7.2 | +| Cross-target apply falsely described as atomic | `partially-succeeded` is a first-class outcome (I-9) | M-8 | +| Secret leakage through connection parsing | Redaction is a conformance case | R-3 | +| Agent instructions drift from reality | Generated from the manifest; every example executed | C-2 | + +### 15.3 Rejected alternatives + +| Alternative | Rejected because | +| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| Keep `DatabaseGraph` as a live runtime object | It is a service locator with a domain name; the durable artifact is a manifest value (Part 1 §2.1). | +| One `@netscript/database` package holding DSL, runtime, and control | Two incompatible gate profiles and dependency needs; doctrine's "one archetype per package" is satisfied by splitting packages. | +| Re-export the provider's runtime type from a framework package | Blocked by `isolatedDeclarations` + slow-types, and by AP-14. | +| Extend the `--allow-slow-types` carve-out to the database packages | Converts an application-local inference problem into permanent framework publish debt (§12.1). | +| A NetScript model DSL that lowers to the upstream contract | A third schema language, permanently lagging, with translated error messages (§10.1). | +| Mirror-validator codegen from the contract | Combinatorially impossible for selection-aware output validation, and it re-creates the repair pipeline (§11.1–11.2). | +| Port `@netscript/prisma-adapter-mysql` forward | Re-imports the hand-maintained low-level driver surface the redesign exists to remove (§9.4). | +| Wait for upstream to close the operational gaps | Gates adoption on someone else's roadmap; the gaps are NetScript's to own anyway (§8.2). | +| A compatibility facade during cutover | Doubles the failure surface in the least-understood window; contradicts the owner directive (§12.5). | +| Universal output validation | Gets disabled wholesale in production, which is worse than precise boundaries (§11.4). | + +### 15.4 Unresolved and conditional decisions + +These must be recorded in the RFC as conditional on Prisma 8 **final**, not resolved by the RC. + +| # | Decision | Conditional on | +| ---- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | +| U-1 | Whether validation can be derived from contract runtime data without a generation step | The maintainer-exchange hypothesis proven by NetScript's own conformance run; if false, revisit §11 wholesale | +| U-2 | The exact control-API package path and option shapes | Post-RC churn settling; contained by §8.3 but not eliminated | +| U-3 | Contract format version and hash representation | Explicitly still moving; NetScript records its own digest meanwhile | +| U-4 | Whether the contingency control backend is ever needed | Built and CI-exercised regardless; promotion decided at GA | +| U-5 | SQLite's capability set | Requires conformance measurement, not the upstream scorecard | +| U-6 | MySQL strategy | Retire-and-defer recommended; revisit if a requirement lands before an upstream target | +| U-7 | Whether an AOT validation projection ships at all | Only if semantic equivalence is mechanically provable (§11.7) | +| U-8 | Advisory-lock strategy per provider | Native lock vs ledger row with fencing, decided per certified provider | +| U-9 | Whether `@netscript/database-testkit` is A6 or folds into `./testing` subpaths | Depends on whether it ships a runnable binary | +| U-10 | Plan signing mechanism and key custody | Out of scope here; required before W10 production use | + +### 15.5 Kill-switch criteria + +Adoption of Prisma 8 as the first provider should be abandoned, and the provider port satisfied by a +different implementation, if any of these hold at GA: + +- The Deno import graph cannot be made clean without vendoring or patching upstream (D-1 unfixable). +- `deno publish --dry-run` cannot pass on the provider package without `--allow-slow-types` (D-4). +- Emission is not deterministic (E-1) or not atomic (E-3) and upstream will not make it so. +- Per-space markers or ledger coupling cannot be made transactional on PostgreSQL (M-9, M-11). +- Contract format changes without a migration path more than once between GA and the first NetScript + release that depends on it. + +The design survives all five because the provider is a leaf behind a port — which is the point of +§8.3. The kill switch costs a provider, not an architecture. + +### 15.6 Decision checkpoints for plan lock + +The supervisor can treat these as a tick-list before locking the Plan-Gate: + +1. Accept or reject the manifest-over-live-graph reframing (Part 1 §2.1). +2. Accept the seven/nine-package split and the per-package archetype assignments, including + **Archetype 3** for the runtime package (F-2). +3. Confirm that no published package will export a contract-typed value, and that the typed binding + is generated app-side (F-1). +4. Add the `@netscript/plugin` breaking-change scope to the plan (F-3). +5. Add the doctrine amendment (`06-archetypes.md` Archetype 5 + archetype table + verdict table) to + the RFC scope (F-4). +6. Add a claim-ledger gate that re-proves every numeric research claim before the RFC cites it + (F-12, F-13). +7. Decide `expose / wrap / translate` for the upstream TypeScript schema builder — recommended: + expose for entities, wrap at the composition seam, translate nothing (§10.1). +8. Decide the validation default — recommended: runtime-derived, memoised by contract identity, with + mirror codegen explicitly rejected (§11.1). +9. Decide the MySQL disposition — recommended: retire and defer (§9.4). +10. Approve the operational-layer ownership split (§8.2), which is the largest scope decision here. +11. Confirm the cutover has no compatibility layer and that adoption writes marker rows only + (§12.3). +12. Record U-1…U-10 as conditional on Prisma 8 final. + +### 15.7 Implementation blockers + +- **B-1.** Plan signing and key custody (U-10) block W10 production use, not earlier waves. +- **B-2.** A real PostgreSQL service in CI blocks W3's acceptance gate; PGlite or an emulator does + not satisfy R-1. +- **B-3.** Windows coverage for migration operations (M-14) needs a runner; without it, the + historical schema-engine failure class stays unproven. +- **B-4.** The maintainer-exchange hypothesis (U-1) blocks finalising §11's default, though the + Standard Schema boundary is safe either way. + +--- + +## 16. Source register and recommendation + +### 16.1 Local sources verified in this session `[OBSERVED]` + +| Path | Used for | +| --------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `deno.json` (root) | `isolatedDeclarations: true`; workspace globs; `arch:check`, `quality:scan`, `publish:dry-run`, `doc:lint` tasks | +| `packages/database/deno.json` | 10 exports; **zero** dependencies | +| `packages/database/mod.ts:128-140` | `withTransaction` cast and callback typing | +| `packages/database/scripts/` | `patch-prisma-client.ts`, `migrate.ts`, `fix-zod-imports.ts`, `generate-zod.ts` published via `./scripts` | +| `packages/plugin/src/domain/constants.ts:16-26` | `ContributionAxis` closed union incl. `database-schema`, `migration` | +| `packages/plugin/src/abstracts/plugin-db-schema-contribution.ts` | `path`, optional `engine` union | +| `packages/plugin/src/abstracts/plugin-migration-contribution.ts` | `name`, `path` | +| repo-wide grep for those abstracts | Zero implementations | +| `packages/config/src/domain/schemas/database-schema.ts` | Provider aliases; `zodGenerator` in core config | +| `packages/cli/src/public/features/db/db-group.ts:32-53` | The fourteen verbs | +| `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:50` | `join('database', provider.dirName)` | +| `…/workspace-resolver.ts:71-88` | `resolveTarget` single-target defaulting | +| `…/workspace-resolver.ts:96+` | `mapEngine` switch (AP-24) | +| `packages/cli/src/kernel/adapters/database/operation-runner.ts:85-107` | `Promise`; `studio → databases[0]`; fail-fast loop | +| `packages/cli/src/kernel/adapters/plugin/db-integration.ts:101-105, 275-300` | Target chain ending `?? databases[0]`; `as DbEngine` cast | +| `packages/cli/src/kernel/adapters/plugin/prisma-schema-writer.ts:133` | Normalised-body collision policy | +| `packages/cli/e2e/…/verify-db-migration-artifacts.ts` | Linux-only guard; literal-string assertion | +| `packages/cli/e2e/…/database-gates.ts` | `GATE.DATABASE_*` command gates | +| `plugins/{auth,workers,sagas,triggers}/database/*.prisma` | `@db.Uuid`/`@db.VarChar`/`@db.Text`; unprefixed vs prefixed names | +| `plugins/workers/scaffold.plugin.json` | `hasDatabaseMigrations` boolean; `dependencies: ["streams"]` | +| `packages/{contracts,plugin,service,sdk}/deno.json` | oRPC + `@standard-schema/spec` topology | +| `docs/architecture/doctrine/01-thesis-and-axioms.md` | A1–A14 | +| `docs/architecture/doctrine/02-public-surface.md:73-138, 217-242` | Entry verbs; subpaths; slow-types carve-out | +| `docs/architecture/doctrine/05-folder-structure.md` | Layering law; folder vocabulary | +| `docs/architecture/doctrine/06-archetypes.md` | Archetypes 1–7; `:209-211` fragment rule; `:374-411` table | +| `docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md` | AP-3, AP-4, AP-14, AP-18, AP-24, AP-25; F-1…F-19 | +| `docs/architecture/doctrine/10-codebase-verdict-and-handoff.md:37, 50, 90-95` | Verdicts; the 36-path gated denominator | +| `.llm/harness/archetypes/README.md:23-26` | One-archetype-per-package law | +| `.llm/harness/gates/archetype-gate-matrix.md` | Gate columns; release-gate class | +| `.llm/harness/gates/plan-gate.md:18-40` | Plan-Gate checklist | +| `.llm/harness/debt/arch-debt.md` | `AP-17` on `packages/database`; `DB-GENERATE-ASPIRE-COUPLING`; auth roadmap R1 | +| `rfcs/README.md`, `rfcs/0000-template.md`, `rfcs/0003-command-composition-kit.md` | RFC triggers, front-matter, section structure, implementation-grade reference | + +### 16.2 Sources carried from the committed research `[CARRIED — NOT RE-VERIFIED]` + +The Prisma 8 primary-source register in `research/prisma-8-deep-dive.md` — RC tag `v8.0.0-rc.1` +(`a76a6c5`), post-RC `main` (`71e2e0d`), the RC scorecard, ADRs 176/212/242, the control-API and +PostgreSQL runtime sources, the project skill, supported-versions and serverless docs, and the +upstream issue/PR ledger — plus the market comparators in `research/market-analysis.md`. The +owner-provided maintainer exchange is treated as primary exploratory evidence for U-1. Every figure +drawn from these must pass the claim-ledger gate (F-12/F-13) before the RFC cites it. Where this +report needed a number I used the supervisor's corrected values: `^7.8.0` root ranges, `^7.4.2` in +generated templates, 30 generated database tasks, TypeScript 5.9 as an **optional** peer, and +roughly 138 top-level `@prisma/orm-postgres` export keys. No skill-count totals are relied upon +anywhere in this report. + +### 16.3 Recommendation + +Proceed, with three amendments to the plan before Plan-Gate lock. + +The research's direction is sound and the Prisma 8 integration thesis holds: adopt the contract, +space, and lineage _semantics_; own the _operational_ layer; keep the provider a replaceable leaf. +The design that follows is smaller than the system it replaces because it refuses to abstract the +query surface — that refusal is what keeps NetScript from building a second ORM, and it should be +stated in the RFC as a non-goal rather than left implicit. + +The three amendments are not stylistic. **First**, reframe the central abstraction from a live graph +to a compiled manifest; this changes what gets published and what stays internal. **Second**, add +Archetype 3 and its mandatory runtime gates; without it the plan's gate set is incomplete by +construction. **Third**, record the `isolatedDeclarations`/slow-types constraint as a first-class +design input; it decides where the typed binding lives, and discovering it during implementation +would invalidate a package boundary after the RFC is accepted. + +One caution on the evidence base. Five of six specialist lanes in this session returned nothing, so +a meaningful share of the Prisma-side detail in the committed research remains unverified by any +independent pass. The architecture in this report does not depend on those figures — it depends on +the upstream _shape_, which is corroborated by multiple independent descriptions — but the RFC will +cite them, and it should not do so until the claim-ledger gate has run. That is the cheapest +remaining risk to retire before locking the plan. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md new file mode 100644 index 0000000000..edaf7dd6ed --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md @@ -0,0 +1,214 @@ +# Layered database DX API audit + +> Scope: owner finding `OWNER-DX-01`; current repository and pinned Prisma RC1 source.\ +> Verdict: **the RFC has the right kernel, but presents its middle layer as the golden path and +> unnecessarily makes a generated TypeScript binding universal.** Adopt the repository's existing +> preset → factory → native-primitives pattern and make direct app-local inference the default. + +Labels below distinguish **[FACT]** repository/upstream evidence, **[INFERENCE]** conclusions from +that evidence, and **[PROPOSAL]** new API. + +## 1. The shipped NetScript pattern + +**[FACT] Service/Hono.** `packages/service/src/presets/define-service.ts:216-275` (`defineService`) +is the golden-path preset and literally calls +`packages/service/src/builder/service-builder.ts:195-200` (`createService`), then applies the +standard chain. `ServiceBuilder` exposes one-method-deeper customization (`withCors`, +`withDatabase`, `withRPC`, `use`, `route`, `build`, `serve`) at lines 61-175. Its implementation +constructs a real Hono app and composes Hono plus NetScript primitives in +`service-builder-impl.ts:12-45,60-88`; direct adopters can instead use such public primitives as +`createRPCPlugins`/`createRPCHandler` in `primitives/handlers.ts:38-114`. The repository calls these +implementation layers 3/2/1; this audit calls them user-facing L1/L2/L3 (highest to lowest). + +**[FACT] SDK/frontend data access.** There is no public symbol named “DAL”. The actual seam is +contract-derived clients and query resources. `packages/sdk/src/presets/define-services.ts:97-127` +(`defineServices`) fans one exact contract map into the same values returned by +`createServiceClient`, `createQueryFactory`, and `createServiceQueryUtils`. The first delegates to +native `createORPCClient` (`src/client/service-client.ts:41-65`); the second derives cache/query +operations without replacing the contract (`src/query/query-factory.ts:41-188`). +`packages/sdk/mod.ts:9-32` explicitly promises that dropping down a layer does not replace wiring. + +**[FACT] Fresh.** `defineFreshApp` returns the real Fresh `App` and accepts an existing app plus +factory/configuration escape hatches +(`packages/fresh/src/runtime/server/define-fresh-app.ts:24-117`). `definePage` builds its public +type-state facade from `createBuilder(createDefaultConfig())` +(`src/application/builders/define-page/builder/mod.tsx:465-471`); `withResource(s)` carries resource +types forward (`builder/state.ts:45-64`) while `retagConfig` changes compile-time state without +inventing runtime concepts (`builder/factory.ts:8-49`). + +**[FACT] Doctrine.** A3 requires the 80% case in one chain and advanced cases one method deeper; A6 +permits helpers only for policy, a test seam, or stable non-trivial work; A10 prefers a plain +composition factory; A11 requires named extension axes. Public `define`/`create` semantics and the +ban on upstream re-exporting remain binding (`docs/architecture/doctrine/01-thesis-and-axioms.md`, +`02-public-surface.md`, `07-composition-and-extension.md`). + +### Reusable laws + +1. The preset uses the public factory; it is not a parallel implementation. +2. Every layer preserves the same inferred source value and returns the same lower-layer objects. +3. NetScript adds cross-cutting policy once; the native library remains visible at the escape hatch. +4. One registration fans out to every consumer; type-state is not promoted into runtime machinery. +5. Defaults are inspectable, immutable, and replaceable; diagnostics name the failed policy. + +## 2. What the current RFC lacks + +**[FACT]** The RFC jumps from native `defineContract` to a 40-line target/space composition and then +to a generated binding (`Step 2`, lines 227-290; `Step 3`, lines 292-363). This is a sound L2/L3 +explanation, not an A3 adoption API. Plugin space registration is separate from the application +contract example. The cost section explicitly accepts surprise “re-emit” (`lines 1037-1045`). + +**[INFERENCE]** Users must currently understand target identity, spaces, policy, artifacts, provider +registration, runtime, and binding generation before the first query. The architecture is flexible, +but the presentation does not resemble NetScript's Hono, SDK, or Fresh adoption surfaces. + +## 3. Proposed three-layer analogue + +All examples describe the same one-target app. L1 and L2 produce the same `DatabaseDefinition`; L3 +uses the same manifest, provider, ports, and native query object. None defines models, fields, +relations, filters, or queries for Prisma. + +### L1 — golden-path recipe + +```ts +import { definePostgresDatabase, fromAspire } from '@netscript/database'; +import { authDatabase } from '@netscript/plugin-auth-core/database'; +import { appContract } from './app.contract.ts'; // native Prisma defineContract(...) + +export default definePostgresDatabase({ + contract: appContract, + connection: fromAspire('postgres'), + extensions: [authDatabase()], +}); +``` + +**[PROPOSAL]** This preset chooses inspectable defaults: target `primary`, app space `app`, managed +ownership, retain-on-removal, and the certified PostgreSQL provider. It calls only the L2 functions +below. An optional chained form is justified only if real successive type-state appears; do not add +a cosmetic builder. + +### L2 — factories used by L1 + +```ts +const primary = defineDatabaseTarget({ + id: 'primary', + provider: prismaPostgres({ minVersion: 15 }), + connection: fromAspire('postgres'), + policy: { destructive: 'deny', defaultOwnership: 'managed' }, +}); + +export default defineDatabase({ + targets: { primary }, + spaces: { + app: defineDatabaseSpace({ + id: 'app', + owner: 'app', + target: 'primary', + contract: appContract, + }), + }, + extensions: [authDatabase()], +}); +``` + +**[PROPOSAL]** `extensions` is the sole registration. Each bundle may contribute authoring, +manifest/control, runtime, and validation facets; the compiler expands it in the already-planned two +phases, rejects duplicate identities, and preserves deterministic order. L1 forwards the exact same +bundle and therefore cannot omit a facet. + +### L3 — native authoring plus NetScript ports + +```ts +// app.contract.ts: direct @prisma/orm-postgres/contract-builder defineContract(...) + +// runtime.ts +import type definition from './database.ts'; // erased +import { manifest } from './.netscript/database/manifest.ts'; // emitted value + +const binding = createPrismaPostgresBinding< + ContractOf +>({ target: 'primary', space: 'app', manifestDigest: manifest.digest }); + +await using runtime = await createDatabaseRuntime({ + manifest, + providers: [prismaPostgres()], + connections, +}); +export const primary = runtime.bind(binding); // primary.query is native Prisma +``` + +**[PROPOSAL]** `ContractOf` only extracts an opaque generic; adapter-owned +`createPrismaPostgresBinding` maps it to Prisma query/transaction types. The provider-neutral kernel +never names Prisma. Advanced consumers may construct ports and call compile/plan/apply separately, +but runtime still receives only the manifest, provider values, connections, and a digest-bearing +binding—not `DatabaseDefinition`. + +## 4. Remove manual type generation + +**[FACT]** Pinned Prisma already proves both halves. Its no-emit demo calls +`postgres({ contract })` +(`.llm/tmp/prisma-v8-rc1/examples/prisma-8-demo/src/prisma-no-emit/context.ts:1-15`). More +importantly, the emitted overload accepts `contractJson` plus a compile-time `TContract`; +`_contract?: TContract` is phantom +(`packages/3-extensions/postgres/src/runtime/postgres.ts:96-129,150-166`). Runtime always +serializes/deserializes to a contract value. `PostgresClient` exposes typed `sql`, `orm`, +enums, and transactions (`lines 45-78`). Therefore a type-only `typeof definition` can type a stable +adapter factory while runtime consumes the canonical artifact. + +**[FACT]** Root `deno.json:174` enables `isolatedDeclarations`. A local minimal Deno check confirms +that an exported `const contract = defineContract(...)`-shaped inferred call requires an explicit +annotation under that option. Prisma's demo does not claim this constraint. The planned JSR audit +correctly forbids slow types for framework packages, but its claim that every app binding must be +generated was prospective, not executed evidence. + +**[PROPOSAL] Decision.** App-owned authoring modules are build inputs, not JSR exports. Give that +narrow app-local project `isolatedDeclarations: false`; retain strict checking and keep every +published `@netscript/*` package at `true`. Then the default emits **no TypeScript binding**: exact +inference flows `typeof definition → ContractOf → adapter binding`, and the import erases. +Emit/watch only content-addressed manifest, contract JSON, lineage, and provenance values. + +Artifact-only plugin spaces remain behind plugin-owned ports. If a consumer intentionally exports an +inferred database definition from a publishable package or requests direct queries over an +artifact-only space, exact types cannot be reconstructed from JSON by TypeScript. In that bounded +case, generate the provider declaration automatically and atomically during the same compile—not a +hand-run NetScript binding, not a framework slow type. W3 must prove both paths against the pinned +public declarations; fall back universally only if the direct fixture fails without private imports +or copied overloads. + +## 5. Automation and projections + +**[PROPOSAL]** `netscript dev/start/test/build` runs an initial content-hash compile before loading +the runtime; `dev` then watches the authoring graph, writes a temporary artifact set, verifies it, +and atomically swaps the directory before restarting affected consumers. Generated task dependencies +make direct project commands do the same. CI runs compile-and-diff; production startup never mutates +schema or auto-applies migrations. A digest mismatch remains a hard safety refusal, but its message +says which file changed and the normal launcher already repairs artifacts—“run re-emit” is only an +escape-hatch command, never the expected workflow. + +Aspire projects target/resources and injects connections from the manifest; CLI projects the same +operation catalog; agents read manifest/plan/receipt schemas. None evaluates the TypeScript +contract. This makes the serializable artifact both the interoperability boundary and the low-token +agent surface; L1 is the low-token authoring path, L2 is explicit customization, and L3 is a stable +escape hatch rather than an undocumented deep import. + +## 6. Ownership, RFC edits, and gates + +**[PROPOSAL] Package impact.** Keep the six-package graph. Add the L1 preset and `ContractOf` to +`@netscript/database`; put only `createPrismaPostgresBinding` and provider type mapping in +`@netscript/database-prisma-postgres/binding`; keep lifecycle in `-runtime`. No new package, global +registry, Prisma re-export, or runtime dependency is required. + +To keep the RFC at or below 10k words, replace rather than append: + +- compress `Step 2` into L1 plus the L2 expansion; replace `Step 3`'s generated module with the + type-only binding example above; +- revise “two tracks”/soundness (`lines 702-723`), costs (`1037-1045`), rationale (`1071-1073`), + migration wave 4, introduction diagram, and conclusion wherever generation is stated as universal; +- fold the single-extension rule into the composition example and delete repetitive prose that + separately re-explains target/space fields already specified in the formal contracts. + +Acceptance requires fixtures for direct inference, type-only erasure, root/published +`isolatedDeclarations`, artifact-only fallback, stale atomic watch, plugin single registration, +packed JSR consumers, manifest mismatch refusal, and native query/transaction inference. Kill the +direct path if it needs Prisma private imports, copied overloads, a provider type in a neutral +package, or runtime evaluation of authoring code; then generation must remain automatic, atomic, +launcher-integrated, and invisible. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md new file mode 100644 index 0000000000..afc10fa286 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md @@ -0,0 +1,843 @@ +# Database Architecture Market Analysis + +## Scope and method + +This is not an ORM popularity comparison. NetScript is a meta-framework, so the relevant question is +which products have solved parts of the framework-level problem: + +- one coherent developer workflow over database tooling; +- schema ownership across application features and plugins; +- multiple databases, schemas, providers, and deployment modes; +- extensible adapters without forcing every contributor to reimplement framework mechanics; +- deterministic generation and migrations; +- safe, inspectable CI/deployment; +- runtime lifecycle and connection routing; and +- an accurate agent-facing surface. + +The comparison uses official product documentation and source repositories observed on 2026-08-13. +It evaluates seventeen purposeful comparators: + +1. Wasp and RedwoodJS as Prisma-based full-stack frameworks; +2. Payload and Better Auth as plugin-heavy TypeScript products; +3. AdonisJS Lucid as an integrated application-framework database layer; +4. Drizzle, MikroORM, and Kysely as TypeScript data-tooling architectures; +5. Flyway and Liquibase as mature migration-ledger, locking, repair, and extension systems; +6. Terraform and Pulumi as plan/apply/state/checkpoint and partial-failure prior art; +7. Atlas and Bytebase as database delivery/control-plane products; +8. ZenStack v3 as a TypeScript schema/plugin/runtime-validation comparator; and +9. Django and Rails as mature app-owned migration and multi-database systems. + +A focused independent correction audit covers the additional evidence and exact recovery semantics +in more depth in [market-gap-audit.md](./market-gap-audit.md). This document integrates its +decision-relevant conclusions without reproducing the companion report verbatim. + +No product is a template to copy wholesale. The desired NetScript architecture combines the +strongest ownership, extensibility, lifecycle, and safety ideas while avoiding their manual seams. + +## Executive comparison + +| Product | Strongest relevant idea | Important limitation for NetScript | +| -------------- | ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | +| Wasp | Framework commands and generated auth/app schema create a coherent Prisma happy path | Still fundamentally one framework-managed Prisma schema/client and provider story. | +| RedwoodJS | Framework-level schema, structural migrations, seeds, and explicit data migrations | Largely forwards Prisma CLI concepts; data and structural migration ordering remains manual. | +| Payload | Thin internal database contract with official Mongo/Drizzle adapters | Adapter abstraction serves Payload's CMS model, not arbitrary app/plugin contract ownership. | +| Better Auth | Typed plugin schema declarations plus an adapter factory that centralizes mechanics | Prisma/Drizzle users still generate an ORM schema and manually migrate it. | +| AdonisJS Lucid | Named typed connections, lifecycle ownership, programmatic runner, locks, data-migration defer | ORM/config is framework-specific and plugins do not own independent contract spaces. | +| Drizzle | Broad dialect coverage, SQL escape hatches, schema filters, many migration workflows | Multiple configs and exported schema aggregation remain developer-managed; ownership is implicit. | +| MikroORM | Clean core/driver/extension split with broad providers and programmable migration runner | One ORM instance does not span independent connections; multi-schema fan-out has stateful caveats. | +| Kysely | Small open dialect/driver/plugin interfaces, zero-dependency cross-runtime query core | Schema types/codegen and migration authoring are intentionally external/manual. | +| Flyway | Mature history states, checksum validation, database locks, repair, and programmatic runner | Locations share one history; repair does not clean objects left by failed non-transactional DDL. | +| Liquibase | Changeset ledger/lock, preview/rollback, broad changelog and Java extension surfaces | Path/order-based composition and one shared ledger are not contributor-owned migration spaces. | +| Terraform | Explicit config/plan/state/backend split and honest partial-apply recovery semantics | Mutable state is not a manifest/receipt; apply is non-atomic and saved plans are opaque/sensitive. | +| Pulumi | Frequent checkpoints and first-class recovery for interrupted, outcome-unknown operations | Complete planning is weakened by program execution/unknowns; robust backends are a hosted concern. | +| Atlas | Composite schema, semantic lint, migration planning, and optional registry/control plane | Composition uses load order; continuous drift, promotion, and fleet history are Cloud services. | +| Bytebase | Plan/issue/rollout stages, SQL review, approvals, and per-database task history | Persistent control plane; current releases removed automatic schema drift detection. | +| ZenStack v3 | Explicit schema imports, schema/CLI/runtime plugins, and runtime-derived shaped Zod schemas | One aggregate history; plugins are preview and validation is Zod-specific rather than Standard. | +| Django | Per-app migration graphs with declared dependencies and mature routing | Multiple databases are operated one at a time and router mistakes may silently skip migrations. | +| Rails | Named DBs, per-DB migration roots, runtime role/shard switching, unmanaged DB flag | Database ownership is config/folder-based, not a typed plugin contribution protocol. | + +The market does not offer one complete equivalent of the proposed NetScript layer. The opportunity +is real: treat database structure as a composed, typed ownership graph; drive runtime and control +planes from it; and make safety and agent context first-class outputs. + +## Comparator deep dives + +### Wasp + +[Wasp entities](https://wasp.sh/docs/0.20/data-model/entities) are Prisma models in a +`schema.prisma` file. Wasp exposes a framework migration command and a singleton Prisma client +through `wasp/server`. Its [database documentation](https://wasp.sh/docs/data-model/databases) +supports SQLite as the default local route and PostgreSQL for production. Wasp Auth +[combines generated auth entities with the user's schema](https://wasp.sh/docs/auth/entities). + +What works: + +- the framework owns a simple end-to-end command surface; +- application code imports a framework database service rather than assembling a client; +- auth schema is derived as part of framework composition; and +- a new application gets a low-friction local database. + +What remains weak: + +- schema combination is a framework special case, not a public ownership protocol; +- plugin dependency/version/removal semantics are not first-class; +- the singleton/runtime shape is not capability- or deployment-mode-specific; +- multi-target identity and independent histories are not central; and +- migration safety remains constrained by the underlying Prisma workflow. + +NetScript lesson: preserve “one obvious workflow,” but replace implicit schema merging and singleton +service access with declared contract spaces and scoped target references. + +### RedwoodJS + +Redwood wraps Prisma migrations and client use through its CLI. Its +[data migration system](https://docs.redwoodjs.com/docs/data-migrations) adds an application-owned +ledger and timestamped TypeScript transforms alongside Prisma's structural migrations. The +[CLI reference](https://docs.redwoodjs.com/docs/cli-commands) separates `migrate dev`, +`migrate deploy`, reset, seed, and data-migrate commands. + +What works: + +- structural and content changes are recognized as different concerns; +- data migrations are plain application code with an execution ledger; +- CLI integration reduces raw tool invocation; and +- the framework documents environment-specific migration behavior. + +What remains weak: + +- structural and data migrations are separate sequences the developer must coordinate; +- new-developer replay can run structural drops before a historical data transform, requiring + defensive code or manual choreography; +- provider switching can require discarding migration history; and +- plugin schema ownership and multi-database composition are not solved. + +NetScript lesson: data transforms must be invariant-bound edges in the same plan as schema +transitions, not a second chronological folder whose correctness depends on invocation order. + +### Payload + +Payload documents a [thin database adapter](https://payloadcms.com/docs/database/overview) over its +internal data structures. Official adapters cover MongoDB/Mongoose and PostgreSQL or SQLite through +Drizzle. Its [migration commands](https://payloadcms.com/docs/database/migrations) share a common +framework surface while adapters implement provider-specific behavior; relational databases use +migration files, while Mongo workflows emphasize data transformations. + +What works: + +- framework code depends on an internal database contract; +- providers live in separate packages; +- the adapter selects the backing ORM without exposing it as the whole product contract; and +- lifecycle/migration commands remain product-level concepts. + +What remains weak: + +- the adapter is shaped around Payload collections and CMS operations; +- provider capability differences are not a general application type system; +- schema-contributing third-party packages do not get independent migration ownership by default; +- multiple arbitrary application databases are not the core abstraction. + +NetScript lesson: use an internal port and target packages, but do not create a giant generic +repository interface. Keep feature ports consumer-owned and make target capabilities explicit. + +### Better Auth + +Better Auth's [database model](https://better-auth.com/docs/concepts/database) supports multiple +adapters. Plugins can declare models/fields; the CLI can generate or migrate the required schema. +The [plugin API](https://better-auth.com/docs/beta/concepts/plugins) makes database schema part of a +typed plugin definition. Its +[adapter factory](https://better-auth.com/docs/beta/guides/create-a-db-adapter) centralizes model +and field mapping, ID generation, JSON conversion, joins, and schema configuration so an adapter +author focuses on database operations. + +What works: + +- plugin-owned database requirements are declarative and typed; +- one factory owns cross-cutting adapter behavior; +- the plugin schema is available to tooling; +- framework migration can be automatic when using the built-in Kysely route; and +- adapter authors do not repeat naming/serialization mechanics. + +What remains weak: + +- with Prisma or Drizzle, Better Auth generates ORM schema that the user must merge/apply; +- the contribution does not own a full independent migration graph and database marker; +- version upgrade/removal/data-retention policy is not a universal contract-space protocol; and +- application-wide target routing is out of scope. + +NetScript lesson: emulate the declaration and adapter-factory ergonomics, but eliminate the +“generate this then manually integrate/migrate it” boundary. + +### AdonisJS Lucid + +Lucid's [typed database configuration](https://lucid.adonisjs.com/docs/configuration) defines a +default and named connections, supports read replicas, opens connections lazily, and lets the +framework close them during shutdown. Each connection can own migration paths. Its +[migration system](https://lucid.adonisjs.com/docs/migrations) provides TypeScript up/down classes, +a ledger, transactions, advisory locks, dry runs, safe-mode options, rollback constraints, seed +integration, and a programmatic `MigrationRunner`. `defer` supports data work that should run after +schema operations. + +What works: + +- one framework config names every connection; +- runtime lifecycle belongs to the framework; +- CLI and programmatic runners use the same migration semantics; +- migration locks and transaction behavior are visible; +- connections can have separate migration roots; and +- generated schema types can be refreshed after migrations. + +What remains weak: + +- connection and migration ownership are configured in application files, not composed from + versioned plugin spaces; +- the relational/ORM model remains Lucid-specific; +- cross-connection apply is not globally atomic; and +- type regeneration is still an explicit lifecycle step. + +NetScript lesson: named connections, lazy lifecycle, one programmatic runner, and explicit lock/dry- +run behavior should all be first-class. NetScript can go further by deriving them from one graph and +making stale artifacts impossible to overlook. + +### Drizzle ORM and Drizzle Kit + +Drizzle supports +[code-first, database-first, and external migration workflows](https://orm.drizzle.team/docs/migrations). +`drizzle-kit generate` covers PostgreSQL, MySQL, SQLite, Turso, SingleStore, SQL Server, and +CockroachDB, accepts schema files or folders, checks conflicts, and permits custom SQL migrations. +The [schema declaration guide](https://orm.drizzle.team/docs/sql-schema-declaration) allows schema +split across files as long as all declarations are exported. The +[configuration file](https://orm.drizzle.team/docs/drizzle-config-file) offers schema/table/ +extension filters and multiple project configs. + +What works: + +- broad provider/dialect support; +- schema is ordinary TypeScript and can be split by feature; +- generated SQL remains inspectable and editable; +- database-first and code-first teams can use the same toolkit; +- filters can exclude externally managed objects such as PostGIS tables; and +- multiple configs can represent stages or databases. + +What remains weak: + +- multiple config files are the composition mechanism rather than one typed graph; +- exported declaration aggregation is a developer convention; +- filters express inclusion, not versioned ownership/history; +- extension/plugin migration ordering and removal are not a public framework protocol; and +- generated type/schema lifecycle is user-driven. + +NetScript lesson: retain inspectable SQL, broad adapters, and ownership filters, but make target and +space composition explicit and machine-checkable. + +### MikroORM + +MikroORM's [architecture](https://mikro-orm.io/docs/architecture) separates a database-agnostic core +from provider packages. Official drivers include PostgreSQL, MySQL/MariaDB, SQLite/libSQL, SQL +Server, Oracle, MongoDB, and others. The +[configuration system](https://mikro-orm.io/docs/configuration) registers extensions such as the +migrator, schema generator, entity generator, and seeder without forcing dynamic optional imports. +It supports replicas and attached SQLite databases. + +Its [migrator](https://mikro-orm.io/docs/migrations) is both CLI- and programmatically accessible, +supports transaction/all-or-nothing policy, snapshots, blank migrations, status/pending/check, +fresh/seed, rollup, and target ranges. Runtime schema selection can fan one migration set across +tenant schemas, with explicit documented caveats: shared-instance parallel fan-out is unsupported, +the schema state is reset in `finally`, and MSSQL does not support that runtime schema mode. + +What works: + +- clear core/driver/extension package boundaries; +- broad provider coverage without one monolithic driver; +- extension registration avoids bundler-hostile dynamic loading; +- programmatic operations match CLI operations; +- migration behavior is configurable and observable; and +- provider-specific limitations are documented rather than hidden. + +What remains weak: + +- one ORM instance does not span independent connections; +- parallel schema fan-out requires separate processes/instances; +- entity/schema ownership is still ORM metadata aggregation, not contributor contract spaces; +- feature packages do not naturally carry independent migration histories. + +NetScript lesson: capability documentation and programmatic extension registration are strong +patterns. The graph must instantiate isolated per-target runners and must never share stateful +migration instances across parallel targets. + +### Kysely + +Kysely presents a small type-safe SQL query core. Its +[`Dialect` interface](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html) creates a +driver, adapter, introspector, and compiler; users can implement their own. Official support covers +PostgreSQL, MySQL, SQL Server, SQLite, and PGlite. The [project overview](https://www.kysely.dev/) +emphasizes zero dependencies, cross-runtime execution, raw SQL escape hatches, and optional +migrations. + +The [official `kysely-ctl`](https://github.com/kysely-org/kysely-ctl) is TypeScript-first and +cross-runtime. Its config can accept a dialect or existing Kysely instance and replace migration +providers, migrators, seed providers, and seeders. Kysely's adapter base provides migration-lock +hooks, using native locks where available or a lock table otherwise. + +What works: + +- narrow, open, composable SPIs; +- query core is decoupled from schema generation; +- adapter authors can extend a base with forward-compatible defaults; +- migrations/providers are independently replaceable; +- Deno/Bun/Node are intentional targets; and +- raw SQL is an honest, typed escape hatch. + +What remains weak: + +- type generation/introspection belongs to external tools; +- schema source, migration source, and runtime type source can drift; +- migration authoring is intentionally manual; +- plugin schema ownership is not a built-in concept; and +- framework lifecycle/orchestration is left to the caller. + +NetScript lesson: keep the SPI small and extensible, but do not inherit the fragmented toolchain. +One graph must tie schema, types, migrations, connections, and agent surface together. + +### Flyway + +Flyway's Java API centers on `Flyway.configure().dataSource(...).load()` and programmatic operations +such as `migrate()`. Its +[command surface](https://documentation.red-gate.com/flyway/reference/commands) includes `migrate`, +`info`, `validate`, `repair`, and `baseline`, with undo, dry-run, comparison, and drift features +varying by edition. Recursively scanned +[locations](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-locations-setting) +feed one migration sequence and one +[schema history table](https://documentation.red-gate.com/flyway/flyway-concepts/migrations/flyway-schema-history-table). +That table records checksums and precise states including failed, missing, future, out-of-order, +outdated, and superseded migrations. + +Migration starts under a database lock with a configurable retry count; Native Connectors currently +do not implement that locking. Where the database supports transactional DDL, migrations can run +individually or, with `group=true`, as one pending-migration transaction. PostgreSQL may need a +session-level rather than transactional advisory lock for operations such as +`CREATE INDEX CONCURRENTLY`. +[Repair](https://documentation.red-gate.com/flyway/reference/commands/repair) can remove failed +ledger rows and realign checksums, but user objects left by a failed non-transactional migration +still require manual cleanup. + +Flyway also supports Java migrations, callbacks, and custom migration resolvers/executors through +its [Java hooks](https://documentation.red-gate.com/flyway/reference/usage/api-java/api-hooks). +Those are strong execution-extension points, not typed schema ownership: multiple locations still +share one history and do not acquire stable contributor IDs, independent heads, or removal policy. + +NetScript lesson: migration state vocabulary, locks, checksum integrity, and structured repair are +mature prior art. NetScript must add contributor/target identity and distinguish `failed`, +`cleanup_required`, and `outcome_unknown`; “repair ledger” must never imply “repair database.” + +### Liquibase + +Liquibase composes XML, YAML, JSON, or formatted-SQL changelogs. A changeset's durable identity is +`id + author + filepath`; +[`logicalFilePath`](https://docs.liquibase.com/secure/reference-guide-5-1-1/changelog-attributes/logicalfilepath) +stabilizes moves and avoids module collisions. `includeAll` loads recursively in alphabetical order +unless a custom comparator is supplied. These mechanisms support modular files, but not semantic +dependency edges or independent contributor histories. + +`DATABASECHANGELOG` stores checksum, order, execution type, contexts, labels, and a deployment ID; +`DATABASECHANGELOGLOCK` serializes updates with a single database row and may require +`release-locks` after an unclean exit. +[`update-sql`](https://docs.liquibase.com/secure/reference-guide-5-2-1/init-update-and-rollback-commands/update-sql) +previews generated SQL but explicitly does not prove correctness or bind a later apply. Changesets +are transactional where possible; with +[`runInTransaction=false`](https://docs.liquibase.com/secure/reference-guide-5-1/changelog-attributes/runintransaction), +a mid-changeset error can leave both schema and ledger inconsistent. Rollback, snapshot, `diff`, and +`diff-changelog` provide explicit recovery and inspection, not a continuously reconciled state +backend. +[Inspection command coverage](https://docs.liquibase.com/secure/reference-guide-5-2-1/database-inspection-change-tracking-and-utility-commands/what-are-database-inspection-commands) +also varies by object and edition. + +Liquibase has a broad Java extension model covering databases, changes, changelog formats, +executors, preconditions, snapshots, SQL generators, and resource access. `ServiceLoader` discovers +implementations and priority selects one for the current context. This is powerful but demonstrates +why NetScript contribution resolution should reject ambiguity rather than hold a plugin priority +contest. +[Extension anatomy](https://contribute.liquibase.com/extensions-integrations/extensions-overview/extension-anatomy/) + +NetScript lesson: use logical, path-independent space/migration IDs; topologically order declared +dependencies rather than files; treat arbitrary extension code as a pinned supply-chain boundary; +and do not mistake a shared lock/ledger for contributor isolation. + +### Terraform + +Terraform's most useful analogy is its explicit separation of configuration, saved plan, mutable +state, and state backend. [State](https://developer.hashicorp.com/terraform/language/state) maps +resource addresses to remote object identities and provider metadata. It is not desired +configuration and is not an immutable run receipt. A +[saved plan](https://developer.hashicorp.com/terraform/cli/commands/plan) is an opaque apply input +that can contain the full configuration, values, options, and cleartext sensitive data; a +speculative plan carries no apply intent. + +Backends store state and may provide locking, but locking is optional by backend. State uses lineage +and monotonically increasing serials to reduce unsafe manual pushes. On +[apply failure](https://developer.hashicorp.com/terraform/tutorials/cli/apply), Terraform records +completed changes, unlocks, and exits without automatic rollback; the operator fixes the cause and +applies again. `-target` is explicitly exceptional recovery machinery because it may leave changes +and outputs incomplete. `-refresh-only` makes adoption of observed drift reviewable, and also shows +why changing the framework's record of reality must be a deliberate operation. + +Provider executables expose schema, validate, configure, read, plan, and apply RPCs over gRPC and +are version/checksum-pinned. Those schemas describe provider/resource configuration and state, not +application query/mutation/result validation. +[Provider RPC lifecycle](https://developer.hashicorp.com/terraform/plugin/framework/internals/rpcs) + +NetScript lesson: the resolved manifest is immutable generated configuration, not Terraform state; +the operation receipt is evidence, not an authoritative shadow database; executable plans must be +secret-free, baseline-bound, and revalidated; and routine `--target`-style partial apply should be +rejected. NetScript should not build a remote state backend or generic provider RPC ecosystem. + +### Pulumi + +`pulumi up` executes a program, observes resource registrations, constructs a goal graph, and +compares it with recorded stack state. Pulumi does not query every provider automatically before +each preview/update; explicit refresh incorporates live drift. +[Saved update plans](https://www.pulumi.com/docs/iac/concepts/update-plans/) remain experimental and +are checked incrementally as the program runs. Unknown outputs, resources created inside `apply`, +and providers configured with unknown values can make preview incomplete, so earlier operations may +run before a plan discrepancy is discovered. + +Pulumi writes frequent checkpoints. Pulumi Cloud supplies transactional checkpoint APIs, while DIY +blob backends have locking/history but document weaker recovery from some partial failures. +Interrupted creates can remain `pending` because the engine cannot know whether the provider +finished; recovery requires inspecting the provider and then clearing or importing the object with +`pulumi refresh`. +[Interrupted-update recovery](https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/) +Pulumi does not automatically roll back failed updates, and targeted operations may use stale +recorded values for non-targeted dependencies. + +Providers combine a separate executable with language SDKs generated from a package schema; native, +Terraform-bridged, parameterized, and dynamic providers are supported. The +[plugin architecture](https://www.pulumi.com/docs/iac/concepts/plugins/) is strong extensibility +prior art, but package schemas generate SDKs rather than Standard Schema-compatible trust-boundary +validators. + +NetScript lesson: composition must be pure enough to yield a complete deterministic plan; receipts +need an `outcome_unknown` phase; uncertain operations must be inspected before retry; and hosted +transactional checkpoints, policy, audit, scheduled drift, and KMS are integration concerns rather +than kernel features. + +### Atlas + +Atlas is the closest comparator for the database control plane rather than runtime ORM. Its +[project configuration](https://atlasgo.io/atlas-schema/projects) includes a `composite_schema` data +source that loads multiple schemas—from SQL, HCL, ORMs, or external sources—into one graph. Order +controls loading for dependencies, and multiple sources can extend the same database namespace. That +is useful composition, but configuration order is weaker than declared semantic dependency edges and +independent contributor histories. + +Its [CI/CD workflow](https://atlasgo.io/guides/evaluation/ci-cd) develops a desired schema, plans a +migration, runs semantic lint/simulation in review, delivers an approved artifact, and applies it. +The local CLI/Pro surface provides schema testing, machine-readable output, versioned/declarative +planning, and synchronous pre-apply drift checks. Registry promotion, fleet deployment history, +continuous drift monitoring, notifications, and agent-mediated database access belong to +[Atlas Cloud](https://atlasgo.io/cloud/getting-started) and its +[paid agent](https://atlasgo.io/cloud/agents). Its +[destructive-change policy](https://atlasgo.io/guides/destructive-change-policy) can remove drops +from a plan, fail them deterministically in CI, and enforce deprecation workflows. The +[agent guidance](https://atlasgo.io/guides/ai-tools) treats migration generation, linting, policy, +and testing as a structured agent workflow. + +What works: + +- multiple schema sources become one inspectable graph; +- desired state and versioned migration workflows can coexist; +- semantic lint and policy run before apply; +- executable migration artifacts can be reviewed before local apply; +- synchronous pre-apply drift can guard deployments; and +- agent behavior is constrained by deterministic policy. + +What remains weak: + +- runtime query typing/client lifecycle are separate concerns; +- registry/promotion, fleet status, continuous drift, audit history, approvals, and notifications + require a hosted/commercial control plane; +- composite ordering is configuration order unless stronger semantics are layered above it; +- app/plugin packages do not automatically expose a TypeScript contribution factory. + +NetScript lesson: copy the plan-review-deliver-apply state machine, policy gates, drift vocabulary, +and composed graph semantics that can run locally. Do not infer that Atlas Cloud's registry, +continuous monitoring, rollout history, agents, or collaboration layer are cheap local primitives. +An Atlas adapter can remain an optional future delivery backend. + +### Bytebase + +Bytebase's [Plan](https://docs.bytebase.com/change-database/plan) defines DDL/DML changes for one or +more databases, receives automatic SQL review, becomes an Issue for approval, and then drives a +Rollout. Rollouts contain environment stages and per-database tasks; stages can progress +sequentially while tasks within a stage can run in parallel. SQL review, rollout policy, approvals, +scheduling, task status/logs, explicit skip reasons, and before/after schema history make partial +fleet progress visible. + +This is a persistent database control plane even when self-hosted in one container: it owns +workspace metadata, users, roles, issues, schedulers, credentials, policies, and audit history. It +does not provide an application ORM, runtime Standard Schema layer, or typed contributor-owned +migration spaces. A server-side Plan/Issue/Rollout record is not the same as a portable, signed, +offline NetScript plan artifact. + +A material current correction is that Bytebase +[removed Schema Drift Detection in 3.14.0](https://docs.bytebase.com/changelog/bytebase-3-14-0), +including its related API fields. Current schema comparison, history, and +[synchronization](https://docs.bytebase.com/change-database/synchronize-schema) must not be scored +as continuous drift monitoring. + +NetScript lesson: borrow staged per-target result visibility, SQL policy vocabulary, and explicit +partial success. Keep IAM, approval flows, schedulers, database groups, notifications, permanent +audit storage, and fleet dashboards outside the local kernel; integrate with Bytebase optionally. + +### ZenStack v3 + +ZenStack v3 is no longer Prisma-backed at runtime; it uses a Kysely-based ORM while retaining a +Prisma-superset ZModel language and PrismaClient-compatible query shape. +[Explicit imports](https://zenstack.dev/docs/modeling/multi-file) are type-checked and merged into +one schema AST before downstream tools run. This is clearer than implicit directory merging, but it +still produces one aggregate schema and one migration history rather than contributor-owned spaces. + +The preview [plugin model](https://zenstack.dev/docs/modeling/plugin) accepts a built-in provider, +local module, or npm package. Plugins can contribute schema attributes/functions, generation, CLI +behavior, and ORM runtime interception. Schema enablement and runtime installation remain distinct, +so a contribution can be only half-installed unless a higher-level manifest binds both. The current +`zen migrate` commands expose a single schema and migrations path, temporary Prisma schema +mechanics, and manual `resolve --applied`/`--rolled-back` recovery. + +The [`@zenstackhq/zod` runtime factory](https://zenstack.dev/docs/utilities/zod) is the strongest +direct comparator to NetScript validation: it derives typed model schemas from the resolved ZenStack +schema and supports `select`, `include`, `omit`, nested relation shaping, and create/update +optionality. It remains Zod 4-specific and does not document a provider-neutral Standard Schema +surface for complete operation arguments, storage/wire representations, or extension codecs. + +NetScript lesson: adopt explicit composition, runtime derivation, and selection-aware validator +ergonomics. Add stable contributor identity/history/provenance/removal policy, bind schema and +runtime installation in one record, and keep Standard Schema—not Zod—as the durable public boundary. + +### Django + +Django owns migrations per installed application. Migrations are declarative operation objects, +loaded into a graph, and declare cross-app dependencies. The +[migration operations](https://docs.djangoproject.com/en/5.2/ref/migration-operations/) preserve +historical model state and support custom schema/data operations. The +[migration guide](https://docs.djangoproject.com/en/5.2/topics/migrations/) explains that per-app +execution is best effort because dependencies may require other apps. + +Django's [multiple database](https://docs.djangoproject.com/en/5.2/topics/db/multi-db/) model uses +named aliases and ordered routers for reads, writes, relations, and migrations. Commands operate on +one database at a time through `--database`. Cross-database relations are not supported, and the +documentation warns that changing router behavior can create missing tables, extra tables, broken +foreign keys, or silent migration skips. + +What works: + +- feature/app ownership of migrations is mature; +- dependency graphs compose histories without flattening files; +- historical state allows deterministic migration replay; +- database routing is a first-class policy surface; and +- app removal has an explicit migration/squash/deploy sequence. + +What remains weak: + +- router ordering and `None` fallthrough can be subtle; +- migration refusal can become a silent skip; +- multi-database commands require repeated explicit invocation; +- cross-database relations cannot be made transparent. + +NetScript lesson: adopt per-contributor graphs and explicit dependencies. Reject silent skip: +composition must return a complete target/space decision table, and every omitted operation needs a +reason code. + +### Rails Active Record + +Rails' +[multiple database guide](https://guides.rubyonrails.org/active_record_multiple_databases.html) +supports named databases, primary/replica roles, horizontal shards, automatic/manual connection +switching, per-database migration directories, and a generator `--database` selector. +`database_tasks: false` explicitly marks an external database whose schema/migrations/seeds Rails +must not manage. + +What works: + +- external/unmanaged databases are explicit; +- target identity controls migration folders and generators; +- runtime read/write role and shard switching are framework concepts; +- connection classes provide granular binding. + +What remains weak: + +- ownership is configuration/folder convention rather than a typed graph; +- schema-contributing engines/plugins do not automatically carry isolated migration spaces; +- cross-database associations have caveats; and +- target capability typing is limited. + +NetScript lesson: an explicit `managed: false`-style policy is essential. NetScript should +generalize it into managed/adopted/external/ignored ownership and use stable target IDs for every +artifact. + +## Cross-market capability matrix + +The earlier broad matrix overstated Atlas's local capabilities and scored an unimplemented NetScript +proposal as already strong. This narrower matrix evaluates the four artifacts at the center of the +RFC: resolved manifest, executable plan, receipt/recovery record, and contributor space, plus the +runtime validation boundary. **Strong** means a current primary capability; **partial** means +materially different or manual; **hosted** means a persistent control plane is required. The +NetScript row is an unimplemented design target, not a market fact. + +| Product/pattern | Resolved desired manifest | Apply-bound plan | Durable run evidence / partial recovery | Contributor-owned schema + history | Runtime selection-aware validation | Lock / drift boundary | +| --------------------- | -------------------------------------------- | --------------------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------ | ----------------------------------------------------- | ------------------------------------------------------------- | +| Flyway | Partial config + ordered migrations | None; dry-run is not bound | Strong history/repair; manual object cleanup can remain | None; locations merge into one history | None | JDBC database lock; Native Connector gap; drift edition-gated | +| Liquibase | Partial root changelog | Partial `update-sql` preview | Strong ledger/lock/rollback vocabulary | Partial module identity, shared ledger | None | Database lock; explicit diff/snapshot, not reconciliation | +| Terraform CLI | Strong config graph; mutable state separate | Strong opaque saved plan | Strong mutable state and partial-apply recovery; no rollback | Partial modules/providers, not DB owners | None; provider schemas are unrelated | Backend-dependent lock; refresh/refresh-only drift | +| Pulumi OSS | Partial graph emerges from program execution | Partial/experimental and incrementally enforced | Strong checkpoints and pending-operation recovery | Partial packages/components, not DB owners | None; package schemas generate SDKs | DIY lock; explicit refresh | +| Pulumi Cloud | Same program graph | Partial/experimental | Hosted transactional checkpoints, history, and policy | None for DB schema ownership | None | Hosted locking and scheduled drift | +| Atlas CLI/Pro | Strong schema graph | Partial/strong migration and declarative planning | Strong migration directory/ledger and local apply evidence | Partial composite sources; load order, not owned histories | None | Pre-apply drift is Pro; local apply semantics | +| Atlas Cloud | Strong registry source of truth | Strong promotion/registry workflow | Hosted deployment history and fleet status | Partial source composition | None | Hosted agents, scheduled drift, notifications | +| Bytebase current | Strong persistent server-side Plan | Strong Plan → Issue → Rollout, not offline artifact | Strong stage/task history and partial fleet rollout | None | None | Persistent scheduler; automatic drift feature removed | +| ZenStack v3 | Strong single composed AST | None beyond wrapped migration workflow | Partial migration status/resolve | Partial schema/plugin contribution; one history | Strongest comparator, but Zod-specific and incomplete | No multi-target lock/drift layer | +| Prisma 8 RC substrate | Strong contract snapshot per target | Emerging control plan | Stronger graph/marker/ledger substrate | Strong spaces; removal/retention conditional | No stable public Standard Schema layer | Adapter/provider dependent | +| Proposed NetScript | **Design target, not implemented** | **Design target; live-baseline binding unproven** | **Design target; unknown/partial/resume paths unproven** | **Conditional on NetScript policy and upstream conformance** | **Design target; runtime/AOT equivalence unproven** | **Design target; local per-target only, no hosted monitor** | + +## Design patterns to import + +### 1. One resolved manifest, not many config files + +Adonis, Rails, and Django prove stable named connections are understandable. Atlas proves multiple +schema sources can be composed. NetScript should combine them: + +```text +defineDatabaseManifest({ + targets: { + primary: databaseTarget(...), + analytics: databaseTarget(...), + }, + contributions: [ + appDatabase(...), + auth.database(...), + billing.database(...), + ], +}); +``` + +The source manifest must resolve through one pure function to a deterministic, content-addressed +snapshot before runtime or database access. Array position, file path, provider discovery order, and +package-manager traversal must not become semantic dependency edges. + +### 2. Contributor-owned migration spaces + +Django's per-app graph and Prisma 8's contract spaces are the strongest ownership models. Each +contributor needs: + +- stable ID and version; +- target-selection predicate; +- provider/capability requirements; +- owned contract artifact; +- migration graph and head; +- dependencies; +- data transforms/invariants; +- ownership policy; +- removal/data-retention policy; and +- provenance/signature. + +The app consumes pinned mirrors; installation never mutates another contributor's source. + +### 3. A factory that owns adapter mechanics + +Better Auth and Kysely show how to make extension authors productive: a small factory/base +centralizes naming, lifecycle, serialization, errors, and compatibility. NetScript target authors +should supply only provider-specific capabilities and bindings, then pass a conformance kit. + +### 4. An apply-bound plan is the deployment contract + +Atlas's develop/review/deliver/apply model is useful process prior art. Terraform and Pulumi add the +harder recovery lesson: a preview is not an executable plan, and applying a valid plan is not an +atomic transaction. Every mutating NetScript database operation should follow: + +```text +compose -> inspect -> plan -> policy/lint/test -> approve -> apply -> verify -> receipt +``` + +The approved artifact binds the resolved-manifest digest, exact target and contribution spaces, +environment, live-baseline fingerprint, ordered operations, policy result, provider/package lock +digests, and expiry. It excludes secret values and carries only stable references. Apply acquires +the native lock, revalidates every binding, checkpoints irreversible operations, and refuses stale +inputs. A speculative preview may be human-readable, but it must not be accepted as this artifact. + +### 5. Managed and external ownership are different + +Rails' `database_tasks: false`, Drizzle filters, Atlas external sources, and Prisma's Supabase drift +incident all point to the same requirement. NetScript must never treat every visible object as +framework-owned. + +### 6. Capability-specific APIs beat false portability + +MikroORM and Django document provider differences; Kysely exposes dialect behavior; Prisma separates +families and targets. NetScript should expose common lifecycle/control concepts but capability-gate +provider-specific query and migration features. + +### 7. Programmatic core, CLI and agents as projections + +Adonis, MikroORM, Kysely, and Atlas expose programmatic runners. NetScript commands should call one +typed operation API. Help, JSON schema, documentation, and agent skills should be generated views of +that operation catalog. + +## Artifact and control-plane boundary + +The RFC should name five artifacts and keep their responsibilities disjoint: + +1. **Source manifest:** authored targets, contributions, dependencies, ownership, and policy. +2. **Resolved snapshot:** pure, deterministic, content-addressed composition with provenance. +3. **Executable plan:** an expiring deployment contract bound to one inspected baseline and exact + provider/package locks. +4. **Upstream ledger or marker:** provider-native migration history and lock evidence; NetScript + reads it but does not invent a second mutable source of truth. +5. **Operation receipt:** immutable append-only evidence of attempted work, checkpoints, + verification, and any uncertain or partial outcome. + +The local NetScript kernel should own deterministic resolution and digests; overlap and provenance +checks; local policy/lint/test; native lock orchestration; target/space invocation; immutable +receipts and inspect-before-resume; and the runtime Standard Schema validation boundary. It should +not turn the manifest or receipts into Terraform-like mutable state. + +Remote state and transactional checkpoints, organization/RBAC systems, approval and issue workflow, +artifact registries and promotion, continuous drift schedulers, fleet dashboards, centralized audit +servers, notifications, agents, and KMS/secrets are optional control-plane concerns. Pulumi Cloud, +Atlas Cloud, and Bytebase show their value, but also the persistent services and operators they +require. The local meta-framework should expose stable integration events and artifact formats for +such systems, not quietly rebuild them. + +## Plan-lock consequences + +The comparison changes these RFC decisions: + +1. The manifest, snapshot, plan, upstream ledger, and receipt are separate types. None is a mutable + general-purpose state backend. +2. Preview and executable planning are different operations. Only the latter may be approved and + applied, and it binds manifest digest, target/space set, baseline, ordered operations, policy, + package/provider locks, environment, and expiry. +3. Apply acquires a provider-native lock and then revalidates the baseline and all plan bindings. + Lock scope, timeout, owner/nonce, stale-lock inspection, and any force-unlock path are explicit; + unsupported locking is surfaced as a capability gap. +4. Receipt states include at least `planned`, `locked`, `started`, `applied`, `verified`, `failed`, + `partial_success`, `skipped`, `cleanup_required`, and `outcome_unknown`. Checkpoint after each + irreversible operation. +5. After interruption or transport loss, inspect the database and upstream ledger before retrying. + Never blindly replay an operation whose outcome is unknown. +6. Cross-target execution is a dependency-ordered saga, not an atomic transaction. Report each + target/space result and do not promise automatic rollback. +7. Selective target/space execution includes dependency closure, records omitted work and reasons, + and still verifies whole-manifest invariants. Terraform-style targeting is exceptional recovery, + not the normal deployment model. +8. Drift comparison is ownership-aware: managed, adopted, external, and ignored objects have + different policies. Adoption is an explicit reviewed operation. +9. Logical IDs, not paths, array order, config order, or provider discovery, define identity and + dependencies. +10. Plugin contributions carry version, digest, provenance, capabilities, owned space, lifecycle + phase, and removal policy. Schema-time and runtime halves must install and validate together. +11. Contributor removal and data retention remain conditional until the upstream substrate proves + the required semantics and NetScript passes conformance tests. +12. Runtime validation binds operation, target, normalized selection, wire representation, codecs, + cache key, and runtime/AOT equivalence. A Zod adapter is useful, but is not the Standard Schema + contract itself. +13. Registry, promotion, fleet history, continuous drift, RBAC, approvals, notifications, and + centralized secrets remain external control-plane integrations unless separately chartered. + +## Anti-patterns to reject + +The market analysis reinforces explicit rejection of: + +- forwarding an upstream ORM CLI as the NetScript architecture; +- generated schema that still requires a manual merge or second migrate command; +- multiple same-provider databases represented by copied config files and engine folders; +- plugin installation that copies schema into the application; +- silent router/filter/selector skips; +- a universal singleton client; +- “supports multiple databases” that means only repeated manual commands; +- generated code repaired by string replacement; +- data transforms sequenced independently from structural migration state; +- shared stateful migration runners used concurrently; +- treating the source manifest or immutable receipts as a Terraform-style mutable state backend; +- accepting a dry run or speculative preview as an apply-bound plan; +- using targeted partial apply as the routine deployment path; +- deriving dependencies from alphabetical, filesystem, array, or provider-discovery order; +- treating migration-ledger repair as proof that partially created database objects were cleaned up; +- claiming registry, promotion, fleet, continuous drift, audit, approval, or notification features + without the hosted control plane that implements them; +- assigning a proposed capability a market score of “strong” before implementation and conformance + evidence; +- database-specific behavior hidden behind an over-broad generic repository; and +- agent instructions maintained separately from the real command/type surface. + +## Proposed market position + +NetScript can plausibly offer a distinctive database story: + +> Declare every database target and schema contributor once. NetScript composes and validates the +> resolved manifest, provisions connections, emits only canonical artifacts, binds typed runtime +> sessions, plans and verifies every migration, and gives humans, CI, plugins, and agents the same +> structured view—without copied schemas, patched clients, or hidden manual steps. + +That is materially more than a Prisma wrapper. It is a meta-framework control and composition layer +whose first high-fidelity runtime/control adapter is Prisma 8 PostgreSQL. + +## Primary source register + +- Wasp: [entities](https://wasp.sh/docs/0.20/data-model/entities), + [databases](https://wasp.sh/docs/data-model/databases), + [auth entities](https://wasp.sh/docs/auth/entities) +- RedwoodJS: [data migrations](https://docs.redwoodjs.com/docs/data-migrations), + [CLI commands](https://docs.redwoodjs.com/docs/cli-commands), + [database seeds](https://docs.redwoodjs.com/docs/database-seeds/) +- Payload: [database adapters](https://payloadcms.com/docs/database/overview), + [migrations](https://payloadcms.com/docs/database/migrations) +- Better Auth: [database](https://better-auth.com/docs/concepts/database), + [plugins](https://better-auth.com/docs/beta/concepts/plugins), + [adapter factory](https://better-auth.com/docs/beta/guides/create-a-db-adapter) +- AdonisJS Lucid: [configuration](https://lucid.adonisjs.com/docs/configuration), + [migrations](https://lucid.adonisjs.com/docs/migrations) +- Drizzle: [migration workflows](https://orm.drizzle.team/docs/migrations), + [generate](https://orm.drizzle.team/docs/drizzle-kit-generate), + [migrate](https://orm.drizzle.team/docs/drizzle-kit-migrate), + [schema declaration](https://orm.drizzle.team/docs/sql-schema-declaration), + [configuration](https://orm.drizzle.team/docs/drizzle-config-file) +- MikroORM: [architecture](https://mikro-orm.io/docs/architecture), + [configuration](https://mikro-orm.io/docs/configuration), + [multiple schemas](https://mikro-orm.io/docs/multiple-schemas), + [migrations](https://mikro-orm.io/docs/migrations) +- Kysely: [overview](https://www.kysely.dev/), + [Dialect SPI](https://kysely-org.github.io/kysely-apidoc/interfaces/Dialect.html), + [adapter base](https://kysely-org.github.io/kysely-apidoc/classes/DialectAdapterBase.html), + [official CLI](https://github.com/kysely-org/kysely-ctl) +- Flyway: [commands](https://documentation.red-gate.com/flyway/reference/commands), + [locations](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-locations-setting), + [schema history](https://documentation.red-gate.com/flyway/flyway-concepts/migrations/flyway-schema-history-table), + [repair](https://documentation.red-gate.com/flyway/reference/commands/repair), + [Java hooks](https://documentation.red-gate.com/flyway/reference/usage/api-java/api-hooks) +- Liquibase: + [logical file identity](https://docs.liquibase.com/secure/reference-guide-5-1-1/changelog-attributes/logicalfilepath), + [SQL preview](https://docs.liquibase.com/secure/reference-guide-5-2-1/init-update-and-rollback-commands/update-sql), + [transaction control](https://docs.liquibase.com/secure/reference-guide-5-1/changelog-attributes/runintransaction), + [inspection](https://docs.liquibase.com/secure/reference-guide-5-2-1/database-inspection-change-tracking-and-utility-commands/what-are-database-inspection-commands), + [extension anatomy](https://contribute.liquibase.com/extensions-integrations/extensions-overview/extension-anatomy/) +- Terraform: [state](https://developer.hashicorp.com/terraform/language/state), + [saved/speculative plans](https://developer.hashicorp.com/terraform/cli/commands/plan), + [apply failure](https://developer.hashicorp.com/terraform/tutorials/cli/apply), + [provider RPC lifecycle](https://developer.hashicorp.com/terraform/plugin/framework/internals/rpcs) +- Pulumi: [update plans](https://www.pulumi.com/docs/iac/concepts/update-plans/), + [interrupted updates](https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/), + [plugins](https://www.pulumi.com/docs/iac/concepts/plugins/) +- Atlas: [project/composite schema](https://atlasgo.io/atlas-schema/projects), + [CI/CD](https://atlasgo.io/guides/evaluation/ci-cd), + [destructive policy](https://atlasgo.io/guides/destructive-change-policy), + [agent workflow](https://atlasgo.io/guides/ai-tools), + [Cloud](https://atlasgo.io/cloud/getting-started), [Cloud agents](https://atlasgo.io/cloud/agents) +- Bytebase: [plans](https://docs.bytebase.com/change-database/plan), + [schema synchronization](https://docs.bytebase.com/change-database/synchronize-schema), + [3.14.0 drift-feature removal](https://docs.bytebase.com/changelog/bytebase-3-14-0) +- ZenStack v3: [multi-file schemas](https://zenstack.dev/docs/modeling/multi-file), + [plugins](https://zenstack.dev/docs/modeling/plugin), + [selection-aware Zod factory](https://zenstack.dev/docs/utilities/zod) +- Django: [migrations](https://docs.djangoproject.com/en/5.2/topics/migrations/), + [migration operations](https://docs.djangoproject.com/en/5.2/ref/migration-operations/), + [multiple databases](https://docs.djangoproject.com/en/5.2/topics/db/multi-db/), + [application removal](https://docs.djangoproject.com/en/5.2/howto/delete-app/) +- Rails: [multiple databases](https://guides.rubyonrails.org/active_record_multiple_databases.html) diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md new file mode 100644 index 0000000000..312ad2aae7 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-gap-audit.md @@ -0,0 +1,488 @@ +# Independent Market-Analysis Gap Audit + +Provenance: independent delegated audit, current 2026-08-13, using official/primary sources only. + +Read-only audit completed against the existing `market-analysis.md`, current as of 2026-08-13. No +repository files were changed during the audit. + +## Executive corrections + +The omitted products materially change the market conclusions: + +- Flyway and Liquibase establish that migration ledgers, checksums, locks, repair, rollback + previews, and partial-failure handling are mature prior art. NetScript’s differentiation is not + inventing those mechanics; it is composing them across stable targets and contributor-owned spaces + with typed runtime validation. +- Terraform is useful mainly as negative and recovery prior art. Terraform state is a mutable + binding database, not a manifest or receipt; its apply is not transactional; saved plans are + opaque and sensitive; and targeted apply is explicitly exceptional. +- Pulumi strengthens the checkpoint/unknown-outcome lesson, but also shows the operational cost of + transactional state backends. Its saved update plans remain experimental and are checked + incrementally during execution. +- Bytebase is a persistent database control plane, not a local framework library. Most of its + impressive features depend on server-side plans, issues, IAM, stages, tasks, schedulers, and + metadata. Importantly, Bytebase removed schema drift detection in version 3.14.0 in January 2026. +- ZenStack v3 is the closest omitted comparator for schema/runtime composition. It explicitly + imports schema files into one AST, has preview schema/CLI/runtime plugins, and derives + selection-shaped Zod validators from its runtime schema. But it does not provide contributor-owned + migration spaces, Standard Schema neutrality, or plugin removal/retention semantics. +- No further comparator clears the “truly essential” bar. Kubernetes controllers/finalizers could + add recovery vocabulary, but would pull the RFC toward a continuous reconciler—the exact + control-plane expansion NetScript should avoid. + +The current matrix’s “Proposed NetScript = Strong everywhere” row should be removed. All proposed +capabilities are design targets, and contributor removal remains conditional on NetScript policy +plus upstream conformance. + +## Comparator findings + +### Flyway + +Architecture and mechanics: + +- The Java API centers on `Flyway.configure().dataSource(...).load()` and methods such as + `migrate()`. The CLI exposes `migrate`, `info`, `validate`, `repair`, `baseline`, and + edition-gated `undo`, dry-run, drift, and schema-comparison commands. + [Java API](https://documentation.red-gate.com/flyway/reference/usage/api-java), + [command inventory](https://documentation.red-gate.com/flyway/reference/commands) +- Recursively scanned `locations` provide SQL or classpath Java migrations. All locations feed one + resolved migration sequence and one schema-history table; they are not independent owner + histories. + [Locations](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-locations-setting) +- The history table records version, description, checksum, installer, duration, success, and states + including `Pending`, `Success`, `Failed`, `Missing`, `Future`, `Out of Order`, `Outdated`, and + `Superseded`. Flyway explicitly warns that replay after an out-of-order migration may differ. + [Schema history table](https://documentation.red-gate.com/flyway/flyway-concepts/migrations/flyway-schema-history-table) +- `validate` compares available migrations against applied metadata and checksums. `repair` deletes + failed ledger entries, aligns metadata/checksums, and marks missing migrations deleted. It does + not clean user objects left by a failed non-transactional migration, and it must use the same + locations as `migrate`. + [Repair](https://documentation.red-gate.com/flyway/reference/commands/repair) +- Flyway locks before migration, retrying once per second; the current default is 50 attempts, with + `-1` meaning indefinitely. Native Connectors currently do not implement this locking. + [Lock retry](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-lock-retry-count-setting) +- Migrations are normally transactional where the database permits it. `group=true` can place all + pending migrations in one transaction, but only on transactional-DDL databases; callbacks are + excluded and Native Connectors do not support this transaction mode. + [Group transaction](https://documentation.red-gate.com/flyway/reference/configuration/flyway-namespace/flyway-group-setting) +- PostgreSQL uses transactional advisory locking by default; `CREATE INDEX CONCURRENTLY` may require + session-level locking instead. + [PostgreSQL behavior](https://documentation.red-gate.com/flyway/reference/database-driver-reference/postgresql-database) +- Extension hooks include Java migrations, lifecycle callbacks, and custom `MigrationResolver` plus + `MigrationExecutor` pairs. These add executable migration formats and behavior, not typed schema + contributions or ownership spaces. + [API hooks](https://documentation.red-gate.com/flyway/reference/usage/api-java/api-hooks) + +DX strengths: + +- Extremely legible operational model. +- Same lifecycle available from CLI, build tools, and Java API. +- Explicit status vocabulary and machine-readable command results. +- Honest transaction and cleanup caveats. + +Failure modes and NetScript lessons: + +- Never let “repair ledger” imply “repair database.” Record cleanup-required and outcome-unknown + states separately. +- A lock capability must be part of target conformance; unsupported connectors cannot silently + proceed. +- Out-of-order/cherry-picked application can make fresh replay differ. Selective operations must be + recovery-only or produce a mandatory full verification. +- Multiple locations do not create ownership. NetScript spaces need stable IDs, independent heads, + dependency edges, overlap detection, and removal policy. +- Drift checking and dry-run facilities are edition-gated. NetScript’s local safety baseline should + not depend on reproducing Redgate’s complete comparison product. + +### Liquibase + +Architecture and mechanics: + +- A root changelog in XML, YAML, JSON, or formatted SQL includes changesets and other changelogs. + `includeAll` recursively includes files in alphabetical order unless a custom comparator is + installed. + [includeAll](https://docs.liquibase.com/secure/reference-guide-5-0/changelog-attributes/includeall) +- A changeset is identified by `id + author + filepath`. `logicalFilePath` stabilizes identity + across moves and can prevent module collisions, but module files still share one changelog + execution model and ledger. + [logicalFilePath](https://docs.liquibase.com/secure/reference-guide-5-1-1/changelog-attributes/logicalfilepath) +- `DATABASECHANGELOG` stores each execution, checksum, execution type, order, contexts, labels, and + deployment ID. A deployment ID groups changesets from one update run. + [DATABASECHANGELOG](https://docs.liquibase.com/community/user-guide-5-0-2/what-is-the-databasechangelog-table) +- `DATABASECHANGELOGLOCK` is a single-row database lock. Concurrent updaters wait; an unclean exit + can leave it set, requiring `release-locks`. + [Lock table](https://docs.liquibase.com/pro/user-guide-4-33/what-is-the-database-changelog-lock-table) +- `update-sql` previews generated SQL but explicitly does not establish correctness or predict + deployment errors. It is not an apply-bound plan artifact. + [update-sql](https://docs.liquibase.com/secure/reference-guide-5-2-1/init-update-and-rollback-commands/update-sql) +- Changesets run in a transaction by default where possible. With `runInTransaction=false`, a + mid-changeset failure can leave both the database and `DATABASECHANGELOG` inconsistent. + [runInTransaction](https://docs.liquibase.com/secure/reference-guide-5-1/changelog-attributes/runintransaction) +- Checksums reject unexpected edits; `runOnChange` deliberately re-executes changed definitions. + [runOnChange](https://docs.liquibase.com/reference-guide/changelog-attributes/runonchange) +- Rollback can target a tag, date, count, changeset, or deployment ID depending on edition. Rows are + removed from the active changelog ledger during rollback; newer history facilities preserve a + fuller audit. Rollback SQL is often author-supplied and can lose data. + [Rollback commands](https://docs.liquibase.com/community/reference-guide-5-0/init-update-and-rollback-commands/what-are-rollback-commands) +- `diff`, `snapshot`, and `diff-changelog` compare databases or snapshots. This is explicit + inspection, not Terraform-style continuous state reconciliation. Machine-readable drift reporting + and richer object coverage vary by edition. + [Inspection commands](https://docs.liquibase.com/secure/reference-guide-5-2-1/database-inspection-change-tracking-and-utility-commands/what-are-database-inspection-commands) +- Liquibase’s Java extension surface is broad: database types, changelog formats, changes, + executors, preconditions, snapshot generators, SQL generators, and resource handlers. Java + `ServiceLoader` discovers implementations; priority selects the applicable implementation. + `customChange` can execute code or generate SQL. + [Extension anatomy](https://contribute.liquibase.com/extensions-integrations/extensions-overview/extension-anatomy/), + [extension points](https://contribute.liquibase.com/extensions-integrations/extension-guides/), + [customChange](https://docs.liquibase.com/secure/reference-guide-5-0/change-types/customchange) + +DX strengths: + +- Flexible changelog formats and database coverage. +- Mature module/path identity tools. +- Rich preview, inspection, rollback, and extension ecosystem. +- Integration-independent engine semantics. + +Failure modes and NetScript lessons: + +- Path is part of identity. NetScript space IDs and migration IDs must be logical, never derived + from consumer filesystem layout. +- Alphabetical include order is not a dependency graph. Composition must use declared dependencies + and deterministic topological ordering. +- A global single-row lock and shared ledger do not isolate contributors. +- `validate` checks changelog structure/checksums, not database-specific SQL correctness or all live + drift. +- A plugin priority contest is not a safe schema-contribution protocol. NetScript should reject + ambiguous providers instead of choosing whichever implementation reports the highest priority. +- Arbitrary extension code is a supply-chain boundary; plugin version, checksum, provenance, and + allowed execution phases belong in the manifest snapshot. + +### Terraform state, plan/apply, and providers + +Architecture and mechanics: + +- Terraform configuration plus modules form desired configuration. State is a separate mutable + mapping between resource addresses and real remote objects, including provider metadata. It is + neither desired configuration nor an immutable execution receipt. + [State](https://developer.hashicorp.com/terraform/language/state) +- `plan` refreshes current objects, compares configuration with prior state, and proposes a graph of + actions. A speculative plan has no apply intent. `-out` creates an opaque saved plan consumed by + `apply`; the file embeds full configuration, values, options, and potentially cleartext sensitive + data. [Plan](https://developer.hashicorp.com/terraform/cli/commands/plan) +- Backends store state and may provide locking. Locking is optional by backend. If remote + persistence fails, Terraform writes state locally and requires manual recovery. State snapshots + carry lineage and monotonically increasing serial values to reduce unsafe pushes. + [Backends](https://developer.hashicorp.com/terraform/language/state/backends) +- State locking is automatic for operations that may write state. `force-unlock` requires a unique + lock ID but can still cause concurrent writers if misused. + [State locking](https://developer.hashicorp.com/terraform/language/state/locking) +- On apply failure, Terraform records completed changes in state, unlocks, and exits. It does not + roll back a partially completed apply; the operator fixes the cause and applies again. + [Apply failure](https://developer.hashicorp.com/terraform/tutorials/cli/apply) +- `-target` deliberately produces an incomplete view and is documented only for exceptional + recovery. Terraform recommends splitting routinely independent systems rather than normalizing + targeted apply. + [Resource targeting](https://developer.hashicorp.com/terraform/tutorials/state/resource-targeting) +- Normal plan/apply performs an in-memory refresh. `-refresh-only` lets operators review adoption of + live drift into state; careless refresh can forget resources if provider configuration or + credentials point at the wrong place. + [Refresh-only](https://developer.hashicorp.com/terraform/tutorials/state/refresh) +- Providers are separately downloaded executable plugins using gRPC. `GetProviderSchema`, + validation, configure, read, plan, and apply RPCs form the lifecycle. Provider and resource + schemas describe configuration and state—not application input/output validation. Provider + versions and checksums are pinned in the dependency lock file. + [Provider RPCs](https://developer.hashicorp.com/terraform/plugin/framework/internals/rpcs), + [provider requirements](https://developer.hashicorp.com/terraform/language/providers/requirements) + +DX strengths: + +- Clear preview/apply workflow and dependency graph. +- Strong provider isolation and version locking. +- Good partial-failure recovery vocabulary. +- Backend locking, lineage, serial, and state recovery are proven operational patterns. + +False analogy and lessons: + +- NetScript’s manifest snapshot must not become “Terraform state.” It is immutable resolved + configuration; live database markers and migration ledgers remain provider-owned. +- An operation receipt must not become an authoritative shadow copy of the database. It records what + was attempted and observed. +- A NetScript executable plan should exclude secrets, use secret references, bind the live baseline, + and have a documented stable schema. Copying Terraform’s opaque, sensitive plan artifact would be + wrong. +- Database migration edges are not CRUD resources. DDL atomicity, irreversible data transforms, and + “operation completed but ledger write was lost” need explicit treatment. +- Do not expose casual `--target` semantics. A selected apply needs dependency closure, + omitted-operation reason codes, and a subsequent whole-target verification. +- Do not build a remote state backend, workspace service, or generic provider RPC system merely to + resemble Terraform. + +### Pulumi + +Architecture and mechanics: + +- `pulumi up` executes the user program, observes resource registrations, builds a goal graph, + compares it to recorded stack state, and calls resource providers. Unlike Terraform, Pulumi does + not refresh live resources before every preview/update unless requested. + [State and refresh](https://www.pulumi.com/docs/iac/concepts/state-and-backends/) +- `pulumi preview --save-plan=plan.json` and `pulumi up --plan=plan.json` constrain an update, but + update plans are experimental. They are not validated all at once: discrepancies are discovered as + program execution and input resolution proceed, so earlier planned operations may already have + run. Unknown outputs, resources created inside `apply`, and providers configured with unknown + values reduce plan completeness. + [Update plans](https://www.pulumi.com/docs/iac/concepts/update-plans/) +- State is stored as frequent checkpoints. Pulumi Cloud uses transactional checkpoint APIs; DIY blob + backends have history and locking but explicitly offer weaker recovery from some partial failures. + [State backends](https://www.pulumi.com/docs/iac/concepts/state-and-backends/) +- An interrupted create can leave a `pending operation` because the engine cannot know whether the + provider completed it. Recovery requires checking the provider, then using `pulumi refresh` to + clear or import the created physical resource. + [Interrupted updates](https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/) +- Pulumi does not automatically roll back a failed update. By default it finishes in-flight + operations and stops; `--continue-on-error` may continue independent branches while preserving + dependency constraints. + [Failure behavior](https://www.pulumi.com/docs/support/faq/infrastructure/) +- Targeted operations use URNs. Non-targeted dependencies are read from recorded state, so targeted + work can defer code/infrastructure drift. + [Targeted updates](https://www.pulumi.com/docs/iac/guides/basics/targeted-updates/) +- Providers consist of an executable and a language SDK generated from a package schema. Providers + can be native, bridged from Terraform/OpenTofu, parameterized, or dynamic. Plugins run as separate + processes, mostly over gRPC. [Providers](https://www.pulumi.com/docs/iac/concepts/providers/), + [package schema](https://www.pulumi.com/docs/iac/using-pulumi/extending-pulumi/schema/), + [plugins](https://www.pulumi.com/docs/iac/concepts/plugins/) + +DX strengths: + +- Familiar programming languages and strong generated SDKs. +- Frequent checkpoints preserve partial progress. +- Excellent explicit treatment of unknown outcomes after interruption. +- Components and provider inheritance are ergonomic. + +Failure modes and NetScript lessons: + +- “Preview” is not necessarily a complete plan when the desired graph is computed by arbitrary code. + NetScript composition must be pure and deterministic. +- Receipts need an `outcome_unknown` phase, not just success/failure, for connection loss after an + operation begins. +- Resume must verify uncertain operations before retrying; non-idempotent replay can corrupt data. +- Transactional checkpoint services, audit history, scheduled drift, policy hosting, and KMS-backed + secrets are backend products—not appropriate NetScript kernel responsibilities. +- Pulumi package schemas generate language SDKs. They are not a precedent for Standard + Schema-compatible runtime boundary validation. + +### Bytebase + +Architecture and mechanics: + +- A Bytebase `Plan` contains one or more DDL/DML changes targeting databases or database groups. It + begins in `Draft`, receives automatic SQL review, becomes an Issue for approval, and then produces + a Rollout. [Plans](https://docs.bytebase.com/change-database/plan) +- A rollout is organized into environment stages and per-database tasks. Stages can run sequentially + while tasks within a stage can run in parallel; the API exposes task status and explicit skip + operations with a reason. [Batch change](https://docs.bytebase.com/change-database/batch-change), + [rollout API](https://docs.bytebase.com/api-reference/rolloutservice/get-v1projects-rollouts) +- Rollout policy controls manual versus automatic execution, role permissions, required approvals, + and enforcement of plan-check errors/warnings. + [Rollout permissions](https://docs.bytebase.com/change-database/environment-policy/rollout-policy) +- SQL Review checks syntax, engine-specific policy, schema practices, security, and performance, but + some enforcement levels and approval features are commercial. + [SQL Review](https://docs.bytebase.com/change-database/review) +- Change history records applied SQL plus before/after schema snapshots. Schema Synchronization + compares a selected historical/source schema to targets and generates editable DDL. + [Change history](https://docs.bytebase.com/change-database/change-history), + [schema synchronization](https://docs.bytebase.com/change-database/synchronize-schema) +- Bytebase previously offered automatic schema-drift detection, but release 3.14.0 explicitly + removed the feature and related API fields. Current comparisons and synchronization must not be + described as continuous drift monitoring. + [3.14.0 removal](https://docs.bytebase.com/changelog/bytebase-3-14-0) +- Bytebase is a persistent server even when self-hosted in one Docker container. Its workflow + depends on workspace metadata, users, roles, issues, approvals, schedulers, and database + credentials. It has no application runtime ORM, Standard Schema surface, or typed third-party + schema-contribution protocol. + +DX strengths: + +- Excellent human review and fleet rollout UI. +- Concrete stage/task partial-progress reporting. +- Strong SQL policy and approval workflow. +- Useful before/after schema history. + +Failure modes and NetScript lessons: + +- Do not claim current Bytebase drift detection. +- A server-side Plan/Issue/Rollout record is not the same as a local, portable, signed plan + artifact. +- Multi-database rollout is visibly staged and partially successful, never atomic. +- Automatic retry is safe only when the operation/task defines idempotency and outcome verification. +- NetScript should integrate with Bytebase as an optional delivery backend, not reproduce IAM, + approvals, scheduling, audit UI, notifications, database groups, or persistent metadata services. + +### ZenStack v3 + +Architecture and mechanics: + +- ZenStack v3 is no longer Prisma-backed at runtime; it uses a Kysely-based ORM while retaining a + Prisma-superset ZModel language and PrismaClient-compatible query style. Current v3 supports + PostgreSQL, MySQL, and SQLite. [v3 overview](https://zenstack.dev/docs), + [v2 migration](https://zenstack.dev/docs/migrate-v2) +- ZModel uses explicit `import` statements. Imported files are type-checked and merged into one + schema AST before downstream tools run. This is better than implicit directory merging, but still + one aggregate owner/history. [Multi-file schema](https://zenstack.dev/docs/modeling/multi-file) +- A `plugin` declaration names a built-in plugin, local module, or npm package. Plugins can + contribute ZModel attributes/functions, generation behavior, CLI behavior, and ORM runtime + interception. The entire plugin facility is marked preview and subject to breaking changes. + [Plugin model](https://zenstack.dev/docs/modeling/plugin) +- An npm plugin exports `plugin.zmodel`; the CLI loads ESM from a file, folder, or npm package. CLI + plugins receive the full resolved AST and arbitrary options. Runtime plugins intercept ORM/Kysely + query lifecycles. [Plugin development](https://zenstack.dev/docs/recipe/plugin-dev) +- Schema-level enablement and runtime enablement are distinct. For example, the policy plugin must + be declared in ZModel and installed on the ORM client. This creates a potential mismatch NetScript + should prevent through one resolved manifest. +- `zen migrate dev/deploy/status/resolve` exposes a single schema and migrations path. The current + CLI still creates temporary Prisma schemas and provides `resolve --applied` / `--rolled-back`; + `db push` accepts data-loss and force-reset flags. It is a wrapper around one migration history, + not contributor-owned histories. [CLI](https://zenstack.dev/docs/reference/cli) +- `@zenstackhq/zod` takes the generated/runtime ZenStack schema and builds typed Zod 4 schemas. + `makeModelSchema` supports `select`, `include`, `omit`, nested relation selection, and + create/update optionality. This is the strongest direct prior art for runtime derivation and + selection-shaped validation. [Zod factory](https://zenstack.dev/docs/utilities/zod) + +DX strengths: + +- One expressive schema drives runtime, generation, policies, and validators. +- Explicit imports and a typed AST are understandable. +- Selection-shaped runtime validation avoids one-validator-per-model boilerplate. +- Plugins can span schema, tooling, and runtime behavior. + +Failure modes and NetScript lessons: + +- Explicit imports do not establish independent ownership, migration heads, provenance, retention, + or removal semantics. +- Schema and runtime plugin installation can diverge. NetScript must resolve both from one + contribution record and reject half-installed plugins. +- Preview arbitrary-code plugins are not a stable public contract. NetScript’s contribution protocol + should be declarative; executable hooks belong behind phase-specific, capability-limited adapters. +- ZenStack’s validator is tied to Zod rather than Standard Schema, and documented coverage is + model/type/enum shape rather than full query/mutation argument semantics, provider codecs, storage + values, or wire representations. +- NetScript should copy runtime derivation and selection-aware factories, not a generated Zod-only + layer. + +## Revised focused capability matrix + +Legend: `Strong` = primary current capability; `Partial` = similar but materially different/manual; +`Hosted` = capability depends on a persistent control plane; `None` = absent. The NetScript row is +deliberately labeled as an unimplemented design target. + +| Product/pattern | Resolved desired manifest | Apply-bound plan | Durable run evidence / partial recovery | Contributor-owned schema + history | Runtime selection-aware validation | Lock / drift semantics | +| --------------------- | ---------------------------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------- | ----------------------------------------------------- | -------------------------------------------------------------- | +| Flyway | Partial: config + ordered migrations | None; dry-run is not a bound plan | Strong history/repair, but manual cleanup after non-transactional failure | None; locations merge into one history | None | Strong DB lock on JDBC; Native Connector gap; drift Enterprise | +| Liquibase | Partial: root changelog | Partial: `update-sql` preview only | Strong ledger/lock/rollback vocabulary | Partial module identity, shared ledger | None | Strong lock; explicit diff/snapshot, not state reconciliation | +| Terraform CLI | Strong config graph; mutable state is separate | Strong saved opaque plan | Strong mutable state and partial-apply recovery; no rollback | Partial modules/providers, not DB ownership spaces | None; provider schemas are unrelated | Backend-dependent locks; refresh/refresh-only drift | +| Pulumi OSS | Partial: graph emerges from program execution | Partial/experimental; incrementally enforced | Strong checkpoints and pending-operation recovery | Partial packages/components, not DB migration owners | None; package schema generates SDKs | DIY locks; explicit refresh | +| Pulumi Cloud | Same program graph | Partial/experimental | Hosted transactional checkpoints, history, policy | None for DB schema ownership | None | Hosted locking and scheduled drift | +| Atlas CLI/Pro | Strong schema graph | Partial/strong migration/declarative planning | Strong migration directory/ledger; local apply evidence | Partial composite sources; configuration order, not owned histories | None | Pre-apply drift is Pro; local apply semantics | +| Atlas Cloud | Strong registry source of truth | Strong promotion/registry workflow | Hosted deployment history and fleet status | Partial source composition | None | Hosted agents, scheduled drift, notifications | +| Bytebase current | Strong persistent server-side Plan | Strong Plan → Issue → Rollout, but not offline artifact | Strong stage/task history and partial fleet rollout | None | None | Persistent scheduler; current drift detection removed | +| ZenStack v3 | Strong single composed AST | None beyond wrapped migration workflow | Partial Prisma migration status/resolve | Partial schema/plugin contribution; one history | Strongest comparator, but Zod-specific and incomplete | No framework-level multi-target lock/drift layer | +| Prisma 8 RC substrate | Strong contract snapshot per target | Emerging control plan | Stronger graph/marker/ledger substrate | Strong spaces, but removal/retention conditional | No stable public Standard Schema layer | Adapter/provider dependent | +| Proposed NetScript | **Design target, not implemented** | **Design target, conditional on live-baseline binding** | **Design target; must prove unknown/partial/resume paths** | **Conditional on NetScript policy + upstream conformance** | **Design target; runtime/AOT equivalence unproven** | **Design target; local per-target only, no hosted monitor** | + +## Atlas and Terraform analogy corrections + +The RFC should state these explicitly: + +1. Atlas `composite_schema` is useful source composition, but its documented dependency mechanism is + load order. NetScript must require semantic dependency edges and reject cycles/overlaps rather + than inherit configuration order. + [Atlas project configuration](https://atlasgo.io/atlas-schema/projects) +2. Atlas Cloud’s registry, deployment audit, promotion, fleet status, continuous drift, agents, + notifications, and UI are online commercial services. They are not evidence that equivalent local + functionality is cheap. [Atlas Cloud](https://atlasgo.io/cloud/getting-started), + [Atlas Agent](https://atlasgo.io/cloud/agents), + [deployment reporting](https://atlasgo.io/cloud/deployment) +3. Terraform configuration, saved plan, mutable state, and backend are four distinct things. + NetScript must likewise keep source manifest, resolved snapshot, executable plan, database + ledger, and receipt distinct—but it should not create Terraform-style mutable framework state. +4. Terraform/Pulumi apply proves that plan approval does not imply atomic execution. + State/checkpoint updates preserve partial progress; rerun converges or continues. NetScript’s + database operations need per-operation idempotency and verification, not generic “convergence.” +5. Provider schema analogies stop at extension isolation and version pinning. Terraform/Pulumi + schemas describe provider configuration and resource CRUD, not application query/mutation/result + validation. +6. Terraform targeting is recovery machinery. It is positive evidence against treating `--db`, + `--space`, or `--operation` filters as routine unbound apply selectors. +7. Refresh/adoption changes the operator’s record of reality. NetScript verification must never + silently turn external drift into a new baseline; adoption requires an explicit ownership-policy + transition and reviewed plan. + +## Capabilities a local meta-framework should not rebuild + +Keep local: + +- pure manifest resolution and digesting; +- contributor dependency/overlap/provenance checks; +- plan generation and local policy evaluation; +- direct database-native lock acquisition; +- target/space migration invocation; +- per-run receipts, uncertain-outcome diagnostics, and resumable verification; +- optional adapters that export plans/results to external systems; +- runtime Standard Schema derivation from the pinned resolved contract. + +Leave to optional Atlas/Bytebase/Pulumi/HCP-style integrations: + +- remote state/checkpoint backends; +- organization workspaces and RBAC; +- human approval engines and issue tracking; +- schema registries and environment promotion; +- continuous drift agents/schedulers; +- fleet/tenant rollout schedulers and dashboards; +- permanent audit-log servers; +- notifications/webhooks; +- secret storage, KMS, and credential brokering; +- hosted policy distribution. + +## Plan-lock decisions affected + +1. **Artifact taxonomy:** lock separate definitions for source manifest, resolved snapshot, + executable plan, upstream ledger/marker, and immutable operation receipt. +2. **No mutable NetScript state:** the snapshot is generated data; receipts are evidence. Neither + becomes an authoritative shadow database. +3. **Executable plan contract:** bind manifest digest, target IDs, space versions, provider/package + lock, live baseline, operation digests, policy result, expiry, and environment. Store secret + references only. +4. **Speculative versus executable:** give offline/speculative plans a distinct type/status; only + live-baseline-bound plans can be applied. +5. **Apply revalidation:** reacquire the lock and recheck baseline, manifest, package set, target + identity, ownership policy, and expiry immediately before mutation. +6. **Lock protocol:** specify target/space scope, timeout, owner/nonce, stale-lock diagnostics, safe + force-unlock rules, and behavior when an adapter lacks locking. +7. **Receipt state machine:** include at least `planned`, `locked`, `started`, `applied`, + `verified`, `failed`, `partial_success`, `skipped(reason)`, `cleanup_required`, and + `outcome_unknown`. +8. **Checkpoint granularity:** persist a receipt checkpoint after every irreversible operation or + transaction group; never only at end-of-target. +9. **Recovery:** uncertain operations are inspected before retry; resume never blindly re-executes + non-idempotent DDL or data transforms. +10. **No cross-target atomicity:** lock wording now. Multi-target applies are staged collections of + independent target outcomes. +11. **Selective apply:** target/space filters require dependency closure, explicit omitted reasons, + plan binding, and whole-target verification afterward. They are not routine convenience + shortcuts. +12. **Ownership-aware drift:** distinguish migration-integrity drift, managed-object drift, adopted + baselines, allowed external drift, and ignored objects. Baseline adoption is a reviewed + mutation. +13. **Contribution identity:** use stable logical space and migration IDs independent of file paths, + package install paths, provider names, or include order. +14. **Plugin execution boundary:** pin version/checksum/provenance and declare which phases may + execute code. Composition should consume declarative records by default. +15. **Removal remains conditional:** NetScript can define diagnostics and retention policy now, but + must not score removal as implemented until upstream behavior and conformance prove it. +16. **Validation scope:** lock operation-aware inputs, selection-aware outputs, runtime versus wire + representations, codec contribution, stale-cache rejection, and fail-closed unsupported + constructs. +17. **Validation portability:** Standard Schema is public; Zod is one adapter. ZenStack’s runtime + schema factory is prior art for ergonomics, not for choosing Zod as the kernel. +18. **Hosted boundary:** explicitly defer RBAC, approval workflows, registry/promotion, continuous + monitoring, fleet scheduling, and permanent audit services. +19. **Matrix honesty:** replace the proposed “Strong” self-score with “design target / conditional / + unproven” until each conformance gate passes. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md new file mode 100644 index 0000000000..1c811fd685 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md @@ -0,0 +1,295 @@ +# NetScript Database Current-State Audit + +## Scope and baseline + +- Repository: `rickylabs/netscript` +- Baseline: `origin/main` at `cd720529333328bcba5e1a308ce7632f4350efdf` +- Audit date: 2026-08-13 +- Package dependency baseline: the root catalog declares Prisma caret ranges `^7.8.0` (the lock + resolves the installed versions); generated workspaces still encode `^7.4.2` specifiers. +- Sources: current source and docs, architecture-debt ledger, Git history, GitHub issue/PR evidence, + and focused `deno doc`/dependency-tool inspection. + +This document describes the system that exists. It does not carry forward the compatibility-first +solution from issue [#313](https://github.com/rickylabs/netscript/issues/313). + +## Executive finding + +NetScript does not currently have one database architecture. It has five partially-overlapping +systems whose identities and ownership rules do not line up: + +1. an appsettings/Aspire database-resource model; +2. a fixed CLI engine registry and operation runner; +3. a generated per-engine Prisma workspace and task graph; +4. a runtime adapter wrapper around user-constructed Prisma clients; and +5. an install-time plugin Prisma-fragment copier. + +The happy path works only after those systems agree on config keys, engine directory names, +environment variables, generated files, Prisma CLI behavior, adapter packages, and a live Aspire +resource graph. The framework makes that agreement a developer and CI responsibility, then adds +post-generation repair scripts where upstream output does not fit Deno/browser expectations. + +The redesign therefore cannot be a Prisma version substitution. The missing foundation is one +NetScript-owned, typed, inspectable database graph from which resource provisioning, schema +composition, client construction, generated imports, migrations, validation artifacts, plugin +contributions, diagnostics, and CI plans are derived. + +## Present topology + +```text +appsettings.json + NetScript.PrimaryDatabase + NetScript.Databases. + | + +--> Aspire helpers/resources and allocated connection values + | + +--> DbWorkspaceResolver + configKey -> fixed DbEngine -> database// + | + +--> per-engine deno.json tasks + +--> prisma.config.ts + +--> schema/**/*.prisma + +--> migrations/ + +--> scripts/* + +--> schema/.generated/* + | + +--> generated engine mod.ts + +--> deep user imports / @database/zod + +plugin package database/**/*.prisma + | + +--> package/source resolution + +--> install-time file copy + +--> regex declaration collision scan + +--> database//schema/plugins//*.prisma +``` + +There is no canonical graph or manifest joining these views. The effective configuration is spread +across `appsettings.json`, the root workspace list, a generated database `deno.json`, +`prisma.config.ts`, schema files, generated Aspire helpers, generated engine modules, environment +variables, plugin package metadata, and generated output. + +## Identity model and its limitations + +| Identity | Current representation | Consequence | +| ------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- | +| Logical target | `NetScript.Databases.` | Used for CLI selection and Aspire resource lookup. | +| Primary target | `NetScript.PrimaryDatabase` | Used by Aspire/service wiring, but ignored by `DbWorkspaceResolver.resolveTarget`. | +| Engine | Closed union: `postgres | mysql | +| Schema workspace | `database//` | Multiple same-engine targets share one schema, client, migrations, and tasks. | +| Physical database | `DatabaseName` plus Aspire resource | Coupled to config and provisioning mode. | +| Prisma datasource | One `datasource db` per generated workspace | Not a first-class NetScript object. | +| Generated client | Deep path under `schema/.generated/client.server.ts` | User code can import the wrong target or a stale artifact. | +| Plugin schema owner | Installed file path under `schema/plugins/` | Ownership is filesystem-derived, not a versioned contribution contract. | + +Two correctness gaps follow directly from this model: + +- `db add postgres --name analytics` creates another config target but still renders and resolves + `database/postgres/`. It cannot represent two PostgreSQL databases with independent schemas or + migration histories. The public second-database guide currently claims otherwise. +- With more than one enabled target, omitting `--db` does **not** resolve + `NetScript.PrimaryDatabase`; `resolveTarget` only defaults when exactly one target exists. This + conflicts with current documentation that says a bare command targets the primary database. + +## Public and generated runtime surfaces + +### `@netscript/database` + +The root package currently exposes: + +- tracing activation (`enableInstrumentation` / tracing subpath); +- generic adapter/status/connection/transaction types; +- the PostgreSQL adapter on the root and adapter barrel; +- MySQL and MSSQL adapters on explicit subpaths; +- JSON field extensions; +- a structurally-cast `withTransaction` helper; and +- connection-string parsers/builders. + +The central `DatabaseAdapter` port owns client lifecycle, health, status, and raw query +methods. Concrete adapters do not construct the client. The user must: + +1. create the NetScript wrapper; +2. ask it for a Prisma driver adapter; +3. construct the schema-generated `PrismaClient` with that driver; +4. pass the client back through `setClient`; and only then +5. call connect, health, status, or raw-query methods. + +This is circular assembly. The wrapper is neither a driver adapter nor an owning database factory, +and unsupported Prisma drivers bypass its lifecycle entirely. + +### Generated database package + +Each engine workspace generates another facade with its own singleton, connection resolution, driver +selection, health query, exported Prisma client symbols, and `DB` type. This duplicates the +published adapter layer rather than composing it. Applications and docs also import generated Prisma +clients by physical path. + +The generated package exposes `./zod` from generated output. Root workspace aliases and generated +contract templates depend on precise, hand-maintained generated symbol names. Issues +[#1254](https://github.com/rickylabs/netscript/issues/1254) and +[#1290](https://github.com/rickylabs/netscript/issues/1290) show that changing the barrel target +first hid models and then broke clean scaffolds at type-check and startup time. + +### Custom MySQL Prisma adapter + +`@netscript/prisma-adapter-mysql` implements Prisma's low-level `SqlDriverAdapter` contracts and +conversion/error/transaction behavior itself. It imports upstream unstable driver-adapter utility +types and `mysql2/promise`; comments still describe an earlier Deno MySQL implementation. This is a +large upstream-coupled maintenance surface, not merely a thin NetScript integration adapter. + +## CLI and lifecycle + +The CLI exposes fourteen verbs: add, list, remove, init, generate, migrate, seed, status, studio, +introspect, reset, deploy, validate, and resolve. + +The operation path is: + +1. parse `appsettings.json`; +2. map a closed engine enum to a fixed provider registry; +3. derive workdir as `database/`; +4. require the resident Aspire AppHost for every shared operation, including pure generation; +5. materialize an operation-request JSON file; +6. explicitly start `netscript-db-` inside the resident graph; +7. have that resource invoke a generated `deno task db::`; +8. poll Aspire until terminal, fetch logs, stop the resource, remove the request, and release a + filesystem lock. + +Important behavior: + +- `--db all` is sequential and fail-fast; there is no complete per-target result or resumable plan. +- Studio silently executes only the first resolved target. +- Pure `generate` is Aspire-coupled even though the generated workspace task can run without a + database. `DB-GENERATE-ASPIRE-COUPLING` remains open architecture debt. +- `db add` scaffolds and rewrites config/helpers, but intentionally does not migrate, generate, or + seed. Users must restart/reload orchestration and run the lifecycle steps themselves. +- The engine registry is a registry in implementation shape only. Its key type is closed, its + providers contain hard-coded template switches, and operation commands instantiate their own + default resolver/runner. Third-party database support cannot be contributed as a coherent public + capability. + +## Generation and repair pipeline + +A generated engine workspace contains at least: + +- `deno.json` with more than twenty database tasks and duplicated Prisma version specifiers; +- `prisma.config.ts` with connection-string normalization; +- a generated engine `mod.ts` with driver/client/tracing/lifecycle code; +- `schema/schema.prisma`; +- a seeded placeholder generated client; +- migrations and seed directories; +- Zod generator config in two locations; and +- clear-placeholder, migrate, generate-Zod, fix-Zod, and patch-client scripts. + +The nominal `db:generate` pipeline performs: + +1. placeholder removal; +2. Prisma client generation; +3. a second Prisma generation through the Zod wrapper; +4. generated Zod import rewriting; +5. circular-reference rewriting; +6. getter-pattern rewriting; +7. decimal compatibility rewriting; +8. a generated CRUD alias barrel; +9. Prisma client renaming/facade patching; and +10. another outer fix-Zod pass. + +The result is non-atomic generated source that NetScript mutates based on upstream textual output. +Users can edit the schema without running the pipeline and continue compiling against stale types. +Multi-database projects multiply this state and expose physical generated paths to consumers. + +## Plugin contribution model + +Plugins declare schema by shipping plain `database/**/*.prisma` files. During installation the CLI: + +- discovers or downloads package fragments; +- chooses one database target (explicit, primary-ish, or first available); +- copies each fragment into the consumer's active schema tree; +- scans top-level `model`, `enum`, `type`, and `view` blocks using a custom regex/balanced-brace + parser; +- removes byte-normalized identical declarations; and +- rejects same-name declarations with different normalized bodies. + +What this model does not express: + +- contribution contract or schema version; +- supported providers/capabilities; +- target selection policy beyond install-time flags; +- dependency ordering or contribution dependencies; +- declaration ownership and allowed augmentation; +- migration ownership, rollout, rollback, or data transforms; +- generated validator/client requirements; +- uninstall data policy; +- compatibility with an existing database version; +- deterministic graph digest/provenance; or +- a programmatic contributor test kit. + +The filesystem assumption already caused dependency-mode installs to report success while omitting +all plugin tables ([#1014](https://github.com/rickylabs/netscript/issues/1014)). Model-name clashes +then broke authentication installs and required namespacing plus a custom collision guard +([PR #1059](https://github.com/rickylabs/netscript/pull/1059)). The removal path deletes the copied +schema directory; it does not plan or execute a safe database migration. + +## Recurrent failure classes + +Path-scoped Git history since 2026-06-01 contains 30 `fix*` commits touching the database package, +custom adapter, CLI database kernel/templates, schema writer, or database E2E gate (release commits +excluded from that count). The audited implementation/test/template surface is about 9,175 lines. +The number is descriptive, not a quality metric; the failure history is the stronger evidence. + +| Failure class | Evidence | Architectural lesson | +| ----------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | +| Prisma schema-engine crash/hang on Windows | [PR #98](https://github.com/rickylabs/netscript/pull/98), [PR #145](https://github.com/rickylabs/netscript/pull/145), retry/timeout code in `migrate.ts` | NetScript CI owns upstream subprocess lifecycle and flake classification. | +| SQLite facade compiled only against placeholder, failed after real generation | [#173](https://github.com/rickylabs/netscript/issues/173) | Stubs and generated-client contracts can diverge; every capability axis needs generated-project proof. | +| Plugin schema silently absent in dependency installs | [#1014](https://github.com/rickylabs/netscript/issues/1014) | Source-layout discovery is not a contribution contract. | +| Plugin/base model collision | [PR #1059](https://github.com/rickylabs/netscript/pull/1059) | Global Prisma declaration namespace needs explicit ownership and conflict semantics. | +| Read-only DB command killed resident AppHost | #1011 / [PR #1088](https://github.com/rickylabs/netscript/pull/1088) | Database operations lacked a stable lifecycle owner. | +| Ephemeral AppHost leaked and masked the real host | [#1196](https://github.com/rickylabs/netscript/issues/1196), [PR #1301](https://github.com/rickylabs/netscript/pull/1301) | Fixing lifecycle symptoms without one operation model moved the failure. | +| Second AppHost mounted live PGDATA and corrupted it | [#1310](https://github.com/rickylabs/netscript/issues/1310), [PR #1311](https://github.com/rickylabs/netscript/pull/1311) | Resource reconstruction is unsafe; operations must bind an authoritative graph. | +| Stale allocated Postgres endpoint | [#1202](https://github.com/rickylabs/netscript/issues/1202), [PR #1393](https://github.com/rickylabs/netscript/pull/1393) | Runtime connection provenance must be inspectable and validated against the live allocation. | +| Headless migrate returned success without an artifact | [#1327](https://github.com/rickylabs/netscript/issues/1327), [PR #1393](https://github.com/rickylabs/netscript/pull/1393) | Exit code is insufficient; operations need typed plans and artifact/state postconditions. | +| Multi-model Zod alias hid symbols, then its repair broke startup | [#1254](https://github.com/rickylabs/netscript/issues/1254), [#1290](https://github.com/rickylabs/netscript/issues/1290) | Generated symbol paths cannot be the framework contract. | +| Split Zod module instances broke schema interoperability | [#1295](https://github.com/rickylabs/netscript/issues/1295) | Validation must use a standards-facing contract and controlled dependency boundary. | + +The most severe lifecycle bug cost a measured pilot hours, two database resets, and a privileged +host scrub. The final artifact-proof repair in PR #1393 took six serialized `scaffold.runtime` +attempts as successive test-harness assumptions surfaced. This is exactly the CI instability the new +design must structurally retire. + +## Architecture-debt alignment + +- `packages/database — AP-17` remains open. Source has already renamed `interfaces/` to `ports/`, so + that part of the debt entry is stale; the unresolved composition-root finding remains current. +- `DB-GENERATE-ASPIRE-COUPLING` remains open and documents the pure-codegen/Aspire mismatch. +- Current doctrine classifies `packages/database` as an A2 integration package needing refactor and + `packages/prisma-adapter-mysql` as an A2 integration package. The new owner directive supersedes + the old recommendation to preserve the existing database port unchanged. +- Auth roadmap item R1 independently requires deterministic plugin-aware schema and migration + generation; this RFC must make that an ordinary contribution, not an auth-specific escape hatch. + +## What is worth preserving as evidence, not API compatibility + +- Explicit subpaths keep heavy engine dependencies out of unrelated consumers. +- Artifact-first migration verification is correct and should become a general operation contract. +- Resident-resource binding fixed the unsafe duplicate-AppHost model. +- Deterministic provider registries and generated composition roots match doctrine in principle. +- Plugin schema conflicts now fail rather than silently overwrite. +- Engine-specific behavior is real and must remain capability-visible; a lowest-common-denominator + database API would be a regression. + +These are invariants to re-express in the new architecture. They do not justify retaining current +package names, ports, generated paths, task names, or runtime shims. + +## Clean-break implications + +The RFC design must make the following impossible or mechanically detectable: + +1. editing a database definition without refreshing the effective client/validator/schema graph; +2. constructing a driver, client, and lifecycle wrapper in the wrong order; +3. importing a client by its generated filesystem path; +4. running an operation against an implicit or ambiguous target; +5. reporting success without proving planned artifacts and database state; +6. copying an unversioned plugin fragment without capability/conflict/migration analysis; +7. representing two logical databases as one accidental engine directory; +8. adding an engine by editing switches across CLI, templates, Aspire, packages, docs, and CI; +9. requiring Aspire/Docker for pure compilation; and +10. patching upstream generated text as an undocumented permanent compatibility layer. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md new file mode 100644 index 0000000000..a437689cf3 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/planned-jsr-audit.md @@ -0,0 +1,79 @@ +# Prospective JSR Audit — Planned Database Surface + +> Scope: Plan-Gate audit of the proposed packages, not an audit of implemented packages.\ +> Verdict: **PASS-AS-PLANNED**; **NOT ACTUAL PUBLISH READINESS**. + +The planned database graph satisfies the JSR rubric if the implementation preserves the boundaries +below. The six new packages do not exist, so running `deno publish --dry-run`, `deno doc --lint`, or +a packed/remote install against them is currently **N/A**, not a pass. Actual readiness begins only +when each package has a real manifest, export graph, source surface, and publish file list. + +## Planned surface + +| Unit | Status / archetype | Intended exports and boundary | JSR obligations and principal risk | +| ------------------------------------- | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database-contract` | Public, A1 | Root for small identities/invariants; split focused subpaths only if the root approaches 20 symbols. | Zero provider dependencies; explicit annotations; no Prisma types. | +| `@netscript/database` | Public, A4 | Root `defineDatabase` authoring surface; focused definition/compiler subpaths only when responsibilities require them. | Frozen plain definitions and explicit public return types. Native Prisma contracts are accepted without being re-exported. | +| `@netscript/database-runtime` | Public, A3 | Root lifecycle factory and small session handles; validation or connection-source subpaths only if independently consumable. | Public generics remain narrow. Concrete inferred query/session bindings are generated **app-locally**, never exported here. | +| `@netscript/database-control` | Public, A2 | Root programmatic operations; focused catalog/testing subpaths if needed. | Plain plans, receipts, diagnostics, and ports; no provider control types or terminal-text contract. | +| `@netscript/database-prisma-postgres` | Public only after certification, A2 | Experimental provider root, with narrowly justified authoring/runtime/control subpaths. | Sole framework Prisma import boundary. It must not re-export Prisma, expose private/deep-import types, or make moving upstream types part of NetScript semver. | +| `@netscript/database-testkit` | Public tooling, A6 | Root library plus binary only if provider certification genuinely needs one. | Never a runtime dependency; machine receipts and fixtures excluded or deliberately published. Reconsider the package split before W1 if no binary exists. | +| `@netscript/plugin` | Existing public A4, changed | Add one documented database-space/contribution subpath; remove legacy copied-schema abstractions in the clean break. | Plain descriptor types only; no runtime/control/provider dependency. Breaking surface accounting required. | +| first-party `plugins/*` | Existing public A5, changed | Thin root plus established service/contract/scaffold surfaces; publish descriptors and generated contract/lineage assets. | Provider-native authoring stays in controlled build input. Deployment must work from pinned plain artifacts without importing plugin code. | +| `@netscript/aspire` | Existing public A2, changed | Add a narrow connection-source/provisioning adapter on an existing relevant subpath. | Deno/Aspire edge only; must not become required by pure database packages. | +| `@netscript/cli` | Existing public A6, changed | Existing binary/root project the operation catalog; no new database logic export. | Generated help/agent assets require freshness checks and production remote-graph E2E. | + +Each unit has exactly one archetype. The testkit exception is explicitly conditional before public +release, so the one-package/one-archetype law is satisfied as planned. + +## Non-negotiable publish rules + +- Every package gets one `deno.json` with scoped name, synchronized version, license, a concise + description/tagline under 250 bytes, explicit exports, and an `include` whitelist plus test and + fixture exclusions. Every entrypoint has `@module` documentation, a runnable example, and full + symbol JSDoc; stable surfaces target a 100% JSR documentation score. +- Root and subpath surfaces remain skimmable. Cross-package imports use declared `jsr:`/`npm:`/ + `node:` specifiers under repository dependency policy. Imports within the same package are + relative, preventing JSR self-referential-subpath resolution against an older published version. +- All published code is ESM and Deno-compatible. Node/Bun/browser compatibility is claimed only + after its matrix passes; default JSR settings may claim Deno alone. No CommonJS, HTTP imports, + top-level filesystem assumptions, or unconditional `fromFileUrl(import.meta.url)` are allowed. +- No database package receives the doctrine's oRPC-only slow-type carve-out. Public declarations + must satisfy root `isolatedDeclarations`; `--allow-slow-types` is a failure. Application-specific + `typeof contract`, Prisma query types, and inferred `TargetBinding` values terminate in generated + application files. Direct application authoring may import Prisma's public builder; NetScript + packages neither vendor nor re-export it. +- Publishable generated assets are checked-in TypeScript constants with deterministic + regeneration-plus-diff gates. Runtime file reads and text/JSON import attributes are forbidden + until an authenticated registry canary proves the known JSR limitation resolved. Contract JSON, + declarations, lineage, and provenance are explicit whitelisted artifacts, content-addressed and + atomically generated—not patched source. + +## Implementation and release gates + +W1–W6 must add each new unit to the publish denominator and require, per unit: scoped +check/lint/fmt, `deno doc --lint` with zero diagnostics across every export, +`deno publish --dry-run` without slow types, inspected publish file list, README/tagline checks, +`quality:scan`, `arch:check`, generated asset freshness, public import tests, and a clean packed +consumer install. W3 additionally requires an exact Prisma import allowlist, one resolved component +set, Deno import purity, and real PostgreSQL conformance before the provider package is advertised. + +W7–W9 apply the same gates to the changed plugin/CLI/Aspire surfaces, plus breaking-surface diff, +plugin thinness/seam checks, package-free artifact consumption, and executed generated examples. W10 +requires release preflight, authenticated canary publish with GitHub OIDC/SLSA provenance, registry +settings reconciliation, and the production `e2e-cli-prod` path against exact published JSR +versions. A local dry-run or packed install cannot substitute for this remote-graph verdict. + +## Blocking findings / kill criteria + +Plan Gate remains satisfied only while implementation proves all of the following. Kill or split a +surface if Prisma types leak into a public declaration, app inference requires a published slow +type, any unit needs `--allow-slow-types`, the provider requires private/deep imports or upstream +re-exports, internal bare self-imports appear, generated assets need runtime filesystem access, a +package combines two archetypes, or a clean remote consumer resolves duplicate/off-allowlist Prisma +components. Do not publish the Prisma adapter if its dry-run, docs, Deno graph, packed consumer, +provenance, canary, or production E2E gate is red. + +**Final audit verdict:** the proposed boundaries provide enough explicit mitigation for a +**PASS-AS-PLANNED** at PLAN-EVAL. They provide no evidence of actual publish readiness until the +implementation-time and release-time commands above produce green receipts. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md new file mode 100644 index 0000000000..48a306a43c --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md @@ -0,0 +1,704 @@ +# Prisma 8 / Prisma Next Deep Dive + +## Research pin and confidence model + +This audit deliberately separates three upstream states that must not be conflated: + +| State | Pin | Why it matters | +| ----------------- | ---------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- | +| Announced release | [`v8.0.0-rc.1`](https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1), published 2026-08-07 | The version named by the NetScript RFC request. | +| RC source | [`a76a6c5`](https://github.com/prisma/prisma/tree/a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5) | Reproducible basis for package, runtime, migration, skill, and scorecard claims. | +| Upstream main | [`71e2e0d`](https://github.com/prisma/prisma/tree/71e2e0d9ee1f306b5a11435cd1973023cb33866a), observed 2026-08-13 | Six days of post-RC changes that reveal which integration seams are still moving. | + +Prisma calls this release Early Access and explicitly does not recommend it for production +workloads. The RC source requires Node.js 24+, declares TypeScript 5.9 as an optional package peer +floor, and describes PostgreSQL as the sole database intended for 8.0 GA. MongoDB remains Early +Access, SQLite is a proof of concept, MySQL follows later, and SQL Server is not present in the +Prisma 8 target set. + +The analysis below uses this confidence vocabulary: + +- **implemented**: an observable public or source-level implementation exists; +- **proven**: Prisma's RC scorecard cites a real-database integration test; +- **untested**: reachable through a public surface but not proven by the scorecard's + integration-test standard; +- **absent**: the RC scorecard explicitly says the capability is not in 8.0; +- **moving**: the relevant surface changed on `main` after the RC tag; +- **NetScript gate**: NetScript must prove the behavior independently before adopting it. + +## Executive conclusion + +Prisma 8 is not Prisma 7 with a new client generator. It is a TypeScript database framework built +around a canonical data contract, composable family/target/adapter/driver/extension descriptors, +structured query and migration plans, and separate control and execution planes. The generated +executable `PrismaClient` disappears. The durable emitted artifacts are a canonical `contract.json` +and a type declaration; a small runtime facade consumes the contract. + +That direction directly attacks several NetScript pain points: + +- generated executable client source can disappear; +- source-rewriting and Zod repair passes can disappear; +- schema ownership can be modeled rather than inferred from copied files; +- migrations can be planned and verified through a programmatic API; +- structured results and errors can replace log scraping; and +- database families, targets, adapters, drivers, and extensions are distinct axes. + +It is not yet a safe foundation to expose directly. The RC's public package surface is extremely +wide, its CLI/config distribution changed materially within six days, important runtime and +migration cells remain unproven, the project skill contains stale internal imports and behavioral +contradictions, and the only 8.0 GA target is PostgreSQL. NetScript should therefore adopt the +contract/control/runtime architecture, wrap a deliberately narrow upstream seam, and make release +adoption conditional on a NetScript-owned conformance suite. + +## The architecture that actually replaces Prisma 7 + +The source is arranged as layers rather than as one client package: + +```text +authoring source (.prisma or TypeScript DSL) + | + v +family + target + extension lowering + | + v +canonical contract.json + contract.d.ts + domain plane storage plane hashes/profile + | + +---------+---------+ + | | + v v + control plane execution plane + plan / diff / emit SQL DSL / ORM / raw + migrate / verify middleware / codecs + introspect / sign driver / transaction +``` + +The important decomposition is: + +| Axis | Meaning | NetScript consequence | +| -------------- | --------------------------------------------------------------- | ----------------------------------------------------------- | +| Family | Shared semantics, such as SQL versus Mongo | Do not use “engine” as the only discriminator. | +| Target | Concrete database behavior, such as PostgreSQL | Provider capabilities belong to a target descriptor. | +| Adapter | Lowers framework operations into target operations | NetScript must not reimplement this SPI unless certified. | +| Driver | Owns wire connectivity and lifecycle | Driver choice is distinct from database target. | +| Extension | Adds authoring, contract, control, execution, codecs, or schema | Contributions need declared capabilities and compatibility. | +| Contract space | One contributor's owned contract and migration history | Plugin schema ownership becomes first-class. | + +The framework core composes descriptors into control and execution stacks. Component descriptors +carry family and target identity, and their instances contribute capabilities. The source checks +several duplicate-ownership conditions, such as conflicting codec or authoring constructs, while +capability-value merging itself is last-writer-wins. NetScript must therefore validate contribution +identity and collisions before handing a resolved stack to Prisma; upstream merge order alone is not +a sufficient plugin policy. + +### Public packages and coupling risk + +The RC publishes facade, framework, family, target, toolchain, and extension packages under +`@prisma/orm-*`. `@prisma/orm-postgres` is described as the one package an application installs, but +its export map contains 138 top-level subpath keys spanning adapters, control internals, contract +internals, migration tooling, query ASTs, runtime, target planning, and utilities. It also depends +on `pg`. + +This is useful for extension authors and dangerous for a meta-framework: + +- a direct NetScript re-export would turn upstream RC internals into NetScript public API; +- deep imports would make upstream refactors consumer-breaking; +- a duplicate component/engine package can become a runtime correctness problem; +- Node-oriented driver dependencies can silently leak into Deno/browser graphs. + +The integration boundary should therefore be one private NetScript package with an allowlist of +upstream imports and a dependency check that fails on every newly introduced deep import. + +## Contract-first emission + +### What is emitted + +Prisma 8 compiles PSL or a TypeScript builder into: + +- canonical `contract.json`, used by tooling and runtime; +- `contract.d.ts`, carrying the type-level contract; and +- a very small application facade that imports the two artifacts. + +This is the inverse of the Prisma 7 model: executable client implementation is not the generated +artifact. The runtime is a versioned package and the contract is data. The architecture explicitly +calls this “types-only emission.” + +Consequences for NetScript: + +1. Generated output can be content-addressed and atomically replaced. +2. A clean build can compare a graph digest rather than patch generated TypeScript. +3. Multiple targets can emit independently when their output directories are distinct. +4. Framework validation, docs, agent context, and CI can consume the same canonical graph. +5. Runtime upgrades do not require regenerating an executable client unless the contract format + itself changes. + +### Contract planes and hashes + +The unified contract separates domain structure from physical storage structure. Storage is +namespace-aware and uses an open entry-kind dictionary, allowing a target or pack to add target-only +entities. Prisma computes distinct identities for storage, execution, and profile concerns. +Migration identity is storage-based; runtime plans carry the storage hash and, when present, profile +hash. + +This separation is valuable, but NetScript must not make raw upstream hash fields its own long-lived +public identifiers. The RC upgrade recipes show contract canonicalization and hash representation +changing across pre-release versions. NetScript should record: + +- its own database-graph digest; +- the exact upstream package set and contract format version; +- each target's upstream storage/profile hashes; and +- the resolved contributor provenance. + +That lets NetScript explain drift without treating one upstream digest as the identity of the whole +application database graph. + +### Authoring modes + +Prisma supports PSL and a TypeScript contract builder. Both lower to the same contract model. The +TypeScript route provides immediate `typeof contract` inference; PSL relies on emitted declaration +artifacts and has a language server. + +NetScript should not invent a third database model DSL. It should provide a composition DSL for +targets, spaces, policies, routing, capabilities, and lifecycle while allowing the application +contract source to remain Prisma PSL or TypeScript. A NetScript plugin contribution should point at +or construct a contract space; it should not concatenate Prisma syntax. + +## Runtime surface + +The PostgreSQL facade consumes `contractJson` and returns a contract-typed runtime with: + +- `sql`: structured SQL builder; +- `orm`: model-oriented collection API; +- `raw`: escape hatch; +- `enums` and `nativeEnums`; +- `context` and `stack`; +- `connect` / `close`; +- `runtime` for lower-level access; +- `transaction`; and +- `prepare`. + +The serverless facade is intentionally asymmetric. It creates an async-disposable runtime per +request and omits closure-cached `orm`, `runtime()`, and `transaction()` surfaces that would be +unsafe in that lifecycle. This is a strong precedent for NetScript: runtime capability types should +reflect deployment mode rather than promising one universal client. + +### What NetScript should expose + +Application features should not receive the Prisma facade globally. They should receive +consumer-owned ports or an explicitly typed target reference: + +```ts +export interface AccountStore { + findByEmail(email: string): Promise; + save(account: Account): Promise; +} + +export const accountsDatabase = dbRef<'primary', AppDatabaseContract>(); +``` + +The application composition root can bind that reference to the Prisma 8 runtime. A feature that +truly needs the query surface may depend on a NetScript-owned `DatabaseSession` view; +most domain code should depend on a narrower feature port. This preserves query power without making +Prisma a framework-wide service locator. + +### Lifecycle implications + +Prisma separates long-lived, static, and serverless runtime shapes. NetScript must own: + +- target resolution; +- connection-source resolution; +- one lifecycle owner per runtime instance; +- request versus process scope; +- graceful close ordering; +- health/readiness semantics; +- transaction/session scoping; and +- observability middleware. + +It must not restore the current circular sequence in which a wrapper creates a driver, the user +creates a client, and the client is set back onto the wrapper. + +## Programmatic control plane + +The RC publishes `createControlClient` from `@prisma/orm-toolchain/cli/control-api`. It accepts +family, target, adapter, optional driver, extensions, and an optional connection. It can initialize +without a live driver for offline work and exposes domain operations for: + +- contract verification and emission; +- schema verification; +- database signing; +- `dbInit` and `dbUpdate` in plan/apply modes; +- migration planning/application; +- introspection; and +- lifecycle connect/close. + +Progress is modeled as nested start/end spans. Operations return structured results and dotted-code +errors instead of requiring terminal log parsing. The control client intentionally uses `any` at +descriptor variance boundaries; NetScript should type the resolved descriptors before that boundary +and contain the cast inside its integration package. + +Current `main` strengthens this seam: migration and database commands were routed through the +control API; output channels and typed next actions became explicit; a ControlClient test double was +added; and command-independent operations were exported. This makes the programmatic seam the +correct integration direction, while simultaneously proving that exact package paths and option +shapes are still moving. + +### Operation classification + +NetScript should classify operations before invoking Prisma: + +| Class | Examples | Required context | +| --------------- | -------------------------------------------------------------------------- | ------------------------------------------------- | +| Pure/offline | compose graph, validate ownership, emit, format, migration integrity check | Source tree only; never Aspire. | +| Live/direct | inspect, plan against live state, verify, status | Target connection; no resident app required. | +| Mutating/direct | initialize, apply migrations, sign, seed | Target connection, lock, consent policy, receipt. | +| Resident-only | operations whose connection exists only inside AppHost resource binding | Aspire session, explicitly selected. | + +The current NetScript rule that routes even generation through a resident AppHost must not survive. + +## Migration system + +### Graph, refs, marker, and ledger + +Prisma 8 models migrations as graph edges between storage hashes rather than only timestamped steps. +Named refs identify graph nodes. Contract snapshots are content-addressed. Each contract space has +its own marker state, and the migration ledger records applied edges. PostgreSQL and SQLite source +and tests implement the ledger; Mongo participates with target-specific atomicity semantics. + +For transactional SQL, the edge execution and ledger update are transactionally coupled. Mongo DDL +cannot rely on a multi-document transaction, so it verifies the destination before advancing the +marker and diagnoses partial state. + +This is a stronger model than NetScript's current “call the generated task and inspect logs,” but it +is not a distributed transaction system. Applying two different database targets can never be +globally atomic. NetScript needs a run receipt with per-target phases, idempotent resume, and +explicit partial-success reporting. + +### Plans and destructive consent + +`dbInit` and `dbUpdate` separate plan from apply. Destructive operations require explicit consent, +and structured errors can carry the destructive operation list. Current `main` further distinguishes +findings from execution errors and assigns different exit behavior. + +NetScript should add policy above consent: + +- an interactive “yes” is never enough in CI; +- production plans need a signed graph digest and environment binding; +- provider capability and transaction behavior must be visible; +- destructive operations need a deterministic policy decision; +- data-loss warnings require data-aware preflight where feasible; and +- apply must reject a plan if the graph, live baseline, package set, or target changed. + +### Data migrations + +Prisma models data transforms as invariant-guarded transitions. A transform declares a precondition +query that detects remaining work and a mutation plan; the runner verifies the invariant afterward. +The destination identity includes the required invariants. This is a sound foundation for resumable, +auditable data movement. + +The authoring experience is not finished. Planner output can leave placeholders in generated +`migration.ts` files that a developer must fill. The upstream multi-extension example still imports +contract/head/migration artifacts manually and uses several `as unknown` casts. NetScript should +preserve the invariant model but generate descriptor wiring, references, and contributor packaging +from its graph. + +### Important absent or weak migration capabilities + +The RC scorecard marks or reveals gaps that matter to NetScript: + +- no mature reset/resolve/diff/execute/squash workflow comparable with Prisma 7; +- no general shadow-database workflow; +- no complete advisory-lock story across targets; +- no row-count-aware data-loss analysis; +- no comprehensive diagnosis for unexecutable changes or unique constraints over dirty data; +- views absent from the 8.0 feature surface; +- raw migration operation coverage unproven; +- PostgreSQL and SQLite `dataTransform` integration coverage unproven; +- many individual destructive PostgreSQL operations unproven; and +- extension removal is unsupported. + +NetScript must not paper over these with shell scripts. Every required operation needs either an +upstream-proven capability, a NetScript implementation behind a target adapter, or an explicit +unsupported diagnostic. + +## Contract spaces: the key plugin concept + +[ADR 212](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md) +defines each contributor as a disjoint tuple: + +```text +(contract.json, migration graph, head ref) +``` + +The application owns one space. Each schema-contributing extension owns another. The consumer repo +contains a pinned mirror of extension artifacts, so production apply/verify does not need to import +`node_modules`. The database marker stores one row per space. The verifier aggregates spaces in +memory and rejects overlapping storage ownership. + +This solves the central semantic failure in NetScript's copied-fragment model: schema contribution +is a versioned owner with history, not a file copied into someone else's schema. + +### What contract spaces do and do not solve + +They provide: + +- one owner per storage object; +- independent migration histories; +- pinned consumer-side artifacts; +- per-space plan/run/verify; +- cross-space foreign-key declarations; +- extension-controlled schema versus app-controlled schema; and +- a basis for dependency ordering and removal diagnostics. + +They do not provide: + +- one merged on-disk contract; +- cross-database atomicity; +- transparent cross-database relations; +- runtime traversal across spaces as a complete ORM feature; +- extension removal/data-retention policy; +- automatic author descriptor packaging; +- a NetScript target-selection policy; or +- stable compatibility across arbitrary extension/core versions. + +The RC ADR text also contains stale layout and command statements relative to later source. Source +implements topological extension dependency ordering even where older ADR prose says dependency +ordering is deferred. NetScript's design must pin behavior to tests and package versions, not copy +upstream prose as an executable contract. + +### External ownership and drift + +Issue [#29896](https://github.com/prisma/prisma/issues/29896) shows a hosted Supabase database +failing `db verify` because a pinned extension contract and externally evolving tables diverged. The +workaround was effectively marker-only. This is not an edge case for NetScript plugins; it is the +normal shape of managed services. + +NetScript contributions therefore need an ownership policy: + +- `managed`: NetScript may plan and apply the object; +- `adopted`: NetScript verifies selected properties and can establish a baseline; +- `external`: another system owns lifecycle; NetScript records capabilities and allowed drift; +- `ignored`: deliberately excluded with an auditable reason. + +That policy belongs on each contract space or owned object set and must influence diff, plan, +verification, removal, and agent instructions. + +## Multiple schemas, databases, and engines + +Prisma's contract is namespace-aware, and the PostgreSQL runtime proves multi-namespace access. +Cross-space foreign keys can target another contributor's table in the same physical database. + +A Prisma config/control stack still describes one target and connection. Multiple independent +databases require a framework-level graph above Prisma. NetScript must model at least: + +```text +database graph + target id + family + provider target + driver/runtime mode + connection/provisioning source + namespaces + contract spaces + migration root + dependencies + operational policy +``` + +Target identity must be a stable user-defined key, not the engine name. `primary` and `analytics` +must be distinct even when both are PostgreSQL. Their output, migration history, runtime binding, +health, and operation receipts must never collide. + +The graph must be open to multiple adapters, but capability-driven rather than lowest-common- +denominator. PostgreSQL can expose RLS/native enums/vector operations; SQLite or a future SQL Server +adapter can expose different capabilities. Code requiring a capability should fail at composition or +type-check time, not at a late database call. + +## Validation and generated types + +The pinned RC source supports a qualified runtime-interpreter design. The emitted contract contains +a bounded runtime value algebra: scalar codec references, value objects, unions, nullability, +`many`, `dict`, and value-set references +(`packages/1-framework/0-foundation/contract/src/domain-types.ts:5-39`). SQL storage adds native +type, codec parameters/references, defaults, nullability, and value sets +(`packages/2-sql/1-core/contract/src/ir/storage-column.ts:15-25`), while model relations and +cross-space coordinates remain explicit (`domain-types.ts:41-75` and +`packages/1-framework/0-foundation/contract/src/cross-reference.ts:5-14`). NetScript can interpret +that bounded algebra directly into `StandardSchemaV1` values without generating validator source. +This is feasibility against `v8.0.0-rc.1`, not evidence of a stable upstream validation API. + +Standard Schema is the right NetScript public boundary, but Prisma's existing Standard Schema slot +does not validate model values. `CodecDescriptor.paramsSchema` validates JSON-sourced codec +_parameters_ and exposes TypeScript renderers +(`packages/1-framework/1-core/framework-components/src/shared/codec-descriptor.ts:27-54`). Codec +instances instead define three conversion representations—application runtime, database-driver wire, +and contract/database JSON +(`packages/1-framework/1-core/framework-components/src/shared/codec.ts:16-30,44-51`)—without a value +predicate. NetScript should therefore expose `representation: 'runtime' | 'json'`, reserve driver +wire for adapter internals, and require every built-in or custom codec contributor to provide an +explicit value schema for each supported representation. A codec with conversion functions but no +matching value schema is unsupported; conversion success must not be treated as validation. + +The interpreter must remain narrower than Prisma's generated type universe. SQL plans retain the +operation AST, parameters, projection aliases, expressions, and optional codec references +(`packages/2-sql/4-lanes/relational-core/src/plan.ts:19-22` and +`src/ast/types.ts:1480-1505,1510-1538,1892-1910,1984-2002`), but codec metadata is explicitly absent +for computed, subquery, and raw projections (`ast/types.ts:1484-1488`). Mongo plans retain the +command and an optional nested result shape +(`packages/2-mongo-family/4-query/query-ast/src/query-plan.ts:15-20` and +`src/result-shape.ts:1-13`), yet that shape permits `unknown`. Generated SQL field, operation, +codec, and aggregate type maps are phantom/type-only +(`packages/2-sql/1-core/contract/src/types.ts:90-139,207-215`) and are emitted into `contract.d.ts` +(`packages/1-framework/3-tooling/emitter/src/generate-contract-dts.ts:179-221`), not retained as +runtime validation metadata. Direct model fields and fully known selections can be validated; +filters, nested writes, polymorphic narrowing, computed/aggregate/include/raw results, and any +unknown shape require an explicit operation/result contributor or must fail closed. + +Contract spaces also remain separate identities. The aggregate exposes app and extension contracts +per space rather than merging them +(`packages/1-framework/3-tooling/migration/src/aggregate/types.ts:32-79,81-123`), and cross-space +domain checks are deferred to aggregate deployment +(`packages/1-framework/0-foundation/contract/src/validate-domain.ts:140-147`). Validator lookup and +cache identity must include `spaceId`, resolve references through an integrity-checked aggregate, +and never flatten equal namespace/model names from different spaces. + +No existing section hash is a complete validator cache key. RC hashing separately covers storage, +execution, and capability profile +(`packages/1-framework/0-foundation/contract/src/hashing.ts:74-106`), while domain, roots, and +extensions can change independently. NetScript should digest the canonical full-contract +representation (`contract/src/canonicalization.ts:250-277`) together with schema version, space, +target/family, operation or selection, representation, interpreter ABI, and codec/pack contributor +identities; include execution identity when defaults matter. Unsupported metadata must raise a +deterministic schema-construction error, never silently become `unknown` or pass-through. + +Ahead-of-time output remains an optional startup/performance optimization only if conformance tests +prove it is semantically identical to the runtime interpreter for success values, issue paths, +representation handling, unsupported-case failures, and cache invalidation. It must not become a +second hand-maintained model universe or require textual repair. + +Post-RC evidence is narrower and must not be read back into the RC: object `71e2e0d` adds +`packages/2-sql/2-authoring/contract-ts/src/data-contract-json-schema.ts:10-15,31-38,68-110`, which +labels generated contract JSON Schema lossy/advisory, keeps ArkType authoritative, and accepts +unknown pack maps generically because a static editor schema cannot know contributed kinds. That +improves validation of `contract.json`; it does not add model-data schemas, codec value predicates, +or universal result-shape metadata. + +## Runtime/platform support and Deno + +The RC documentation lists Node 24 as primary and Bun 1.2 / Deno 2.0 as best-effort. The PostgreSQL +facade depends on `pg`; serverless documentation requires Node compatibility in Cloudflare and +records a real Hyperdrive cursor limitation. Source imports Node built-ins in relevant paths. + +“Deno is listed” is therefore not sufficient for NetScript. Adoption needs: + +- Deno import-graph verification; +- Deno compile and runtime tests without undeclared Node globals; +- connection, query, transaction, stream, close, and error mapping tests; +- bundler tests for the supported deployment modes; +- no CLI/toolchain modules in runtime graphs; +- leak detection under repeated start/stop and request lifecycles; and +- one real external PostgreSQL run, not only PGlite or emulation. + +## Maturity scorecard + +Prisma's RC scorecard is unusually honest and should be used rather than feature-list marketing. Its +integration-test threshold counts a capability as proven only when a Prisma Next test executes +against the corresponding real database test environment and asserts observable behavior. + +Across 593 atomic feature rows and 1,779 database cells: + +| Verdict | Cells | +| ---------------------- | ----: | +| Proven | 416 | +| Reachable but untested | 488 | +| Experimental | 12 | +| Absent | 244 | +| Not applicable | 619 | + +Per database: + +| Target | Proven | Untested | Experimental | Absent | N/A | +| ---------- | -----: | -------: | -----------: | -----: | --: | +| PostgreSQL | 222 | 136 | 4 | 111 | 120 | +| SQLite | 85 | 235 | 4 | 98 | 171 | +| MongoDB | 109 | 117 | 4 | 35 | 328 | + +Selected consequences: + +- PostgreSQL is the only credible first adoption target, but still requires NetScript conformance. +- SQLite's presence in source is not feature parity. +- MongoDB validates family abstraction, not production equivalence. +- MySQL and SQL Server need different adapters or later upstream targets. +- Open query/result/transaction work after RC means type presence cannot substitute for runtime + verification. + +## Agent surface audit + +Prisma 8 treats agent instructions as product surface. `init` installs a version-pinned project +skill and a lock file, and the skill routes by workflow. The direction is excellent: an agent gets +local version-specific commands, structured errors, known gaps, and explicit references. + +The RC content is not trustworthy enough to consume directly. Repo-local scans find dozens of legacy +`@internal/...` paths and `PN-*` error-code references, but exact totals vary materially with the +token/root-counting pattern and are not load-bearing evidence. More importantly: + +- legacy internal imports and error-code vocabulary remain after the public move to dotted codes; +- one reference says raw SQL is unavailable while runtime source exposes `raw`; +- one reference says prepared statements are not a user surface while runtime source exposes + `prepare`; +- another debugging reference recommends raw access, contradicting the query reference; and +- migration workflow prose mentions commands or layouts that do not match the RC/current source. + +Issue [#29932](https://github.com/prisma/prisma/issues/29932), where a published `orderBy` nulls +type was accepted but ignored at runtime, is a concrete warning: type surface, docs, and execution +must be tested together. + +NetScript should generate its agent surface from its machine-readable database graph and command +catalog: + +- target/space inventory with capabilities and ownership; +- exact command schemas and structured outputs; +- environment/destructive policy; +- generated import examples that compile; +- known unsupported operations; +- error code and next-action catalog; and +- a conformance test that runs every documented example. + +The generated skill is an output of the architecture, not a hand-maintained parallel manual. + +## Six days of post-RC churn + +Between the RC tag and the 2026-08-13 `main` pin, Prisma landed a long chain of release-candidate +development commits. The following are integration-significant: + +| Change | Evidence | Interpretation | +| ------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | +| Stop publishing the `prisma-next` CLI; use unified `@prisma/cli@next` / `prisma-cli` and a nested ORM config | [`3dc98cb`](https://github.com/prisma/prisma/commit/3dc98cb) | RC binary/config names are not a stable NetScript contract. | +| Route migration/database commands through control API | [`d0c8333`](https://github.com/prisma/prisma/commit/d0c8333) and later command-port commits | Programmatic control is becoming the intended seam. | +| Add sectioned config diagnostics, config format marker, and ControlClient test double | [`15308c6`](https://github.com/prisma/prisma/commit/15308c6) | Config and testing contracts are still formalizing. | +| Generate contract JSON Schema from ArkType | [`92b6ee3`](https://github.com/prisma/prisma/commit/92b6ee3) | Machine validation is improving; pin schema format. | +| Add packed-import, non-throwing-validator, and tarball-install conformance checks | [`c4a5875`](https://github.com/prisma/prisma/commit/c4a5875) | Upstream recognizes publish-surface correctness as a release gate. | +| Lower PostgreSQL floor from 17 to 15 | [`5d4a4db`](https://github.com/prisma/prisma/commit/5d4a4db) | RC documentation can become stale within days. | +| Change aggregate number semantics and add lossless variants | [`a900bc1`](https://github.com/prisma/prisma/commit/a900bc1) | Result typing/precision is not frozen. | +| Make all command output channels explicit | [`71e2e0d`](https://github.com/prisma/prisma/commit/71e2e0d9ee1f306b5a11435cd1973023cb33866a) | Structured orchestration is improving but not settled. | + +The RFC should describe desired NetScript semantics and an upstream compatibility window, not freeze +RC package names into public examples. + +## Open upstream issue and pull-request ledger + +Observed 2026-08-13: + +| Item | Surface | NetScript risk/gate | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ | ----------------------------------------------------------------------------- | +| [Issue #29896](https://github.com/prisma/prisma/issues/29896) | External Supabase contract drift breaks verify | Test external/adopted ownership and version-skew policy. | +| [Issue #29923](https://github.com/prisma/prisma/issues/29923) / [PR #29944](https://github.com/prisma/prisma/pull/29944) | Introspection schema selector silently ignored | Test every selector against a non-default schema; never accept silent ignore. | +| [Issue #29932](https://github.com/prisma/prisma/issues/29932) | Published null-ordering type ignored by runtime | Conformance must cross type, plan, SQL, and result. | +| [PR #29997](https://github.com/prisma/prisma/pull/29997) | Whole-query raw SQL redesign | Treat raw/escape-hatch API as moving. | +| [PR #30009](https://github.com/prisma/prisma/pull/30009) | Exact CLI-engine peer needed to prevent duplicate engine copies | Enforce one resolved upstream component set. | +| [PR #30006](https://github.com/prisma/prisma/pull/30006), [#30014](https://github.com/prisma/prisma/pull/30014), [#30015](https://github.com/prisma/prisma/pull/30015) | Prepared statement counts/results/guards and transaction lifecycle | Prepared/transaction behavior needs dedicated acceptance tests. | +| [PR #29979](https://github.com/prisma/prisma/pull/29979) | Shared PostgreSQL connection query serialization | Test concurrency with externally supplied pools/connections. | +| [PR #29956](https://github.com/prisma/prisma/pull/29956) | Structural pool compatibility | Do not type-promise arbitrary pool implementations before proof. | + +Only items applicable to the Prisma 8 source were used. Prisma 7 engine/client issues were not +silently generalized to the new stack. + +## Adopt, wrap, defer, reject + +| Upstream idea/surface | Decision | Reason | +| -------------------------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------- | +| Canonical contract JSON + declaration | Adopt | Eliminates executable client generation and enables one inspectable graph. | +| Domain/storage separation and hashes | Adopt behind NetScript manifest | Excellent internal identity; upstream representation may evolve. | +| Family/target/adapter/driver/extension split | Adopt conceptually | Correct open-axis model for multiple engines and runtimes. | +| PostgreSQL runtime facade | Wrap | Powerful but too upstream-specific to become NetScript-wide API. | +| Programmatic ControlClient | Wrap and pin | Correct orchestration seam; package/options still moving. | +| Contract spaces | Adopt and extend | Best basis for plugin ownership; needs NetScript target, policy, removal, and provenance. | +| Migration graph, refs, marker, ledger | Adopt after conformance | Stronger than linear scripts; operational gaps remain. | +| Invariant-guarded data transforms | Adopt | Correct semantic model; automate wiring and placeholder detection. | +| Structured errors/progress/results | Adopt and translate | Enables stable CLI/agent surfaces without log parsing. | +| Project-level agent skill | Recreate from NetScript graph | Direction good; RC content stale and internally coupled. | +| Prisma CLI binary/config surface | Do not bind | Changed immediately after RC. | +| Public Prisma package re-exports | Reject | Would transfer upstream RC churn into NetScript API. | +| Hand-written low-level driver adapters | Reject by default | High correctness/security/lifecycle burden; require certification if unavoidable. | +| Copied/merged schema fragments | Reject | No ownership, history, policy, or safe removal. | +| Generated-source text patching | Reject | Non-semantic, non-atomic, and upstream-output coupled. | +| Universal lowest-common-denominator DB API | Reject | Hides real capability differences and weakens every provider. | +| Prisma 7 compatibility facade | Reject | Owner explicitly requires a clean break. | + +## Required NetScript adoption gates + +Prisma 8 can become the PostgreSQL implementation only after all gates pass against a pinned release +candidate or final package set: + +1. **Publish integrity** + - install packed artifacts in a blank Deno/Node fixture; + - verify every NetScript-used export and peer resolves exactly once; + - reject internal/deep imports outside the allowlist. +2. **Contract determinism** + - emit twice from clean checkout and compare bytes/digests; + - emit multiple targets concurrently into distinct roots; + - prove atomic replacement and interruption recovery. +3. **Runtime** + - CRUD, relations, raw, codecs, transactions, prepared statements, streaming/cancellation; + - connection injection, serverless lifecycle, close/leak behavior; + - error mapping and sensitive-value redaction. +4. **Control** + - offline emission never starts Aspire; + - every plan/apply/verify result is structured; + - cancellation and progress spans behave deterministically. +5. **Migration** + - greenfield, existing adoption, drift, destructive refusal, stale-plan refusal; + - graph branch/ref resolution, ledger/marker atomicity, resume after failure; + - data-transform invariants and migration locking; + - non-default namespace and two same-provider target isolation. +6. **Contract spaces** + - two plugins, dependency order, collisions, cross-space FK; + - version upgrade, external drift, missing artifact, uninstall/retention refusal; + - apply/verify with no plugin package installed. +7. **Platform** + - Deno compile/runtime and dependency graph; + - supported bundlers/deployment modes; + - one real PostgreSQL service, not only an emulator. +8. **Docs/agent** + - all generated examples type-check and run; + - command/flag/error catalogs match machine output; + - no internal imports or stale command names. +9. **Upstream maturity** + - no unresolved blocker in the used surface; + - NetScript matrix records upstream scorecard status and local proof; + - an explicit owner signs off each waived upstream gap. + +## Architectural implications for the RFC + +The database RFC should make the following non-negotiable: + +- one NetScript-owned database graph is the composition source of truth; +- Prisma is one target implementation, not the definition of NetScript's database architecture; +- a target ID, not engine name, owns output, connection, migrations, runtime, and receipts; +- contract spaces replace plugin file copying; +- offline work is independent of Aspire; +- generated artifacts are minimal, deterministic, target-scoped, and atomically emitted; +- validation is provider-based and never repaired textually; +- runtime types expose actual capabilities and lifecycle mode; +- consumers own domain ports; database integration is bound at composition roots; +- control operations are programmatic and structured; +- cross-target apply is resumable, never falsely described as atomic; +- agent/docs surfaces derive from the same graph and command schema; +- no Prisma 7 compatibility client, legacy generated module, or runtime shim survives; and +- adoption is gated by NetScript proof, not by an upstream “supported” label. + +## Primary source register + +- [Prisma 8.0.0 RC1 release](https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1) +- [RC source tree](https://github.com/prisma/prisma/tree/v8.0.0-rc.1) +- [Root README and support posture](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/README.md) +- [Architecture overview](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/ARCHITECTURE.md) +- [Feature scorecard](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/scorecard.md) +- [Contract spaces ADR](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md) +- [Data migrations ADR](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20176%20-%20Data%20migrations%20as%20invariant-guarded%20transitions.md) +- [Public package policy ADR](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20242%20-%20Public%20npm%20surface%20-%20single%20%40prisma%20scope%20with%20consolidated%20publish%20packages.md) +- [Programmatic Control API source](https://github.com/prisma/prisma/tree/v8.0.0-rc.1/packages/1-framework/3-tooling/cli/src/control-api) +- [PostgreSQL runtime source](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres.ts) +- [Serverless PostgreSQL runtime source](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres-serverless.ts) +- [Prisma 8 project skill](https://github.com/prisma/prisma/tree/v8.0.0-rc.1/skills/prisma-8) +- [Supported versions](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/Supported%20Versions.md) +- [Serverless deployment guide](https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/Serverless%20Deployment%20Guide.md) diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md new file mode 100644 index 0000000000..83da8c4a8b --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/qwen-prisma-risk-review.md @@ -0,0 +1,326 @@ +# Qwen 3.8 Max — Prisma 8 Integration and Abstraction Falsification Review + +Run: `docs-database-architecture-rfc--prisma-8-rfc` · Date: 2026-08-13 · Status: independent +research/review lane (not PLAN-EVAL, not RFC authorship). + +## 1. Route identity and interruptions + +| Field | Value | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Requested route | OpenRouter · `qwen/qwen3.8-max` · effort `max` | +| Observed harness | Claude Code session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b`; backend SKU is not self-verifiable from inside the session | +| Route caveat | The session executes inside an Anthropic Claude Code harness. The launcher's dispatch record, not this report, is authoritative for whether OpenRouter actually routed `qwen/qwen3.8-max`. Treat this lane as "the session briefed as the Qwen third-opinion lane" until the dispatch log confirms it. | +| Interruption 1 | The original parent spawned four read-only verification children; one child requested `claude-opus-5` and the evaluator model guard denied the cross-model request. This is a route-policy failure, not an architecture finding. The children left no completion records, so the parent re-verified all load-bearing claims itself, single-parent, read-only. | +| Interruption 2 | The single-parent recovery pass was terminated by the local PTY supervisor (signal 15 / exit 143) mid-Prisma-audit. All reasoning and tool results survived in-session; this report synthesizes from them plus a final narrow verification batch. | +| Constraint honored | No Agent/Task/Workflow/child facilities used in the recovery turns; no files edited except this artifact. | + +## 2. Independent verdict + +**[INFERENCE]** The proposed direction is **correct and should proceed to plan lock, with three +corrections and five conditional deferrals**. The evidence supports every structural claim that +motivates it: + +- NetScript verifiably has no join point between its five database systems; target resolution + provably ignores `PrimaryDatabase`, same-provider targets provably collide at + `database/`, and every operation — including pure codegen — provably requires the + resident Aspire AppHost (§3, items F1–F10). +- Prisma 8 RC1 verifiably replaces the executable generated client with contract data + a versioned + runtime, exposes a real programmatic control seam (`createControlClient`, confirmed at source), + and verifiably churned its CLI/config/publish surface within days of the RC tag (all eight churn + commits confirmed present and post-RC in the local clone). + +**[INFERENCE]** The direction is falsified in no place, but it over-specifies in three: + +1. **"Capability negotiation" as a first-class mechanism** risks becoming the seed of a second + type-level ORM. Compile-time capability tags are sufficient; a runtime negotiation protocol is + unnecessary and should be deferred indefinitely (§4). +2. **"Consumer-owned ports" framed as a NetScript concept** — ports are an application practice, not + framework API. NetScript should ship a typed target reference (`dbRef`-style) and guidance, not a + port framework (§4). +3. **Treating contract spaces as a solved plugin-removal story** — the deep dive itself records that + extension removal is unsupported in RC; the market matrix nonetheless scores proposed NetScript + "Strong" on plugin/feature schema ownership. That strength is conditional on an upstream + capability that does not exist (§8, R6; §9). + +The minimum durable NetScript surface is **smaller than the research proposes**: a declarative +manifest, an operation protocol with receipts, and a contribution/ownership record — nothing else +(§4). Everything deeper (contract, hashes, migration graph, runtime facade) is Prisma-owned and +stays adapter-local. + +## 3. Corrected-fact ledger + +Evidence classes: **[RC-tag]** = verified against local `v8.0.0-rc.1` checkout (`a76a6c5`); +**[main]** = verified against post-RC commits present in the same clone (`origin/main` tip +`71e2e0d`, 50 commits after the RC tag); **[NS]** = verified against NetScript worktree at baseline +`cd72052`; **[doc]** = restated from the run's research documents, not independently re-verified +this session (flagged for PLAN-EVAL). + +### 3.1 Corrections to the research documents + +| # | Research claim | Verified fact | Class | Evidence | +| --- | ----------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| F1 | "Prisma `7.8.0` in the root catalog/lock" | Root catalog uses **caret ranges `^7.8.0`**, not exact pins, for `@prisma/adapter-mssql`, `@prisma/adapter-pg`, `@prisma/client`, `@prisma/driver-adapter-utils`, `@prisma/instrumentation-contract`. The lock resolves them; the catalog does not pin. | [NS] | `deno.json:231–235` | +| F2 | Generated workspaces encode `^7.4.2` | Confirmed, and the divergence is structural: templates render `npm:prisma@^7.4.2` and `npm:@prisma/adapter-pg@^7.4.2` while the root catalog carries `^7.8.0`. Templates also reference `npm:@prisma/adapter-libsql@^7.4.2` — a libsql/SQLite axis exists in current templates and has **no Prisma 8 GA equivalent** (SQLite is proof-of-concept upstream). | [NS] | `packages/cli/src/kernel/templates/database/generate-db-deno-json.ts:36,56,59,61,67,71,74`; `generators_test.ts:41,58,219` | +| F3 | "more than twenty database tasks" in generated `deno.json` | **Exactly 30 unique `db:*` tasks** (incl. `db:fix-zod`, `db:patch-client`, `db:clear-seeded-client`, `db:resolve-applied`, `db:resolve-rolled-back`, `db:zod`, `db:format`, and per-op `:all` variants). | [NS] | `generate-db-deno-json.ts` (enumerated) | +| F4 | Fourteen CLI verbs | Confirmed exactly: add, deploy, generate, init, introspect, list, migrate, remove, reset, resolve, seed, status, studio, validate (`operations/` is internal plumbing, `db-group.ts` the group). | [NS] | `packages/cli/src/public/features/db/` | +| F5 | `resolveTarget` ignores `NetScript.PrimaryDatabase` and defaults only with exactly one enabled target | Confirmed; strengthened: `PrimaryDatabase` **is maintained** (set on `db add`, reassigned on `db remove`) but is never consulted during operation resolution. With >1 enabled target and no `--db`, resolution throws `Unknown database target: (default)`. | [NS] | `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:66` (body quoted below); `workspace-mutator.ts:67–71,120–121` | +| F6 | Two same-engine targets collide at `database//` | Confirmed: `workspaceDir: join('database', provider.dirName)` — keyed by provider dir, not target id. | [NS] | `workspace-resolver.ts:51` | +| F7 | Circular adapter assembly (`setClient`) | Confirmed on all three adapters; port is `DatabaseAdapter` + `DatabaseAdapterFactory`. | [NS] | `packages/database/adapters/postgres.adapter.ts:97`, `mssql.adapter.ts:434`, `mysql.adapter.ts:368`; `ports/database-client.ts:85,132` | +| F8 | `@netscript/database` subpath story | Confirmed with nuance: exports are `.`, `./ports`, `./adapters`, `./adapters/postgres`, `./adapters/mssql`, `./adapters/mysql`, `./extensions`, `./scripts`, `./tracing`, `./testing` (package v0.0.6). MySQL/MSSQL adapters exist **both** in-package (subpath) and, for MySQL's low-level driver adapter, in the separate `packages/prisma-adapter-mysql`. | [NS] | `packages/database/deno.json` | +| F9 | Custom MySQL adapter is a large upstream-coupled surface | Confirmed: implements `SqlDriverAdapter` directly, imports `@prisma/driver-adapter-utils` types/`Debug`/`DriverAdapterError`, uses `mysql2/promise` (dynamic import), and carries legacy lineage in its debug namespace `prisma:driver-adapter:deno-mysql`. | [NS] | `packages/prisma-adapter-mysql/src/adapter.ts:15–23,30,319,427,570`; `errors.ts:7`; `conversion.ts:8–9` | +| F10 | Plugin fragment model is regex-based file copying | Confirmed: 123-line scanner with header regex `/^\s*(model\|enum\|type\|view)\s+([A-Za-z_][A-Za-z0-9_]*)\s*\{/gm`. | [NS] | `packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts:2,13` | +| F11 | Aspire coupling incl. pure generate; studio first-target; `--db all` sequential fail-fast | All confirmed: detached execution demands the resident AppHost ("The resident Aspire AppHost is not running…"); `studio` executes `databases[0]` only; the `all` loop returns on first non-zero exit with no per-target result record. | [NS] | `packages/cli/src/kernel/adapters/database/operation-runner.ts:85–101,116–117,179–181`; debt entry `DB-GENERATE-ASPIRE-COUPLING` (`.llm/harness/debt/arch-debt.md:1954+`, cites `executeDetached` + `aspire start --apphost apphost.mts`, ~243ms fast-fail without Aspire) | +| F12 | Debt entries `packages/database — AP-17` and `DB-GENERATE-ASPIRE-COUPLING` open | Confirmed, with a wording correction: the AP-17 entry says "`interfaces/` should become `ports/`; composition root needs confirmation" — the rename is **pending**, not already done ("ports were renamed" in the current-state audit is inaccurate). Note AP-17 is a per-package verdict id reused across packages (the `packages/cron` AP-17 entry is closed). | [NS] | `.llm/harness/debt/arch-debt.md:316–324` | +| F13 | `@prisma/orm-postgres` export map has "more than one hundred subpaths" | Undercount. The published package.json contains **~275 unique `./…` export subpath keys**. It depends on `pg` (`"pg": "catalog:"`), and TypeScript is an **optional** peer with floor `>=5.9`, enforced by a `MIN_TYPESCRIPT_PEER` constant + `pnpm lint:manifests` CI gate. No `engines.node` field was observed in that package.json; the Node 24 floor is documented in Supported Versions, not that manifest. | [RC-tag] | `packages/9-public/@prisma/orm-postgres/package.json:24,32,35–39`; `docs/Supported Versions.md:11,26–32` | +| F14 | Skill audit: "83 distinct `@internal/` roots, 116 occurrences, 47 `PN-*` codes" | Directionally confirmed, numerically **not reproducible**: this review measured **35 distinct roots, 191 occurrences, 66 `PN-*` references** over `skills/prisma-8` (grep methodology: `grep -rho "@internal/[A-Za-z0-9_./$-]*" | sort -u | wc -l`, etc.). The qualitative conclusion — the shipped agent skill is laced with legacy internals and obsolete error codes — holds under either measurement. The RFC must not cite either set of counts as load-bearing. | +| F15 | Post-RC churn table (8 commits) | All eight commits exist locally, all are descendants of `v8.0.0-rc.1`, and `71e2e0d` is the tip of `origin/main` (50 commits after the RC tag). Exact subjects: `3dc98cb` feat(cli)!: stop publishing the prisma-next CLI — unified prisma-cli replaces it (#30005); `d0c8333` Route migration/db commands through the control-api seam (TML-3173) (#29911); `15308c6` Config diagnostics by section, defineConfig version marker, ControlClient test double (#29936); `92b6ee3` generate contract.json JSON schema from arktype source (#29935); `c4a5875` publish path gains three conformance checks (#29998); `5d4a4db` lower PostgreSQL floor from 17 to 15 (ADR 244) (#29971); `a900bc1` count/sum/avg return JS numbers, with lossless variants (#29930); `71e2e0d` ORM commands state all four output channels (#30004). | [main] | local git objects; `git merge-base --is-ancestor v8.0.0-rc.1 ` for each | +| F16 | RC1 publishes a `prisma-next` CLI | Confirmed — `packages/9-public/prisma-next` is `private: false` at the RC tag, and post-RC `3dc98cb` then **stops publishing it**. This is the sharpest locally-proven example of a public name dying within days of the RC. | [RC-tag] + [main] | `packages/9-public/prisma-next/package.json`; `3dc98cb` | +| F17 | Scorecard methodology: "proven" = integration test against a real database | Confirmed with a critical nuance: for **Postgres, "proven" includes PGlite-backed integration tests** ("Postgres via PGlite, SQLite via its real driver, MongoDB via mongodb-memory-server"). Upstream "proven" therefore does **not** imply proof against a server PostgreSQL. NetScript's gate "one real external PostgreSQL run, not only PGlite" is necessary, not redundant. | [RC-tag] | `scorecard.md:3,9–15` | +| F18 | Early Access posture; DB target set | Confirmed: README — "Prisma Next is currently in Early Access … we don't recommend it for production workloads yet" (line 21); MongoDB "early access; proves the framework works beyond SQL" (line 91); scorecard matrix has **only Postgres/SQLite/MongoDB columns** — MySQL and SQL Server are absent from the RC feature surface entirely; Supported Versions at RC: Node 24 primary, Bun 1.2/Deno 2.0 best-effort, PostgreSQL floor **17** (lowered to 15 only post-RC, `5d4a4db`). | [RC-tag] + [main] | `README.md:21,91`; `scorecard.md:3`; `docs/Supported Versions.md:11–21` | +| F19 | Package topology `@prisma/orm-*` | Confirmed: 16 published `@prisma/*` packages — facades `orm-postgres`/`orm-mongo`/`orm-sqlite`; `orm-framework`; families `orm-family-sql`/`orm-family-mongo`; targets `orm-target-postgres`/`-sqlite`/`-mongo`; `orm-toolchain`; extensions `orm-extension-arktype-json`, `-middleware-cache`, `-paradedb`, `-pgvector`, `-postgis`, `-supabase`. The extension list is **missing from the deep dive** and matters: upstream already ships vendor/pack extensions (Supabase, PostGIS, pgvector, ParadeDB) — NetScript's contribution model must coexist with upstream extensions, not assume it is the only extension layer. | [RC-tag] | `packages/9-public/@prisma/*/package.json` | +| F20 | `createControlClient` programmatic seam | Confirmed at source: `export function createControlClient(options: ControlClientOptions): ControlClient`; consumed by `commands/migrate.ts`, `commands/migration-show.ts`, with `test/control-api/client.errors.test.ts`. The published subpath spelling (`@prisma/orm-toolchain/cli/control-api`) was not re-verified in the exports map. | [RC-tag] | `packages/1-framework/3-tooling/cli/src/control-api/client.ts:69` | + +### 3.2 Claims NOT re-verified this session ([doc] class — carry as research assertions) + +- Exact scorecard verdict tallies (593 rows / 1,779 cells / 416-488-12-244-619; per-DB table). + Methodology verified (F17); tallies not re-counted. +- ADR 212 (contract spaces) and ADR 176 (invariant-guarded data transforms) text details. +- Runtime facade surface inventory (`sql`/`orm`/`raw`/`prepare`/`transaction`/…) and serverless + facade asymmetry details. +- Upstream issue/PR ledger semantics (#29896, #29923/#29944, #29932, #29997, #30009, + #30006/#30014/#30015, #29979, #29956) — GitHub-side evidence; the RC-side churn commits that + correspond to them (F15) are locally verified. +- Contract emission file names (`contract.json`/`contract.d.ts`) and "types-only emission" phrase. + +## 4. Minimum viable NetScript-owned architecture + +**[PROPOSAL]** The durable kernel is **three artifacts, not five concepts**. "Database graph, target +descriptors, contract spaces, capability negotiation, consumer-owned ports" collapses to: + +1. **Database manifest (data, not an object system).** A declarative, typed document + one pure + resolution function producing a deterministic, content-addressed manifest snapshot. Contents per + target: stable user-defined target id; family + provider target; connection / provisioning source + reference; namespaces; list of contribution-space refs; operational policy (consent, environment + binding). No methods, no runtime graph object, no service registry. This is the join point the + five current systems lack (F1–F11). Renaming "graph" → "manifest" is deliberate: graphs accrete + traversal APIs and become control planes; manifests do not. +2. **Operation protocol.** One typed API — `classify / compose / plan / apply / verify / status` — + with structured results, dotted-code errors, and **receipts** (per-target phases, graph digest, + package-set identity, live-baseline binding, expiry, resume cursor). Offline classification is a + protocol property: `compose/emit/format` must never start Aspire (kills F11's coupling). `apply` + refuses drifted inputs (graph, baseline, package set, or target changed since plan). Cross-target + apply is resumable with explicit partial success — never described as atomic. +3. **Contribution record.** Per schema contributor: space id, version, provenance digest, target + binding predicate, ownership policy (`managed` / `adopted` / `external` / `ignored`), dependency + list, removal/retention policy. NetScript maps this 1:1 onto Prisma contract spaces (ADR 212) — + it wraps and polices them; it does not reimplement the marker/ledger machinery. + +**Demoted from the research proposal:** + +- _Capability negotiation_ → static capability tags on targets checked at composition/type time (a + branded `TargetRef` constraint). Runtime negotiation deferred indefinitely; + it is the most likely seed of a second ORM. +- _Consumer-owned ports_ → application practice + guidance + `dbRef`-style typed target references. + Not a NetScript port framework, not a generated repository interface. +- _Validation generation_ → pluggable validator providers emitting once into an atomic target-scoped + artifact root, proven by semantic tests; textual repair forbidden (this already follows from the + research; retained as-is). +- _Agent surface_ → generated projection of manifest + operation catalog; never hand-maintained (the + RC skill audit, F14, is the cautionary tale). + +**[INFERENCE]** This kernel is the minimum: remove the manifest and the five systems diverge again; +remove the protocol and success-without-artifacts (#1327-class failures) returns; remove the +contribution record and plugin schema falls back to regex file copying (F10). Nothing else is +load-bearing — everything further is Prisma-owned mechanics or app-owned practice. + +## 5. Ownership / boundary table + +| Concept | Owner | Surface class | Rationale / evidence | +| --------------------------------------------------------------------------------------------- | ---------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Database manifest schema + resolution | NetScript | **Public** (types + one function) | The join point; must be inspectable by users, CI, agents. | +| Manifest snapshot / digest lockfile | NetScript | **Generated data** | Content-addressed, atomically replaced; the stale-artifact detector. | +| Operation protocol (`plan/apply/verify/status`), receipts, error codes | NetScript | **Public** | Replaces log scraping; stable contract even as upstream seams move (F15). | +| Target id, ownership-policy enum, consent policy | NetScript | **Public** | Durable vocabulary; survives provider swaps. | +| `dbRef`-style typed target reference, session scoping types | NetScript | **Public (narrow)** | The only runtime-facing public type; capability-tagged at type level. | +| Capability tag registry | NetScript | **Public data, closed extension process** | Tags are data; adding one is a reviewed change, not a plugin right. | +| Contribution descriptor types + conformance kit | NetScript | **Public** | Plugin authors need only this. | +| Resolution algorithms, digest computation, lock management | NetScript | **Internal** | No public promise; free to change. | +| Aspire/provisioning binding | NetScript | **Internal** | F11 shows what happens when orchestration leaks into operations. | +| `contract.json` / `contract.d.ts`, storage/profile hashes, migration graph/refs/marker/ledger | Prisma | **Adapter-local** (surfaces in receipts only as opaque, versioned handles) | Upstream representation still moving (92b6ee3: contract JSON schema itself regenerated from ArkType post-RC). Raw upstream hashes must never be NetScript public identifiers. | +| ControlClient invocation + option translation | NetScript adapter | **Adapter-local** | `createControlClient` confirmed real (F20) but command routing/output channels moved post-RC (d0c8333, 71e2e0d). | +| Runtime facade (`sql/orm/raw/prepare/transaction`) | Prisma | **Adapter-local**, exposed only through capability-tagged session types | Result/number semantics moved post-RC (a900bc1); raw redesign open (#29997 per deep dive). | +| Engine/provider specifics (Postgres floor, PGlite-vs-server behavior) | Provider/target adapter | **Adapter-local data** | Floor moved 17→15 post-RC (5d4a4db); NetScript records, does not hardcode. | +| Plugin schema artifacts (pinned mirrors of spaces) | Plugin author; pinned by app | **Generated data in consumer repo** | ADR 212 model; removal/retention policy is NetScript's addition (unsupported upstream in RC). | +| Validator artifacts (Zod etc.) | Validator provider | **Generated data** | One atomic target-scoped root; semantic tests required. | +| Agent skill/manifest | NetScript generator | **Generated data** | F14 proves hand-maintained upstream skills rot within a release. | + +## 6. Prisma adopt / wrap / reject / defer + +Evidence class in brackets. Decisions differ from the deep dive only where noted. + +| Upstream surface | Decision | Evidence | +| -------------------------------------------------------------- | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ | +| Canonical contract data + types-only emission | **Adopt** behind manifest snapshot | Eliminates generated executable client and text patching (F3 pipeline); [doc] emission names | +| Domain/storage hash separation | **Adopt as adapter-local handles** in receipts; NetScript digest stays primary | 92b6ee3 [main]: contract JSON schema regenerated from ArkType — format not frozen | +| Family/target/adapter/driver/extension axis split | **Adopt conceptually** as manifest vocabulary | F19 topology confirms the decomposition is real | +| Programmatic ControlClient | **Wrap + pin** inside integration package; translate to NetScript operation protocol | F20 source confirmed; d0c8333/15308c6/71e2e0d [main] prove the seam is improving but moving | +| PostgreSQL runtime facade | **Wrap**, capability-tagged; no NetScript-wide re-export | F13: ~275 subpaths + `pg` dep — direct re-export would import RC internals and Node-only deps into Deno graphs | +| Contract spaces (ADR 212) | **Adopt + extend with NetScript ownership/removal policy** | [doc] ADR text; F19 vendor extensions mean NetScript spaces must coexist with upstream packs | +| Migration graph/marker/ledger | **Adopt after conformance** | [doc]; PG "proven" includes PGlite (F17) — server-proof is NetScript's job | +| Invariant-guarded data transforms | **Adopt semantics**; automate wiring | [doc] ADR 176; placeholder ergonomics unfinished per deep dive | +| Structured errors/progress spans | **Adopt + translate** to NetScript code catalog | 71e2e0d [main]: output channels still being formalized | +| `prisma-next` / unified CLI binary & config names | **Reject as contract** | F16 + 3dc98cb [main]: the RC's own CLI package stopped being published six days later | +| Re-exporting any `@prisma/orm-*` subpath | **Reject** | F13 surface breadth | +| Hand-written low-level driver adapters | **Reject by default** | F9 shows the cost: `packages/prisma-adapter-mysql` is a full `SqlDriverAdapter` implementation on an unstable upstream utils package | +| Copied/merged schema fragments; generated-source text patching | **Reject** | F10, F3 | +| Prisma 7 compatibility facade | **Reject** | Owner directive; clean break | +| Prepared-statement/transaction public guarantees | **Defer until final** | [doc] PR ledger #30006/#30014/#30015 in flight | +| Raw SQL escape hatch as NetScript API | **Defer/reject as public**; adapter-local at most | [doc] #29997 whole-query redesign | +| Numeric/aggregate semantics promises | **Defer until final** | a900bc1 [main]: count/sum/avg semantics changed post-RC | +| Extension removal via upstream primitive | **Defer; NetScript owns interim diagnostics** | [doc] scorecard: removal unsupported in RC | +| MySQL/SQL Server/MongoDB production posture | **Defer past 8.0 GA** | F18: absent from RC matrix / early access | + +## 7. Multi-provider and Prisma-GA contingency strategy + +**[PROPOSAL]** Do not block the architecture on Prisma 8's PostgreSQL-only GA, and do not retain +Prisma 7 compatibility: + +1. **Ship the kernel provider-neutral; ship the adapter Postgres-only.** The manifest, operation + protocol, and contribution record (§4) contain no Prisma concepts in their public fields — the + schema artifact is an implementation-defined handle. The first (and for v1 only) implementation + adapter targets Prisma 8 PostgreSQL. +2. **Non-Postgres targets get an explicit `unsupported-target` diagnostic**, never a silent skip and + never a legacy fallback path. This retires the current MySQL/MSSQL adapter surface (F8, F9) as a + product direction while the architecture stays open. +3. **Reserved-but-unbuilt SPI.** A target-implementation interface thin enough that a future + Drizzle/Kysely-backed or later-Prisma-family adapter can be added without manifest changes. Do + not build it now; conformance-kit first, second adapter later. +4. **SQLite regression is explicit debt.** Current templates carry `adapter-libsql` (F2); Prisma 8 + SQLite is proof-of-concept (F18). The clean break must state in the RFC that SQLite/libsql + targets are **not carried forward** until upstream SQLite cells are proven (scorecard), or a + non-Prisma SQLite adapter is built under the SPI. +5. **If Prisma 8 GA slips or regresses**: the kernel ships anyway; the adapter stays feature-flagged + and unpublished; conformance gates (§9) are the only release valve. Delay the adapter, never the + architecture, and never re-open a Prisma 7 code path (release-policy maintenance of the old major + is a branch question, not an architecture question). +6. **Duplicate-component guard**: exactly one resolved `@prisma/orm-*` set per app (deep-dive PR + #30009 concern — exact CLI-engine peer to prevent duplicate engine copies); a dependency check + fails on any second copy or off-allowlist deep import. + +## 8. Adversarial failure / risk ledger + +### 8.1 Ten highest-risk RFC decisions + +| # | Decision at risk | Severity | Evidence | Required disposition | +| --- | -------------------------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | +| R1 | Freezing any upstream package/CLI name into public API or examples | **Critical** | F15/F16: `prisma-next` CLI unpublished 6 days post-RC; config/output channels moved (`3dc98cb`, `15308c6`, `71e2e0d`) | RFC names NetScript semantics + a compatibility window; zero upstream import paths in public contracts | +| R2 | Binding NetScript operation contracts to ControlClient option shapes | **High** | F20 + d0c8333/15308c6 [main] — seam real but still formalizing | Translate layer inside the integration package; regenerate per pinned upstream release; conformance covers shape drift | +| R3 | Public numeric/result promises (aggregates, decimals) | **High** | a900bc1 [main]: count/sum/avg semantics changed post-RC | No numeric-semantics guarantees until GA; tests assert observed behavior per pin | +| R4 | Plugin removal promised via contract spaces | **High** | [doc] extension removal unsupported in RC; market matrix "Strong" ownership score contradicts it | RFC specifies NetScript-level removal diagnostics + retention policy now; marks upstream removal a conditional enhancement | +| R5 | Deno support assumed from "Deno listed" | **High** | F18: Bun/Deno explicitly best-effort; F13: facade depends on `pg`; F17: PG proof is PGlite-based | NetScript platform gate (import graph, compile, lifecycle, leaks, one real server PostgreSQL) before any adapter publishes | +| R6 | Externally-owned schemas treated as verifiable like managed ones | **High** | [doc] #29896 Supabase drift breaks `db verify`; workaround marker-only | Ownership policy (`managed/adopted/external/ignored`) is manifest data and changes plan/verify behavior; conformance scenario required | +| R7 | Multi-target apply described or implemented as atomic | **Medium** | No cross-DB atomicity upstream; current `--db all` is fail-fast with no result record (F11) | Per-target receipt phases + idempotent resume + explicit partial-success; RFC must forbid the word "atomic" cross-target | +| R8 | Same-provider multi-target identity by engine/provider name | **Medium** | F6: `join('database', provider.dirName)` | Target id owns output/connection/migrations/runtime/receipts; conformance: two postgres targets, independent schemas/histories, zero shared paths | +| R9 | Capability negotiation runtime enters the kernel | **Medium** | Abstraction-minimization analysis (§4); market's second-ORM hazard | Compile-time tags only; runtime negotiation rejected unless a concrete use case survives plan-gate | +| R10 | Stale artifacts remain possible after schema edits | **Medium** | F3 (30-task non-atomic pipeline); #1254/#1290-class history in current-state audit | Manifest snapshot digest gates compile/run; mismatch = typed error, not warning | + +### 8.2 Market-audit falsifications + +**[INFERENCE]** + +- **Missing competitors that weaken conclusions:** (1) **Flyway/Liquibase** — the deepest prior art + for migration ledgers, locks, out-of-order handling; absent entirely, so the audit's + ledger/lessons appear newer than they are. (2) **Terraform/Pulumi** — the origin of + plan/apply/state-lock/drift/partial-apply semantics the audit borrows from Atlas; their hardest + lessons (state backends, locking, `-target`-style partial apply, tainted resources) map directly + onto NetScript receipts and are unconsidered. (3) **Bytebase** — open-source schema-change control + plane with review policy + drift detection; closer comparator to the proposed policy gates than + Atlas. (4) **ZenStack** — Prisma-schema extension/plugin model directly relevant to contract-space + contributions on Prisma. +- **Dangerous analogies:** (1) **Atlas-as-local**: Atlas's drift monitoring, target groups, rollout, + and audit history are hosted-control-plane products; assuming local replication underprices the + build, and its `composite_schema` "order = dependency" is a weak ordering NetScript must not + import. (2) **The capability matrix self-score**: "Proposed NetScript" is scored "Strong" across + the board, including plugin ownership, while the deep dive records extension removal as + unsupported upstream — the matrix must be re-scored as _conditional_. (3) **Django routers** as + routing precedent risk importing runtime-string resolution into what must be compile-time binding; + the audit's own anti-pattern list (silent skips) already shows why. + +## 9. Conformance and release matrix + +**[PROPOSAL]** Every row must cross **type → plan → SQL/artifact → result → lifecycle**; a +compile-time pass alone never satisfies a row (this is the direct answer to #29932-class +type/runtime divergence and to F17's PGlite nuance). Negative paths are first-class tests. + +| Scenario | Negative path that MUST fail correctly | Layers asserted | +| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| Two same-provider targets (`primary`, `analytics`, both postgres) | Cross-target import/operation by engine name; shared output path | type, plan, artifacts, runtime isolation | +| Multi-schema / non-default namespace | Introspect/selector silently ignoring schema (cf. [doc] #29923) — must error, not skip | plan, SQL, result | +| External ownership | `apply` against `external`-policy objects; `verify` with accepted drift must pass, unaccepted drift must fail with reason code | plan, verify, receipt | +| Plugin upgrade | Apply with stale pinned space artifacts; version skew between space and core | plan refusal, receipt | +| Plugin removal | Removal without retention decision → typed refusal; copied-directory deletion path must not exist | lifecycle, migration state | +| Partial cross-target apply | Second target fails mid-run → receipt records phase per target; resume continues only unfinished targets; no re-execution of applied ones | receipt, resume, result | +| Interrupted emission | Kill during emit → no partial artifact visible to consumers; re-emit byte-identical | artifact atomicity, determinism | +| Stale plan | Apply after graph/baseline/package-set change → refusal with drift reason; expired plan refusal | plan binding, receipt | +| Version skew | App runtime package vs pinned contract format mismatch → typed error naming both versions | contract version check | +| Deno dependency graph | Any Node builtin/`pg` leak outside the adapter package; CLI/toolchain modules in runtime graphs → import-graph test fails | graph purity, compile, leak tests | +| Real server PostgreSQL | Full lifecycle (connect/query/txn/stream/close/leak) against a server instance, never satisfied by PGlite (F17) | runtime, lifecycle | +| Agent/docs surface | Every documented example must compile and run; command/flag/error catalogs diffed against machine output | docs-as-tests | + +**Release gates (adapter publishes only when):** publish integrity (packed install, single +resolution of the `@prisma/orm-*` set, allowlist enforced) → contract determinism (double-emit byte +equality, concurrent multi-target emit) → runtime + control + migration conformance rows above → +platform rows → docs/agent rows → upstream-maturity row (no unresolved blocker in the used surface; +each waived gap owner-signed). The `scaffold.runtime` E2E remains the merge-readiness proof per +AGENTS.md, with the db suite exercising rows 1, 6, 7, 8 end-to-end. + +## 10. Conditional decisions and kill/switch criteria + +**[PROPOSAL]** Must remain conditional until Prisma 8 final (or a NetScript-gated exception): + +| Conditional item | Unblocks when | Kill/switch criterion | +| -------------------------------------- | ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- | +| Upstream import allowlist frozen | GA package topology stable ≥1 release | Any post-GA rename of a used subpath → allowlist bump is a NetScript patch, never a public break | +| Prepared/transaction guarantees | PR ledger (#30006/#30014/#30015 class) merged + proven cells | Still unproven at GA → ship session API without `prepare`; no facade promises | +| Raw SQL surface | #29997-class redesign lands + proven | Still moving at GA → raw stays adapter-local, undocumented publicly | +| Numeric semantics | GA behavior + scorecard proven | Any post-GA semantic change → NetScript pins and translates, does not chase | +| Contract hash/format identity | Format stable across two releases | Canonicalization change → receipts treat hashes as opaque handles (already the design; this is the switch) | +| Extension removal | Upstream primitive proven | Absent at GA → NetScript removal diagnostics + retention policy is the product behavior (R4) | +| PostgreSQL floor | GA docs confirm 15 (post-RC direction, 5d4a4db/ADR 244) vs RC's 17 | Floor rises again → adapter records floor as adapter-local data | +| Deno support | NetScript platform gate passes on GA bits | Fails → adapter unpublished for Deno; kernel unaffected (§7.5) | +| Scorecard tallies as adoption evidence | Re-counted at GA | Tallies move materially → conformance matrix re-run, not re-argued | +| `orm-*` single-resolution invariant | #30009-class peer guarantee in GA | Duplicate-component corruption observed → hard dependency-check gate blocks release | + +## 11. Source register + +**NetScript (worktree @ baseline `cd720529`, class [NS]):** `deno.json:231–235` (catalog `^7.8.0`); +`packages/cli/src/kernel/templates/database/generate-db-deno-json.ts` (30 tasks, `^7.4.2`, libsql +specifier); `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51,66`; +`workspace-mutator.ts:67–71,120–121`; +`packages/cli/src/kernel/adapters/database/operation-runner.ts:85–101,116–117,179–181`; +`packages/cli/src/public/features/db/` (14 verbs); +`packages/cli/src/kernel/adapters/plugin/prisma-declaration-scanner.ts`; +`packages/database/deno.json`, `ports/database-client.ts:85,132`, +`adapters/{postgres,mssql,mysql}.adapter.ts` (`setClient`); +`packages/prisma-adapter-mysql/src/{adapter,errors,conversion}.ts`; +`.llm/harness/debt/arch-debt.md:316–324,1954+`. + +**Prisma RC (`.llm/tmp/prisma-v8-rc1`, HEAD = tag `v8.0.0-rc.1` = `a76a6c5`, class [RC-tag]):** +`README.md:21,91`; `scorecard.md:3,9–15`; `docs/Supported Versions.md:11–32`; +`packages/9-public/@prisma/*/package.json` (16 packages + surface counts); +`packages/9-public/prisma-next/package.json`; +`packages/9-public/@prisma/orm-postgres/package.json:24,32,35–39`; +`packages/1-framework/3-tooling/cli/src/control-api/client.ts:69`; `skills/prisma-8/**`. + +**Post-RC main (same clone, class [main]):** commits `3dc98cb`(#30005), `d0c8333`(#29911), +`15308c6`(#29936), `92b6ee3`(#29935), `c4a5875`(#29998), `5d4a4db`(#29971, ADR 244), +`a900bc1`(#29930), `71e2e0d`(#30004) — all verified descendants of `v8.0.0-rc.1`; `origin/main` tip += `71e2e0d` (50 commits after RC tag). + +**Run research documents ([doc] where not re-verified):** `research/netscript-current-state.md`, +`research/prisma-8-deep-dive.md`, `research/market-analysis.md`; upstream issue/PR ledger therein +(#29896, #29923/#29944, #29932, #29997, #30009, #30006/#30014/#30015, #29979, #29956); ADRs 212, +176, 242. + +**Process artifacts:** `supervisor.md` (route table), `plan.md` (locked decisions L0–L4), +`drift.md`, `briefs/qwen-prisma-risk-review.md`, `briefs/claude-opus-architecture.md`. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md new file mode 100644 index 0000000000..0f536c5c96 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-maintainer-exchange.md @@ -0,0 +1,116 @@ +# Runtime Validation — Owner / Prisma Maintainer Exchange + +## Provenance and confidence + +- Source: three owner-provided screenshots from the public `#prisma-next` Discord channel. +- Exchange dates: 2026-03-05 through 2026-03-06. +- Participants visible in the screenshots: `rickyshowtime` (NetScript owner) and `wmadden` + (identified by the owner as a Prisma maintainer). +- Confidence: primary evidence of an exploratory maintainer conversation, **not** an upstream + roadmap commitment or proof that a stable public validation API ships in Prisma 8 RC1. + +## What the exchange establishes + +The owner proposed deriving Standard Schema-compatible validation from Prisma Next's +machine-readable contract so applications no longer hand-write or third-party-generate schemas that +mirror model types, nullability, and constraints. The proposed scope covered both: + +1. mutation/query inputs; and +2. query outputs when data crosses trust boundaries such as API responses, SSR hydration, or an + external service. + +The owner initially described either a built-in emission step or a first-party `afterEmit` plugin. +The maintainer replied that the idea was viable and then sharpened the direction: validation could +probably be derived from the contract **at runtime**, skipping the extra generation step, because +the contract contains the necessary type and runtime data. + +That distinction is architectural. The opportunity is not “replace one Zod generator with another.” +It is to make the resolved contract the runtime validation authority and treat any emitted validator +artifact as an optional, semantically equivalent optimization. + +## NetScript design implications to resolve in the RFC + +### Durable boundary + +- Standard Schema is the interoperability contract; Zod, Valibot, ArkType, and other libraries are + consumer choices, not framework foundations. +- The default validator is interpreted/compiled from the resolved contract snapshot and cached by + target + contract/profile identity. +- Validation artifacts must never become a second source of truth. Optional ahead-of-time emission + is atomic, derived, replaceable, and proven equivalent to the runtime interpreter. +- Plugin/contribution spaces participate automatically through the same resolved aggregate contract; + plugin authors do not maintain parallel validator files. + +### Two distinct planes + +- **Input validation:** operation-aware mutation/query inputs, including required/optional/defaulted + fields, nested writes, relation identifiers, constraint metadata, provider types, codecs, and + plugin-contributed fields. +- **Output validation:** selection/projection-aware result shapes at an explicit trust boundary. A + whole-model validator is incorrect for partial selects, aggregates, raw/provider results, or + relation projections. + +The RFC must also separate runtime database values from serialized/wire values. Dates, decimals, +bigints, bytes, native enums, JSON, custom codecs, and redacted fields can have different valid +representations before and after serialization. + +### Candidate public shape + +```ts +const users = db.ref('primary').model('User'); + +const createUser = users.input('create'); // StandardSchemaV1 +const publicUser = users.output({ // selection-aware StandardSchemaV1 + select: { id: true, email: true }, + representation: 'wire', +}); + +const parsed = await createUser['~standard'].validate(requestBody); +const safe = await publicUser['~standard'].validate(responseBody); +``` + +The exact names remain subject to plan lock. The important constraints are that the surface is +target-aware, operation/selection-aware, representation-aware, and derived from a pinned contract +identity. + +### Integration surface + +- Fresh route/action params and bodies; +- form libraries that consume Standard Schema; +- tRPC/oRPC or other request/response boundaries; +- SSR serialization/hydration checks; +- plugin configuration and plugin-owned model inputs/outputs; +- test-fixture/data-factory validation without generated mirror types. + +### Required failure semantics + +- structured issues with target, contract identity, operation/selection path, field path, expected + representation, actual value class, and stable NetScript error code; +- explicit errors for an unsupported contract construct or codec—never silently weakening to + `unknown`; +- stale-contract/cache rejection when the manifest snapshot changes; +- deterministic behavior across interpreted and optional ahead-of-time modes. + +## Plan-lock questions + +1. Which Prisma contract constraints are public/stable enough at RC1 versus adapter-local? +2. Does the result plan expose enough selection/result-shape metadata for output validation without + reconstructing Prisma's type system? +3. Which validation representations are required initially: runtime, JSON/wire, storage, or a strict + subset? +4. How do custom extension codecs contribute Standard Schema behavior and serialization rules? +5. Is output validation opt-in per trust boundary, policy-driven, or both? +6. What is the cache and optional AOT equivalence proof? +7. What performance budget makes runtime derivation acceptable for cold start, edge, and hot paths? + +## Mandatory RFC gates + +- No hand-written or copied model validator in the default path. +- Input and selection-aware output examples compile and execute. +- Standard Schema consumer proof with at least two independent libraries/integrations. +- Contract-space/plugin fields appear automatically. +- Codec and wire-representation fixtures cover dates, decimals, bigints, bytes, JSON, enums, and one + extension-defined type. +- Runtime and optional AOT modes, if both exist, pass the same semantic corpus. +- Contract change invalidates cached validators and stale artifacts deterministically. +- Unsupported constructs fail closed with structured diagnostics. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md new file mode 100644 index 0000000000..73b9b31834 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md @@ -0,0 +1,299 @@ +# Runtime validation source audit + +> Provenance: independent delegated pinned-source audit. RC-tag evidence and post-RC-main evidence +> are explicitly separated below. No web sources were used. The requested `.llm/tmp/prisma-v8-rc1` +> path was absent; the evidence checkout actually inspected was the intact, clean, detached checkout +> at `/home/codex/.local/share/Trash/files/prisma-v8-rc1`, verified at HEAD +> `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` (`v8.0.0-rc.1`). Post-RC comparison used the locally +> available Git object `71e2e0d` only where explicitly labeled. + +## Bottom-line decision + +**Qualified YES to interpretation, NO to contract-only full parity.** A NetScript runtime can +interpret the emitted contract into `StandardSchemaV1` validators for a deliberately bounded algebra +(model/value-object/union/list/dict/nullability/value-set plus known codecs), and can use plan +metadata for a bounded set of projections. That can eliminate generated validator _code_. It cannot +eliminate validator _metadata/contributions_, and it cannot correctly validate Prisma’s complete +create/update/filter/nested-write/aggregate/raw surface from the RC contract alone. Full parity +would require rebuilding the missing operation type system and custom-codec application predicates; +unsupported cases must fail at schema construction, never degrade to `unknown`/pass-through. + +This is **source-level feasibility, not a stable Prisma API commitment**. The relevant common +contract facade is exported by the RC public package, but family IR/plan details remain experimental +and the package itself is `8.0.0-rc.1`. + +## 1. What the machine contract actually contains (RC proof) + +**Envelope/namespaces.** `packages/1-framework/0-foundation/contract/src/contract-types.ts:29-56` +calls `Contract` the canonical in-memory model and carries `target`, `targetFamily`, `roots`, +namespaced `domain`, family storage, `capabilities`, opaque `extensions: Record`, +optional execution, `profileHash`, metadata, control policy; `:36-37` explicitly says persisted +`schemaVersion`/`sources` live only at serialization. `domain-envelope.ts:9-21` gives each +application namespace `models`, optional `valueObjects`, optional `enum`. `cross-reference.ts:5-14` +has namespace/model and optional cross-space `space`; `value-set-ref.ts:25-30` has plane, +namespaceId, entity kind/name and optional `spaceId`. + +**Model/value shape.** `domain-types.ts:5-29` is the runtime value algebra: scalar +`{codecId,typeParams?}`, value-object by name, union of scalar/value-object, and fields with +mandatory `nullable` plus `many?`, `dict?`, `valueSet?`. `:31-39` gives ordered domain enums as +`{codecId,members:[{name,value:JsonValue}]}`. `:41-75` represents reference/embed relations, +local/target fields, cardinality, and N:M junction coordinates. `:77-99` has discriminator/variants, +value objects, model fields/relations/storage/base/owner. There is **no field-level +required/optional flag and no per-value Standard Schema**. + +**Defaults.** `contract/src/types.ts:95-133` defines JSON values and storage column defaults +(`literal` or opaque function expression; author input may be `Date`); `:147-179` defines execution +generators by namespace/table/column and `onCreate`/`onUpdate`. These help determine some +omission/default behavior, but are not a complete create/update input grammar. + +**SQL provider/native detail and constraints.** `packages/2-sql/1-core/contract/src/types.ts:65-75` +maps a model field to `{column,codecId?,nullable?}` and model to `{table,namespaceId,fields}`. +`ir/storage-column.ts:15-25,40-63` carries `nativeType`, `codecId`, `nullable`, `many`, mutually +exclusive `typeParams`/`typeRef`, default/control/valueSet. `ir/storage-table.ts:12-20,34-69` +carries columns, PK, uniques, indexes, FKs, checks and control. `ir/primary-key.ts:4-7`, +`ir/unique-constraint.ts:4-7`, and `ir/foreign-key.ts:5-24` carry names, column tuples, target refs +and referential actions. `ir/sql-index.ts:13-43,63-97` permits column or opaque expression, opaque +partial predicate, unique/type/options. `ir/check-constraint.ts:10-22` only models a structured +column→valueSet check, not arbitrary check SQL. Thus DB structural constraints are present, but +uniqueness/FK/index enforcement is not locally decidable and opaque expressions are +information-losing. + +**SQL contract extensibility.** `ir/sql-storage.ts:65-69,98-118` is namespaced storage with known +`table`/`valueSet` plus open pack entity kinds; `:168-203` deliberately fails unknown storage type +discriminators. `validators.ts:131-177` validates registered entity kinds and fails unregistered +kinds; `:416-442` defines the full ArkType contract envelope. +`sql-contract-serializer-base.ts:40-61,81-99` validates structure then hydrates IR; `:219-240` +serializes all registered namespace entry kinds. Pack entities are therefore runtime-extensible but +only interpretable when their contributor is installed. + +**Postgres native enum.** +`packages/3-targets/3-targets/postgres/src/core/postgres-native-enum.ts:6-12,21-38,49-59` stores +target-only native enum `typeName`, ordered string members and control under +`storage.namespaces[ns].entries.native_enum`. `postgres/src/core/codecs.ts:374-388` says its codec +is string pass-through and does **not** carry members; membership comes from the column +valueSet/native type. NetScript must resolve the valueSet/native-enum entity, not infer membership +from codec ID. + +**Mongo family.** `packages/2-mongo-family/1-foundation/mongo-contract/src/contract-types.ts:37-78` +has model collection/relation storage and one namespaced domain; `:87-107,154-167` has phantom type +maps and falls back to `unknown` without them. `contract-schema.ts:7-80` validates field +algebra/enums/relations; `:82-135` Mongo JSON validator; `:139-211` indexes/collection options; +`:213-238` model discriminators/variants/base/owner; `:245-343` collection storage; `:345-351` value +sets; `:380-413` pack-fragment handling; `:416-458` full envelope. +`ir/mongo-validator.ts:3-10,29-40` stores Mongo JSON Schema/validation level/action; +`ir/mongo-collection.ts:19-24` stores indexes/validator/options/control. A stored Mongo validator is +DB-side collection validation, not automatically the application model/result schema. + +**Type information that is NOT runtime data.** SQL `contract/src/types.ts:90-139` defines +codec/query-operation/field input/output/storage/aggregate maps, but `:207-215` installs them under +an optional phantom key. `framework/emitter/src/generate-contract-dts.ts:179-221` emits those maps +into generated `contract.d.ts`; SQL emitter `src/index.ts:531-541` says defaults use the codec JSON +channel, and `:575-615` renders refined input/output/valueSet/many/nullability types. These type +maps are erased at runtime. This is the strongest evidence against “contract alone has all Prisma +type semantics.” + +## 2. Plans: operation and result-shape sufficiency (RC proof) + +**Common plan.** `framework-components/src/execution/query-plan.ts:15-22` carries only `meta` plus +runtime-absent phantom `_row`; `:25-33` adds nothing in `ExecutionPlan`. +`contract/src/types.ts:223-232` plan metadata is target/family, storageHash, optional profileHash, +lane, arbitrary annotations—no executionHash, contract-full hash, or runtime row schema. + +**SQL.** `relational-core/src/plan.ts:19-22` retains `AnyQueryAst` and params. AST operation kinds +are explicit: `ast/types.ts:1892-1910` insert rows/onConflict/returning, `:1984-2002` update +set/where/returning, `:2051-2065` delete/where/returning, and `:2122-2140` raw SQL. Select +`:1510-1538` retains from/joins/projection/filter/group/having/etc. Projection `:1480-1505` retains +alias, expression, optional `CodecRef`, but `:1484-1488` explicitly says codec is absent for +computed expressions, subqueries and raw aliases. Table source `:346-368` has namespaceId; direct +columns can be resolved to storage. The current decoder confirms the limits: +`packages/2-sql/5-runtime/src/codecs/decoding.ts:28-45` extracts projections and only resolves +codecs; `:164-171` says value validation lives only inside a codec; `:179-186` accepts null and +missing codecs/pass-through; `:198-223` checks only the array container for `many`; `:251-299` +checks missing projected aliases but is not a declarative result validator. Result: operation-aware +input walking is possible for literal/simple AST positions, and direct-column returning/select +output is recoverable by alias+column+codec; computed/raw/subquery/include/aggregate output is not +generally recoverable. + +**Mongo.** `query-ast/src/query-plan.ts:15-20` retains collection, discriminated command and +optional `resultShape`. `result-shape.ts:1-13` is unusually useful: document/unknown, leaf +`{codecId,nullable}`, nested document/array/unknown. Commands `commands.ts:8-179` distinguish +insert/update/delete/find-and/aggregate and retain documents/filter/update/options. Raw commands +`raw-commands.ts:4-156` use opaque `Document`. The decoder proves the shape is a decode hint, not +enforcement: `runtime/src/codecs/decoding.ts:48-60` passes unknown/nonobject; `:65-85` passes +missing codecs; `:100-149` accepts null regardless of `nullable` and passes wrong document/array +types; `:159-175` passes unshaped keys. Thus NetScript can interpret a fully-known Mongo +`resultShape` more strictly than Prisma’s decoder, but must reject `unknown`/raw and needs a +separate operation grammar for filters/updates. + +**Conclusion for plans.** They retain enough metadata for a useful subset and selection-aware +outputs when every leaf is known. They do **not** retain a universal runtime schema equivalent to +phantom `ResultType`/generated operation type maps. + +## 3. Existing Standard Schema use (RC proof) + +`packages/9-public/@prisma/orm-framework/package.json:17-20` depends on +`@standard-schema/spec ^1.1.0` and ArkType; exports include `./contract` and `./contract/types` at +`:50-75`. But `framework-components/src/shared/codec-descriptor.ts:27-54` gives +`paramsSchema: StandardSchemaV1

` specifically for JSON-sourced **codec parameters** and TS +renderers; it has no application/wire/json value schema. `:34-41` is explicit about parameter +validation and `.d.ts` rendering. `Codec` itself (`shared/codec.ts:16-32,34-51`) carries conversions +only. Other Standard Schema occurrences similarly cover config/control/policy/extension parameters. +Contract envelopes are authoritative ArkType schemas (which happen to be Standard-Schema-compatible +implementations), but they validate the **contract document**, not CRUD model data. There is no +existing general model-data Standard Schema surface. + +## 4. Runtime vs driver-wire vs JSON (RC proof) + +Prisma actually has **three** representations, not two: `shared/codec.ts:16-30` defines application +`TInput`, database-driver `TWire`, and target JSON used in artifacts/database-produced JSON; +`:44-51` exposes async encode/decode and sync encodeJson/decodeJson. Therefore a NetScript API +option named `wire` is ambiguous; public boundary modes should be `runtime | json`, reserving driver +wire for internal adapters. + +Postgres examples: + +- BigInt/int8: `postgres/codecs.ts:659-689` application `bigint`, driver string|number|bigint + (canonical write string), JSON decimal string. +- Decimal/numeric: `:860-910` application/output is canonical numeric **string**, driver + string|number, JSON string. It is not Prisma.Decimal in this codebase. +- Date: `:921-960`; timestamps `:971-1036`: runtime `Date`; JSON conversion is target helper/ISO. + Date-only is UTC-midnight canonicalized. +- Bytes: `:1262-1298`: runtime/wire `Uint8Array` (Buffer normalized), JSON/base projection base64. +- JSON/jsonb: `:1471-1547`: application `JsonValue`, wire string|JsonValue, JSON identity. +- Native enum: `:390-410` runtime/wire/JSON string; membership elsewhere. + +Mongo builtins `packages/3-mongo-target/2-mongo-adapter/src/core/codecs.ts:22-71`: ObjectId wire +BSON `ObjectId` → runtime hex string; primitives identity; Date runtime/wire Date ↔ JSON ISO; vector +number array. `:78-86,139-166` lists the standard builtins—no contract scalar codec for +Decimal128/Long/bytes/JSON there. Do not assume provider BSON exports imply supported application +scalar semantics. + +Custom codecs are the hard stop: `mongo-codec/src/codecs.ts:23-42,44-82` requires conversion +functions and JSON roundtrip for non-JsonValue inputs, but no Standard Schema value predicate. +Conversion success is not validation (arbitrary coercion/acceptance is legal). Without a new +contributor-provided `{runtimeSchema,jsonSchema}` (and driver schema only if needed), a custom codec +must be unsupported/fail closed. + +## 5. Contract-space aggregation (RC proof) + +`migration/src/aggregate/types.ts:32-79` defines each app/extension as a separate space with its own +head/hash/contract; `:81-123` exposes an aggregate, sorted extension spaces and an ownership +oracle—it does not merge contracts. `aggregate/loader.ts:23-38,53-74` takes the live app contract +and lazily deserializes extension snapshots; `:77-95` synthesizes app head from storageHash; +`:108-148` loads extension spaces independently. Cross-space relation validation is explicitly +deferred: `contract/src/validate-domain.ts:140-147` skips `CrossReference.space` targets for +aggregate deploy-time verification. + +Implication: validator identity and resolution must include `spaceId`; resolve cross-space +references/valueSets through a verified aggregate, never flatten models by namespace/name. Call +aggregate integrity first; unreadable/missing/mismatched space heads must make validator +construction fail. + +## 6. Hash/version/cache identity (RC proof) + +`contract/src/hashing.ts:14` fixes schema version `'1'`; `:39-43` is SHA-256. Crucially `:74-106` +computes three section hashes only: storage (`target/family/storage`), execution +(`target/family/execution`), profile (`target/family/capabilities`). Domain/roots/extensions are +excluded from all three. `contract-types.ts:21-26,41-55` stores executionHash only with execution, +storageHash inside storage, profileHash top-level. `canonicalization.ts:250-277` can produce +canonical full-contract bytes including roots/domain/storage/execution/extensions/capabilities/meta, +but there is no full-contract hash field. Plan meta only has storage/profile (`types.ts:223-232`). +SQL execution content hashing (`packages/2-sql/5-runtime/src/content-hash.ts:5-43`) keys +storageHash+SQL+params; that is an execution-result cache key, not sufficient validator identity. + +Required derived-validator key: digest(canonical full contract snapshot + schemaVersion + spaceId + +target/family + representation + operation/selection shape + NetScript validator ABI/version + +codec/pack contributor ID/version). Include executionHash when default-sensitive. Do not use +storageHash alone: domain/API/extension semantics can change without storage changing. Codec IDs +conventionally embed `@version`, but a custom contributor registry version/identity should also be +explicit. + +`contract/src/types.ts:238-247` marker has storage/profile hashes, contractJson, `canonicalVersion`, +timestamps etc.; it still supplies no domain/full-content digest. Contract JSON schemaVersion is +serialization-only (`contract-types.ts:36-37`). + +## 7. Mandatory fail-closed cases + +Throw a deterministic `DB_VALIDATION_UNSUPPORTED` while constructing a schema for: unknown codec or +codec without representation-specific value schema; async-only/non-deterministic value validators if +NetScript promises synchronous validation; unknown pack entity kind; unresolved/corrupt cross-space +ref/valueSet; union branches whose runtime identity cannot be discriminated safely; model +variants/discriminators when selection/branch cannot be resolved; opaque SQL +raw/computed/subquery/aggregate/include result with no explicit shape; `selectAllIntent` that cannot +map a unique table namespace; Mongo `resultShape.kind:'unknown'` or any unknown leaf; raw Mongo +`Document`; arbitrary SQL index/check expression (not local data validation); DB-state constraints +(unique/FK/exclusion/etc.); create/update/filter/nested-write semantics absent from a registered +operation contributor; JSON values with custom semantic schemas not contributed. Never mirror Prisma +decoders’ permissive pass-through behavior. + +## 8. Can this be a StandardSchemaV1 interpreter without recreating Prisma’s type system? + +**Yes, if bounded:** implement a small internal validation IR for +scalar/valueObject/union/list/dict/null/valueSet, plus object presence/default policy and +plan-shaped projections; wrap it as `StandardSchemaV1`. Codec/pack contributors supply +representation-specific leaf schemas. This is interpretation, not source generation and not a +reimplementation of Prisma’s TS conditional types. + +**No for full Prisma parity:** create/update/filter operators, nested relation writes, polymorphic +narrowing, aggregates/computed expressions, custom codec predicates and exact projected rows live in +generated type maps/builders/phantoms, not in the runtime contract. Supporting all of them would +recreate Prisma’s operation type system. State the supported subset and fail closed outside it. + +## 9. Smallest public API + conformance matrix + +Recommended API (two methods, no public compiler/cache/generator): + +```ts +const users = db.ref('primary').model('User'); +const createSchema: StandardSchemaV1 = users.input('create', { representation: 'runtime' }); +const resultSchema: StandardSchemaV1 = users.output(planOrSelection, { representation: 'runtime' }); +``` + +Allow `representation: 'runtime' | 'json'`; do not call JSON `wire`. `output` should require a +plan/selection for selection-aware shape; optional whole-model output may be an explicit +`users.output('model', …)` form. Unsupported schema construction throws immediately. Keep +space/model lookup and contract pinning behind `db.ref()`. + +Minimum conformance matrix before claiming support: + +| Axis/case | Expected | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | +| SQL/Postgres + Mongo; each namespace and extension space | Exact coordinate resolution; duplicate names never collide | +| Primitive identity scalars | accept correct, reject wrong, null independently | +| Date, bigint, numeric, bytes, ObjectId, JSON | test runtime and JSON separately with roundtrips and malformed/canonical edge cases | +| Domain enum/valueSet/Postgres native enum | only declared encoded values; order irrelevant to validation; cross-space refs tested | +| nullable / many / dict / value object / union | nested paths and issues; reject `many+dict` (domain validation already rejects at `validate-domain.ts:273-300`) | +| create defaults / update patches | support only operations with explicit presence policy; otherwise unsupported | +| SQL direct select/returning | aliases, missing/extra fields policy, column codec/nullability; namespace qualification | +| SQL computed/subquery/include/aggregate/raw | unsupported absent explicit contributed result schema | +| Mongo fully-known nested resultShape | strict object/array/nullability/leaf enforcement | +| Mongo unknown/raw | unsupported | +| custom codec with runtime+JSON schemas | supported and representation-specific | +| custom codec without either schema | unsupported, never `unknown` | +| unique/FK/index/arbitrary DB check | documented as DB constraints, not claimed as local value validation | +| contract-space broken head/hash/ref | construction fails before validator is returned | +| cache mutation tests | invalidate on domain-only, extension-only, execution-default, codec-version, representation, selection and space changes | +| Standard Schema protocol | sync success, path-rich issues, no throws for invalid user data; construction errors only for unsupported metadata | + +## RC vs post-RC-main and stability + +**RC-tag proof above is authoritative for v8.0.0-rc.1.** The checked-in RC SQL editor schema is +visibly stale: `packages/2-sql/2-authoring/contract-ts/schemas/data-contract-sql-v1.json:71-98` +still describes flat `models` and `storage.tables`, unlike the namespaced runtime types—do not treat +that JSON Schema as authoritative. + +**Post-RC main evidence only:** object `71e2e0d` adds +`packages/2-sql/2-authoring/contract-ts/src/data-contract-json-schema.ts:10-15`, explicitly calling +generated JSON Schema lossy/advisory and ArkType authoritative; `:31-38` accepts unknown pack maps +generically because static JSON Schema cannot know contributed kinds; `:68-110` generates the editor +schema and wire-only keys from the contract schema. This fixes editor-schema drift, not model-data +validation. No post-RC change adds codec value Standard Schemas or a universal result schema. Treat +this as corroborating direction, not RC functionality. + +**Public/stability seam:** `@prisma/orm-framework/package.json:2-7,50-75` is an RC public package +exporting contract surfaces. `packages/0-shared/publish-surface/src/shells.ts:156-170,182-194` says +facades republish `@internal/contract`; `:197-203` describes family/target/runtime republishing. +That makes pinned consumption feasible without importing `@internal/*`, but the detailed +contract/AST layouts are not demonstrated stable. Pin exact Prisma version, probe +schemaVersion/target/family/contributor IDs, and isolate all Prisma decoding behind one NetScript +adapter. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md new file mode 100644 index 0000000000..9d5eddb358 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md @@ -0,0 +1,853 @@ +# Prisma 8 TypeScript-schema and oRPC transfer audit + +> Provenance: independent delegated architecture/source audit for the NetScript DB RFC, completed +> 2026-08-13. Prisma RC source inspected at `/home/codex/.local/share/Trash/files/prisma-v8-rc1`, +> detached at `a76a6c5ad627ceaf1d78e874757cb2ca43e93ff5` (`v8.0.0-rc.1`, 2026-08-07), with +> current-main object `71e2e0d9ee1f306b5a11435cd1973023cb33866a` also inspected. Historical +> evolution was checked against commit `fd88abf4`, redesign PR +> [prisma-next#261](https://github.com/prisma/prisma-next/pull/261) / commit +> [`27ccefc3`](https://github.com/prisma/prisma-next/commit/27ccefc3), and legacy-removal commit +> [`e1e5ab2c`](https://github.com/prisma/prisma-next/commit/e1e5ab2c) / PR #317. NetScript oRPC +> evidence was inspected in `/home/codex/repos/netscript-db-rfc`. + +Legend: **Fact** = directly source-backed; **Inference** = architectural consequence of those facts; +**Recommendation** = proposed NetScript design. + +## 1. Executive conclusion + +**Fact:** The fluent API shown in the early architecture +material—`defineContract().target(...).model(...).column(...).primaryKey(...)...`—was real, but it +is no longer Prisma Next's authoring direction. It was replaced in April 2026 by a model-first +callback API: + +```ts +defineContract( + { extensions: { pgvector } }, + ({ field, model, rel, type }) => { + const User = model('User', { + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + }, + }); + + return { models: { User } }; + }, +); +``` + +The redesign explicitly removed the separate table/column choreography, stringly typed cross-model +references, hard-coded helper vocabulary, and required storage-name repetition. The current API +instead uses typed model tokens, semantic fields and relations, pack-contributed helpers, and a +`.sql(...)` storage overlay. + +**Recommendation:** NetScript should adopt the current native Prisma builder as its authoring +foundation. It should not recreate the old fluent chain or introduce a parallel NetScript model DSL. +NetScript's layer should own composition, policy, contract-space ownership, extension bundles, +artifact automation, migrations, runtime lifecycle, validation, and consumer adapters while +preserving native Prisma builder values and `typeof contract` end to end. + +This is directly analogous to how NetScript already augments oRPC: it starts with the real upstream +builder, applies NetScript policy and conventions, derives types from upstream-native values, and +fans the result into other framework surfaces. + +## 2. Evolution of the Prisma API + +### Historical fluent builder + +**Fact:** Historical source at commit `fd88abf4` contained: + +- `SqlContractBuilder` +- `.target(...)` +- `.extensionPacks(...)` +- `.table(...)` +- `.model(...)` +- top-level `defineContract()` + +The associated table builder exposed `.column(...)`, `.primaryKey(...)`, `.unique(...)`, +`.index(...)`, and `.foreignKey(...)`. + +Primary historical source: + +- [`contract-builder.ts` at `fd88abf4`](https://github.com/prisma/prisma-next/blob/fd88abf4/packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts) +- [`table-builder.ts` at `fd88abf4`](https://github.com/prisma/prisma-next/blob/fd88abf4/packages/1-framework/2-authoring/contract/src/table-builder.ts) + +**Fact:** [PR prisma-next#261](https://github.com/prisma/prisma-next/pull/261), merged on April 3, +2026, documents the redesign. Its “before” example shows the fluent table/model chains; its “after” +example introduces callback-scoped helpers, typed model tokens, inline semantic attributes, and +`.sql(...)`. + +The implementation landed in [`27ccefc3`](https://github.com/prisma/prisma-next/commit/27ccefc3). +The legacy implementation was subsequently removed in +[`e1e5ab2c`](https://github.com/prisma/prisma-next/commit/e1e5ab2c), associated with PR #317. + +### RC1/current authoring model + +**Fact:** ADR 181 now says “No table or column layer.” The relevant source is: + +- `docs/architecture docs/adrs/ADR 181 - Contract authoring DSL for SQL TS authoring.md:7-70` +- Same ADR at `:90-104`, `:108-151`, and `:153-183` + +The ADR's core principles are: + +- semantic model first, storage second; +- pack-driven vocabulary; +- typed local references; +- same canonical downstream contract; +- pure, deterministic canonical output. + +The exact RC1 demo is at: + +- `examples/prisma-8-demo/prisma/contract.ts:1-70` + +It demonstrates: + +- Postgres public `defineContract`; +- an extension pack, pgvector; +- `type.pgvector.Vector(1536)`; +- native enums; +- `field.id.uuidv4String()`; +- temporal presets; +- JSON and optional fields; +- literal defaults; +- typed `rel.hasMany`/`rel.belongsTo`; +- foreign-key authoring using typed column/model references; +- table mapping through `.sql(...)`. + +The Postgres-bound public overloads are at: + +- `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121` + +The callback receives exactly: + +```ts +ComposedAuthoringHelpers; +``` + +and may return native `types`, `models`, and `enums`. The Postgres wrapper delegates to the generic +`buildBoundContract`. + +### Volatility + +**Fact:** The RC release notes explicitly warn that RC respins may break, remove, or rename APIs and +the contract format. See the +[Prisma 8.0.0 RC1 release](https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1). + +**Fact:** Churn has continued after the callback redesign: + +- `extensionPacks` became `extensions`; +- current main adds check-constraint/no-check functionality absent from RC1; +- current main adds generated JSON Schema for `contract.json`; +- authoring and contract-format commits continue to land between RC1 and current main. + +**Recommendation:** The RFC should commit to the architectural direction, not freeze the exact RC1 +overload syntax. Put all Prisma-version-sensitive integration behind a very small adapter package +and pin Prisma tightly during implementation. + +## 3. Exact current builder anatomy + +### Contract definition and lowering + +**Fact:** `ContractDefinition` currently contains: + +- family and target; +- extension packs; +- naming; +- storage hash; +- foreign-key defaults; +- control policy; +- namespaces; +- types; +- models; +- codec lookup; +- enums; +- entity handles. + +Source: + +- `packages/2-sql/2-authoring/contract-ts/src/contract-builder.ts:43-82` + +`buildBoundContract` constructs the composed helper surface before invoking the callback and then +merges returned types, models, enums, and entities: + +- `contract-builder.ts:416-505` + +The callback overload preserves its returned literal types: + +- `contract-builder.ts:437-462` + +### Schema DSL + +The implementation in: + +- `packages/2-sql/2-authoring/contract-ts/src/contract-dsl.ts` + +contains: + +- naming strategies around `:30-35`; +- scalar field state around `:43-76`; +- scalar builder methods—optional, column mapping, list cardinality, literal defaults, SQL defaults, + identity, unique, SQL overlay—around `:162-434`; +- relation state/builders around `:555-700`; +- typed references, including cross-contract-space references, around `:709-757`; +- indexes, foreign keys, and referential actions around `:771-895`; +- SQL constraints around `:965-1137`; +- model attributes and SQL stages around `:1141-1184`; +- typed model builders around `:1370-1563`; +- contract input around `:1659-1738`; +- model overloads and per-model namespaces around `:1741-1796`; +- branded `extensionModel` cross-space handles around `:1813-1850`; +- relation and lazy-token handling around `:1878-2028`. + +**Fact:** The core helper surface only hard-codes `field.column`, `field.generated`, and +`field.namedType`; the richer vocabulary is composed from family, target, and extension packs: + +- `packages/2-sql/2-authoring/contract-ts/src/composed-authoring-helpers.ts:43-102` +- `:132-154` + +Packs may contribute type helpers, field helpers, entity helpers, and index types. Composition +includes collision checks: + +- `composed-authoring-helpers.ts:214-233` +- `:272-306` + +**Inference:** Prisma's own native builder is already an extensible semantic DSL. A competing +NetScript DSL would duplicate the part Prisma has specifically designed as an extension seam. + +## 4. Plugin fragments without a proprietary schema DSL + +### Feasibility + +**Fact:** The callback may return maps of native builder values: + +```ts +{ + types?: Record; + models?: Record; + enums?: Record; + entities?: readonly PackEntityHandle[]; +} +``` + +**Inference:** A NetScript plugin can contribute native Prisma model/type/enum/entity values without +translating them into a NetScript-owned AST. + +A fragment can therefore be a function receiving the exact native helper object and returning a +const-preserved native result: + +```ts +export const workersFragment = definePrismaFragment({ + id: 'workers', + ownership: 'app', + build(h) { + const Job = h.model('Job', { + fields: { + id: h.field.id.uuidv4String(), + status: h.field.text(), + }, + }); + + return { + models: { Job }, + } as const; + }, +}); +``` + +`definePrismaFragment` must be a composition/metadata facility, not a schema language. Its returned +`Job` remains Prisma's model-builder value. + +### Two-phase composition requirement + +**Fact:** Extension packs are part of the scaffold and determine the helper object's static and +runtime shape before the callback runs. + +**Inference:** Arbitrary “register an extension while executing a fragment” composition cannot be +sound. NetScript needs two phases: + +1. Collect fragment manifests: required packs, control/runtime/validation facets, target + requirements, ownership, dependencies and namespaces. +2. Build the final scaffold, obtain the fully composed native Prisma helper object, then invoke + fragments. + +### Literal-type preservation + +**Inference:** A generic `Array.reduce()` into `Record` would erase literal model +names, relation coordinates and field inference. This would repeat an existing problem visible in +NetScript CRUD contracts, where widening to oRPC's `AnySchema` required phantom markers to restore +exact types. + +**Recommendation:** Generate an app-local composition root with explicit const-preserving calls and +object spreads. Do not expose a general runtime registry whose return type is merely +`Record`. + +### Two ownership modes + +**Recommendation:** Make ownership explicit: + +```ts +ownership: 'app' | 'space'; +``` + +- `app`: the host app owns the model fragment and its migration history. The generated app contract + composes it. +- `space`: the plugin owns a complete native Prisma contract space with its own canonical artifact, + migration graph and head. + +Plugin-owned tables should normally use `space`. App-owned fragments are appropriate only when the +application deliberately owns the resulting schema and migrations. + +Prisma's contract-space ADR already defines one `contract.json`, migration graph and head per owner: + +- `docs/architecture docs/adrs/ADR 212 - Contract spaces.md:46-88` +- package and emit layout at `:90-127` +- per-space planning at `:194-228` +- artifact self-consistency at `:251-268` + +Cross-space model handles are already represented by Prisma-native branded values: + +- `packages/3-extensions/supabase/src/contract/handles.ts:1-77` + +## 5. NetScript's oRPC architecture as the direct precedent + +| Existing NetScript/oRPC pattern | Prisma-builder transfer | DB-specific addition | +| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| `baseContract = oc.errors(commonErrorMap)` uses the real oRPC builder | Start with the real public Prisma `defineContract`; apply NetScript presets around it | Persist canonical contract identity and migration ownership | +| Precise types flow from the upstream builder into `implement()` | Preserve exact `typeof contract` into ORM/query/runtime/validation | Preserve family, target, namespace, contract-space and resource identity | +| CRUD factory returns real oRPC route-builder values | Fragment factories return real Prisma model/type/enum/entity values | Fragments must be deterministic and migration-owning | +| Generated const-generic service root creates clients, queries and query utils | Generated DB root creates resources, operations, validators and framework adapters | Must also construct pools, transactions, health and disposal | +| Standard Schema is consumed structurally through `~standard` | Derived database validators implement Standard Schema V1 | Must distinguish create/update/read/wire channels and codec semantics | +| `$context()` supplies typed handler context | `createDatabase(definition, binding)` supplies typed runtime resource context | Runtime URLs, credentials, pools and transaction scopes | +| Soundness tests use compile failures and `@ts-expect-error` | Builder/fragment/namespace/operation compile-time conformance tests | Artifact, migration and provider-capability conformance | +| One source contract fans into SDK surfaces | One database definition fans into ORM, queries, validation, SSR and agents | Canonical artifact emission and migration ledger | + +Exact NetScript evidence: + +- Real upstream oRPC builder and NetScript error augmentation:\ + `packages/contracts/src/application/contract-primitives.ts:1-9`, `:55-89`, `:125-159` +- CRUD generation through real `.route().input().output()` calls:\ + `packages/contracts/crud/create-crud-contract.ts:107-145`, `:278-407` +- The type-erasure workaround that DB composition should avoid:\ + `create-crud-contract.ts:119-145` +- Structural Standard Schema contract:\ + `packages/contracts/src/domain/schema-types.ts:16-52` +- SDK inference from Standard Schema and public `~orpc` metadata:\ + `packages/sdk/src/ports/service-client.ts:7-46`, `:49-124` +- One const-generic service map fanning into three surfaces:\ + `packages/sdk/src/presets/define-services.ts:19-127` +- Generated app-local composition root:\ + `packages/cli/src/kernel/assets/workspace/contracts/v1-aggregate.ts.template:1-20` +- Real upstream builder plus typed worker context and implementation:\ + `packages/plugin-workers-core/src/contracts/v1/workers.contract-definition.ts:70-96`, `:437-573` +- Types derived from native contract values:\ + `packages/plugin-workers-core/src/contracts/v1/workers.contract-types.ts:59-89` +- Typed `$context()`:\ + `plugins/workers/services/src/routers/router-context.ts:27-61` +- Compile-time soundness tests:\ + `plugins/workers/services/src/routers/workers-contract-soundness_test.ts:11-75` +- Runtime definition/lifecycle precedent:\ + `packages/service/src/presets/define-service.ts:216-275` + +**Recommendation:** The Prisma analogue of `baseContract` is not a new model language. It is a +policy-applied native builder entry point or a native contract wrapped in a frozen NetScript +database definition. + +## 6. Candidate public APIs + +These are RFC candidates, not descriptions of existing APIs. + +### Candidate A — native contract plus NetScript database definition + +This is the recommended baseline because it minimizes coupling to unstable Prisma type internals. + +```ts +import pgvector from '@prisma/orm-extension-pgvector/pack'; +import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; +import { defineDatabase } from '@netscript/database/prisma'; + +export const contract = defineContract( + { + extensions: { pgvector }, + namespaces: ['app'], + }, + ({ field, model, type }) => { + const types = { + Embedding: type.pgvector.Vector(1536), + } as const; + + const User = model('User', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + email: field.text().unique(), + }, + }); + + const Post = model('Post', { + namespace: 'app', + fields: { + id: field.id.uuidv4String(), + userId: field.uuidString(), + embedding: field.namedType(types.Embedding).optional(), + }, + }); + + return { + types, + models: { + User: User.relations({ + posts: rel.hasMany(Post, { by: 'userId' }), + }), + Post: Post.relations({ + user: rel.belongsTo(User, { from: 'userId', to: 'id' }), + }), + }, + }; + }, +); + +export const appDatabase = defineDatabase({ + id: 'app', + contract, + migrations: { space: 'app' }, + validation: { profile: 'boundaries' }, +}); +``` + +`defineDatabase` must retain `typeof contract` unchanged. It adds identity and policy; it does not +reinterpret models. + +Runtime creation remains separate: + +```ts +export const db = createDatabase(appDatabase, { + url: env.DATABASE_URL, +}); +``` + +This follows NetScript doctrine: `defineDatabase` is a frozen definition; `createDatabase` performs +environment-sensitive runtime construction. + +### Candidate B — generated native fragment composition + +```ts +export const workersSchema = definePrismaFragment({ + id: 'workers', + ownership: 'app', + extensions: [workersExtension], + build(h) { + const Job = h.model('Job', { + fields: { + id: h.field.id.uuidv4String(), + state: h.field.text(), + }, + }); + + return { models: { Job } } as const; + }, +}); +``` + +A generated app root performs explicit native composition: + +```ts +export const contract = defineContract(scaffold, (h) => { + const workers = workersSchema.build(h); + const app = appSchema.build(h, { workers }); + + return { + types: { + ...workers.types, + ...app.types, + }, + models: { + ...workers.models, + ...app.models, + }, + enums: { + ...workers.enums, + ...app.enums, + }, + } as const; +}); +``` + +The generator resolves dependencies and collisions before emitting this root. It should not use a +type-erasing registry/reduce path. + +Plugin-owned schema instead exports a full space: + +```ts +export const workersSpace = defineDatabaseSpace({ + id: 'workers', + target: 'postgres', + contract: defineContract(/* native Prisma contract */), + migrations: { + owner: '@netscript/plugin-workers', + directory: './migrations', + }, +}); +``` + +### Candidate C — policy-applied native factory + +This is the closest analogue to NetScript's `baseContract`: + +```ts +export const postgresContract = createPrismaContractFactory({ + naming: { + tables: 'snake_case', + columns: 'snake_case', + }, + defaultControlPolicy: 'managed', + extensions: [pgvector], +}); + +export const contract = postgresContract.define((h) => { + // `h` must be Prisma's exact composed helper surface. +}); +``` + +**Kill condition for Candidate C:** Reject it if implementing it requires copying Prisma's +overloads, reaching into private package paths, or re-declaring its generic model/type machinery. In +that case Candidate A is safer and still gives excellent DX. + +## 7. End-to-end type system + +Recommended flow: + +```text +native Prisma TS builder + ↓ +native typed contract value + ↓ +canonical contract + stable content hash + ↓ +NetScript database definition/resource identity + ↓ +typed ORM/query/operation definitions + ↓ +Standard Schema input / output / wire views + ↓ +oRPC · tRPC · Fresh · TanStack · forms · SSR · agents +``` + +### Operation surface + +```ts +const createUser = db.operations.User.create({ + select: { + id: true, + email: true, + }, +}); + +createUser.input; // StandardSchemaV1 +createUser.output; // selection-aware StandardSchemaV1 +createUser.wire; // JSON/SSR representation +createUser.execute; +``` + +It can be plugged directly into oRPC: + +```ts +const route = baseContract + .route({ method: 'POST', path: '/users' }) + .input(createUser.input) + .output(createUser.output); +``` + +A custom query uses the same operation abstraction: + +```ts +export const recentPosts = defineDatabaseOperation(appDatabase, { + input: schemas.recentPosts.input, + output: schemas.recentPosts.output, + query: ({ orm }, input) => + orm.post.findMany({ + where: { createdAt: { gte: input.since } }, + select: { id: true, title: true }, + }), +}); +``` + +### Runtime validation model + +**Fact:** Prisma's codec layer distinguishes input, wire and JSON representations and supplies +encode/decode functions: + +- `packages/1-framework/1-core/framework-components/src/shared/codec.ts:16-51` +- `codec-descriptor.ts:27-55` + +However, Standard Schema currently validates codec constructor parameters, not arbitrary model +values. + +**Fact:** TypeScript authoring helper arguments are not fully runtime-validated: + +- `packages/2-sql/2-authoring/contract-ts/src/authoring-type-utils.ts:32-38` +- confirmed by `packages/2-sql/9-family/test/authoring-field-presets.test.ts:68-87` + +**Fact:** The ArkType JSON extension documents that its no-emit type may be `unknown` and that +encoding does not validate the value. An invalid write can reach the database before failing on +RETURNING decode: + +- `packages/3-extensions/arktype-json/README.md:7-17`, `:40`, `:74-87` + +**Recommendation:** NetScript's Standard Schema layer must be an interpreter over the canonical +contract plus a codec-validation registry. It cannot assume that SQL native types or codec +encode/decode alone provide sound validation. + +Expose at least these separate schemas: + +- `create`: accepted mutation input, accounting for defaults and generated values; +- `update`: partial mutation semantics; +- `read`: full domain output; +- `wire`: serialized JSON/SSR representation. + +Do not collapse those into one “model schema.” + +Selection-aware query output schemas are mandatory. A full-model validator cannot validate a +projection correctly. + +Database-dependent invariants—unique constraints, foreign keys, and arbitrary SQL check +expressions—must not be advertised as synchronous local structural validation. They may be exposed +as optional asynchronous database refinements. + +For SSR: + +1. validate/encode the domain value; +2. validate the wire representation; +3. serialize; +4. validate/decode after hydration. + +For agents, expose an allowlisted operation registry with input/output schemas and policy metadata. +Do not automatically hand agents unrestricted ORM access. + +## 8. Multi-schema, multi-provider and runtime identity + +### Multi-schema gap + +**Fact:** Runtime lowering honors per-model namespaces, but RC1 type inference does not faithfully +preserve them: + +- `packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:644-648` notes the current namespace + limitation; +- `:658-689` places storage models into the default namespace and leaves additional namespace maps + empty; +- `:771-798` similarly constructs field type maps under the default target namespace. + +Current main still retains this limitation. + +**Inference:** NetScript cannot claim sound end-to-end multi-schema inference merely because the +runtime contract accepts namespaces. + +**Recommendation:** Make namespace type/runtime parity an upstream-blocking conformance gate. Do not +mask the problem with NetScript casts or flatten namespaces. + +### Multi-provider + +**Fact:** Prisma configuration currently describes one family/target/adapter/extension set and one +contract/migration location: + +- `packages/1-framework/1-core/config/src/config-types.ts:70-116` + +**Recommendation:** NetScript multi-database support should mean multiple explicitly named database +resources: + +```ts +defineDataPlatform({ + primary: postgresDatabase, + analytics: clickhouseDatabase, + cache: sqliteDatabase, +}); +``` + +Each resource has exactly one provider/target and independent: + +- canonical contract identity; +- runtime binding; +- pool/client lifecycle; +- migration ledger; +- provider capabilities. + +A cross-resource reference is an application-level link, not a foreign key. NetScript must not imply +cross-provider atomic transactions. + +## 9. Migration and artifact boundary + +**Fact:** The migration system is artifact-driven, not source-driven. Migration planning consumes +canonical JSON and operations artifacts, with storage hashes and per-space markers: + +- `docs/architecture docs/subsystems/7. Migration System.md:59-102` +- canonical offline diff at `:127-139` +- content-addressed snapshots and apply artifacts at `:287-318` + +**Fact:** Native no-emit runtime use is supported, but even an in-memory native contract is +serialized/deserialized before runtime use: + +- `packages/3-extensions/postgres/src/runtime/postgres.ts:96-130` +- no-emit versus emitted modes at `:150-166` + +**Fact:** Emit canonicalizes and atomically publishes artifacts: + +- `packages/1-framework/3-tooling/cli/src/control-api/operations/contract-emit.ts:134-149` +- source-provider invocation at `:198-211` +- serialization/canonicalization at `:230-271` +- atomic publication/hash at `:279-302` + +**Recommendation:** NetScript should eliminate manual emit/generate/migrate choreography, but not +erase the artifact boundary. Tooling and production migration application should consume canonical +artifacts, never execute arbitrary app/plugin TypeScript. + +The generated root/build pipeline should automatically: + +1. evaluate native schema authoring in the controlled build phase; +2. canonicalize; +3. verify deterministic hash; +4. emit contract and type artifacts atomically; +5. compare migration head; +6. generate or validate a migration; +7. attach provenance and ownership; +8. make the runtime use the exact verified artifact in CI/production. + +## 10. Extension-bundle design + +**Fact:** Prisma's current pgvector example requires the same logical extension to appear +independently in: + +- schema authoring as `/pack`; +- control/config as `/control`; +- runtime construction as `/runtime`. + +Evidence: + +- `examples/prisma-8-demo/prisma/contract.ts:1`, `:18` +- `examples/prisma-8-demo/prisma-next.config.ts:1-10` +- `examples/prisma-8-demo/src/prisma-no-emit/context.ts:1-11` + +**Recommendation:** NetScript should define one database-extension contribution bundle: + +```ts +defineDatabaseExtension({ + id: 'pgvector', + version: '...', + provider: 'postgres', + authoring: pgvectorPack, + control: pgvectorControl, + runtime: pgvectorRuntime, + validation: pgvectorValidation, +}); +``` + +The generated root fans this single declaration into all Prisma phases. NetScript must verify that +every facet has the same stable extension ID/version and compatible provider capabilities. + +This replaces today's primitive DB contribution: + +- `packages/plugin/src/config/domain/db-schema-contribution.ts:1-7` +- `packages/plugin/src/config/builders/plugin-builder.ts:192-202` +- `packages/plugin/src/config/contribution-merger.ts:3-26` + +It also removes the currently generated instructions to copy a schema and manually run +migration/generation: + +- `packages/cli/src/kernel/assets/generated/plugins/generate-plugin-db-schema-1.ts.template:1-10` + +## 11. Required invariants + +1. The native Prisma contract is the sole schema truth. NetScript has no parallel model AST. +2. `typeof contract` is preserved through database definitions and fragment composition. +3. Authoring identity, canonical contract hash, NetScript resource ID, runtime binding, and + migration space/head are distinct concepts. +4. Schema evaluation is deterministic and independent of environment, filesystem ordering, + randomness, time and network. +5. Environment access is confined to `createDatabase` and application composition. +6. Extension authoring/control/runtime/validation facets must share verified identity and version. +7. Namespace inference must match runtime namespace lowering exactly. +8. Input, output and wire validation are distinct. +9. Every codec used by a public validated operation has a sound validation facet; unsupported codecs + fail closed. +10. Query output schemas are selection-aware. +11. Plugin ownership is explicit, and model/constraint collisions report both owners. +12. Fragment order cannot alter the canonical contract hash. +13. One database definition has one provider/target. +14. Cross-database foreign keys and atomic transactions are not representable. +15. Migration apply executes immutable artifacts, not schema TypeScript. +16. Artifact publication is atomic and includes hash/provenance. +17. Unsupported provider capabilities are either statically unavailable or rejected during + definition, never deferred to a production migration. + +## 12. Anti-patterns to forbid + +- Reimplementing the obsolete screenshot fluent chain. +- A proprietary NetScript schema DSL parallel to Prisma. +- Re-exporting Prisma's builder as though NetScript owns it. +- Copying Prisma private overloads or phantom type maps into public NetScript types. +- Fragment merging through widened `Record` registries. +- Copying plugin PSL/schema files into applications. +- Requiring users to register the same extension separately for authoring, migrations and runtime. +- Executing plugin/application TS during migration apply. +- Generating a separate validation schema that can drift from the canonical contract. +- Treating TypeScript checking as runtime boundary validation. +- Validating a query projection with a full-model schema. +- Flattening namespaces to work around upstream inference bugs. +- Pretending uniqueness, foreign keys or arbitrary SQL checks are purely local validation. +- Reading environment variables or network state during schema construction. +- One mega-contract spanning unrelated providers. +- Exposing unrestricted ORM methods as an agent tool surface. + +## 13. Conformance suite + +The RFC should require at least: + +1. Direct native Postgres contract, both emitted and no-emit. +2. App fragment composition preserving literal model/field/relation types. +3. Plugin-owned contract space with independent migration head. +4. One extension declaration correctly supplying authoring/control/runtime/validation. +5. Required/optional/default/generated/nullable create and update validation. +6. Selection-aware output validation. +7. Date, bigint, decimal, bytes, JSON, enum and vector input/output/wire round trips. +8. Multiple namespaces, including duplicate model names, with exact type/runtime parity. +9. Cross-space handle and ownership validation. +10. Duplicate model/constraint contribution diagnostics naming both owners. +11. Fragment reordering yielding the same canonical hash. +12. Environment/time/random/filesystem/network access rejected during deterministic evaluation. +13. Stale or half-published contract artifacts rejected. +14. Migration apply functioning from JSON/ops artifacts only. +15. Multiple database resources remaining type-, pool- and ledger-isolated. +16. Namespace use on SQLite rejected. +17. Postgres native enum, vector, RLS, indexes and checks. +18. SSR serialization/hydration round trip. +19. The same Standard Schema value consumed by Fresh, TanStack, oRPC, tRPC and form adapters. +20. Output corruption detected at an enabled trust boundary. +21. Prisma RC upgrade contained to the integration adapter. +22. Type-check and editor latency on a 500-model representative application. +23. Agent operation allowlisting and provenance. +24. Invalid helper arguments rejected even from JavaScript/untyped/generated code. +25. Invalid custom JSON input rejected before the database write, not after commit/RETURNING. + +## 14. Kill criteria + +Stop or redesign the proposal if any of these remain true: + +- Native builder integration requires Prisma private import paths. +- The wrapper or fragment mechanism widens away Prisma's native inference. +- Multi-schema no-emit types remain wrong and NetScript can only hide the bug with casts. +- Schema evaluation cannot be made deterministic and build-phase-isolated. +- Extension facets cannot be identity/version checked. +- Canonical contract plus codec facets cannot produce sound value validators. +- Custom codecs silently become `unknown` rather than failing closed. +- Runtime and AOT validators cannot pass semantic-equivalence tests. +- Plugin migrations require arbitrary TypeScript execution during apply. +- Type-check/editor latency breaches the agreed budget. +- Migration hashes/receipts cannot bind applied migrations to exact contract artifacts. +- Prisma RC churn repeatedly leaks as public NetScript breaking changes. +- Multi-provider abstraction collapses into a lowest-common-denominator ORM surface. +- Invalid input can be committed before validation completes. +- Contract-space ordering/dependencies cannot safely represent NetScript plugin dependencies. + +The architectural stance should be: **native Prisma model-first authoring, NetScript-owned +composition and operational system**. That preserves Prisma's strongest new idea—the TypeScript +contract as the source of a complete inferred model—while putting NetScript's effort into the gaps +that actually determine framework DX: zero-manual composition, deterministic artifacts, migration +ownership, extension bundles, runtime lifecycle, validation, and all consumer surfaces. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md new file mode 100644 index 0000000000..e461eedeed --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/grok-rfc-adversarial-review.md @@ -0,0 +1,90 @@ +### Route receipt + +| Field | Value | +| --- | --- | +| Requested | OpenCode via OpenRouter, `openrouter/x-ai/grok-4.6`, variant `high` | +| Observed | OpenCode (`OPENCODE=1`, PID `2056871`); model `openrouter/x-ai/grok-4.6` from runtime identity. Variant `high` is **not** independently echoed into the session identity string; observed model does not differ. | +| Session | OpenCode PID `2056871`; receipt `.llm/tmp/grok-rfc-adversarial-review-receipt.jsonl` (`msg_ffc9bb764001ebDsKVA7KpWQuK` …) | +| Evaluated commit | `5dfc4e8eb3988818fc81c6f5dc2856d551443249` (`docs(rfc): consolidate database architecture draft`) | +| RFC identity | blob `f46040d8b89f94809c61371da478aeeffb68c9db`; sha256 `20c1a6b719a2b523be61a4dff4a33cc9006273a34009a3d0467d77afa98b5e22`; **11,205 words**. Worktree bytes **identical** to `5dfc4e8eb`. HEAD is `be83301c6` on a clean `docs/database-architecture-rfc` tree; RFC file itself is unchanged. | +| Required files read completely | `rfcs/0000-database-architecture.md`; `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md`; `reviews/root-rfc-review.md`; `reviews/qwen-rfc-focused-review.md` | +| Qwen artifact | **present** at `.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md` | +| Extra inspection | `research/prisma-8-deep-dive.md:430-469`; `research/architecture-plan-synthesis.md:265-317`; `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:45-113`; pinned Prisma RC1 `define-contract.ts:40-122`, `contract-types.ts:644-691`; doctrine `02-public-surface.md:217-236` | +| Subagents | **None.** One Grok parent session. | + +### Verdict + +**`PASS_WITH_REFINEMENTS`** + +The checkpoint is one architecture: native Prisma authoring, thin NetScript definition, distinct artifacts, Prisma-8/PostgreSQL-only adapter, fail-closed validation, and a data-safe clean break. No blocker remains; eight refinements must be dispositioned so the flagship examples and a few authority sentences cannot be implemented as a merged-contract or Prisma-import leak. + +Counts: **0 blocker**, **8 refinement**. + +### Findings + +| ID | Class | Axis | RFC lines | Violated invariant/decision | Consequence | Smallest correction | Offset deletion | +| -- | ----- | ---- | --------- | --------------------------- | ----------- | ------------------- | --------------- | +| GR-01 | refinement | 5 | 169–171, 299–311, 334, 371–373, 713–714 | `@netscript/*` examples executable as written; binding is a generated **value** | `export declare const primaryBinding` / `PRIMARY_MANIFEST_DIGEST` emit nothing; `runtime.bind` and `.ref()` are unlinkable. Confirms Qwen QF-01 on this checkpoint. | Emit a real value module (or `.d.ts` + runtime sibling) that constructs the binding and digest. | Delete the two `declare` lines and the “GENERATED” header’s implied ambient style (~25 w). | +| GR-02 | refinement | 2 | 492–507 vs 661–665 | Only the adapter imports Prisma **runtime/control**; apps/plugins import the public **authoring** builder | Step 7’s bundle, if authored in app/plugin code, must import `/control` and `/runtime`. Kernel `defineDatabaseExtension` cannot name those Prisma types under isolatedDeclarations. Confirms QF-02. | One sentence: bundles are defined by the adapter/extension-pack publisher; facets are opaque handles. Show the import from `@netscript/database-prisma-postgres`. | Drop “Today a single logical extension…” (488–491) (~45 w). | +| GR-03 | refinement | 1 | 299–307, 765–767; identity 626–631 | Plugin spaces are separate contracts/artifacts; Prisma aggregate **does not merge** contracts (RC1 `aggregate/types.ts`, deep-dive 456–458) | Flagship binding is `QueryOf` from `./primary/contract.d.ts` with **one** `cs:` hash. A reader will merge app+auth into one target contract, breaking space identity. | Binding is per-target; query/validator types are **per-space**. Path `primary/app/contract.d.ts`; header lists each space snapshot; `ref({space})` is the query key, not a merged `AppContract`. | Delete “One generic model is used everywhere…” (313–318) after folding the three parameters into the corrected example (~70 w). | +| GR-04 | refinement | 1 | 603–620, 776, 800–802 vs 692–699 | Definition is “never consumed by … control”; catalog lists `compose` as a control `pure` op | Implementers will put `compileDatabase` in `-control` or pass definitions into apply/verify. | Authority cell: only `compose`/`compileDatabase` (A4, catalog-projected) consumes a definition; runtime/apply/verify consume the manifest. | Shrink the five-values prose (614–620) to a pointer at the authority table (~40 w). | +| GR-05 | refinement | 3 | 479–484, 965–968, 981–986 | Detach-and-retain must not invite later DDL; `adopted` is also the post-adopt manage-forward policy | Same row says adopted is Planned/Mutated **Yes**. After uninstall, a literal reading allows planning retained plugin tables. | Tombstoned retain: verify-only, not planned/mutated, until a new space re-adopts. Keep adopted-from-`db adopt` as manage-forward. | One clause; delete the second “ownership is downgraded…” repeat (484 vs 985) (~25 w). | +| GR-06 | refinement | 3 | 544–556, 852–856 | Per-space statuses exist; run-level `partial-success` is **target**-mixed only | Mixed spaces on one locked target have no rollup. | A target is `succeeded` iff every requested space succeeded; mixed spaces → that target failed/cleanup-required/outcome-unknown; only mixed **targets** yield run `partial-success`. | Drop mermaid-duplicated “diagram teeth” sentences (839–841) (~40 w). | +| GR-07 | refinement | 5 | 247–256 vs 328; 331, 520–531 | One implementable API; examples executable | `prismaPostgres({ minVersion: 15 })` vs `providers: [prismaPostgres]`; `connections` / `runId` / `policy` unbound (QF-03). | One sentence: factory vs configured descriptor. Bind or mark elisions. | No net add: replace the dual call sites’ surrounding prose. | +| GR-08 | refinement | 7 | see ledger | 11,205 > 10,000; repeated refusals/proof | Editors will re-expand during disposition. | Apply the deletion ledger; do not add sections. | **≈1,320 words** below. QF-04 (line 181: prefix “Prisma RC1”) and QF-05 (899–901: split paramsSchema vs conversion channels) fold here (~15 w replace, not add). | + +### Axis verdicts + +| Axis | Verdict | Strongest negative evidence | Result | +| --- | --- | --- | --- | +| 1 Abstraction integrity | **FAIL** | GR-03 one `AppContract`/`cs:` vs unmerged spaces; GR-04 compose vs “control never consumes definition.” Pipeline, six-value authority, preview≠plan, and definition↛runtime otherwise hold. | Correct the binding shape and authority sentence. Architecture stands. | +| 2 Kernel vs Prisma leakage | **PASS** | GR-02 is example placement, not a kernel import. No query DSL, no re-export, adapter subpaths = root+`/binding`, `QueryOf` stays adapter-local, “provider-neutral” ≠ portable queries. | State bundle ownership. | +| 3 Artifact / recovery safety | **PASS** | GR-05/GR-06 are rollup/policy precision. Closed target set, plan bindings, lock `(target, physical DB)`, `outcome-unknown`, inspect-before-resume, receipt lookup, marker-only adopt, no false rollback — hold. | Two sentences. | +| 4 Plugin / multi-space / multi-DB | **PASS** | One `ObjectKey` owner; pinned mirrors; grant-closed augmentation; physical collisions refused; non-default namespace refused; cross-target relation ≠ same-target cross-space. R1 still fixed. | GR-03 is the query-type consequence, not an ownership hole. | +| 5 Public API / DX / types | **FAIL** | GR-01/GR-02/GR-07. `defineDatabase` target-key check, `const` inference, distinct `TTx`, request session without `transaction`, fail-closed `input`/`output`, `runtime\|json` — sound. | Fix examples; do not change the type model. | +| 6 Feasibility / gates | **PASS** | W0–W11 are ordered; `-runtime`/`-control` do not import each other or a provider; RC pin/allowlist/namespace/JSR/slow-types are gated; kill list in the plan is strong enough. Type-check budget lives in the plan, not the RFC — acceptable after consolidation. | No RFC rewrite. | +| 7 Editorial economy | **FAIL** | Still 1,205 words over the preferred cap; refusals, kill lists, and market lessons are restated. | Net-delete; do not add chapters. | + +### Net deletion ledger + +| Cut | Lines | Est. words | Why safe | +| --- | ---: | ---: | --- | +| Motivation repair/`resolveTarget` mechanics; keep analytics collision + non-atomic conclusion | 85–102 | 90 | Linked current-state audit | +| Prisma-8 “attacks pain points” hexad | 127–139 | 35 | Mirrors Motivation | +| “Three things NetScript will not do” | 222–226 | 45 | Alternatives table | +| “What you stop doing” octad; keep refusal table | 578–584 | 65 | Restates guide | +| Five-values prose (GR-04 pointer) | 614–620 | 40 | Authority table 771–782 | +| Composition-validates laundry list | 789–794 | 35 | Guide refusals | +| Diagram-teeth / catalog-projection repeats (GR-06) | 838–841, 857–859 | 55 | Mermaid + Step 8 | +| ValidationIR positive paragraph | 913–919 | 35 | Fail-closed list remains | +| Refusal-boundary no-compat/no-re-export | 1006–1013 | 80 | 661–665 and 1126–1131 | +| Drawbacks EA/indirection/conformance overlap | 1017–1035, 1053–1056 | 80 | Summary + plan risk register | +| Why-this-shape obs. 3–4 lists | 1062–1073 | 65 | Deep-dive + 722–723 | +| Scope-law paragraph | 1115–1118 | 35 | D-31, summary, alternatives | +| Prior-art lesson restatement | 1190–1206 | 95 | 1092–1113; keep oRPC 1208–1212 | +| Unresolved implementation sweep + locked-topics opener | 1216–1233 | 130 | Plan already linked | +| Future policy-factory bullet | 1264–1267 | 25 | Root removed it from v1 | +| Market-lesson tighten + Step 5 isolation list + target-key trailing fallback sentence | 282–290, 432–436, 1092–1113 | 75 | Identity table + linked analysis | +| GR-01/02/03 local swaps | 313–318, 488–491 | 95 | Replaced by shorter corrections | +| **Gross delete** | | **≈1,180** | | +| **Gross add** (GR-01 value emit, GR-02 sentence, GR-03 space-keyed header, GR-04/05/06 clauses, GR-07 factory sentence, QF-04/05 wording) | | **≈140** | | +| **Net** | | **≈ −1,040 to −1,200** | Lands ~10,000–10,160. A second pass on Motivation 114–123 incident-table prose (−80) crosses 10,000 without touching APIs. | + +**Do not cut:** all code blocks except GR-01/GR-03 rewrite; refusal table 586–599; authority + identity tables; four inference rules + bind soundness seam; namespace withhold 989–1000; fail-closed inventory + mandatory-boundary rules; mermaid apply diagram; adoption steps, pre-cutover list, rollback table; alternatives table; incident table; JSON/`db.plan.stale` examples; official Prisma/comparator links; D-01–D-47 and W0–W11 (stay in the plan). + +### Sound claims not to reopen + +Checked on this checkpoint / pinned RC1 / current NetScript source: + +1. `workspace-resolver.ts:51` collapses workspaces to `database/`; `resolveTarget` defaults only when one target is enabled and throws `Unknown database target: (default)`; engine map is a four-way `switch` (`:97–113`). +2. RC1 `defineContract(scaffold, callback)` exists with `const` generics and `ComposedAuthoringHelpers` (`define-contract.ts:82–104`). +3. Authoring storage maps put every table under the default namespace and leave non-default maps as `Record` (`contract-types.ts:644–691`). D-37 is evidenced. +4. Prisma aggregate exposes per-space contracts and does **not** merge them (deep-dive 456–458). Do not “fix” GR-03 by inventing a merged `AppContract`. +5. Codec `paramsSchema` validates parameters; three representations are **conversion** channels (deep-dive 430–439). Public `runtime \| json` remains correct. +6. oRPC-only `--allow-slow-types` carve-out is doctrine (`02-public-surface.md:217–231`). Do not extend it to database packages. +7. Root R1–R10 are present and consistent (namespace, target-key site, structurally offline control, pure `sign`, one `(TId,TQuery,TTx)` model, `input`/`output`, space vs fragment, honest `TTx`, receipt lookup, explicit adopt set + proved marker removal). +8. Qwen QF-01–QF-05 still exist in `5dfc4e8eb`; not silently fixed. + +### Final gate statement + +RFC may proceed to author/editor disposition of GR-01–GR-08; this is not final acceptance — Fable 5 high remains the last substantive gate. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md new file mode 100644 index 0000000000..1edc793cf4 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/qwen-rfc-focused-review.md @@ -0,0 +1,83 @@ +# Qwen 3.8 Max — focused review: database architecture RFC + +## Route receipt + +| Field | Value | +| --- | --- | +| Requested model | `qwen/qwen3.8-max` | +| Requested effort | `max` | +| Evaluated commit | `5dfc4e8eb` (`docs/database-architecture-rfc`); RFC file verified byte-identical to commit | +| Files read completely | `rfcs/0000-database-architecture.md` (11,205 words); run `plan.md`; `reviews/root-rfc-review.md`; `research/typescript-schema-orpc-audit.md`; `research/runtime-validation-source-audit.md`; `research/prisma-8-deep-dive.md`; `research/market-analysis.md`; `research/planned-jsr-audit.md` | +| Prisma source inspected | **Yes** — pinned checkout `.llm/tmp/prisma-v8-rc1`, verified at tag `v8.0.0-rc.1` (commit `a76a6c5`). Paths read: `packages/2-sql/2-authoring/contract-ts/src/contract-types.ts:630-704`; `packages/3-extensions/postgres/src/contract/define-contract.ts:40-125`; `packages/2-sql/1-core/contract/src/types.ts:85-140, 200-220`; `packages/9-public/@prisma/orm-postgres/package.json` (export count). All inspections are **RC1 evidence**; no post-RC object was needed — the RFC's post-RC statements are correctly labeled as churn enumeration and were checked against the deep-dive's labeled post-RC table only. | +| NetScript source inspected | `packages/cli/src/kernel/adapters/database/workspace-resolver.ts:40-109`; doctrine `06-archetypes.md:209`, `02-public-surface.md:217-231`, `09-anti-patterns-and-fitness-functions.md:165` | + +## Verdict: `PASS_WITH_CHANGES` + +No decision, invariant, or refusal in D-01–D-47 is violated; the five findings are example-level and wording-level. One high finding (a flagship example that is not executable as written) must be fixed before the final refinement pass. + +## Findings + +| ID | Sev | RFC line(s) | Violated decision/invariant | Why it matters | Smallest correction | +| --- | --- | --- | --- | --- | --- | +| QF-01 | high | 309–310; consumed at 324, 334, 371–373 | Example-status block (169–171: `@netscript/*` examples "executable exactly as written"); one implementable API | `primary.binding.ts` shows `export declare const primaryBinding: AppBinding<…>` and `export declare const PRIMARY_MANIFEST_DIGEST` — ambient declarations emit **no runtime value**. But `primaryBinding` is imported as a value and called: `runtime.bind(primaryBinding)` (334) and `primaryBinding.ref({space:'app'}).model('User')` (371–373), and the digest is load-bearing for startup refusal (713–714). As written the module exports nothing and the imports throw at link time — the generated-binding example, the RFC's center of gravity, is pseudocode with incompatible symbol roles. | Rewrite the generated file as an emitted value module (e.g. the emitter constructs `primaryBinding` and the digest constant), or split into a `.d.ts` plus a runtime module the composition root imports. ≤3 example lines; no API change. | +| QF-02 | medium | 492–507 vs 661–665 | Dependency law: "only the adapter imports Prisma runtime or control modules"; application/plugin modules may import only the public **authoring** builder | The Step 7 extension bundle carries `control` and `runtime` facets. If the bundle is authored in app/plugin code as the example implies, that code must import Prisma `/control` and `/runtime` modules — forbidden by the RFC's own law. The RFC never says where `defineDatabaseExtension` bundles are defined, so the example can force a forbidden dependency (an implementation-gate question for the W3 import allowlist). | One sentence: extension bundles are defined by the adapter/extension-pack publisher inside the controlled build (facets opaque to consumers), or explicitly widen the law to allow controlled-build extension modules the public facet subpaths under the W3 allowlist. | +| QF-03 | low | 331, 335, 520–531 | Example-status "executable exactly as written" | The composition-root and control-journey examples (both presented as complete files with `@netscript/*` imports) leave `connections`, `runId` (×4), and `policy` unbound; `AccountStore`/`PrismaAccountStore` are prose-explained but not marked elided. Undercuts the executability claim the RFC makes of itself. | Declare the values (`const runId = …`, `const connections = fromEnv(…)`, `const policy = …`) or mark elisions with a comment. ~4 lines. | +| QF-04 | low | 181 | Claim attribution discipline | `packages/3-extensions/postgres/src/contract/define-contract.ts:46-121` is a path in the **Prisma** checkout but appears in the guide without attribution; every other citation in the section is a NetScript repo path. A reader will look for it in this repo. | Prefix "Prisma RC1" or link the deep dive. One phrase. | +| QF-05 | low | 899–901 | Audit-faithful wording (runtime-validation-source-audit §3/§4) | "Prisma's own Standard Schema usage validates codec parameters rather than model values, across three representations" conflates two distinct audit facts: `paramsSchema` validates JSON-sourced codec *parameters*; the three representations are *conversion* channels, not all validation channels. The derived conclusion (`runtime \| json` public, wire internal) is unaffected but the sentence overstates its premise. | Split: Prisma validates codec parameters, not model values; its codecs define three conversion representations, of which the driver-wire one stays adapter-internal. | + +## Six-axis verdict + +| Axis | Verdict | Negative evidence | +| --- | --- | --- | +| 1. TypeScript inference & API coherence | **FAIL** | QF-01/QF-03. The type model itself is sound: `defineDatabase`'s `const` generics with `DatabaseSpaceDefinition, unknown>` make `target: 'primry'` error at the right call site (verified against R2's requirement); one 3-parameter generic `(TId, TQuery, TTx)` is used consistently for `AppBinding`/`ProcessTargetSession`; `RequestTargetSession` has no `TTx` and no `transaction`; transaction surface is honestly deferred to W4 (358–363); no widening, private imports, re-export, or query DSL found in any signature. | +| 2. Standard Schema & trust boundaries | **PASS** | `input`/`output` semantics, `runtime \| json`, whole-model `'model'` form, construction-time `DB_VALIDATION_UNSUPPORTED` with coordinates, path-rich issues for invalid values, mandatory external boundaries, cache-key composition, codec value-schema requirement — all match the pinned-source audit. No full-parity claim (58–60, 408–414); no generated-validator repair pipeline (1084 row). Defect: QF-05 wording only. | +| 3. Control, recovery, artifact authority | **PASS** | Pure `createDatabaseControl` has no connection resolver (518–520; structural, not promised); `sign` is pure and lock-free; six-value authority table is disjoint; `outcome-unknown` on transport loss; resume = lookup (append + lookup by `RunId`/`ReceiptId`/resume token, source/sink split allowed); aggregate outcome when no target succeeds is failed/refused/outcome-unknown, never `partial-success` (854–856); every requested target appears with status; plan expiry/staleness/revocation codes present. No silent-subset or atomic-cross-target path found. | +| 4. Migration & plugin safety | **PASS** | One `managed` owner per `ObjectKey`; identical text is still a conflict; physical name collisions refused while the namespace capability is withheld (472–478, 592) — R1 resolved consistently across guide, refusal table, and reference; pinned mirror gives package-free apply/verify with `db.space.skew`; augmentation is grant-closed with explicit denies; detach-and-retain is the only guaranteed removal; adoption is marker-only over an explicitly selected target set with per-target statuses and blocked cutover; rollback row 2 promises marker removal only where provider semantics prove it. No accidental data-mutation claim found. | +| 5. Package & prospective JSR surface | **FAIL** (narrow) | Sole defect is QF-02 (last clause of this axis: whether any example forces a forbidden dependency). Everything else verifies: exact A1/A4/A3/A2/A2/A6 graph matches the plan; `-runtime`/`-control` never import each other or a provider; adapter subpaths are exactly root + `/binding`; inferred typing terminates app-local; `isolatedDeclarations` reasoning for the fragment-publish ban is correct; no slow-types waiver (669–671, 1088); no actual-publish-readiness claim anywhere in the RFC. | +| 6. Market/upstream claims & reader economy | **PASS** | All load-bearing upstream claims carry direct official links; RC1/post-RC separation is maintained (143–156); the 138-export-surface claim and the EA/scorecard claims are RC1-pinned and verified; comparator treatment credits each product before stating the limitation (no straw man); the NetScript row in the market matrix is labeled design-target, and the RFC never claims more. Defect: ~1,200 words of redundancy remain (ledger below). | + +## Deletion ledger (≥1,200 words; no decision, invariant, refusal, or API contract removed) + +| # | Location (lines) | Cut | Words | +| --- | --- | --- | ---: | +| 1 | 1006–1013 | Refusal boundary: delete the no-compat enumeration (restated verbatim at 1126–1131) and the no-re-export clause (restated at 661–665); keep only the no-text-patched-source/no-arbitrary-TS and no-implicit-target clauses | 80 | +| 2 | 1222–1233 | Unresolved questions: compress the implementation-time enumeration to the three largest open decisions (W3 allowlist/namespace; W5/W10 signatures; W10 window) — the full sweep is already linked in the plan (1219–1220) | 115 | +| 3 | 1190–1206 | Prior art: the five adopted lessons are already stated with links at 1092–1113; compress to link + one "no product is a template" sentence; keep the oRPC-precedent sentences (1208–1212) | 95 | +| 4 | 578–584 | "What you stop doing" prose: the eight-item enumeration restates Motivation and earlier guide steps; keep the refusal table and one intro sentence | 65 | +| 5 | 85–102 | Motivation defects: keep the `db add postgres --name analytics` counter-example and the non-atomic conclusion; move `resolveTarget` mechanics (`:66-91`, `PrimaryDatabase`) and the seven-step repair enumeration behind the linked current-state audit | 90 | +| 6 | 127–139 | "That attacks NetScript's pain points at the root" — compress the six-item mirror of Motivation to one clause | 35 | +| 7 | 913–919 | `ValidationIR` coverage paragraph: one sentence naming the supported algebra (the fail-closed inventory at 920–928 already carries the negative half) | 35 | +| 8 | 1115–1118 | Scope-law paragraph: already stated as D-31, summary non-goal (55–57), and alternatives row (1087); reduce to one sentence | 35 | +| 9 | 838–849 | Diagram-teeth prose: drop what the mermaid diagram already encodes (outcome-unknown edge, inspect-before-resume); keep never-replay, checkpoint granularity, lock scope, certified-lock refusal | 45 | +| 10 | 789–794 | Composition-validates prose: keep the determinism gate and "every invariant has a diagnostic"; drop the validation list duplicating guide refusals | 35 | +| 11 | 1053–1056 | Conformance-cost drawback: merge one sentence into the Early-Access drawback | 30 | +| 12 | 1029–1035 | Indirection drawback: drop the closing comparator ("four packages where a less disciplined design would ship one") | 30 | +| 13 | 1024–1028 | Early-Access drawback: mitigation list overlaps 157–163 and the risk register; compress | 30 | +| 14 | 866–870 | Serverless-precedent sentence: compress to a subordinate clause | 30 | +| 15 | 614–620 | Five-values paragraph: the authority table (771–782) re-introduces the same values with roles; shrink to a forward pointer | 30 | +| 16 | 222–225 | "Three things NetScript will not do": restated in summary non-goals, alternatives rows, and refusal boundary; one sentence pointing to alternatives | 45 | +| 17 | 1062–1073 | Why-this-shape: observation 3's operational-gap list is duplicated proof (lives in the deep dive); observation 4 restates 722–723 and 1037–1039 | 65 | +| 18 | 675–677 | Definition-layer wrap intro: overlaps Step 2 prose (276–280) and the contract-identity rule (703–704) | 30 | +| 19 | 741–749 | Two-phase paragraph: trim the phase-1 enumeration, keep the two-phase rationale and the no-registry/no-reduce law | 25 | +| 20 | 852–859 | Saga paragraph: the catalog-projection sentence restates Step 8's opening (510–512); keep freshness-gate/executed-examples clauses | 30 | +| 21 | 55–60 | Summary non-goals second sentence: compress the withheld-capability enumeration (each is detailed in Drawbacks/Unresolved/refusal table) | 25 | +| 22 | 282–290 | Target-key prose: drop the trailing "no fallback chain anywhere" sentence (restated at 1140–1141) | 20 | +| 23 | 1092–1113 | Market lessons: tighten each bullet ~8 words against the linked analysis | 40 | +| 24 | 432–436 | Step 5 isolation enumeration: compress to a pointer at the identity table | 15 | +| 25 | 1264–1267 | Future: policy-factory bullet — removed from v1 narrative per root review; its kill condition restates 1266–1267's own guard | 25 | +| 26 | 1216–1220 | Unresolved opening: trim the locked-topics enumeration | 15 | +| 27 | 1017–1022 | Drawbacks opening: trim ~20 words of restated scope | 20 | +| | | **Total** | **≈1,240** | + +**Must not be cut:** all code blocks except the QF-01 rewrite; the refusal tables (586–599) and refusal boundary pointer; the authority and identity tables; the four inference rules and the soundness-seam paragraph; the namespace paragraph (989–1000); the fail-closed inventory and mandatory-boundary rules; the mermaid diagram (the one retained lifecycle diagram); the adoption step table, pre-cutover list, and rollback table; the alternatives table; the incident table; the operational-journey JSON/error examples; and all direct official links. With these cuts the RFC lands at ≈9,965 words. + +## Claims checked and found sound (do not reopen without new evidence) + +1. `@prisma/orm-postgres` publishes **138** top-level export subpath keys at the RC1 pin (RFC 149–151) — counted from `package.json` at tag `v8.0.0-rc.1`. +2. Authoring type maps lump all models under the default storage namespace and leave non-default namespace table maps empty (`contract-types.ts:644-691`, RFC 990) — verified verbatim; the withheld namespace capability (D-37) rests on accurate evidence. +3. The `defineContract(scaffold, callback)` overload exists with `const` generics preserving returned literal types; the callback receives `ComposedAuthoringHelpers` (RFC 179–182) — verified. +4. SQL field/operation/codec/aggregate type maps are installed under an optional phantom key (`__@internal/sql-contract/typeMaps@__`) — the "not runtime data" premise of bounded validation (RFC 893–896) — verified. +5. `workspace-resolver.ts:51` computes `join('database', provider.dirName)`; `resolveTarget` defaults only when exactly one target is enabled, never consults `NetScript.PrimaryDatabase`, and throws `Unknown database target: (default)` (RFC 86–91); engine selection is a four-engine `switch` (`:97-109`) — all verified against source. +6. Doctrine codifies plain `*.prisma` plugin fragments (A5, `06-archetypes.md:209`) and the oRPC-only slow-types carve-out (`02-public-surface.md:217-231`); AP-24 exists (`09-…:165`) — RFC 92–94, 667–671 are sound. +7. RC1 vs post-RC wording discipline (RFC 143–156) holds; post-RC churn items are correctly attributed as post-tag changes with linked evidence in the deep dive. +8. Root-review corrections R1–R10 are all present and consistent in the committed text (namespace contradiction, target-key location, structural offline control, pure `sign`, one binding generic, validation vocabulary, contribution modes, transaction honesty, receipt lookup, adoption closure). diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md new file mode 100644 index 0000000000..f8580dde92 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-rfc-review.md @@ -0,0 +1,248 @@ +# Root review: database architecture RFC + +## Review receipt + +| Field | Value | +| ---------------- | ------------------------------------ | +| Reviewer | Root Codex supervisor | +| Date | 2026-08-13 | +| Evaluated commit | `05e5fbac2` | +| Evaluated file | `rfcs/0000-database-architecture.md` | +| Raw size | 28,194 words; 3,140 lines | +| Verdict | `REVISE_CONSOLIDATE` | + +The draft is evidence-complete and contains the approved architecture, but it is not an acceptable +reader-facing RFC. The owner explicitly rejected a book-length result. The next version must be a +specific architectural decision document whose center of gravity is the end-state API and developer +experience. Research, source traces, implementation gates, and review provenance should be linked, +not recopied. + +Target **8,000–10,000 words**. Hard ceiling **12,000 words**. The final document should be useful to +an implementer who reads it once and to an owner who wants to decide whether the proposed database +story is the right one. + +## Consolidated draft receipt + +| Field | Value | +| ---------------- | ------------------------------------------------------------------- | +| Reviewer | Root Codex supervisor | +| Date | 2026-08-13 | +| Evaluated commit | `5dfc4e8eb` | +| Authoring lane | Native Claude Code `claude-opus-5`, high, session `de518f07-68e0-…` | +| Evaluated file | `rfcs/0000-database-architecture.md` | +| Size | 11,205 words; 1,296 lines | +| Verdict | `PASS_TO_FOCUSED_REVIEW` | + +Root read the complete consolidated RFC, not only the diff. The rewrite removes 60% of the raw +draft, deletes the appendices and inline evidence taxonomy, retains one lifecycle diagram, links the +research corpus, and moves the center of gravity to the native contract, NetScript definition, +app-local binding, Standard Schema, plugin-space/extension, runtime, and plan/apply DX. Findings +R1–R10 below are resolved in the committed text. + +Root made three narrow correctness corrections before accepting the checkpoint: + +- downstream runtime now consumes the compiled manifest and generated binding, not the authored + `DatabaseDefinition`; this preserves the manifest join point and package-free plugin deployment; +- the authority section now distinguishes the five control-flow values from each space's + provider-owned `ContractArtifact`, instead of silently changing the locked taxonomy; and +- `partial-success` now requires mixed successful and unsuccessful target outcomes; a run in which + no target succeeds cannot be called partial success. + +The draft is ready for the owner-locked Qwen 3.8 Max focused review. It is below the mandatory +12,000-word ceiling but remains 1,205 words above the preferred band. Subsequent reviewers must +identify deletions or consolidations alongside findings; they must not grow the RFC into another +research report. The final target is at most 10,000 words when that can be achieved without removing +an API contract, a safety invariant, or an explicit refusal. + +## What the RFC must make obvious + +After reading the RFC, a contributor should be able to answer these questions without opening the +research corpus: + +1. What does an application author write to define a database contract, target, and space? +2. How do native Prisma TypeScript contract types flow into an application-local typed binding? +3. How does a plugin contribute an independently owned database space or a permitted augmentation? +4. How does one extension registration supply authoring, control, runtime, and validation facets? +5. How are `StandardSchemaV1` input and output validators obtained, and where does validation fail + closed? +6. What is pure and deterministic, what needs a live database, and what is mutating? +7. What artifacts exist, who owns each artifact, and how do plan, apply, receipt, and recovery + differ? +8. What is deliberately removed, and how can existing production data be adopted without a dual + runtime or schema mutation? + +The document should lead with one coherent end-to-end journey and a small number of executable-shape +API examples. Reference details should exist only when they constrain implementation or prevent an +unsafe interpretation. + +## Required editorial changes + +### Keep and sharpen + +- The native, model-first Prisma `defineContract` example. State plainly that NetScript wraps the + contract with identity, ownership, policy, and lifecycle; it neither clones nor re-exports the + Prisma builder. +- One `defineDatabase` composition example, one generated binding/runtime example, one validation + example, one plugin-space/extension example, and one plan/apply example. +- The contract-first type-flow promise: authored contract → manifest → app-local binding → native + query types → boundary schemas → operation artifacts. +- The five distinct artifact roles: definition, manifest, executable plan, provider ledger/marker, + immutable receipt. Prefer a compact authority table to full interface declarations. +- The bounded, fail-closed Standard Schema decision and the `runtime | json` representation split. +- The ownership/removal rule, explicit target identity, no silent omission, and multi-target saga + semantics. +- The clean-break law and data-safe adoption protocol. +- The major refusals: no query DSL, no compatibility stack, no global registry/service locator, no + false portability, and no hosted control plane in this RFC. + +### Replace with links or remove + +- Remove process front matter, evidence-tag vocabulary, “how to read” mechanics, reviewer order, + session identifiers, and claim-by-claim provenance from the public RFC. +- Remove Appendices A–G. D-01–D-47, W0–W11, the conformance matrix, JSR audit, risk register, claim + ledger, and review trace already have canonical run artifacts. +- Replace per-package ownership/dependency/permission/publication/gate subsections with one package + graph table that says why each boundary exists. +- Remove the optional policy factory from v1. The thin Candidate-A surface is the decision; a future + factory need not compete with it in the main narrative. +- Replace large TypeScript declarations for every artifact, diagnostic, port, and operation with the + smallest signatures necessary to lock the public contract. +- Keep at most one lifecycle diagram. Summarize the other state machines as invariants or short + transition lines. +- Replace the large market matrix with four to six lessons and link `research/market-analysis.md` + for the evidence. +- Move exact current-state counts, verb-by-verb disposition, exhaustive gates, kill criteria, and + publication mechanics to the linked research/plan unless a number is essential to the decision. +- Eliminate repeated statements of the same refusal or clean-break rule. +- Replace `[RC1]`, `[PROPOSAL]`, `[NS-SRC]`, and similar inline tags with normal prose and direct + links near the few claims for which stability or evidence class matters. + +## Required technical corrections + +These are blocking findings for the consolidated draft. + +### R1 — first-adapter namespace contradiction + +The guide maps `app` and `auth` to separate physical namespaces and claims namespaces prevent plugin +table collisions, while the reference section withholds Prisma multi-namespace certification. The +first certified PostgreSQL adapter examples must use its one supported physical namespace. Logical +`SpaceId` and ownership coordinates prevent silent merging; they do not make identical physical +table names coexist. Until upstream type/runtime parity is proven, composition must refuse physical +name collisions and non-default namespace requests. + +### R2 — target-key type-check location + +An independently evaluated `defineDatabaseSpace({ target: 'primary' })` call cannot know the keys of +a later `targets` object. State that the mismatch is rejected when the space is composed by +`defineDatabase`, unless implementation proves a contextual factory signature. Do not promise a type +error at the standalone space call site. + +### R3 — pure control must be structurally offline + +The guide constructs `createDatabaseControl` with `connections` and then calls `emit` “with no +connection.” Make the API boundary prove that claim: construct the pure compiler/control catalog +without live connections, and pass explicit live dependencies only to `inspect`, `plan` when live +state is needed, `apply`, and `verify`; or expose distinct pure and live executors. The public +example must not rely on a promise that an injected connection resolver simply goes unused. + +### R4 — operation classification + +Signing an artifact is not a target-database mutation and must not require a migration lock. Keep +artifact-side policy/signature work separate from live database mutation. Operation classes should +be intuitive from the API rather than supported by an exhaustive catalog declaration. + +### R5 — one binding generic model + +The draft alternates between `AppBinding<'primary', AppContract>` and a runtime `bind` signature +whose second generic acts like a query type. Choose one model and show it consistently. The +generated application-local binding should own the contract-to-query association, while +provider-specific `QueryOf` remains inside generated/provider code and does not leak into +framework packages. + +### R6 — validation API and example semantics + +Choose one small public vocabulary. Recommended reader-facing shape: + +```ts +const users = primaryBinding.ref({ space: 'app' }).model('User'); + +const createUser = users.input('create', { representation: 'json' }); +const publicUser = users.output( + { select: { id: true, email: true } }, + { representation: 'json' }, +); +``` + +An explicit whole-model form may be `users.output('model', options)` if needed. Avoid competing +`value`/`operation`/`result` and `input`/`output` vocabularies. Reuse the create-input schema at an +input boundary and the selected-output schema at output boundaries; do not validate an arbitrary +Fresh payload with a query-result schema. Preserve the decisive limitation: unsupported operation or +selection metadata throws `DB_VALIDATION_UNSUPPORTED` at schema construction, while invalid user +data produces path-rich Standard Schema issues. + +### R7 — plugin contribution modes must be implementable + +The RFC both forbids published app fragments because provider helper types cannot cross a stable +published boundary and shows a generated `authFragment`-style contribution. Define the v1 modes +without contradiction: + +- persistent plugins contribute full independently versioned spaces with pinned artifacts by + default; +- application-local composition may use const-preserving, two-phase native fragments; +- cross-space augmentation is explicit, capability-limited, and ownership-checked; +- a published package may not masquerade as an app-local native fragment unless W3 proves a + generated-source or provider-specific package mechanism that preserves exact inference. + +### R8 — transaction and import surfaces must not overclaim + +Do not assert that a transaction exposes exactly the ordinary `TQuery` surface until W4 proves it; +use a distinct inferred transaction query type or keep the example illustrative. Use one coherent +package/subpath import story throughout. Do not introduce `@netscript/database/connection` unless +the package graph explicitly owns that public subpath. + +### R9 — receipts need a recovery read path + +A write-only `ReceiptSink` cannot by itself support resume and evidence lookup. The concise RFC need +not lock every port method, but it must state that the immutable receipt store supports append and +lookup by `RunId`/resume token, or name separate source and sink roles. + +### R10 — adoption cannot silently proceed on a subset + +“Proceed for reachable targets only” conflicts with explicit target closure and no silent omission. +Adoption may operate on an explicitly selected target set and must return a status for every +selected target. Full cutover is blocked until all intended targets are reachable, attributed, +baselined, and verified. Marker removal should be promised only where provider semantics prove it. + +## Recommended final structure and budget + +Preserve the repository RFC template headings, with roughly this allocation: + +| Section | Purpose | Budget | +| ------------------------------ | -------------------------------------------------------------------------- | ----------: | +| Summary | Decision, scope, non-goals, one architecture flow | 500–700 | +| Motivation | Manual surface and why Prisma 8 changes the opportunity | 700–1,000 | +| Guide-level explanation | End-state authoring, composition, binding, validation, plugins, operations | 3,000–3,800 | +| Reference-level explanation | Concepts, package boundaries, artifacts, invariants, capabilities | 2,000–2,800 | +| Drawbacks | Real costs and upstream coupling | 400–700 | +| Rationale and alternatives | Why this layer, why not the rejected shapes, short market lessons | 700–1,000 | +| Breaking changes and migration | Clean break, safe adoption, parallel branch strategy | 700–1,100 | +| Prior art | Links and the lessons actually adopted | 300–500 | +| Unresolved questions | Only decisions genuinely left to implementation or upstream proof | 250–500 | +| Future possibilities | Explicitly deferred capabilities | 200–400 | + +The section budgets are guidance; the 12,000-word ceiling is mandatory. + +## Acceptance for the next draft + +- 8,000–10,000 words preferred; no more than 12,000. +- Template headings remain and the title is shortened. +- The first two pages expose the decision and the end-state API/DX, not process metadata. +- Every code sample participates in one coherent API and respects the first adapter's actual + capabilities. +- The native contract type is preserved through composition and an app-local binding without a + NetScript query DSL or Prisma type leakage into provider-neutral packages. +- Plugin space, extension bundle, validation, control, and adoption stories each fit in one focused + subsection. +- All ten technical findings above are corrected or explicitly dispositioned in this review file. +- Exhaustive evidence remains reachable through direct links to the run research and approved plan. +- No compatibility shim, dual runtime, or false multi-provider claim is reintroduced while editing. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md new file mode 100644 index 0000000000..41e3ec38e2 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/reviews/root-semantic-closure.md @@ -0,0 +1,50 @@ +# Root Semantic Closure — Database Architecture RFC + +## Checkpoint + +- RFC: `rfcs/0000-database-architecture.md` +- Reviewed and pushed commit: `d28d8e779` +- Branch: `docs/database-architecture-rfc` +- Owner supersessions in force: RFC length is not an acceptance gate; no Claude/Fable route may be + launched or resumed. +- Result: **PASS_TO_FINAL_MECHANICAL** + +## Closed findings + +| Finding | Final disposition | +| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Executable extension facets had no live downstream path | One extension value is registered once on the configured provider. Native authoring consumes `postgres.authoring.scaffold`; compile verifies serializable pins; runtime/control receive the same provider value carrying live facets. | +| Native builder was described as running again during compile | Authoring invokes Prisma's native builder once. Offline compile verifies, canonicalizes, and publishes the completed contract; it never retroactively invokes authoring. | +| Hand-written generic binding could lie about space types/snapshots | The compiler emits a target descriptor with canonical `SpaceId` keys, `ManifestDigest`, per-space `ContractSnapshotId`, source-native evidence for app spaces, and declaration evidence only for artifact-owned spaces. | +| L3 imported generated binding before it emitted artifacts | L3 is split into a prior build/emission module graph and a later application/runtime graph. First boot and stale static-import ordering are explicit refusals. | +| `emit` had two owners and hidden IO | Catalog/CLI `emit` is the sole projection of `compileDatabase` with an explicit atomic publisher. `DatabaseControl` has no `emit` method. | +| Query examples passed ordinary strings to branded UUID fields | Application ports derive field values through provider-specific `FieldValueOf`; external strings cross only after validation/decoding. | +| Validation projection implied automatic query coupling | The RFC calls the literal selection a validation projection, requires handler output-type alignment, and gates provider plan/selection coupling on W3 proof. | +| Plugin `SpaceId` used an erased local alias | Definition maps, emitted descriptors, manifests, receipts, diagnostics, and `.space(...)` all use the same canonical plugin ID; map key and contribution ID are constrained to match. | +| Remote plugin aggregate could require network during offline compile | The plugin statically imports a generated aggregate module containing/importing the complete artifact graph. Release gates require cold remote materialization followed by network-disabled emit/verify. | +| Retained rollback was not a durable transition | Provider lock/fence plus a receipt-backed ledger transition preserves marker, previous head/snapshot, reason, and retained verify-only state; repository rollback does not claim provider metadata vanished. | + +## Independent closure + +The existing non-Claude lanes performed read-only checks of the corrected RFC. They made no edits, +commits, pushes, model launches, or word-count checks. + +| Lane | Scope | Verdict | +| ----------------------------------- | --------------------------------------------------------------------------------------------- | -------- | +| `/root/typescript_schema_audit` | TypeScript/API, native RC1 shapes, binding evidence, examples, validation | **PASS** | +| `/root/planned_jsr_audit` | Package graph, static aggregate transport, offline emit, JSR/release gates, retained rollback | **PASS** | +| `/root/architecture_plan_synthesis` | D-01–D-47, OWNER-DX-01, canonical identities, extension ordering, L3 loading, emit authority | **PASS** | + +## Mechanical evidence at semantic gate + +- `deno fmt --check rfcs/0000-database-architecture.md`: PASS +- `deno task docs:links`: PASS (`103` documents; no broken links, anchors, or enforced orphans) +- `git diff --check`: PASS +- Markdown fences: `40`, balanced +- Semantic residue scan: no obsolete hand-written binding, duplicate `control.emit`, + definition-level extension registration, stale binding path, second builder invocation, or numeric + length gate in the RFC + +No blocker or high-severity finding remains. Implementation claims remain conditional on the W1–W10 +conformance and release gates named in the RFC; this is an RFC acceptance verdict, not a claim that +the future packages already pass those gates. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md new file mode 100644 index 0000000000..4aad82bab7 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/supervisor.md @@ -0,0 +1,164 @@ +# Supervisor Identity — docs-database-architecture-rfc--prisma-8-rfc + +Written at run start per `workflow/lane-policy.md` § Supervisor identity. + +| Field | Value | +| -------- | ------------------------------------------------------------------------------------ | +| Model | Codex · OpenAI · GPT-5 family · high (root session; exact routed SKU is not exposed) | +| Session | `019ffbc7-133b-7852-905d-53a163fe9819` | +| Host | `YogaBook9i` · WSL2 Linux 6.18.33.2 · user `codex` | +| Checkout | `/home/codex/repos/netscript-547-lffix` | +| Worktree | `/home/codex/repos/netscript-db-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Baseline | `origin/main` @ `cd720529333328bcba5e1a308ce7632f4350efdf` (2026-08-13) | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | + +## Routes used and final disposition + +| Task lane | Provider / model / effort | Role in this run | +| ------------------------------------- | --------------------------------------- | -------------------------------------------------------------------------- | +| `planning_decisions` | OpenAI · Codex · GPT-5 family · high | Root research coordinator and RFC generator in the active user session | +| owner-directed architecture deep dive | Anthropic · Claude Code · Opus 5 · high | Fresh independent architecture/API review with optional native workflows | +| `deep_analysis` | Anthropic · Fable 5 · medium | Architecture decision analysis when the native agentic route is available | +| `formal_plan_evaluation` | Anthropic · Fable 5 · medium | Fresh opposite-family PLAN-EVAL before the RFC file is authored | +| focused post-draft RFC review | OpenRouter · Qwen 3.8 Max · max | Focused review after the root's complete-draft personal review | +| owner-directed adversarial RFC review | OpenCode · OpenRouter · Grok 4.6 · high | Post-draft attack on portability, migration safety, trust, and abstraction | +| owner-directed final refinement | Anthropic · Fable 5 · high | Ran 2026-08-15 as one fresh session; verdict `PASS` with one refinement | + +## Delegated research and synthesis lanes + +| Agent path | Model / effort | Scope | Status | +| ----------------------------------- | --------------------------- | ---------------------------------------------------------------- | -------- | +| `/root/market_gap_audit` | OpenAI · GPT-5.6 Sol · high | Missing delivery/control/validation comparators and market QA | Complete | +| `/root/validation_source_audit` | OpenAI · GPT-5.6 Sol · high | RC contract/result-plan proof for runtime Standard Schema | Complete | +| `/root/typescript_schema_audit` | OpenAI · GPT-5.6 Sol · high | Native TypeScript builder evolution and NetScript oRPC transfer | Complete | +| `/root/architecture_plan_synthesis` | OpenAI · GPT-5.6 Sol · high | Plan-Gate synthesis plus repository-grounded `OWNER-DX-01` audit | Complete | +| `/root/planned_jsr_audit` | OpenAI · GPT-5.6 Sol · high | Prospective publishability/slow-type review of the planned graph | Complete | + +These lanes are independent research/synthesis inputs. The three existing non-Claude lanes also +performed the final read-only closure checks. The owner later reinstated one fresh Fable 5 high +evaluator/refiner; no other Claude/Fable lane is reopened. + +## Formal plan evaluation + +| Cycle | Route / model / effort | Session | Evaluated commit | Verdict | Disposition | +| ----- | ---------------------------------------------- | -------------------------------------- | ---------------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| 1 | Native Claude Code · `claude-fable-5` · medium | `dd3cfbee-1a53-4dfd-84a3-e78e38ef5b22` | `3cbcfcec8` | `FAIL_PLAN` | Sole medium factual-integrity finding corrected in mutable records; cycle 2 resubmission ready, with canonical RFC authorship still blocked. | +| 2 | Native Claude Code · `claude-fable-5` · medium | `f3286656-7d0f-4da2-a22d-32897a5e6482` | `383170bbc` | `PASS` | Corrected 42-per-workspace finding confirmed; D-01–D-47 and slice/gate set accepted; RFC authorship unblocked. | + +Cycle 1 used the required fresh `formal_plan_evaluation` route, separate from the supervisor and all +research/synthesis lanes. Its only required fix was the copied claim of 30 generated `db:*` tasks: +evaluator execution of `generateDatabaseDenoJson` established 42 keys per generated engine workspace +for PostgreSQL, SQLite, MySQL, and MSSQL. `research.md`, the architecture synthesis, and `plan.md` +now carry the executed result and disposition Qwen F3 as an incorrect correction; independent model +reports and briefs remain immutable evidence. Cycle 2 passed at `383170bbc` and unblocked RFC +authorship; no further PLAN-EVAL cycle is requested. The current phase is `final-verification` after +semantic closure at `d28d8e779`. Cycle 2 also classified current-main `01e096049` as nonblocking +CI/gate-tooling drift and independently confirmed 42 generated `db:*` keys per engine workspace. + +After cycle 2, `OWNER-DX-01` explicitly overrode D-07/D-08/D-36. It requires the shipped NetScript +L1 preset/recipe → L2 public factories → L3 native-framework/primitives progression and prefers an +erased source-native `typeof definition` binding over universal generated TypeScript. This is owner +authority applied after evaluation, not a third PLAN-EVAL cycle; the six-package graph and all other +decisions remain locked, and no further PLAN-EVAL will run. + +## RFC authoring and consolidation + +| Stage | Route / model / effort | Session | Result | +| ------------------------ | -------------------------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------- | +| Raw draft | Native Claude Code · Opus 5 · high | `105f7bbd-895d-4dcd-8641-6768c6e076c8` | 28,194-word evidence-complete draft pushed as `05e5fbac2`; root requested consolidation. | +| Consolidation | Native Claude Code · Opus 5 · high | `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` | R1–R10 resolved; 11,205-word compact RFC committed and pushed as `5dfc4e8eb`. | +| Root review | Codex supervisor · personal full read | `019ffbc7-133b-7852-905d-53a163fe9819` | `PASS_TO_FOCUSED_REVIEW`; Qwen 3.8 Max is next, but final acceptance has not been granted. | +| Qwen focused review | OpenRouter · `qwen/qwen3.8-max` · max | `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` | Commit `5dfc4e8eb`; 2,181 words, no edits, `PASS_WITH_CHANGES`; QF-01–QF-05 open. | +| Grok whole-RFC review | OpenCode/OpenRouter · `x-ai/grok-4.6` · high | `ses_003644aeaffeSm3UCAW9xUqRIK` | Commit `5dfc4e8eb`, blob `f46040d8...`; no subagents/edits; `PASS_WITH_REFINEMENTS`, 0 blockers. | +| Author/editor checkpoint | Native Claude Code · Opus 5 · high | completed session recorded in worklog | Root corrections applied and pushed as `ad8effff9`; no later Opus use. | +| Root semantic closure | Codex supervisor + existing non-Claude lanes | current root session | TypeScript/API, JSR, and architecture verdicts `PASS`; pushed as `d28d8e779`. | +| Final evaluator/refiner | Native Claude Code · Fable 5 · high | `3517a6d2-b0b5-47ec-a207-b3533657a90c` | Starting commit `a7a6887c2`; verdict **`PASS`**; one example refinement; gate `cc90ead70` pushed. | + +Before commit `5dfc4e8eb`, root added three narrow corrections: runtime consumes the compiled +`DatabaseManifest`, not `DatabaseDefinition`; the authority table distinguishes each artifact and +value's role; and `partial-success` requires mixed successful and unsuccessful target outcomes. The +later author/editor and root closure passes resolved all blocker/high findings without changing the +package graph. The phase is `closed — final gate passed`; length is not an acceptance gate. + +Root independently verified the final route from the native stream receipt: systemd unit +`netscript-db-rfc-final-fable-20260815` exited with `Result=success` and status 0; the stream +reports model `claude-fable-5`, session `3517a6d2-b0b5-47ec-a207-b3533657a90c`, terminal reason +`completed`, and no permission denials. Receipt SHA-256 is +`9939f19d8c66981eadb2589ffdce0f2a3025f24e92ebfb5982a6f24d115cdff3`. At gate close, local, remote, +and live draft PR #1640 all resolved gate head `cc90ead7047a6f071c239c305619ac1ed77f2dae`; later +root-only terminal bookkeeping does not alter the RFC. + +The Qwen focused review passed architecture/type model, Standard Schema boundary, control/recovery, +migration/plugin safety, and market/upstream claims. Its QF-01–QF-05 findings are dispositioned in +the author/editor/root passes; its deletion ledger remains historical editorial input. + +The Grok review ran against current HEAD `be83301c6` while proving the RFC blob byte-identical to +commit `5dfc4e8eb`. Axes 2, 3, 4, and 6 passed. GR-01–GR-08 are dispositioned; its deletion ledger +is historical editorial input, not a gate. + +The subsequent `OWNER-DX-01` audit is recorded in `research/layered-dx-api-audit.md`. It inspected +the defining service/Hono preset, builder, and native primitives; SDK/Fresh analogues; and pinned +Prisma's runtime `contractJson` plus phantom compile-time contract split. The final RFC selects that +layered API, source-native app inference, and bounded artifact-only declarations; its emitted target +descriptor couples both evidence tracks to canonical runtime snapshot identities. + +## Recorded lane/eval overrides + +- The root session is Codex rather than the default Opus 5 orchestrator. This is the active + user-facing session surface; exact backend SKU is not exported, so the observed identity is + recorded without claiming GPT-5.6 Sol. +- The owner corrected the execution posture on 2026-08-13: the root must orchestrate rather than + absorb the substantive work. A fresh native Claude Code Opus 5 high lane is therefore added for + the independent architecture deep dive before plan lock. It is an input to, not a substitute for, + the separate PLAN-EVAL. +- Claude launch evidence: background handle `3f8a9a69`, full session + `3f8a9a69-5589-4b91-9a32-91f7770fe7c2`, PID `1944525`, worktree matched, native UI reported “Opus + 5 with high effort · Claude Max.” The session immediately exposed four internal agents; their + roles/identities must be recorded in its report. +- Historical directive: the owner initially selected Fable 5 **high** as the final refinement gate, + then froze all further Claude/Fable usage before it launched. On 2026-08-14 the owner explicitly + superseded that cancellation for exactly one fresh final Fable 5 high gate at the next midnight. + All other Claude usage remains frozen. +- Qwen 3.8 Max is selected for the owner-clarified focused post-draft review, after the root's + personal complete-draft review and before Grok's whole-RFC adversarial pass. The completed route + requested and observed `qwen/qwen3.8-max` at `max`, session + `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`, against commit `5dfc4e8eb`. +- The owner subsequently requires Grok 4.6 high. On 2026-08-13 the live OpenRouter models API + returned `x-ai/grok-4.6` with `reasoning_effort` support. The repository's static model catalog + still names Grok 4.5, so this is an explicit owner-directed route override rather than a claim + that the catalog is current. Use the existing bounded OpenCode/OpenRouter runner with model + `openrouter/x-ai/grok-4.6` and variant `high`, record requested/observed identity and raw receipt, + and run it after the focused Qwen review. That Grok route completed; the later planned Fable route + was temporarily cancelled, then explicitly reinstated once and completed at `cc90ead70`. +- The completed Grok route requested and observed `x-ai/grok-4.6`, variant `high`, session + `ses_003644aeaffeSm3UCAW9xUqRIK`, with no subagents and no edits. It evaluated RFC commit + `5dfc4e8eb` / blob `f46040d8...` at HEAD `be83301c6` and returned `PASS_WITH_REFINEMENTS` with + zero blockers. +- Qwen integration-risk launch evidence: OpenRouter evaluator guard requested `qwen/qwen3.8-max` at + `max`; session `f5c1afd0-f89f-48e2-9dfc-3e8f5ade646b` initialized with observed model + `qwen/qwen3.8-max` and provider `Alibaba`. This is a complementary falsification pass, not + PLAN-EVAL. +- Qwen's initial parent was interrupted before synthesis when a child request attempted + `claude-opus-5`; the HTTP-boundary evaluator guard recorded the denial and exited 78. The same + Qwen session is resumed in single-parent mode with all child-agent facilities forbidden. This + failed attempt is route evidence only and cannot be counted as a completed review. +- The native Opus parent paused after its specialist fan-out and placeholder creation. The same Opus + 5 high session is resumed for synthesis, preserving its completed workflow evidence rather than + launching a replacement author. +- The owner elevated Prisma Next's proposed pure-TypeScript schema authoring as a second primary + architecture axis beside contract-derived validation. A separate read-only source audit must + establish the exact upstream state and derive candidate end-to-end NetScript type flows before + plan lock; the Opus synthesis brief now requires this subsystem explicitly. +- Historical sequence: root personal review → Qwen 3.8 Max focused review → Grok 4.6 high whole-RFC + adversarial review → Opus author/editor dispositions. The owner temporarily cancelled the planned + Fable step; root plus the three existing non-Claude lanes closed semantics before the owner later + reinstated and completed exactly one final Fable gate. +- After PLAN-EVAL cycle 2 and the frozen Qwen/Grok review inputs, the owner issued `OWNER-DX-01`. + The override changes D-07/D-08/D-36 only: progressive NetScript adoption layers are required, only + a mirrored Prisma model/field/relation/query DSL is forbidden, and erased source-native app + inference replaces universal generated declarations. It triggered no further PLAN-EVAL. The + completed author/editor/root passes selected the API and proved the fallback boundary. +- Terminal owner supersession: RFC length is not an acceptance gate. Exactly one fresh final Fable 5 + high session was reinstated over the earlier freeze and has completed; no additional Claude or + Fable session may be launched or resumed. Only owner review of draft PR #1640 remains. diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh new file mode 100755 index 0000000000..e4b1c5f882 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/workflows/launch-final-fable.sh @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +umask 077 + +readonly repo='/home/codex/repos/netscript-db-rfc' +readonly branch='docs/database-architecture-rfc' +readonly run_dir="$repo/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc" +readonly prompt="$run_dir/briefs/fable-final-evaluator.md" +readonly output_dir="$repo/.llm/tmp/final-fable-evaluator" +readonly deno_bin='/home/codex/.deno/bin/deno' + +export HOME='/home/codex' +export PATH='/home/codex/.local/bin:/home/codex/.deno/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin' + +mkdir -p "$output_dir" +readonly launched_at="$(date --iso-8601=seconds)" +readonly log_path="$output_dir/$launched_at.stream-json.log" +readonly status_path="$output_dir/latest-status.json" + +exec > >(tee -a "$log_path") 2>&1 + +write_status() { + local exit_code="$?" + local head='unavailable' + local remote_head='unavailable' + head="$(git -C "$repo" rev-parse HEAD 2>/dev/null || printf unavailable)" + remote_head="$(git -C "$repo" ls-remote origin "refs/heads/$branch" 2>/dev/null | awk '{print $1}' || printf unavailable)" + local completed_at + completed_at="$(date --iso-8601=seconds)" + local temporary_status="$status_path.tmp" + printf '{"launchedAt":"%s","completedAt":"%s","exitCode":%s,"head":"%s","remoteHead":"%s","log":"%s"}\n' \ + "$launched_at" "$completed_at" "$exit_code" "$head" "$remote_head" "$log_path" > "$temporary_status" + mv "$temporary_status" "$status_path" + printf 'final-fable launcher exit=%s head=%s remote=%s log=%s\n' \ + "$exit_code" "$head" "$remote_head" "$log_path" +} +trap write_status EXIT + +cd "$repo" + +if [[ "$(git branch --show-current)" != "$branch" ]]; then + printf 'refusing launch: expected branch %s, found %s\n' "$branch" "$(git branch --show-current)" >&2 + exit 20 +fi + +if [[ -n "$(git status --porcelain --untracked-files=all)" ]]; then + printf 'refusing launch: worktree is not clean\n' >&2 + git status --short >&2 + exit 21 +fi + +git fetch --quiet origin "refs/heads/$branch" +local_head="$(git rev-parse HEAD)" +remote_head="$(git rev-parse FETCH_HEAD)" + +if [[ "$local_head" != "$remote_head" ]]; then + if git merge-base --is-ancestor "$local_head" "$remote_head"; then + git merge --ff-only "$remote_head" + else + printf 'refusing launch: local and remote branch are diverged or local is unpushed\n' >&2 + exit 22 + fi +fi + +printf 'launching final evaluator at %s from commit %s\n' "$launched_at" "$(git rev-parse HEAD)" + +"$deno_bin" run -A .llm/tools/agentic/claude/claude-print.ts \ + --model claude-fable-5 \ + --effort high \ + --prompt "$prompt" + +if [[ -n "$(git status --porcelain --untracked-files=all)" ]]; then + printf 'evaluator returned with an uncommitted worktree\n' >&2 + git status --short >&2 + exit 30 +fi + +readonly final_head="$(git rev-parse HEAD)" +readonly pushed_head="$(git ls-remote origin "refs/heads/$branch" | awk '{print $1}')" +if [[ "$final_head" != "$pushed_head" ]]; then + printf 'evaluator did not push final HEAD: local=%s remote=%s\n' "$final_head" "$pushed_head" >&2 + exit 31 +fi + +if [[ ! -s "$run_dir/evaluate.md" ]]; then + printf 'evaluator did not create a non-empty evaluate.md\n' >&2 + exit 32 +fi + +printf 'final Fable gate completed and pushed at %s\n' "$final_head" diff --git a/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md new file mode 100644 index 0000000000..5387dd3b88 --- /dev/null +++ b/.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/worklog.md @@ -0,0 +1,329 @@ +# Worklog: NetScript Database Architecture and Prisma 8 RFC + +## Run Metadata + +| Field | Value | +| -------------- | ------------------------------------------------------------- | +| Run ID | `docs-database-architecture-rfc--prisma-8-rfc` | +| Branch | `docs/database-architecture-rfc` | +| Phase | `closed — final gate passed` | +| Archetype | Docs-only RFC describing future A1/A2/A3/A4/A5/A6 surfaces | +| Scope overlays | `SCOPE-docs.md`; future packages use their archetype matrices | + +## Design + +The Design checkpoint is **locked and evaluator-approved**. Cycle 1 returned `FAIL_PLAN` solely +because the copied generated-workspace task count was factually wrong; evaluator execution found 42 +`db:*` keys per workspace for all four providers. After correction, native Fable 5 medium cycle 2 +session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. +Canonical RFC authorship is complete and no further PLAN-EVAL cycle is planned. After cycle 2, the +owner issued `OWNER-DX-01`, overriding D-07/D-08/D-36 to require layered adoption and source-native +app inference by default. The author/editor checkpoint landed at `ad8effff9`; root then closed the +remaining semantic findings, and three non-Claude lanes passed the result at `d28d8e779`. The owner +removed the length target and temporarily stopped further Claude/Fable usage, then reinstated +exactly one fresh final Fable 5 high gate. Session `3517a6d2-b0b5-47ec-a207-b3533657a90c` returned +`PASS`, applied one narrow pgvector example repair, and pushed `cc90ead70`. The run is closed for +owner review; the exact six-package graph is unchanged. + +### Public Surface and Package Graph + +- Canonical RFC record: `rfcs/0000-database-architecture.md`; its final substantive gate passed. +- `@netscript/database-contract` (A1): plain identities, manifest/plan/receipt/diagnostic schemas, + capabilities, ownership, and shared small SPIs; zero provider dependencies. +- `@netscript/database` (A4): L1 preset/recipe, the L2 `defineDatabase`/target/space/policy + factories it uses, deterministic resolution, and compile/emit through an explicit publisher. +- `@netscript/database-runtime` (A3): process/request lifecycle, connection ownership, + health/readiness, cancellation, and validation coordination. +- `@netscript/database-control` (A2): preview/inspect/plan/apply/verify, policy, provider ports, + locks, receipts, recovery, and cross-target saga; it does not own compile/emit. +- `@netscript/database-prisma-postgres` (A2): experimental/certified provider and sole framework + Prisma runtime/control boundary; no Prisma re-export. +- `@netscript/database-testkit` (A6): runnable provider/space conformance only if a binary is + justified; reconsider before W1 otherwise. +- Existing `@netscript/plugin` (A4), first-party plugins (A5), Aspire (A2), and CLI (A6) receive + thin database contribution, connection-source, and operation-projection changes. + +Candidate A remains the authoring baseline: current model-first Prisma `defineContract` is schema +authority. NetScript exposes its established L1 preset/recipe → L2 public factories → L3 native +Prisma plus NetScript primitives/ports progression. It bans a mirrored Prisma +model/field/relation/query DSL, vendoring/re-export, copied overloads, private types, and +widening—not progressive orchestration. App-owned contracts prefer erased `typeof definition` +inference while runtime consumes manifest/artifact values; automatic atomic launcher-integrated +declarations are a W3-proven fallback only for publish/artifact-only boundaries. + +### Domain Vocabulary + +- `DatabaseDefinition`: pure authored TypeScript composition. +- `NativeContract`: provider-native schema value. +- `SpaceContribution`: declarative owner/version/capability/dependency/provenance/retention record. +- `ContractArtifact`: canonical provider data/declaration/lineage/provenance, pinned per space. +- `DatabaseManifest`: deterministic versioned resolved value and durable join point; a graph is + private compiler IR only. +- `AppBinding`: app-local inferred target/session/validation bridge, source-native by default and + declaration-backed only at a proved boundary. +- `TargetRef`/`TargetSession`: explicit identity and lifecycle shell with app-local query generic. +- `SpeculativePreview` versus baseline-bound `ExecutablePlan`. +- Provider-owned `ProviderMarker`/`ProviderLedger` versus immutable NetScript `OperationReceipt`. +- `OperationCatalog`: machine source for CLI/help/docs/agents. +- `ValidationIR`: bounded internal value/selection algebra, never a second ORM type system. + +Stable identities are target, role, namespace, space, object, contract snapshot, manifest, plan, +run, and receipt IDs. Provider/engine/path/order/discovery strings never substitute for identity. + +### Ports + +- `ContractArtifactSource` and atomic artifact publisher. +- `ProviderRuntimeFactory` for process/request sessions. +- `ProviderControl` for provider-native emit/inspect/plan/apply/verify translation. +- `ConnectionSource` for environment, Aspire, or secret-reference resolution. +- Provider `MigrationLock` capability with owner/nonce/fencing evidence. +- `ReceiptSink` for atomic immutable checkpoints. +- Clock/ID/signature policy only where deterministic tests or production approval need seams. + +Ports stay cohesive at three or four methods. Provider registries are immutable composition-root +values, not globals. Concrete Prisma contracts/control/runtime/codec/AST types remain adapter-local. +Application domain ports remain application practice, not a generated NetScript repository system. + +### Constants and State Machines + +- Ownership: `managed`, `adopted`, `external`, `ignored`. +- Runtime scope: `process`, `request`. +- Validation representation: `runtime`, `json`; driver wire is internal. +- Operation class: `pure`, `live-read`, `mutating`, `resident`. +- Receipt outcomes include success, refusal, skip, failure, partial success, cleanup required, + cancellation, and outcome unknown. +- Removal guarantee: detach-and-retain; archive/drop are conditional. +- Capability IDs are open namespaced static data, not a negotiation protocol. + +Composition, planning/approval, apply/checkpoint/verify/recovery, contribution lifecycle, and +multi-target saga transitions are specified in `plan.md`. Preview cannot be applied; every unknown +outcome is inspected before resume; cross-target atomicity is never claimed. + +### Commit Slices + +| # | Slice | Gate | Files | +| - | ------------------------------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------------------------------- | +| 0 | Harness bootstrap/review surface. | Artifact/format/diff; landed. | Run root. | +| 1 | Research corpus, rebaseline index, planned JSR audit, and Plan-Gate lock. | PLAN-EVAL input completeness, source/claim, format/diff. | `research.md`, `research/*.md`, planning/context/drift artifacts. | +| 2 | Independent Plan-Gate verdict. | Fresh separate-session `PASS`. | `plan-eval.md`, planning artifacts only. | +| 3 | Canonical architecture/API RFC body. | Source alignment, docs, decision coverage. | RFC plus run context/worklog. | +| 4 | Cutover/waves/conformance/risks/market completion. | Migration safety, claim trace, docs gates. | RFC plus run context/worklog. | +| 5 | Root, Qwen focused, and Grok whole-RFC reviews complete. | Review receipts; no undispositioned critical/high. | RFC plus review/run artifacts. | +| 6 | Author/editor dispositions complete. | Finding ledger closed; decision/contradiction trace. | RFC plus review/run artifacts. | +| 7 | Root semantic closure, three non-Claude passes, and publish handoff. | Closure verdicts, then mechanical checks only. | RFC/final run/handoff artifacts. | + +### Prospective JSR Verdict + +`research/planned-jsr-audit.md` returns **PASS-AS-PLANNED / NOT ACTUAL PUBLISH READINESS**. The six +new packages do not exist, so actual `deno publish --dry-run`, `deno doc --lint`, publish-list, +packed-install, canary, and remote-consumer results are **N/A**, not PASS. + +Implementation requires per unit: explicit manifest/export/include surface, docs/JSDoc/examples, +isolated declarations, no slow-types waiver, scoped check/lint/fmt, `quality:scan`, `arch:check`, +`deno doc --lint`, `deno publish --dry-run`, publish-list inspection, generated-asset freshness, +public import and packed-consumer tests. W10 adds authenticated OIDC/SLSA canary, registry +reconciliation, and `e2e-cli-prod` against exact JSR versions. + +### Open Decisions and Deferred Scope + +- Must resolve now: **none**. +- Pre-implementation by wave: manifest encoding/versioning; exact Prisma pin/import allowlist; + namespace capability verdict; lifecycle/transaction types; signature/key custody; provider lock; + receipt retention/fault harness; augmentation grants; cutover window/runbook. +- Safe to defer: second provider, Prisma non-PostgreSQL targets, runtime negotiation, AOT, archive/ + drop, raw/prepared/aggregate conveniences, hosted control plane, cross-database relation/ + transaction support. +- All production packages, doctrine mutations, publication, provider certification, plugin + conversion, legacy deletion, and release operation begin only after RFC acceptance. + +### Contributor Path and Implementation Waves + +Contributors author native provider contracts, then declare app-owned fragments or plugin-owned full +spaces. A two-phase root collects extension bundles/dependencies first, then invokes native +fragments with exact helpers. One extension registration fans all facets. Plugin tables default to +their own space, artifacts, lineage, and head; production apply/verify consumes the pinned mirror +without plugin code. Generated type declarations are not universal and, where W3 proves them +necessary, are created automatically in the same atomic launcher-integrated compile. + +W0 RFC/doctrine plan → W1 contract → W2 definition/compiler → W3 experimental Prisma PostgreSQL and +type-boundary spike → W4 manifest-only runtime → W5 control → W6 testkit → W7 plugin seam → W8 +layered CLI/agent/emit-watch adoption → W9 first-party spaces → W10 clean cutover → W11 second +provider only when real/mature. Every wave has the archetype, source, JSR, consumer, conformance, +and release exits recorded in `plan.md`. + +## Progress Log + +| Time | Slice | Step | Notes | +| ---------- | ----- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2026-08-13 | 0 | bootstrap | Fresh worktree and branch created from current `origin/main`; run artifacts initialized. | +| 2026-08-13 | 1 | research | Owner directed the root to orchestrate. Added a fresh Claude Code Opus 5 high independent architecture lane; its exclusive report feeds plan lock. | +| 2026-08-13 | 1 | research | Owner supplied a March 2026 Prisma-maintainer exchange supporting contract-derived runtime validation. Elevated Standard Schema input/output validation to a first-class subsystem and recorded runtime/AOT equivalence gates. | +| 2026-08-13 | 1 | research | Owner elevated Prisma Next's proposed pure-TypeScript schema authoring. Added a dedicated source/architecture audit and required schema-to-contract-to-operation-to-validation-to-transport type propagation in the Opus synthesis and Plan-Gate. | +| 2026-08-13 | 1 | research | Owner clarified the target is Prisma's native `defineContract` builder and named NetScript's oRPC extension model as the precedent. Expanded the audit to compare native-surface preservation, factory augmentation, plugin typing, and app-local composition against database-specific lifecycle/ownership needs. | +| 2026-08-13 | 1 | research | Pinned-source validation audit found a qualified runtime-interpretation path, not full contract-only parity. Locked fail-closed bounded semantics, runtime/JSON representations, contributor value schemas for custom codecs, selection metadata requirements, aggregate-space identity, and a canonical full-contract validator cache digest. | +| 2026-08-13 | 1 | research | Claude Code Opus 5 high completed its three-part independent architecture synthesis. It recommends a compiled manifest, app-local inferred contract binding, an A3 runtime package, an operational protocol replacing `Promise`, native TypeScript authoring at the composition seam, and a clean Postgres-first cutover. | +| 2026-08-13 | 1 | synthesis | Delegated a separate Plan-Gate synthesis to reconcile Opus, Qwen, source audits, market evidence, doctrine, and the pending TypeScript/oRPC audit before formal PLAN-EVAL. | +| 2026-08-13 | 1 | plan-lock | Completed the source-audited TypeScript/oRPC and prospective JSR audits, current-main `research.md` index, decision-grade architecture synthesis, and formal D-01–D-47 Plan-Gate. No must-resolve-now decision remains; phase advanced to `plan-eval-ready`. | +| 2026-08-13 | 2 | plan-eval | Native Fable 5 medium cycle 2 session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit `383170bbc` and returned `PASS`. It independently confirmed 42 generated `db:*` keys per engine workspace and classified current-main commit `01e096049` as nonblocking CI/gate-tooling drift. RFC authorship is unblocked. | +| 2026-08-13 | 3 | raw-draft | Native Claude Code Opus 5 high session `105f7bbd-895d-4dcd-8641-6768c6e076c8` authored the evidence-complete canonical draft. Root committed and pushed it as `05e5fbac2`; the draft was intentionally treated as an input to review, not final prose. | +| 2026-08-13 | 3 | root-review | Root substantively reviewed the 28,194-word raw draft and returned `REVISE_CONSOLIDATE`. The review locks a reader-first 8,000–10,000-word target (12,000 hard ceiling), removes duplicated evidence/process appendices, and records ten blocking API/correctness repairs before Qwen and Grok review. | +| 2026-08-13 | 5 | qwen-review | Qwen 3.8 Max session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7` reviewed frozen commit `5dfc4e8eb` at effort `max`, returned 2,181 words and `PASS_WITH_CHANGES`, made no edits, and opened QF-01 high, QF-02 medium, and QF-03–QF-05 low. Four substantive axes passed; TypeScript/API and package/dependency examples need disposition. | +| 2026-08-13 | 5 | grok-review | OpenCode/OpenRouter requested and observed `x-ai/grok-4.6` variant `high`, session `ses_003644aeaffeSm3UCAW9xUqRIK`, against RFC commit `5dfc4e8eb` and byte-identical blob `f46040d8...` while HEAD was `be83301c6`. It used no subagents, made no edits, and returned `PASS_WITH_REFINEMENTS`, zero blockers, and GR-01–GR-08. | +| 2026-08-13 | 6 | owner-dx | `OWNER-DX-01` audited shipped service/Hono preset→factory→native primitives, SDK/Fresh analogues, and Prisma's runtime `contractJson` plus phantom compile-time contract split. Owner overrode D-07/D-08/D-36 after PLAN-EVAL: source-native app inference is default; automatic declarations are a bounded W3 fallback. No new PLAN-EVAL. | +| 2026-08-13 | 6 | disposition | The author/editor pass resolved QF/GR and OWNER-DX-01 findings; root's correction pass was committed and pushed as `ad8effff9`. | +| 2026-08-13 | 7 | owner-gate | Owner removed word-count acceptance criteria and froze all further Claude/Fable usage. Existing completed sessions remain provenance only; no planned final Fable session ran. | +| 2026-08-13 | 7 | closure | Root corrected executable extension transport, canonical space/snapshot binding evidence, emit/load ordering, compile/emit authority, branded IDs, validation projection honesty, package aggregate transport, and retained rollback. TypeScript/API, prospective JSR, and architecture lanes all returned `PASS`; `d28d8e779` was pushed. | +| 2026-08-14 | 8 | owner-gate | Owner reinstated exactly one fresh native Fable 5 high final evaluator/refinement gate at 2026-08-15 00:00 Europe/Zurich. Unit `netscript-db-rfc-final-fable-20260815` uses the persisted fail-closed launcher and brief; no fallback, subagent, workflow, or other Claude route is authorized. | +| 2026-08-15 | 8 | final-gate | Fresh native Fable 5 high session `3517a6d2-b0b5-47ec-a207-b3533657a90c` ran from starting commit `a7a6887c2` (= remote tip), read the complete RFC, run artifacts, three reviews, and three audits, re-verified the pinned RC1 claims (138 exports, phantom type maps, namespace flattening, demo helper spellings), applied one narrow example repair (`pgvector()` — extension-level `dimensions` removed as upstream-false), and returned **`PASS`** in `evaluate.md`. Gate `cc90ead70` is pushed; docs gates are green post-edit. | + +### RFC Consolidation and Root Acceptance + +Native Claude Code Opus 5 high session `de518f07-68e0-4f77-9cb5-e59dc3e81ebc` completed the +single-author consolidation. The canonical RFC fell from 28,194 to 11,205 words while resolving +R1–R10 and preserving the locked architecture; root committed and pushed it as `5dfc4e8eb`. + +Root personally read the entire compact RFC and added three narrow corrections before commit: +runtime consumes the manifest rather than `DatabaseDefinition`; artifact/value authority remains +explicit; and `partial-success` requires mixed successful and unsuccessful target outcomes. Targeted +fmt, `docs:links`, and diff checks passed. The checkpoint is accepted for Qwen review, not finally +accepted. + +### Qwen Focused Post-Draft Review + +OpenRouter requested and observed `qwen/qwen3.8-max` at effort `max`, model session +`3d1277dd-be6a-44af-9e98-4560d8aaf1b7`, against RFC commit `5dfc4e8eb`. The exact review output was +2,181 words, made no edits, and returned `PASS_WITH_CHANGES`. Architecture/type model, Standard +Schema boundary, control/recovery, migration/plugin safety, and market/upstream claims passed. The +narrow failures were TypeScript/API examples and one package/dependency example. + +Dispositioned findings: + +- **QF-01:** closed by the compiler-emitted target descriptor carrying real manifest/snapshot + values. +- **QF-02:** closed by registering one extension value on the configured provider before authoring. +- **QF-03:** closed by explicit complete-module/excerpt status and bound example imports. +- **QF-04/QF-05:** closed by pinned API attribution and the runtime/JSON validation boundary. + +Qwen also supplied a deletion ledger. It remains historical editorial input, not authorization to +remove load-bearing semantics; the owner later removed length as an acceptance criterion. + +### Grok Whole-RFC Adversarial Review + +OpenCode/OpenRouter requested and observed `x-ai/grok-4.6`, variant `high`, session +`ses_003644aeaffeSm3UCAW9xUqRIK`. It evaluated RFC commit `5dfc4e8eb`; the RFC blob was +byte-identical to `f46040d8...` at current HEAD `be83301c6`. The lane used no subagents, made no +edits, and returned `PASS_WITH_REFINEMENTS` with zero blockers. Axes 2, 3, 4, and 6 passed; axis 1 +abstraction, axis 5 public API/DX/types, and axis 7 economy failed narrowly while the architecture +stood. + +Dispositioned refinements: + +- **GR-01–GR-03:** closed by the emitted canonical-space/snapshot descriptor and configured provider + value; Prisma contract spaces remain disjoint. +- **GR-04:** closed by making catalog/CLI `emit` the sole projection of `compileDatabase` with an + explicit publisher; `DatabaseControl` has no competing method. +- **GR-05–GR-06:** closed by durable receipt-backed retained transitions and total outcome rollup. +- **GR-07–GR-08:** closed by the provider module, honest excerpt markers, source corrections, and + consolidation that preserved content over a numeric length target. + +Grok's deletion ledger remains historical editorial input. QF/GR dispositions are complete; the +owner's later direction makes content and clarity, not a numeric length, the acceptance criterion. + +### PLAN-EVAL Cycle 1 + +Fresh Fable 5 medium cycle 1 returned `FAIL_PLAN` on one medium factual-integrity defect only: an +independently reported count of 30 generated `db:*` tasks was copied into mutable Plan-Gate records, +while executing the generator produced 42 per engine workspace for every provider. All architecture +decisions, slices, risks, gates, and deferrals otherwise passed. + +The three mutable records now use the executed 42-per-workspace result and disposition Qwen F3 as an +incorrect correction while preserving independent reports and evaluator evidence. Targeted format +and full diff checks passed. + +### PLAN-EVAL Cycle 2 + +Fresh native Fable 5 medium session `f3286656-7d0f-4da2-a22d-32897a5e6482` evaluated commit +`383170bbc` and returned `PASS`. It re-executed the generator and confirmed 42 task keys **per +workspace**, verified D-01–D-47 and all eight slices, and found no open rework-forcing decision. It +also inspected the one-commit current-main delta (`01e096049`) and classified it as nonblocking +CI/gate-tooling drift that changes structured check invocation rather than database or RFC premises. + +## Decisions + +| Decision | Reason | Source | +| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------- | +| #313 is superseded design evidence | Its additive/compatibility premise conflicts with the owner-directed clean break. | Owner directive + current rebaseline | +| Compiled manifest, not live graph | A plain deterministic value is the durable join point and avoids service location. | Synthesis D-03/D-04 | +| Exact A1/A4/A3/A2/A2/A6 package split | One archetype per responsibility; runtime lifecycle requires A3 gates. | Doctrine + synthesis §4 | +| Native model-first Prisma authoring and layered adoption | Prisma owns schema vocabulary; L1 preset uses L2 factories and L3 exposes native Prisma plus NetScript primitives/ports. | OWNER-DX-01 + D-06/D-07/D-36 | +| App-local inferred binding | Prefer erased `typeof definition`; use atomic launcher-integrated declarations only at W3-proven publish/artifact boundaries. | OWNER-DX-01 + D-08 | +| Contract spaces and extension bundles | Plugin ownership/history and one authoring/control/runtime/validation registration replace copied fragments/manual facets. | Prisma source + D-17–D-20/D-38–D-40 | +| Bounded Standard Schema interpreter | Contract runtime data is useful but omits full operation/result types; runtime/JSON schemas fail closed. | Validation source audit + D-21–D-25 | +| Provider-neutral kernel, PostgreSQL-only first adapter | Matches Prisma maturity without compatibility fallback or false portability. | Prisma scorecard/source + D-10/D-11/D-34 | +| NetScript operational semantics, provider migration mechanics | NetScript owns policy/locks/recovery/receipts/saga while provider owns diff/lineage/marker. | Market/source reconciliation + D-27–D-30 | +| PLAN-EVAL before RFC | Architecture has no open must-resolve item but still requires independent acceptance. | Harness Plan-Gate + D-01–D-47 | +| One final Fable 5 high route | Latest owner directive supersedes the prior cancellation for this gate only; all other Claude usage remains frozen. | Owner directive | +| No numeric RFC length gate | Content and clarity govern acceptance; consolidation is not a word-count exercise. | Owner directive | + +## Drift + +| Drift | Severity | Logged in drift.md | +| ------------------------------------------------------------ | ------------- | -------------------------------- | +| #313 compatibility-first plan is no longer authoritative | architectural | yes | +| Final Fable cancellation was later superseded for one gate | significant | owner-directed one-shot schedule | +| Word-count target was removed by owner | significant | run-state override | +| `origin/main` advanced by CI/gate-tooling commit `01e096049` | nonblocking | plan-eval evidence | + +## Gate Results + +### Static Gates + +| Gate | Command or check | Result | Notes | +| -------------- | ------------------------------------------------------ | ------ | ----------------------------------------------------------------------- | +| Bootstrap diff | `git diff --check`; targeted `deno fmt --check` | PASS | Six required run artifacts are present and formatted. | +| Compact RFC | Targeted fmt; `docs:links`; `git diff --check` | PASS | Commit `5dfc4e8eb`; 11,205 words and R1–R10 resolved. | +| Semantic RFC | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Commit `d28d8e779`; final blocker/high findings closed. | +| Final schedule | Targeted fmt; `docs:links`; `bash -n`; diff; calendar | PASS | One-shot launcher resolves to 2026-08-15 00:00 CEST. | +| Final gate | Targeted fmt; `docs:links`; `git diff --check`; fences | PASS | Post-refinement: 1 file checked, 103 docs 0 broken, 40 balanced fences. | + +### Fitness Gates + +| Gate | Result | Evidence | Notes | +| ---------------------------- | --------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | +| Archetype/package assignment | PASS_PLANNED | `plan.md` package graph | A1/A2/A3/A4/A5/A6 responsibilities and gates are explicit. | +| Open-decision sweep | PASS_OWNER_OVERRIDE | D-01–D-47 plus `OWNER-DX-01` | No must-resolve-now item; D-07/D-08/D-36 updated without changing package boundaries. | +| Prospective JSR audit | PASS_AS_PLANNED | `research/planned-jsr-audit.md` | New-package dry-run/docs/packed/canary gates are N/A until implementation, not PASS. | +| PLAN-EVAL | PASS_CYCLE_2 | `plan-eval.md`; session `f3286656-7d0f-4da2-a22d-32897a5e6482` | Commit `383170bbc`; no further Plan-Eval cycle. | +| Qwen focused RFC review | PASS_WITH_CHANGES | Session `3d1277dd-be6a-44af-9e98-4560d8aaf1b7`; commit `5dfc4e8eb` | Five findings were later dispositioned; review made no edits. | +| Grok whole-RFC review | PASS_WITH_REFINEMENTS | Session `ses_003644aeaffeSm3UCAW9xUqRIK`; blob `f46040d8...` | Zero blockers; GR-01–GR-08 were later dispositioned. | +| TypeScript/API closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Extension, binding, loading, branded ID, validation and examples closed. | +| Prospective JSR closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | Static aggregate module plus cold-remote/network-disabled gate closed the last high. | +| Architecture closure | PASS | `reviews/root-semantic-closure.md`; `d28d8e779` | D-01–D-47, OWNER-DX-01, package graph and four prior findings closed. | +| Final Fable evaluator | PASS | `evaluate.md`; session `3517a6d2-b0b5-47ec-a207-b3533657a90c` | Starting commit `a7a6887c2`; gate `cc90ead70`; one narrow refinement; gates green. | + +### Runtime Gates + +| Gate | Result | Evidence | Notes | +| ---------------- | ------ | ------------------- | ----------------------------------------------------------------------------------------------- | +| Runtime behavior | N/A | Docs-only Plan-Gate | Future A3/provider/control runtime matrices are selected in `plan.md`; no implementation claim. | + +### Consumer Gates + +| Consumer | Result | Evidence | Notes | +| ---------------------- | ------ | ------------------------------------------------------------- | -------------------------------------------------------------------- | +| PLAN-EVAL reader | PASS | `plan-eval.md`, corrected research/plan, synthesis and audits | Cycle 2 accepted the locked plan. | +| RFC reader/implementer | PASS | RFC `d28d8e779`; Qwen/Grok plus three closure verdicts | No blocker/high finding remains; implementation gates stay explicit. | + +## Handoff Notes + +- Planning is complete and evaluator-approved at commit `383170bbc`. Cycle 1's failure remains + preserved; cycle 2 passed and no further PLAN-EVAL cycle is requested. `OWNER-DX-01` is an + explicit later owner override, not an evaluator rerun. +- Prospective package publishability is `PASS-AS-PLANNED`; actual JSR commands remain N/A until + packages exist and must produce implementation/release receipts later. +- Qwen returned `PASS_WITH_CHANGES`; Grok returned `PASS_WITH_REFINEMENTS`. Author/editor and root + dispositions are complete, and three final non-Claude closure audits passed `d28d8e779`. +- The owner removed the word-count gate. The earlier Claude/Fable freeze remains in force except for + the explicitly scheduled single fresh Fable 5 high evaluator/refiner, which ran on 2026-08-15 from + starting commit `a7a6887c2` and returned **`PASS`** with one narrow example refinement + (`evaluate.md`). Only owner review of draft PR #1640 remains; the PR stays draft. diff --git a/rfcs/0000-database-architecture.md b/rfcs/0000-database-architecture.md new file mode 100644 index 0000000000..caeb492630 --- /dev/null +++ b/rfcs/0000-database-architecture.md @@ -0,0 +1,1529 @@ +--- +rfc: 0000 +title: Database architecture — a provider-neutral kernel with a Prisma 8 PostgreSQL adapter +status: Draft +authors: ['@rickylabs'] +created: 2026-08-13 +tracking-issue: https://github.com/rickylabs/netscript/issues/313 +target-milestone: Backlog / Triage +--- + +# Database architecture — a provider-neutral kernel with a Prisma 8 PostgreSQL adapter + +## Summary + +NetScript replaces its inherited database foundation with one provider-neutral composition and +operations kernel, and certifies exactly one adapter first: Prisma 8 on PostgreSQL. + +Applications and plugins author schema in **native Prisma TypeScript** — the current model-first +`defineContract(scaffold, callback)` form — and pass that exact native value into NetScript's own +adoption surface, which adds identity, ownership, capability requirements, policy, and lifecycle. +That surface has the three levels NetScript already uses for Hono, the SDK, and Fresh: an **L1 +recipe** for the golden path, the **L2 factories** it calls, and **L3 native Prisma plus kernel +primitives**. None of them describes a model, field, relation, or query: NetScript adds no schema or +query vocabulary and re-exports no builder. A compiler with no live dependencies resolves those +definitions into canonical contract artifacts and one deterministic, content-addressed +`DatabaseManifest`. That manifest is the durable join point for everything downstream: an emitted +app-local binding descriptor coupling erased inference for authored contracts with an automatically +emitted declaration for any space the consumer did not author; typed process/request sessions; +bounded `StandardSchemaV1` validators; programmatic emit/inspect/plan/apply/verify operations; +provider markers and ledgers; immutable receipts; and generated CLI, Aspire, and agent projections. + +The end-to-end flow is one pipeline of separately named values, and no stage may impersonate +another: + +```text +native contracts + NetScript definitions + → deterministic composition → ContractArtifacts → DatabaseManifest + → app-local binding → sessions + bounded validators + → inspected baseline → ExecutablePlan → provider apply/ledger + → immutable OperationReceipts → verify / resume +``` + +This is a clean break. There is no compatibility API, no Prisma 7 fallback, no dual runtime, no +legacy adapter facade, and no application that composes both stacks. Data continuity is nevertheless +absolute: `netscript db adopt` introspects live databases, proposes ownership, writes provider +marker metadata only, and performs **no application-schema DDL and no application-data DML** — the +only writes are idempotent, receipt-backed provider marker and ledger rows. + +Two acceptance conditions bind implementation, and the design is narrowed rather than softened if +either fails: + +> **Exact native contract inference survives into the app-local query binding** — no private +> imports, no copied overloads, no casts, no widening, and no manual type-generation step in a +> developer's normal loop. +> +> **Runtime validation is intentionally bounded and fails closed** — a schema is produced only where +> the contract plus registered operation, selection, codec, and extension metadata can prove it. + +Explicit non-goals: no query DSL or repository layer, no portable client facade, no runtime +capability negotiation, no global provider registry, and no hosted control plane. Where a capability +cannot be made sound today — multi-namespace typing, full operation validation from contract data, +destructive plugin removal, non-PostgreSQL providers — this RFC withholds the claim and names the +gate that would release it. The locked decision ledger, waves, and conformance matrices live in the +[approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md); the evidence +behind every upstream claim lives in the linked research artifacts. + +## Motivation + +### The problem is not a Prisma version + +NetScript does not have one database architecture. It has five partially overlapping systems whose +identities and ownership rules do not line up: an appsettings/Aspire resource model, a fixed CLI +engine registry and operation runner, a generated per-engine Prisma workspace and task graph, a +runtime adapter wrapping a user-constructed Prisma client, and an install-time plugin fragment +copier. The happy path works only when all five agree about config keys, engine directory names, +environment variables, generated files, Prisma CLI behaviour, adapter packages, and a live Aspire +resource graph — an agreement the framework makes a developer and CI responsibility. No canonical +value joins the five views, so every fix lands in one of them and the failure moves +([current-state audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/netscript-current-state.md)). + +Three defects are structural rather than incidental. + +**Provider identity has replaced target identity.** The generated workspace directory is computed as +`join('database', provider.dirName)` from a closed engine enum +(`packages/cli/src/kernel/adapters/database/workspace-resolver.ts:51`), so two PostgreSQL databases +share one schema tree, one migration history, one generated client, and one task set: +`db add postgres --name analytics` writes another configuration entry but still resolves +`database/postgres/`. Engine selection is a `switch` over +`'postgres' | 'mysql' | 'sqlite' | 'mssql'` — the literal counter-example doctrine records as AP-24 +([anti-patterns](../docs/architecture/doctrine/09-anti-patterns-and-fitness-functions.md)) — and +every downstream artifact inherits that collapse. + +**Generation is a repair pipeline, not an emission.** The nominal `db:generate` path removes +placeholders, generates a client, generates again through a Zod wrapper, rewrites the result four +ways, builds an alias barrel, patches a facade, and repairs once more — non-atomic generated source +that NetScript mutates from upstream textual output, while a developer can edit the schema, skip the +pipeline, and keep compiling against stale types. Pure code generation also boots Aspire, the open +`DB-GENERATE-ASPIRE-COUPLING` debt entry. + +**Plugin schema contribution has no ownership semantics.** Plugins ship plain `database/**/*.prisma` +files that the CLI copies into the consumer's schema tree, scanning top-level blocks with a regex +parser and rejecting same-name declarations with different bodies. That cannot express a +contribution contract, schema version, capability requirement, dependency order, declaration or +migration ownership, uninstall data policy, or provenance, and its failure modes are on record: +dependency-mode installs reported success while omitting every plugin table ([#1014][ns-1014]), and +model-name clashes broke authentication installs until namespacing plus a collision guard landed +([PR #1059][ns-1059]). Removal deletes a directory; it plans no migration. + +The operational history says the same thing from a different angle. Each row below cost real +recovery time, and each is a missing architectural concept rather than a missing feature: + +| Incident | Lesson the architecture must encode | +| -------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| A read-only command killed the resident AppHost | Operations need one lifecycle owner and an operation class | +| A second AppHost mounted live `PGDATA` and corrupted it | Operations bind an authoritative resolved value, never rebuild it | +| Headless migrate returned success with no artifact | An exit code is not a result; operations need typed postconditions | +| A generated Zod alias hid symbols; its repair broke boot | Generated symbol paths cannot be the contract; validation needs a standards-facing boundary | + +Substituting Prisma 8 for Prisma 7 under this structure would preserve every one of those seams. + +### Why Prisma 8 changes the calculus + +Prisma 8 is not Prisma 7 with a new generator. Its source is arranged as a canonical contract plus +separate control and execution planes: PSL or a TypeScript builder lowers into a canonical +`contract.json` and `contract.d.ts`, a small versioned runtime consumes the contract, a programmatic +control client exposes emit/inspect/plan/apply, migrations are content-addressed graph edges with +per-space markers and a ledger, and **contract spaces** make one contributor's +`(contract, migration graph, head ref)` a first-class disjoint tuple ([ADR 212][adr-212]). That +replaces generated client source, source rewriting, copied-file ownership, log scraping, and the +single `engine` string with modelled equivalents +([deep dive](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/prisma-8-deep-dive.md)). + +It is also not a safe surface to expose directly, and this RFC treats that as a design input: + +- RC1 is Early Access and explicitly not recommended for production ([README][rc1-readme]); its + notes warn that respins may break, remove, or rename APIs and the contract format + ([release][rc1-release]). PostgreSQL is the sole database intended for the 8.0 GA target set — + MongoDB is Early Access, SQLite a proof of concept, MySQL later, SQL Server absent + ([scorecard][rc1-scorecard]). +- `@prisma/orm-postgres`, the one package an application installs, publishes 138 top-level export + subpath keys at the pin, spanning adapters, control and contract internals, migration tooling, + query ASTs, runtime, and utilities; re-exporting that surface would convert Early-Access internals + into NetScript public API. +- The seam moved within six days of the RC tag: the `prisma-next` CLI stopped being published in + favour of a unified CLI ([`3dc98cb`][pn-3dc98cb]), migration commands moved behind the control + API, contract JSON Schema became generated, the PostgreSQL floor dropped from 17 to 15, and + aggregate number semantics changed. + +The correct response to a good architecture on a moving surface is to adopt its _semantics_ through +one small allowlisted adapter, and keep NetScript's own vocabulary, artifacts, and operations stable +across the churn. + +## Guide-level explanation + +This section describes the system as if it had shipped. + +> **Example status.** A snippet explicitly marked _complete module_ is complete for the packages in +> [§ The package graph](#the-package-graph); every other snippet is an excerpt whose surrounding +> application values are named where they matter. `@netscript/*` shapes are proposed API. +> `@prisma/*` shapes are observed in the pinned RC1 checkout and linked to it; the exact module +> specifier is an adapter-pinned, implementation-time decision (W3), because Prisma's public CLI +> package name changed six days after the RC tag. + +### Step 1 — author the contract natively + +Schema authoring is Prisma's job and NetScript does not put a vocabulary in front of it. The current +authoring API is model-first: `defineContract(scaffold, callback)`, where the callback receives a +composed helper surface and returns native `types`, `models`, and `enums` +([`define-contract.ts`][rc1-define-contract]; the callback overload preserves its returned literal +types). + +One thing precedes the contract: the configured provider value. A logical extension such as pgvector +has authoring, control, runtime, and validation facets, and the authoring facet has to exist +_before_ the builder runs. The application therefore creates the extension once, registers it once +on the provider, and uses that provider's **public authoring scaffold** with `defineContract`: + +```ts +// database/provider.ts — complete module; the sole live provider/extension composition root +import { pgvector, prismaPostgres } from '@netscript/database-prisma-postgres'; + +const vector = pgvector(); + +export const postgres = prismaPostgres({ + minVersion: 15, + extensions: [vector], +}); +``` + +```ts +// database/app.contract.ts — provider-native authoring; specifier pinned in W3 +import { defineContract, rel } from '@prisma/orm-postgres/contract-builder'; +import { postgres } from './provider.ts'; + +export const appContract = defineContract( + postgres.authoring.scaffold, + ({ field, model, type }) => { + const types = { Embedding: type.pgvector.Vector(1536) } as const; + + const User = model('User', { + fields: { + id: field.id.uuidv4String(), + email: field.text(), + createdAt: field.temporal.createdAt(), + }, + }); + + const Post = model('Post', { + fields: { + id: field.id.uuidv4String(), + userId: field.uuidString(), + title: field.text(), + createdAt: field.temporal.createdAt(), + embedding: field.namedType(types.Embedding).optional(), + }, + }); + + return { + types, + models: { + User: User.relations({ posts: rel.hasMany(Post, { by: 'userId' }) }), + Post: Post.relations({ user: rel.belongsTo(User, { from: 'userId', to: 'id' }) }), + }, + }; + }, +); +``` + +Every helper above is the pinned RC1 spelling, including `field.temporal.createdAt()` and the +`type.pgvector.Vector(1536)` named type ([pinned contract example][rc1-contract-example]). NetScript +neither recreates the fluent `target(...).table(...).column(...)` chain that upstream removed, nor +mirrors this vocabulary in a schema or query DSL of its own, nor re-exports Prisma's builder — it +owns only the orchestration around the contract, and that surface has three levels. + +### Step 2 — three levels of adoption, one application + +The same app and the same `appContract` appear at every level. L1 calls L2; L2 produces the value +L3's primitives consume. Nothing below defines a model, field, relation, or query. + +`postgres.authoring.scaffold` contains Prisma's native PostgreSQL scaffold composed with the +registered extension authoring facets. It does not expose control or runtime implementations. The +same `postgres` module can therefore be imported by build tooling and by the application runtime +without making the runtime import the contract module; the dependency points from the contract to +the provider, never back from the provider to authoring code. + +**L1 — the golden path.** One call with inspectable, replaceable defaults: target id `primary`, app +space `app`, managed ownership, and retain-on-removal. The provider is **not** one of the defaults — +the application constructs exactly one configured provider value and hands it in, so a +provider-neutral package never chooses, imports, or looks up a provider. + +```ts +// database/database.ts +import { fromAspire } from '@netscript/aspire'; +import { defineSingleTargetDatabase } from '@netscript/database'; +import { authSpace } from '@netscript/plugin-auth-core/database'; +import { appContract } from './app.contract.ts'; +import { postgres } from './provider.ts'; + +export default defineSingleTargetDatabase({ + provider: postgres, + contract: appContract, + connection: fromAspire('netscript-db'), + spaces: [authSpace()], // plugin-owned schema, independently versioned +}); +``` + +`defineSingleTargetDatabase` is provider-neutral: it names the shape it supports (one target, one +app space) rather than promising a PostgreSQL implementation from a package that has no provider +dependency, and it literally calls the L2 factories below and returns the same `DatabaseDefinition`. +`fromAspire` is an Aspire-owned **pure reference constructor** exported by `@netscript/aspire`; it +builds plain connection-reference data and performs no IO, and the matching `ConnectionSource` +adapter that resolves it lives in the same package. `@netscript/database` exports only the neutral +`fromEnv` equivalent and never imports Aspire. + +**L2 — the factories L1 calls.** Drop one level for a second target, an explicit policy, a role, or +several app-owned spaces. The recipe is not a parallel implementation: it calls exactly these, and +returns the same `DatabaseDefinition`. + +```ts +// database/database.ts — the same app, one level down +import { fromAspire } from '@netscript/aspire'; +import { + defineDatabase, + defineDatabaseSpace, + defineDatabaseTarget, + fromEnv, +} from '@netscript/database'; +import { authSpace } from '@netscript/plugin-auth-core/database'; +import { appContract } from './app.contract.ts'; +import { postgres } from './provider.ts'; +import { warehouseContract } from './warehouse.contract.ts'; + +const primary = defineDatabaseTarget({ + id: 'primary', + provider: postgres, + connection: fromAspire('netscript-db'), + roles: { writer: {}, 'reader:reporting': { readOnly: true } }, + policy: { destructive: 'deny', defaultOwnership: 'managed' }, +}); + +const analytics = defineDatabaseTarget({ + id: 'analytics', // same provider, different database, zero shared state + provider: postgres, + connection: fromEnv('ANALYTICS_DATABASE_URL'), + policy: { destructive: 'plan-only', defaultOwnership: 'adopted' }, +}); + +export default defineDatabase({ + targets: { primary, analytics }, + spaces: { + app: defineDatabaseSpace({ + id: 'app', + owner: 'app', + version: '1.0.0', + target: 'primary', + contract: appContract, // `typeof appContract` is preserved exactly + policy: { removal: 'retain' }, + }), + [authSpace.id]: authSpace({ target: 'primary' }), + warehouse: defineDatabaseSpace({ + id: 'warehouse', + owner: 'app', + version: '1.0.0', + target: 'analytics', + contract: warehouseContract, + }), + }, +}); +``` + +Adding `analytics` is the entire multi-target delta. The two targets share nothing — separate output +roots, artifacts, lineages, markers, bindings, locks, and receipts — a relation between their models +is refused with `db.compose.cross-target-relation`, and no multi-target operation is ever described +as atomic. + +`defineDatabaseSpace` stores `appContract` and preserves `typeof appContract` unchanged; everything +NetScript adds is plain data that survives a provider replacement. Both coordinates are checked +where their halves are visible: `defineDatabase` requires every space's target to be a key of +`targets` and every map key to equal that contribution's canonical `SpaceId`. Thus +`target: 'primry'` or `{ auth: authSpace(...) }` is a type error at that call; a bypassed check is +refused with `db.compose.target.unknown` or `db.compose.space-id.mismatch` — there is no fallback or +alias chain anywhere. + +**L3 — the native foundation.** The same native contract and definition, but the application owns +the two module-graph phases that the launcher normally sequences. Emission must finish before the +application imports emitted bindings; pretending both happen through static imports in one module +would make first boot impossible and could pair a new manifest with a stale binding. + +```ts +// tools/emit-database.ts — excerpt; a build process runs this before application type-check/load. +// `io` is the explicit artifact source + atomic publisher the launcher normally supplies. +import { compileDatabase } from '@netscript/database'; +import database from '../database/database.ts'; + +const compiled = await compileDatabase(database, io); // offline effects; no connection in scope +if (!compiled.ok) throw new DatabaseCompositionError(compiled.diagnostics); +``` + +The successful atomic publish contains the manifest and one target binding descriptor. The following +is simplified **emitted output**, not code a developer maintains: + +```ts +// .netscript/database/primary.binding.ts — emitted atomically with manifest.ts +import type database from '../../database/database.ts'; +import { + artifactSpaceEvidence, + createPrismaPostgresBinding, + definePrismaPostgresBindingDescriptor, + type QueriesOf, + sourceSpaceEvidence, +} from '@netscript/database-prisma-postgres/binding'; +import type { ProcessSessionOf } from '@netscript/database-runtime'; +import type { AuthContract } from './primary/plugin-auth.contract.d.ts'; +import { manifest } from './manifest.ts'; + +const descriptor = definePrismaPostgresBindingDescriptor({ + target: 'primary', + manifestDigest: 'nsdb1:9f3c…', + spaces: { + app: sourceSpaceEvidence({ snapshot: 'nsdbc1:2c71…' }), + 'plugin:@netscript/plugin-auth': artifactSpaceEvidence({ + snapshot: 'nsdbc1:71ba…', + }), + }, +}); + +export const primaryBinding = createPrismaPostgresBinding({ descriptor, manifest }); +export type PrimaryQueries = QueriesOf; +export type PrimarySession = ProcessSessionOf; +``` + +The compiler, not application code, writes that literal map. Each key is the canonical `SpaceId` +used by definitions, manifests, receipts, `.space(...)`, and diagnostics; local aliases do not +exist. Each value couples type-only evidence to a value-level `ContractSnapshotId`, while the +descriptor itself carries its target and `ManifestDigest`. The adapter rejects a missing, duplicate, +extra, wrong-target, or wrong-snapshot entry before returning a binding, and bind time rechecks the +descriptor against the manifest. Editing or hand-writing the generated module is detected by +`db emit --verify`. + +`app` still gets its exact contract type from erased `typeof database`; no app model type is +generated. The plugin space needs the automatically emitted `AuthContract` declaration because its +publisher supplied data artifacts rather than the consumer's TypeScript source. Prisma spaces stay +separate contracts with separate heads ([space aggregate][rc1-space-aggregate]); this descriptor +associates them but never merges their models or query types. An application that does not query a +pinned space asks the emitter to omit its binding evidence: the space is still planned, applied, and +verified, but has no typed query surface. + +Only after that build phase does the application module graph import `primary.binding.ts` and create +runtime or control values. Nothing downstream receives `DatabaseDefinition`: runtime and control +take the manifest, the same configured provider value, connections, and emitted bindings. + +#### Who owns what + +| Surface | Owner | Source of truth | Produces / lowers to | Must not cross | +| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `defineContract`, ORM and SQL query surfaces | `@prisma/orm-postgres`, imported directly by app and plugin authoring modules | Prisma | native contract value, `contract.json`, `contract.d.ts` | never mirrored, wrapped, or re-exported by NetScript | +| L1 `defineSingleTargetDatabase` and the L2 `defineDatabase*` factories | `@netscript/database` | this RFC | L1 calls L2 → one `DatabaseDefinition` → `resolveDatabase`/`compileDatabase` | no schema or query vocabulary, no provider import, no live IO | +| `prismaPostgres(...)` and `pgvector(...)` bundles | `@netscript/database-prisma-postgres` plus compatible extension publishers | provider composition | one configured provider carrying registered extension identities and live facets | manifest stores only pins; runtime code never reconstructs executable facets from data | +| `fromAspire` and its `ConnectionSource` adapter | `@netscript/aspire` | Aspire | plain connection-reference data, resolved at runtime | reference construction performs no IO; the kernel never imports Aspire | +| emitted target descriptor; `createPrismaPostgresBinding`, `QueriesOf` | compiler; `@netscript/database-prisma-postgres/binding` | app-local `typeof` evidence + emitted declarations + manifest | canonical per-space query/transaction types and a digest-verifying runtime value | no hand-written evidence map, provider-neutral query API, or local space alias | +| Sessions, validators, ports | `@netscript/database-runtime`, `@netscript/database-control` | manifest, binding, pinned artifacts | typed sessions, Standard Schema values, plans, receipts | provider-neutral packages never name a Prisma type | +| CLI, Aspire resources, agent surfaces | `@netscript/cli`, `@netscript/aspire` | `DatabaseManifest` + operation catalog | commands, resources, agent schemas | never evaluates authoring TypeScript | + +#### The normal loop has no manual type generation + +`netscript dev`, `start`, `test`, and `build` compile the authoring graph to a content-addressed +artifact set before the runtime loads; generated task dependencies give a plain `deno task` the same +behaviour. `dev` watches the graph, writes a temporary artifact set, verifies it, and atomically +swaps the directory before restarting affected consumers — which is also how the generated +declaration for an artifact-only space stays current without anyone running a type-generation +command. CI runs an explicit `netscript db emit --verify` compile-and-diff so a stale commit fails +there rather than in production. A digest mismatch is still a hard refusal that names the file that +changed, but the normal launcher has already repaired it, so `db emit` is an escape hatch, never a +ritual. Compilation is not migration: it reads authoring sources and publishes artifacts, and it +never opens a connection, plans, or applies. Plan and apply authority stays explicit. + +### Step 3 — sessions and queries + +```ts +// composition-root.ts — complete module; the only place a target is bound by name +import { aspireConnections } from '@netscript/aspire'; +import { + createDatabaseRuntime, + envConnections, + resolveConnections, +} from '@netscript/database-runtime'; +import { manifest } from './.netscript/database/manifest.ts'; +import { primaryBinding, type PrimarySession } from './.netscript/database/primary.binding.ts'; +import { PrismaAccountStore } from './database/accounts.store.ts'; +import { postgres } from './database/provider.ts'; +import type { AccountStore } from './ports/account.store.ts'; + +const connections = await resolveConnections(manifest, [aspireConnections, envConnections]); + +await using runtime = await createDatabaseRuntime({ + manifest, + providers: [postgres], + bindings: [primaryBinding], + scope: 'process', + connections, +}); + +const primary: PrimarySession = runtime.bind(primaryBinding); // digests verified before any query +const accounts: AccountStore = new PrismaAccountStore(primary); // application-owned port +``` + +```ts +// database/accounts.store.ts — complete application-owned adapter. `space` selects one contract +// space; the surface inside it is Prisma's own (shapes follow the pinned RC1 ORM examples). +import type { FieldValueOf } from '@netscript/database-prisma-postgres/binding'; +import { primaryBinding, type PrimarySession } from '../.netscript/database/primary.binding.ts'; +import type { AccountStore } from '../ports/account.store.ts'; + +type UserId = FieldValueOf; + +export class PrismaAccountStore implements AccountStore { + constructor(private readonly primary: PrimarySession) {} + + recentPosts(userId: UserId, limit: number) { + return this.primary.space('app').orm.Post + .where({ userId }) + .orderBy((post) => post.createdAt.desc()) + .take(limit) + .all(); + } + + register(id: UserId, email: string) { + return this.primary.transaction( + 'app', + (tx) => tx.orm.User.select('id', 'email').create({ id, email }), + ); + } +} +``` + +Those are the RC1 collection shapes — Pascal-case models, fluent `where(...)` filtering, +`orderBy(...).take(...).all()` reads and `select(...).create(...)` writes ([filter][rc1-orm-filter], +[reads][rc1-orm-read], [writes][rc1-orm-write]). The ID type is derived from the binding because +RC1's UUID string codec is a branded `Char<36>`, not an ordinary `string`; external text reaches +this port only after a boundary schema validates and decodes it to `UserId`. `space('app')` hands +back the provider's own facade, so `.orm` is the ORM collection client and `.sql` is the same SQL +DSL escape hatch the provider already ships; NetScript wraps neither and adds no query language of +its own. `postgres` is the identical configured provider value the target declared, imported from +the application's own database module, so no composition root builds a second one. Connections are +resolved from the manifest's connection references through `ConnectionSource` adapters, which is the +only place Aspire enters the picture. + +Feature code receives `AccountStore` — an application-owned port — not the runtime. `runtime.bind` +is reachable only from declared composition-root files, enforced by `arch:check`, because a database +handle reachable from anywhere is a service locator with a domain name; NetScript generates no +repositories. + +Space selection is explicit because spaces are separate contracts, and the transaction callback +receives that space's own inferred transaction type, **distinct** from its query type: whether an +interactive transaction exposes exactly the ordinary surface is upstream behaviour W4 must prove. +Interactive transactions exist only on process-scoped sessions; a request-scoped session is +`AsyncDisposable`, caches no collaborators, and has no `transaction` member at all. + +### Step 4 — validation at trust boundaries + +Validators come from the registered values, not from the contract alone, and there is no generated +validator file anywhere in the repository. The contract proves model **values**; the create, update, +and filter grammar the collection surface accepts is compile-time-only at run time (see +[§ the runtime validation subsystem](#the-runtime-validation-subsystem)), so an **operation pack** +has to contribute it. The configured provider value carries exactly one — `prismaPostgres` registers +`ormCollection@1`, covering the RC1 collection grammar — through the same single registration flow +as every other facet: no second import, no separate validator wiring. That pack's `(id, version)` is +recorded in the manifest beside the provider pin and enters every derived validator's cache key, so +`input('create', …)` below is supported _because_ `ormCollection@1` is registered for this space. A +space whose provider or extensions contribute no pack for an operation fails at schema construction +instead of guessing. + +```ts +import { primaryBinding } from './.netscript/database/primary.binding.ts'; + +const users = primaryBinding.ref({ space: 'app' }).model('User'); + +const createUser = users.input('create', { representation: 'json' }); +const publicUser = users.output({ select: { id: true, email: true } }, { representation: 'json' }); +const wholeUser = users.output('model', { representation: 'json' }); +``` + +Two methods, two representations. `input` produces an **operation input** schema — the pack-backed +half — while `output` produces a selected-result schema or the whole-model shape under the explicit +`'model'` form. The literal `select` above is a validation projection, not a second query API and +not automatically the identity of a later query: the route handler's inferred result is checked +against the schema output type. The overload also accepts a provider-produced plan or selection +value when the adapter can prove every projected leaf; W3 must prove that public coupling for the +pinned ORM, and otherwise the explicit projection is the honest fallback. The only public +representations are `runtime` and `json`. Both implement `StandardSchemaV1`, so they drop into +independent consumers unchanged, and each boundary uses the schema that actually describes it: + +```ts +// excerpt: `baseContract` is the application oRPC builder. +const createAccount = baseContract + .route({ method: 'POST', path: '/accounts' }) + .input(createUser) + .output(publicUser); + +// excerpt: `formPayload` is already a JSON-shaped object, not a raw FormData value. +const parsed = await createUser['~standard'].validate(formPayload); +if (parsed.issues) return renderFieldErrors(parsed.issues); +``` + +Validating an inbound payload with a query-result schema is a category error, and the API's shape +makes it visible rather than merely discouraged. + +Both limits are enforced rather than documented. An unsupported operation — or an `output` selection +whose leaves are computed, raw, or aggregated — throws `DB_VALIDATION_UNSUPPORTED` while the schema +is being constructed, naming the missing metadata. Invalid user data never throws: it returns +Standard Schema issues with a field path, a stable code, and the contract coordinates. + +### Step 5 — install a plugin that owns its schema + +A plugin whose tables outlive an install — auth, workers, sagas — contributes a **full space**: its +own native contract, canonical artifact, migration lineage, and head, versioned independently of the +application. + +```ts +// plugins/auth/core/src/database.ts — the plugin owns a space, not a fragment +import { CAP, pinnedSpace } from '@netscript/database-contract'; +import { definePluginSpace } from '@netscript/plugin'; +import { authSpaceAggregate } from './artifacts/auth.space.ts'; + +export const AUTH_SPACE_ID = 'plugin:@netscript/plugin-auth' as const; + +export const authSpace = definePluginSpace({ + id: AUTH_SPACE_ID, + owner: '@netscript/plugin-auth', + version: '0.0.7', + contractFormat: '>=1 <2', + requires: [CAP.sqlFamily, CAP.nativeUuid], + owns: { tables: ['auth_user', 'auth_session', 'auth_account', 'auth_verification'] }, + augmentation: { + grants: [{ object: 'auth_user', kind: 'add-optional-column', prefix: 'x_' }], + denies: ['drop-column', 'change-type', 'add-required-column'], + }, + policy: { removal: 'retain' }, + // A generated module statically materializes the whole aggregate in Deno's module graph. + space: pinnedSpace(authSpaceAggregate), +}); +``` + +`definePluginSpace` returns a **callable descriptor** carrying its literal `.id`: `authSpace()` +takes the single target an L1 application has, `authSpace({ target: 'primary' })` names one +explicitly at L2, and both produce the same `SpaceContribution`. L2 keys the contribution with +`[authSpace.id]`; there is no shorter local alias whose meaning disappears at run time. +`auth.space.ts` is a checked-in deterministic generated module that statically contains or imports +every descriptor, canonical contract value and declaration, migration package/graph, head, hash, and +provenance record. It is in the publisher's explicit JSR asset/export allowlist, so Deno +materializes the complete graph before executing the consumer; `compileDatabase` receives an +already-loaded value and performs no fetch. The release gate proves a cold remote consumer can +materialize the package once and then run emit/verify with network access disabled. + +Installation copies nothing into the application's schema; it publishes that pinned aggregate under +the application's generated root, mirroring the shape Prisma's own migration tooling already loads +per space ([space aggregate][rc1-space-aggregate]). Production apply and verify read the local +mirror, so a deployment never needs the plugin package graph resolvable, and an aggregate that +disagrees with the installed package is `db.space.skew`. Typed queries against the space use the +consumer declaration emitted from that same aggregate — the `AuthContract` import in the binding +above — and the spaces are never merged. + +Ownership is checked over `(target, namespace, object kind, name)`, not over declaration text, so +two spaces wanting a table named `user` are a conflict naming both. Because the first adapter +supports one physical namespace per target, physical name collisions are refused at composition and +a published space names its objects so they cannot collide. + +Uninstalling is a planned operation, not a directory delete: **detach-and-retain** removes the +runtime binding while data, provider marker, lineage, and ownership history stay behind a +verify-only tombstone. + +### Step 6 — one extension value, registered once + +Upstream, one logical extension is several modules: `@prisma/orm-extension-pgvector/pack` for +authoring and `@prisma/orm-extension-pgvector/runtime` for the runtime facet, plus control wiring. +Registering some of them and forgetting the rest is silent until something fails. Those runtime and +control modules are exactly what an application must not import, so the **adapter or a compatible +extension publisher** assembles one bundle for the provider boundary: + +```ts +// @netscript/database-prisma-postgres — assembled inside the provider boundary, not by the app +export declare function pgvector(options?: PgVectorOptions): PostgresExtension<'pgvector'>; +// → { id, version, requires: [CAP.pgvector], authoring, control, runtime, validation } +``` + +The application creates the extension **once**, before the contract, and passes it once to +`prismaPostgres({ extensions: [...] })` (Step 1). That provider composes +`postgres.authoring.scaffold` for the app's one native `defineContract` call and retains the same +bundle's executable control, runtime, and validation facets. The completed contract records the +extension identity and version. Later, `compileDatabase` does **not** invoke the builder again: it +compares those recorded pins with the extensions registered on the target's provider, refuses a +duplicate, missing identity, version skew, or facet mismatch with +`db.compose.extension.facet-mismatch`, and writes only serializable pins and capabilities to the +manifest. At run time the application supplies the same configured `postgres` value; runtime and +control obtain executable facets from it, never from manifest data and never from a global registry. + +This is a two-stage flow, not retroactive authoring: **authoring** evaluates the app-owned native +builder with the already-composed scaffold; **offline compilation** verifies, canonicalizes, and +publishes. A third-party publisher participates by returning a compatible `PostgresExtension` value +to the application's explicit provider configuration. The L3 escape hatch remains native: an author +may assemble Prisma's public pack directly, but a NetScript target using that contract is accepted +only when its configured provider carries the same extension identity/version and all facets +required by the claimed capabilities. Otherwise native authoring still works outside the NetScript +seam, while NetScript runtime/control/validation correctly refuse it. + +### Step 7 — the operational journey + +Every operation is a typed programmatic call first; the CLI, the docs, and the agent surface are +projections of the same catalog. The API boundary — not a promise in prose — is what proves that +pure work cannot reach a database: + +```ts +// excerpt: `manifest`, `postgres`, and `connections` are the values bound in Step 3 +import { createDatabaseControl } from '@netscript/database-control'; +import { newRunId } from '@netscript/database-contract'; + +const runId = newRunId(); +const policy = { destructive: 'allow-with-approval' } as const; + +// Pure control: artifacts and policy only. It has no connection resolver to reach. +const control = createDatabaseControl({ manifest, providers: [postgres] }); + +const advisory = await control.preview({ targets: ['primary'], runId }); + +// Live control: constructed from the pure catalog by supplying explicit live dependencies. +await using live = await control.connect({ connections }); + +const baseline = await live.inspect({ targets: ['primary'], runId }); +const plan = await live.plan({ targets: ['primary'], baseline, policy, runId }); + +const signed = await control.sign(plan); // artifact-side: no database, no lock +const applied = await live.apply({ plan: signed, runId }); +const verified = await live.verify({ targets: ['primary'], runId }); +``` + +There is deliberately no `control.emit`. `emit` is the operation-catalog/CLI projection of +`compileDatabase(definition, sourceAndPublisher)` from L3; the explicit `ArtifactPublisher` is its +effect port, and the control package never receives a definition. It is offline because there is no +connection in scope, not because an injected resolver happens to go unused. This is the structural +closure of the `DB-GENERATE-ASPIRE-COUPLING` debt entry: Aspire is a property of a target's +connection source, and a pure operation never receives one. + +```console +$ netscript db plan --target primary --json +{ + "operation": "plan", + "runId": "01JYZ…", + "outcome": "succeeded", + "perTarget": [ + { + "target": "primary", + "status": "succeeded", + "spaces": [ + { "space": "app", "status": "planned", "steps": 3, "destructive": 0 }, + { "space": "plugin:@netscript/plugin-auth", "status": "planned", "steps": 1 } + ], + "plan": { "planId": "plan:4c19…", "expiresAt": "2026-08-13T18:42:00Z" } + } + ], + "diagnostics": [], + "nextAction": { "operation": "apply", "args": { "plan": "plan:4c19…" } } +} +``` + +Four properties follow from that shape. Every requested target appears with a status — no silent +skip, no implicit "all". `nextAction` is structured data, so CLI, CI annotations, and agents render +the same remediation without parsing prose. Human text is never a contract; gates assert on codes. +And the exit code is a projection of `outcome` (`succeeded` → 0, `refused`/`failed` → non-zero, +`partial-success` → non-zero with a resume token), never the result itself. + +When something goes wrong, the vocabulary is equally explicit: + +```console +$ netscript db apply --plan plan:4c19… +error db.plan.stale: plan plan:4c19… was bound to manifest nsdb1:9f3c…, current is nsdb1:12ab… + target: primary + next: netscript db plan --target primary +``` + +### What you stop doing, and what you are refused + +Copied plugin fragments, self-repairing generate pipelines, hand-synchronised Zod mirrors, deep +imports into generated output, silent target defaulting, Aspire-to-compile, log-scraped migration +results, and hand-maintained agent instructions all stop being developer-visible work. What the +system declines to do is equally explicit: + +| You try to… | You get | +| --------------------------------------------------------------------- | -------------------------------------------------------------------------------- | +| Bind a space to a target that does not exist | A **type error** at `defineDatabase`; `db.compose.target.unknown` if bypassed | +| Declare a relation between models in two targets | `db.compose.cross-target-relation` | +| Let two spaces manage one object or claim one table name | `db.compose.ownership.conflict` / `db.compose.object-name.conflict`, naming both | +| Use a capability the bound target does not declare | `db.compose.capability.missing`, naming capability, space, target | +| Request a non-default physical namespace | `db.target.namespace-unsupported` — withheld, not faked | +| Apply a speculative preview | Refusal: a preview has no `planId`; `apply` takes bound plans only | +| Apply a plan after manifest, baseline, pins, or policy changed | `db.plan.stale`; after expiry, `db.plan.expired` | +| Migrate a read replica | Refusal: replicas are roles, and no operation addresses a role | +| Run a destructive production step on an interactive "yes" | Refusal: production requires an approved, signed plan | +| Build a validator with no contributed operation or selection metadata | `DB_VALIDATION_UNSUPPORTED` at schema construction | +| Target Prisma SQLite, MongoDB, MySQL, or SQL Server | `db.target.unsupported` — no fallback, no Prisma 7 path | +| Drop a plugin's tables on uninstall | Refusal: `retain` is guaranteed; `archive`/`drop` await conformance | + +## Reference-level explanation + +### Vocabulary and identity + +Similar-looking values are intentionally distinct; conflating any two is a review finding. + +| Term | Meaning and invariant | +| -------------------- | ----------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Authored targets, spaces, connections, capabilities, policy. Pure; no IO. Not a manifest. | +| `NativeContract` | A Prisma `defineContract` result; NetScript never translates its vocabulary. | +| `AppBinding` | App-local bridge from authored contracts to sessions and validators. Never published. | +| `SpeculativePreview` | Advisory only. **Cannot be approved or applied**; has no `PlanId`. | + +A `SpaceContribution` carries a space's owner, version, target, dependencies, ownership, +capabilities, artifact refs, and retention; `ValidationIR` is the internal, never-exported +value/selection algebra behind the validators. `DatabaseDefinition`, `DatabaseManifest`, +`ExecutablePlan`, `ProviderMarker`/`ProviderLedger`, and `OperationReceipt` stay separate, and a +provider-owned `ContractArtifact` is pinned per space and distinct from all five. + +Identity is declared, never derived: provider names, engine names, filesystem paths, config aliases, +and traversal order are never identities and never dependency edges. + +| Identity | Notes | +| --------------------- | ------------------------------------------------------------------------------------------- | +| `TargetId` | Author-chosen. Owns connection, output root, binding, lineage, locks, receipts. | +| `RoleRef` | `(TargetId, 'writer' \| 'reader:')`. A replica is a role; no operation addresses one. | +| `NamespaceRef` | `(TargetId, namespace)`. Kernel axis; the first adapter declares only the default. | +| `SpaceId` | `'app'`, `'plugin:@netscript/plugin-auth'`. One schema owner; never an install path. | +| `ObjectKey` | `(TargetId, namespace, objectKind, name)`. Unit of ownership; one `managed` owner. | +| `RunId` / `ReceiptId` | Sortable ids supplied at the edge, so receipts are addressable and resumable. | + +`ContractSnapshotId`, `ManifestDigest`, and `PlanId` are content hashes, described with the +artifacts they address. + +### The package graph + +Six new units and four changed ones. Each has exactly one doctrine archetype; where two genuinely +apply, the remedy is two packages, not one package with two shapes. + +| Unit | Archetype | Why this boundary exists | +| ------------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database-contract` | A1 | Identities, artifacts, diagnostics, SPIs. Zero dependencies, so everything can depend on it. | +| `@netscript/database` | A4 | L1 recipe, L2 factories, `ContractOf`, and deterministic resolution; separation from control keeps composition free of live IO. | +| `@netscript/database-runtime` | A3 | Scope, binding, connection ownership, close ordering, cancellation — the mandatory A3 gate column. | +| `@netscript/database-control` | A2 | Catalog, plan/apply/verify, policy, locks, receipts, recovery, saga — with failure-injection gates. | +| `@netscript/database-prisma-postgres` | A2 | The **only** framework Prisma import boundary, extensions included; independently versioned. | +| `@netscript/database-testkit` | A6 | Runnable provider **and space** conformance certification with machine-readable reports. | + +Four existing units change: `@netscript/plugin` (A4) gains `definePluginSpace` typed only by +`-contract` and loses the legacy database abstracts; first-party `plugins/*` (A5) become thin +descriptors plus pinned artifacts; `@netscript/aspire` (A2) narrows to one `ConnectionSource` +adapter and a manifest-derived resource projection, **never required by a pure operation**; and +`@netscript/cli` (A6) projects the operation catalog with no database logic and no engine switch. + +The dependency edges are exact, and each clause is mechanically checkable: + +- `@netscript/database-contract` imports nothing from this family and no provider. Everything else + depends on it. +- `@netscript/database` depends on `-contract` only. It owns the L1 recipe, the L2 factories, and + deterministic resolution. +- `@netscript/database-runtime` and `@netscript/database-control` depend on `-contract` only. They + consume manifests, pinned artifacts, and the shared SPIs — never a `DatabaseDefinition`, so they + have no reason to depend on `@netscript/database` — and they never import each other. +- `@netscript/database-prisma-postgres` implements the published runtime and control SPIs and is + supplied to both as a value by the application composition root. +- `@netscript/plugin` publishes plain contributions typed by `-contract`, with no provider, runtime, + or control dependency. +- `@netscript/database-testkit` may depend on every public surface; nothing depends on it at + runtime. + +**No provider-neutral framework package depends on a provider** — providers are composition-root +values, so there is no global registry and no lookup by string — and **no framework package +re-exports Prisma**: only the adapter and extension publishers import Prisma runtime or control +modules, while application and plugin authoring modules import Prisma's public authoring builder +during the controlled build phase. The adapter owns exactly two public subpaths, its root and +`/binding`; provider-specific `defineContractFragment` lives at the adapter root rather than leaking +a Prisma helper type into `@netscript/database`. W1/W3 cannot publish any of these surfaces until +documentation/type lint, `isolatedDeclarations`, JSR dry-run, packed and cold remote consumers, +explicit aggregate-module asset inclusion, network-disabled emit/verify after dependency +materialization, provenance, and release E2E all pass. + +Doctrine currently codifies the model this RFC removes — Archetype 5 makes plugin database +contributions plain `*.prisma` files ([archetypes](../docs/architecture/doctrine/06-archetypes.md)) +— so wave W0 amends it and registers every new unit in the gated denominator. No database package +inherits the oRPC-only `--allow-slow-types` carve-out +([public surface](../docs/architecture/doctrine/02-public-surface.md)). + +### The definition layer and type propagation + +`defineDatabaseSpace` wraps an already-authored native contract: `TContract` is inferred from the +passed value and never widened, re-keyed, or re-interpreted, so `SpaceDefinition['contract']` has +type `TContract`. The target key is checked one level up, where both halves are visible: + +```ts +// @netscript/database + +/** Composes targets and canonically keyed spaces into a frozen definition. */ +export declare function defineDatabase< + const TTargets extends Readonly>>, + const TSpaces extends Readonly< + Record, unknown>> + >, +>( + input: { + targets: TTargets; + spaces: + & TSpaces + & { + readonly [K in keyof TSpaces]: DatabaseSpaceDefinition< + Extract, + Extract, + unknown + >; + }; + }, +): DatabaseDefinition; + +/** + * Mathematically pure and total: in-memory resolution of a definition plus already-loaded contract + * snapshots. No IO of any kind; it returns diagnostics instead of throwing on authoring mistakes. + */ +export declare function resolveDatabase( + definition: AnyDatabaseDefinition, + snapshots: readonly ContractSnapshot[], +): + | { readonly ok: true; readonly manifest: DatabaseManifest } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] }; + +/** + * Offline effects only: reads contract artifacts through the supplied source, calls + * `resolveDatabase`, and atomically publishes the emitted artifact set. Never resolves a + * connection, Aspire resource, secret, or network endpoint. + */ +export declare function compileDatabase( + definition: AnyDatabaseDefinition, + io: ContractArtifactSource & ArtifactPublisher, +): Promise< + | { readonly ok: true; readonly manifest: DatabaseManifest } + | { readonly ok: false; readonly diagnostics: readonly Diagnostic[] } +>; +``` + +The split matters because "pure" is used for two different things elsewhere in this document. +`resolveDatabase` is pure in the mathematical sense. `compileDatabase` performs offline effects — +loading sources, publishing artifacts — and is classified `pure` **only** in the operation catalog's +sense defined below: no live database, network, or connection. Live control never receives a +definition at all. + +Four inference rules, each with a conformance fixture: literal preservation through `const` type +parameters; **contract identity**, so `typeof definition.spaces.app.contract` is exactly +`typeof appContract`; **no structural widening**, so a deliberately widened fixture must _fail_ its +soundness gate; and **no leakage into neutral packages**, so no **provider-neutral** NetScript +declaration names a Prisma type. `ContractOf` extracts one space's contract +evidence as an opaque generic; mapping it to concrete Prisma query and transaction types is the job +of the adapter's explicitly provider-specific `/binding` declaration, which is allowed to name +Prisma types because that is precisely what it is for. + +Two tracks run in parallel and must never be merged. The **inference track** is `typeof definition`: +provider generics valid only inside the application's own compilation, erased at run time. The +**identity track** is `ContractSnapshotId` and `ManifestDigest`: plain data used by plans, markers, +receipts, validators, and agents, crossing every boundary freely. Conflating them is how a system +ends up unable to answer "is this database consistent with this build?" without type-checking, so +every binding carries the digests and refuses a mismatch at bind time with `db.artifact.stale`. + +#### Where each space's type evidence comes from + +Two upstream facts decide the app-authored case. Prisma's emitted runtime option type carries a +compile-time `TContract` in a phantom `_contract?: TContract` field beside the runtime +`contractJson` ([`postgres.ts`][rc1-postgres-runtime]), and the no-emit path passes the authored +value directly as `postgres({ contract })` ([no-emit context][rc1-no-emit]) — so a +query surface can be typed from `typeof` while the runtime value comes from the canonical artifact. +And root `deno.json` enables `isolatedDeclarations`, under which an exported inferred +`defineContract(...)` constant needs an explicit annotation; app-owned authoring modules are **build +inputs, not JSR exports**, so that narrow app-local project sets `isolatedDeclarations: false` while +every published `@netscript/*` package keeps it `true`. For app-authored spaces no contract +declaration or generated model/query type is emitted, no neutral declaration names a Prisma type, +and no slow-types waiver is requested: evidence flows +`typeof definition → ContractOf → emitted adapter binding descriptor`. + +A consumer cannot do that for a space it did not author. A pinned plugin space arrives as artifacts, +and TypeScript cannot reconstruct an exact contract type from JSON. For those spaces — and for an +application that deliberately exports an inferred definition from a publishable package — the +provider **declaration** is generated **automatically and atomically in the same compile** that +publishes the artifacts. The compiler also emits the target binding descriptor shown above: it +references app-authored spaces through `typeof definition`, artifact-only spaces through their +generated declarations, and couples both to value-level snapshot identities. This is generated +wiring, not generated app model types. It is never hand-run, never a framework slow type, and never +control authority: runtime and control still consume the manifest, descriptor, and pinned artifact +values, and a declaration only tells the type checker what the artifact already says. + +The fallback is bounded to exactly those two boundaries, both proved in W3. If direct app inference +turns out to require a private import, a copied overload, a cast, a provider type in a neutral +package, or runtime evaluation of authoring code, that is recorded as a **W3 kill/rethink +criterion** — the layered surface is reconsidered rather than silently promoted to universal +generation. + +**The one deliberate soundness seam.** `runtime.bind` returns a session whose source-authored query +types are erased at run time. Application code cannot supply an arbitrary type map: the compiler +emits the descriptor from the same resolution that emits the manifest, with canonical `SpaceId`s, +provider pin, manifest digest, and per-space snapshot ids. The adapter verifies those values before +constructing the binding, and conformance swaps every target, space, declaration, and snapshot in +turn to prove a mismatch fails at construction or bind rather than at first query. + +### Contribution modes + +The mode decides migration ownership, and it is explicit. + +| Mode | Owns migrations | Used for | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | -------------------------------------------------------------- | +| Space (`definePluginSpace`, `defineDatabaseSpace`) — a complete native contract, canonical artifact, lineage, and head, published as pinned data | The contributor | **All persistent plugin-owned tables**, and application schema | +| App-local fragment (`defineContractFragment`) — a function taking the exact composed native helpers and returning const-preserved `types`/`models`/`enums` | The application | Application schema split across modules | + +A fragment's `build` parameter necessarily names the provider's composed helper type, so under +`isolatedDeclarations` a **published** package cannot export one without putting a Prisma type in a +published declaration. Fragments are therefore application-local and a published fragment is a gate +failure — which is why persistent plugin tables default to full spaces published as plain data plus +pinned artifacts. + +Extension composition and contract compilation are ordered but do not invoke the builder twice. The +app first configures the provider extensions, then its explicit contract root invokes Prisma's +native builder once and invokes app-local fragments in dependency order against that composed helper +surface. The later offline compiler verifies extension pins, dependency edges, capability +requirements, ownership, and cycles; canonicalizes the completed contract; and atomically publishes +artifacts. Only the in-memory resolution step is mathematically pure — publishing is an explicit +offline effect. The authoring root uses explicit calls and const-preserving spreads in deterministic +order, never a registry, `Array.reduce`, or `Record`, and fragment order must not +change the canonical digest. Plugin spaces never appear in that root. + +```ts +// database/contract-root.ts — excerpt; app-owned fragments in one const-preserving native root +export const primaryContract = defineContract(postgres.authoring.scaffold, (h) => { + const billing = billingFragment.build(h, {}); + const app = appFragment.build(h, { billing }); + + return { + types: { ...billing.types, ...app.types }, + models: { ...billing.models, ...app.models }, + enums: { ...billing.enums, ...app.enums }, + } as const; +}); +``` + +### Artifacts and their authority + +Six separately named values, with disjoint responsibilities. Nothing else is authoritative for these +questions. + +| Value or artifact | Authoritative for | Identity and failure behaviour | +| ----------------------------------- | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | +| `DatabaseDefinition` | Authored intent | Consumed only by `compileDatabase` in `@netscript/database`; no runtime, control, apply, or verify path takes one | +| `ContractArtifact` | Provider contract content | `ContractSnapshotId`; `db.artifact.stale` refuses to plan or bind | +| `DatabaseManifest` | Resolved desired composition | `ManifestDigest` over the canonical manifest including pins; a different digest refuses and names both | +| `ExecutablePlan` | What will be executed | `PlanId`; `db.plan.stale`, `db.plan.expired`, `db.plan.revoked` | +| `ProviderMarker` / `ProviderLedger` | **Applied state** | Provider-owned opaque versioned attributes; divergence is drift, classified by ownership | +| `OperationReceipt` | Evidence of attempts and observations | `ReceiptId` per run, ordered checkpoints; never desired state, and resume reads it _plus_ live state | + +Manifests and plans carry secret _references_ only, so a plan is safe to commit and archive. +Artifact roots are staged and atomically committed, never patched in place. Receipt outcomes are +`succeeded`, `refused`, `skipped`, `failed`, `partial-success`, `cleanup-required`, +`outcome-unknown`, and `cancelled`; the last three are separate from `failed` because "the ledger +was repaired" must never read as "the database was repaired" ([Flyway repair][flyway-repair]). + +Composition is pure and total: every invariant it checks has a diagnostic and a negative test, and a +determinism gate asserts that `ManifestDigest` is a pure function of the definition, its snapshots, +and its pins. + +### Operations, plans, and recovery + +Operations are classified before they run, and the class determines what an operation may resolve. +In this catalog `pure` means **no live database, network, connection, or orchestrator** — not +side-effect-free: `emit` is the CLI/catalog projection of `compileDatabase`, reads authoring +artifacts, and publishes through its explicit atomic publisher. `compose` projects +`resolveDatabase`; neither operation is a method on `DatabaseControl`. The control package does not +own the compiler, and live control never receives a `DatabaseDefinition`. + +| Class | Examples | May resolve | Lock | +| ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | +| `pure` | `compose`, `emit`, `inventory`, offline `preview`, `sign` | Artifact readers, the atomic publisher, the signature policy. **Never** a connection, Aspire, Docker, secrets, or the network. | No | +| `live-read` | `inspect`, live `preview`, `plan`, `verify` | An explicit target connection | No | +| `mutating` | `apply`, `seed`, adoption baseline, space retirement | An explicit connection, provider lock/fencing, a bound plan | Yes | +| `resident` | `studio`, and anything whose connection lives inside a host | An explicit target and an orchestration binding | Advisory | + +`sign` is deliberately `pure`: signing binds a policy decision to an artifact, so it neither takes a +connection nor acquires a migration lock. A plan is created only from an inspected baseline and +binds everything that could invalidate it — manifest digest, closure, baseline fingerprint, provider +pins, policy decision, environment, secret references, ordered steps, the destructive-operation list +with its data-loss risk, and a mandatory expiry. In CI and production the policy must be +`allow-with-approval` **and** the plan must carry a signature. + +```mermaid +stateDiagram-v2 + [*] --> planned + planned --> acquiring_lock + acquiring_lock --> refused: db.apply.lock.held (owner, nonce, TTL reported) + acquiring_lock --> locked + locked --> revalidating: re-check manifest, baseline, pins, policy, expiry + revalidating --> refused: db.plan.stale / db.plan.expired / db.plan.revoked + revalidating --> applying + applying --> applying: atomic receipt checkpoint per irreversible step or transaction group + applying --> outcome_unknown: transport lost after dispatch + applying --> failed + applying --> cancelled: AbortSignal + applying --> applied + applied --> verifying + verifying --> succeeded + failed --> cleanup_required: a non-transactional step left objects behind + outcome_unknown --> inspect_before_resume + cleanup_required --> inspect_before_resume + cancelled --> inspect_before_resume + inspect_before_resume --> revalidating: resume only steps whose outcome is known and unfinished + succeeded --> [*] + refused --> [*] +``` + +The rules that give that diagram teeth. **Resume never blindly replays** non-idempotent DDL or a +data transform: it inspects live state and the provider ledger first, revalidates the plan bindings, +and continues only operations whose outcome is known and unfinished. Because resume is a _lookup_, +the receipt store supports append plus lookup by `RunId`, `ReceiptId`, and resume token, and an +implementation may split those into source and sink roles. **Checkpoints are per irreversible +operation or provider transaction group.** **Lock scope is `(target, physical database)`**, with +owner identity, nonce, fencing evidence where the provider supports it, TTL, heartbeat, and explicit +force-unlock preconditions; a provider without a certified lock is refused for concurrent-safe +apply. + +**Multi-target execution is a saga, never a transaction.** Selection expands to a dependency +closure, records every omission with a reason code, orders targets deterministically, and gives each +its own runner, lock, and receipt. + +Rollup is a total deterministic function over terminal statuses. Every selected space ends in +exactly one of `succeeded`, `skipped` (deliberately excluded, with a recorded reason), or a +non-success status — `outcome-unknown`, `cleanup-required`, `failed`, `refused`, `cancelled` — in +that closed dominance order. A target is `succeeded` when every selected space is `succeeded` or +`skipped` and at least one succeeded; `skipped` when every selected space is `skipped`; otherwise it +takes the dominant non-success status among its spaces. Mixed space outcomes therefore never make a +target "partially successful". The run applies the same function one level up: `succeeded` when +every selected target is `succeeded` or `skipped` with at least one success, `skipped` when all are, +`partial-success` when at least one target succeeded **and** another has a non-success status, and +otherwise the dominant non-success status — so a run in which no target succeeded is never reported +as partial success. + +Selective execution is recovery machinery, not the normal deployment path +([resource targeting][tf-targeting]). The catalog is the source: CLI, Aspire, docs, and agent +surfaces are projections, a freshness gate fails on any diff, and a conformance case executes every +documented example. + +### The runtime layer + +A session carries its `TargetId`, scope, per-space contract snapshot ids, a `health(signal)` method, +and `space(id)`. That call returns the provider's own facade for one space — for the Prisma adapter, +`.orm` is the collection client and `.sql` the SQL DSL escape hatch, both exactly as upstream ships +them — typed from that space's own evidence. Scope is a **type**, not a configuration flag: +`ProcessTargetSession` adds `transaction(space, run, options?)`, while +`RequestTargetSession` is `AsyncDisposable`, caches no collaborators, and has no +`transaction` member at all — the same asymmetry Prisma's serverless facade encodes by omitting its +closure-cached surfaces. + +Guarantees the A3 gates must prove: **one lifecycle owner** — no `setClient`, no circular assembly; +**close ordering** — sessions drain before connections close, in reverse bind order, leak-free +across repeated start/stop and request lifecycles; **cancellation** — every long-running call takes +an `AbortSignal`, observable in the receipt and never orphaning a connection; **readers cannot +migrate**; **redaction** — connection strings, passwords, and secret references never reach +diagnostics, receipts, or logs; and **bind refuses mismatch**. + +Ports stay at three or four cohesive methods, because AP-3 names "a port with every operation the +backend can perform" as the integration-package failure mode and today's `DatabaseAdapter` +is that anti-pattern in shipped code. The consumed set is `ContractArtifactSource`, +`ArtifactPublisher` (stage/commit/abort, never patch in place), `ProviderContractCompiler` +(validate/canonicalize), `ProviderRuntimeFactory`, `ProviderControl` (inspect/plan/apply), +`ConnectionSource` (the Aspire, environment, and secret-reference adapters), `MigrationLock`, and +the append-plus-lookup receipt store, plus `Clock`, `IdSource`, and `SignaturePolicy` where +deterministic testing or production approval requires them. **Verify is not a provider method**: it +is composed from `ProviderControl.inspect` plus a manifest comparison plus ownership classification, +which is what keeps drift semantics identical across providers. + +### The runtime validation subsystem + +This is the axis where an attractive inference is easiest to over-sell. The +[runtime-validation source audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/runtime-validation-source-audit.md) +is the evidence; three facts are decisive. The contract carries a bounded runtime value algebra — +codec references, value objects, unions, mandatory nullability, `many`, `dict`, value-set +references, and explicit relation and cross-space coordinates. But **the complete operation and +result type universe is not runtime data**: the SQL field, operation, codec, and aggregate type maps +sit under an optional phantom key ([`TypeMapsPhantomKey`][rc1-type-maps]), are emitted into +`contract.d.ts`, and are erased at runtime. And plans retain enough for **direct** projections and +no more — a projection carries alias, expression, and an _optional_ codec reference, absent for +computed expressions, subqueries, and raw aliases. + +Two related upstream facts are often merged and must not be. Prisma's own Standard Schema usage +validates codec **parameters**, not model values. Separately, a codec declares three **conversion** +representations — application runtime, driver wire, and target JSON — of which only `runtime` and +`json` are NetScript's public validation representations; the driver-wire channel stays +adapter-internal, and conversion success is never validation. + +Three schema classes with materially different guarantees, which is why they are not hidden behind +one method: + +| Class | Guarantee | Refusal boundary | +| --------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | +| Model value | `output('model', …)` validates a named model, value object, or enum. | Never implies uniqueness, foreign keys, or check constraints hold. | +| Operation input | `input(op, …)` exists **only** where a registered operation pack contributes exact runtime metadata. | Create/update/filter/nested-write/polymorphic grammar absent from runtime data fails at construction. | +| Selected result | `output(selection, …)` validates a direct projection with known alias, codec, nullability, representation. | Computed, subquery, raw, aggregate, include, and unknown leaves need a contributed schema or fail. | + +Operation metadata reaches the interpreter as an **operation pack** contributed by the configured +provider or an extension bundle through the single registration flow — `prismaPostgres` contributes +`ormCollection@1` for the RC1 collection grammar — and each pack's identity and version is recorded +in the manifest and in every derived validator's cache key. Nothing is inferred from the contract +that the contract does not contain. + +`ValidationIR` supports exactly the algebra the pinned source proves: registered codec leaves, +nullability, lists and dictionaries, value objects, whole-model values with an explicit presence +policy, direct-column projections, integrity-checked cross-space relations, deterministically +discriminable unions, and value sets and enums whose membership resolves from the value set or +native-enum entity rather than from a codec id. + +Schema **construction** throws a deterministic `DB_VALIDATION_UNSUPPORTED` — with coordinates naming +target, space, snapshot, model, operation or selection, representation, and the missing metadata — +for at least: unknown codecs or codecs without a representation-specific value schema; unknown pack +entity kinds; corrupt or missing aggregate spaces, heads, hashes, cross-space references, or value +sets; ambiguous unions and unresolvable model variants; operation grammar absent from runtime data; +computed, subquery, raw, aggregate, include, or unknown result leaves; opaque SQL index and check +expressions; database-state constraints such as uniqueness and foreign keys, which are not local +value validation; and asynchronous predicates where the requested mode promises synchronous +validation. + +No unsupported case becomes `unknown`, a pass-through, or a warning. This is deliberately **stricter +than the provider's own decoders**, which accept missing codecs and pass through unknown shapes: a +decoder's job is decoding, a validator's job is refusing. Invalid _values_ never throw — they return +Standard Schema issues carrying a stable code, contract coordinates, field path, expected class, and +observed value class. + +A codec is supported only when its contributor supplies a deterministic value schema for **every** +advertised public representation: + +```ts +defineValidationCodec({ + codecId: 'pgvector.vector@1', + representations: { runtime: vectorRuntimeSchema, json: vectorJsonSchema }, +}); +``` + +Encode/decode functions are not validation: conversion success is compatible with arbitrary +coercion, as the ArkType JSON extension documents. A derived validator's cache key covers the +canonical snapshot digest, contract schema version, `SpaceId`, target/family, operation or +normalized selection shape, representation, interpreter ABI version, and the identity and version of +every contributing operation pack and codec; a storage hash alone is insufficient, because domain, +roots, and extension semantics can change without storage changing. Plugin spaces cache under their +own `SpaceId`. + +Input validation is **mandatory** at external mutation boundaries wherever a supported schema +exists; output validation is **mandatory** for declared API/RPC responses, SSR/hydration payloads, +and external-service messages, and **opt-in** for internal query loops, because a design that +validates every row on every read gets disabled wholesale. An input failure is a client error with +field paths; an output failure is a server/contract error **and** a drift signal. NetScript +re-exports no validation library, and no ahead-of-time projection is claimed: one may ship later +only if it is content-addressed, atomically replaced, never required by any code path, and corpus- +equivalent to the runtime interpreter. + +### Ownership, spaces, and the withheld namespace capability + +| Policy | Planned | Mutated | Verified | Typical source | +| ---------- | ------- | ------- | --------------------------- | ----------------------------------------------------------------- | +| `managed` | Yes | Yes | Fully | A space that owns the objects | +| `adopted` | Yes | Yes | Against a reviewed baseline | Objects brought under management by `db adopt` | +| `external` | No | No | Against declared assertions | Hosted platforms and upstream extensions owning their own objects | +| `ignored` | No | No | No | Deliberate exclusion with a recorded reason | + +Exactly one `managed` owner per `ObjectKey`; identical declaration text from two contributors is +still a conflict; cross-space references require the same target plus a declared dependency edge; +and augmentation is an **owner-granted closed permission**, so the absence of a grant is a denial +and an unsupported modification either asks the owner or becomes an app-owned migration. The +`external` policy is not an edge case — a hosted database whose tables evolve outside the +framework's knowledge is the normal shape of a managed service, and upstream has a recorded instance +of a pinned extension contract diverging from an externally evolving database and failing +verification ([prisma#29896][pn-29896]). + +The space lifecycle is `declared → installed → upgraded`, with refusals for overlap, missing or +cyclic dependencies, contract-format skew, capability regression, ownership widening, and mirror +skew; then `detached → retained`, with `archived` and `dropped` specified but unclaimed. +Detach-and-retain is the **only guaranteed removal**, and retained is a lifecycle state rather than +an ownership policy. Under the provider lock/fence, one receipt-backed ledger transition records the +previous head/snapshot, reason, `retained` state, and transition `ReceiptId`; the runtime binding is +removed and the provider marker is preserved. The space keeps its data, lineage, and ownership +history as a **verify-only tombstone** that inventory and drift reporting still see but no plan or +apply may touch until a new explicit space re-adopts it. Detaching a space a still-installed space +depends on is refused. + +Prisma's runtime lowering honours per-model namespaces, but its authoring type maps do not: the +authoring path lumps every model under the default storage namespace and leaves additional namespace +maps empty ([`contract-types.ts`][rc1-namespace-map]), and the audited post-RC object retains the +limitation. `NamespaceRef` therefore stays a **kernel** identity axis — manifests, ownership, object +keys, and plans all carry it — while the adapter declares only the default physical namespace as a +capability, and a second namespace or a non-default binding is refused with +`db.target.namespace-unsupported`. The capability must not be advertised until exact type/runtime +parity passes with **no casts, no private imports, and no flattening workaround**. Logical `SpaceId` +and ownership coordinates prevent silent merging, but they do **not** let two identical physical +table names coexist in one namespace. If upstream never fixes the type maps, the kernel carries an +unused axis and nothing else needs rework. + +### The refusal boundary + +These refusals are the architecture: each is mechanically checkable and each has a conformance row +in the [approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). Beyond +the summary's non-goals and the guide's refusals: **no compatibility layer** and no code path that +selects between the two stacks; **no text-patched generated source and no arbitrary TypeScript +during production apply**, because artifacts are emitted from an IR and replaced atomically while CI +consumes verified artifacts; and **no implicit target selection, cross-target atomicity, +cross-database relation, or cross-database transaction**. + +## Drawbacks + +**It is a large program, it lands as a break, and it adds indirection.** Twelve waves, six new +packages, changes to four existing ones, a doctrine amendment, a first-party plugin conversion, and +a cutover; until then the repository carries both foundations on separate branches. A definition +compiles to a manifest, which binds a plan, which yields a receipt — for a solo developer with one +PostgreSQL database that is more moving parts than `prisma migrate dev`, and the pay-off arrives +with the second target, the first plugin space, the first partial failure, and the first production +apply. Six published packages are likewise a real maintenance surface, each carrying JSR +obligations. + +**It bets on an Early-Access upstream, and pays for the insulation.** RC1 is not recommended for +production, its notes warn that respins may break APIs and the contract format, and the seam moved +within six days of the tag. One adapter package, one facade module, an import allowlist, independent +versioning, and a kill switch that costs a provider rather than the architecture keep that contained +— but they add a boundary a direct dependency would not need, and the conformance matrix behind them +(real PostgreSQL, Windows and Linux, failure injection, crash and unknown-outcome recovery, packed +consumer installs, a two-consumer Standard Schema corpus) is a standing CI bill. That cost is the +point: it turns "upstream says it is supported" into "NetScript proved it". + +**Validation is narrower than users will want, and some capabilities regress.** "Derive all my +validators from the schema" is the intuitive expectation, and this design refuses it for filters, +nested writes, polymorphic narrowing, and computed/raw/aggregate results unless exact metadata is +contributed — a correct refusal this RFC would rather explain than silently return a schema that +accepts wrong data. Prisma SQLite, MongoDB, MySQL, and SQL Server are not carried forward, +multi-namespace typing is withheld, and destructive plugin removal is not guaranteed; each names the +gate that would release it, but a user with a MySQL target today has no path inside this design +other than the old release line. One soundness seam at `runtime.bind` is likewise accepted rather +than eliminated, mitigated by three gates but real. And the type story is not uniform: app-authored +spaces need no emitted types at all, while a queried pinned space depends on a declaration the +launcher emits — automatic and atomic, but still a build artifact a reader has to know exists. + +## Rationale and alternatives + +### Why this shape + +Four observations force the design. **Nothing joins the five current systems**, so a join point is +mandatory — and it must be a _value_, because inspection, diffing, hashing, review, transport to CI, +agent consumption, and stale detection are properties of a serialisable value, while a live graph +reachable from feature code is a service locator with a domain name. **Provider identity replaced +target identity**, so identity must be declared, provider-neutral, and the key of every artifact. +**Prisma's contract, space, and lineage semantics are good while its operational layer has gaps**, +so NetScript owns policy, locking, recovery, receipts, and the saga. And **NetScript already has an +adoption pattern** — preset, factories, native primitives — so the database surface is a third +instance of it rather than a new idiom. + +### Alternatives considered and rejected + +| Alternative | Why rejected | +| -------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Keep Prisma 7 and add Prisma 8 as an opt-in pilot (issue #313) | It preserves every seam in Motivation; the current architecture is what a compatibility-first constraint produced. | +| A one-to-one migration of the current design onto Prisma 8 | Engine-as-identity, the repair pipeline, copied fragments, exit-code results, and Aspire-coupled generation are version-independent. | +| A proprietary NetScript schema DSL lowering to the contract | A third schema language tracking every native type, index kind, constraint, and default; permanently lagging. | +| A live `DatabaseGraph` as the public artifact | A runtime graph accretes traversal APIs and becomes a lookup surface; the manifest gives every property it was wanted for. | +| Re-export Prisma from a NetScript package | AP-14, the publish constraint, and 138 upstream export keys — it converts Early-Access internals into NetScript public API. | +| Generated model/query declarations as the universal type source | Prisma's phantom contract type parameter and an app-local `isolatedDeclarations` scope preserve direct inference for app-authored spaces. The target descriptor is emitted wiring, but generated contract declarations remain bounded to pinned spaces the consumer did not author and publishable exports. | +| Generated mirror validators (one schema file per model/input/output) | Combinatorially wrong for selection-aware output, and it recreates the repair pipeline that already failed here. | +| Claim full operation/result validation from contract data | The operation and result type maps are phantom and erased at runtime; the claim would be false. | +| Copy plugin schema fragments (status quo) | No version, ownership, capability guard, dependency order, provenance, or safe removal — two recorded production failures. | +| Build a hosted control plane (registry, RBAC, approvals, drift) | Persistent products with operators, not local primitives; a local kernel exposes stable artifacts and integration events instead. | +| Extend the `--allow-slow-types` carve-out to database packages | It converts an application-local inference problem into permanent framework-wide publish debt. | + +### Market lessons + +Seventeen comparators were examined for the framework-level problem rather than for ORM popularity +([market analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md)). +Five lessons changed this design: + +- **One resolved manifest beats many config files.** Named connections in Adonis, Rails, and Django + are legible and Atlas proves multiple schema sources can compose, but none yields a deterministic + content-addressed resolved value. +- **Contributor-owned migration spaces are the only ownership model that scales**, and **managed and + external ownership are different**. Django's per-app graphs and Prisma's contract spaces are the + strong examples, while Flyway locations and Liquibase changelogs merge into one shared history; + Rails' `database_tasks: false`, Drizzle's filters, Atlas's external sources, and the upstream + Supabase drift incident all show that treating every visible object as your own reports permanent + false drift. +- **A preview is not an executable plan, and applying a valid plan is not a transaction.** Atlas's + develop → review → deliver → apply model is the right process shape; Terraform and Pulumi supply + the recovery lesson encoded here as `outcome-unknown` and inspect-before-resume. +- **Runtime-derived, selection-shaped validation is the right ergonomic, but the boundary must be + standard.** ZenStack v3 is the closest comparator ([its Zod factory][zenstack-zod]), and its + validators are Zod-specific while schema-time and runtime installation can diverge; NetScript + binds both halves in one contribution record and keeps Standard Schema as the boundary. + +## Breaking changes and migration + +**This is a breaking change.** The tracking issue and the RFC PR carry the `breaking` label. + +### The no-compatibility law + +None of the following survives: a Prisma 7 client or facade; a legacy generated module or alias +barrel; a dual client or `setClient` lifecycle; a deprecated re-export; a dual migration history; a +copied schema bridge; a runtime shim; or any code path that selects between the old and new stacks. +Old and new may coexist **in the repository** on separate branches or release lines while features +are developed; a single application composition may never load both. + +| Surface | Break | +| ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- | +| `@netscript/database` (current adapters, `setClient`) and `@netscript/prisma-adapter-mysql` | Replaced wholesale; the hand-written driver adapter is retired. | +| Generated engine workspaces `database//` | Deleted with their `db:*` task graph, repair scripts, and Zod pipeline. | +| Generated client deep imports | Removed; applications consume the app-local binding. | +| `@netscript/plugin` legacy database abstracts and plugin `*.prisma` fragments | Replaced by `definePluginSpace` and pinned-artifact spaces. Copying stops. | +| The current `db` CLI verbs | Catalog projections: `generate` → pure `emit`, `migrate` → `plan` + `apply`, `list`/`status` → `inventory`/`verify`. | +| Implicit target defaulting and silent single-target execution | **Deliberately removed.** There is no fallback chain anywhere. | +| Prisma SQLite / MySQL / SQL Server targets | Not carried forward; structured `db.target.unsupported`. | + +### The adoption protocol + +`netscript db adopt` is a temporary migration codemod and tool. It is not a compatibility layer, not +a permanent command, and it is deleted after the migration window. It operates on an **explicitly +selected target set** and returns a status for **every** selected target — there is no "whatever was +reachable" mode. + +| Step | Operation | Mutates the database? | Failure behaviour | +| ---- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------ | +| 1 | Read legacy configuration and derive explicit `TargetId`s from config keys, never engine names | No | Refuse on ambiguous or duplicate keys, or when two keys resolved to one engine directory | +| 2 | Introspect every **selected** target | No | An unreachable target is `not-attempted` with a reason code; the run continues but cannot be marked complete | +| 3 | Propose ownership — one space per attributable owner, plus `external`/`adopted` — and hard-stop on unattributed or conflicting objects | No | Unattributable objects are reported, never guessed | +| 4 | Compile the manifest, atomically emit artifacts, and establish one baseline lineage node per space matching the **observed** state | No | Standard composition diagnostics | +| 5 | Write provider marker/ledger metadata **only** — no application-schema DDL, no application-data DML | **Yes: provider metadata rows** | Idempotent and re-runnable; every write is receipt-backed | +| 6 | Verify live state against the manifest and baseline; require zero drift on every selected target | No | Any diff is a genuine finding: an unattributed object or a wrong ownership assignment | +| 7 | Delete legacy engine workspaces, task graphs, copied fragments, repair scripts, and old adapters | No | Reversible by reverting the commit | + +Step 5 is the load-bearing property, stated precisely: adoption performs **no application-schema DDL +and no application-data DML**. It does write provider marker and ledger metadata — that is metadata +DML, it is idempotent, and every write is backed by a receipt — and it creates, alters, or drops +nothing that belongs to the application. That is what makes the migration safe on production data. +Full cutover — step 7 and removal of the legacy release line — is blocked until every _intended_ +target has been reached, attributed, baselined, and verified; a partially adopted target set is +resumable, never finished. + +Required before a release-class cutover: a seeded production-shaped **rehearsal** proving zero +schema/data mutation with the receipt as evidence; a verified restorable **backup** before the first +mutating operation in each environment; a committed **ownership preflight** listing every target +with reachability and provider version, every `ObjectKey` with owner and policy, every +unattributable object, and every capability requirement; **destructive consent** as an approved +signed plan; per-target **partial outcomes** with resume tokens; a **crash** fault-injection run +exercising checkpoints, `outcome-unknown`, and inspect-before-resume; **idempotent marker** writes; +a **secret** redaction case; **lock** contention, TTL expiry, holder death, and force-unlock +preconditions; and an agreed migration window, legacy release-line end date, and rollback runbook. + +### Rollback boundaries + +| Point | Rollback | Cost | +| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | +| Before the marker write | Delete generated artifacts | None; nothing was written to any database | +| After markers, before the cutover commit | Under the provider lock/fence, append a receipt-backed lifecycle transition carrying previous head/snapshot, reason, and `retained`; preserve the marker as a verify-only tombstone. Remove metadata only where certified provider semantics prove the inverse transition safe and idempotent | Application schema/data are untouched; provider metadata remains auditable | +| After the cutover commit, before the first new `apply` | Revert the repository commit; retain and verify any adoption metadata already written | Repository rollback only for application code/schema; provider metadata may remain retained | +| After the first new `apply` | **Forward only** — lineage, provider ledger, receipts | Ordinary migration recovery; the receipt names which steps ran | + +There is deliberately no "run both stacks" rollback: it would require the compatibility layer this +design refuses and would double the failure surface exactly when the system is least understood. + +## Prior art + +No product is a template. The +[market analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/market-analysis.md) +records the full comparison; the sources that shaped specific decisions are +[Django's per-app migration graphs][django-multidb] and Prisma's [contract spaces ADR][adr-212] for +contributor ownership, [Terraform's targeting guidance][tf-targeting] and +[Pulumi's interrupted-update recovery][pulumi-interrupted] for saga semantics, +[Flyway's `repair`][flyway-repair] for the ledger-versus-database distinction, +[ZenStack's runtime Zod factory][zenstack-zod] for selection-shaped validators, and the upstream +[Supabase drift incident][pn-29896] for ownership policy. + +NetScript's own prior art is closer. The oRPC integration proves the type discipline — the real +upstream builder, NetScript policy around it, precise types flowing from upstream values, Standard +Schema consumed structurally, and compile-failure soundness tests +([transfer analysis](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/typescript-schema-orpc-audit.md)) +— while `defineService`, `defineServices`, and `defineFreshApp` prove the adoption shape: a preset +that literally calls the public factories, which compose the native library +([layered DX audit](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/research/layered-dx-api-audit.md)). + +## Unresolved questions + +The vocabulary, identity model, package graph, artifact taxonomy, refusal boundary, ownership model, +plan/apply/recovery semantics, validation bounds, layered adoption surface, and clean-break law are +**locked**. Nothing below can force a package-boundary rewrite, and the full ledger with owning +waves is in the [approved plan](../.llm/runs/docs-database-architecture-rfc--prisma-8-rfc/plan.md). + +Implementation-time, by owning wave: the exact Prisma import allowlist, module specifiers, L1/L2 API +spelling, the source-native-versus-generated boundary, and whether the multi-namespace capability +can be claimed at all (W3 — adapter-local by construction, and pinning a specifier now would design +against a surface that moved post-RC); the concrete scope shapes and whether an interactive +transaction can expose the ordinary query type (W4); plan signature format and key custody, the +provider lock mechanism, and receipt storage and retention (W5/W10 — the ports and the signed-plan +requirement are locked, only the mechanisms are open); and the migration window, legacy release-line +end date, and rollback runbook (W10). + +Conditional on upstream, each blocking only a _claim_: whether Prisma's namespace type map stops +flattening non-default namespaces; whether prepared-statement, transaction, raw-SQL, and +numeric/aggregate semantics settle by GA (aggregate semantics already changed after RC1, so no +public guarantee is made until proven per pin); whether upstream ships an extension or space removal +primitive (if not, `retain` is the product behaviour); whether the contract format stabilises (more +than one break without a migration path is a kill trigger); and whether the Deno platform matrix is +clean without vendoring or patching (failure kills the adapter, not the kernel). + +Explicitly deferred rather than open: a second provider; Prisma SQLite, MongoDB, MySQL, and SQL +Server; runtime capability negotiation; AOT validation; archive/drop removal; public +raw/prepared/aggregate conveniences; and hosted approval, registry, promotion, fleet, drift, and +secret services. Cross-database relations and transactions are **unsupported**, not parity debt. + +Two questions are genuinely for reviewers. Is detach-and-retain as the only guaranteed removal +acceptable for the first release, given that archive and drop are specified but unclaimed? And is +the split type story the right trade — an app-local `isolatedDeclarations: false` authoring scope +(build inputs, never JSR exports) for spaces the application authors, plus an automatically emitted +declaration for spaces it only consumes — against the simpler-to-explain alternative of generating +every space's types? + +## Future possibilities + +Natural extensions this architecture enables and this RFC deliberately excludes: + +- **A second certified provider**, proving the narrow provider SPI with a real adapter when demand + and maturity exist — never a speculative fallback built to prove a port. +- **The multi-namespace capability**, **archive/drop retirement**, and **AOT validation**, each + released by its gate — upstream type parity, provider conformance, corpus equivalence — rather + than by a workaround. +- **Delivery-backend adapters** exporting plans, receipts, and diagnostics to Atlas, Bytebase, or a + hosted approval system, and **deeper agent capability** through an allowlisted operation surface + with catalog-derived policy metadata — adapters over stable artifacts, never local + reimplementations. +- **Additional first-party spaces** beyond auth, workers, sagas, triggers, and streams, and + **read-replica-aware routing helpers** if a concrete need appears — composition affordances, never + a hidden router that could send a write to a reader. + + + +[ns-1014]: https://github.com/rickylabs/netscript/issues/1014 +[ns-1059]: https://github.com/rickylabs/netscript/pull/1059 + + + +[rc1-release]: https://github.com/prisma/prisma/releases/tag/v8.0.0-rc.1 +[rc1-readme]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/README.md +[rc1-scorecard]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/scorecard.md +[adr-212]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/docs/architecture%20docs/adrs/ADR%20212%20-%20Contract%20spaces.md +[pn-3dc98cb]: https://github.com/prisma/prisma/commit/3dc98cb +[pn-29896]: https://github.com/prisma/prisma/issues/29896 + + + +[rc1-define-contract]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/contract/define-contract.ts#L46-L121 +[rc1-contract-example]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/prisma/contract.ts +[rc1-postgres-runtime]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/3-extensions/postgres/src/runtime/postgres.ts#L96-L110 +[rc1-no-emit]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/prisma-no-emit/context.ts#L11 +[rc1-orm-filter]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/get-posts-by-tag-filter.ts +[rc1-orm-read]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/get-user-posts.ts +[rc1-orm-write]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/examples/prisma-8-demo/src/orm-client/create-user.ts +[rc1-space-aggregate]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/1-framework/3-tooling/migration/src/aggregate/types.ts#L71-L124 +[rc1-namespace-map]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/2-sql/2-authoring/contract-ts/src/contract-types.ts#L644-L691 +[rc1-type-maps]: https://github.com/prisma/prisma/blob/v8.0.0-rc.1/packages/2-sql/1-core/contract/src/types.ts#L207 + + + +[flyway-repair]: https://documentation.red-gate.com/flyway/reference/commands/repair +[tf-targeting]: https://developer.hashicorp.com/terraform/tutorials/state/resource-targeting +[pulumi-interrupted]: https://www.pulumi.com/docs/iac/operations/troubleshooting/interrupted-updates/ +[zenstack-zod]: https://zenstack.dev/docs/utilities/zod +[django-multidb]: https://docs.djangoproject.com/en/5.2/topics/db/multi-db/