feat: P1 profile/portrait API and freeze local-dev environment

Add host-first environment contracts (Local vs CI vs Prod), deps-only
compose, and the Profile → Portrait → deep-access mock payment slice
with device identity and auto-migrate on API startup.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-02 16:24:57 +08:00
co-authored by Cursor
parent dd94e57277
commit 0f320e040b
49 changed files with 1907 additions and 191 deletions
+18 -9
View File
@@ -1,9 +1,10 @@
# Database — Golden Rules
Schema source of truth for P1 tables: [domain/erd.md](domain/erd.md).
## Naming
- `snake_case` only for tables and columns.
- Good: `user_profile`, `payment_order`, `user_session`.
- Forbidden prefixes: `tbl_`, `t_`.
## Required columns on business tables
@@ -17,9 +18,8 @@ deleted_at
## Types
- Never `varchar(5000)` as a habit.
- Prefer bounded `varchar(n)`.
- `TEXT` only when necessary (long content bodies).
- `TEXT` only when necessary.
- Timestamps: `timestamptz`.
## Keys & indexes
@@ -27,13 +27,22 @@ deleted_at
- Every foreign key indexed.
- Unique business keys enforced with UNIQUE.
## Migrations
## Migration Rules(强制)
- Schema change without migration = incomplete feature.
- Migrations live in `apps/api/migrations/`.
- Provide Up and Down when tool supports it.
1. **Every schema change requires a migration** under `apps/api/migrations/`.
2. **Never** modify production (or shared) databases by hand (`ALTER TABLE` in psql as a substitute for migration).
3. **Migration files are immutable** after merge to `main` — fix forward with a new migration; do not rewrite history on shared branches.
4. **Destructive changes** (drop column/table, type narrowing) require an explicit rollback/forward strategy in the same change set (Down file or follow-up migration + note).
5. App code must not query columns that are not yet migrated.
6. Local apply: start APIauto-migrateor documented migrate command in [commands.md](commands.md).
## Soft delete
- Default: set `deleted_at`, do not hard delete user content in MVP.
- Queries must filter `deleted_at IS NULL` unless explicitly including deleted.
- Default: set `deleted_at`; do not hard-delete user content in P1.
- Queries filter `deleted_at IS NULL` unless the task says otherwise.
## AI MUST NOT
- 「先改库再补 migration」
- 在 handler 里拼临时 DDL
- 发明未在 `domain.md` / `erd.md` 出现的表名(先改文档)