Skip to content

API — Allocation rules

Purpose

Configuration of the allocation rules engine: rule sets, the rules within them, their scopes, and the rule-type catalog. This is the engine's configuration surface; running the engine is on Rosters & allocation runs.

Auth & roles

Base /api/allocation/rules · class [Authorize]. Reads gate on allocation_rule.read; all writes gate on allocation_rule.write — SYS_ADMIN + HR_ADMIN only (a PLANNER can run the engine but cannot edit rule sets; see the RBAC matrix).

Endpoints

Rule sets

Method Path Purpose Gate
GET / POST /api/allocation/rules/sets List / create rule sets read / write
GET / PUT / DELETE /api/allocation/rules/sets/{id} Read / update / delete a set read / write
PATCH /api/allocation/rules/sets/{id}/reorder Reorder rules in a set write
POST /api/allocation/rules/sets/{id}/rules Add a rule to a set write
POST /api/allocation/rules/sets/{id}/set-default Mark the set default write

Rules & scopes

Method Path Purpose Gate
PUT / DELETE /api/allocation/rules/{id} Update / delete a rule write
GET / POST /api/allocation/rules/{ruleId}/scope Read / add a rule scope read / write
DELETE /api/allocation/rules/scope/{scopeId} Remove a scope write

Rule-type catalog

Method Path Purpose Gate
GET / POST /api/allocation/rules/types List / add rule types read / write

Shapes & errors

A rule set bundles rules of catalog types (7 hard + 7 soft — all LIVE, sheet 07); rules carry scopes that narrow where they apply. The catalog's handler_class_name is display-only — dispatch is by RuleTypeCode, not the catalog string. Standard ProblemDetails; deleting the last critical hard rule of its type is blocked (400 CRITICAL_HARD_RULE_REQUIRED — see Coexistence pattern).

Gotchas

  • allocation_rule.write is SYS_ADMIN + HR_ADMIN only — the single most common RBAC mis-assumption. PLANNER runs, doesn't edit.
  • All 14 rules are live — the engine is not stubbed (reverses an old handover claim, sheet 00-index headline #1). Only the test-only NoOpAllocationRule is a stub.
  • Catalog handler_class_name is cosmetic — don't rely on it for behaviour.
  • Critical hard rules are protected — you can't delete the last one of a type.