home / skills / velcrafting / codex-skills / domain-logic-module

domain-logic-module skill

/skills/backend/domain-logic-module

This skill helps you extract and standardize domain logic into testable modules with explicit invariants and deterministic errors.

npx playbooks add skill velcrafting/codex-skills --skill domain-logic-module

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.5 KB
---
name: domain-logic-module
description: Add or refactor domain rules into a testable module boundary with explicit invariants.
metadata:
  short-description: Domain rules + invariants + tests
  layer: backend
  mode: write
  idempotent: false
---

# Skill: backend/domain-logic-module

## Purpose
Create or refactor domain logic so that business rules live in:
- a testable module boundary
- with explicit invariants
- and deterministic error behavior

This skill prevents domain rules from leaking into controllers, jobs, or adapters.

---

## Inputs
- Domain concept to implement or change (1–3 sentences)
- Invariants that must always hold (must/must-not list)
- Entry points that will call this module:
  - endpoint handler / job / integration adapter
- Repo profile (preferred): `<repo>/REPO_PROFILE.json`

---

## Outputs
- Domain module(s) with:
  - clear inputs/outputs
  - explicit invariants
  - deterministic error returns
- Unit tests that cover:
  - happy path
  - invariant violations
  - at least one edge case

---

## Non-goals
- Wiring endpoints (use `backend/endpoint-scaffold`)
- Schema/migrations (use `backend/persistence-layer-change`)
- External API IO concerns (use `backend/integration-adapter`)
- UI logic

---

## Workflow
1) Locate the correct domain boundary (existing module/folder pattern wins).
2) Define the public API of the module:
   - function(s) or class with explicit types
3) Encode invariants explicitly:
   - validate preconditions
   - validate postconditions where meaningful
4) Define error behavior:
   - typed error codes (align with `shared/error-taxonomy` if present)
   - avoid throwing raw exceptions across boundaries unless repo standard
5) Write unit tests focused on rules, not wiring.
6) Ensure callers orchestrate and do not re-implement rules.
7) Run required validations from profile.

---

## Checks
- Invariants are explicit and enforced
- Errors are deterministic and mapped cleanly
- Callers become thinner after extraction
- Unit tests cover:
  - happy path
  - at least 2 invariant failures
  - edge case
- Typecheck/lint pass if configured

---

## Failure modes
- Invariants unclear or contested → recommend `$decision-capture` before encoding.
- Rule sprawl across multiple modules → propose consolidation (but do not refactor widely).
- Tests hard to write due to coupling → extract dependencies and inject interfaces.

---

## Telemetry
Log:
- skill: `backend/domain-logic-module`
- domain_area: `<short label>`
- invariants_added_or_changed: count
- tests_added: count
- files_touched
- outcome: `success | partial | blocked`

Overview

This skill extracts or adds domain rules into a focused, testable module so business invariants live at a clear boundary. It produces modules with explicit inputs/outputs, deterministic error behavior, and accompanying unit tests. The goal is to keep controllers, jobs, and adapters thin and free of core business logic.

How this skill works

I locate the appropriate domain boundary in your codebase and define a public API (functions or classes) with explicit types. Invariants are encoded as preconditions and, where meaningful, postconditions; errors are returned as typed, deterministic results aligned to any shared error taxonomy. I then add unit tests that exercise the happy path, invariant violations, and at least one edge case.

When to use it

  • When business rules are sprinkled across controllers, jobs, or adapters
  • When invariants are unclear or inconsistently enforced
  • When you need deterministic error behavior for orchestration
  • When tests fail to cover core domain rules or are hard to write
  • When preparing logic for reuse by multiple callers

Best practices

  • Pick an existing domain folder pattern, do not invent wide-reaching structure
  • Design a minimal public API with clear input/output types and return-value errors
  • Validate preconditions early and enforce postconditions where useful
  • Use typed error codes instead of throwing raw exceptions across boundaries
  • Write focused unit tests that prove rules, not wiring; mock dependencies via interfaces

Example use cases

  • Encapsulate pricing or discount rules so payments and checkout call a single deterministic module
  • Refactor eligibility checks currently duplicated in endpoints and background jobs
  • Create a domain module that enforces quotas and returns explicit error codes for callers to act on
  • Add invariants for state transitions (e.g., order -> shipped) with tests for illegal transitions
  • Extract validation-heavy creation logic so integration adapters can rely on a single source of truth

FAQ

What if the invariants are contested by stakeholders?

Capture the decision using a lightweight decision record before encoding rules; avoid hard-coding disputed invariants.

Should I throw exceptions or return error values?

Prefer deterministic, typed error returns aligned with any shared taxonomy; only follow codebase conventions if exceptions are the standard boundary behavior.