curo1305
41d81c089f
feat(09-01): implement GET /api/admin/overview endpoint — ADMIN-11
...
- New backend/api/admin/overview.py: aggregate stats (user_count,
total_storage_bytes, doc_status) + last 10 audit entries in one payload
- Sub-router carries NO prefix (parent __init__.py carries /api/admin)
- Reuses _build_filtered_query_with_handles + _audit_to_dict_with_handles
from api.audit — no new serializer or query logic
- Registered overview_router on admin parent router in __init__.py
- All 8 ADMIN-11 tests pass; existing admin and audit suites stay green
2026-06-12 15:50:38 +02:00
curo1305
4caeed2d22
test(09-01): add failing xfail tests for ADMIN-11 overview endpoint
...
- 8 xfail tests covering auth guards, aggregate stats, and sensitive field scan
- Tests will become real assertions once overview.py is implemented in Task 2
2026-06-12 15:47:18 +02:00
curo1305 and Claude Sonnet 4.6
2fd7591eac
docs(09): fix plan checker warnings — ORDER BY desc, closed tag, resolved marker
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 15:40:31 +02:00
curo1305 and Claude Sonnet 4.6
ba30ada87a
docs(09): create phase 9 plan — Admin Panel Rearchitecture
...
5 plans across 4 waves covering ADMIN-08..12, CODE-06, CODE-09:
- 09-01 (W1): backend GET /api/admin/overview + 8 ADMIN-11 tests
- 09-02 (W1): AdminLayout + AdminSidebar + AdminOverviewView + getAdminOverview API
- 09-03 (W2): extract 4 admin tab components to standalone views
- 09-04 (W3): nested /admin route + to.matched.some guard + D-08/D-09/D-10 redirects + Tailwind safelist (sky+amber) + login redirect + delete AdminView/tabs
- 09-05 (W4): CODE-09 comment purge for Phase 9 + retroactive Phase 8 backend sub-packages + human UAT checkpoint
All locked decisions D-01..D-16 mapped to tasks; safelist corrected to include sky (OneDrive) and amber (audit badges) per RESEARCH.md Pattern 7.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 15:34:31 +02:00
curo1305 and Claude Sonnet 4.6
373e009ed8
docs(09): research phase — admin panel rearchitecture
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 13:35:34 +02:00
curo1305
e5bed6e219
docs(state): record phase 9 context session
2026-06-12 13:23:29 +02:00
curo1305
6721e60166
docs(09): capture phase context
2026-06-12 13:23:25 +02:00
curo1305 and Claude Sonnet 4.6
a42f0ed623
test(08): UAT complete — 7/7 passed, phase 8 marked complete
...
All 7 UAT tests passed (cold start, auth, documents, admin, cloud storage,
session revocation, Vite 6 build). Security gate: 0 threats open. Phase 8
transition complete — ROADMAP.md updated, PROJECT.md evolved with Phase 8
decisions, stale handoff deleted. Next: Phase 9 (Admin Panel Rearchitecture).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 11:28:56 +02:00
curo1305 and Claude Sonnet 4.6
ee3d2d2d3d
docs(phase-08): mark VALIDATION.md complete — Nyquist-compliant 9/9
...
Audit confirmed all phase-8 requirements are COVERED:
- CR-01/02/03: session revocation tests promoted from stubs → 3 passing
- CODE-01/02/03: route regression — 58 passed, 4 xfailed
- CODE-04: frontend smoke — 136/136 passed
- CODE-08: single CloudConnectionOut definition confirmed
- PERF-01: npm packages verified
Full suite: 405 passed, 6 skipped, 7 xfailed (1 pre-existing env gap: no local python-docx)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 11:24:49 +02:00
curo1305 and Claude Sonnet 4.6
cd4f372e46
docs(phase-08): add security threat verification — all 45 threats closed
...
Register sourced from 8 PLAN.md threat_model blocks (register_authored_at_plan_time: true).
36 mitigate threats verified CLOSED by gsd-security-auditor. 9 accepted risks documented.
threats_open: 0 — phase advancement unblocked.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 11:18:16 +02:00
curo1305 and Claude Sonnet 4.6
ace8899211
test(08): complete UAT — 7/7 passed, all regression verified
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 11:07:24 +02:00
curo1305 and Claude Sonnet 4.6
6bda133c81
chore(08-08): PERF-01 packages + Vite 6 upgrade + pin requirements.txt
...
- Upgraded vite 5.4.21 → 6.4.3 (fixes CVE-2026-39363, CVE-2026-39364)
- Upgraded @vitejs/plugin-vue 5.2.4 → 6.0.7 (Vite 6 peer dep)
- Installed @vueuse/core@14.3.0, @vueuse/integrations@14.3.0,
sortablejs@1.15 .7, @tailwindcss/forms@0.5.11,
rollup-plugin-visualizer@7.0.1, @types/sortablejs@1.15 .9
- Wired @tailwindcss/forms plugin in tailwind.config.js (VISUAL-02 ready)
- Pinned backend/requirements.txt to exact == versions per D-17 (32 packages)
- Frontend: 136/136 tests pass on Vite 6; 0 npm audit vulnerabilities
- Backend: 408 passed, 4 skipped, 7 xfailed (baseline 405+1)
- Phase 8 complete (8/8 plans)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 10:54:34 +02:00
curo1305 and Claude Sonnet 4.6
8828871ecd
wip: phase-08 paused at plan 08/08 — wave 2 complete, 08-08 pending npm verification
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 10:34:41 +02:00
curo1305 and Claude Sonnet 4.6
9a3ce6ef39
docs(08-04/05/06): add plan summaries — wave 2 backend decomposition complete
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 10:29:40 +02:00
curo1305 and Claude Sonnet 4.6
81337bd9e3
feat(08-05): decompose documents API monolith into documents/ package — CODE-02 CODE-08
...
- upload.py: request_upload_url, upload_document, confirm_upload (3 routes)
- crud.py: list_documents, get_document, patch_document, delete_document, classify_document (5 routes)
- content.py: stream_document_content + _parse_range (1 route)
- shared.py: _CLOUD_PROVIDERS, UploadUrlRequest, DocumentPatch (single definitions)
- __init__.py: router aggregator prefix=/api/documents, 9 routes total
- documents.py monolith deleted; all URL paths unchanged
- list_documents registered on parent router to avoid FastAPI empty-path/prefix check
- get_storage_backend_for_document re-exported for test monkeypatching compatibility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 10:27:48 +02:00
curo1305 and Claude Sonnet 4.6
f01fb0e6d5
feat(08-04): delete admin.py monolith after URL regression — CODE-01 CODE-08
...
Task 3: 54 admin+cloud+ai-config tests pass with package; admin.py and
admin_OLD_REMOVE_IN_TASK_3.py removed. admin/ package is the sole definition.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-12 10:16:38 +02:00
curo1305
7e99b6ecc1
docs(08-07): add plan summary — CODE-04 CODE-08 frontend api decomposition complete
2026-06-10 18:45:56 +02:00
curo1305
02bf04cc63
feat(08-07): decompose frontend api/client.js into domain modules + utils — CODE-04 CODE-08
...
- Rewrite client.js as 20-line barrel re-export (was 636 lines)
- All 35+ consumer files continue to resolve named exports unchanged
- Fix pre-existing bug: testAiConnection was POST but tests expected GET with query params
- All 136 frontend tests pass; production build succeeds
2026-06-10 18:43:41 +02:00
curo1305
3ec198768d
feat(08-04): create backend/api/admin/ package — users, quotas, ai, shared, init
...
- users.py: list_users, create_user, update_user_status, initiate_password_reset,
update_ai_config, delete_user, create_system_topic (7 routes)
- quotas.py: get_user_quota, update_user_quota (2 routes)
- ai.py: get_ai_config_models, test_ai_connection, get_ai_config,
update_system_ai_config (4 routes); validate_provider_id call-through (D-11)
- shared.py: _user_to_dict helper (T-02-27 / SEC-07 field whitelist)
- __init__.py: router aggregator with prefix=/api/admin; 13 routes total
- admin.py monolith renamed to admin_OLD_REMOVE_IN_TASK_3.py (deleted in task 3)
- All sub-routers have NO prefix (D-04)
- All handlers inject Depends(get_current_admin) (T-08-04-01)
2026-06-10 18:43:01 +02:00
curo1305
5117e2542a
feat(08-06): create backend/api/auth/ package — Task 1
...
- Create api/auth/shared.py: limiter, all Pydantic request models, _set_refresh_cookie, _user_dict
- Create api/auth/tokens.py: register, login, refresh, logout, logout-all, me, quota, preferences handlers
- Create api/auth/totp.py: totp/setup, totp/enable, totp DELETE handlers (CR-02, CR-03 preserved)
- Create api/auth/password.py: change-password, password-reset, password-reset/confirm handlers (CR-01 preserved)
- Create api/auth/__init__.py: router aggregator with prefix=/api/auth; re-exports limiter
- Rename auth.py monolith to auth_OLD_REMOVE_IN_TASK_2.py (deleted in Task 2 after tests pass)
- All 15 routes confirmed; limiter re-export verified; skip_token_hash calls preserved verbatim
2026-06-10 18:42:27 +02:00
curo1305
a895b1812f
feat(08-07): create domain modules admin.js, folders.js, shares.js, cloud.js — CODE-04
...
- admin.js: 17 functions; adminExportAuditLogCsv + adminDownloadDailyExport use fetchWithRetry
- folders.js: 6 functions — import request from utils.js
- shares.js: 5 functions — import request from utils.js
- cloud.js: 7 functions including initiateOAuth — import request from utils.js
- Blob-download retry boilerplate eliminated from admin.js (CODE-08)
2026-06-10 18:42:01 +02:00
curo1305
fd9188b53c
feat(08-07): create domain modules documents.js, auth.js, topics.js — CODE-04
...
- documents.js: 10 functions; fetchDocumentContent refactored to use fetchWithRetry
- auth.js: 15 functions (login through getMyQuota) — import request from utils.js
- topics.js: 5 functions — import request from utils.js
- All functions copied verbatim from client.js; no consumer files modified
2026-06-10 18:40:32 +02:00
curo1305
80d6f376b0
feat(08-07): create api/utils.js with request() and fetchWithRetry() — CODE-08
...
- Move request() verbatim from client.js to utils.js (breaks circular dep)
- Add fetchWithRetry() consolidating 3 blob-download 401-retry patterns
- Lazy import of authStore preserved for Pinia bootstrap cycle safety
- Bearer token from authStore memory only per CLAUDE.md security rule
2026-06-10 18:39:41 +02:00
curo1305
4d7157d7fc
feat(08-04): add validate_provider_id helper to services/ai_config.py (D-11)
...
- Migrate inline provider_id validator to service layer per CLAUDE.md
- Raises ValueError (not HTTPException) — service-layer rule
- PROVIDER_DEFAULTS already imported; placed after load_provider_config helpers
2026-06-10 18:39:03 +02:00
curo1305 and Claude Sonnet 4.6
f5109b80c3
docs(phase-8): update tracking after wave 1 — plan 08-03 complete
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-08 16:38:35 +02:00
curo1305
226418ca21
chore: merge executor worktree (worktree-agent-a21897142a1981a82)
2026-06-08 16:37:04 +02:00
curo1305
aa1c5ee75e
docs(08-03): complete plan 03 — useToastStore stub, CR wire-up, xfail promotion
...
- SUMMARY.md created with test output, forward reference to Phase 10, and self-check
2026-06-08 16:36:41 +02:00
curo1305
44ec28d474
test(08-03): promote CR-01/CR-02/CR-03 session-revocation tests from xfail to passing
...
- Remove @pytest.mark.xfail decorator from test_change_password_revokes_other_sessions (CR-01)
- Remove @pytest.mark.xfail decorator from test_enable_totp_revokes_other_sessions (CR-02)
- Remove @pytest.mark.xfail decorator from test_disable_totp_revokes_other_sessions (CR-03)
- All three tests now show PASSED (not XPASS) in strict pytest runs
2026-06-08 16:35:26 +02:00
curo1305
3b8e2c1bd4
refactor(08-03): migrate session-revoked inline toast to toastStore.show()
...
- Remove sessionRevokedToast ref + setTimeout + inline HTML from SettingsAccountTab.vue
- Remove sessionRevokedToast ref + setTimeout + inline HTML from TotpEnrollment.vue
- Add toastStore.show('Other sessions have been terminated.', 'success') in changePassword
- Add toastStore.show('Other sessions have been terminated.', 'success') in disableTotp
- Add toastStore.show('Other sessions have been terminated.', 'success') in confirmEnrollment
- Update SettingsAccountTab.test.js to assert on mockShow instead of DOM text
- Update TotpEnrollment.test.js to assert on mockShow instead of DOM text
2026-06-08 16:34:44 +02:00
curo1305
e417b71539
feat(08-03): create useToastStore Pinia stub with locked show() contract
...
- Defines show(message, type='success', duration=4000) as silent no-op
- Positional parameters only per UI-SPEC.md contract
- Phase 10 (UX-10) must implement rendering without modifying call sites
2026-06-08 16:30:30 +02:00
curo1305 and Claude Sonnet 4.6
ccb8a0bb77
docs(phase-8): update tracking after wave 0 — plans 08-01 and 08-02 complete
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-08 16:28:35 +02:00
curo1305
98dcf809b2
chore: merge executor worktree (worktree-agent-ad0b098c151ab9e3f)
2026-06-08 16:24:51 +02:00
curo1305
91d0896ddd
chore: merge executor worktree (worktree-agent-a2766ede6d70fdbe3)
2026-06-08 16:24:17 +02:00
curo1305 and Claude Sonnet 4.6
c636ac956f
docs(08-01): complete Wave 0 xfail stubs plan — 3 xpassed, CR-01/02/03 contracts locked
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-08 16:23:13 +02:00
curo1305
f750d30224
test(08-01): add xfail stubs for CR-01/CR-02/CR-03 session revocation
...
- test_change_password_revokes_other_sessions: verifies skip_token_hash
preserves current session while revoking all other refresh tokens
- test_enable_totp_revokes_other_sessions: verifies TOTP enrollment
revokes other sessions via skip_token_hash
- test_disable_totp_revokes_other_sessions: verifies TOTP disablement
revokes other sessions via skip_token_hash
- All three marked xfail(strict=False); currently xpassed (backend already complete)
- Plan 08-03 promotes these to strict passing tests
2026-06-08 16:21:58 +02:00
curo1305
26c11aff4c
docs(08-02): complete shared-schemas plan — schemas.py + cloud.py import switch
...
- backend/api/schemas.py created with CloudConnectionOut (SEC-08 compliant)
- backend/api/cloud.py import switched from api.admin to api.schemas
- 51 cloud + admin tests pass; no behavior change
- Original admin.py definition preserved for plan 08-04 deletion
2026-06-08 16:13:31 +02:00
curo1305
61fa6e2051
refactor(08-02): switch cloud.py import to api.schemas.CloudConnectionOut
...
- Replace `from api.admin import CloudConnectionOut` with `from api.schemas import CloudConnectionOut`
- Eliminates cross-package coupling between api/cloud.py and api/admin.py (Pitfall 3)
- All 51 cloud + admin tests pass; CloudConnectionOut serialization unchanged
- Original definition in api/admin.py untouched until plan 08-04
2026-06-08 16:12:38 +02:00
curo1305
10e0900a89
feat(08-02): create backend/api/schemas.py with CloudConnectionOut
...
- New cross-package Pydantic schemas module (D-10, CODE-08)
- CloudConnectionOut moved here from api/admin.py to eliminate coupling
- SEC-08: credentials_enc deliberately excluded; 7-field whitelist preserved
- field_validator coerce_id_to_str preserves UUID→str coercion behavior
- Original definition in api/admin.py left intact until plan 08-04
2026-06-08 16:11:58 +02:00
curo1305 and Claude Sonnet 4.6
25e568973f
docs(08): create phase 8 plan — 8 plans, 3 waves (stack upgrade + backend decomposition)
...
Wave 0: CR-01/02/03 test stubs + api/schemas.py (CloudConnectionOut migration)
Wave 1: useToastStore stub + Phase 7.1 frontend completion
Wave 2 (parallel): api/admin/, api/documents/, api/auth/ package splits + client.js decomposition + PERF-01 deps
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-08 14:59:27 +02:00
curo1305
c20a5d8913
docs(08): research phase — decomposition boundaries, CR status, Vite 6 migration
2026-06-07 11:01:54 +02:00
curo1305 and Claude Sonnet 4.6
118f4ee850
docs(08): UI design contract — toast API contract + sessions-revoked interaction spec
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-07 10:50:39 +02:00
curo1305 and Claude Sonnet 4.6
845b681b36
docs(08): UI design contract — useToastStore API and sessions-revoked spec
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-07 10:49:01 +02:00
curo1305
6f2dba8478
docs(state): record phase 8 context session
2026-06-07 10:39:50 +02:00
curo1305
28e1e4aaf4
docs(08): capture phase context
2026-06-07 10:39:32 +02:00
curo1305 and Claude Sonnet 4.6
258b0006d6
docs: create milestone v0.2 roadmap (4 phases, 40 requirements)
...
Phases 8–11: stack upgrade + backend decomposition, admin panel
rearchitecture, UX & interaction, visual design + responsive layout.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-07 09:50:52 +02:00
curo1305 and Claude Sonnet 4.6
f7758776ec
docs: define milestone v0.2 requirements (36 reqs, 6 categories)
...
UI overhaul, codebase quality, admin panel rearchitecture, UX
improvements, responsive layout, and performance/stack updates.
Research: STACK.md, FEATURES.md, ARCHITECTURE.md, PITFALLS.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-07 09:22:40 +02:00
curo1305 and Claude Sonnet 4.6
fd05563ec6
test(07.4): complete UAT — 4 passed, 1 fixed (fgp concatenation collision)
...
UAT found and resolved a concatenation collision in _compute_fgp (no separator
between user_agent and accept_lang). Fix committed in c77b97b . All 5 FGP tests
pass. Full suite: 401 passed, 6 skipped, 7 xfailed, 1 pre-existing failure
(test_extract_docx — missing docx module, unrelated to this phase).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 23:04:17 +02:00
curo1305 and Claude Sonnet 4.6
c77b97b6d3
fix(fgp): add null-byte separator in HMAC input to prevent concatenation collision
...
Without a separator, UA='foobar'+AL='' and UA='foo'+AL='bar' produced the same
HMAC input, allowing a token fingerprint to match a different header split.
Fix: use '\x00' as separator between user_agent and accept_lang fields.
Regression test added: test_fgp_no_concatenation_collision (FGP-05).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 23:03:48 +02:00
curo1305 and Claude Sonnet 4.6
de622e8004
docs(phase-07.4): mark VALIDATION.md complete — 7/7 tasks green, nyquist_compliant: true
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 22:48:59 +02:00
curo1305 and Claude Sonnet 4.6
52c56b5416
docs(phase-07.4): add security threat verification — 5/5 threats closed
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 22:30:57 +02:00
curo1305
3414571091
docs(07.4): add verification report — 8/8 must-haves confirmed
2026-06-06 22:27:55 +02:00
curo1305
ab4b6052a7
docs(07.4): add code review report — 3 critical, 3 warning, 2 info
2026-06-06 22:23:41 +02:00
curo1305
537bbd83e6
docs(phase-07.4): mark phase complete — 2/2 plans, 4 FGP tests passing, v0.1.3
2026-06-06 22:17:42 +02:00
curo1305
5bc92d996f
chore: merge executor worktree (worktree-agent-acc04a00e1a55bd86)
2026-06-06 22:16:16 +02:00
curo1305
5d95fcd686
docs(07.4-02): complete token fingerprinting plan — _compute_fgp + fgp validation + 4 FGP tests passing
2026-06-06 22:15:14 +02:00
curo1305
61b1e045c4
feat(07.4-02): update api/auth.py call sites, promote FGP tests, version bump 0.1.3
...
- api/auth.py login + refresh call sites pass User-Agent and Accept-Language
headers to create_access_token (D-05 — fgp binding at token issuance)
- test_auth_fgp.py: promote all 4 xfail stubs to real assertions (FGP-01..04)
- conftest.py: add _TEST_USER_AGENT constant; configure async_client to send
consistent User-Agent; update auth_user/second_auth_user/admin_user fixtures
to bind fgp to _TEST_USER_AGENT so tokens validate correctly in tests
- test_auth_deps.py: import _TEST_USER_AGENT; update auth_client fixture and
all create_access_token calls to use the constant
- test_cloud.py: update _create_user_and_token to bind fgp to _TEST_USER_AGENT
- test_documents.py: update 3 inline create_access_token calls to pass user_agent
- test_security_headers.py: import _TEST_USER_AGENT; update headers_client +
token creation to use the constant
- Version bump: backend 0.1.2 → 0.1.3, frontend 0.1.2 → 0.1.3
- [Rule 1 - Bug] Fix httpx default User-Agent vs empty-string fgp mismatch in
test infrastructure: 10 tests were failing due to fgp check rejecting tokens
created with fgp="" when client sent "python-httpx/X.Y.Z"
2026-06-06 22:12:57 +02:00
curo1305
1420180be7
feat(07.4-02): add fgp validation block to get_current_user in deps/auth.py
...
- Add `import hmac` to deps/auth.py imports block
- Insert fgp check after user_nbf block: extract fgp_claim from payload,
skip if empty (migration grace for pre-7.4 tokens, D-06), recompute
fgp_actual via auth_service._compute_fgp, compare with hmac.compare_digest
- Mismatch raises HTTP 401 "Token fingerprint mismatch" (D-03)
- Block placed outside try/except (pure computation, no I/O, no fail-open)
2026-06-06 21:55:13 +02:00
curo1305
25c9142fe0
feat(07.4-02): add _compute_fgp helper + extend create_access_token with fgp claim
...
- Add _compute_fgp(user_agent, accept_lang) helper returning 16-char hex
HMAC-SHA256 fingerprint (D-04); uses existing hmac + hashlib imports
- Extend create_access_token signature with user_agent/accept_lang params
(empty-string defaults for backward compatibility, D-05)
- Embed fgp claim in every issued access token payload
2026-06-06 21:54:47 +02:00
curo1305
8c817705b7
docs(phase-07.4): update tracking after wave 0 — plan 07.4-01 complete
2026-06-06 21:52:35 +02:00
curo1305
1adddf8cf4
chore: merge executor worktree (worktree-agent-a37beb50341e88a90)
2026-06-06 21:51:52 +02:00
curo1305
bbd7a11935
docs(07.4-01): complete Wave 0 xfail stub plan — 4 FGP stubs, SUMMARY.md
...
- SUMMARY.md: plan metadata, task commit hash, self-check passed
- backend/tests/test_auth_fgp.py committed in 7833edb
2026-06-06 21:50:27 +02:00
curo1305
7833edbf3b
test(07.4-01): add Wave 0 xfail stubs for FGP-01..FGP-04
...
- Create backend/tests/test_auth_fgp.py with 4 xfail(strict=False) stubs
- FGP-01: test_fgp_match_returns_200 (matching headers → 200)
- FGP-02: test_fgp_mismatch_returns_401 (wrong UA → 401)
- FGP-03: test_no_fgp_claim_allowed (no fgp claim → 200 migration grace)
- FGP-04: test_missing_headers_empty_string_binding (empty-string binding → 200)
- All 4 tests report XFAIL; full suite remains at 1 pre-existing failure only
2026-06-06 21:49:46 +02:00
curo1305 and Claude Sonnet 4.6
22fcb53d9d
docs(07.4): create phase plan — token fingerprinting / token binding
...
2 plans (2 waves): Wave 0 xfail stubs for test_auth_fgp.py (4 FGP tests),
Wave 1 production implementation (_compute_fgp helper, create_access_token
fgp claim, get_current_user fgp validation, login/refresh call-site updates,
test promotion) + version bump to 0.1.3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 21:44:21 +02:00
curo1305 and Claude Sonnet 4.6
de0f3fb7c3
docs(07.4): create phase plan — 2 plans, Wave 0 xfail stubs + Wave 1 fgp implementation
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 20:22:29 +02:00
curo1305
50668cc916
docs(state): record phase 7.4 context session
2026-06-06 19:42:13 +02:00
curo1305
78316b6ed7
docs(07.4): capture phase context
2026-06-06 19:42:08 +02:00
curo1305 and Claude Sonnet 4.6
169c2e7e29
docs(phase-07.3): mark complete — 3/3 plans, 9/9 tests, remember_me shipped
...
Plan 03 human checkpoint passed. 07.3-03-SUMMARY.md written.
ROADMAP: 07.3-03 checked, progress table updated to 3/3 Complete 2026-06-06.
STATE: current_phase → 07.4, completed_phases → 12, completed_plans → 63.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 19:19:17 +02:00
curo1305
739d5b3d9a
chore: merge executor worktree (worktree-agent-a9c4907ff53a1a111)
...
# Conflicts:
# .env.example
# README.md
# backend/config.py
# backend/main.py
# backend/tests/test_auth_es256.py
2026-06-06 18:07:31 +02:00
curo1305 and Claude Sonnet 4.6
e0f2d6c71f
docs(readme): add JWT_PRIVATE_KEY + JWT_PUBLIC_KEY to Quick Start step 3
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 18:00:15 +02:00
curo1305
21e5d27c90
feat(07.3-03): frontend remember_me — checkbox + ref threading + store pass-through
...
- LoginView.vue: add rememberMe ref(false) + "Stay signed in for 30 days" checkbox in password step; thread rememberMe.value through all 3 submit handlers (submitPassword, submitTotp, submitBackupCode) (D-12)
- stores/auth.js: login() forwards options.rememberMe as remember_me in api.login body (D-12)
- api/client.js: no change needed — already forwards full body verbatim
- Frontend build passes (vite build exits 0)
2026-06-06 17:23:02 +02:00
curo1305
9cc11b5446
feat(07.3-03): backend remember_me — TTL split + cookie Max-Age + 3 promoted tests
...
- services/auth.py: create_refresh_token gains remember_me=False param; selects 16h or 30d TTL (D-09, D-10, D-11)
- api/auth.py: LoginRequest.remember_me bool field; _set_refresh_cookie remember_me param for conditional max_age; login handler threads remember_me through both calls (D-11, RM-03)
- test_auth_es256.py: promote RM-01, RM-02, RM-03 stubs — all 9 phase tests now PASSED
2026-06-06 17:21:14 +02:00
curo1305
8be792ab4c
feat(07.3-02): ES256 JWT algorithm upgrade + startup rotation hook
...
- config.py: add refresh_token_expire_hours=16, jwt_private_key, jwt_public_key fields (D-01, D-09)
- services/auth.py: swap all 4 JWT sites to ES256 via base64-decoded PEM keys; remove HS256 (D-02, D-03)
- main.py: add _rotate_tokens_on_algorithm_change lifespan hook — bulk-revokes refresh tokens on algorithm change; idempotent on repeat boots (D-04, D-05)
- test_auth_es256.py: promote ES256-01..05 + CFG-01 stubs to 6 passing tests; RM-01..03 remain xfail
- docker-compose.yml: inject JWT_PRIVATE_KEY + JWT_PUBLIC_KEY into backend + celery-worker (D-07)
- README.md: add JWT key env vars + key generation Python one-liner snippet
- .env.example: add JWT_PRIVATE_KEY= and JWT_PUBLIC_KEY= lines
- Version bump to 0.1.2
2026-06-06 17:19:50 +02:00
curo1305
99f55825aa
test(07.3-01): Wave 0 Nyquist scaffold — 9 xfail stubs for ES256 + remember_me
...
- Create test_auth_es256.py with 9 xfail(strict=True) stubs: ES256-01..05, RM-01..03, CFG-01
- Add es256_keys(autouse) fixture using cryptography P-256 keygen + monkeypatch with raising=False
- Extend test_settings_has_jwt_config to assert refresh_token_expire_hours==16 + jwt key fields
2026-06-06 17:13:50 +02:00
curo1305 and Claude Sonnet 4.6
cc959171ba
docs(phase-07.3): update tracking after wave 1
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 17:10:37 +02:00
curo1305 and Claude Sonnet 4.6
c606191f17
fix(07.3): add global ES256 test key fixture to conftest.py
...
After the ES256 upgrade, create_access_token requires non-empty
jwt_private_key / jwt_public_key. The auth_user, second_auth_user,
and admin_user fixtures in conftest.py call create_access_token
without keys being set, breaking all tests that exercise the auth
system. Add a function-scoped autouse fixture that provisions a
generated P-256 keypair for every test.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 17:10:28 +02:00
curo1305
0f01a7aa82
chore: merge executor worktree (worktree-agent-ad0ae14e8e88d89cf)
2026-06-06 17:05:56 +02:00
curo1305
e7e3f527a5
docs(07.3-02): complete plan 02 SUMMARY — ES256 core upgrade + startup rotation
...
6 tests promoted from xfail to passing (ES256-01..05 + CFG-01); 3 remain xfail for Plan 03
2026-06-06 17:05:31 +02:00
curo1305
0d1ab05e45
chore(07.3-02): wire JWT env vars in docker-compose, README key-gen, .env.example, bump to 0.1.2
...
- docker-compose.yml: add JWT_PRIVATE_KEY + JWT_PUBLIC_KEY to backend and celery-worker service env blocks
- README.md: add JWT_PRIVATE_KEY/JWT_PUBLIC_KEY to required env vars table; add JWT Key Generation section with Python one-liner and warning about session revocation
- .env.example: add JWT_PRIVATE_KEY= and JWT_PUBLIC_KEY= adjacent to SECRET_KEY
- backend/main.py: version bump 0.1.1 -> 0.1.2
- frontend/package.json: version bump 0.1.1 -> 0.1.2
2026-06-06 17:03:59 +02:00
curo1305
8d261b0509
security(07.3-02): add _rotate_tokens_on_algorithm_change lifespan hook + promote tests
...
- backend/main.py: add import logging, select; add _rotate_tokens_on_algorithm_change helper above lifespan; call from lifespan with try/except wrap
- backend/tests/test_auth_es256.py: promote ES256-04 and ES256-05 startup rotation tests from xfail to passing; suite reports 6 PASSED + 3 XFAILED
2026-06-06 17:02:45 +02:00
curo1305
fd3f611546
security(07.3-02): ES256 signing — swap 4 JWT sites + config keys + promote tests
...
- backend/config.py: add refresh_token_expire_hours=16, jwt_private_key, jwt_public_key
- backend/services/auth.py: add import base64; all 4 JWT sites use ES256 with inline PEM decode; zero HS256/secret_key references
- backend/tests/test_auth_es256.py: promote ES256-01..03 + CFG-01 tests from xfail to passing
2026-06-06 16:59:38 +02:00
curo1305 and Claude Sonnet 4.6
1eb1d59c8d
docs(phase-07.3): update tracking after wave 0
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 16:54:48 +02:00
curo1305
b9e1f2a464
chore: merge executor worktree (worktree-agent-a6bcbfd85b592800f)
2026-06-06 16:53:02 +02:00
curo1305
b1e3d0bc73
docs(07.3-01): add plan execution SUMMARY.md
...
- Documents 9 xfail stubs created + test_settings_has_jwt_config extension
- Records test counts: 372 passed / 1 failed / 9 xfailed
- Includes promotion plan mapping each stub to its Plan 02/03 task
- Confirms no production code was modified in this Wave 0 plan
2026-06-06 16:51:40 +02:00
curo1305
fac0e781f9
test(07.3-01): extend test_settings_has_jwt_config — red until Plan 02
...
- Assert settings.refresh_token_expire_hours == 16 (CFG-01 / D-09)
- Assert hasattr(settings, "jwt_private_key") (CFG-01 / D-01)
- Assert hasattr(settings, "jwt_public_key") (CFG-01 / D-01)
- Existing refresh_token_expire_days == 30 assertion preserved (Pitfall 5)
- Test intentionally fails until Plan 02 adds the three new config fields
2026-06-06 16:50:32 +02:00
curo1305
5c1a1f9504
test(07.3-01): add Wave 0 xfail scaffold — 9 ES256/RM/CFG stubs
...
- Create backend/tests/test_auth_es256.py with 9 xfail(strict=True) stubs
- Cover ES256-01..05 (access token, HS256 rejection, reset token, startup rotation)
- Cover RM-01..03 (16h default TTL, 30d remember_me TTL, cookie max_age)
- Cover CFG-01 satellite (jwt_private_key/jwt_public_key presence)
- Add es256_keys autouse fixture generating fresh P-256 keypair per test
- All 9 stubs collect and run as XFAIL; zero XPASS, zero ERROR
2026-06-06 16:49:58 +02:00
curo1305 and Claude Sonnet 4.6
4d0ada6d06
docs(phase-07.2): mark VERIFICATION.md passed — CR-02 gap resolved
...
Gap (password_reset_confirm missing user_nbf write) was fixed during UAT
phase: request: Request param added + Redis write at auth.py:744-750.
VALIDATION.md: 84/84 tests, nyquist_compliant=true. VERIFICATION.md
updated from gaps_found → passed (9/9). STATE.md advanced to phase 07.3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 12:37:59 +02:00
curo1305 and Claude Sonnet 4.6
2265aaaba4
docs(phase-07.2): mark VALIDATION.md complete — nyquist_compliant: true
...
Audited post-execution state: all 11 tasks (9 original + CR-02 gap fix +
activate anti-pattern guard) have green automated tests. 84/84 passing.
Zero xfail stubs remaining. Sign-off approved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 11:54:57 +02:00
curo1305 and Claude Sonnet 4.6
b8e0e3adec
test(07.2): complete automated UAT — 7/7 pass
...
All Phase 7.2 behaviors verified end-to-end against the running app:
- JTI UUID claim present in every issued access token
- Token rejected (Session invalidated) after password change
- Refresh cookie survives password change (skip_token_hash)
- Token rejected after enable-TOTP and disable-TOTP
- Token rejected after admin deactivation
- Reactivation does NOT write user_nbf (no spurious revocation)
Findings recorded in UAT.md:
- Workers must be restarted after Phase 7.2 deploy (--workers 2 does not hot-reload)
- D-02 same-second edge case confirmed benign in real usage
- Deactivation fires is_active check before user_nbf in same-second scenarios (belt-and-suspenders)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 11:47:59 +02:00
curo1305 and Claude Sonnet 4.6
95c6db5c42
security(07.2): add SECURITY.md audit — JTI claim + Redis NBF revocation
...
9/9 threats CLOSED; 11/11 Phase 7.2 tests PASSED; bandit 0 HIGH; full
391-test suite green. Documents gap closure for CR-02 (password_reset_confirm
user_nbf write). HS256→ES256 deferred to Phase 7.3.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-06-06 00:33:31 +02:00
curo1305
646736d4d3
docs(phase-07.2): complete phase execution
2026-06-06 00:12:09 +02:00
curo1305
8e4e199062
docs(07.2): add phase verification report
2026-06-06 00:11:44 +02:00
curo1305
d3deef4f95
fix(07.2): add user_nbf write to password_reset_confirm — CR-02 gap closure
2026-06-06 00:11:41 +02:00
curo1305
7e23a3ed0e
docs(07.2): add code review report
2026-06-06 00:07:51 +02:00
curo1305
a20d27123d
docs(07.2): update tracking after Wave 2 — plan 07.2-03 complete
2026-06-06 00:04:58 +02:00
curo1305
d3588ba055
docs(07.2-03): complete Wave 2 plan — user_nbf write sites in all 4 security-event handlers SUMMARY
2026-06-06 00:04:45 +02:00
curo1305
ae11a6e913
security(07.2-03): add import time + user_nbf write to admin deactivation handler; promote stubs to PASSED
2026-06-06 00:02:27 +02:00
curo1305
efeb75b279
feat(07.2-03): add import time + user_nbf writes to api/auth.py (change_password, enable_totp, disable_totp)
2026-06-06 00:01:19 +02:00
curo1305
2665a5085d
docs(07.2): update tracking after Wave 1 — plan 07.2-02 complete
2026-06-05 19:21:48 +02:00
curo1305
9f90d46649
chore: merge executor worktree (worktree-agent-a9a1eb8685f2efc98) — Wave 1 plan 07.2-02
2026-06-05 19:21:09 +02:00
curo1305
61199752b5
docs(07.2-02): complete Wave 1 plan — jti claim + user_nbf NBF check SUMMARY
...
- jti UUID claim in create_access_token (D-01)
- user_nbf Redis NBF check in get_current_user with fail-open + re-raise guard (D-02, D-03, D-04, T-7.2-02)
- 4 Wave 0 xfail stubs promoted to PASS; 29 tests passing in target suites
2026-06-05 19:20:42 +02:00