Skip to main content

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.
  1. 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 ./contracts entry or in @stackra/contracts, not in separate contract packages (0117, which superseded 0015).
  2. HTTP and events.
    • Every operation is one action exposed by an adapter; gen emits the api() (0098, 0091).
    • Boundary validation is @stackra/validation compiled to Zod, not Encore’s Min/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 @OnEvent and imports only the producer’s ./contracts; it never imports another service’s Topic (0078, 0091).
    • The envelope’s actor is the 0098 actor model with its onBehalfOf chain; PublicId and the prefix registry live in @stackra/contracts (0117).
  3. 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/iam resolves 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.
  4. Security SEC3. The audit record is written by the action pipeline’s audit step and carries the full Actor chain, so an agent action names the agent and the human it acted for (0098 decisions 3, 6 and 7).
  5. 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.
  6. Index. The dependency-direction principle follows 0003: config → lib → app and service, with apps and services as peers.
  7. Rules and standards that restate these laws follow them: .agents/rules/tenancy.md, standards/packages, standards/i18n-rtl. The .specify constitution is regenerated by pnpm agents:sync.
Not amended here, because each needs an owner choice:
  • B20: whether defineToken (0005 decision 2) is carved out of 0094 or renamed createToken.
  • 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.md get 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.

Supersedes and sources

Supersedes: the previous text of the amended law sections (boundaries, HTTP and events, tenancy, security SEC3 and the effective-permission formula, delegation D4 and the brief template, the index principles). Sources: gap questionnaire 2026-10-19 (B5, B7, B9, B19, B21); owner decisions in chat, 2026-10-19 (S2, S3, S12, AI3b).