feat: 统一生产初始化流程并保护系统管理员

This commit is contained in:
Cheng Zhou
2026-03-27 17:17:32 +08:00
parent f2f856ea24
commit a67991740e
14 changed files with 492 additions and 10 deletions
@@ -0,0 +1,40 @@
# Production Initialization Design
**Goal:** Replace the current production bootstrap approach with a single, explicit initialization flow that creates an empty schema via Alembic and seeds exactly one protected administrator account.
**Problem**
- Production currently mixes multiple initialization sources: `database/init.sql`, Alembic migrations, and development-only startup seed behavior.
- This creates schema drift risk and has already caused production startup failures when application models expected columns that the SQL bootstrap script did not create.
- The default administrator identity is also not aligned with the required production account.
**Decisions**
- Production schema source of truth becomes Alembic only.
- New production environments must start from an empty database.
- Production initialization explicitly runs schema migrations first, then ensures a fixed administrator account exists.
- No demo users, demo projects, demo fees, or any other seed business data are created in production initialization.
- The fixed administrator is `admin@huapont.cn` with initial password `admin123`.
- The fixed administrator cannot be deleted, disabled, downgraded from `ADMIN`, or have its email changed.
- The fixed administrator may change its password after first login.
**Architecture**
- A dedicated backend initialization command handles production bootstrap responsibilities.
- The command runs `alembic upgrade head`, then creates or repairs the protected administrator account if needed.
- The API layer enforces immutability rules for the protected administrator so UI or API requests cannot remove or weaken that account.
- The development environment may still keep development-only conveniences, but production deployment no longer depends on app startup side effects for schema creation.
**Operational Flow**
1. Start PostgreSQL with an empty data directory.
2. Run the one-shot backend initialization command.
3. Start long-lived backend and Nginx services.
4. Log in with `admin@huapont.cn / admin123`, then change the password.
**Non-Goals**
- No automatic demo data import.
- No runtime auto-migration inside the long-lived backend container.
- No second schema definition maintained in `database/init.sql`.
**Verification Targets**
- Empty production database initializes successfully through Alembic.
- After initialization, the only seeded account is the fixed administrator.
- Attempts to delete, disable, change role, or change email for the protected administrator fail.
- Password change for the protected administrator succeeds.