fix(schema): harden migrations, FKs, seed, and truncation (PMS-196) #210

Merged
David merged 2 commits from feat/pms-196-harden-migrations-rls-integrity into main 2026-06-13 23:50:53 +02:00
Owner

Most RLS findings were already closed by 038/041 (fail-closed policy, tenant-less table coverage). This change handles the remaining schema-integrity and code-path findings, using new forward migrations rather than editing shipped migrations (sqlx validates the checksum of every applied migration on run, and that path is now fatal).

New migration 042_pms196_fks_and_triggers.sql: re-runs the updated_at trigger sweep idempotently (DROP TRIGGER IF EXISTS + CREATE), which both makes trigger attachment re-runnable and attaches the trigger to post-024 tables that never got one (e.g. kb_article_votes); adds appointment_reminders FKs on tenant_id/appointment_id with ON DELETE CASCADE; adds the four bare companies pointer FKs with ON DELETE SET NULL.

New auth migration 20260516000001_org_invitations_citext.sql: changes org_invitations.email to CITEXT to match admin_invites (so case no longer bypasses the one-open-invite-per-(tenant,email) guard) and adds the octet_length(token_hash)=32 CHECK that admin_invites already carries.

src/main.rs: migration failure now fails fast (.expect) instead of being swallowed as a warning, so the server never starts on a stale schema.

src/modules/tenants/service.rs: copy_default_config no longer parses a hardcoded magic UUID with unwrap(); the seed-source tenant is read from MOKOSH_SEED_TENANT_ID (fallible parse, Configuration error on malformed value) and falls back to Uuid::from_u128(1).

src/utils/validation.rs: truncate() snaps the cut point back to the nearest char boundary via char_indices so multi-byte UTF-8 input no longer panics; adds a regression test.

#PMS-196

Co-Authored-By: Claude Opus 4.8 (1M context) noreply@anthropic.com

Most RLS findings were already closed by 038/041 (fail-closed policy, tenant-less table coverage). This change handles the remaining schema-integrity and code-path findings, using new forward migrations rather than editing shipped migrations (sqlx validates the checksum of every applied migration on run, and that path is now fatal). New migration 042_pms196_fks_and_triggers.sql: re-runs the updated_at trigger sweep idempotently (DROP TRIGGER IF EXISTS + CREATE), which both makes trigger attachment re-runnable and attaches the trigger to post-024 tables that never got one (e.g. kb_article_votes); adds appointment_reminders FKs on tenant_id/appointment_id with ON DELETE CASCADE; adds the four bare companies pointer FKs with ON DELETE SET NULL. New auth migration 20260516000001_org_invitations_citext.sql: changes org_invitations.email to CITEXT to match admin_invites (so case no longer bypasses the one-open-invite-per-(tenant,email) guard) and adds the octet_length(token_hash)=32 CHECK that admin_invites already carries. src/main.rs: migration failure now fails fast (.expect) instead of being swallowed as a warning, so the server never starts on a stale schema. src/modules/tenants/service.rs: copy_default_config no longer parses a hardcoded magic UUID with unwrap(); the seed-source tenant is read from MOKOSH_SEED_TENANT_ID (fallible parse, Configuration error on malformed value) and falls back to Uuid::from_u128(1). src/utils/validation.rs: truncate() snaps the cut point back to the nearest char boundary via char_indices so multi-byte UTF-8 input no longer panics; adds a regression test. #PMS-196 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
fix(schema): harden migrations, FKs, seed, and truncation (PMS-196)
Some checks failed
E2E / Playwright against staging (pull_request) Failing after 17s
Check / fmt + clippy + compile + tests (pull_request) Failing after 2m33s
eaa150f50e
Most RLS findings were already closed by 038/041 (fail-closed policy, tenant-less table coverage). This change handles the remaining schema-integrity and code-path findings, using new forward migrations rather than editing shipped migrations (sqlx validates the checksum of every applied migration on run, and that path is now fatal).

New migration 042_pms196_fks_and_triggers.sql: re-runs the updated_at trigger sweep idempotently (DROP TRIGGER IF EXISTS + CREATE), which both makes trigger attachment re-runnable and attaches the trigger to post-024 tables that never got one (e.g. kb_article_votes); adds appointment_reminders FKs on tenant_id/appointment_id with ON DELETE CASCADE; adds the four bare companies pointer FKs with ON DELETE SET NULL.

New auth migration 20260516000001_org_invitations_citext.sql: changes org_invitations.email to CITEXT to match admin_invites (so case no longer bypasses the one-open-invite-per-(tenant,email) guard) and adds the octet_length(token_hash)=32 CHECK that admin_invites already carries.

src/main.rs: migration failure now fails fast (.expect) instead of being swallowed as a warning, so the server never starts on a stale schema.

src/modules/tenants/service.rs: copy_default_config no longer parses a hardcoded magic UUID with unwrap(); the seed-source tenant is read from MOKOSH_SEED_TENANT_ID (fallible parse, Configuration error on malformed value) and falls back to Uuid::from_u128(1).

src/utils/validation.rs: truncate() snaps the cut point back to the nearest char boundary via char_indices so multi-byte UTF-8 input no longer panics; adds a regression test.

#PMS-196

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merge origin/main into feat/pms-196-harden-migrations-rls-integrity
Some checks failed
E2E / Playwright against staging (pull_request) Failing after 26s
Check / fmt + clippy + compile + tests (pull_request) Successful in 4m26s
Create release / Create release from merged PR (pull_request) Has been skipped
ad47e38e9e
Resolve src/main.rs: keep main's structured return-Err migration-failure
path over this branch's expect()/panic; both make migration failure fatal
(PMS-286 / PMS-196). Renumber 042_pms196_fks_and_triggers to 043 to clear
the prefix collision with main's 042_portal_setup_tokens.

#PMS-196
David merged commit 06bddef16f into main 2026-06-13 23:50:53 +02:00
David deleted branch feat/pms-196-harden-migrations-rls-integrity 2026-06-13 23:50:54 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/mokosh-server!210
No description provided.