Skip to content
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
4be857e
docs(drive): pin a registryRoot test-isolation override on the emulat…
wmadden-electric Jul 22, 2026
e9ef7b3
feat(dev-emulators): scaffold the @internal/dev-emulators package
wmadden-electric Jul 22, 2026
d0b3028
feat(dev-emulators): add the shared daemon layer and loopback clients
wmadden-electric Jul 22, 2026
ed633b4
feat(dev-emulators): add the Compute emulator daemon
wmadden-electric Jul 22, 2026
32eb9e6
feat(dev-emulators): add the bucket emulator daemon
wmadden-electric Jul 22, 2026
ad0791b
test(dev-emulators): drive both daemons real APIs standalone
wmadden-electric Jul 22, 2026
9d6d64c
fix(dev-emulators): kill a spawned daemon that never became healthy
wmadden-electric Jul 22, 2026
7b7648e
docs(drive): record the registryRoot scope inconsistency found in S3
wmadden-electric Jul 22, 2026
dec518f
docs(drive): registryRoot governs state-dir and log path too; failed …
wmadden-electric Jul 22, 2026
f6c468f
docs(drive): drop the S3 Open Questions entry, superseded by 9d6adf9
wmadden-electric Jul 22, 2026
97f81a5
fix(dev-emulators): review nits — no-op persist gap, log fd leak, sta…
wmadden-electric Jul 22, 2026
f890baa
docs(design): per-app bucket credential scoping, sanitized ORM diagno…
wmadden-electric Jul 22, 2026
4725393
fix(dev-emulators): per-tenant SigV4 scoping closes the bucket cross-…
wmadden-electric Jul 22, 2026
5c84930
docs(drive): bucket tenant resolution reads the registration record, …
wmadden-electric Jul 22, 2026
88c58d7
docs(drive): resolve the S4 findings — build-only exemption, verified…
wmadden-electric Jul 23, 2026
7908b67
docs(design): inter-process daemon-ensure lock; precise emulator-topo…
wmadden-electric Jul 23, 2026
2c24876
fix(dev-emulators): serialize ensureDaemon across processes with a di…
wmadden-electric Jul 23, 2026
41cb6ae
fix(dev-emulators): make the concurrent-ensure test portable, no pgre…
wmadden-electric Jul 23, 2026
6893207
docs(drive): sync spec.md to design tip 4ce7160 (fresh-port-retry pin)
wmadden-electric Jul 23, 2026
48a3a1f
feat(dev-emulators): fresh daemon allocations retry the next port on …
wmadden-electric Jul 23, 2026
f6ffe17
test(dev-emulators): make daemon-port tests robust to shared-machine …
wmadden-electric Jul 23, 2026
db8373f
fix(dev-emulators): make findFreePort's port check errno-driven and s…
wmadden-electric Jul 23, 2026
cd60a09
docs(drive): sync spec.md to design tip 904d23a (session-resume + dep…
wmadden-electric Jul 23, 2026
53bdf45
feat(dev-emulators): POST /apps/<app>/start — the session-resume endp…
wmadden-electric Jul 23, 2026
1687766
refactor(dev-emulators): proper-lockfile for the daemon lock, get-por…
wmadden-electric Jul 23, 2026
79f5bc2
docs(drive): sync spec.md to design tip 62d1a6a (postgres-main admin …
wmadden-electric Jul 23, 2026
bb1a62d
feat(dev-emulators): postgres-main — the third emulator daemon, @pris…
wmadden-electric Jul 23, 2026
82d2625
fix(dev-emulators): CodeQL — linear slug regex, sanitize fixture-sour…
wmadden-electric Jul 23, 2026
581d755
fix(dev-emulators): CodeQL A01+A02 — fixture body travels via env var…
wmadden-electric Jul 23, 2026
605a6c6
fix(dev-emulators): A03 — assert the 500 status and no leaked paths o…
wmadden-electric Jul 23, 2026
2820f21
Merge main; resolve shared design-doc conflicts to the design branch tip
wmadden-electric Jul 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .drive/projects/local-dev/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,10 @@ scripts. Implementer dispatches use Sonnet-4.6-mid, reviewers Opus-4.8-mid
merged prefixed logs); `watch.ts` (debounced rebuild → re-assemble →
re-converge; converge failure leaves the running app untouched);
`--fresh`; Ctrl-C = `stopServices()` + exit; every error string from the
spec verbatim.
spec verbatim. Plus publish-safe daemon-entry resolution (spec § 2's
publish note): `ensureDaemon` takes the entry path; public daemon-entry
subpaths on `@prisma/composer-prisma-cloud`; the published dist resolves
its own daemons.
- **Proves:** the spec's acceptance criteria 1–6 on `examples/store`,
scripted as an integration test where feasible (bring-up, single-service
restart on rebuild, warm restart after Ctrl-C with stable ports/URLs,
Expand Down
368 changes: 258 additions & 110 deletions .drive/projects/local-dev/spec.md

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions architecture.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@
"layer": "lowering",
"plane": "shared"
},
{
"glob": "packages/1-prisma-cloud/0-lowering/dev-emulators/src/**",
"domain": "prisma-cloud",
"layer": "lowering",
"plane": "control"
},
{
"glob": "packages/1-prisma-cloud/1-extensions/target/src/control/**",
"domain": "prisma-cloud",
Expand Down
2 changes: 1 addition & 1 deletion docs/design/10-domains/local-dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ Deploy's rule holds: every failure names its fix.
| `bun` not on PATH | that dev runs services under bun (the Compute runtime) and how to install it |
| no installed `prisma` bin (the local-Postgres emulator) | what was searched for and to add `prisma` to devDependencies |
| the bucket emulator fails to start or report healthy | the instance name, its log file path, and the port it tried |
| ORM `prisma dev` fails to start | the exact command that was attempted and its output |
| ORM `prisma dev` fails to start | the exact command that was attempted and its output, sanitized — connection-URL credentials are masked before embedding |
| port conflict on a persisted allocation | which service, which port, and how to free or re-allocate (`--fresh`) |
| secret slot unbound | warning (not an error) naming the env var and the placeholder behavior |
| env-sourced param unbound | hard error listing the missing names, deploy-preflight style |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,9 @@ this repo owns.
- [ADR-0007](ADR-0007-deploy-drives-alchemy-through-a-generated-stack-file.md)
— the terminating converge child the machine-scoped emulators decouple
dev from.
- [ADR-0011](ADR-0011-targets-supply-the-deploy-state-layer.md) — the state
layer the `dev.state` descriptor supplies locally.
- [ADR-0011](ADR-0011-targets-supply-the-deploy-state-layer.md) — targets
supply the durable deploy state layer; dev instead uses Alchemy's own
`localState()` through `LowerOptions.state` (tool state, ADR-0004).
- [ADR-0017](ADR-0017-control-plane-loads-through-the-app-config.md) /
[ADR-0038](ADR-0038-containers-are-an-extension-descriptor.md) — the
extension-descriptor pattern `dev` extends.
Expand Down
2 changes: 1 addition & 1 deletion docs/design/90-decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,4 @@ _Earlier drafts (ADR-0001, ADR-0002) were retired as the high-level design settl
- [ADR-0038](ADR-0038-containers-are-an-extension-descriptor.md) — Container lifecycle (ensure/locate/remove) is an optional `container` descriptor on `ExtensionDescriptor`, the same pattern as `preflight`/`teardown`; the resolved instance is opaque to core and crosses the CLI parent→alchemy child boundary as one framework-named environment variable per extension, via the extension's own `serialize()`/`deserialize()`. `StateDescriptor` names its owning extension so core can hand it that extension's resolved container. Deletes the `crossDomainExceptions` entry that let the CLI import `@internal/lowering` directly — `0-framework` imports nothing again.
- [ADR-0039](ADR-0039-a-compute-services-own-origin-is-a-target-resolved-property.md) — A compute service's own platform-assigned origin is a target-resolved property, read as `ComputeService.origin()` — never a declared param, never operator config, never in `config()`. It rides ADR-0031's reserved provider-param channel as the first *service-derived* entry (`valueForService(provisioned, address)`, written for every compute service, exposing or not), sourced from the provisioned service's own `endpointDomain` — made trustworthy pre-promote by the upstream PRO-200 fix. `envParam(…)` remains correct for operator-known origins (custom domains); narrows ADR-0032's `appOrigin` example accordingly.
- [ADR-0040](ADR-0040-the-pn-binding-carries-the-url-and-a-lazy-client.md) — `pnPostgres(contract)`'s dependency binding is `{ url, client }`: the raw connection string plus the typed client, constructed lazily and memoized on first `client` access — `hydrate` builds nothing. The contract remains the compatibility interface (hash check and deploy-time migration unchanged, ADR-0022); the binding becomes a strict superset of plain `postgres()`'s `{ url }`, so an app that owns its database client still gets framework-run migrations. Contract validation cost and failure move from `load()` (where one bad input poisoned every input, unattributed) to the first `client` access. Cross-kind satisfaction (`'prisma-next'` satisfying `'postgres'`) rejected in its favor.
- [ADR-0041](ADR-0041-local-dev-runs-the-deploy-pipeline-against-local-providers.md) — `prisma-composer dev` runs the **same deploy pipeline** (Load → assemble → lower → Alchemy converge) against local implementations of the same Alchemy resource types, declared on an optional `dev` field of `ExtensionDescriptor` (providers, container, state, preflight, teardown — **no** `nodes`/`provisions`, so the lowering cannot diverge). Converge terminates; the local `Deployment` provider writes desired-process records and the long-running `dev` command supervises them. Stand-ins: child processes + local env store (compute), ORM `prisma dev` (postgres), the storage module's S3 handler over plain files on disk (buckets); `ServiceKey`/`S3Credentials`/`PgWarm`/`PnMigration` are shared verbatim. Credential-free by requirement. Rejects a local Management API (reimplements another team's server-side semantics, drifts silently) and per-kind dev descriptors (an open-set parallel seam).
- [ADR-0041](ADR-0041-local-dev-runs-the-deploy-pipeline-against-local-providers.md) — `prisma-composer dev` runs the **same deploy pipeline** (Load → assemble → lower → Alchemy converge) against local implementations of the same Alchemy resource types, declared on an optional `dev` field of `ExtensionDescriptor` (providers, container, preflight, emulators, attach, teardown — **no** `nodes`/`provisions`, so the lowering cannot diverge; no `state` either — dev uses Alchemy's own `localState()` through `LowerOptions.state`). The target runs **emulators per node kind**: Compute and buckets are machine-global, multi-tenant daemons (the Compute emulator owns the service child processes — deployment PUTs, crash supervision, logs; buckets serve the S3 wire over plain files on disk), while Postgres runs one detached ORM `prisma dev` instance per `Database` resource under the ORM CLI's own manager. Providers provision instances by communicating with the emulators during converge, and the dev command is a view through `attach`; `ServiceKey`/`S3Credentials`/`PgWarm`/`PnMigration` are shared verbatim. Credential-free by requirement. Rejects a local Management API (reimplements another team's server-side semantics, drifts silently) and per-kind dev descriptors (an open-set parallel seam).
47 changes: 47 additions & 0 deletions packages/1-prisma-cloud/0-lowering/dev-emulators/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@internal/dev-emulators",
"version": "0.2.0",
"type": "module",
"exports": {
".": "./dist/index.mjs",
"./buckets-main": "./dist/buckets-main.mjs",
"./compute-main": "./dist/compute-main.mjs",
"./postgres-main": "./dist/postgres-main.mjs",
"./package.json": "./package.json"
},
"scripts": {
"typecheck": "tsc --noEmit",
"test": "bun test",
"build": "tsdown",
"clean": "rm -rf dist"
},
"dependencies": {
"@internal/s3-protocol": "workspace:0.2.0",
"get-port": "^7.2.0",
"proper-lockfile": "^4.1.2"
},
"devDependencies": {
"@aws-sdk/client-s3": "^3.1085.0",
"@aws-sdk/s3-request-presigner": "^3.1085.0",
"@internal/tsdown-config": "workspace:0.2.0",
"@prisma/dev": "^0.24.14",
"@types/bun": "^1.3.13",
"@types/node": "^25.9.3",
"@types/pg": "^8.20.0",
"@types/proper-lockfile": "^4.1.4",
"pg": "^8.22.0",
"tsdown": "^0.22.7",
"typescript": "^6.0.3"
},
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/prisma/compose.git",
"directory": "packages/1-prisma-cloud/0-lowering/dev-emulators"
},
"engines": {
"node": ">=24"
},
"private": true,
"types": "./dist/index.d.mts"
}
Loading