SOP config (Governance step) now sets project discipline policy:
- disciplines list, discipline strategy (single/multi/planner-choice),
letter instance-suffix style, and a max-hours split threshold.
WP Creator becomes discipline-aware:
- discipline picker; selecting 2+ turns the flat scope into per-discipline
scope sections, each with its own status (rolls up to least-advanced).
- "Split by Discipline" turns a multi-discipline WP into WP01A/B/C instances
linked to a kept master (instanceOf/parentNumber/split/children).
- est-hours warning against the SOP split threshold.
New WP Dashboard (header button, home card, ?view=dashboard deep-link):
metrics, status/discipline breakdowns, a gating panel, and a filterable
board with view/edit/issue. Reads localStorage via an API-ready WPData
adapter; masters excluded from counts.
Backend: POST /api/wps/{id}/issue (enforces the constraint gate),
POST /api/wps/{id}/status, GET /api/wps/metrics; work_packages gains
parent_id + issued_at.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Work Package Suite API
A small Python (FastAPI) service that stores project SOPs, Work Packages,
and comments in PostgreSQL. NGINX serves the static site and proxies /api/
to this service.
browser → NGINX ──serves──> static site (index.html, …)
└─proxy /api/─> this API (uvicorn/gunicorn :8000) → PostgreSQL
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/health |
liveness check |
| POST | /api/sops |
create/update a SOP (upsert by id) |
| GET | /api/sops |
list SOP summaries |
| GET | /api/sops/latest?complete=true |
most recent (complete) SOP |
| GET | /api/sops/{id} |
full SOP document |
| DELETE | /api/sops/{id} |
delete a SOP |
| POST | /api/wps |
create/update a Work Package (upsert by id) |
| GET | /api/wps?sop_id=… |
list WPs (optionally for one SOP) |
| GET | /api/wps/{id} |
full WP document |
| DELETE | /api/wps/{id} |
delete a WP |
| POST | /api/comments (and /api/feedback) |
add a comment |
| GET | /api/comments?source=&sop_id=&wp_id=&step= |
list comments |
Interactive docs once running: /api/docs.
The full client document is stored in each row's data (JSON) column; common
fields (name, number, status, …) are promoted to columns for listing/filtering.
Local dev
cd server
python -m venv .venv && . .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
# No DATABASE_URL → uses a local sqlite file, so you can start immediately:
uvicorn server.app:app --reload --port 8000 # run from the PROJECT ROOT
Then open http://localhost:8000/api/docs.
Run uvicorn/gunicorn from the project root (the folder that contains the
server/directory), because the import path isserver.app:app.
PostgreSQL setup (production)
CREATE DATABASE wpsuite;
CREATE USER wpsuite WITH PASSWORD 'CHANGE_ME';
GRANT ALL PRIVILEGES ON DATABASE wpsuite TO wpsuite;
Tables are created automatically on first startup. (For future schema changes, introduce Alembic migrations rather than editing tables by hand.)
Run in production (gunicorn + systemd)
/etc/systemd/system/wp-suite-api.service:
[Unit]
Description=Work Package Suite API
After=network.target
[Service]
User=www-data
WorkingDirectory=/opt/wp-suite
Environment="DATABASE_URL=postgresql+psycopg://wpsuite:CHANGE_ME@localhost:5432/wpsuite"
ExecStart=/opt/wp-suite/.venv/bin/gunicorn -k uvicorn.workers.UvicornWorker -b 127.0.0.1:8000 server.app:app
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now wp-suite-api
NGINX already proxies /api/ to 127.0.0.1:8000 (see nginx-wp-suite.conf).
Quick test
curl -X POST http://127.0.0.1:8000/api/comments \
-H 'Content-Type: application/json' \
-d '{"type":"home_feedback","name":"Test","text":"hello"}'
curl http://127.0.0.1:8000/api/comments