- server/: FastAPI app with SQLAlchemy models for sops, work_packages, comments - Endpoints for SOP/WP upsert+list+get+delete and comment create+list; /api/feedback kept as an alias so the existing client keeps working - Portable across engines (PostgreSQL prod, SQLite dev fallback) - requirements.txt, .env.example, and server/README.md (Postgres + systemd) - NGINX now proxies /api/ to the API (replaces the Power Automate hop; comments persist to SQL) - Rewrite DEPLOYMENT.md for the API + database architecture - Add .gitignore for venv/.env/sqlite Phase 2 (wire the client apps to the API) is next. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
82 lines
3.2 KiB
Markdown
82 lines
3.2 KiB
Markdown
# Deployment
|
|
|
|
The Work Package Suite has two parts:
|
|
|
|
- a **static front end** (plain HTML/CSS/JS — no build step), and
|
|
- a **Python API** (FastAPI) backed by **PostgreSQL**, which stores the project
|
|
SOPs, Work Packages, and comments so they are shared across users instead of
|
|
living in each person's browser.
|
|
|
|
```
|
|
browser → NGINX ──serves──> static site (index.html, …)
|
|
└─proxy /api/─> Python API (uvicorn/gunicorn :8000) → PostgreSQL
|
|
```
|
|
|
|
Everything runs inside your firewall; the app makes **no outbound internet
|
|
calls** (the logo and scripts are local and the old Google-Fonts dependency was
|
|
removed).
|
|
|
|
## 1. Front end (NGINX)
|
|
|
|
Copy the project files to a web root and serve them over HTTPS. The provided
|
|
[`nginx-wp-suite.conf`](nginx-wp-suite.conf) serves the static files and proxies
|
|
`/api/` to the Python API. Set `server_name`, the `ssl_certificate` paths, and
|
|
`root`, then `sudo nginx -t && sudo systemctl reload nginx`.
|
|
|
|
Serving over real HTTP(S) (not `file://`) also makes the embedded Work Package
|
|
Creator (`<iframe>`) and any browser-side caching behave reliably.
|
|
|
|
## 2. API + database
|
|
|
|
Full setup — PostgreSQL, the systemd service, and the endpoint reference — is in
|
|
[`server/README.md`](server/README.md). In short:
|
|
|
|
1. Create the `wpsuite` Postgres database/user.
|
|
2. `pip install -r server/requirements.txt` into a venv.
|
|
3. Set `DATABASE_URL` and run the API as a systemd service on `127.0.0.1:8000`.
|
|
4. Tables are created automatically on first start.
|
|
|
|
Interactive API docs are at `/api/docs` once it's running.
|
|
|
|
## 3. Comments / feedback
|
|
|
|
Every feedback surface (home *Leave Feedback*, SOP *Step Comments*, WP *Comments*)
|
|
posts to `/api/feedback`, which the API stores in the `comments` table. The
|
|
**Export / Import** buttons remain as an offline fallback — a reviewer can export
|
|
a JSON file and someone can import/merge it — but with the API running, comments
|
|
are collected centrally with no manual steps.
|
|
|
|
> The earlier Power Automate route is **no longer needed** — comments go straight
|
|
> to Postgres. If you still want a Power App view, point a Power App at the
|
|
> Postgres `comments` table via the on-prem data gateway, or have a flow read the
|
|
> table; no change to this app is required.
|
|
|
|
### Comment payload shape
|
|
|
|
```json
|
|
{
|
|
"app": "Work Package Suite",
|
|
"page": "/work-package-suite.html",
|
|
"submittedAt": "2026-06-15T18:20:00.000Z",
|
|
"type": "sop_step_comment",
|
|
"name": "J. Park",
|
|
"text": "Consider adding a fiber WP type",
|
|
"step": 4
|
|
}
|
|
```
|
|
|
|
`type` is one of `home_feedback`, `sop_step_comment`, or `wp_review_comment`. The
|
|
API maps `name`/`author` → the comment author and keeps any extra fields in the
|
|
row's `extra` JSON column.
|
|
|
|
## Data model (PostgreSQL)
|
|
|
|
| Table | Holds | Key columns |
|
|
|-------|-------|-------------|
|
|
| `sops` | project SOP baselines | `name`, `number`, `complete`, `data` (full SOP JSON) |
|
|
| `work_packages` | individual IWPs | `sop_id`, `number`, `subject`, `type`, `status`, `data` (full WP JSON) |
|
|
| `comments` | feedback from any page | `source`, `sop_id`, `wp_id`, `step`, `author`, `text` |
|
|
|
|
The complete client document is stored verbatim in each row's `data` column;
|
|
frequently-listed fields are promoted to real columns for filtering.
|