CRUD Completion — All Operationally Relevant Resources
On this page
Context
CRAIG has several operationally relevant resources that lack full CRUD API coverage. Some (NIST controls, rate tables) are seed-only with no create endpoint. Others are missing get-by-ID, update, or delete operations. Agencies need complete API control over all configurable data — seed scripts should only be used for test/demo data, not operational configuration.
This plan adds 31 new endpoints across 5 services, organized as 5 independent MRs (one per service). Each MR includes store functions, API handlers, route registration, OpenAPI annotations, test-lib client methods, integration tests, and CLI commands.
Design Decisions
-
Hard delete for tables without an
activecolumn; soft-delete (active=false) forexchange_partnerswhich has one -
FK constraint violations on delete → 409 Conflict (let PostgreSQL enforce, catch in handler)
-
Delete of stateful records: only allowed in safe states (e.g., only
pendingadjustments, onlydraftagreements) -
RBAC: matches sibling endpoints on the same resource (admin for config data, caseworker_or_above for case/placement data)
-
POST returns 200, DELETE returns 204, per project conventions
MR 1: craig-security (5 endpoints + UUID v7 migration)
craig-security’s 5 original tables (audit_log, security_reviews, archive_records, nist_controls, review_evidence) still use gen_random_uuid() (v4).
All other services were migrated via 20260305100000_uuid_v7_defaults.sql.
This MR includes a migration (20260310100000_uuid_v7_defaults.sql) to fix this.
|
Branch: feature/crud-gaps-security
| Endpoint | Method | RBAC |
|---|---|---|
|
POST |
admin |
|
GET |
admin |
|
DELETE |
admin |
|
GET |
admin |
|
DELETE |
admin |
Files
| File | Changes |
|---|---|
|
Add |
|
Add |
|
Add |
|
Add 5 client methods |
|
Add: create, create-duplicate-409, get, get-404, delete, delete-404 |
|
Add: get-review, get-404, delete-review, delete-with-evidence-409 |
|
Add |
|
Add |
|
Add create/get/delete tests; rewrite update to use CLI-created control |
|
Add get/delete review tests |
MR 2: craig-exchange (4 endpoints)
Branch: feature/crud-gaps-exchange
| Endpoint | Method | RBAC |
|---|---|---|
|
GET |
admin |
|
DELETE |
admin (soft-delete) |
|
GET |
admin |
|
DELETE |
admin (draft only) |
Files
| File | Changes |
|---|---|
|
Add |
|
Add |
|
Add |
|
Update route registration |
|
Add 4 client methods |
|
Add get/delete tests for partners + agreements |
|
Add |
|
Add |
Notes
-
Partner delete = soft-delete via existing
update_partner(active=Some(false));get_partnerstore fn already exists -
Agreement delete only works on
draftstatus;get_agreementstore fn already exists -
Agreement FK (
partner_id → exchange_partners) uses RESTRICT, so soft-delete on partners is the right approach
MR 3: craig-financial (6 endpoints)
Branch: feature/crud-gaps-financial
| Endpoint | Method | RBAC |
|---|---|---|
|
GET |
eligibility_worker_or_above |
|
PUT |
admin |
|
DELETE |
admin |
|
GET |
eligibility_worker_or_above |
|
GET |
eligibility_worker_or_above |
|
DELETE |
supervisor_or_above (pending only) |
Files
| File | Changes |
|---|---|
|
Add |
|
Add |
|
Add |
|
Add |
|
Add routes + OpenAPI paths/schemas |
|
Add 6 client methods |
|
Add rate get/update/delete tests, adjustment list/get/delete tests |
|
Add |
|
Add |
MR 4: craig-placement (7 endpoints)
Branch: feature/crud-gaps-placement
| Endpoint | Method | RBAC |
|---|---|---|
|
GET |
caseworker_or_above |
|
GET |
caseworker_or_above |
|
PUT |
caseworker_or_above |
|
DELETE |
caseworker_or_above |
|
GET |
caseworker_or_above |
|
PUT |
caseworker_or_above |
|
DELETE |
caseworker_or_above |
Files
| File | Changes |
|---|---|
|
Add |
|
Add |
|
Add |
|
Add |
|
Add routes + OpenAPI |
|
Add 7 client methods |
|
Add training + kinship CRUD tests |
|
Add |
|
Add |
MR 5: craig-cases (9 endpoints)
Branch: feature/crud-gaps-cases
| Endpoint | Method | RBAC |
|---|---|---|
|
GET |
caseworker_or_above |
|
PUT |
caseworker_or_above |
|
DELETE |
caseworker_or_above |
|
GET |
caseworker_or_above |
|
PUT |
caseworker_or_above |
|
DELETE |
caseworker_or_above |
|
GET |
caseworker_or_above |
|
GET |
caseworker_or_above |
|
DELETE |
caseworker_or_above |
Files
| File | Changes |
|---|---|
|
Add |
|
Add |
|
Add |
|
Add |
|
Add |
|
3 handlers (list_tasks, get_task, delete_task) |
|
Add routes + OpenAPI |
|
Add 9 client methods |
|
Add contact/court_order/task CRUD tests |
|
Add contact/court-order get/update/delete subcommands |
|
Add task list/get/delete subcommands |
Notes
-
Delete contact must also clean up
contact_attachmentsfrom object store (follow pattern incontact_attachments::delete_attachment) -
Delete court order must clean up document from object store if
object_keyis set -
Individual resource routes (GET/PUT/DELETE) use flat paths (
/contacts/{id}) not nested (/cases/{case_id}/contacts/{id}) -
get_contact,get_court_order,get_taskstore functions already exist
Status
All 5 MRs completed and merged:
-
✅ MR 1: craig-security — MR !4 merged. 5 endpoints + UUID v7 migration.
-
✅ MR 2: craig-exchange — MR !6 merged. 4 endpoints (partner/agreement get/delete).
-
✅ MR 3: craig-financial — MR !7 merged. 6 endpoints (rate CRUD + adjustment list/get/delete).
-
✅ MR 4: craig-placement — MR !8 merged. 7 endpoints (training + kinship CRUD).
-
✅ MR 5: craig-cases — MR !9 merged. 9 endpoints (contact/court-order/task CRUD).
Total: 31 new endpoints, 790 tests passing.
Implementation Order
-
Save this plan as
docs/modules/ROOT/pages/plans/crud-completion.adocand add nav entry. No code changes until committed. -
MR 1: craig-security — smallest, admin-only, no object store. Good warmup.
-
MR 2: craig-exchange — small, store functions mostly exist already.
-
MR 3: craig-financial — medium, new paginated list + query types.
-
MR 4: craig-placement — medium, two sub-resources.
-
MR 5: craig-cases — largest, most complex (object store cleanup on delete).
Documentation
After each MR merges, update:
-
.claude/docs/services.md— Add new endpoints to service endpoint tables -
docs/modules/ROOT/pages/implementation-guide.adoc— Update endpoint and test counts -
.claude/CLAUDE.md— Update phase status endpoint counts -
This plan file — Mark completed MRs
GitLab
-
Epic: "CRUD Completion — All Operationally Relevant Resources" (labels:
feat,P2-medium) -
Issue 1:
feat: Add NIST + review CRUD endpoints to craig-security(weight: 3) -
Issue 2:
feat: Add partner + agreement get/delete endpoints to craig-exchange(weight: 2) -
Issue 3:
feat: Add rate + adjustment CRUD endpoints to craig-financial(weight: 3) -
Issue 4:
feat: Add training + kinship CRUD endpoints to craig-placement(weight: 3) -
Issue 5:
feat: Add contact, court-order, task CRUD endpoints to craig-cases(weight: 5)
Verification (per MR)
-
cargo fmt --check --all && cargo clippy --workspace --locked — -D warnings -
cargo nextest run --workspace --lib(unit tests) -
cargo xtask dev restart(MR 1 has schema change) orcargo xtask dev reload(MRs 2-5) -
cargo nextest run --workspace(all integration tests) -
Swagger UI — verify new endpoints appear with correct schemas
-
CLI smoke test — exercise new create/get/delete commands