Skip to content

Accept a deployed app's addresses as command subjects: prisma service logs @pr-42:shop.api - #373

Merged
wmadden-electric merged 15 commits into
mainfrom
feat/node-address-subjects
Oct 28, 2026
Merged

wmadden-electric merged 15 commits into
mainfrom
feat/node-address-subjects

Conversation

@wmadden-electric

Copy link
Copy Markdown
Contributor
$ prisma service logs @pr-42:shop.api
project: proj_…
service: shop.api
version: cpv_…
… log lines …

$ prisma postgres delete @shop.catalog --confirm wrong
✘ [CLI.CONSENT_REQUIRED] "Deleting database db_… in production (branch main) is destructive and requires the exact address." … Grant it by passing --confirm @shop.catalog.

Decision

Every command whose subject is a project, service, database or bucket now accepts an address in place of the id: @<environment>:<address>. Leave the environment out and it means production.

Why

A Composer app names each part it deploys. For example, shop.catalog is the catalog database inside the app shop. Composer writes that name to the platform as the row's logicalId. prisma deploy list prints these names. Until now, using one with a platform command meant looking up the row's id first. With this change, people and agents can pass the name straight to the commands they already use.

How an address is read

  1. Split at the first :. Before it is the environment; after it is the address. Branch names will reject : (PRO-225), so the split cannot be wrong.
  2. Find the Project. The address's first dot segment is the app name. It is the Project's logicalId (GET /v1/projects?logicalId=).
  3. Find the Branch. With no environment, or with production, this is the Project's default Branch (isDefault). This is Composer's own rule for production. Any other environment is the Branch whose git name matches it.
  4. Find the row. The CLI lists that kind with logicalId equal to the full address on that Branch, and matches it exactly on the client too. Older address formats are not translated.
  5. Hand over. The command then runs exactly as it does when given the row's id.

A Project's address is the app name alone, with no environment. prisma project delete @pr-42:shop is refused, because deleting a Project removes every environment, production included.

Safety

A destructive command given an address takes the address itself as its --confirm token. The consent question names the row's id and environment, and says plainly when the environment is production.

Combining --project or --branch with an address is a usage error, because the address already names both.

Errors

New codes, each with next actions:

  • ADDRESS.USAGE_ERROR: a malformed address, a flag combined with an address, or an environment on a Project address.
  • ADDRESS.NOT_FOUND: no Project, no Branch, or nothing at that address.
  • ADDRESS.AMBIGUOUS: more than one match.
  • ADDRESS.WRONG_KIND: the address names another kind, such as a database given to service logs.
  • ADDRESS.API_ERROR: a listing failed.

Commands covered

  • service: show, delete, logs, open, version list, version rollback
  • postgres: show, delete, usage, backup list, backup restore, connection list, connection create
  • bucket: delete, key list, key create, key delete
  • project: show, delete, transfer, link

Version ids, connection ids and domain hostnames are not addresses, so those commands are unchanged.

Other changes

  • Branch listing is shared in lib/branch/list.ts; branch list and the service read path now use it.
  • postgres commands share one resolvePostgresDatabase helper.
  • docs/product/command-principles.md describes the address form.

Evidence

  • Unit tests cover parsing, resolution, every error, the production rule, the client-side exact match, flag conflicts and consent.
  • e2e/address.e2e.ts runs against the real Management API: 11 of 11 pass, in order and shuffled. It also gives service logs its first real-API test.
  • Manual QA on a deployed Composer 0.35.0 app (examples/storefront-auth) with a production and a preview environment:
    • service logs and service show reached the right row in each environment.
    • postgres delete by address removed only the preview database.
    • The wrong-kind, not-found and no-branch errors appeared as expected.
    • The QA Project was then deleted with project delete @<app>.

Alternatives considered

  • A --node flag. Rejected, because flags never name a command's subject in this CLI.
  • Keeping the row id as the consent token. Rejected: you would need the id you were trying to avoid looking up, and the address names the target just as exactly once the prompt shows the environment.
  • Resolving production to a Branch literally named production. Rejected: Composer deploys production to the default Branch, which is created as main.

Agent: mulder-63

🤖 Generated with Claude Code

wmadden-electric and others added 15 commits October 27, 2026 19:56
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
A scratch Project with a logicalId, a default and a preview branch,
and rows sharing an address on each, built through the management
API. Covers service logs and show, project show, bucket key list and
delete, postgres show and delete, consent by address, and the
wrong-kind and not-found errors. service logs leaves the coverage
backlog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
branch list and the service read path each had their own cursor loop
over /v1/projects/{projectId}/branches. Both now use one listing that
can also ask the API for a single git name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
…address

postgres delete @shop.db used to ask only for 'the exact address', so a
user could delete production without ever seeing the word. A destructive
command given an address now names the row id, the environment (saying
production plainly) and the branch in its consent question:

  Deleting database db_123 in production (branch main) is destructive
  and requires the exact address.

Alongside:
- The resolver moves to lib/address/address.ts with names for what they
  hold: AddressSubject for the typed @env:address string, AddressMatch
  for the one result, BranchScopedKind for service/database/bucket, and
  resolveBranchScopedSubject beside resolveProjectSubject. ScopeFlags is
  optional, so bucket no longer passes {}.
- A named environment asks the API for that branch by gitName, through
  the shared branch listing.
- Every group trims the subject before reading it as an address, and the
  consent token is the trimmed address.
- The project commands share resolveProjectPositional.
- @env:app on a project command is ADDRESS.USAGE_ERROR; every
  ADDRESS.AMBIGUOUS carries matches: [{id, name}], and every
  ADDRESS.WRONG_KIND carries expected and actual.
- Tests assert which service row was deleted or listed, that the
  client-side logicalId/branchId check holds when the API ignores its
  filters, and that project delete and transfer refuse @env:app at the
  command level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The service, postgres, bucket and project group cards now say how to
name a resource by its address, what the address is (the name the app
gave it, such as shop.db) and what the part before ':' is (the
environment the app was deployed to: its branch, or production when left
out). The postgres card no longer uses 'address' as a verb.

command-principles.md states that production means the Project's
default Branch, not the production-role Branch or a Branch named
production. The error reference drops 'deploy address' and says that an
ADDRESS code can replace a group's own not-found code.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The not-found test used the address the delete test had just emptied,
and the bucket delete removed the bucket other tests read. The delete
tests now act on their own database pair and bucket, the not-found test
uses an address nothing was ever deployed at, and the consent test
checks that the question names the environment and branch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@coderabbitai

coderabbitai Bot commented Oct 27, 2026

Copy link
Copy Markdown

Warning

Review limit reached

This review ran on the open-source allowance, not this organization's plan, because the pull request author doesn't have an assigned seat. Waiting won't change this — ask an organization admin to assign them a seat, or add seats in Billing if every seat is already assigned, then retry.

Next included review available in 58 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 94d588da-bc9d-4e4b-97a5-c43d576e53f8
Commits

Reviewing files that changed from the base of the PR and between 155206e and 53efc9a.

Files selected for processing: 42
  • docs/product/command-principles.md
  • docs/reference/error-reference.md
  • packages/cli/e2e/address.e2e.ts
  • packages/cli/e2e/deployed-service.ts
  • packages/cli/src/cli.ts
  • packages/cli/src/commands/bucket/context.ts
  • packages/cli/src/commands/bucket/delete.ts
  • packages/cli/src/commands/bucket/key-create.ts
  • packages/cli/src/commands/bucket/key-delete.ts
  • packages/cli/src/commands/bucket/key-list.ts
  • packages/cli/src/commands/postgres/backup-list.ts
  • packages/cli/src/commands/postgres/backup-restore.ts
  • packages/cli/src/commands/postgres/connection-create.ts
  • packages/cli/src/commands/postgres/connection-list.ts
  • packages/cli/src/commands/postgres/context.ts
  • packages/cli/src/commands/postgres/delete.ts
  • packages/cli/src/commands/postgres/show.ts
  • packages/cli/src/commands/postgres/usage.ts
  • packages/cli/src/commands/project/context.ts
  • packages/cli/src/commands/project/delete.ts
  • packages/cli/src/commands/project/link.ts
  • packages/cli/src/commands/project/show.ts
  • packages/cli/src/commands/project/transfer.ts
  • packages/cli/src/commands/service/delete.ts
  • packages/cli/src/commands/service/logs.ts
  • packages/cli/src/commands/service/open.ts
  • packages/cli/src/commands/service/show.ts
  • packages/cli/src/commands/service/target.ts
  • packages/cli/src/commands/service/version-list.ts
  • packages/cli/src/commands/service/version-rollback.ts
  • packages/cli/src/controllers/branch.ts
  • packages/cli/src/lib/address/address.ts
  • packages/cli/src/lib/app/read-branch.ts
  • packages/cli/src/lib/branch/list.ts
  • packages/cli/tests/address.test.ts
  • packages/cli/tests/bucket.test.ts
  • packages/cli/tests/e2e-coverage.test.ts
  • packages/cli/tests/helpers/fake-address-api.ts
  • packages/cli/tests/postgres.test.ts
  • packages/cli/tests/project.test.ts
  • packages/cli/tests/service-address.test.ts
  • scripts/list-error-codes.mjs
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@pkg-pr-new

pkg-pr-new Bot commented Oct 27, 2026

Copy link
Copy Markdown

Open in StackBlitz

npx https://pkg.pr.new/@prisma/cli@373
npx https://pkg.pr.new/@prisma/cli-engine@373

commit: 53efc9a

@wmadden
wmadden enabled auto-merge (squash) October 28, 2026 07:03
@wmadden-electric
wmadden-electric merged commit dc78ac7 into main Oct 28, 2026
16 checks passed
@wmadden-electric
wmadden-electric deleted the feat/node-address-subjects branch October 28, 2026 08:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants