Files
jobtrackingapp/docs/verification/jt-019-schema-ownership.md
T
cesnimda 058d13de47 refactor(db): migrate Identity schema
Complete schema ownership by moving all ASP.NET Identity tables to an additive provider-aware migration. Preserve credentials, security state, preferences, roles, claims, external logins, tokens, indexes, and cascades.
2026-08-30 22:02:35 +02:00

7.7 KiB

JT-019 schema ownership — incremental migration transfers

Scope

This work establishes a behaviour-preserving ownership boundary and moves small independent or cohesive table groups. It does not attempt to delete the legacy reconciler wholesale.

Implemented

  • Added StartupSchemaOwnership, classifying all 49 EF model tables into disjoint migration-owned and reconciler-owned creation sets.
  • Added a regression that fails when a model table is unclassified, multiply classified, or when a compatibility bootstrap is incorrectly treated as migration ownership.
  • Added 20260830120000_AdoptSystemEmailSettingsSchema, with provider-aware additive DDL for SQLite and MariaDB/MySQL.
  • Removed the MariaDB startup CREATE TABLE block for SystemEmailSettings and moved the table to the migration-owned set.
  • Added 20260830121000_AdoptUserRuleSettingsSchema and removed both provider startup-create paths for the independent per-user rule-settings table.
  • Added 20260830122000_AdoptGmailReviewDecisionsSchema, removed the SQLite startup-create path, and supplied the previously absent MariaDB table definition.
  • Added 20260830123000_AdoptAuthenticationSupportSchema for recovery codes, trusted devices, and revocable user sessions; both provider startup-create paths are removed while guarded MariaDB repair checks remain for historical schemas.
  • Added 20260830124000_AdoptEmailConnectionSchema for Gmail, Microsoft Graph, and IMAP connection records. Encrypted credentials and sync state are retained; scoped Gmail column repair and guarded MariaDB index/identity repair remain for historical installations.
  • Added 20260830125000_AdoptCvExtractionSchema for upload artifacts and extraction runs, retaining parsed output and the nullable ON DELETE SET NULL artifact relationship.
  • Added 20260830126000_AdoptTailoredCvDraftSchema for the job-specific tailored document, retaining generated and manually edited content plus its ON DELETE CASCADE application relationship.
  • Added 20260830127000_AdoptJobWorkspaceNotesSchema for interview preparation and irregular AI workspace results, retaining reviewed output and both application cascade relationships.
  • Added 20260830128000_AdoptCvVariantSchema for saved CVs and their append-only revision history, retaining public slugs, builder settings, and job-link/version retention semantics.
  • Added 20260830129000_AdoptAiInteractionSchema to take ownership from both the startup reconciler and historical compatibility bootstrap while retaining append-only results and usage counters.
  • Added 20260830130000_AdoptApplicationChecklistSchema for application workflow state, retaining stable system keys, manual steps, completion state, and user ordering.
  • Added 20260830131000_AdoptCoverLetterVersionSchema for append-only document history, retaining manual and AI-approved text plus source/action metadata.
  • Added 20260830132000_AdoptInterviewPrepItemSchema for durable interview-practice content, retaining user and AI questions, answers, prepared state, source metadata, and ordering.
  • Added 20260830133000_AdoptCareerProfileSchema for the canonical profile, append-only history, and all six ordered relational child types. Legacy JSON, Norwegian text, stable keys, and cascade ownership are retained.
  • Added 20260830134000_AdoptIdentitySchema for the complete ASP.NET Identity aggregate, preserving accounts, password hashes, 2FA state, preferences, roles, claims, external logins, and tokens.
  • Corrected the ownership runbook: new tables now default to migrations; the reconciler is legacy compatibility code to retire one dependency group at a time.

Data compatibility

The migration uses CREATE TABLE IF NOT EXISTS. Existing MariaDB installations keep their table and rows; SQLite installations that never received the reconciler-only table now receive it. Down is intentionally non-destructive because it cannot determine whether the existing table predates this migration.

Proof

  • Ownership and migration-chain focused suite: 6/6 passed.
  • Blank SQLite chain applies all migrations twice and creates all ten expected SystemEmailSettings columns.
  • A database stopped immediately before the adoption migration, seeded with a representative SMTP settings row, upgrades without changing that row.
  • A representative per-user rules row survives adoption, downgrade, and re-upgrade.
  • A representative Gmail review decision survives adoption, downgrade, and re-upgrade.
  • Representative recovery-code, trusted-device, and user-session rows survive adoption, downgrade, and re-upgrade, and their indexes are present afterwards.
  • Representative encrypted credentials for all three email providers survive adoption, downgrade, and re-upgrade, and all five expected provider indexes are present afterwards.
  • Representative CV artifact metadata and structured extraction output survive adoption, downgrade, and re-upgrade; deleting the artifact preserves the run and clears its nullable relationship.
  • A representative tailored CV's summary, custom section, and generation context survive adoption, downgrade, and re-upgrade; deleting the parent application still deletes its draft.
  • Representative interview-preparation and candidate-fit outputs survive adoption, downgrade, and re-upgrade; deleting the parent application still deletes both cached note types.
  • A representative CV and two saved revisions survive adoption, downgrade, and re-upgrade; deleting its job clears only the optional link, while deleting the CV cascades through its revisions.
  • A representative AI result, mode, provider, and usage counts survive adoption, downgrade, and re-upgrade; deleting the parent application still cascades through its interaction history.
  • Representative system-generated and manual checklist steps survive adoption, downgrade, and re-upgrade; deleting the parent application still cascades through its workflow items.
  • Representative manual and AI cover-letter revisions survive adoption, downgrade, and re-upgrade; deleting the parent application still cascades through document history.
  • Representative user-authored and AI-generated interview-preparation items survive adoption, downgrade, and re-upgrade with practice state intact; their ordering index and application cascade remain effective.
  • A populated Career Profile with history, long-tail JSON, Norwegian text, experience, education, skills, projects, certifications, and languages survives adoption, downgrade, and re-upgrade; all 14 aggregate indexes and parent cascades remain effective.
  • A populated Identity account with password hash, Bokmål preference, 2FA state, role assignment, role/user claims, external login, and token survives adoption, downgrade, and re-upgrade; all eight Identity indexes and user/role cascades remain effective.
  • Generated MariaDB SQL contains the provider-correct SystemEmailSettings DDL.
  • Full backend: 736/736 passed after the Identity aggregate transfer.
  • Fresh application startup over a new disposable SQLite data root applied the complete chain, queried/seeded Identity roles, and reached the healthy listening state with no schema failure.
  • Fresh application startup over a new disposable SQLite database applied 20260830120000_AdoptSystemEmailSettingsSchema and reached the healthy listening state.

Remaining JT-019 work

No EF model tables remain startup-created. JT-019's creation-ownership transfer is complete; the startup reconciler now performs compatibility repair only and can be reduced further when historical provider fixtures prove individual repairs obsolete. with parent dependencies. Transfer them in small dependency-aware migrations with blank, populated, retry and MariaDB runtime proof. Column/index repairs must remain until historical upgrade fixtures prove each one redundant.