Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions docs/design/05-prisma-cloud/alchemy-lowering.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ of the dependency graph rather than luck.

The postgres family (`Project`, `Database`, `Connection`), the compute
family (`App`, `Deployment`, `EnvironmentVariable`) and the bucket family
(`Bucket`, `BucketAccessKey`) are **upstream alchemy's** (`alchemy/Prisma`), not
(`Bucket`, `BucketAccessKey`) are **upstream alchemy's** (`@alchemy.run/prisma`), not
ours: Composer registers their providers and binds their props. What
`@internal/lowering` still owns is the artifact packager, `ServiceKey`, and the
hosted state store.
Expand Down Expand Up @@ -82,11 +82,11 @@ and manual cleanup).
## The resource inventory

Each row is a resource type the lowering binds. The `Prisma.*` families are
upstream `alchemy/Prisma` classes (ADR-0048) — Composer registers them in its
upstream `@alchemy.run/prisma` classes (ADR-0048) — Composer registers them in its
provider collection and defines resources only where no Management API exists
behind them.

| Resource (upstream `alchemy/Prisma`) | PDP entity it manages | Props (in) | Outputs (out) | Notes |
| Resource (upstream `@alchemy.run/prisma`) | PDP entity it manages | Props (in) | Outputs (out) | Notes |
| --- | --- | --- | --- | --- |
| `Prisma.Project` | Project | name | projectId | **one per Prisma Composer application**; resolved by the CLI before Alchemy runs, so no lowering yields one |
| `Prisma.Database` | Database | project, name?, region, branchId?, logicalId? | databaseId, connection strings | one per Module-provisioned postgres resource; never the project default; a branch-attached database is created with `branchId` and no display name (upstream refuses the combination — see [deploying.md](../../guides/deploying.md)) |
Expand Down Expand Up @@ -168,7 +168,7 @@ Every role is a noun naming the piece: `deployment`, `env`, `generated`, `servic

**Platform names.** Every platform name Composer writes is the node's address (`shop.catalog`, `shop.auth.api`): the App `displayName`, the branchless Database `name`, and the Connection, Bucket and BucketAccessKey `name`. They are labels, never identity. Upstream adds `-` and a 12-character token to every Connection name, so a Connection's platform name is the address plus that suffix. `validatePlatformName` checks the address against each kind's limit (Connection 52, so the address fits beside the suffix in the platform's 65; Bucket 100; App 256; an access key has none) and fails naming the address; it never shortens a name. A hosted Database takes no name from Composer, because upstream refuses a name together with branch attachment; upstream derives its physical name from the resource ID and updates it in place.

On the upgrade deploy every one of these names changes from the short address to the full one. Upstream `alchemy/Prisma` replaces, rather than updates:
On the upgrade deploy every one of these names changes from the short address to the full one. Upstream `@alchemy.run/prisma` replaces, rather than updates:

- a Connection when its `name` or database changes, which mints new credentials;
- a BucketAccessKey when its `name`, `role` or bucket changes, which mints new credentials;
Expand Down
2 changes: 1 addition & 1 deletion docs/design/05-prisma-cloud/build-reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ How it behaves:
- The state layer reads `PRISMA_BUILD_ID`. When it is absent it uses the store
unwrapped and reports nothing.

The mapping, keyed by upstream `alchemy/Prisma` type ids:
The mapping, keyed by upstream `@alchemy.run/prisma` type ids:

| Alchemy resource | Platform type |
| --- | --- |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Amended by [ADR-0057](ADR-0057-a-nodes-address-is-its-full-path-from-the-app-nam

## Decision

Composer does not implement Alchemy resources for Prisma Cloud's Management API. It composes the official `alchemy/Prisma` provider's resources and providers, and defines its own resources only where the upstream provider has no support yet (buckets, whose routes upstream deferred) or where no Management API exists behind them (local mechanisms like migration steps).
Composer does not implement Alchemy resources for Prisma Cloud's Management API. It composes the official upstream Prisma provider's (`@alchemy.run/prisma`, formerly `alchemy/Prisma`) resources and providers, and defines its own resources only where the upstream provider has no support yet (buckets, whose routes upstream deferred) or where no Management API exists behind them (local mechanisms like migration steps).

The live wiring is composition, not implementation:

Expand Down Expand Up @@ -85,6 +85,6 @@ No plaintext reaches state: members are `Redacted` in props, and only the salted
## References

- ADR-0005 (the framework never builds or bundles user code), ADR-0034 (hosted deploy state), ADR-0039 (a service's origin is a target-resolved property), ADR-0041 (local dev runs the deploy pipeline against local providers).
- The provider: the `alchemy/Prisma` module of the `alchemy` package, 2.0.0-beta.74 or later (buckets and `Deployment.triggers` first ship there).
- The provider: the `alchemy/Prisma` module of the `alchemy` package, 2.0.0-beta.74 or later (buckets and `Deployment.triggers` first ship there). From 2.0.0-beta.84 it is the separate `@alchemy.run/prisma` package, with the same resources.
- `docs/design/05-prisma-cloud/alchemy-lowering.md` — the current resource-by-resource lowering map.
- `docs/guides/deploying.md` — operator-facing upgrade notes (one-time deployment reship, branch-database renames, leftover placeholder rows).
2 changes: 1 addition & 1 deletion docs/design/90-decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ _Earlier drafts (ADR-0001, ADR-0002) were retired as the high-level design settl
- [ADR-0045](ADR-0045-deploy-state-lives-behind-the-platform-state-api.md) — Deploy state lives behind the platform state API (the Management API implements Alchemy's stock `HttpStateApi` wire contract per Branch; composer's state layer is Alchemy's stock HTTP client), and deploys hold a server-side per-`(stack, stage)` lease (TTL 60s, heartbeated, released on exit; contention fails fast naming the holder; state operations without a live lease fail 409). Supersedes ADR-0010 (lock → lease) and the storage half of ADR-0034 (Branch scoping and lifetime stand; the visible per-stage database is gone); closes ADR-0012 as obsolete. No migration: legacy stages are refused until destroyed or deleted.
- [ADR-0046](ADR-0046-the-orm-facade-is-a-peer-dependency.md) — `@prisma/composer-prisma-cloud` takes the Prisma ORM postgres facade (`@prisma/orm-postgres`) as a **peer** dependency at one exact version, not a regular dependency: Composer registers an extension pack against the application's copy of the target, and two copies of a shell in one tree means two codec/operation registries and two class identities — a value from one is rejected by the other, silently. As a peer, that combination fails at install instead. Every `@prisma/orm-*` spec in the workspace is one exact version and all name the same one (`scripts/lint-orm-pins.mjs`). `@prisma/orm-toolchain`, which Composer drives rather than extends, stays a regular dependency. Replaces ADR-0022's consequence bullet on how the ORM is installed.
- [ADR-0047](ADR-0047-compute-assembly-preserves-safe-runtime-topology.md) — Compute assembly traces runtime files from the author-declared Node entry without rebundling app code, preserves only symlinks whose resolved targets remain inside the staged bundle, and installs narrowly runtime-gated bootstrap compatibility when a framework needs Node semantics. Each local mechanism is removed once the upstream Alchemy Compute provider owns the equivalent guarantee. Supersedes ADR-0005's blanket ban on symlinks and its assumption that directory output is already self-contained.
- [ADR-0048](ADR-0048-prisma-cloud-resources-come-from-the-upstream-alchemy-provider.md) — The six Management-API resource families (project, database, connection, app, deployment, environment variable) are the upstream `alchemy/Prisma` provider's classes, registered in Composer's `PrismaComposer` collection; Composer defines resources only where the upstream provider has no support yet (buckets) or no Management API exists behind them. Compute binds the low-level App/Deployment/EnvironmentVariable trio (the `COMPOSER_*_ORIGIN` self-edge and ADR-0005 rule out composite `Compute`); the env→deployment ordering edge rides the deployment's `app` prop, and a deployment is replaced exactly when its artifact or environment fingerprint changes — unchanged services are reused. Legacy rows in the platform state API (retired type-ids and shapes) migrate on read — the older retired SQL state stores stay destroy-only under ADR-0045 — branch-stage databases take generated physical names, and the platform's seeded `DATABASE_URL` is left system-managed. *(Amended by ADR-0057: resource IDs are the node's full address, or the address plus `.` and a role, each declaring its previous ID with `renamedFrom`.)*
- [ADR-0048](ADR-0048-prisma-cloud-resources-come-from-the-upstream-alchemy-provider.md) — The six Management-API resource families (project, database, connection, app, deployment, environment variable) are the upstream Prisma provider's (`@alchemy.run/prisma`, formerly `alchemy/Prisma`) classes, registered in Composer's `PrismaComposer` collection; Composer defines resources only where the upstream provider has no support yet (buckets) or no Management API exists behind them. Compute binds the low-level App/Deployment/EnvironmentVariable trio (the `COMPOSER_*_ORIGIN` self-edge and ADR-0005 rule out composite `Compute`); the env→deployment ordering edge rides the deployment's `app` prop, and a deployment is replaced exactly when its artifact or environment fingerprint changes — unchanged services are reused. Legacy rows in the platform state API (retired type-ids and shapes) migrate on read — the older retired SQL state stores stay destroy-only under ADR-0045 — branch-stage databases take generated physical names, and the platform's seeded `DATABASE_URL` is left system-managed. *(Amended by ADR-0057: resource IDs are the node's full address, or the address plus `.` and a role, each declaring its previous ID with `renamedFrom`.)*
- [ADR-0049](ADR-0049-composers-configuration-is-the-composer-section-of-prisma-config.md) — Composer's configuration is the `composer` section of `prisma.config.ts`, loaded by the Prisma CLI engine. The validator checks only the fields that identify extension and state descriptors, passes descriptors through as the file's own objects, rejects unknown keys, and takes the nearest declaring file's section whole so the generated stack imports exactly one file. The old `prisma-composer.config.ts` and the `configPath` pointer are refused with `CONFIG.SECTION_MISSING`, `CONFIG.FIELD_RETIRED` and `CONFIG.FILE_RETIRED`, never migrated. The validator returns the section with its declaring file, and the programmatic operations take the same `ComposerConfigSource` (`{ value, file }`) and run the same checks. The Alchemy child evaluates the whole `prisma.config.ts`. The effect pre-flight and `DEPS.EFFECT_VERSION_CONFLICT` are retired: a broken tree fails evaluation of `prisma.config.ts` with the engine's `CLI.CONFIG_UNREADABLE`. *(Amended: the alternatives section lists the rejected ways to keep a Composer-owned effect check. Amended 2026-10-23: the section takes an optional `entry`, resolved against the declaring file's directory; `--entry` or an operation's `entry` overrides it; neither gives `CONFIG.ENTRY_MISSING`.)* *(Amended by ADR-0062: the section gains `config` adapters.)* *(Amended 2026-10-30: the section takes `config` and `secrets` adapter lists, defaulting to `[environmentVariables()]`; the stack files read the pools again in the child.)*
- [ADR-0050](ADR-0050-composer-runs-as-prisma-deploy-and-prisma-dev.md) — Composer has no binary of its own: the `prisma` CLI mounts exactly two Composer commands, `prisma deploy` and `prisma dev`, mounted at the root as bare verbs on purpose rather than under a noun. `destroy` and `log` are operations on `@prisma/composer/control`, called from a script; a teardown script reads `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID`. Where teardown and logs belong in the `prisma` command tree is not decided; until it is, agents and users need a script for both. A `destroy` command was rejected: the CLI's destructive verb is `delete`, and no Composer command takes `--production`. Retires the `prisma-composer` binary; a CI lint keeps its name out of user-facing files. *(Amended by ADR-0053: the family also ships `dev url`, `dev stop` and `emulator list`, and `prisma dev` gains `--detach`. Amended 2026-10-23: neither command takes a positional entry; both take `--entry` over the config's `entry`. Amended 2026-10-27: the family also ships `deploy list`.)* *(Amended by ADR-0062: the flag is `--environment`, defaulting per command; `destroy` targets an environment by name.)*
- [ADR-0051](ADR-0051-a-nodes-address-is-its-logical-id-on-the-platform.md) — A node's address is its identity on Prisma Cloud: Composer writes it, byte for byte, as the `logicalId` of the node's one platform row (Project, App, Database, Bucket) and as the node's `logicalId` in the application topology, so the platform joins topology nodes to rows, and one node across branches, by string equality. A provision ID defaults to the node's name, so changing a name changes identity. The value is never an Alchemy resource ID, a display name or a platform `id`; App, Database and Bucket rows get it as a prop on the upstream resource that creates them, and the Project from container resolution; no separate resource writes it. Changing an address changes the entity's identity; changing a display name changes nothing. *(Amended 2026-10-16: on the app's own Project and Branch, the row holding a node's `logicalId` is that node's row, so a deploy resuming an interrupted create uses it. Superseded by ADR-0057: addresses start with the app name, and resource IDs, env keys and `serviceOrigin()` are built from them; the identity rules here are carried forward.)*
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/deploying.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,8 +469,8 @@ resolves a single `effect`.
The fix is to use the same `effect` as Composer. Match your own `effect`
dependency to `@prisma/composer`'s exact pin (see its `dependencies.effect`),
or, when a dependency you cannot change pins another version, force
Composer's. `<pin>` below stands for that exact version (`4.0.3` in
Composer 0.29.1). With npm, in your app's `package.json`:
Composer's. `<pin>` below stands for that exact version (`4.1.0` at the time of
writing). With npm, in your app's `package.json`:

```json
"overrides": {
Expand Down Expand Up @@ -526,6 +526,7 @@ What deployed apps actually run into, and what to do about it:
ingress) buffers a response until it completes, so an open SSE tail
delivers nothing and times out at 60s. Don't build on streamed HTTP
responses.
- **A new named hostname adds a DNS wait to the deploy.** Before it attaches the hostname, the deploy asks the hostname's authoritative nameservers for its CNAME record, every 3 seconds for up to a minute, and waits 10 more seconds once they all answer. The machine that runs the deploy needs DNS access; if the lookups fail, the deploy goes ahead and the platform reports any missing record.
- **Next.js: pages that call `service.load()` need
`export const dynamic = 'force-dynamic'`.** The runtime environment doesn't
exist at build time, and Next won't re-read it for prerendered routes.
Expand Down
4 changes: 2 additions & 2 deletions examples/bucket/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"@prisma/composer": "workspace:0.36.0",
"@prisma/composer-cli": "workspace:0.36.0",
"@prisma/composer-prisma-cloud": "workspace:0.36.0",
"alchemy": "2.0.0-beta.83",
"effect": "4.0.3"
"alchemy": "catalog:",
"effect": "catalog:"
},
"devDependencies": {
"@types/bun": "^1.3.13",
Expand Down
6 changes: 3 additions & 3 deletions examples/cron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
"destroy": "( set -a; . \"${PRISMA_DEPLOY_ENV:-../../.env}\"; set +a; bun ../../scripts/composer-destroy.ts --environment production ${CRON_STACK_NAME:+--name \"$CRON_STACK_NAME\"} )"
},
"dependencies": {
"@effect/platform-bun": "4.0.3",
"@effect/platform-bun": "catalog:",
"@prisma/composer": "workspace:0.36.0",
"@prisma/composer-prisma-cloud": "workspace:0.36.0",
"alchemy": "2.0.0-beta.83",
"alchemy": "catalog:",
"arktype": "^2.2.3",
"effect": "4.0.3"
"effect": "catalog:"
},
"devDependencies": {
"@prisma/composer": "workspace:0.36.0",
Expand Down
2 changes: 1 addition & 1 deletion examples/orm-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"@prisma/composer": "workspace:0.36.0",
"@prisma/composer-prisma-cloud": "workspace:0.36.0",
"@prisma/orm-postgres": "8.0.0-rc.20",
"effect": "4.0.3",
"effect": "catalog:",
"pg": "8.22.0"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions examples/storage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"@aws-sdk/client-s3": "^3.1085.0",
"@prisma/composer": "workspace:0.36.0",
"@prisma/composer-prisma-cloud": "workspace:0.36.0",
"alchemy": "2.0.0-beta.83",
"effect": "4.0.3"
"alchemy": "catalog:",
"effect": "catalog:"
},
"devDependencies": {
"@prisma/composer": "workspace:0.36.0",
Expand Down
6 changes: 3 additions & 3 deletions examples/store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@
"destroy": "( set -a; . ../../.env; set +a; bun ../../scripts/composer-destroy.ts --environment production ${STORE_STACK_NAME:+--name \"$STORE_STACK_NAME\"} )"
},
"dependencies": {
"@effect/platform-bun": "4.0.3",
"@effect/platform-bun": "catalog:",
"@prisma/composer": "workspace:0.36.0",
"@prisma/composer-cli": "workspace:0.36.0",
"@prisma/composer-prisma-cloud": "workspace:0.36.0",
"@store/catalog": "workspace:0.36.0",
"@store/orders": "workspace:0.36.0",
"@store/promotions": "workspace:0.36.0",
"@store/storefront": "workspace:0.36.0",
"alchemy": "2.0.0-beta.83",
"alchemy": "catalog:",
"arktype": "^2.2.3",
"effect": "4.0.3"
"effect": "catalog:"
},
"devDependencies": {
"@types/bun": "^1.3.13",
Expand Down
6 changes: 3 additions & 3 deletions examples/storefront-auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@
"test": "bun test module.test.ts"
},
"dependencies": {
"@effect/platform-bun": "4.0.3",
"@effect/platform-bun": "catalog:",
"@prisma/composer": "workspace:0.36.0",
"@prisma/composer-prisma-cloud": "workspace:0.36.0",
"@storefront-auth/auth": "workspace:0.36.0",
"@storefront-auth/storefront": "workspace:0.36.0",
"alchemy": "2.0.0-beta.83",
"alchemy": "catalog:",
"arktype": "^2.2.3",
"effect": "4.0.3"
"effect": "catalog:"
},
"devDependencies": {
"dotenv": "^17.4.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/0-framework/1-core/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
},
"dependencies": {
"@standard-schema/spec": "^1.1.0",
"alchemy": "2.0.0-beta.83",
"effect": "4.0.3",
"alchemy": "catalog:",
"effect": "catalog:",
"@internal/foundation": "workspace:0.36.0"
},
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion packages/0-framework/3-tooling/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,12 @@
"dotenv": "^17.4.2"
},
"devDependencies": {
"@alchemy.run/prisma": "catalog:",
"@internal/tsdown-config": "workspace:0.36.0",
"alchemy": "2.0.0-beta.83",
"@types/bun": "^1.3.13",
"@types/cross-spawn": "^6.0.6",
"@types/node": "^26.0.1",
"alchemy": "catalog:",
"tsdown": "^0.22.7",
"typescript": "^6.0.3"
},
Expand Down
Loading
Loading