docs: consolidate repository guides and preserve audit history

This commit is contained in:
cesnimda
2026-09-11 14:22:41 +02:00
parent 115441a409
commit 682a3028bb
404 changed files with 3402 additions and 2621 deletions
+10
View File
@@ -0,0 +1,10 @@
# Database
EF Core owns the current schema and migrations. SQLite is the local default; MariaDB/MySQL is supported for server deployments.
- [Schema overview](schema.md)
- [Migrations and compatibility](migrations.md)
- [Backups](backups.md)
- [Database ownership in the architecture](../architecture/overview.md)
Never reset a development or production database as part of documentation work. Use disposable test databases for migration checks.
+5
View File
@@ -0,0 +1,5 @@
# Database backups
SQLite backups use a consistent snapshot (`VACUUM INTO`) and are retained under the data root. The runtime also preserves data files, CV artifacts, exports, Data Protection keys, and account-deletion tombstones as separate recovery concerns. MariaDB/MySQL uses external database backup tooling rather than the SQLite job.
Backup age, manifest completeness, restore correctness, key availability, and tombstone replay must be checked together. The current production restore rehearsal is still an operator gate; see [infrastructure backups](../infrastructure/backups.md) and [known issues](../roadmap/known-issues.md).
+39
View File
@@ -0,0 +1,39 @@
# Migrations and compatibility
The API applies EF Core migrations on startup and performs guarded legacy-schema reconciliation for SQLite and MariaDB/MySQL compatibility. Fresh and repeated disposable SQLite migration chains are the normal local verification; generated provider SQL is not proof of a live production migration.
The `Job`/`JobApplication` opportunity cutover is an expand/verify/contract change. Keep dual writes and compatibility reads until a production report and restored-backup rehearsal pass, then observe one release before removing legacy columns in a later migration. Never edit the history of an applied migration.
### Production cutover validation
After the additive backfill, run these read-only MariaDB/MySQL checks against production and a restored
backup. Every result must be `0`; do not turn them into an update script.
```sql
SELECT COUNT(*) AS missing_job
FROM JobApplications
WHERE JobId IS NULL;
SELECT COUNT(*) AS missing_target
FROM JobApplications a
LEFT JOIN Jobs j ON j.Id = a.JobId
WHERE a.JobId IS NOT NULL AND j.Id IS NULL;
SELECT COUNT(*) AS owner_mismatch
FROM JobApplications a
JOIN Jobs j ON j.Id = a.JobId
WHERE NOT (a.OwnerUserId <=> j.OwnerUserId);
SELECT COUNT(*) AS field_mismatch
FROM JobApplications a
JOIN Jobs j ON j.Id = a.JobId
WHERE NOT (a.CompanyId <=> j.CompanyId)
OR NOT (a.JobTitle <=> j.JobTitle)
OR NOT (a.Location <=> j.Location)
OR NOT (a.JobUrl <=> j.JobUrl)
OR NOT (a.Description <=> j.Description)
OR NOT (a.Salary <=> j.Salary);
```
Observe one release after the checks pass, then change reads, re-run the checks on a fresh restore, and
only then make `JobId` required and remove duplicated opportunity columns in a later migration.
+7
View File
@@ -0,0 +1,7 @@
# Schema overview
Identity users own companies, jobs, applications, correspondence, attachments, CV artifacts/runs, sessions, trusted devices, and career data. `Job` represents the opportunity; `JobApplication` represents the user's pursuit. Applications also retain compatibility opportunity fields until the production cutover gate.
Important relationships include company → jobs/applications, application → correspondence/attachments/events/checklist/AI and tailored-CV records, and CV upload → extraction runs. The career profile has relational child records plus a JSON long-tail field. Tags remain a JSON string for compatibility. Owner-prefixed indexes support tenant-scoped lists, boards, reminders, and CV queries.
The model snapshot and migrations live in `JobTrackerApi/Migrations/`. Startup initialization performs compatibility reconciliation for historical schemas; this is a known ownership debt, not permission to rewrite applied migrations.