Task: Enforce contract-enum-only imports in recipe-app via a @recipe/contract/enums subpath and ESLint #25

Open
opened 2026-10-02 17:19:07 +00:00 by araemer · 0 comments
Owner

recipe-app may import contract enums directly into models and components (recipe-app/docs/adr/2026-09-20-contract-enums-in-models.md), but never DTO interfaces. Today that rule lives in recipe-app/CLAUDE.md as a list of enum names, which goes stale with every new contract enum. Spec 001 replaces the list with a rule by kind. This issue makes a tool enforce the rule instead of prose.

Proposal

Contract (cross-cutting):

  • Add api-contract/src/enums.ts, which re-exports only the as const enums (values and derived types).
  • Add a ./enums entry to the package's exports map, for both the source and the dist/ build.
  • Write a cross-cutting ADR covering the subpath and the rule that each new contract enum is also re-exported from enums.ts.
  • The root export stays unchanged, so nothing breaks in either sibling.
  • Consider a small contract test that compares the root's enum exports with enums.ts, so a forgotten re-export is caught on the contract side.

recipe-app:

  • Add an ESLint no-restricted-imports rule: no imports from @recipe/contract in src/models/, src/components/ (and probably pages and contexts), while @recipe/contract/enums is allowed.
  • Move the existing enum imports in those folders to the subpath.
  • Write an app ADR that supersedes the rule-by-kind ADR from spec 001.
  • Replace the rule in CLAUDE.md with a pointer to the lint rule.

recipe-backend: no change.

Effect

A DTO leaking past the resource layer becomes a lint error, and nobody maintains a list of names.

recipe-app may import contract enums directly into models and components (`recipe-app/docs/adr/2026-09-20-contract-enums-in-models.md`), but never DTO interfaces. Today that rule lives in `recipe-app/CLAUDE.md` as a list of enum names, which goes stale with every new contract enum. Spec 001 replaces the list with a rule by kind. This issue makes a tool enforce the rule instead of prose. ## Proposal **Contract (cross-cutting):** - Add `api-contract/src/enums.ts`, which re-exports only the `as const` enums (values and derived types). - Add a `./enums` entry to the package's `exports` map, for both the source and the `dist/` build. - Write a cross-cutting ADR covering the subpath and the rule that each new contract enum is also re-exported from `enums.ts`. - The root export stays unchanged, so nothing breaks in either sibling. - Consider a small contract test that compares the root's enum exports with `enums.ts`, so a forgotten re-export is caught on the contract side. **recipe-app:** - Add an ESLint `no-restricted-imports` rule: no imports from `@recipe/contract` in `src/models/`, `src/components/` (and probably pages and contexts), while `@recipe/contract/enums` is allowed. - Move the existing enum imports in those folders to the subpath. - Write an app ADR that supersedes the rule-by-kind ADR from spec 001. - Replace the rule in `CLAUDE.md` with a pointer to the lint rule. **recipe-backend:** no change. ## Effect A DTO leaking past the resource layer becomes a lint error, and nobody maintains a list of names.
araemer changed title from Enforce contract-enum-only imports in recipe-app via a @recipe/contract/enums subpath and ESLint to Task: Enforce contract-enum-only imports in recipe-app via a @recipe/contract/enums subpath and ESLint 2026-10-02 20:08:39 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
araemer/recipe-platform#25
No description provided.