Repository navigation
Description
Problem
The control service has an explicit compiled migration command, but it currently migrates only Better Auth's schema. session-peer's first-party tables are created from runtime constructors:
auth.ts:relay_public_signupsapp.ts:relay_device_claimsrelay-control.ts: devices, challenges, operations, contract metadata and public-state revision
This makes a fresh database work, but it does not provide a complete, versioned upgrade contract for an installed Alpha service. The existing registration marker correctly refuses to reinterpret an incompatible draft database; the next step is an operator-reviewable migration path that preserves devices, revocation tombstones, operation receipts and revision history.
Proposed behavior
- Add a versioned first-party migration ledger for every session-peer-owned control table and index.
- Make the compiled migration entry point run Better Auth migrations and first-party migrations under the same service identity and writer lock.
- Keep each first-party migration transactional and idempotent. Record completion only after the schema/data change commits.
- Change normal service startup to validate the expected schema and fail with an actionable
migration_requiredhealth/error state rather than creating or altering first-party tables. - Preserve the
zero_based_v1registration contract, stable principals, generations, revoked tombstones, pending/committed operations and the monotonic public revision. - Require a consistent protected snapshot before an upgrade that changes persistent state. Never restore or delete state automatically after migration failure.
- Document preflight, migrate, start, verify and rollback/fencing steps for generic and KR deployments.
Acceptance criteria
- A fresh empty state migrates to the complete current schema without starting the HTTP service.
- A sanitized
v1.0.0-alpha.1database fixture upgrades without losing users, devices, tombstones, receipts or revision state. - Re-running the migration is a no-op and reports the installed schema version.
- Normal startup against an old, partial, future or corrupted schema fails closed and does not mutate it.
- Fault injection covers interruption before commit, failed commit, restart after a completed migration and a migration error after the protected snapshot.
- Backup/restore tests verify schema version together with SQLite integrity, signing-key/JWKS identity and replay/public revision fencing.
- Node 22/24 and the actual Node/Python control integration suite pass from both a fresh and upgraded fixture.
Non-goals
- Silently renumbering generations, replacing stable principals or deleting receipts.
- Automatically running migration from
ExecStartPreor every service start. - Treating an old database snapshot as an authorized rollback.
- Changing OAuth provider identities or public signup policy.
This is a v1.0.0-beta gate. It should be coordinated with the deployment layout work in #111; later source modularization in #112 must consume the resulting migration contract rather than inventing another one.
Activity