feat: 统一生产初始化流程并保护系统管理员
This commit is contained in:
@@ -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.
|
||||
@@ -0,0 +1,169 @@
|
||||
# Production Initialization Implementation Plan
|
||||
|
||||
> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
|
||||
|
||||
**Goal:** Make production initialization use Alembic as the only schema source and seed exactly one protected administrator account with no demo data.
|
||||
|
||||
**Architecture:** A dedicated initialization entrypoint will run migrations and seed the protected administrator. The runtime backend container will stop relying on production startup side effects for database structure, and the user-management API will enforce immutability rules for the protected administrator account.
|
||||
|
||||
**Tech Stack:** FastAPI, SQLAlchemy AsyncSession, Alembic, PostgreSQL, Docker Compose, pytest
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Add Protected Admin Constants And Seed Logic
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/app/crud/user.py`
|
||||
- Create or Modify: `backend/app/core/config.py`
|
||||
- Test: `backend/tests/...` for protected admin behavior
|
||||
|
||||
**Step 1: Write a failing test**
|
||||
|
||||
Add a backend test that proves the seed helper creates `admin@huapont.cn` with `ADMIN` role and `ACTIVE` status when the account is missing.
|
||||
|
||||
**Step 2: Run test to verify it fails**
|
||||
|
||||
Run: `cd backend && pytest <new-test-path> -v`
|
||||
Expected: FAIL because the current seed helper still creates `admin@example.com`.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Introduce protected admin constants and replace the current seed helper with logic that ensures the fixed admin exists with the required immutable identity fields while allowing password updates through normal user flows.
|
||||
|
||||
**Step 4: Run test to verify it passes**
|
||||
|
||||
Run: `cd backend && pytest <new-test-path> -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add backend/app/crud/user.py backend/app/core/config.py <test-path>
|
||||
git commit -m "feat: seed protected production admin"
|
||||
```
|
||||
|
||||
### Task 2: Block Destructive Changes To The Protected Admin
|
||||
|
||||
**Files:**
|
||||
- Modify: `backend/app/api/v1/users.py`
|
||||
- Modify: `backend/app/crud/user.py` if helper methods are needed
|
||||
- Test: `backend/tests/...` covering update/delete constraints
|
||||
|
||||
**Step 1: Write failing tests**
|
||||
|
||||
Add tests showing the protected admin cannot be deleted, disabled, downgraded from `ADMIN`, or have its email changed, while password change remains allowed.
|
||||
|
||||
**Step 2: Run tests to verify they fail**
|
||||
|
||||
Run: `cd backend && pytest <user-api-test-path> -v`
|
||||
Expected: FAIL because the current API only guarantees at least one admin remains.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Add explicit checks in the user update and delete endpoints so the protected admin is immutable for identity and role/status fields but still allows password updates.
|
||||
|
||||
**Step 4: Run tests to verify they pass**
|
||||
|
||||
Run: `cd backend && pytest <user-api-test-path> -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add backend/app/api/v1/users.py backend/app/crud/user.py <test-path>
|
||||
git commit -m "feat: protect system admin account"
|
||||
```
|
||||
|
||||
### Task 3: Add Production Initialization Entrypoint
|
||||
|
||||
**Files:**
|
||||
- Create: `backend/scripts/init_production.py`
|
||||
- Modify: `backend/app/main.py`
|
||||
- Modify: `backend/Dockerfile` if command support is needed
|
||||
- Test: script-level verification or targeted unit test
|
||||
|
||||
**Step 1: Write a failing verification**
|
||||
|
||||
Define a verification path that proves the initialization script performs migrations and then seeds the protected admin.
|
||||
|
||||
**Step 2: Run verification to confirm current flow is insufficient**
|
||||
|
||||
Run: `cd backend && python scripts/init_production.py --help` or targeted tests
|
||||
Expected: FAIL because no dedicated production init command exists.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Create a one-shot initialization script that runs `alembic upgrade head` and then invokes the protected-admin seed helper. Remove production reliance on app-startup schema or admin side effects.
|
||||
|
||||
**Step 4: Run verification to confirm it passes**
|
||||
|
||||
Run: `cd backend && python scripts/init_production.py --help` and relevant tests
|
||||
Expected: PASS
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add backend/scripts/init_production.py backend/app/main.py backend/Dockerfile
|
||||
git commit -m "feat: add production init entrypoint"
|
||||
```
|
||||
|
||||
### Task 4: Align Compose And Docs With The New Production Flow
|
||||
|
||||
**Files:**
|
||||
- Modify: `docker-compose.yaml`
|
||||
- Modify: `README.md`
|
||||
- Modify: `docs/release-checklist.md`
|
||||
- Optionally modify: `database/init.sql`
|
||||
|
||||
**Step 1: Write failing verification**
|
||||
|
||||
Document or verify that the current compose/release instructions still imply schema bootstrap from the wrong place.
|
||||
|
||||
**Step 2: Run verification to confirm mismatch**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: configuration still lacks an explicit production init workflow.
|
||||
|
||||
**Step 3: Write minimal implementation**
|
||||
|
||||
Add a one-shot compose service or documented command for production initialization. Update docs so production deploy always runs migrations and protected-admin seeding explicitly. Remove `database/init.sql` from the production path or reduce it so it is no longer treated as the schema source of truth.
|
||||
|
||||
**Step 4: Run verification to confirm it passes**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: PASS with the new init workflow represented in configuration or documentation.
|
||||
|
||||
**Step 5: Commit**
|
||||
|
||||
```bash
|
||||
git add docker-compose.yaml README.md docs/release-checklist.md database/init.sql
|
||||
git commit -m "docs: define production database init flow"
|
||||
```
|
||||
|
||||
### Task 5: End-To-End Verification
|
||||
|
||||
**Files:**
|
||||
- Verify only
|
||||
|
||||
**Step 1: Validate backend tests**
|
||||
|
||||
Run: `cd backend && pytest <affected-test-selection> -v`
|
||||
Expected: PASS
|
||||
|
||||
**Step 2: Validate compose configuration**
|
||||
|
||||
Run: `docker compose config`
|
||||
Expected: PASS
|
||||
|
||||
**Step 3: Validate production init command**
|
||||
|
||||
Run: `docker compose run --rm backend python scripts/init_production.py`
|
||||
Expected: migrations run successfully and the protected admin is ensured.
|
||||
|
||||
**Step 4: Validate service health**
|
||||
|
||||
Run: `docker compose up -d`
|
||||
Expected: `db`, `backend`, and `nginx` start successfully.
|
||||
|
||||
Run: `curl -i http://127.0.0.1/health`
|
||||
Expected: `200 OK`
|
||||
@@ -1,7 +1,7 @@
|
||||
# Release Checklist(立项配置)
|
||||
|
||||
## 1. 构建与迁移
|
||||
- [ ] `cd backend && docker compose run --rm backend python -m alembic upgrade head`
|
||||
- [ ] `docker compose run --rm backend-init`
|
||||
- [ ] `cd backend && python3 -m compileall app scripts`
|
||||
- [ ] `cd frontend && npm run build`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user