Implements docs/design-kanzlai-integration.md §8 Phase A. Schema (paliad.*): - users (extends auth.users) with office, practice_group, role - akten with visibility columns: owning_office, collaborators uuid[], firm_wide_visible (per design §2) - parteien, fristen, termine, dokumente, akten_events, notizen (polymorphic notes; notizen_exactly_one_parent CHECK) - proceeding_types, deadline_rules, holidays (reference data) - 4 feedback tables re-namespaced from public.* into paliad.* (handler swap to direct DB is a follow-up; old public tables stay intact for now and continue serving via PostgREST) Visibility (paliad.can_see_akte): - single SQL function, used by every RLS policy - predicate: firm_wide_visible OR owning_office matches user's office OR auth.uid() ∈ collaborators OR user is admin - mirrored at app layer in Phase B (defense in depth) RLS (real, not permissive): - akten: visibility predicate; insert restricted to own office or admin; delete restricted to partners + admins - parteien/fristen/dokumente/akten_events: inherit via can_see_akte(akte_id) - termine: personal (akte_id NULL) visible only to creator; Akte-linked follow visibility predicate - notizen: paliad.notiz_is_visible() resolves polymorphic parent - reference tables: SELECT for any authenticated user - users: SELECT all; UPDATE/INSERT only self - feedback tables: INSERT for any authenticated user (write-only) Seed data (ported from KanzlAI seed_upc_timeline.sql): - 7 proceeding_types (INF, REV, CCR, APM, APP, AMD, ZPO_CIVIL) - 40 deadline_rules (32 UPC + 4 ZPO + 4 cross-type appeal spawns) including conditional logic: Reply rule code (RoP.029b → 029a) and Rejoinder duration (1mo → 2mo) flip when CCR active - 55 holidays (DE federal 2026/2027 + UPC summer 2026 + UPC winter 26/27) Indexes per audit §3.3 + visibility-predicate hot paths: - akten: (status, owning_office), (owning_office), partial on firm_wide_visible, GIN on collaborators - fristen: (status, due_date), (akte_id) - termine: (start_at), (akte_id) - akten_events: (akte_id, created_at DESC) - notizen: 4 partial indexes per parent type - users: (office), (role) Migration tooling: - golang-migrate/migrate/v4 with embed.FS source - Migrations live in internal/db/migrations/ (Go embed can't reach outside the package; this is the conventional Go layout for embedded migrations) - Applied at server startup before HTTP listener binds - DATABASE_URL is optional today (existing knowledge tools work without DB); becomes required once Phase B services land - Mock Supabase auth schema for local testing in internal/db/migrations/_dev/mock_supabase_auth.sql (excluded from embed pattern by the underscore prefix) Other changes: - Dockerfile: bump golang to 1.24, copy go.sum (audit §2.9), rename binary patholo → paliad - docker-compose.yml: add DATABASE_URL passthrough - README.md: rewritten to reflect Paliad brand + Phase A migration system Verified locally: - 11 migrations applied cleanly against postgres:16-alpine - RLS enabled on all 15 paliad.* tables (verified via pg_class.relrowsecurity) - Visibility predicate verified with 4-case scenario: - Alice (Munich associate): sees Munich + firm-wide + collab-on (t f t t) - Bob (Düsseldorf associate): sees Düsseldorf + firm-wide + collab-on (f t t t) - Carol (Munich partner): sees Munich + firm-wide only (t f t f) - Anonymous: sees firm-wide only (f f t f) - migrate down + re-up cycle clean (initial 007 down had ordering bug, fixed: drop policies before referenced function) - Existing endpoints (/, /login) return 302 + 200 — no regressions
98 lines
5.9 KiB
SQL
98 lines
5.9 KiB
SQL
-- Phase A seed: holidays 2026 + 2027.
|
||
--
|
||
-- German federal public holidays (observed in all 16 Länder).
|
||
-- Easter-relative dates computed manually using Gregorian-algorithm output:
|
||
-- 2026: Easter = 2026-04-05 (Karfreitag 04-03, Ostermontag 04-06,
|
||
-- Christi Himmelfahrt 05-14,
|
||
-- Pfingstsonntag 05-24, Pfingstmontag 05-25)
|
||
-- 2027: Easter = 2027-03-28 (Karfreitag 03-26, Ostermontag 03-29,
|
||
-- Christi Himmelfahrt 05-06,
|
||
-- Pfingstsonntag 05-16, Pfingstmontag 05-17)
|
||
--
|
||
-- UPC judicial vacations (official 2026 periods per UPC Annual Report of work):
|
||
-- Winter: 24 Dec 2026 – 6 Jan 2027 (holiday_type = 'vacation')
|
||
-- Summer: 27 Jul 2026 – 28 Aug 2026 (holiday_type = 'vacation')
|
||
--
|
||
-- For 2027 we seed known-fixed dates + Easter-derived set; summer/winter UPC
|
||
-- vacations are added once the UPC publishes them.
|
||
|
||
-- ============================================================================
|
||
-- German federal — 2026
|
||
-- ============================================================================
|
||
INSERT INTO paliad.holidays (date, name, country, holiday_type) VALUES
|
||
('2026-01-01', 'Neujahr', 'DE', 'public_holiday'),
|
||
('2026-04-03', 'Karfreitag', 'DE', 'public_holiday'),
|
||
('2026-04-05', 'Ostersonntag', 'DE', 'public_holiday'),
|
||
('2026-04-06', 'Ostermontag', 'DE', 'public_holiday'),
|
||
('2026-05-01', 'Tag der Arbeit', 'DE', 'public_holiday'),
|
||
('2026-05-14', 'Christi Himmelfahrt', 'DE', 'public_holiday'),
|
||
('2026-05-24', 'Pfingstsonntag', 'DE', 'public_holiday'),
|
||
('2026-05-25', 'Pfingstmontag', 'DE', 'public_holiday'),
|
||
('2026-10-03', 'Tag der Deutschen Einheit', 'DE', 'public_holiday'),
|
||
('2026-12-25', '1. Weihnachtstag', 'DE', 'public_holiday'),
|
||
('2026-12-26', '2. Weihnachtstag', 'DE', 'public_holiday')
|
||
ON CONFLICT (date, name, country) DO NOTHING;
|
||
|
||
-- ============================================================================
|
||
-- UPC summer vacation 2026 (27 Jul – 28 Aug, weekdays only — weekends are
|
||
-- already non-working days, storing the whole span as vacation entries)
|
||
-- ============================================================================
|
||
INSERT INTO paliad.holidays (date, name, country, holiday_type) VALUES
|
||
('2026-07-27', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-07-28', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-07-29', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-07-30', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-07-31', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-03', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-04', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-05', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-06', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-07', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-10', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-11', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-12', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-13', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-14', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-17', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-18', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-19', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-20', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-21', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-24', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-25', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-26', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-27', 'UPC Summer Vacation', 'UPC', 'vacation'),
|
||
('2026-08-28', 'UPC Summer Vacation', 'UPC', 'vacation')
|
||
ON CONFLICT (date, name, country) DO NOTHING;
|
||
|
||
-- ============================================================================
|
||
-- UPC winter vacation 2026 → 2027 (24 Dec 2026 – 6 Jan 2027, weekdays)
|
||
-- ============================================================================
|
||
INSERT INTO paliad.holidays (date, name, country, holiday_type) VALUES
|
||
('2026-12-24', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2026-12-28', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2026-12-29', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2026-12-30', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2026-12-31', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2027-01-04', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2027-01-05', 'UPC Winter Vacation', 'UPC', 'vacation'),
|
||
('2027-01-06', 'UPC Winter Vacation', 'UPC', 'vacation')
|
||
ON CONFLICT (date, name, country) DO NOTHING;
|
||
|
||
-- ============================================================================
|
||
-- German federal — 2027 (so deadlines falling into early 2027 adjust correctly)
|
||
-- ============================================================================
|
||
INSERT INTO paliad.holidays (date, name, country, holiday_type) VALUES
|
||
('2027-01-01', 'Neujahr', 'DE', 'public_holiday'),
|
||
('2027-03-26', 'Karfreitag', 'DE', 'public_holiday'),
|
||
('2027-03-28', 'Ostersonntag', 'DE', 'public_holiday'),
|
||
('2027-03-29', 'Ostermontag', 'DE', 'public_holiday'),
|
||
('2027-05-01', 'Tag der Arbeit', 'DE', 'public_holiday'),
|
||
('2027-05-06', 'Christi Himmelfahrt', 'DE', 'public_holiday'),
|
||
('2027-05-16', 'Pfingstsonntag', 'DE', 'public_holiday'),
|
||
('2027-05-17', 'Pfingstmontag', 'DE', 'public_holiday'),
|
||
('2027-10-03', 'Tag der Deutschen Einheit', 'DE', 'public_holiday'),
|
||
('2027-12-25', '1. Weihnachtstag', 'DE', 'public_holiday'),
|
||
('2027-12-26', '2. Weihnachtstag', 'DE', 'public_holiday')
|
||
ON CONFLICT (date, name, country) DO NOTHING;
|