curo1305
8cc46a8d8d
docs(phase-06.2): resolve UAT gaps after 06.2-05 gap closure
2026-05-31 20:16:43 +02:00
curo1305
c3c7030e91
docs(phase-06.2): update tracking after wave 3 — all 5 plans complete
2026-05-31 20:16:08 +02:00
curo1305
8a078e4040
chore: merge executor worktree (worktree-agent-ad4015e9fb03e9447)
2026-05-31 20:13:19 +02:00
curo1305
e30401ddff
docs(06.2-05): complete plan summary — 4 UAT gaps closed
...
- Task 1: @handle in AccountView + AdminUsersTab
- Task 2: actionable cloud error (Settings link) + audit log @ prefix
- Task 3: clearFilters() + activeFilterCount + Clear filters button + filter count badge
2026-05-31 20:12:27 +02:00
curo1305
5d457d68bf
feat(06.2-05): clear filters button and active filter count in AuditLogTab
...
- Add clearFilters() function that resets all filter fields and refetches
- Add activeFilterCount computed property (counts non-empty filter fields)
- Add "Clear filters" button (visible only when activeFilterCount > 0)
- Wrap Export CSV button with filter count indicator (amber text below button)
- Add computed to vue import
2026-05-31 20:11:02 +02:00
curo1305
f5e111bfa2
feat(06.2-05): actionable cloud error + audit log @ prefix
...
- CloudFolderView: detect no-connection error and show actionable message
directing user to Settings; add router-link to /settings and Retry button
- AuditLogTab: prefix user handles with @ in the User column
2026-05-31 20:10:22 +02:00
curo1305
045e723f7a
feat(06.2-05): show @handle in AccountView and AdminUsersTab
...
- Add Username row (@handle) to Account information section in AccountView.vue
- Add Handle column (th + td with @prefix) to users table in AdminUsersTab.vue
- Both use existing data already present in API responses (no backend changes)
2026-05-31 20:09:50 +02:00
curo1305
6307d9dd86
test(06.2): update UAT with root cause diagnoses for all 4 gaps
2026-05-31 20:01:56 +02:00
curo1305
1d8c7dba91
test(06.2): complete UAT — 3 passed, 4 issues, 2 skipped, 2 blocked
2026-05-31 16:10:54 +02:00
curo1305 and Claude Sonnet 4.6
77263bd569
docs(phase-06.2): mark validation strategy nyquist-compliant
...
All 11 Wave 0 test stubs verified green (50 passed, 4 xfailed).
Updated per-task map, wave 0 checklist, sign-off, and audit trail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:44:25 +02:00
curo1305 and Claude Sonnet 4.6
73b180ac9d
docs(phase-06.2): add security threat verification report
...
16/16 threats CLOSED — mitigate dispositions verified in code with exact file:line citations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:41:33 +02:00
curo1305
f037d2be45
docs(06.2): add phase verification report
2026-05-31 15:36:08 +02:00
curo1305
758d1a687e
docs(06.2): add code review report
2026-05-31 15:29:57 +02:00
curo1305
abb964531f
docs(phase-06.2): update tracking after wave 2 — plan 06.2-04 complete
2026-05-31 15:24:44 +02:00
curo1305
46f7505e36
chore: merge executor worktree (worktree-agent-af66944050628b0e4)
2026-05-31 15:23:36 +02:00
curo1305
893da5b9ba
docs(06.2-04): complete ADMIN-06 audit enrichment + daily exports — 10 tests pass
...
- Handle-enriched audit log (user_handle, actor_handle via aliased double-JOIN)
- user_handle filter with handle-to-UUID resolution, empty result for unknown handles
- fetch+Blob CSV export replacing window.location.href (T-06.2-04-03)
- GET /audit-log/daily-exports and /daily-exports/{date} with date regex validation
- Daily exports section in AuditLogTab with date dropdown + Download button
- Full audit test suite: 10 passed; backend suite: 337 passed, 1 pre-existing failure
2026-05-31 15:22:46 +02:00
curo1305
0647e6e9bf
feat(06.2-04): frontend — user_handle filter, fetch+Blob export, daily-export section
...
- adminListAuditLog: rename user_id param to user_handle (backend API change)
- adminExportAuditLogCsv(): fetch+Blob pattern — sends Bearer header (D-13, T-06.2-04-03)
- adminListDailyExports(): raw fetch returning JSON for daily export listing (D-17)
- adminDownloadDailyExport(date): fetch+Blob download with audit-{date}.csv filename (D-17)
- AuditLogTab: rename filters.user_id to filters.user_handle + label 'User handle' (D-12, C-5)
- AuditLogTab: exportCsv() replaced with async fetch+Blob call, exportingCsv loading state
- AuditLogTab: daily exports section below pagination — date dropdown + Download button (D-17, C-4)
- window.location.href removed from AuditLogTab (broken auth bypass closed)
- Build exits 0, full backend suite: 337 passed, 1 pre-existing failure
2026-05-31 15:21:23 +02:00
curo1305 and Claude Sonnet 4.6
f176235ee8
docs(phase-04): update VALIDATION.md — Nyquist-compliant (all gaps resolved)
...
Mark nyquist_compliant: true. All 22 tasks now have automated coverage.
4 gaps resolved: FOLD-04 sort, FOLD-05 FTS, SEC-08 credentials_enc, SEC-09
MinIO cleanup. 1 impl bug logged and fixed (FTS try/except misplacement).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:21:08 +02:00
curo1305 and Claude Sonnet 4.6
62daf0d750
test(phase-04): fill Nyquist validation gaps — FOLD-04, FOLD-05, SEC-08, SEC-09
...
Add 6 new tests covering document sort (name/size), FTS search cross-user
isolation, credentials_enc exclusion from all responses, and MinIO object
cleanup on user deletion.
Fix FTS try/except misplacement in api/documents.py — was wrapping the ORM
statement builder (never raises) instead of the execute call, causing HTTP 500
on SQLite test env. Now falls back to unfiltered results when @@ unsupported.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:21:02 +02:00
curo1305
839bfe0ffe
feat(06.2-04): backend — handle enrichment, user_handle filter, two daily-export endpoints
...
- Add _audit_to_dict_with_handles() with user_handle + actor_handle fields
- Add _build_filtered_query_with_handles() with aliased User double-JOIN
- Change list_audit_log user_id param to user_handle string with handle→UUID resolution
- Change export_audit_log user_id param to user_handle (Pitfall 7 — both endpoints enriched)
- Add GET /audit-log/daily-exports — lists MinIO audit-logs bucket, asyncio.to_thread
- Add GET /audit-log/daily-exports/{date} — streams CSV, date regex validation (T-06.2-04-01)
- Move daily-export endpoints before viewer to ensure specific path registration order
- Update test_audit_log_export_csv to match enriched CSV header (user_handle, actor_handle)
- All 10 test_audit.py tests pass
2026-05-31 15:17:53 +02:00
curo1305
d7cfc5ccee
test(06.2-04): add failing tests for handle enrichment, user_handle filter, daily exports
...
- test_audit_log_includes_user_handle: asserts user_handle/actor_handle in items
- test_audit_log_filter_by_handle: asserts filtering by handle works correctly
- test_audit_log_filter_unknown_handle: asserts 200+empty for unknown handle
- test_daily_exports_list: mocks MinIO list_objects, asserts sorted items
- test_daily_export_download: mocks MinIO get_object, asserts CSV response + 404 on bad date
2026-05-31 15:15:46 +02:00
curo1305 and Claude Sonnet 4.6
eab5f124f6
docs(06.2-03): complete cloud-delete gap closure — 24 tests pass
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:11:51 +02:00
curo1305 and Claude Sonnet 4.6
cce8586235
feat(06.2-03): frontend — CloudDeleteWarningModal + remove_only path in DocumentView
...
- api/client.js: deleteDocument gains removeOnly param; deleteDocumentRemoveOnly wrapper added
- DocumentView.vue: confirmDelete inspects response.cloud_delete_failed, shows modal on failure
- DocumentView.vue: inline CloudDeleteWarningModal (C-3 contract) with Remove from app / Cancel
- confirmRemoveOnly() calls DELETE ?remove_only=true and navigates to /
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:11:31 +02:00
curo1305 and Claude Sonnet 4.6
95c7ed786a
feat(06.2-03): backend — cloud-aware delete routing + skip_quota + remove_only param
...
- storage.delete_document gains skip_quota=False param; quota decrement gated on it
- DELETE /api/documents/{id} gains remove_only=bool query param
- Cloud docs (storage_backend != minio): attempt cloud backend delete_object first
- On failure: return HTTP 200 {success: false, cloud_delete_failed: true} (not 4xx)
- On success or remove_only: delete DB row with skip_quota=True
- Cloud creds/exception message never included in response body (T-06.2-03-02)
- Promote 3 xfail stubs to real tests (propagates, failure, remove_only)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:09:44 +02:00
curo1305 and Claude Sonnet 4.6
e812922a26
docs(06.2-02): complete SHARE-05 + SHARE-03 gap closure — 12 tests pass
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:07:26 +02:00
curo1305 and Claude Sonnet 4.6
3cc4a5335d
docs(phase-03): update VALIDATION.md — Nyquist-compliant (partial)
...
15 automated tests green, 4 manual-only (PostgreSQL/migration infra).
Added 4 previously unlisted passing tests to task map (D-15, D-16, D-09×2).
Audit trail appended. Status: nyquist_compliant: true, status: partial.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:07:23 +02:00
curo1305 and Claude Sonnet 4.6
1ee27da332
test(phase-03): remove stale xfail markers from quota tests
...
test_quota_increment_atomic and test_quota_exceeded_response were marked
xfail for PostgreSQL but pass on SQLite — markers removed, tests now PASSED.
Concurrent race and delete decrement keep xfail; they require real PG locking.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:07:18 +02:00
curo1305 and Claude Sonnet 4.6
34b18a9f08
feat(06.2-02): frontend — is_shared badge fix + permission dropdown + View/Edit toggle
...
- DocumentCard.vue: fix Shared pill to read doc.is_shared (was doc.share_count > 0)
- ShareModal.vue: add permission select between handle input and submit button
- ShareModal.vue: replace static "view" span with View/Edit toggle group per share row
- ShareModal.vue: add handlePermissionChange with optimistic update + rollback on error
- documents.js: update shareDocument(docId, handle, permission='view') signature
- documents.js: add updateSharePermission(shareId, permission) action
- api/client.js: pass permission in createShare POST body
- api/client.js: add updateSharePermission PATCH helper
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:07:04 +02:00
curo1305 and Claude Sonnet 4.6
ea231853e9
feat(06.2-02): backend — ShareCreate.permission field + PATCH /{share_id} endpoint
...
- Add permission field (default "view") with field_validator to ShareCreate
- Add SharePermissionPatch model with same validator
- Wire body.permission into grant_share() Share constructor
- Add PATCH /{share_id} endpoint with IDOR protection (T-06.2-02-01)
- Promote 3 xfail stubs to real tests (create_with_permission, patch_permission, patch_idor)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 15:04:53 +02:00
curo1305 and Claude Sonnet 4.6
7e62868fea
docs(phase-02): add VALIDATION.md — Nyquist-compliant, all 24 tasks mapped, 4 manual-only
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 12:04:28 +02:00
curo1305 and Claude Sonnet 4.6
d98e3ab7a1
test(phase-02): add Nyquist validation tests — fill SEC-05, AUTH-08, SEC-03 and frontend gaps
...
8 test files, 60 new tests (14 backend + 46 frontend). All green.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 12:04:21 +02:00
curo1305
6c79f92d70
chore: merge executor worktree (worktree-agent-a3dd74026d1efb9af)
2026-05-31 12:01:28 +02:00
curo1305
21fde406e7
docs(06.2-01): complete Wave 0 Nyquist scaffold — 11 xfail stubs across 3 test files
...
- 3 stubs in test_shares.py (SHARE-03 permission field, PATCH, IDOR)
- 3 stubs in test_documents.py (cloud delete propagation, failure, remove_only)
- 5 stubs in test_audit.py (handle enrichment, handle filter x2, daily exports x2)
- All 11 reported as XFAIL; full 3-file suite: 35 passed, 15 xfailed, exits 0
2026-05-31 11:58:58 +02:00
curo1305
7271eeb53c
test(06.2-01): add xfail stubs for ADMIN-06 audit enrichment + daily exports (Task 3)
...
- test_audit_log_includes_user_handle: user_handle and actor_handle in audit items (D-11)
- test_audit_log_filter_by_handle: user_handle query param filters entries (D-12)
- test_audit_log_filter_unknown_handle: unknown handle returns empty list, not 422 (D-12)
- test_daily_exports_list: daily-exports listing endpoint returns {items} (D-15)
- test_daily_export_download: daily export download returns CSV bytes with Content-Disposition (D-16)
2026-05-31 11:58:05 +02:00
curo1305
bbf5355edb
test(06.2-01): add xfail stubs for cloud-delete document tests (Task 2)
...
- test_delete_cloud_document_propagates: cloud backend delete_object called for non-minio docs (D-01)
- test_delete_cloud_document_failure: structured JSON error when provider raises (D-03)
- test_delete_cloud_remove_only: remove_only=true skips cloud delete, removes DB row only (D-02)
2026-05-31 11:57:55 +02:00
curo1305
ecdeffb63d
test(06.2-01): add xfail stubs for SHARE-03 permission tests (Task 1)
...
- test_share_create_with_permission: POST /api/shares permission field (SHARE-03, D-08, D-10)
- test_share_patch_permission: PATCH /api/shares/{id} permission change (SHARE-03, D-09)
- test_share_patch_idor: PATCH by non-owner returns 404 IDOR protection (SHARE-03, T-IDOR)
2026-05-31 11:54:52 +02:00
curo1305 and Claude Sonnet 4.6
708fd7fad0
docs(phase-6.2): record planning complete — 4 plans verified, state updated
...
- ROADMAP.md: progress table → Planned; wave annotations already added by planner
- STATE.md: phase 6.2 row → Planned (4 plans, 3 waves); session note added
- 06.2-03-PLAN.md: remove incorrect SHARE-03/SHARE-05 from requirements field
- 06.2-RESEARCH.md: mark Open Questions section as RESOLVED
- 06.2-UI-SPEC.md: add to version control (was untracked)
Verification: 0 blockers, 2 cosmetic warnings fixed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 11:41:32 +02:00
curo1305 and Claude Sonnet 4.6
4adc77d8cc
docs(06.2): create 4-plan phase covering SHARE-03, SHARE-05, cloud-delete, ADMIN-06
...
Wave 0: 11 xfail stubs across test_shares/test_documents/test_audit
Wave 1 (parallel): SHARE-05 badge + SHARE-03 permission control; cloud-delete propagation
Wave 2: audit handle enrichment, user_handle filter, CSV fetch+Blob, daily-export UI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 11:36:33 +02:00
curo1305
67f0c01540
docs(phase-6.2): add validation strategy
2026-05-31 11:12:23 +02:00
curo1305 and Claude Sonnet 4.6
695649eefa
docs(06.2): add research document for phase 6.2 gap-closure
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 11:10:59 +02:00
curo1305 and Claude Sonnet 4.6
7be48266ae
docs(06.2): capture phase context + fix admin user creation 500
...
- Phase 6.2 CONTEXT.md: cloud-delete propagation, SHARE-03/05, audit
log CSV export fix, daily export UI, user handle display
- Fix: admin create_user missing session.flush() before write_audit_log
caused FK violation on PostgreSQL (silent on SQLite)
- Regression test: test_create_user_writes_audit_log in test_admin_api.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-31 11:00:45 +02:00
curo1305 and Claude Sonnet 4.6
3825f670a1
docs(phase-6.1): add VALIDATION.md and commit VERIFICATION.md
...
VALIDATION.md: Nyquist audit — 3 gaps found, 2 resolved automated
(SHARE-03 permission field, SHARE-05 is_shared indicator), 1 escalated
to manual-only (STORE-06 requires INTEGRATION=1 PostgreSQL).
VERIFICATION.md: was untracked artifact from gsd-verifier run.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:38:16 +02:00
curo1305 and Claude Sonnet 4.6
ce4dc55e4f
test(6.1): add SHARE-03 and SHARE-05 Nyquist gap tests
...
- test_share_default_permission_view: asserts permission='view' in POST
response and owner's GET /api/shares list (SHARE-03)
- test_share_indicator_in_owner_list: asserts is_shared flips True in
owner's GET /api/documents after sharing (SHARE-05)
All 14 phase tests now pass (9 shares + 5 audit).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:38:06 +02:00
curo1305 and Claude Sonnet 4.6
56bfdba8d1
docs(phase-6.1): mark phase complete — 12 tests, 310 total passing
...
SHARE-01..05 and ADMIN-06 test coverage gaps closed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:30:34 +02:00
curo1305 and Claude Sonnet 4.6
451fff1e4d
test(6.1): add audit filter behavioral test (ADMIN-06 SC3)
...
Verifies event_type filter returns only matching entries.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:30:05 +02:00
curo1305 and Claude Sonnet 4.6
57784f9f80
fix(6.1): close WR-01/WR-02 code review findings in test_audit.py
...
WR-01: extend nested metadata_ forbidden-key check to all 4 keys
WR-02: assert no forbidden fields in CSV export body (D-15)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:24:26 +02:00
curo1305 and Claude Sonnet 4.6
5762f65b09
docs(6.1): add code review report — 3 warnings, 2 info
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:24:05 +02:00
curo1305 and Claude Sonnet 4.6
1e4654aad5
docs(phase-6.1): update tracking after wave 1 — both plans complete
...
11 tests passing (7 shares + 4 audit), 309 total, 0 failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 23:18:04 +02:00
curo1305
21ea3bf169
chore: merge executor worktree (06.1-01 shares tests)
2026-05-30 23:16:38 +02:00
curo1305
eee9970cf2
chore: merge executor worktree (06.1-02 audit tests)
2026-05-30 23:16:14 +02:00
curo1305
ec14fc722f
docs(6.1-01): complete plan — promote test_shares.py stubs to real tests
...
- 2/2 tasks complete: second_auth_user fixture + 7 real share tests
- 7 PASSED in Docker (0 xfailed, 0 failed)
- SHARE-01..05 requirements covered
2026-05-30 23:13:09 +02:00
curo1305
9973f42f98
feat(6.1-01): replace 7 xfail stubs with real share tests (SHARE-01..05)
...
- Remove all 7 @pytest.mark.xfail decorators and pytest.xfail() calls
- Remove unused 'import os'
- Add module-level pytestmark = pytest.mark.asyncio
- Add _make_doc() helper: creates uploaded Document row via ORM
- test_share_success: POST grants share, recipient sees doc in /received
- test_share_handle_not_found: unknown handle returns 404
- test_shared_with_me: metadata fields present, extracted_text absent (T-04-04-03)
- test_share_no_quota_impact: recipient used_bytes stays 0 (T-04-04-04)
- test_revoke_share: DELETE 204, doc gone from recipient /received
- test_share_revoke_wrong_owner_404: IDOR protection, 404 not 403 (T-04-04-02)
- test_share_duplicate: second share of same doc+recipient returns 409
- All 7 tests verified passing in Docker (pytest 9.0.3)
2026-05-30 23:12:24 +02:00
curo1305
0ccdee48ba
docs(6.1-02): complete plan 06.1-02 — promote test_audit.py stubs to real tests
...
- 4 PASSED, 0 xfailed; ADMIN-06 test coverage complete
2026-05-30 23:11:01 +02:00
curo1305
bda123db8d
feat(6.1-02): promote test_audit.py stubs to real tests (ADMIN-06)
...
- Replace all 4 @pytest.mark.xfail stubs with real assertions
- Add _seed_audit() helper calling write_audit_log() + commit
- test_audit_log_viewer: verifies paginated JSON shape and total >= 1
- test_audit_log_no_doc_content: asserts no filename/extracted_text in items
- test_audit_log_regular_user_403: asserts 403 for regular users
- test_audit_log_export_csv: asserts text/csv content-type and CSV header line
- Remove unused 'import os'
- Add pytestmark = pytest.mark.asyncio at module level
2026-05-30 23:10:14 +02:00
curo1305
b7df9719c2
feat(6.1-01): add second_auth_user fixture to conftest.py
...
- Add @pytest_asyncio.fixture second_auth_user with handle prefix 'user2_'
- Creates User + Quota row following the same pattern as auth_user
- Returns {user, token, headers} dict shape for use in sharing tests
2026-05-30 23:09:39 +02:00
curo1305 and Claude Sonnet 4.6
838698e715
docs(06): capture phase context — performance & production hardening
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 22:41:14 +02:00
curo1305 and Claude Sonnet 4.6
767c5234de
docs(milestone): update v1.0 audit — Phase 1 Nyquist upgraded to compliant
...
Phase 1 moved from partial_phases to compliant_phases after
gsd-validate-phase 1 closed all 3 gaps. Audit status remains
gaps_found (3 blockers unchanged: SHARE-02/DOC-01, STORE-06/SEC-09,
ADMIN-06). Nyquist overall: partial (phases 3, 4 still draft; phase 2
missing).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 21:34:09 +02:00
curo1305 and Claude Sonnet 4.6
a2ece9ee7d
docs(phase-1): mark VALIDATION.md Nyquist-compliant — all 6 rows green
...
Audit 2026-05-30: 3 gaps closed (STORE-07 concurrent test added,
test_confirm_endpoint unblocked, alembic tests moved to manual-only).
nyquist_compliant: true, status: compliant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:57:07 +02:00
curo1305 and Claude Sonnet 4.6
bf7d86184d
fix(documents): normalize UUID to undashed hex in raw SQL quota UPDATE
...
str(uuid) returns dashed format (xxxx-xxxx-…) which mismatches SQLite's
CHAR(32) storage (undashed hex). Replace with .replace('-', '') so the
WHERE clause matches in both SQLite (tests) and PostgreSQL (production).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:57:02 +02:00
curo1305 and Claude Sonnet 4.6
bd765f69bf
test(phase-1): add Nyquist validation tests — STORE-07 concurrent put, fix confirm UUID
...
- Add test_concurrent_put_objects to test_storage.py (STORE-07: verifies no
per-instance lock blocks concurrent MinIO workers via asyncio.gather)
- Remove @pytest.mark.xfail from test_confirm_endpoint; test now passes on
SQLite after uuid format fix in api/documents.py
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:56:58 +02:00
curo1305 and Claude Sonnet 4.6
33e5efe846
docs(v1.0): add milestone audit — 48/54 requirements satisfied, 3 blockers
...
Audit findings: share recipient doc-metadata 404 (SHARE-02/DOC-01),
cloud document delete corrupts MinIO quota (STORE-06/SEC-09), admin
CSV export returns 403 (ADMIN-06). 6 tech debt warnings.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:44:16 +02:00
curo1305 and Claude Sonnet 4.6
710e535411
docs(phase-5): mark VALIDATION.md Nyquist-compliant — all 13 rows green
...
All 117 cloud tests pass; 13/13 validation map requirements COVERED.
Updated status, frontmatter, sign-off, and added audit trail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:24:12 +02:00
curo1305 and Claude Sonnet 4.6
cafdceef10
docs(phase-5): add security threat verification
...
56/56 threats verified CLOSED across all 12 plans. 14 accepted risks documented. Unregistered flag (GET /connections/{id}/config) reviewed and confirmed fully mitigated.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:18:22 +02:00
curo1305 and Claude Sonnet 4.6
1a6fa08a34
docs(05): add code review and verification reports for phase 5
...
REVIEW.md: 3 critical findings fixed (HTTPException passthrough,
Redis pre-flight ordering, CLOUD_CREDS_KEY in celery-worker env)
VERIFICATION.md: 7/7 must-haves verified; 6 human-verification items
require live cloud credentials (Google Drive, OneDrive, Nextcloud/WebDAV)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:07:42 +02:00
curo1305 and Claude Sonnet 4.6
b1a136b5be
fix(05-12): resolve 3 critical code review findings
...
CR-01: add `except HTTPException: raise` before broad except in
stream_document_content — prevents 503 (reconnect prompt) from being
swallowed and replaced with misleading 502
CR-02: move pre-flight credential checks BEFORE Redis setex in
oauth_initiate — no orphan state tokens written for unconfigured providers;
also adds onedrive_tenant_id to OneDrive pre-flight condition (WR-02)
CR-03: add CLOUD_CREDS_KEY to celery-worker environment in docker-compose.yml
— worker cannot decrypt cloud credentials without this key; every cloud
document task was silently failing at runtime
WR-03: assert Redis store empty after 400 pre-flight responses in both
new tests — confirms no token leak on misconfigured-provider requests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 18:04:09 +02:00
curo1305 and Claude Sonnet 4.6
12dd692f00
docs(05): mark phase 5 complete — 12/12 plans done, all UAT gaps resolved
...
Update STATE.md and ROADMAP.md to reflect plan 05-12 completion and Phase 5
as fully complete. All UAT gaps (OneDrive 500 → 400, cloud stream 500 → 502,
upload hint) resolved. 293 tests passing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 17:56:18 +02:00
curo1305 and Claude Sonnet 4.6
10175ee4b5
fix(05-12): close 3 UAT gaps — OAuth 400 preflight, 502 cloud fallback, upload hint
...
- oauth_initiate: pre-flight check returns 400 with env-var hint when
GOOGLE_CLIENT_ID/SECRET or ONEDRIVE_CLIENT_ID/SECRET are not configured,
preventing opaque MSAL/OAuth library 500 errors on misconfigured servers
- stream_document_content: broad except-clause catches non-CloudConnectionError
exceptions and returns 502 with user-friendly message (was raw 500)
- docker-compose.yml: add volumes: - ./backend:/app to celery-worker so code
changes are picked up by docker compose restart without a rebuild
- CloudStorageView: upload hint paragraph directs users to navigate into a
cloud folder; no DropZone added (no folder context at overview level)
- 3 new backend tests pass; 2 existing tests patched with credential monkeypatch;
full suite: 293 passed, 0 new failures, 1 pre-existing (test_extract_docx)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 17:55:08 +02:00
curo1305 and Claude Sonnet 4.6
f4f340545b
chore: add .DS_Store, node_modules/, screenshots/ to .gitignore
...
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 11:58:51 +02:00
curo1305 and Claude Sonnet 4.6
5250895587
feat(05): cloud folder browser views, routing, and sidebar nav
...
Add CloudStorageView (/cloud) and CloudFolderView (/cloud/:provider/:folderId).
Tree items filter to directories only (is_dir) to hide files in the nav tree.
CloudProviderTreeItem root click navigates to /cloud/{provider}/root instead
of /settings. AppSidebar Cloud Storage link upgraded to router-link with
active-class highlighting. Router registers both cloud routes with requiresAuth.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 11:58:08 +02:00
curo1305 and Claude Sonnet 4.6
54ef3357ba
fix(05): cloud API path param, root sentinel, webdav creds in list, upload path
...
cloud.py: list_connections now decrypts and surfaces server_url +
connection_username for nextcloud/webdav providers; folder route uses
{folder_id:path} to handle slashes; translates "root" sentinel to "".
nextcloud_backend.py: skip parent directory entry in PROPFIND Depth:1 results.
webdav_backend.py: add cloud_folder + original_filename params to
upload_object so files land in the user's chosen folder with their real name.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 11:58:01 +02:00
curo1305 and Claude Sonnet 4.6
67edc19a36
docs(05): add UAT, UI-SPEC, deferred items, debug notes; refine plans 09-11
...
Plan refinements: Vitest tests added to 09/10 must-haves, explicit
mock_flow two-tuple pattern in 10, test_admin_api.py fixture usage in 11.
New artifacts: UAT checklist, UI-SPEC, deferred-items, debug investigation
for cloud-doc-operations-fail.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 11:57:54 +02:00
curo1305 and Claude Sonnet 4.6
34f012b4e8
fix(05): resolve 5 critical code review findings
...
CR-01: add Field(min_length=1) to UserDeleteConfirm.admin_password
CR-02: add folder ownership check in PATCH /documents/{id} — prevents IDOR
when folder_id belongs to another user
CR-03: add min_length=1, max_length=255, and path-separator validator to
DocumentPatch.filename — prevents empty and path-traversal filenames
CR-04: fetchDocumentContent now throws on non-ok responses instead of
silently returning the error Response
CR-05: object URL revoke in DocumentView uses pagehide + load events with
120s fallback instead of unreliable 60s blind timer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 11:51:54 +02:00
curo1305
9935c06aab
docs(05): add code review report — 5 critical, 6 warning, 3 info findings
2026-05-30 11:49:43 +02:00
curo1305 and Claude Sonnet 4.6
aafd552a1e
fix(05-09): set storage_backend='minio' in test_celery_task_uses_user_provider
...
Cloud-aware routing added in 05-09 checks doc.storage_backend; MagicMock
attribute is truthy and != 'minio', so the test was entering the cloud branch
without any mock for get_storage_backend_for_document. Regression: test passed
before 05-09 when _run() had no cloud routing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 11:43:48 +02:00
curo1305
02ef11c432
chore: merge executor worktree (05-11 admin hard-delete)
2026-05-30 11:40:40 +02:00
curo1305
3180e759de
docs(05-11): complete admin hard-delete with password confirmation plan
...
- UserDeleteConfirm Pydantic model + Argon2 password verification in delete_user
- adminDeleteUser(id, adminPassword) exported from client.js
- AdminUsersTab inline delete confirmation panel with password field
- Three new tests pass: 204/403/422 scenarios
- Full 21-test admin suite green; frontend build clean
2026-05-30 11:40:14 +02:00
curo1305
72687212a1
feat(05-11): add adminDeleteUser API function + inline delete confirmation panel
...
- Export adminDeleteUser(id, adminPassword) from client.js — sends JSON body to DELETE /api/admin/users/{id}
- AdminUsersTab: add confirmDelete, deletePassword, deleteError state refs
- AdminUsersTab: add startDelete, cancelDelete, confirmDoDelete functions (mutually exclusive with deactivate panel)
- AdminUsersTab: Delete button added to active and deactivated user rows
- AdminUsersTab: inline password confirmation panel with Argon2 verification via backend
2026-05-30 11:39:10 +02:00
curo1305
390a693ec6
feat(05-11): add UserDeleteConfirm model + admin password verification in delete_user
...
- Import verify_password from services.auth
- Add UserDeleteConfirm Pydantic model (admin_password field)
- delete_user handler now requires body; fails fast with 403 on wrong password
- All existing SEC-09 cloud/MinIO purge logic and audit log unchanged
- Three new tests pass: 204 on correct pw, 403 on wrong pw, 422 on no body
2026-05-30 11:37:59 +02:00
curo1305
8727592bff
test(05-11): add failing tests for delete_user password verification
...
- test_delete_user_correct_password: 204 on correct admin password
- test_delete_user_wrong_password: 403 on wrong password, user survives
- test_delete_user_no_body: 422 when no body provided (Pydantic validation)
2026-05-30 11:37:12 +02:00
curo1305
bd3b637d30
chore: merge executor worktree (05-10 OAuth fix + cloud UI gaps)
2026-05-30 11:33:57 +02:00
curo1305
f5ea2103b3
docs(05-10): complete OAuth initiate fix + cloud UI gap closure plan
2026-05-30 11:31:42 +02:00
curo1305
87de148a59
feat(05-10): OAuth fetch + Nextcloud edit fix + Edit on ERROR + text overflow
...
- client.js: add initiateOAuth() and getConnectionConfig() helpers
- SettingsCloudTab: replace window.location.href with initiateOAuth() + fetch/JWT
- SettingsCloudTab: add Edit button to ACTIVE and ERROR blocks for non-OAuth providers
- SettingsCloudTab: wrap ConfirmBlock in w-full overflow-hidden div
- CloudCredentialModal: add existing prop, edit-mode pre-population via /config endpoint
- CloudCredentialModal: add showAdvanced + customEndpoint for Nextcloud custom paths
- ConfirmBlock: add break-words class to message paragraph
- cloud.py: add GET /api/cloud/connections/{id}/config endpoint (non-secret fields)
2026-05-30 11:30:13 +02:00
curo1305
e2e499b8b1
feat(05-10): oauth_initiate returns 200 JSON {url} instead of 302 redirect
...
- Remove response_class=RedirectResponse from @router.get decorator
- Replace both RedirectResponse(status_code=302) returns with JSONResponse({url})
- Frontend can now inject Bearer header before navigating to OAuth URL (T-05-10-01)
- Update test_connect_google_drive to expect 200 JSON (regression fix)
2026-05-30 11:24:33 +02:00
curo1305
9b6d3f91d4
test(05-10): add failing tests for OAuth initiate JSON URL return
2026-05-30 11:23:38 +02:00
curo1305
dc475aaaa2
chore: merge executor worktree (05-09 cloud doc access)
2026-05-30 11:20:41 +02:00
curo1305
7534f679f3
docs(05-09): complete cloud document access fixes plan — PATCH endpoint, cloud-aware re-analyze, authenticated preview
2026-05-30 11:19:33 +02:00
curo1305
4a42ccee5a
feat(05-09): authenticated document preview via fetch + Blob URL
...
- Add fetchDocumentContent() to client.js: fetch with Bearer auth, 401 refresh
retry pattern, returns raw Response (not parsed JSON) for blob() calls
- Replace iframe :src=proxyUrl (unauthenticated) in DocumentPreviewModal.vue
with authenticated fetch → blob → URL.createObjectURL; loading/error states;
URL.revokeObjectURL on unmount to prevent memory leaks
- Replace window.open(rawUrl) in DocumentView.vue openPdf() with
fetchDocumentContent → blob → objectUrl → window.open; 60s auto-revoke
- Frontend build exits 0 with zero errors
- Closes T-05-09-04: no persistent unauthenticated content exposure
2026-05-30 11:18:01 +02:00
curo1305
6d094d17f0
feat(05-09): PATCH /documents/{id} endpoint + cloud-aware Celery re-analyze
...
- Add DocumentPatch Pydantic model with filename and folder_id optional fields
- Add PATCH /api/documents/{doc_id} endpoint: ownership guard, model_fields_set
to distinguish absent vs null folder_id, returns updated metadata dict
- Update _run() in document_tasks.py to use get_storage_backend_for_document
for non-MinIO backends instead of hardcoded MinIO path
- CloudConnectionError caught in cloud path: returns extract_failed status
- Update test to use pure unit mocks (no PostgreSQL) for _run() cloud routing
- All 3 plan tests pass; 23 test_cloud.py tests pass
2026-05-30 11:16:01 +02:00
curo1305
9bc056100c
test(05-09): add failing tests for PATCH /documents/{id} and cloud-aware re-analyze
...
- test_patch_document_filename: expects 200 with updated filename (PATCH endpoint missing → 405)
- test_patch_document_wrong_owner: expects 404 for non-owner (PATCH endpoint missing → 405)
- test_reanalyze_cloud_document_routes_to_cloud_backend: expects cloud backend called for nextcloud docs
2026-05-30 11:13:31 +02:00
curo1305 and Claude Sonnet 4.6
f006c00d49
docs(05): create UAT gap closure plans 09-11
...
Three new plans address all 6 diagnosed gaps from 05-UAT.md:
- 05-09: cloud document open (fetch+Blob URL), re-analyze (cloud-aware
Celery task), and edit (PATCH /api/documents/{id})
- 05-10: OAuth initiate JSON response fix, Nextcloud custom endpoint
edit round-trip, Edit button on ERROR rows, confirmation text overflow
- 05-11: admin hard-delete with admin-password confirmation (backend
UserDeleteConfirm model + frontend inline panel)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-30 10:39:47 +02:00
curo1305
7691477c6d
docs(05): mark Phase 5 complete — all 8 plans executed, security gates passed, human checkpoint approved
...
- ROADMAP.md: all 05-01..05-08 plans marked [x], phase gates [x], Progress Table row updated to Complete 2026-05-29
- STATE.md: status→complete, completed_phases→5, percent→100, session continuity entry added
2026-05-29 09:16:45 +02:00
curo1305
f1a7f52616
fix(security): bump python-multipart>=0.0.27 and PyMuPDF>=1.26.7 — pip-audit findings
2026-05-29 09:14:27 +02:00
curo1305
c6a97b6a89
docs(05-08): complete cloud sidebar tree plan — awaiting human checkpoint
2026-05-29 08:34:42 +02:00
curo1305
98576ac298
feat(05-08): add Cloud Storage collapsible section to AppSidebar
...
- Import CloudProviderTreeItem and useCloudConnectionsStore
- Add cloudExpanded ref (default true) and activeCloudConnections/loadingCloudConnections computed
- Insert Cloud Storage section between Folders and Topics sections
- Fetch connections on mount; render one CloudProviderTreeItem per ACTIVE connection
- Empty state: 'No cloud storage connected'; loading state: 'Loading...'
2026-05-29 08:33:33 +02:00
curo1305
34b0593782
feat(05-08): add cloud tree components and getCloudFolders API function
...
- Add getCloudFolders(provider, folderId) to api/client.js (GET /api/cloud/folders/{provider}/{folderId})
- Create CloudProviderTreeItem.vue: lazy-load folder tree per connection, providerIconColor computed, expand/collapse arrow, loading/error states
- Create CloudFolderTreeItem.vue: recursive folder tree node with is_dir expand arrow, lazy-load children, depth padding
2026-05-29 08:32:19 +02:00
curo1305
ec0c69fb4e
docs(05-07): complete cloud storage frontend UI plan — SUMMARY and STATE
...
- useCloudConnectionsStore, 3-tab SettingsView, SettingsCloudTab, CloudCredentialModal
- 61 Vitest tests passing, Vite build exits 0
- Fixed pre-existing build failure (top-level await) via build.target=esnext
2026-05-29 08:18:48 +02:00
curo1305
63a68296a5
feat(05-07): 3-tab SettingsView, SettingsCloudTab, CloudCredentialModal
...
- Convert SettingsView to 3-tab layout (Preferences/AI/Cloud) matching AdminView pattern
- Extract SettingsPreferencesTab.vue and SettingsAiTab.vue from original SettingsView
- Create SettingsCloudTab.vue with all 4 providers, status badges, action buttons
- Create CloudCredentialModal.vue for WebDAV/Nextcloud credential input
- Handle OAuth callback query params (cloud_connected/cloud_error) in SettingsView.onMounted
- Add success toast (auto-dismiss 5s) and persistent error banner for OAuth results
- Fix pre-existing build failure: add build.target=esnext to vite.config.js for top-level await support
- 2 SettingsCloudTab mount tests passing (W4 — CLAUDE.md)
2026-05-29 08:12:36 +02:00
curo1305
612d542c06
feat(05-07): cloud connections Pinia store + API client functions
...
- Create useCloudConnectionsStore with connections/loading/error refs
- fetchConnections, disconnect(id), disconnectAll() actions
- Append listCloudConnections, disconnectCloud, connectWebDav, updateDefaultStorage to api/client.js
- Add vitest test script to package.json
- 4 unit tests passing (W4 — CLAUDE.md)
2026-05-29 08:05:59 +02:00
curo1305
c44e861271
docs(05-06): complete cloud upload/test integration plan — SUMMARY and STATE
...
- Create 05-06-SUMMARY.md: documents.py cloud extension + 20 passing cloud tests
- Update STATE.md: plan 5→6 of 8, session notes, next action → 05-07
- Update ROADMAP.md: mark 05-06 as complete [x]
2026-05-29 07:58:03 +02:00
curo1305
d84e38acca
test(05-06): promote 11 integration test stubs to real passing tests
...
- test_connect_google_drive: OAuth initiate redirects to Google (Redis mocked)
- test_oauth_callback_valid_state: valid state + mocked Flow.fetch_token → 302 (CLOUD-01)
- test_oauth_callback_invalid_state: invalid state → error redirect (CLOUD-01)
- test_webdav_connect_validates: localhost URL → 422 (D-17 SSRF)
- test_credentials_enc_not_exposed: credentials_enc absent from response (CLOUD-02, SEC-08)
- test_cloud_upload_no_presigned: cloud upload returns no upload_url (CLOUD-03)
- test_connection_status_display: ACTIVE status in list response (CLOUD-04)
- test_invalid_grant_sets_requires_reauth: 503 on invalid_grant (CLOUD-05)
- test_disconnect_deletes_credentials: DELETE 204 + DB row gone (CLOUD-06)
- test_admin_cannot_see_credentials: admin gets 403 (SEC-08 IDOR)
- test_cross_user_idor: wrong-owner delete → 404 (SEC-08 IDOR)
Also fix CloudConnectionOut.id field validator to accept UUID objects from ORM
(Rule 1: Bug - UUID id caused pydantic validation error on list_connections)
All 20 cloud tests PASSED; full suite: 282 passed, 1 pre-existing failure
2026-05-29 07:51:02 +02:00