feat: establish catalog identity and atomic file ownership

This commit is contained in:
Cline committed 2026-10-12 19:38:38 -05:00
1 parent 390a7a557a
commit 6b9fb54b4f
16 files changed
+1381 -23

No files matched your search

+57
View File
@@ -5,3 +5,60 @@ changes versioned and repeatable; do not introduce a competing runner here.
Subsequent issues #13-18 add physical folders, logical models, distinct files,
metadata and import jobs. Application added_at timestamps are separate from file
mtime. Migrations must never implicitly delete underlying library files.
## Catalog identity — 20261012120001
Back up the database and **stop all writers** (web requests, import workers and
other database clients) before either upgrade or downgrade. Keep them stopped
through preflight and DDL. Preflight is not a concurrency lock.
Upgrade rejects duplicate managed paths and noncanonical paths, even without a
collision, reporting offending file IDs. It makes file ownership nullable with
RESTRICT on model deletion, replaces idx_files_model_path with unique
idx_files_managed_path and nonunique idx_files_model_id, and makes
idx_models_folder_name nonunique. Explicitly detach files before model deletion.
Rows, IDs, timestamps, dependent metadata and unrelated indexes/FKs are preserved.
Managed paths are lexical slash-separated relative names, preserved verbatim.
Empty/dot/dot-dot segments, backslashes, NUL, absolute paths and URI/drive prefixes
are rejected. Windows additionally rejects colons and trailing dots/spaces in
segments. Case and Unicode are not normalized. This is not filesystem case
comparison or symlink authorization; PathSafety still governs I/O. Migration
validation performs no filesystem access.
Investigate reported IDs and explicitly resolve catalog paths and ownership
against the library before retrying. No automatic merging, renaming, reassignment
or deletion repairs conflicts.
Downgrade to 20261011120006 rejects unassigned file IDs and duplicate same-folder
model titles before DDL. Explicitly assign files and disambiguate titles first.
Only then are NOT NULL, per-model path uniqueness, unique folder/title and the
old CASCADE model FK restored. Preflight failure leaves schema, data and migration
version unchanged.
Tasks 1–3 restore repository/importer compatibility and add the bounded catalog
service: explicit same-title identities, ambiguity-safe legacy lookup, nullable
registration and expected-owner associations using savepoint-backed transactions.
Association changes update only model_id, not physical files or home folders.
Task 4 verified the full suite on 2026-10-13:
- Windows PHP 8.3.35: foundation passed; PHPUnit 377 tests / 2032 assertions /
28 skips; standard lint passed (Composer script commands invoked directly).
- Fresh isolated PostgreSQL 17 / PHP 8.4.26 via `sh bin/test-postgres.sh`: Composer
tests 377 / 2160 / 7 skips and lint passed. Log on the Docker host:
`keith@192.168.2.23:/tmp/meshvault-catalog-tests-Ov96uNzU/pg-run-3.log`.
- The suite runs production migrations in generated schemas, including populated
down/up, dependent metadata, direct constraints, index preservation and unchanged
preflight-rejection snapshots. This does not replace an operator backup/restore
drill or deployment migration smoke acceptance.
- First PG run exposed four SQLite-trigger syntax errors in rollback tests;
dialect-specific test triggers now prove rollback after an actual earlier write.
Six new two-session cases verify 55P03 contention, stale/no-op behavior, ascending
execution parameters, nested rollback/lock release and root creation serialization.
They passed existing locking code; no induced deadlock or mutation-red claim.
No development database or historical workspace was touched. Independent full-slice
review approved this bounded implementation; #28 is not complete. Importer confirmation/recovery, broader
metadata/lifecycle contracts and unresolved M2/M3 acceptance remain open. See
`docs/project-status.md` for the evidence and limitations.