Skip to content

A node depends on an interface or exposes one: retire Input and Output, rename the module body's inputs to deps - #398

Open
wmadden-electric wants to merge 7 commits into
claude/resolve-values-ca39d3from
claude/interface-vocabulary
Open

wmadden-electric wants to merge 7 commits into
claude/resolve-values-ca39d3from
claude/interface-vocabulary

Conversation

@wmadden-electric

Copy link
Copy Markdown
Contributor

At a glance

A module body receives its dependencies as deps, the same word the boundary declares them with:

export default module('auth', { deps: { db: rawPostgres() }, expose: { verify: authContract } },
  ({ deps, provision }) => {                                  // was ({ inputs, provision })
    const svc = provision(authService, { id: 'api', deps: { db: deps.db } });
    return { verify: svc.verify };
  });

And the design documents describe the same thing in the same words. The glossary, before and after:

A connection is an edge that wires one node's Output to another node's Input.

A connection is an edge that wires one node's dependency to another node's exposed interface.

What this PR changes

  1. A new decision record: a node depends on an interface or exposes one, and Input and Output are retired as the words for the two ends of a connection.
  2. The glossary defines Interface, Dependency and Exposed interface, and loses its Input, Output and Port entries. The domain map, the layering map, the authoring-surface narrative, the example app, the guiding principles and the domain docs use the new words.
  3. ModuleContext.inputs is renamed deps. The shared modules, the examples, the tests, the guide and the agent skill follow, with an upgrade note in the guide.
  4. The application topology's direction field keeps in and out, now documented as the dependency end and the exposed end.

Why the words were ambiguous

Take a service web that offers an HTTP API and needs a database. Composer's documents named the two ends by dataflow: the API is an output, because other nodes call web through it, and the database is an input, because web calls it. Ports and adapters, the architecture most readers bring, names the same two ends the other way round: the API is an input port, because calls come into web through it, and the database is an output port, because calls go out through it.

Both are consistent. Every end has both aspects, who provides it and which way calls flow, and the two traditions weigh them differently. So a reader from either tradition read half the sentences in the glossary backwards. The design discussion behind this change went through exactly that, sentence by sentence, until it was clear the words were the problem rather than either reader.

The words that name the relationship

Whether a node depends on an interface or exposes one is a fact about the node, not a direction the reader has to pick. The authoring surface already said it: deps and expose. The record makes those the vocabulary:

  • An interface is the typed thing a connection carries. In code it is a Contract, which keeps its name. An interface in Composer's terms is what ports and adapters calls a port; that analogy appears once, in the glossary, and "port" is not otherwise used, because Composer also has HTTP and TCP ports.
  • A dependency is a node's need for an interface, declared with deps.
  • An exposed interface is one a node offers, declared with expose; a resource exposes the one interface it provides, and a node may expose nothing.
  • A connection wires a dependency to an exposed interface.

"Input" keeps its other meaning, the configuration document a service or module declares as input. That is not an end of a connection, and the glossary says so once.

The one user-facing rename

The module body's inputs was the only authoring-surface word that called a dependency an input. It is now deps, so the body reads like the boundary it forwards: ({ deps, provision }) => provision(svc, { deps: { db: deps.db } }). The guide's module section carries the upgrade note. Two internal names keep the old word, ServiceNode.inputs and InputRef; renaming them reaches into the Prisma Cloud extension and the local target, so they are recorded as debt in .drive/deferred.md.

The topology's wire field

The application topology sends each end's direction as in or out to the platform, and the Console draws them. The field is not renamed: it belongs to the Portal team's API, and its meaning is unambiguous once defined. in is a dependency, out is an exposed interface, and the type's doc comment now says so.

Tests

No behaviour changes. The rename is covered by the existing module-composition, authored-graph, resource-slot and application-topology tests, which now destructure deps; pnpm typecheck across all 80 packages proves no caller was missed, and the full pnpm test suite passes. The website content test proves every guide link still resolves, and the skill packaging check proves the skill is still the one that ships.

Alternatives considered

  • Keep Input and Output, defined by the dataflow reading. They were already defined that way, and the discussion showed the definition does not survive contact with a reader from the other tradition.
  • Flip Input and Output to the ports-and-adapters reading. Renames ctx.inputs anyway, flips the meaning of a public API field, and moves every end in the Console to the other side of its card, for words that stay ambiguous to the next reader.
  • Provided and required interface (UML's ball-and-socket). Sound, but the authoring surface says deps and expose, and "provider" already means an Alchemy provider here.
  • Driving and driven ports (Cockburn). Nobody on the authoring surface says "driven", and "port" is out.
  • Rename expose to provides so services match resource({ provides }). A user-facing rename for consistency between a keyword and a verb the prose no longer leans on; left for another day.

Agent: hermione-26

🤖 Generated with Claude Code

wmadden-electric and others added 4 commits October 29, 2026 13:37
Input and Output were the words for the two ends of a connection, and
they were ambiguous: the dataflow reading and the ports-and-adapters
reading give the same two ends opposite names. The record settles the
words the authoring surface already uses, deps and expose, with
interface as the noun, and retires the port words.

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

The glossary defines Interface, Dependency and Exposed interface in place
of Input, Output and Port; the domain map, layering map, authoring
surface, example app, principles and domain docs use the same words.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
The one user-facing place that called a dependency an input. The shared
modules, the example and the tests follow; the topology's port direction
field says what in and out mean.

Co-Authored-By: Claude Fable 5.1 <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 Fable 5.1 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>
@prisma-gizmo

prisma-gizmo Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

✅ Gizmo reviewed 885170a — posted 0 inline comment(s) this pass.

Open findings: none

Change walkthrough

This PR retires the Input/Output vocabulary across Composer in favor of dependency / exposed interface — the words the authoring surface already uses (deps / expose) — because the old terms flip meaning between the dataflow and ports-and-adapters reading traditions. A new ADR records the decision, the glossary defines the three new terms, and the one user-facing rename renames ModuleContext.inputs to deps.

Terminology and docs. The glossary, guiding principles, domain map, layering map, example-app narrative, and domain docs now describe a connection as wiring a node's dependency to another node's exposed interface. "Input" survives only in its unrelated meaning — the configuration document declared as input — and the glossary says so once. The example app's tables changed from Inputs/Outputs columns to Depends on/Exposes.

Authoring surface. ModuleContext.inputs is renamed deps so the module body reads like the boundary it forwards (({ deps, provision }) => provision(svc, { deps: { db: deps.db } })). Shared modules, examples, tests, the guide (with an upgrade note), and the agent skill follow the rename. The rename is type-level, and the PR reports pnpm typecheck across all 80 packages plus the full test suite passing, so no caller was missed.

Deliberately unchanged. Two internal names keep the retired word — ServiceNode.inputs and InputRef — because renaming them reaches into the Prisma Cloud extension and the local target; they are recorded as debt in .drive/deferred.md. The application topology's direction: 'in' | 'out' field keeps its wire values since they belong to the Portal team's API; its doc comment now defines in as the dependency end and out as the exposed end. The PR's alternatives section explains why the UML and Cockburn vocabularies and an expose→provides rename were considered and rejected.

Tests. No behavior changes. The composition, authored-graph, resource-slot, and application-topology tests now destructure deps; in core, the lone-service error test's title was updated to stop calling a dependency "the input" (module.test.ts:287), matching the unwired dependency wording the LoadError itself emits.

@coderabbitai

coderabbitai Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

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: e644ed86-cf55-4948-816a-ede467a04d9f

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • 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 29, 2026 •

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@prisma/composer@398
npm i https://pkg.pr.new/@prisma/composer-cli@398
npm i https://pkg.pr.new/@prisma/composer-prisma-cloud@398

commit: 885170a

@prisma-gizmo prisma-gizmo Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New findings: 🟡 2 minor · trace

Comment thread packages/0-framework/1-core/core/src/load-module.ts
Comment thread skills/prisma-composer-core-concepts/SKILL.md
wmadden-electric and others added 2 commits October 29, 2026 13:47
…interface

The error texts still called a declared dependency an input and an exposed
interface an output, and the skill still said ports.

Co-Authored-By: Claude Fable 5.1 <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 Fable 5.1 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>

@prisma-gizmo prisma-gizmo Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New findings: 🟡 1 minor · trace

Comment thread packages/0-framework/1-core/core/src/__tests__/module.test.ts Outdated
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Signed-off-by: willbot <w.a.madden+machine@gmail.com>
Signed-off-by: Will Madden <madden@prisma.io>

@prisma-gizmo prisma-gizmo Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New findings: none · trace

@prisma-gizmo prisma-gizmo Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No Gizmo finding is open and the head commit has been reviewed. Approving.

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.

1 participant