Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
ad08295
Run deploy through alchemy/Alchemist in the prisma process
wmadden-electric Oct 31, 2026
bfa4539
Address slice 2 review: app install, values-only lower, safe process …
wmadden-electric Oct 31, 2026
95d63db
Address slice 2 round 2 review: version check, shared flag, exit 130
wmadden-electric Oct 31, 2026
38e2d2e
Check a converge contract, not the package version; keep the outcome …
wmadden-electric Oct 31, 2026
686a1f8
Merge branch 'claude/alchemy-api-evaluation-5f1d17' into claude/alche…
wmadden-electric Nov 3, 2026
4ac2b24
Merge branch 'claude/alchemy-api-evaluation-5f1d17' into claude/alche…
wmadden-electric Nov 5, 2026
5fb814e
build(deps): pin the alchemy and distilled previews that make the Pri…
wmadden-electric Nov 6, 2026
c259ac6
feat(core): lower() hands the caller's credentials to providers and s…
wmadden-electric Nov 6, 2026
aa67480
feat(prisma-cloud): send every Management API request through the sup…
wmadden-electric Nov 6, 2026
57dd838
feat(cli): prisma deploy works with a prisma login session
wmadden-electric Nov 6, 2026
53cf8b6
docs: deploy authenticates through ctx.api
wmadden-electric Nov 6, 2026
5a21d7c
build(deps): pin alchemy to the tarball @alchemy.run/prisma names as …
wmadden-electric Nov 6, 2026
223f090
fix(prisma-cloud): address slice 4 review of deploy through ctx.api
wmadden-electric Nov 6, 2026
d7125d3
fix(prisma-cloud): send state store requests through ctx.api in a rea…
wmadden-electric Nov 6, 2026
e958c4e
ci: build lowering dependencies before the logical-id resolution check
wmadden-electric Nov 6, 2026
1602a7f
Merge branch 'claude/alchemy-api-evaluation-5f1d17' into claude/alche…
wmadden-electric Nov 6, 2026
98460cd
fix(cli): keep the converge contract at 2
wmadden-electric Nov 6, 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
1 change: 1 addition & 0 deletions .github/workflows/e2e-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -182,4 +182,5 @@ jobs:
persist-credentials: false
- uses: ./.github/actions/setup
- run: pnpm install --frozen-lockfile
- run: pnpm turbo run build --filter '@internal/lowering^...'
- run: bun scripts/logical-id-resolution.ts
12 changes: 12 additions & 0 deletions architecture.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,18 @@
"layer": "public",
"plane": "control"
},
{
"glob": "packages/9-public/composer/src/exports/internal-converge.ts",
"domain": "public",
"layer": "public",
"plane": "control"
},
{
"glob": "packages/9-public/composer/src/exports/internal-converge-contract.ts",
"domain": "public",
"layer": "public",
"plane": "control"
},
{
"glob": "packages/9-public/composer-cli/src/exports/family.ts",
"domain": "public",
Expand Down
10 changes: 9 additions & 1 deletion docs/design/03-domain-model/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ The values one command knows are secrets: the value under each secrets key the g

### The app configuration file

The JSON file a command's first process writes for its second process. It holds what Load read from the app configuration (the root input fields the root's body passes on, and the text of each configuration key the graph reads) and the first process's node addresses. It never holds a secret: Load and the CLI refuse to write one into it. Deploy and destroy write it to `.prisma-composer/app-configuration-<pid>-<uuid>.json` and delete it when the run ends. `prisma dev` writes it to `<dev environment dir>/app-configuration-<pid>.json` before each converge and deletes it as soon as that converge ends. Only its owner can read it. The CLI also deletes it when its process exits. A file left by a process killed outright is deleted at the start of a later deploy, destroy or `prisma dev`, once it is ten minutes old. It is not `prisma.config.ts`, which is "the config file". In code: `PRISMA_COMPOSER_APP_CONFIGURATION_FILE`, `AppConfigurationRead`, `readAppConfigurationFile`.
The JSON file a command's first process writes for its second process. It holds what Load read from the app configuration (the root input fields the root's body passes on, and the text of each configuration key the graph reads) and the first process's node addresses. It never holds a secret: Load and the CLI refuse to write one into it. Destroy writes it to `.prisma-composer/app-configuration-<pid>-<uuid>.json` and deletes it when the run ends. Deploy writes none: it runs Alchemy in its first process and hands `lower()` what Load read as a value (ADR-0064). `prisma dev` writes it to `<dev environment dir>/app-configuration-<pid>.json` before each converge and deletes it as soon as that converge ends. Only its owner can read it. The CLI also deletes it when its process exits. A file left by a process killed outright is deleted at the start of a later deploy, destroy or `prisma dev`, once it is ten minutes old. It is not `prisma.config.ts`, which is "the config file". In code: `PRISMA_COMPOSER_APP_CONFIGURATION_FILE`, `AppConfigurationRead`, `readAppConfigurationFile`.

### Config adapter

Expand Down Expand Up @@ -410,6 +410,10 @@ The compilation from one plane to the next: authoring topology → provisioning
resource graph → hosting primitives. Analogous to Prisma ORM lowering a contract
to a plan.

### Converge

Making an environment match the lowered stack: Alchemy plans what to create, update, replace and delete, then applies it. `prisma deploy` converges in its own process through Alchemy's programmatic API; `prisma dev` and `destroy` converge in an Alchemy child process. The *app converge* is the app install's `lower` and in-process converge, which `deploy` loads from `@prisma/composer/internal/converge` ([ADR-0064](../90-decisions/ADR-0064-deploy-runs-alchemy-in-process.md)). Codes: `DEV.CONVERGE_FAILED`, `DEPLOY.CONVERGE_RUNNING`, `DEPS.CONVERGE_UNRESOLVABLE`, `DEPS.CONVERGE_CONTRACT_MISMATCH`.

### Control plane / Execution plane

Two the framework modes. **Control plane**: import the topology, validate, build the
Expand Down Expand Up @@ -456,6 +460,10 @@ otherwise found by `gitName` or created). The
deploy CLI resolves and ensures both; Alchemy provisions only the resources
inside them and never creates or destroys a container itself.

### Caller credentials

What the caller of a deploy or destroy has already authenticated: a workspace and a platform API client (`CallerCredentials`). For `prisma deploy` they are the active credential's workspace and the engine's `ctx.api`. The framework hands them unchanged to every extension hook that talks to the platform: the container lifecycle, `preflight`, reporters, `providers` and the state store. When the caller has none, each extension uses its own credential protocol, for Prisma Cloud `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID` ([ADR-0064](../90-decisions/ADR-0064-deploy-runs-alchemy-in-process.md)).

## Authoring surface — the next layer

How a developer actually writes the [Core nouns](#core-nouns). The concrete
Expand Down
12 changes: 3 additions & 9 deletions docs/design/05-prisma-cloud/build-reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,7 @@ The CLI calls the hook three times:
`state` (`succeeded`, `failed` or `cancelled`), `failingStep` (Composer's
error code, capped at 500 characters) and `errorMessage` (capped at 5000).

The session also hands the alchemy child its environment through
`childEnv()`: `PRISMA_BUILD_ID`, so reporting inside the apply finds the run.
The session also hands the apply its environment through `childEnv()`: `PRISMA_BUILD_ID`, so reporting inside the apply finds the run. `deploy` runs the apply in its own process and sets these variables in `process.env` for the length of the apply ([ADR-0064](../90-decisions/ADR-0064-deploy-runs-alchemy-in-process.md)).

The reporter installs no signal handlers. The CLI engine owns signals, and an
interrupt reaches the reporter as `cancelled` on the ordinary `finish` path.
Expand Down Expand Up @@ -170,9 +169,7 @@ has no resource row; the Build's `projectId` carries the association.

`--report <path>` or `PRISMA_COMPOSER_REPORT_FILE` writes a versioned JSON file
with the app, its environment, its nodes and entities (including preview URLs), and
the failure cause. It is written on failure too. It is separate from the
internal summary the alchemy child hands the CLI, which is deleted after every
run so resource ids and URLs do not accumulate on disk. The Prisma GitHub
the failure cause. It is written on failure too. It is separate from the deployment summary `deploy` returns as a value, which is never written to disk. The Prisma GitHub
Action reads it to comment preview links on a pull request. It is
transitional: it can go once the Action reads the Build, topology and versions
from the platform.
Expand All @@ -199,10 +196,7 @@ from the platform.
builds. An interrupt the engine catches is reported as `cancelled`; SIGKILL
and a torn-down CI runner cannot be. CI cancellation is common, so this is
the normal case, not a defect.
- **A failed apply reports `DEPLOY.ENGINE_FAILED` as its `failingStep`.** Every
failure inside the alchemy child shares that code. The `errorMessage`
carries the exit status and, when the child recorded one on its way out, the
underlying cause.
- **A failed apply reports `DEPLOY.ENGINE_FAILED` as its `failingStep`.** Every failure Alchemy's plan or apply ends with shares that code. The `errorMessage` carries the errors Alchemy failed with, with every known secret and credential-looking value removed (ADR-0062).
- **`branchId` stays empty on a `production` deploy.** Only the Branch of
another environment is attached to the Build.

Expand Down
2 changes: 1 addition & 1 deletion docs/design/10-domains/core-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ interface LowerOptions {
readonly name: string // stack name (+ Load's root id override)
readonly environment?: string // the environment being deployed, as --environment gave it;
// Load's environment.name. The generated stack files always pass it.
readonly appConfigurationRead?: AppConfigurationRead // passed to Load and the serializer; the generated stack files read it from the app configuration file
readonly appConfigurationRead?: AppConfigurationRead // passed to Load and the serializer; deploy passes its own Load's, the generated stack files read it from the app configuration file
readonly firstProcessNodeAddresses?: readonly string[] // from the same file; lowering refuses a graph whose addresses differ
// `prisma deploy` runs each service's build-adapter assembler and writes
// the resulting bundle dirs here, into the generated stack file it hands to
Expand Down
Loading
Loading