Commit Graph

5 Commits

Author SHA1 Message Date
Praxis CI e39521d51d feat(P01): SLICE-03 operator auth — argon2id + signed cookies + rate limit
- TASK-03-01 server/auth/passwords.py: argon2id via argon2-cffi
  PasswordHasher (t=3, m=64MiB, p=4 — exceeds OWASP). hash/verify/
  needs_rehash; verify returns False on mismatch (uniform 401 path).
- TASK-03-02 server/auth/cookies.py: get_session_middleware_kwargs()
  → Starlette SessionMiddleware (itsdangerous HMAC-SHA256, D-056).
  Cookie praxis_op, httpOnly, SameSite=strict, max_age=28800 (8h).
  PRAXIS_COOKIE_SECURE default true; false logs WARNING (R-AUTH-01).
  G-031 reframe documented: k-anon defense-in-depth is the PRIMARY
  mitigation (sniffed cookie → no PII); secure flag is SECONDARY.
- TASK-03-03 server/auth/rate_limit.py: slowapi Limiter (in-memory,
  D-041), 5/minute per IP on login. reset_login_rate_limit() helper.
- TASK-03-04 server/auth/dependencies.py + models.py: current_operator
  Depends — reads signed-cookie session, fetches operator from PgStore,
  401 on missing/invalid/inactive (clears session), 503 if no Postgres.
  Never trusts the client (D-057).
- TASK-03-05 server/auth/routes.py: APIRouter(prefix=/api/operator)
  with POST /login (rate-limited, rehash-on-login), POST /logout
  (auth-gated, clears session), GET /me (auth-gated, React guard).
- TASK-03-06 tests/test_auth.py: 18 unit tests (mocked PgStore) —
  passwords, cookie config, rate limit, 401/503 cases, login/logout/me,
  rehash-on-login.
- pyproject.toml: added itsdangerous>=2.1 (SessionMiddleware dep).

---ci---
project: praxis
phase: 1
milestone: v0.4
status: execute
persona: security-engineer
task: 03-01,03-02,03-03,03-04,03-05,03-06
requirements:
  covered: [REQ-AUTH-01, REQ-NFR-AUTH-01]
  grill:
    - G-031 (R-AUTH-01 reframe: k-anon primary, secure flag secondary)
---/ci---
2026-08-04 00:52:16 +00:00
Praxis CI 131545b70a feat(P01): SLICE-02 devops config + G-008 backup-restore drill
- TASK-02-01 .env.example: v0.4 operator vars (PRAXIS_PG_PASSWORD,
  PRAXIS_PG_DSN, PRAXIS_COOKIE_SECRET, PRAXIS_COOKIE_SECURE,
  PRAXIS_BOOTSTRAP_OPERATOR_USER/PASS, PRAXIS_VC_ISSUER_KEY,
  PRAXIS_ISSUER_URL) with documentation comments. PRAXIS_COOKIE_SECURE
  documents the G-031 reframe: k-anon defense-in-depth is the PRIMARY
  R-AUTH-01 mitigation (sniffed cookie leaks no PII); the secure flag is
  the SECONDARY mitigation. PROXMOX_MEMORY_MB default bumped 4096→6144.
- TASK-02-02 lxc-clone.sh: memory default 4096→6144 (REQ-NFR-MT-01 —
  Postgres ~400MB + praxis ~500MB + Docker ~200MB + build headroom ~1GB).
- TASK-02-03 scripts/backup-pg.sh: POSIX-sh nightly cron script,
  pg_dump -Fc to /backups/praxis-<dow>.dump (rolling 7-file, D-055),
  with restore-drill documentation in comments.
- G-008 tests/test_backup_restore.py: backup-restore drill — seeds all 5
  operator-tier tables, pg_dump, drop schema, pg_restore --clean --if-exists,
  verify 5 tables + row counts match. Skips if PRAXIS_PG_DSN unset.

---ci---
project: praxis
phase: 1
milestone: v0.4
status: execute
persona: devops-engineer
task: 02-01,02-02,02-03,G-008
requirements:
  covered: [REQ-NFR-MT-01]
  grill:
    - G-008 (backup-restore drill)
---/ci---
2026-08-04 00:48:14 +00:00
Praxis CI b0cb6280d7 feat(P01): TASK-01-04..07 Postgres DB foundation — migrate + schema + PgStore + tests
- db/pg_migrate.py: asyncpg migration runner with _pg_migrations tracking
  table, ordered .sql, transactional, 3x retry on connection failure (R-MT-02).
- db/pg_schema.sql + db/pg_migrations/0001_operator_tier.sql: 5 operator-tier
  tables (operators, issued_credentials, mastery_gate_events,
  cohort_aggregates, issuer_keys) using gen_random_uuid() (PG16 core, no
  extension). cohort_aggregates is a plain table, NOT partitioned (D-050).
- db/pg_store.py: PgStore class implementing the IssuerKeyStore protocol
  (init/get_active/get_public_key_row/set_superseded) plus operator CRUD,
  cohort aggregate read/write, credential methods, gate events.
  get_public_key_row queries by id (not status) → finds superseded keys
  (R-VC-MIG-01 verification fallback, D-051). No cross-DB FKs (D-031).
- tests/test_pg_store.py: 13 integration tests (skip if PRAXIS_PG_DSN unset).

---ci---
project: praxis
phase: 1
milestone: v0.4
status: execute
persona: data-engineer
task: 01-04,01-05,01-06,01-07
requirements:
  covered: [REQ-MT-01, REQ-NFR-MT-01, REQ-MT-02]
---/ci---
2026-08-04 00:47:14 +00:00
Praxis CI 813bd586d6 docs(milestone): merge v0.3-mastery-scoring → main
v0.3 milestone merged to main. Mastery scoring + competency rubrics +
verifiable credentials (formative-tier) shipped. 13/13 REQ-IDs covered.
Next milestone: v0.4 (operator tier — cohort dashboard + auth + Postgres).

---ci---
project: praxis
phase: 2
milestone: v0.3
status: complete
milestone_complete: true
milestone_merged_to_main: true
---/ci---
2026-08-04 00:14:59 +00:00
Praxis CI fbd6602814 docs(milestone): complete v0.1 foundation
---ci---
phase: 0
milestone: v0.1
status: complete
---/ci---
2026-08-01 13:32:48 +00:00