mAi
a4e2f3526d
feat(checklists): t-paliad-225 Slice A backend — user-authored templates
m/paliad#61 Slice A. Introduces paliad.checklists (mig 114) as the
DB-backed companion to the static Go catalog. ChecklistCatalogService
unifies both sources at read time; ChecklistTemplateService handles
authoring CRUD + visibility toggle (private↔firm; Slice B opens
'shared' and 'global').
Schema (mig 114, idempotent):
- paliad.checklists (uuid, slug UNIQUE, owner_id FK, title/description
/regime/court/reference/deadline/lang, body jsonb, visibility CHECK
('private','shared','firm','global'), promoted_at/_by, timestamps)
- paliad.can_see_checklist(uuid, uuid) STABLE SECURITY DEFINER —
owner OR firm/global. Slice B extends with the explicit-share branch.
- RLS: select via can_see_checklist; insert owner=self; update/delete
owner OR global_admin
- ALTER paliad.checklist_instances ADD COLUMN template_snapshot jsonb
(snapshot semantics so per-Akte instances stay decoupled from
subsequent template edits)
Services:
- ChecklistCatalogService — ListVisible, Find, SnapshotBody, IsStaticSlug.
Reapplies visibility application-side (service-role bypasses RLS, per
visibility.go pattern). Static-slug map computed once at boot for
collision detection.
- ChecklistTemplateService — Create (auto-generates u-<slug>-<hex> with
retry), Update (changed_fields[] in audit), SetVisibility, Delete,
ListOwnedBy, GetBySlug. Owner-or-global_admin gate.
- SystemAuditLogService.WriteChecklistEvent — thin helper writing into
paliad.system_audit_log with scope='org'.
- ChecklistInstanceService.Create now captures template_snapshot via
the catalog; GetByID returns it inline so the frontend can render
the captured body even after the upstream template is mutated.
Endpoints (all owner-gated where mutating):
- GET /api/checklists — merged catalog (static + DB visible)
- GET /api/checklists/{slug} — single template; static-first lookup
- GET /api/checklists/templates/mine — caller's authored templates
- POST /api/checklists/templates — create
- PATCH /api/checklists/templates/{slug} — edit
- PATCH /api/checklists/templates/{slug}/visibility — private↔firm
- DELETE /api/checklists/templates/{slug} — delete
- GET /checklists/new, /checklists/{slug}/edit — author wizard pages
Tests: pure-helper unit tests cover slugifyTitle (umlaut → ae/oe/ue/ss
normalisation + clamp), regime/lang/visibility validation, body-shape
enforcement, static-slug detection, predicate shape, clamp.
2026-05-20 15:24:06 +02:00
..
2026-05-06 16:05:00 +02:00
2026-05-15 03:03:34 +02:00
2026-05-15 03:03:34 +02:00
2026-05-20 13:05:27 +02:00
2026-05-20 14:46:36 +02:00
2026-05-20 14:46:36 +02:00
2026-05-20 13:05:59 +02:00
2026-04-30 16:46:31 +02:00
2026-05-19 12:51:52 +02:00
2026-05-20 13:05:27 +02:00
2026-05-07 20:58:57 +02:00
2026-05-07 20:58:57 +02:00
2026-05-07 20:58:57 +02:00
2026-05-20 13:26:23 +02:00
2026-04-17 11:59:49 +02:00
2026-05-13 00:11:14 +02:00
2026-05-13 00:11:14 +02:00
2026-05-20 13:26:23 +02:00
2026-04-30 16:46:31 +02:00
2026-05-07 22:41:18 +02:00
2026-05-07 22:41:18 +02:00
2026-05-20 15:24:06 +02:00
2026-05-20 15:24:06 +02:00
2026-05-20 15:24:06 +02:00
2026-05-20 15:24:06 +02:00
2026-05-06 12:47:12 +02:00
2026-05-20 13:55:56 +02:00
2026-05-20 13:55:56 +02:00
2026-05-20 13:55:56 +02:00
2026-05-20 13:55:56 +02:00
2026-05-20 13:55:56 +02:00
2026-05-20 13:55:56 +02:00
2026-05-04 12:03:56 +02:00
2026-05-18 15:06:04 +02:00
2026-05-18 15:06:04 +02:00
2026-05-15 17:53:44 +02:00
2026-05-18 15:06:04 +02:00
2026-05-18 17:29:14 +02:00
2026-05-18 17:29:14 +02:00
2026-04-30 16:46:31 +02:00
2026-05-08 20:04:10 +02:00
2026-05-06 17:16:17 +02:00
2026-05-07 21:50:31 +02:00
2026-05-19 13:05:54 +02:00
2026-05-20 15:19:48 +02:00
2026-04-29 22:09:39 +02:00
2026-05-20 15:19:48 +02:00
2026-05-20 15:19:48 +02:00
2026-05-05 13:29:47 +02:00
2026-05-18 12:13:24 +02:00
2026-05-16 01:17:23 +02:00
2026-05-16 01:17:23 +02:00
2026-05-04 19:49:37 +02:00
2026-05-20 14:43:42 +02:00
2026-05-15 01:09:31 +02:00
2026-05-18 15:06:04 +02:00
2026-04-30 16:46:31 +02:00
2026-05-20 13:03:57 +02:00
2026-05-20 13:03:57 +02:00
2026-05-20 13:03:57 +02:00
2026-05-07 12:51:37 +02:00
2026-05-20 10:02:36 +02:00
2026-05-18 15:06:04 +02:00
2026-05-20 14:53:22 +02:00
2026-05-06 12:47:12 +02:00
2026-05-06 12:47:12 +02:00
2026-04-20 12:34:38 +02:00
2026-04-29 22:09:39 +02:00
2026-05-07 22:41:18 +02:00
2026-05-07 22:41:18 +02:00
2026-04-30 03:18:03 +02:00
2026-05-20 15:19:48 +02:00
2026-05-07 20:58:57 +02:00
2026-05-07 20:58:57 +02:00
2026-05-03 18:39:06 +02:00
2026-05-15 03:03:12 +02:00
2026-05-08 12:42:57 +02:00
2026-05-08 21:48:08 +02:00
2026-05-08 21:48:08 +02:00
2026-05-08 21:48:08 +02:00
2026-05-06 16:41:41 +02:00
2026-04-30 16:46:31 +02:00
2026-05-07 22:29:39 +02:00
2026-05-07 22:21:45 +02:00
2026-05-18 12:13:24 +02:00
2026-05-20 14:53:22 +02:00
2026-05-20 14:53:22 +02:00
2026-05-20 14:55:55 +02:00
2026-05-20 14:55:55 +02:00
2026-05-07 22:58:44 +02:00
2026-05-04 19:30:37 +02:00
2026-05-18 12:13:24 +02:00
2026-05-20 14:55:55 +02:00
2026-05-18 15:06:04 +02:00
2026-05-18 12:13:24 +02:00
2026-05-09 18:52:01 +02:00
2026-05-18 15:06:04 +02:00
2026-05-20 14:55:55 +02:00
2026-05-18 15:06:04 +02:00
2026-04-30 16:46:31 +02:00
2026-05-07 21:50:31 +02:00
2026-05-15 00:06:37 +02:00
2026-05-15 00:06:37 +02:00
2026-05-15 02:09:10 +02:00
2026-05-18 15:06:04 +02:00
2026-05-18 15:06:04 +02:00
2026-05-18 16:52:38 +02:00
2026-05-20 14:55:55 +02:00
2026-05-19 13:42:51 +02:00
2026-05-19 13:42:51 +02:00
2026-05-20 14:55:55 +02:00
2026-05-20 15:19:48 +02:00
2026-05-20 15:19:48 +02:00
2026-05-20 15:24:06 +02:00
2026-05-07 12:51:37 +02:00
2026-05-08 22:11:19 +02:00
2026-05-20 13:05:27 +02:00
2026-05-20 14:46:36 +02:00
2026-04-30 16:46:31 +02:00
2026-05-20 15:19:48 +02:00
2026-05-07 12:51:37 +02:00
2026-05-07 12:51:37 +02:00
2026-05-20 10:02:36 +02:00
2026-05-04 12:03:56 +02:00
2026-05-04 18:57:06 +02:00
2026-05-20 13:55:56 +02:00