Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
46f3a76
test: add reservation lifecycle smoke guard
chuanman2707 May 12, 2026
5289bc7
test: add stay lifecycle smoke guard
chuanman2707 May 12, 2026
d10dc84
Merge branch 'codex/core-pms-smoke-tests-137'
chuanman2707 May 13, 2026
5cd0e28
docs: design frontend shell composition
chuanman2707 May 13, 2026
e1726eb
docs: clarify frontend shell composition design
chuanman2707 May 13, 2026
1de4ed3
docs: add frontend invoke wrapper design
chuanman2707 May 14, 2026
1c50d21
docs: clarify frontend invoke wrapper spec
chuanman2707 May 14, 2026
bd1f0d6
test: cover pricing invoke wrapper
chuanman2707 May 14, 2026
6d9d248
test: cover settings invoke wrapper
chuanman2707 May 14, 2026
39d0e4a
test: cover housekeeping invoke wrapper
chuanman2707 May 14, 2026
03f6f18
test: guard frontend invoke wrapper usage
chuanman2707 May 14, 2026
f54e82f
test: tighten invoke wrapper guardrail
chuanman2707 May 14, 2026
c4e0829
test: harden invoke wrapper guardrail
chuanman2707 May 14, 2026
089be43
test: align housekeeping invoke wrapper expectation
chuanman2707 May 14, 2026
7971de5
test: catch dynamic raw invoke calls
chuanman2707 May 14, 2026
1928234
docs: design experimental runtime gating
chuanman2707 May 15, 2026
0ed3dfe
docs: address experimental runtime spec review
chuanman2707 May 15, 2026
a3c9a21
refactor: add effective experimental runtime flags
chuanman2707 May 15, 2026
d4fbe7d
refactor: gate gateway runtime by experimental profile
chuanman2707 May 15, 2026
867b069
refactor: gate agent supervisor by experimental profile
chuanman2707 May 15, 2026
e1d89b2
feat: add frontend experimental runtime profile
chuanman2707 May 15, 2026
11a7ccb
test: harden experimental runtime profile fallback
chuanman2707 May 15, 2026
e4069e8
refactor: hide app gateway surfaces by runtime profile
chuanman2707 May 15, 2026
c59e1b3
fix: ignore stale gateway status responses
chuanman2707 May 15, 2026
b4239e8
refactor: hide experimental settings by runtime profile
chuanman2707 May 15, 2026
7e597b2
fix: reset hidden experimental settings sections
chuanman2707 May 15, 2026
84718c5
test: allow experimental runtime status invoke
chuanman2707 May 15, 2026
2729514
test: enable gateway profile in settings api key test
chuanman2707 May 15, 2026
65eb6a2
chore: keep experimental runtime gates clippy-clean
chuanman2707 May 15, 2026
e3d7c0d
Merge remote-tracking branch 'origin/main' into codex/experimental-ru…
chuanman2707 May 15, 2026
5d00d37
chore: drop stale frontend wrapper spec
chuanman2707 May 15, 2026
9b97612
docs: design experimental runtime batch 2 gating
chuanman2707 May 15, 2026
59495dd
docs: clarify experimental runtime batch 2 gates
chuanman2707 May 15, 2026
2e41eb2
test: lock peripheral runtime flag semantics
chuanman2707 May 15, 2026
57a053c
refactor: fail closed inside gateway startup
chuanman2707 May 15, 2026
b37cc3f
refactor: make outbox subscriber profile explicit
chuanman2707 May 15, 2026
6bc6bc6
test: cover inactive outbox dispatcher startup
chuanman2707 May 15, 2026
fa34162
test: guard experimental observer and outbox boundaries
chuanman2707 May 15, 2026
0df0fc6
Merge remote-tracking branch 'origin/main' into codex/experimental-ru…
chuanman2707 May 15, 2026
72805ea
docs: design migration extraction setup
chuanman2707 May 16, 2026
04596b4
docs: tighten migration extraction spec
chuanman2707 May 16, 2026
2389976
refactor: extract core PMS migrations
chuanman2707 May 16, 2026
7db391c
docs: design migration extraction follow-up
chuanman2707 May 17, 2026
dae4b6e
docs: address migration extraction spec review
chuanman2707 May 17, 2026
bf21a09
refactor: extract remaining migrations
chuanman2707 May 17, 2026
7dd3458
Merge branch 'codex/experimental-runtime-gating'
chuanman2707 May 17, 2026
7a58a73
refactor: extract command idempotency types
chuanman2707 May 17, 2026
9a00c0f
docs: design command lock-key extraction
chuanman2707 May 18, 2026
a14a5a5
refactor: extract command lock-key preparation
chuanman2707 May 18, 2026
e917ab1
Merge remote-tracking branch 'origin/main' into codex/command-lock-ke…
chuanman2707 May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 213 additions & 0 deletions docs/superpowers/specs/2026-05-17-migration-extraction-146-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
# Migration Extraction Follow-Up Design

Issue: #146 ARCH-13 Batch 3: Move command-safety and experimental migrations in follow-up batches

Parent roadmap: #133 Core PMS Architecture Stabilization V2.1

Date: 2026-05-17
Status: User-approved design; subagent review findings addressed

## Purpose

Move the remaining inline migration bodies `V7` through `V19` out of `mhm/src-tauri/src/db.rs` without changing database behavior.

Although issue #146 is framed around command-safety, outbox, gateway, and agent-related migrations, this approved follow-up intentionally includes `V8` invoice and `V9` group-booking migrations as well. Those versions are included so the follow-up completes the migration extraction after #144/#145 and leaves `db.rs` as a runner/bootstrap module rather than leaving isolated inline migration bodies behind.

This is a no-behavior-change extraction. It must make `db.rs` a migration runner and database bootstrap module instead of a migration monolith, while preserving schema semantics, migration order, compatibility behavior, command safety behavior, money migration behavior, outbox behavior, gateway runtime behavior, agent runtime behavior, and frontend behavior.

## Scope

- Keep database bootstrap and the main migration runner in `mhm/src-tauri/src/db.rs`.
- Keep existing helper functions in `db.rs`, including `set_schema_version`, `execute_compat_alter`, and `restore_foreign_keys_after_v14_migration`.
- Move remaining migration bodies `V7` through `V19` into private modules under `mhm/src-tauri/src/db/`.
- Keep the existing `V1` through `V6` extraction in `mhm/src-tauri/src/db/migrations.rs`.
- Keep the final schema version at `19`.
- Keep existing migration tests and fresh database guards intact.

`V7` through `V19` cover:

- `V7`: gateway API key storage
- `V8`: invoice PDF system
- `V9`: group booking system
- `V10`: command idempotency
- `V11`: command terminal error replay payload
- `V12`: operator-ready command ledger metadata
- `V13`: origin idempotency on ledger and folio rows
- `V14`: integer VND money foundation, including the existing command ledger legacy hash compatibility column
- `V15`: command recovery queue and audit actions
- `V16`: durable outbox events
- `V17`: outbox per-aggregate open-row FIFO support
- `V18`: agent safety session, audit, and memory schema
- `V19`: CEO hourly digest run state

## Non-Goals

- Do not change SQL semantics.
- Do not reorder migrations.
- Do not combine migrations.
- Do not change the final schema version.
- Do not change command idempotency logic.
- Do not change outbox dispatcher behavior.
- Do not change gateway, agent, digest, Telegram, OpenAI, or frontend runtime behavior.
- Do not gate or delete experimental schemas.
- Do not introduce a new migration framework or registry abstraction.
- Do not move or refactor unrelated backend modules.

## Context

Issues #144 and #145 introduced the migration module structure and moved `V1` through `V6` into `mhm/src-tauri/src/db/migrations.rs`. The remaining migrations `V7` through `V19` still live inline in `run_migrations`.

Issue #146 intentionally has higher risk than the first extraction because the remaining migrations include command-safety, money, outbox, gateway, agent, and digest schema. Those schemas are safety-sensitive even when the runtime surfaces are experimental.

GitNexus impact analysis for `run_migrations` returned CRITICAL risk: 53 direct callers, 8 affected execution flows, and 20 affected modules. The affected surface includes app startup, database migration tests, command idempotency tests, outbox tests, gateway tests, agent tests, digest tests, setup tests, and booking tests.

GitNexus impact analysis for `set_schema_version` and `execute_compat_alter` also returned CRITICAL risk. This extraction may widen visibility only as needed for private child migration modules, but it must not change helper behavior.

## Chosen Approach

Move all remaining inline migrations `V7` through `V19` in one issue, but split them into domain-focused private modules so the high-risk areas remain reviewable.

Use this module shape:

```text
mhm/src-tauri/src/db.rs
mhm/src-tauri/src/db/
migrations.rs
core_extensions.rs
command_safety.rs
money.rs
outbox.rs
agent.rs
```

Module ownership:

- `migrations.rs` keeps the existing `V1` through `V6` early PMS migrations.
- `core_extensions.rs` owns `V7` through `V9`.
- `command_safety.rs` owns `V10` through `V13` and `V15`.
- `money.rs` owns the `V14` integer VND money migration special case.
- `outbox.rs` owns `V16` and `V17`.
- `agent.rs` owns `V18` and `V19`.

Rejected alternatives:

- Keep everything in a single growing `migrations.rs`. This reduces `db.rs` but recreates a migration monolith.
- Create one file per migration version. This gives maximum isolation, but creates more file churn than the current migration count needs.
- Split #146 into multiple issues. This is safest per PR, but the chosen scope is to move all remaining migrations while preserving review boundaries inside the PR.

## Module Interfaces

Each new module should expose only parent-module-internal functions needed by `run_migrations`.

`core_extensions.rs`:

```rust
pub(super) async fn migrate_v7_gateway_api_keys(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v8_invoice_pdf_system(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v9_group_booking_system(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
```

`command_safety.rs`:

```rust
pub(super) async fn migrate_v10_command_idempotency(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v11_command_terminal_error_replay(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v12_command_ledger_metadata(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v13_origin_idempotency(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v15_command_recovery(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
```

`money.rs`:

```rust
pub(super) async fn migrate_v14_integer_vnd_money(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
```

`outbox.rs`:

```rust
pub(super) async fn migrate_v16_durable_outbox_events(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v17_outbox_fifo_support(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
```

`agent.rs`:

```rust
pub(super) async fn migrate_v18_agent_safety_tables(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
pub(super) async fn migrate_v19_agent_digest_runs(pool: &Pool<Sqlite>) -> Result<(), sqlx::Error>;
```

The modules should reuse shared helpers from `db.rs` instead of duplicating compatibility or schema-version logic.

## Data Flow

The runtime flow remains unchanged:

1. `init_db` creates the SQLite pool.
2. `init_db` calls `run_migrations`.
3. `run_migrations` reads the current schema version.
4. `run_migrations` checks each version gate in order.
5. For `V1` through `V19`, `run_migrations` delegates to private migration module functions.
6. `init_db` inserts default settings after migrations complete.

`run_migrations` remains the only place that decides migration order. The extracted modules own only migration bodies.

The `V14` flow is the existing exception and must remain behaviorally identical:

1. Acquire a connection.
2. Disable foreign keys.
3. Run the migration transaction callback.
4. Add `legacy_request_hash` through `execute_compat_alter`.
5. Call `crate::money_migration::migrate_integer_vnd_money`.
6. Set schema version `14`.
7. Restore foreign key behavior through `restore_foreign_keys_after_v14_migration`.

## Error Handling

Error behavior must stay unchanged.

Each extracted migration returns `Result<(), sqlx::Error>` and uses `?` exactly like the current inline code. If a query fails, the transaction is not committed and the error bubbles back to `run_migrations`.

`execute_compat_alter` keeps its current behavior: duplicate column and already-exists errors are logged and ignored; other errors fail the migration.

`V14` keeps the existing foreign-key restore path. The extraction must not add a new recovery path, repair path, fallback path, migration skip path, or best-effort schema creation path.

## Testing

Validation commands:

```bash
cd /Users/binhan/HotelManager/mhm/src-tauri && cargo test db::tests
cd /Users/binhan/HotelManager/mhm/src-tauri && cargo test migration
cd /Users/binhan/HotelManager/mhm/src-tauri && cargo test
cd /Users/binhan/HotelManager/mhm/src-tauri && cargo clippy --all-targets -- -D warnings
```

Expected coverage:

- fresh database migration still reaches schema version `19`;
- required PMS, core extension, command safety, outbox, and agent tables still exist;
- fresh migration tests and existing database upgrade tests for `V10` through `V19` still pass where those tests currently exist;
- V14 money conversion and rollback tests still pass;
- V16 and V17 outbox schema, index, and insert contract tests still pass;
- V18 and V19 agent and digest schema tests still pass;
- compatibility alters still ignore duplicate columns where intended;
- later runtime tests that create migrated test pools still pass.

Before committing implementation changes, run GitNexus change detection. The expected affected scope should be limited to `db.rs`, private `db/` migration module files, and migration execution flows.

## Review Guardrails

Implementation should be a mechanical move:

- preserve SQL strings exactly;
- preserve comments where they identify migration versions or existing behavior;
- preserve transaction boundaries;
- preserve version numbers;
- preserve call order;
- preserve V14 foreign-key handling;
- avoid unrelated formatting churn in untouched code;
- do not edit command idempotency, outbox, gateway, agent, digest, frontend, or service behavior;
- do not edit the unrelated dirty file `mhm/src/stores/useHotelStore.test.ts`.

Before editing implementation symbols, run GitNexus impact analysis for each edited function or helper. If GitNexus reports that the index is stale, run `npx gitnexus analyze` before relying on impact output. At minimum, run impact analysis for `run_migrations`, `set_schema_version`, `execute_compat_alter`, and `restore_foreign_keys_after_v14_migration` if their bodies or visibility are modified. `run_migrations`, `set_schema_version`, and `execute_compat_alter` are already known CRITICAL risk; implementation should report that blast radius before editing and continue only with the approved mechanical extraction scope.
Loading
Loading