MotirBuilding in public
MOTIR · moooon
onMotir
You’re viewing a public project. Anyone can view it — no account needed. Sign in to submit, upvote, or comment on requests.View-only — you can’t edit work items
MOTIR-71

2.1.2 Service-layer type-parent validation

Done
Description

Estimate: 15m · Depends on: 2.1.1

Add an issuesService (and a thin workItemRepository if Story 1.4 didn't already ship one) enforcing the type-parent rules at the application layer before any write, so the API returns a clean typed error rather than relying on the DB constraint to reject with a raw Postgres error. The DB constraint from 1.4 stays as the structural backstop (defense in depth); this layer is the friendly gate.

Why both layers: the 1.4 DB constraint guarantees integrity even against direct writes, but a 500 from a constraint violation is a poor API contract. The service validates first and throws InvalidParentTypeError (→ 422) with a message naming the offending pair. Same pattern as the workspace invite errors from 1.2.5.

Acceptance criteria

  • issuesService.assertValidParent(parentType, childType) throws a typed InvalidParentTypeError (code INVALID_PARENT_TYPE) on illegal pairs.
  • The create/move paths (built in 2.1.3 and later Stories) call it before writing.
  • Depth rule honored: a subtask/bug at the leaf cannot parent anything (delegates to canParent from 2.1.1).
  • Vitest (real Postgres) proving the service rejects an illegal pair AND that the DB constraint still rejects a direct illegal write (both layers verified).

Context refs

  • lib/issues/issueTypes.ts from 2.1.1
  • lib/services/* + lib/repositories/* patterns + lib/workspaces/errors.ts (typed-error precedent from 1.2.5)
  • Story 1.4's DB constraint definition