Commit Graph

11 Commits

Author SHA1 Message Date
f023192b74 T10.6 - deployment docs and env var reference describe Okta, not the never-shipped LDAP config
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>
2026-09-03 13:47:48 -07:00
7ef1fcdd96 Add Micron asset picker to work package creator
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.
2026-08-18 14:56:55 -05:00
26f4a9242a Entrypoint static variable removed to allow validation of scripting files before startup 2026-08-04 18:51:08 -07:00
39b48055ff Productionize WP Suite: auth, security hardening, sync, dashboard, PWA, email
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>
2026-07-15 17:51:15 -07:00
20afb0e565 Add secure username/password login portal
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>
2026-06-25 16:55:54 -05:00
66da5b708a Fix API DB connection: build URL from POSTGRES_* (auto-encode password)
The api crash-looped because DATABASE_URL had an un-encoded special-char
password (@/!), so SQLAlchemy parsed part of the password as the host
("...@db" → name resolution failure).

db.py now prefers building the connection from POSTGRES_USER/PASSWORD/DB via
SQLAlchemy URL.create(), which encodes the password automatically — any
password works with no manual escaping. DATABASE_URL remains an optional
override (still must be hand-encoded if used). docker-compose now passes the
POSTGRES_* vars to the api container; DEPLOYMENT.md updated (incl. a Portainer
env-vars note).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 15:24:17 -07:00
362aa633ed Build nginx image with static files baked in; remove host bind mounts 2026-06-15 14:57:54 -05:00
960b4a4b94 nginx updates 2026-06-15 14:42:25 -05:00
8598606165 fix docker compose 2026-06-15 14:31:56 -05:00
65996c2c0a troubleshoot docker-compose 2026-06-15 14:25:18 -05:00
b0a3d74412 Add docker compose 2026-06-15 14:02:52 -05:00