docs: add stage 1.6 enterprise governance plan
This commit is contained in:
@@ -0,0 +1,628 @@
|
|||||||
|
# Stage 1.6 Enterprise Governance Implementation Plan
|
||||||
|
|
||||||
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||||
|
|
||||||
|
**Goal:** Add a usable enterprise governance baseline with login, current user, users, user groups, roles, menus, API permission enforcement, permission-driven frontend navigation, and deployment bootstrap.
|
||||||
|
|
||||||
|
**Architecture:** Backend keeps Django's built-in `User`, `Group`, and `Permission` as the core auth model, adds `UserGroup` and `MenuItem` for product governance, exposes session-authenticated Django Ninja APIs, and enforces permissions in ticket/solution/audit/governance routers. Frontend wraps the Vite SPA in an auth provider, renders a shadcn-based Chinese login page for anonymous users, consumes backend menu data in `AppSidebar`, and adds shadcn-based system governance pages.
|
||||||
|
|
||||||
|
**Tech Stack:** Python 3.12, Django, Django Ninja, pytest, ruff, React, Vite, TypeScript, Tailwind CSS v3, shadcn/ui, Radix UI, npm.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Source Spec
|
||||||
|
|
||||||
|
- `docs/superpowers/specs/2026-07-01-stage-1-6-enterprise-governance-design.md`
|
||||||
|
|
||||||
|
## File Structure
|
||||||
|
|
||||||
|
Backend:
|
||||||
|
|
||||||
|
- Modify: `backend/config/settings/base.py`
|
||||||
|
- Modify: `backend/config/urls.py`
|
||||||
|
- Modify: `backend/apps/accounts/models.py`
|
||||||
|
- Modify: `backend/apps/accounts/permissions.py`
|
||||||
|
- Modify: `backend/apps/accounts/schemas.py`
|
||||||
|
- Modify: `backend/apps/accounts/api.py`
|
||||||
|
- Create: `backend/apps/accounts/auth.py`
|
||||||
|
- Create: `backend/apps/accounts/menus.py`
|
||||||
|
- Create: `backend/apps/accounts/bootstrap.py`
|
||||||
|
- Create: `backend/apps/accounts/management/commands/bootstrap_governance.py`
|
||||||
|
- Create: `backend/apps/accounts/migrations/0001_initial.py`
|
||||||
|
- Modify: `backend/apps/tickets/api.py`
|
||||||
|
- Modify: `backend/apps/solutions/api.py`
|
||||||
|
- Modify: `backend/apps/audit/api.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_auth_api.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_governance_api.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_permission_enforcement.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_bootstrap_governance.py`
|
||||||
|
- Modify: existing ticket/solution/audit tests to authenticate where protected endpoints are exercised.
|
||||||
|
|
||||||
|
Frontend:
|
||||||
|
|
||||||
|
- Modify: `frontend/src/lib/api.ts`
|
||||||
|
- Create: `frontend/src/features/auth/types.ts`
|
||||||
|
- Create: `frontend/src/features/auth/api.ts`
|
||||||
|
- Create: `frontend/src/features/auth/AuthProvider.tsx`
|
||||||
|
- Create: `frontend/src/features/auth/LoginPage.tsx`
|
||||||
|
- Modify: `frontend/src/app/App.tsx`
|
||||||
|
- Modify: `frontend/src/app/router.tsx`
|
||||||
|
- Modify: `frontend/src/app/layout/AppShell.tsx`
|
||||||
|
- Modify: `frontend/src/components/app/AppSidebar.tsx`
|
||||||
|
- Modify: `frontend/src/components/app/AppTopbar.tsx`
|
||||||
|
- Create: `frontend/src/features/system/api.ts`
|
||||||
|
- Create: `frontend/src/features/system/types.ts`
|
||||||
|
- Create: `frontend/src/features/system/SystemUsersPage.tsx`
|
||||||
|
- Create: `frontend/src/features/system/SystemUserGroupsPage.tsx`
|
||||||
|
- Create: `frontend/src/features/system/SystemRolesPage.tsx`
|
||||||
|
- Create: `frontend/src/features/system/SystemMenusPage.tsx`
|
||||||
|
- Create: `frontend/src/features/audit/AuditLogPage.tsx`
|
||||||
|
- Add shadcn components if missing: `checkbox`, `switch`, `alert`, `pagination`.
|
||||||
|
|
||||||
|
Deployment/docs:
|
||||||
|
|
||||||
|
- Modify: `.env.example`
|
||||||
|
- Create: `infra/backend-entrypoint.sh`
|
||||||
|
- Modify: `infra/backend.Dockerfile`
|
||||||
|
- Modify: `infra/docker-compose.yml`
|
||||||
|
- Modify: `docs/development/local-setup.md`
|
||||||
|
|
||||||
|
## Task 1: Backend Governance Models And Bootstrap
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/apps/accounts/models.py`
|
||||||
|
- Modify: `backend/apps/accounts/permissions.py`
|
||||||
|
- Create: `backend/apps/accounts/menus.py`
|
||||||
|
- Create: `backend/apps/accounts/bootstrap.py`
|
||||||
|
- Create: `backend/apps/accounts/management/commands/bootstrap_governance.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_bootstrap_governance.py`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write failing bootstrap test**
|
||||||
|
|
||||||
|
Create `backend/apps/accounts/tests/test_bootstrap_governance.py` with tests proving:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.auth.models import Group, Permission
|
||||||
|
from django.core.management import call_command
|
||||||
|
|
||||||
|
from apps.accounts.models import MenuItem, UserGroup
|
||||||
|
|
||||||
|
|
||||||
|
def test_bootstrap_governance_seeds_admin_roles_groups_permissions_and_menus(db, settings):
|
||||||
|
settings.DJANGO_SUPERUSER_USERNAME = "admin"
|
||||||
|
settings.DJANGO_SUPERUSER_PASSWORD = "admin12345"
|
||||||
|
settings.DJANGO_SUPERUSER_EMAIL = "admin@example.com"
|
||||||
|
|
||||||
|
call_command("bootstrap_governance")
|
||||||
|
call_command("bootstrap_governance")
|
||||||
|
|
||||||
|
user = get_user_model().objects.get(username="admin")
|
||||||
|
assert user.is_superuser is True
|
||||||
|
assert user.check_password("admin12345")
|
||||||
|
assert Group.objects.filter(name="系统管理员").exists()
|
||||||
|
assert Permission.objects.filter(codename="system.user.manage").exists()
|
||||||
|
assert UserGroup.objects.filter(code="default").exists()
|
||||||
|
assert MenuItem.objects.filter(code="system.users", title="用户管理").exists()
|
||||||
|
assert MenuItem.objects.filter(code="system.roles", permission_code="system.role.view").exists()
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run the test to verify RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests/test_bootstrap_governance.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: fails because `MenuItem`, `UserGroup`, and `bootstrap_governance` do not exist.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement models, catalog, menus, bootstrap command**
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
- `UserGroup` with `name`, `code`, `description`, `users`, `is_active`, timestamps.
|
||||||
|
- `MenuItem` with `code`, `title`, `path`, `icon`, `parent`, `sort_order`, `permission_code`, `is_visible`, `is_enabled`, timestamps.
|
||||||
|
- Chinese permission names and governance permission codes in `permissions.py`.
|
||||||
|
- Default role names in Chinese.
|
||||||
|
- Default menu catalog in `menus.py`.
|
||||||
|
- `bootstrap_governance()` service function and `bootstrap_governance` management command.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Make migrations and verify GREEN**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python manage.py makemigrations accounts
|
||||||
|
python -m pytest apps/accounts/tests/test_bootstrap_governance.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: test passes.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/apps/accounts
|
||||||
|
git commit -m "feat: add governance bootstrap models"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 2: Backend Auth And Current User APIs
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/config/settings/base.py`
|
||||||
|
- Modify: `backend/config/urls.py`
|
||||||
|
- Create: `backend/apps/accounts/auth.py`
|
||||||
|
- Modify: `backend/apps/accounts/schemas.py`
|
||||||
|
- Modify: `backend/apps/accounts/api.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_auth_api.py`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write failing auth API tests**
|
||||||
|
|
||||||
|
Create `backend/apps/accounts/tests/test_auth_api.py` with tests for:
|
||||||
|
|
||||||
|
```python
|
||||||
|
from django.contrib.auth import get_user_model
|
||||||
|
from django.contrib.auth.models import Group
|
||||||
|
from django.core.management import call_command
|
||||||
|
|
||||||
|
|
||||||
|
def test_login_me_and_logout_flow(client, db):
|
||||||
|
call_command("bootstrap_governance")
|
||||||
|
|
||||||
|
login = client.post(
|
||||||
|
"/api/accounts/auth/login",
|
||||||
|
data={"username": "admin", "password": "admin12345"},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
assert login.status_code == 200
|
||||||
|
assert login.json()["username"] == "admin"
|
||||||
|
|
||||||
|
me = client.get("/api/accounts/auth/me")
|
||||||
|
assert me.status_code == 200
|
||||||
|
payload = me.json()
|
||||||
|
assert payload["username"] == "admin"
|
||||||
|
assert "system.user.manage" in payload["permissions"]
|
||||||
|
assert any(menu["code"] == "system" for menu in payload["menus"])
|
||||||
|
|
||||||
|
logout = client.post("/api/accounts/auth/logout")
|
||||||
|
assert logout.status_code == 200
|
||||||
|
assert client.get("/api/accounts/auth/me").status_code == 401
|
||||||
|
|
||||||
|
|
||||||
|
def test_login_rejects_invalid_password(client, db):
|
||||||
|
get_user_model().objects.create_user(username="u", password="right")
|
||||||
|
|
||||||
|
response = client.post(
|
||||||
|
"/api/accounts/auth/login",
|
||||||
|
data={"username": "u", "password": "wrong"},
|
||||||
|
content_type="application/json",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert response.status_code == 401
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run tests to verify RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests/test_auth_api.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: fails because auth endpoints do not exist.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement session auth endpoints**
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
- `GET /api/accounts/auth/csrf`
|
||||||
|
- `POST /api/accounts/auth/login`
|
||||||
|
- `POST /api/accounts/auth/logout`
|
||||||
|
- `GET /api/accounts/auth/me`
|
||||||
|
- `CORS_ALLOW_CREDENTIALS = True`
|
||||||
|
- `CSRF_TRUSTED_ORIGINS` env parsing
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests/test_auth_api.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/config backend/apps/accounts
|
||||||
|
git commit -m "feat: add session auth api"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 3: Backend Governance CRUD APIs
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `backend/apps/accounts/schemas.py`
|
||||||
|
- Modify: `backend/apps/accounts/api.py`
|
||||||
|
- Create: `backend/apps/accounts/tests/test_governance_api.py`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write failing governance API tests**
|
||||||
|
|
||||||
|
Tests must cover:
|
||||||
|
|
||||||
|
- Admin lists users.
|
||||||
|
- Admin creates a user.
|
||||||
|
- Admin creates a user group and assigns members.
|
||||||
|
- Admin creates a role and assigns permissions.
|
||||||
|
- Admin lists menus and updates one menu permission.
|
||||||
|
- Anonymous calls to governance endpoints return 401.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run tests to verify RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests/test_governance_api.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: fails because CRUD endpoints do not exist.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement schemas and APIs**
|
||||||
|
|
||||||
|
Implement `/api/accounts` endpoints:
|
||||||
|
|
||||||
|
- `/users`
|
||||||
|
- `/users/{id}`
|
||||||
|
- `/users/{id}/reset-password`
|
||||||
|
- `/users/{id}/roles`
|
||||||
|
- `/users/{id}/user-groups`
|
||||||
|
- `/user-groups`
|
||||||
|
- `/user-groups/{id}`
|
||||||
|
- `/user-groups/{id}/members`
|
||||||
|
- `/roles`
|
||||||
|
- `/roles/{id}`
|
||||||
|
- `/roles/{id}/permissions`
|
||||||
|
- `/permissions`
|
||||||
|
- `/menus`
|
||||||
|
- `/menus/{id}`
|
||||||
|
- `/menus/reorder`
|
||||||
|
|
||||||
|
- [ ] **Step 4: Verify GREEN**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests/test_governance_api.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/apps/accounts
|
||||||
|
git commit -m "feat: add governance management api"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 4: Backend Permission Enforcement
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `backend/apps/accounts/auth.py` if not already created.
|
||||||
|
- Modify: `backend/apps/tickets/api.py`
|
||||||
|
- Modify: `backend/apps/solutions/api.py`
|
||||||
|
- Modify: `backend/apps/audit/api.py`
|
||||||
|
- Modify: existing ticket/solution/audit tests.
|
||||||
|
- Create: `backend/apps/accounts/tests/test_permission_enforcement.py`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Write failing permission enforcement tests**
|
||||||
|
|
||||||
|
Tests must prove:
|
||||||
|
|
||||||
|
- Anonymous ticket list is denied.
|
||||||
|
- User with `ticket.view` can list tickets.
|
||||||
|
- User without `ticket.create` cannot create tickets.
|
||||||
|
- User with `solution.view` can list solutions.
|
||||||
|
- User without `system.audit.view` cannot list audit logs.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Run tests to verify RED**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests/test_permission_enforcement.py -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: fails because current APIs are public.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement helpers and protect APIs**
|
||||||
|
|
||||||
|
Implement helpers:
|
||||||
|
|
||||||
|
```python
|
||||||
|
require_login(request)
|
||||||
|
require_permission(request, "ticket.view")
|
||||||
|
```
|
||||||
|
|
||||||
|
Update routers:
|
||||||
|
|
||||||
|
- `/api/system/health` remains public.
|
||||||
|
- tickets require ticket permissions.
|
||||||
|
- solutions require solution permissions.
|
||||||
|
- audit requires `system.audit.view`.
|
||||||
|
- governance endpoints use governance permissions.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Update existing tests to authenticate**
|
||||||
|
|
||||||
|
Existing ticket/solution/audit API tests should create a superuser or assign required permissions before calling protected endpoints.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Verify backend API tests**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest apps/accounts/tests apps/tickets/tests apps/solutions/tests apps/audit/tests -v
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: tests pass.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add backend/apps/accounts backend/apps/tickets backend/apps/solutions backend/apps/audit
|
||||||
|
git commit -m "feat: enforce api permissions"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 5: Frontend Auth Shell And Permission Menus
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `frontend/src/lib/api.ts`
|
||||||
|
- Create: `frontend/src/features/auth/types.ts`
|
||||||
|
- Create: `frontend/src/features/auth/api.ts`
|
||||||
|
- Create: `frontend/src/features/auth/AuthProvider.tsx`
|
||||||
|
- Create: `frontend/src/features/auth/LoginPage.tsx`
|
||||||
|
- Modify: `frontend/src/app/App.tsx`
|
||||||
|
- Modify: `frontend/src/app/layout/AppShell.tsx`
|
||||||
|
- Modify: `frontend/src/components/app/AppSidebar.tsx`
|
||||||
|
- Modify: `frontend/src/components/app/AppTopbar.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add missing shadcn components**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npx shadcn@latest add alert checkbox switch pagination --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
Then review generated files for Tailwind v3 compatibility.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Implement auth API client and provider**
|
||||||
|
|
||||||
|
Implement:
|
||||||
|
|
||||||
|
- CSRF fetch.
|
||||||
|
- login/logout/me calls.
|
||||||
|
- `AuthProvider`.
|
||||||
|
- `useAuth`.
|
||||||
|
- `apiRequest` sends `credentials: "include"` and CSRF token on unsafe methods.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Implement Chinese login page**
|
||||||
|
|
||||||
|
`LoginPage` uses shadcn `Card`, `Input`, `Label`, `Button`, and `Alert`.
|
||||||
|
|
||||||
|
Visible text must include:
|
||||||
|
|
||||||
|
```text
|
||||||
|
AI 工单平台
|
||||||
|
企业技术支持工作台
|
||||||
|
账号
|
||||||
|
密码
|
||||||
|
登录
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 4: Gate app by auth state**
|
||||||
|
|
||||||
|
Anonymous users see `LoginPage`. Authenticated users see `AppShell` and `Router`.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Make sidebar backend-driven**
|
||||||
|
|
||||||
|
`AppSidebar` receives menu data from auth context. Keep local icon mapping with lucide icons.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Run frontend verification**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm run typecheck
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: both pass.
|
||||||
|
|
||||||
|
- [ ] **Step 7: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src frontend/components.json frontend/package.json frontend/package-lock.json
|
||||||
|
git commit -m "feat: add frontend auth shell"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 6: Frontend System Governance Pages
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Create: `frontend/src/features/system/types.ts`
|
||||||
|
- Create: `frontend/src/features/system/api.ts`
|
||||||
|
- Create: `frontend/src/features/system/SystemUsersPage.tsx`
|
||||||
|
- Create: `frontend/src/features/system/SystemUserGroupsPage.tsx`
|
||||||
|
- Create: `frontend/src/features/system/SystemRolesPage.tsx`
|
||||||
|
- Create: `frontend/src/features/system/SystemMenusPage.tsx`
|
||||||
|
- Create: `frontend/src/features/audit/AuditLogPage.tsx`
|
||||||
|
- Modify: `frontend/src/app/router.tsx`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add system API client**
|
||||||
|
|
||||||
|
Create typed API functions for users, user groups, roles, permissions, menus, and audit logs.
|
||||||
|
|
||||||
|
- [ ] **Step 2: Add users page**
|
||||||
|
|
||||||
|
`#/system/users` shows table columns:
|
||||||
|
|
||||||
|
```text
|
||||||
|
用户名
|
||||||
|
显示名称
|
||||||
|
邮箱
|
||||||
|
状态
|
||||||
|
角色
|
||||||
|
用户组
|
||||||
|
操作
|
||||||
|
```
|
||||||
|
|
||||||
|
Use Dialog or Sheet for create/edit.
|
||||||
|
|
||||||
|
- [ ] **Step 3: Add user groups page**
|
||||||
|
|
||||||
|
`#/system/user-groups` shows Chinese table and create/edit dialog.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Add roles page**
|
||||||
|
|
||||||
|
`#/system/roles` shows role list and permission matrix grouped by module.
|
||||||
|
|
||||||
|
- [ ] **Step 5: Add menus page**
|
||||||
|
|
||||||
|
`#/system/menus` shows menu rows, required permission, visibility/enabled status, and edit dialog.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Add audit page**
|
||||||
|
|
||||||
|
`#/audit` shows existing operation logs in a Chinese table.
|
||||||
|
|
||||||
|
- [ ] **Step 7: Run frontend verification**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd frontend
|
||||||
|
npm run typecheck
|
||||||
|
npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: both pass.
|
||||||
|
|
||||||
|
- [ ] **Step 8: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add frontend/src/features/system frontend/src/features/audit frontend/src/app/router.tsx
|
||||||
|
git commit -m "feat: add system governance pages"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Task 7: Deployment Bootstrap And Final Verification
|
||||||
|
|
||||||
|
**Files:**
|
||||||
|
- Modify: `.env.example`
|
||||||
|
- Create: `infra/backend-entrypoint.sh`
|
||||||
|
- Modify: `infra/backend.Dockerfile`
|
||||||
|
- Modify: `infra/docker-compose.yml`
|
||||||
|
- Modify: `docs/development/local-setup.md`
|
||||||
|
|
||||||
|
- [ ] **Step 1: Add environment defaults**
|
||||||
|
|
||||||
|
Add admin bootstrap env vars to `.env.example`:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
DJANGO_SUPERUSER_USERNAME=admin
|
||||||
|
DJANGO_SUPERUSER_PASSWORD=admin12345
|
||||||
|
DJANGO_SUPERUSER_EMAIL=admin@example.com
|
||||||
|
CSRF_TRUSTED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 2: Add backend entrypoint**
|
||||||
|
|
||||||
|
Create `infra/backend-entrypoint.sh`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
python manage.py migrate
|
||||||
|
python manage.py bootstrap_governance
|
||||||
|
exec "$@"
|
||||||
|
```
|
||||||
|
|
||||||
|
- [ ] **Step 3: Wire backend Dockerfile and compose**
|
||||||
|
|
||||||
|
Backend service uses the entrypoint before running `runserver`. Worker can still start Celery after migrations are handled by backend.
|
||||||
|
|
||||||
|
- [ ] **Step 4: Update setup docs**
|
||||||
|
|
||||||
|
Document:
|
||||||
|
|
||||||
|
- fresh Docker startup
|
||||||
|
- default login account
|
||||||
|
- production warning to override password
|
||||||
|
|
||||||
|
- [ ] **Step 5: Run full verification**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd backend
|
||||||
|
python -m pytest -v
|
||||||
|
python -m ruff check .
|
||||||
|
|
||||||
|
cd ../frontend
|
||||||
|
npm run typecheck
|
||||||
|
npm run build
|
||||||
|
npx shadcn@latest info
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: all commands pass.
|
||||||
|
|
||||||
|
- [ ] **Step 6: Verify compose config**
|
||||||
|
|
||||||
|
Run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd infra
|
||||||
|
docker compose --env-file ../.env.example config
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected: config prints without errors. On this Windows host, use Docker Desktop's full docker executable path if `docker` is unavailable in shell PATH.
|
||||||
|
|
||||||
|
- [ ] **Step 7: Browser smoke test**
|
||||||
|
|
||||||
|
Start backend and frontend locally if feasible, then verify:
|
||||||
|
|
||||||
|
- anonymous user sees login page
|
||||||
|
- admin can log in
|
||||||
|
- sidebar shows system governance menus
|
||||||
|
- `#/system/users`, `#/system/roles`, `#/system/menus`, `#/audit` render Chinese UI
|
||||||
|
- logout returns to login
|
||||||
|
|
||||||
|
- [ ] **Step 8: Commit**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git add .env.example infra docs/development
|
||||||
|
git commit -m "feat: add governance deployment bootstrap"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Final Review Checklist
|
||||||
|
|
||||||
|
- [ ] `bootstrap_governance` is idempotent.
|
||||||
|
- [ ] Login/logout/me APIs work.
|
||||||
|
- [ ] Frontend anonymous state shows login only.
|
||||||
|
- [ ] Sidebar menus are backend-driven.
|
||||||
|
- [ ] User/user-group/role/menu pages use shadcn/App components.
|
||||||
|
- [ ] Ticket/solution/audit/governance APIs enforce permissions.
|
||||||
|
- [ ] Docker startup can migrate and seed governance.
|
||||||
|
- [ ] Backend tests pass.
|
||||||
|
- [ ] Backend ruff passes.
|
||||||
|
- [ ] Frontend typecheck passes.
|
||||||
|
- [ ] Frontend build passes.
|
||||||
|
- [ ] shadcn info still reports Vite/Tailwind v3 and installed components.
|
||||||
Reference in New Issue
Block a user