# REL-004: owner-scoped 수동 장부 API + portfolio_ledger metadata migration (M5) - Status: **draft** - Profile: app-service - Included Batch: BAT-024 (REQ-056), BAT-025 (REQ-057) - Release baseline: `origin/main@914b3dc6e6b9e2cbd7068fb30435c83f0581eab5` - Deployment runbook: [REL-004 운영 배포 런북](../runbooks/rel-004-m5-manual-ledger-deployment-runbook.md) - Release approver: Justin Ko (pending) - Operator: trex-op (pending) --- ## 1. Release intent and scope ### Included - **BAT-024 / REQ-056** — owner-scoped manual ledger API: - `POST /v1/portfolios/{portfolio_id}/ledger/manual` - `GET /v1/portfolios/{portfolio_id}/ledger/manual` - user/session-token owner scope, service-token fail-closed, daemon-managed confirmation, reversal deduplication, transaction/row-lock semantics. - **BAT-025 / REQ-057** — explicit Alembic revision `20260715_0028`: - `portfolio_ledger.source TEXT NOT NULL DEFAULT 'broker'` - `target_ledger_entry_id BIGINT NULL` - `confirmation_evidence TEXT NULL` - `actor_user_id TEXT NULL` - existing rows/data preservation and runtime-precreated schema compatibility. ### Excluded - Production DB migration, service restart, API activation, and any live manual-ledger write. These require the release approval and runbook preflight evidence below. - `QUANTITY_ADJUSTMENT`, NXT/strategy service changes, and all M5-excluded cards. - Any `alembic downgrade` or production column deletion. Recovery is forward-only: compatible code rollback while preserving the additive schema and revision. --- ## 2. Release basis | Basis | Evidence | Result | | --- | --- | --- | | REQ-056 API delivery | BAT-024 implementation `b3447f6`; developer verification `594 passed, 12 warnings`; independent QC `deleg_f2337a39` | PASS | | Draft baseline regression re-run | 2026-07-15 clean `origin/main@914b3dc` worktree: `594 passed, 3 skipped, 12 warnings in 39.10s`; skipped tests are PostgreSQL-dependent migration integration cases | PASS | | REQ-057 migration delivery | PR #21, merged into `main` as `914b3dc`; implementation commits `1909caa`, `d48279f`, `2f82251`, `bd51330`, `aac08eb` | PASS | | Migration/data compatibility | isolated loopback PostgreSQL suite: `3 passed in 6.10s`; fresh, existing-row, and runtime-precreated schema cases | PASS | | Full regression at BAT-025 verification | `597 passed, 11 warnings in 41.41s`; Ruff, compileall, diff hygiene pass | PASS | | Independent release-chain QC | PR #21 committed-diff QC `deleg_ae0c6f27`; patch-id mapping, migration semantics, loopback PostgreSQL, Ruff, clean worktree | PASS | | Operational database evidence | backup, locks, current revision, row counts, schema/current postcheck, service smoke | **PENDING — must be captured by trex-op** | The test evidence is intentionally limited to isolated/local PostgreSQL. It is not evidence that an operating database has been backed up, is lock-free, or has safely completed the upgrade. --- ## 3. Mandatory release gates The operator must stop before code deployment or restart when any gate fails. 1. **Approval gate** — Justin Ko records explicit approval for this REL-004 execution window. 2. **Baseline gate** — artifact is built from `914b3dc` or a reviewed descendant; record immutable image/package digest. 3. **Backup gate** — restorable DB backup is complete and path, timestamp, size, and restore owner are recorded. 4. **Database gate** — `alembic heads`, `alembic current`, active-query/lock check, metadata schema snapshot, and `portfolio_ledger` row count are captured before upgrade. 5. **Migration gate** — `alembic upgrade 20260715_0028` succeeds; `current`, all four columns, `source` default/not-null, `source IS NULL = 0`, and unchanged row count are evidenced. 6. **Activation gate** — only after Gate 5, deploy the immutable artifact and perform the service's normal rolling restart procedure. 7. **Smoke gate** — health response and approved owner-token/API smoke pass. A production mutation smoke must use an explicitly designated test portfolio and authorization; it is not implicit approval to alter a customer or live trading portfolio. --- ## 4. Deployment sequence ```text Approval → immutable artifact selection → DB backup/preflight → Alembic 0028 upgrade → schema/current/data verification → portfolio-hub rolling restart using the approved artifact → health and minimum API smoke → observation window → released decision ``` The detailed commands, expected results, stop conditions, evidence template, and forward-only recovery procedure are in the linked runbook. --- ## 5. Rollback and recovery ### Triggers - migration command fails or postcheck differs from expected schema/current/row-count values; - `GET /health` fails or returns `db_enabled != true` after activation; - new manual API returns unexpected 5xx or authorization fail-open behavior; - existing `/ledger/trades` or portfolio read flows show regression. ### Policy - **Before migration succeeds:** stop; do not restart into the new code. Preserve logs and consult the DB owner using the backup and error evidence. - **After migration succeeds:** do **not** run `alembic downgrade` and do not drop the four additive columns. Roll back only to a reviewed compatible code artifact, retaining revision `20260715_0028` and the schema. - DB restore is an exceptional, separately approved recovery operation; it is not an automatic release action. --- ## 6. Release execution evidence (to be completed by trex-op) | Field | Evidence | | --- | --- | | Approval time / approver | Pending | | Maintenance window | Pending | | Artifact ref + immutable digest | Pending | | Operator | Pending | | Backup path / timestamp / size / restore verification owner | Pending | | Preflight `alembic heads/current` | Pending | | Pre/post `portfolio_ledger` row counts | Pending | | Lock/active-query result | Pending | | `0028` upgrade command and exit/result | Pending | | Post-migration schema/default/null/current evidence | Pending | | Rolling restart evidence | Pending | | Health and approved API smoke evidence | Pending | | Observation window / alerts | Pending | | Rollback needed | Pending | ## 7. Release decision - Current decision: **draft — not authorized for production execution yet**. - Transition to `released` requires all mandatory gates and the evidence table to be completed, then a release approver decision recorded in this document.