Skip to content
Merged
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
4 changes: 2 additions & 2 deletions .agents/rules/runtime-tsdown-build-isolation.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ alwaysApply: false
# Runtime `tsdown build()` must be isolated from the package build config

Some packages call tsdown's programmatic `build()` at **runtime** (not as their
own build step) — e.g. `@prisma/compose-node` and `@prisma/compose-nextjs` bundle the
user's server inside `assemble()` during `prisma-compose deploy`.
own build step) — e.g. `@prisma/composer-node` and `@prisma/composer-nextjs` bundle the
user's server inside `assemble()` during `prisma-composer deploy`.

tsdown's `build()` **auto-discovers a `tsdown.config.ts`** from the working
directory. Every publishable package now has one (it enables tsdown's `exports`
Expand Down
4 changes: 2 additions & 2 deletions .agents/rules/test-import-patterns.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ workspace package decides what it exercises.
## Within-package tests

- **Import from source** (`../foo.ts`, `./foo.ts`) — not from the package's own
identifier. Importing your own package by name (`@prisma/compose`) resolves to its
identifier. Importing your own package by name (`@prisma/composer`) resolves to its
built `dist/`, which is stale relative to the source you are editing.

## Cross-package / integration tests

- **Import from the package identifier** (`@prisma/compose`, `@prisma/compose-cloud`, …)
- **Import from the package identifier** (`@prisma/composer`, `@prisma/composer-cloud`, …)
to verify the real public surface. This resolves to `dist/`, so the dependency
must be built first — the `test`/`typecheck` turbo tasks build deps up front,
and CI builds before testing (see
Expand Down
6 changes: 3 additions & 3 deletions .agents/rules/tsdown-config-package-source-only.mdc
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
description: Keep @prisma/compose-tsdown source-only exports
description: Keep @prisma/composer-tsdown source-only exports
alwaysApply: false
globs: ["packages/tsdown-config/**"]
---

# @prisma/compose-tsdown source-only policy
# @prisma/composer-tsdown source-only policy

The package `packages/tsdown-config` (`@prisma/compose-tsdown`) is the shared tsdown
The package `packages/tsdown-config` (`@prisma/composer-tsdown`) is the shared tsdown
base config. It is source-only and must not add emitted JavaScript artifacts to
work around runtime config loading.

Expand Down
8 changes: 4 additions & 4 deletions .agents/rules/workspace-package-not-found.mdc
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
---
description: "A missing workspace package (Cannot find module '@prisma/compose-*' / '@prisma/compose-alchemy' / 'prisma-compose', ERR_MODULE_NOT_FOUND / bun ResolveMessage) is a build/install-state issue, not a code bug — verify with require.resolve (pnpm links per-consumer, not repo root), then pnpm build (stale dist) / pnpm install (new dep)"
description: "A missing workspace package (Cannot find module '@prisma/composer-*' / '@prisma/composer-alchemy' / 'prisma-composer', ERR_MODULE_NOT_FOUND / bun ResolveMessage) is a build/install-state issue, not a code bug — verify with require.resolve (pnpm links per-consumer, not repo root), then pnpm build (stale dist) / pnpm install (new dep)"
globs: []
alwaysApply: true
---

# A missing workspace package is a build/install state issue, not a code bug

The workspace's own packages — `@prisma/compose`, `@prisma/compose-*`, `@prisma/compose-alchemy`,
and the unscoped `prisma-compose` — build to `dist/` and export from there. When one
The workspace's own packages — `@prisma/composer`, `@prisma/composer-*`, `@prisma/composer-alchemy`,
and the unscoped `prisma-composer` — build to `dist/` and export from there. When one
of them fails to resolve ("Cannot find module", `ERR_MODULE_NOT_FOUND`, or bun's
`ResolveMessage`), don't chase it as an import/tsconfig/deps bug.

1. **Verify — a repo-root check lies.** pnpm links workspace packages into the
*consumer's* `node_modules`, never at the repo root:
`node -e "require.resolve('@prisma/compose-node', { paths: ['test/integration'] })"`.
`node -e "require.resolve('@prisma/composer-node', { paths: ['test/integration'] })"`.
2. **Resolves but still fails → stale `dist`** (these packages export `dist/`):
run `pnpm build`. Cross-package (and self-name) imports only resolve once the
dependency's dist exists; the `test`/`typecheck` turbo tasks build deps first,
Expand Down
2 changes: 1 addition & 1 deletion .claude/agents/agent-os/designer.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ color: purple
model: inherit
---

You are a design facilitation specialist for Prisma Compose.
You are a design facilitation specialist for Prisma Composer.

Your job is to facilitate product/architecture design discussions and turn outcomes into incremental updates to the design documentation framework under `docs/design/`.

Expand Down
10 changes: 5 additions & 5 deletions .claude/agents/domain-modeler.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ This agent is designed to be “set loose”: you do the research, make reasonab

4. **Separate stable research from evolving takeaways**
- Keep “how the system works” relatively stable in research docs.
- Keep “what Prisma Compose should do because of it” in a separate takeaways doc that can evolve.
- Keep “what Prisma Composer should do because of it” in a separate takeaways doc that can evolve.

5. **Be explicit about uncertainty**
- Track open questions and assumptions at the end of each doc.
Expand Down Expand Up @@ -85,8 +85,8 @@ Produce this set of files (mirrors the `TanStack/` pattern):
- the user mental model and how it maps to underlying mechanics
- `execution-flows.md`
- the “always happening” flows (deploy lifecycle, routing, local dev loops, etc.)
- `takeaways-for-prisma-compose.md`
- explicitly evolving: what Prisma Compose should emulate/adapt, plus design questions raised
- `takeaways-for-prisma-composer.md`
- explicitly evolving: what Prisma Composer should emulate/adapt, plus design questions raised

Writing guidelines:
- Prefer **small, scannable** docs over one huge one.
Expand All @@ -112,10 +112,10 @@ When asked to “model Cloudflare + Wrangler”, a successful output usually inc

- A new folder: `docs/design/04-inspirations/Cloudflare/` (or similarly named)
- The standard library docs listed above, cross-linked and consistent
- A takeaways doc that cleanly separates “research facts” from “Prisma Compose implications”
- A takeaways doc that cleanly separates “research facts” from “Prisma Composer implications”

## Guardrails

- Do **not** change Prisma Compose’s core domain docs (`docs/design/03-domain-model/`, `docs/design/10-domains/`) unless the user explicitly asks you to translate research into Prisma Compose design changes.
- Do **not** change Prisma Composer’s core domain docs (`docs/design/03-domain-model/`, `docs/design/10-domains/`) unless the user explicitly asks you to translate research into Prisma Composer design changes.
- Do **not** create ADRs unless the user explicitly indicates a decision has been made.
- Prefer documenting what you can verify; label inferred models as assumptions.
22 changes: 11 additions & 11 deletions .drive/deferred.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
- **"Built output missing" error not covered by CLI-package tests — closed by
S5.** `test/integration/test/cli.entry-anchored-resolution.test.ts` now
drives the real CLI binary against a real, unbuilt fixture app and asserts
on the real "no built entry at" message from `@prisma/compose-node`'s assembler.
on the real "no built entry at" message from `@prisma/composer-node`'s assembler.
Origin: S3 review.
- **CLI publishability — closed by S5.** The CLI no longer depends on any
target/adapter pack; resolution is anchored at the app's entry package via
Expand All @@ -31,7 +31,7 @@
encryption at rest.
2. **Reserved/unique project names** — PDP allows duplicate project names
(verified 2026-07-09), so name-based discovery of control-plane projects
(`prisma-compose-state`) is ambiguous and squattable; the client-side ownership
(`prisma-composer-state`) is ambiguous and squattable; the client-side ownership
marker (bootstrap.ts `verifyOwnership`) is a workaround. Ask: unique names
per workspace, or atomic create-if-absent, or a system-project concept.
Related: workspace ids circulate in two shapes (`wksp_`-prefixed in API
Expand Down Expand Up @@ -59,26 +59,26 @@
the standing concern).
- **Deterministic Next-standalone artifact** (BUILD_ID non-determinism →
Next services re-version on unchanged redeploys).
- **`@prisma/compose-node` rename** (descriptor kind means "plain server process",
- **`@prisma/composer-node` rename** (descriptor kind means "plain server process",
not Node.js runtime — needs operator naming call).
- **Interval-lease follow-ups from R8/R9 reviews**: `--wait` affordance on
lock contention; connection-cap telemetry for the state store.
- **CI workspace sweep** (operator/token): ~17 duplicate `prisma-compose-state`
- **CI workspace sweep** (operator/token): ~17 duplicate `prisma-composer-state`
projects accumulated in the CI workspace during the id-shape bug; deploys
are stable (deterministic oldest-first adoption) but they're quota noise.
- **core-model.md R6 absorption**: the doc's type sketches (Nodes, factories,
Graph, SystemBuilder) predate R6 — `expose`, `ConnectionEnd.required`,
ref-ports, the two-overload `provision()`, and required `name`/`pack` are
shipped but absent from the sketches. The false "not yet built" claims and
the missing `@prisma/compose-rpc` entry-map row were fixed at close-out; absorbing
the missing `@prisma/composer-rpc` entry-map row were fixed at close-out; absorbing
the full mechanism into the sketches is a docs slice of its own
(connection-contracts.md is the accurate record meanwhile).

# Stage-as-branch — deferred (2026-07-12)

- **Route container resolution through the extension, not the CLI.** Today
`@prisma/compose-cli` hard-codes the Prisma Cloud specifics of stage resolution:
it imports `@prisma/compose-alchemy`'s `resolveContainer`/`deleteBranch` directly and
`@prisma/composer-cli` hard-codes the Prisma Cloud specifics of stage resolution:
it imports `@prisma/composer-alchemy`'s `resolveContainer`/`deleteBranch` directly and
sets the target-specific `PRISMA_PROJECT_ID`/`PRISMA_BRANCH_ID` env vars on
the alchemy child (`run-alchemy.ts`). That is Prisma Cloud config leaking
into the otherwise target-agnostic CLI — accepted for the first
Expand All @@ -91,18 +91,18 @@
# Auth — deferred (2026-07-12)

- **Adopt the `@prisma/cli` credential mechanism; stop rolling our own auth.**
`@prisma/compose` authenticates the Management API with a static
`@prisma/composer` authenticates the Management API with a static
`PRISMA_SERVICE_TOKEN` read from the env and sent as a raw `Bearer` header
(`@prisma/compose-alchemy` `credentials.ts` `fromEnv()` → `client.ts`
(`@prisma/composer-alchemy` `credentials.ts` `fromEnv()` → `client.ts`
`createManagementApiClient({ token })`) — no login, no refresh, no stored
credential; a long-lived plaintext token in `.env`. `@prisma/cli` already
solves this: interactive `prisma auth login` (PKCE OAuth against
`auth.prisma.io`), a persisted + auto-refreshed credential, with
`PRISMA_SERVICE_TOKEN` as the CI/non-interactive fallback. The same SDK ships
the machinery we're not using (`@prisma/management-api-sdk`:
`createManagementApiSdk` + `createTokenRefreshingFetch`). Ask: reuse the
prisma CLI's credential resolution in `@prisma/compose` — ideally its own loader,
so we don't reimplement the store/refresh — so `prisma-compose deploy`
prisma CLI's credential resolution in `@prisma/composer` — ideally its own loader,
so we don't reimplement the store/refresh — so `prisma-composer deploy`
authenticates exactly like the rest of the CLI and we maintain no auth of our
own. Touches `credentials.ts`, `client.ts`, `app-cli/ensure-containers.ts`,
and the token-based state-store bootstrap (`state/bootstrap.ts`). Origin: auth
Expand Down
12 changes: 6 additions & 6 deletions .drive/next-session-brief.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Next-session brief — Prisma Compose
# Next-session brief — Prisma Composer

You're picking up the **Prisma Compose**, the authoring layer for Prisma Cloud:
You're picking up the **Prisma Composer**, the authoring layer for Prisma Cloud:
developers describe services and their typed dependencies in TypeScript, and
the framework deploys them to Prisma Compute + Prisma Postgres. Work runs
under the **Drive process** (`drive-process` skill). The **authoring-layer
Expand All @@ -18,7 +18,7 @@ its `spec.md` and `plan.md`; tracker issues TML-2998…3005.
2. `docs/design/10-domains/connection-contracts.md` — typed service-to-service
Contracts (`contract()`/`rpc()`/`serve()`, assignability + `satisfies()` +
per-call validation).
3. `docs/design/10-domains/deploy-cli.md` — `prisma-compose deploy <entry>`: the
3. `docs/design/10-domains/deploy-cli.md` — `prisma-composer deploy <entry>`: the
zero-config pipeline (Load → infer target → assemble → generated stack →
Alchemy).
4. `docs/design/90-decisions/` — ADR-0003…0012. The state-store set
Expand All @@ -32,8 +32,8 @@ its `spec.md` and `plan.md`; tracker issues TML-2998…3005.

## Likely next work

- **Naming/rename**: an operator design session settled **Prisma Compose
(`@prisma/compose`) replacing "MakerKit" and Module/`mod()` replacing Hex** (see
- **Naming/rename**: an operator design session settled **Prisma Composer
(`@prisma/composer`) replacing "MakerKit" and Module/`mod()` replacing Hex** (see
agent memory `naming-decisions-2026-07`); the rename has since shipped as
ADR-0014 (framework: Prisma App, unit: System, not Module). Confirm any
remaining scope with the operator.
Expand Down Expand Up @@ -70,7 +70,7 @@ its `spec.md` and `plan.md`; tracker issues TML-2998…3005.
Never print secrets.
- **Deploy state is hosted** (ADR-0009): no local `.alchemy` state matters;
any credentialed machine deploys incrementally. The workspace shows a
`prisma-compose-state` project — control-plane, never delete it as cleanup.
`prisma-composer-state` project — control-plane, never delete it as cleanup.
- **turbo 2 strict env** strips undeclared vars from tasks — declare in
turbo.json (`env`/`globalPassThroughEnv`). Check this first when CI-only
failures make no sense.
Expand Down
2 changes: 1 addition & 1 deletion .drive/projects/config-params-and-cron/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fixed by ADR-0018/0019/0020 and the two domain docs; these slices implement it.

Slices are identified by S-number here; this plan is the source of truth. Linear
issues are created per-slice when the slice starts, not during planning. Tracker
project: [Prisma App: Config Params + Cron](https://linear.app/prisma-company/project/prisma-compose-config-params-cron-78113f9ba550).
project: [Prisma App: Config Params + Cron](https://linear.app/prisma-company/project/prisma-composer-config-params-cron-78113f9ba550).

- **S1** — TML-3007 — Done ([PR #41](https://github.com/prisma/app/pull/41), merged).
- **S2** — TML-3010 — In progress ([spec](specs/s2-cron-driver-system.md)).
Expand Down
4 changes: 2 additions & 2 deletions .drive/projects/config-params-and-cron/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Four decisions, realized in two slices:
- Is the framework foundation the **Forcing-Function Apps** project depends on: its
cron slice (datahub `/tick`) consumes this project's output, and its object-storage
slice will reuse the structured-param mechanism.
- Tracker: [Prisma App: Config Params + Cron](https://linear.app/prisma-company/project/prisma-compose-config-params-cron-78113f9ba550)
- Tracker: [Prisma App: Config Params + Cron](https://linear.app/prisma-company/project/prisma-composer-config-params-cron-78113f9ba550)
(Terminal). Linear issues are created per-slice when a slice starts, not now.

# Cross-cutting requirements
Expand All @@ -62,7 +62,7 @@ Four decisions, realized in two slices:
nor an encoding, never stringifies, and never reads storage.
- **The target owns the medium too.** Encoding, logic, and medium are all the
target's; the framework fixes none of them (env key/value strings are
`@prisma/compose-cloud`'s choice). Params are target-agnostic.
`@prisma/composer-cloud`'s choice). Params are target-agnostic.
- **Structured values stay visible to the graph.** `configOf` reports a param's
schema, not "a string" — introspection and a future native lowering can read the
real shape.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Three coupled changes to the config model:

1. **Schema-typed params** — `ConfigParam` becomes a plain `{ schema, secret?,
optional?, default? }`; the `ParamType = 'string' | 'number'` enum is deleted.
2. **Target-owned serialization** — the target (`@prisma/compose-cloud`) owns all
2. **Target-owned serialization** — the target (`@prisma/composer-cloud`) owns all
encoding, driven by the schema; core never stringifies. `compute()` opens to
user params.
3. **`config()`/`load()` split** — params are read through a new `config()`;
Expand Down Expand Up @@ -42,18 +42,18 @@ export interface ConfigParam<S extends StandardSchemaV1 = StandardSchemaV1> {
- Delete `ParamType` and `TypeOf`. `Values<P>` infers each value via
`StandardSchemaV1.InferOutput<P[K]['schema']>`, keeping the existing
optional/default widening.
- Add core dep `@standard-schema/spec` (type-only; already used by `@prisma/compose-rpc`).
- Add core dep `@standard-schema/spec` (type-only; already used by `@prisma/composer-rpc`).
- Core helpers `string(opts?)`, `number(opts?)` (→ `{ schema: type('string'|'number'), ...opts }`)
and `param(schema, opts?)` (→ `{ schema, ...opts }`). Export from `@prisma/compose`.
and `param(schema, opts?)` (→ `{ schema, ...opts }`). Export from `@prisma/composer`.
Update `packages/app/src/index.ts` (drop `ParamType`/`TypeOf`).
- `ConfigDeclaration` / `configOf` (introspection): replace `type: ParamType` with a
JSON-Schema projection of the param's schema. Stays pure data.
- `packages/app/src/node.ts` `freezeParams` keeps working over the new shape.

## 2. Target-owned serialization (`@prisma/compose-cloud`)
## 2. Target-owned serialization (`@prisma/composer-cloud`)

The target owns encoding, logic, and medium; core hands it the typed `Config`.
Two sites in `@prisma/compose-cloud` do the work today by hand and must drive off the
Two sites in `@prisma/composer-cloud` do the work today by hand and must drive off the
schema instead:

- **Deploy encode** — `control.ts` `serialize` (`ServiceLowering.serialize`):
Expand Down Expand Up @@ -127,7 +127,7 @@ are already correct.)
## Non-goals (this slice)

- **Cron** — S2.
- **A second target** — only `@prisma/compose-cloud` serializes; a second target's
- **A second target** — only `@prisma/composer-cloud` serializes; a second target's
medium is out of scope.
- **Field-level secrets, provisioning refs inside structured params** — excluded by
ADR-0018/0019.
Expand Down
Loading
Loading