Pastura API — Sentinel (root)
GS cascade for the Pastura benchmark. This root is the sentinel: read it first, then descend only the node relevant to the current task. The tree is lossless — the leaves together specify the whole system. Stay within your read budget; do not load all nodes.
Architectural identity
Pastura is a single-tenant REST API for rotational grazing management. It protects rangeland by refusing herd moves that violate three rules and by computing grazing budgets. The system of record is PostgreSQL. The API is stateless per request; all state is in the DB.
Scope boundary: paddocks, herds, forage readings, moves, and the three grazing rules. Out of scope: multi-ranch tenancy, billing, weather, GIS/mapping, notifications.
Architecture (layered — MUST hold)
routes/ HTTP only: parse, authorize, call a service, format the response. NO data-client calls here.
services/ business logic: the three rules (R1/R2/R3) and the computed reads live here.
repositories/ the ONLY layer that touches the data client (Prisma/Knex/pg). One repo per entity.
domain/ types + the rule/compute pure functions (capacity, budget, rest window).
Dependency rule (Defended): routes → services → repositories → data client. A data-client call (prisma.*, knex(...), raw pg) in a routes/ or controller file is a boundary violation and MUST NOT occur. The compute functions in domain/ are pure (no I/O) so they are unit-testable in isolation.
Standards
- TypeScript strict. JWT: secret from
JWT_SECRET(≥32 chars), expiry as a duration string"24h"(never a bare number). Postgres reached via127.0.0.1(notlocalhost). - Error contract is normative — see
contracts.md. Every error body is{error:{code,message}}. - Naming: entities singular (
Paddock), repos<Entity>Repository, services<Area>Service.
Constraints & prohibitions (Defended)
- MUST NOT allow a move that violates R1, R2, or R3 (see
use-cases.md) — the rule check is in the service and MUST run before persisting. - MUST NOT expose
passwordHash. MUST NOT let ahandmutate Paddocks/Herds/RestRules (403). - MUST NOT put SQL or data-client calls outside
repositories/.
Routing (descend only what you need)
| Node | Read when you are… | |—|—| | contracts.md | defining endpoints, request/response shapes, or the error contract | | use-cases.md | implementing a rule (R1/R2/R3) or a computed read — has acceptance criteria | | nfrs.md | wiring auth, DB, config, or performance concerns | | test-architecture.md | writing tests or setting the quality gate |
Tool sequencing
- Read this root, then
contracts.mdfor the surface. - For any move endpoint, read
use-cases.md— the rules are acceptance criteria, not prose. - Implement domain compute functions first (pure), unit-test them, then the service, then the route. Tests are authored with the code (phase collapse), gated per
test-architecture.md.