Context
The constitution says a law outranks an ADR and that changing a law takes an ADR that updates the law page in the same commit (constitution, “Amending a law”). Since the laws were written, Accepted ADRs and locked owner decisions changed what several laws describe, and the pages were not updated. The gap questionnaire of 2026-10-19 lists the conflicts (B5, B7, B9, B19, B21). As written, the laws would make those Accepted ADRs “wrong”. This ADR records the amendments. Each follows from an existing Accepted ADR or a locked owner decision; nothing new is decided.Decision
The law pages change as follows, each with a History entry pointing here.- Boundaries. Shared packages expose decorators, base classes and typed config contracts, not
define*()factories (0094); the principle is renamed “shared packages hold mechanisms, apps hold definitions”. Cross-service types live in a package’s./contractsentry or in@stackra/contracts, not in separate contract packages (0117, which superseded 0015). - HTTP and events.
- Every operation is one action exposed by an adapter; gen emits the
api()(0098, 0091). - Boundary validation is
@stackra/validationcompiled to Zod, not Encore’sMin/MaxLen(0095). - Domain events stay in-process; integration events are named
<aggregate>.<verb>.v<n>(user.created.v1, 0078). Whether a service prefix is added stays open (gap C27). - A subscriber declares
@OnEventand imports only the producer’s./contracts; it never imports another service’sTopic(0078, 0091). - The envelope’s
actoris the 0098 actor model with itsonBehalfOfchain;PublicIdand the prefix registry live in@stackra/contracts(0117).
- Every operation is one action exposed by an adapter; gen emits the
- Tenancy and security. The ltree scope tree leaves the base law and becomes a section that binds only when the Pro
scope driver (
@stackra-pro/scope) is installed; free@stackra/iamresolves RBAC with no scope dependency (0088 decisions 5 and 2, owner decisions S2, S3 and S12, locked 2026-10-19). The effective-permission formula marks its scope step as Pro. - Security SEC3. The audit record is written by the action pipeline’s audit step and carries the full
Actorchain, so an agent action names the agent and the human it acted for (0098 decisions 3, 6 and 7). - Delegation D4. The lead pushes, opens pull requests and merges only through the merge gate; the owner merges the
version pull request and promotes to production (0119). The brief names
specs as
.agents/specs/sta-<n>-<slug>(0120). The preamble already follows 0121 D10. - Index. The dependency-direction principle follows 0003:
config→lib→appandservice, with apps and services as peers. - Rules and standards that restate these laws follow them:
.agents/rules/tenancy.md,standards/packages,standards/i18n-rtl. The.specifyconstitution is regenerated bypnpm agents:sync.
- B20: whether
defineToken(0005 decision 2) is carved out of 0094 or renamedcreateToken. - SEC1 and the HTTP auth flag against Proposed 0093
(
auth: none|optional|required), and the public-id examples against Proposed 0082 (DA9): both wait for those ADRs (OR1). - SEC3 versus Proposed 0046 (audit as a per-model opt-in) beyond the pipeline wording above.
Consequences
- The laws no longer contradict Accepted ADRs on authoring style, events, validation, tenancy, audit or delegation.
- The constitution now names Pro packages, so a free-only product reads the scope sections as not applying to it.
- Agents that read
.specify/memory/constitution.mdget the amended text after the sync.
Enforcement
pnpm agents:check (in pnpm validate) fails when the generated .specify constitution drifts from the law pages. The
laws’ own Enforcement lines are unchanged; their checks stay planned where they were.