D13 never shipped, so DEPLOYMENT.md, server/.env.example and server/README.md
still described the original local-password system as of this task starting -
POST /api/auth/login, bcrypt password_hash, create-admin with a prompted
password, self-service reset-password email flow, AUTH_RESET_MINUTES /
AUTH_RESET_COOLDOWN_SECONDS. All of that is gone as of T10.4; these three files
now describe what actually runs.
server/.env.example and DEPLOYMENT.md's env block both gain the five OKTA_*
variables (ISSUER, CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, IDENTITY_CLAIM),
explained the same way AUTH_SECRET_KEY already was - what it does, where to
get it, what happens if it's missing.
Also updated, not originally named in T10.6's bullet but required for the
documented vars to actually reach a running container: docker-compose.yml's
api service sets environment: as an explicit allowlist, not env_file, so the
four new OKTA_* entries had to be added there too or .env would document
something that silently does nothing. OKTA_IDENTITY_CLAIM specifically is NOT
${OKTA_IDENTITY_CLAIM:-} - compose setting an env var to an empty string is
not the same as leaving it unset, and server/okta_auth.py's own default
(preferred_username) only kicks in when the var is truly unset. Mirrored the
same default in the compose file instead, or every deployment that leaves the
optional line commented out in .env would 503 on every sign-in looking for a
claim literally named "".
server/README.md: replaced the login-portal section with the Okta flow
(access gating is Okta's job, not this app's - roles/authorization stay
local), replaced "create the first admin" with the promote-not-create
bootstrap path (D16) and its no-break-glass posture, replaced the curl-based
login example in Quick Test with a pointer to smoketest.py's own
session-minting technique (there is nothing left to curl - Okta requires a
real browser).
DEPLOYMENT.md: same treatment for its own copies of the env block, the
Portainer var list, the users table's password_hash column, the auth
endpoints summary, the smoke-test walkthrough (WP_SMOKE_USER only, must run
inside the api container or local dev sharing AUTH_SECRET_KEY/DATABASE_URL -
no longer targetable from an arbitrary remote workstation), the entire
"Self-service password reset" section (replaced with "Sign-in and admin
bootstrap (Okta)"), and the project_super_user role description / exclusive-
scope bullet, both of which named "reset passwords" as something that no
longer exists.
Left alone, logged rather than fixed here per CLAUDE.md scope discipline:
- users.failed_attempts / locked_until columns are still in the schema and
still reset to 0/None on every Okta sign-in, but nothing increments them
anymore since local login() is gone - vestigial, not documented as active
lockout behavior in either doc now, but not migrated away either.
- server/README.md's "Production - Docker Compose" section (### 1-5) is a
self-contained alternate quickstart that already duplicated and diverged
from the real root docker-compose.yml before this task; it uses env_file
rather than an explicit allowlist so it isn't broken by this change, but
it's still a second source of truth nobody asked this task to reconcile.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds an optional read-only Micron asset catalog lookup for the WP creator, with searchable asset IDs, CSV import, and graceful fallback to manual asset entry when the catalog is absent or unreachable. This includes the backend /api/assets endpoint, SQL Server connector configuration, Docker network changes for outbound access, and UI updates/documentation to make the catalog read-only and clearly distinguish Micron-vetted assets from manual entries.
Brings the Work Package Suite from a browser-local prototype to a
multi-tenant, SQL-backed deployment hardened for customer IP.
Auth & access control
- Local username/password login (bcrypt + JWT in an HttpOnly cookie),
admin-managed users, per-project membership, and project-scoped API access.
- Admin console: change user roles, view the audit trail, manage settings.
Security hardening
- CSP / HSTS / X-Frame-Options / nosniff headers in nginx; Secure cookie via
X-Forwarded-Proto; CSRF Origin check; attribute-safe output escaping.
- Login lockout, token_version session revocation, stronger password policy,
fail-closed secret loading, encrypted (AES-256) database backups.
Persistence & schema
- SOPs and Work Packages are now DB-backed and shared across users, written
through a durable client sync outbox that queues offline edits.
- Alembic migrations applied automatically on container start.
New capabilities
- Phase 2 dashboard (progress, gating, pagination, archive).
- Phase 3 PWA "Field View" with offline caching and auth fallback.
- WP owner assignment with OPTIONAL email notifications, OFF by default and
toggled from the admin console. SMTP password is read only from the
SMTP_PASSWORD env var (never stored); emails carry a WP number + deep link,
never customer IP.
Also: IBM Carbon restyle, Help section, and DEPLOYMENT.md brought up to date.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Gate the suite behind a self-contained login (no external IdP):
- User model with bcrypt-hashed passwords; admin/user roles
- /api/auth endpoints: login, logout, me, change-password, and
admin-only user management (list/create/delete/reset/enable)
- Stateless JWT session in an HttpOnly, SameSite=Lax, auto-Secure
cookie; middleware refuses every /api data route without a session
- login.html + auth-guard.js: login page and per-page guard with a
top-right "name / Admin / Sign out" pill
- Admin Console now gated on admin role (passphrase gate removed) with
a User administration card
- manage_users.py CLI to bootstrap the first admin
- Rebuilt help.js into a searchable, multi-topic help center
- Local-dev convenience: app serves html/ so the site + API share one
origin under uvicorn (inactive in the prod container)
- Docs/env: AUTH_SECRET_KEY, requirements (bcrypt, PyJWT), README
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 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>