Commit Graph
100 Commits
Author SHA1 Message Date
curo1305andClaude Sonnet 4.6 0ddd983797 chore(planning): update config.json and remove stale debug artifact
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 20:35:58 +02:00
curo1305andClaude Sonnet 4.6 b67e77dd69 docs(13): add phase 13 planning artifacts — virtual local cloud operations
Plans 01–11, CONTEXT, PATTERNS, RESEARCH, REVIEW-FIX, and updated
SUMMARY and CONTEXT for the virtual-local-cloud-operations phase.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 20:34:57 +02:00
curo1305andClaude Sonnet 4.6 73328eee0b docs(12.1): add phase 12.1 planning artifacts — Nextcloud root listing fix
Plans 01–04, CONTEXT, PATTERNS, RESEARCH, UAT, and .gitkeep for
the fix-nextcloud-root-listing-and-sync-visibility sub-phase.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 20:34:47 +02:00
curo1305andClaude Sonnet 4.6 ab31c1344c chore(gitignore): exclude .claire/ and .claude/ local tool directories
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 20:34:42 +02:00
curo1305 e96137174f docs(14-09): complete selective-analysis-and-byte-cache plan 2026-06-23 20:11:42 +02:00
curo1305andClaude Sonnet 4.6 90e1b525f1 docs(14-09): Phase 14 closeout — docs, version bump v0.3.0→v0.4.0, security evidence
- CLAUDE.md/AGENTS.md: update current-state line to v0.4.0 Phase 14 complete;
  add Phase 14 shared module map entries (cloud_cache, cloud_analysis,
  cloud_analysis_processing, cloud_analysis_tasks, analysis router, cache API);
  add Phase 14 non-negotiable rules (hydrate_and_cache_bytes single entry point,
  IDs-only broker payload, object_key/credentials_enc excluded at schema level)
- README.md: bump to v0.4.0; add Selective cloud analysis and Cloud byte cache
  features; add Analysis API table (Phase 14 endpoints)
- SECURITY.md: add Phase 14 threat register (T-14-01..T-14-15) with evidence,
  security gate results, and accepted risks
- backend/main.py: bump FastAPI version to 0.4.0
- frontend/package.json: bump version to 0.4.0
- ROADMAP.md: mark Phase 14 complete (9/9 plans), plan 14-09 checked off
- 14-VALIDATION.md: gate evidence, requirement coverage, acceptance criteria check
- 14-SECURITY.md: security evidence summary and gate checklist

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 20:05:49 +02:00
curo1305 2d697a6036 docs(14-08): complete settings integration plan 2026-06-23 19:55:32 +02:00
curo1305 ba15811f91 feat(14-08): add Analysis Settings section to SettingsCloudTab
- Add cache limit number input with tier cap validation and usage display
- Add segmented control for simplified vs detailed analysis progress (D-06)
- Add segmented control for pause-batch vs continue-item failure behavior (D-11)
- Load cache settings on mount via loadCacheSettings; surface API errors
- Keep existing connection health/reconnect/disconnect UX intact
- All 471 frontend tests pass; no regressions
2026-06-23 19:52:23 +02:00
curo1305 6fc30ac755 feat(14-08): add cache settings API/store wiring for Settings integration
- Fix getCacheSettings/updateCacheSettings URLs to use /api/cloud/analysis/cache
  and /api/cloud/analysis/cache/settings (Rule 1: wrong URLs per Plan 14-03 backend)
- Add loadCacheSettings action: hydrates tierCapBytes, cacheUsage, cacheLimit,
  detailedAnalysisProgress, failureBehavior from server without clearing on error
- Add tierCapBytes, cacheUsage, cacheSettingsLoading, cacheSettingsError state
- updateCacheSettings merges full CacheStatusOut response into local state
2026-06-23 19:50:35 +02:00
curo1305 22e33f1255 docs(14-07): complete frontend analysis UX plan 2026-06-23 19:46:13 +02:00
curo1305 04e6ea2ba2 feat(14-07): extend StorageBrowser and CloudFolderView with analysis UX (Task 2)
StorageBrowser:
- Add analyze-file button per cloud file row (D-01); placed inside name cell
  to avoid interfering with capability-gated file-row-actions (Rule 1 compliance)
- Add file-select checkboxes for multi-select analysis (cloud mode only)
- Add analyze-selection toolbar button (D-01, ANALYZE-02)
- Add analyze-folder toolbar button when breadcrumb is non-empty (D-01)
- Add analyze-connection toolbar button when connectionRoot is set (D-01, ANALYZE-03)
- Add analysisEstimate prop + analysis-estimate-modal (D-03) with estimate-start button
- Add analysisQueue prop + analysis-aggregate-progress with simplified/detailed labels (D-05/D-06)
- Add expandable per-item list via analysis-queue-expand toggle (D-05)
- Add per-item cancel/retry/skip controls in expanded list (D-09, ANALYZE-05)
- Add Cancel all batch button (D-09, ANALYZE-05)
- Emit: analyze-file, analyze-selection, analyze-folder, analyze-connection,
  analysis-confirmed, analysis-cancelled, analysis-item-cancel/retry/skip, analysis-cancel-all

CloudFolderView:
- Pass analysis props to StorageBrowser from cloudStore
- Add analysis estimate, pending request state
- Handle all analysis emits: onAnalyzeFile, onAnalyzeSelection, onAnalyzeFolder,
  onAnalyzeConnection, onAnalysisConfirmed, onAnalysisItemCancel/Retry/Skip, onAnalysisCancelAll
- Routes all API calls through cloudStore (requestEstimate, enqueueAnalysis, etc.)
2026-06-23 19:42:53 +02:00
curo1305 1291040f9b feat(14-07): add analysis API helpers and store state/actions (Task 1)
- Add estimateAnalysis, enqueueAnalysis, getAnalysisJobStatus, listAnalysisJobs,
  cancelAnalysisJob, cancelAnalysisItem, skipAnalysisItem, retryAnalysisItem,
  getCacheSettings, updateCacheSettings to api/cloud.js
- Extend cloudConnections store with analysis state: activeAnalysisJob, analysisQueue
  (computed), failureBehavior, detailedAnalysisProgress, cacheLimit
- Add store actions: requestEstimate, enqueueAnalysis, fetchJobStatus, cancelJob,
  retryItem, skipItem, cancelItem, setFailureBehavior, setDetailedAnalysisProgress,
  updateCacheSettings
- Add translateAnalysisStatus (D-06: single translation source for components)
- Status labels: simplified (waiting/working/done/skipped/failed) and detailed modes
- Credentials never stored in queue state (T-14-02)
2026-06-23 19:35:33 +02:00
curo1305 a2b7928ba4 docs(14-06): complete byte cache for open/preview/download plan 2026-06-23 16:33:01 +02:00
curo1305 b84b912acf test(14-06): add cache transparency assertion to frontend open/preview tests
- Add cache_backed_response_has_no_object_key describe block to CloudFolderOpenPreview.test.js
- Verifies openCloudFile response processed by CloudFolderView never exposes object_key, MinIO paths, or credentials_enc in rendered HTML or API call arguments (T-14-02)
- All 9 tests pass (8 pre-existing + 1 new)
2026-06-23 16:29:11 +02:00
curo1305 dfc335022f feat(14-06): route preview/download bytes through durable byte cache
- Add hydrate_and_cache_bytes to services/cloud_cache.py (Plan 06 cache lifecycle)
  - Cache-hit path: pin existing entry, read from MinIO, release pin in finally
  - Cache-miss path: fetch from provider, store in MinIO, create/reactivate entry, pin during response, release pin in finally
  - CacheQuotaExceeded and MinIO failures are non-fatal (bytes returned from provider path)
  - evict_lru_entries run after pin release to stay within user cache limit
- Update preview_cloud_file and download_cloud_file in operations.py to call hydrate_and_cache_bytes
  - Version key computed from CloudItem metadata (no provider call required for key resolution)
  - Shared _make_minio_cache_wrapper helper eliminates duplicate adapter code
  - Falls through to direct provider fetch when no CloudItem row found
- Add _make_minio_cache_wrapper helper to operations.py (DRY, shared by preview and download)
- Add 5 new tests to test_cloud_cache.py: cache-miss fetches provider, cache-hit skips provider, pin released on hit, pin released on miss, user isolation
- Add 3 new security tests to test_cloud_security.py: preview response excludes object_key, download response excludes object_key, foreign-user IDOR via download blocked
2026-06-23 16:28:06 +02:00
curo1305 5a9f3a628e docs(14-05): complete cloud analysis processing plan 2026-06-23 16:10:42 +02:00
curo1305 f235d894fb feat(14-05): add Celery cloud analysis task with retry harness (Task 2)
- Implement tasks/cloud_analysis_tasks.py: sync Celery bridge to async processing
- Broker payload contains IDs only — credentials decrypted in worker (T-14-10)
- _TransientError and _ClassificationRetry sentinels for bounded retry (max=3)
- Auth errors are terminal (not retried); MaxRetriesExceeded writes failure status
- celery_app.py: add cloud_analysis_tasks route and import registration
- Add 6 contract tests: task registration, broker payload shape, queue routing,
  bounded retries, sentinel pattern, connection-not-found graceful drop
2026-06-23 16:06:07 +02:00
curo1305 cea9980aaf feat(14-05): add cloud analysis processing service (Task 1)
- Implement services/cloud_analysis_processing.py with full pipeline:
  queued -> downloading -> extracting -> classifying -> indexed
- Stale guard: version key comparison fires before provider byte fetch (T-14-13)
- Cache pin lifecycle: pin acquired before bytes used, released in finally block (T-14-12)
- No provider mutation methods called: adapter only used via get_object (T-14-03)
- No local Document row created: classification targets CloudItem directly
- Cooperative cancellation check at job/item level before each stage
- ProcessingResult dataclass with status, cache_entry_id, error_code fields
- Add 4 contract tests: status_transitions, stale_detection, pin_release, no_mutations
2026-06-23 16:02:44 +02:00
curo1305 1ae9930ca7 docs(14-04): complete analysis orchestration and API plan 2026-06-23 15:54:49 +02:00
curo1305 ba48d625dd feat(14-04): add analysis API routes and typed schemas
- POST /analysis/connections/{id}/estimate: scope estimate without bytes (T-14-04)
- POST /analysis/connections/{id}/jobs: enqueue job, returns job_id (ANALYZE-01)
- GET /analysis/jobs, GET /analysis/jobs/{id}: job status list and detail
- POST /analysis/jobs/{id}/cancel: batch cancel (queued items immediate; running cooperative)
- POST /analysis/jobs/{id}/items/{item_id}/cancel|skip|retry: per-item controls (ANALYZE-05)
- AnalysisEstimateRequest/Out, AnalysisEnqueueRequest/Out, AnalysisJobOut: typed schemas
- AnalysisJobOut: both simple (waiting/working/done/skipped/failed) and per-stage counts
- All routes use get_regular_user — admin blocked (T-14-01)
- Response schemas exclude credentials_enc, object_key, raw provider URLs (T-14-02)
- 14/14 test_cloud_analysis_api.py pass; 7 new analysis security tests pass (33/33 total)
2026-06-23 15:50:37 +02:00
curo1305 3f26cd2059 feat(14-04): add cloud_analysis orchestration service
- estimate_scope: file/selection/folder/connection scope from cached metadata only
- enqueue_analysis_job: create CloudAnalysisJob + items; already_current skip without bytes
- already_current detection: indexed analysis_status + live metadata check (metadata-only, T-14-04)
- cancel_job, cancel_job_item, skip_job_item, retry_job_item: full control operations
- check_scan_quota: seam for future tier enforcement (always True in Phase 14)
- _is_supported: content type + extension list; explicit unsupported-override for .exe etc
- get_adapter / resolve_provider_metadata: stubs for Plan 05 provider integration
- No provider mutation methods called (T-14-03); no bytes downloaded (T-14-04)
- 16/16 test_cloud_analysis_contract.py tests pass
2026-06-23 15:50:24 +02:00
curo1305 4e02b04ba8 docs(14-03): complete cache service and API plan 2026-06-23 15:36:24 +02:00
curo1305 299d4b523d feat(14-03): cache settings/status API and security tests
- api/cloud/cache.py: GET /analysis/cache, PATCH /analysis/cache/settings
- api/cloud/analysis.py: analysis router aggregator (Phase 14 parent)
- schemas.py: CacheStatusOut, CacheSettingsUpdateRequest (explicit allowlists)
- __init__.py: register analysis_router under /api/cloud
- 7 new security tests: admin block, unauthenticated block, object_key exclusion,
  response structure, enum validation, tier cap enforcement (T-14-01..02, T-14-08)
- All 47 plan target tests pass (test_cloud_cache.py + test_cloud_security.py)
2026-06-23 15:32:12 +02:00
curo1305 5bdd23f3bc feat(14-03): add cache orchestration functions and tests
- retain_or_reuse_cache_entry: reuse non-evicted entry or reactivate evicted row
- pin_cache_entry / release_cache_entry: pin_count lifecycle management
- update_cache_access: touch last_accessed_at for LRU ordering
- Ownership assertions in all new service functions (T-14-06)
- 9 new integration tests covering retain/reuse, pin/release, and isolation
2026-06-23 15:24:13 +02:00
curo1305 54cc78eb96 docs(14-02): complete Phase 14 Plan 02 — schema and service helpers
- 14-02-SUMMARY.md: documents migration 0007, ORM models, version-key
  precedence helper, settings service, and Phase 14 cache functions
- STATE.md: advance to Plan 3 of 9, record P02 metrics and decisions
2026-06-23 15:17:05 +02:00
curo1305 1df61040c6 feat(14-02): add version-key, settings helpers and Phase 14 cache service functions
- cloud_analysis_versioning.py: compute_version_key with version>etag>fingerprint
  precedence (D-19); compute_fingerprint helper; content_hash is optional post-
  hydration only (D-20); raises ValueError only, no HTTPException
- cloud_analysis_settings.py: get_or_create_user_analysis_settings (upsert on
  first access), update_user_analysis_settings with enum validation and tier-capped
  cache limit, build_default_settings for API responses; raises ValueError only
- cloud_cache.py: Phase 14 durable cache functions added alongside existing Phase 12
  in-memory TTL cache — create_cache_entry, list_cache_entries (owner-scoped),
  evict_lru_entries (LRU, skips pin_count>0 and active_job_count>0), increment/
  decrement_quota_for_cache (atomic UPDATE pattern); re-exports compute_version_key
  from cloud_analysis_versioning so tests have one import site
2026-06-23 15:14:19 +02:00
curo1305 fd76d06b3a feat(14-02): add migration 0007 and ORM models for cloud analysis cache schema
- 0007_cloud_analysis_cache.py: new Alembic migration adding 4 Phase 14 tables
  - cloud_byte_cache_entries: durable MinIO cache with version_key uniqueness,
    pin_count/active_job_count guards, LRU eviction indexes
  - cloud_analysis_jobs: batch job rows (scope_kind, status, aggregate counters,
    provider_bytes_estimate, failure_behavior)
  - cloud_analysis_job_items: per-item idempotency rows (status vocabulary,
    controlled error fields, cache_entry_id, retry_count, version_key fingerprint)
  - user_analysis_settings: per-user preferences (progress_detail, failure_behavior,
    cloud_cache_limit_bytes)
  - Reversible downgrade drops Phase 14 objects only
- db/models.py: CloudByteCacheEntry, CloudAnalysisJob, CloudAnalysisJobItem,
  UserAnalysisSettings ORM models mirroring migration
2026-06-23 15:06:24 +02:00
curo1305 493d348ba6 docs(14-01): complete Phase 14 Plan 01 red test contract 2026-06-23 15:00:57 +02:00
curo1305andClaude Sonnet 4.6 7f2f570582 test(14-01): add RED frontend tests for analysis queue UX and store actions
- StorageBrowser.analysis-queue.test.js: row-level Analyze action (D-01),
  toolbar Analyze Selection/Folder/Connection (D-01..03), estimate modal
  with D-03 required fields (supported_count/bytes/unsupported, Start action),
  aggregate progress with simplified/detailed labels (D-05..08), expandable
  queue item list, per-item cancel/retry/skip controls (D-09..10),
  batch Cancel all (D-09), architecture no-parallel-grid guard (CLAUDE.md)
- cloudConnections.analysis.test.js: analysis state existence, translateAnalysisStatus
  single-source (D-06/D-12), API call assertions without credentials (T-14-02),
  cancel/retry/skip action coverage (ANALYZE-05), failure_behavior default=pause_batch
  (D-11), detailedAnalysisProgress preference (D-06), cache limit exposure
  (CACHE-04/D-15), credential-free localStorage guard

Requirements: ANALYZE-01..05, CACHE-04..05
All tests fail against missing Phase 14 implementation — no import errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 14:56:39 +02:00
curo1305andClaude Sonnet 4.6 f67559c7f0 test(14-01): add RED contract tests for cloud analysis and byte cache (backend)
- test_cloud_analysis_contract.py: estimate (single/selection/connection/folder),
  already-current skip without byte fetch, changed-etag requeue, no-mutation
  invariant, IDOR/admin-negative access (T-14-01..04), cancel/retry transitions
- test_cloud_cache.py: CloudByteCacheEntry schema, LRU eviction with pin
  protection, quota increment/decrement seam (T-14-05), owner isolation
  (CACHE-05), object-key secrecy (T-14-02), version-key precedence helper
- test_cloud_analysis_api.py: route registration gates, job status shape,
  simplified/detailed progress labels (D-06), skip/cancel controls, scan
  quota seam (D-13), failure_behavior field acceptance, unauthenticated block

Requirements: ANALYZE-01..07, CACHE-03..05
All tests fail against missing Phase 14 modules — no syntax/import errors in tests themselves

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 14:56:29 +02:00
curo1305 b528b51881 docs(phase-14): plan selective analysis and byte cache 2026-06-23 14:24:43 +02:00
curo1305 3514fdcf3a docs(workflow): require gsd worktrees before edits 2026-06-23 14:10:41 +02:00
curo1305 fac7721dd9 docs(state): record phase 14 context session 2026-06-23 14:04:48 +02:00
curo1305 d3700e20c4 docs(14): capture phase context 2026-06-23 13:59:53 +02:00
curo1305andClaude Sonnet 4.6 2f00e122d3 docs(phase-13): update VALIDATION.md — all tasks green, wave-0 complete
Nyquist audit 2026-06-23: 3 gaps found and resolved (open/create-folder/rename
audit writes). All 10 tasks marked green, wave_0_complete: true, status: complete.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 08:17:29 +02:00
curo1305andClaude Sonnet 4.6 ed046752e4 test(13): add Nyquist validation — promote 3 xfail audit tests to green
Implemented write_audit_log calls for open_cloud_file, create_cloud_folder,
and rename_cloud_item in api/cloud/operations.py. Removed xfail markers from
test_cloud_audit.py. All 11 audit tests pass; 360 cloud tests pass total.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 08:17:24 +02:00
curo1305andClaude Sonnet 4.6 fd48c5b928 docs(phase-13): add security threat verification — 34/34 threats CLOSED
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 07:52:31 +02:00
curo1305 0c4f9ccba3 test(13): persist human verification items as UAT 2026-06-23 07:41:48 +02:00
curo1305 40b1572582 test(13): persist human verification items as UAT 2026-06-23 00:43:01 +02:00
curo1305 f92270fda4 test(13): persist human verification items as UAT 2026-06-23 00:42:48 +02:00
curo1305 b1a9f436c4 fix(13): WR-06 read result.status (not result.state) in testConnection to reflect actual server field name 2026-06-23 00:30:01 +02:00
curo1305 60df8552b5 fix(13): CR-05 commit audit log after write_audit_log in reconnect endpoint so event is not silently lost 2026-06-23 00:29:34 +02:00
curo1305 af0de30e93 fix(13): CR-04 soft-delete CloudItem row on successful cloud delete to prevent orphaned metadata 2026-06-23 00:29:11 +02:00
curo1305 405c7a6610 fix(13): CR-03 wrap post-upload DB block in try/except to handle provider-success/DB-fail divergence 2026-06-23 00:28:34 +02:00
curo1305 a1d1c3ba2e fix(13): CR-02 apply PurePosixPath.name guard in WebDAV upload_file and rename to prevent path traversal 2026-06-23 00:27:52 +02:00
curo1305 d4b2697109 fix(13): CR-01 use RFC 6266 filename*=UTF-8'' encoding in Content-Disposition to prevent header injection 2026-06-23 00:26:59 +02:00
curo1305 ebc74f4abe fix(13): CR-06 re-raise HTTPException in preview_cloud_file instead of masking as unsupported_preview 2026-06-23 00:26:23 +02:00
curo1305 fcb38c50b1 docs(13): add code review report 2026-06-23 00:24:20 +02:00
curo1305 cd5bd82260 docs(13-11): update ROADMAP.md via gsd roadmap.update-plan-progress — Phase 13 11/11 summaries verified 2026-06-23 00:19:40 +02:00
curo1305 f09387a9d4 docs(13-11): add self-check result to summary 2026-06-23 00:18:52 +02:00
curo1305 25cc2537bb docs(13-11): complete Phase 13 closeout plan summary and state update
- 13-11-SUMMARY.md: gate evidence (766 backend + 429 frontend tests pass, bandit 0 HIGH, npm audit clean, gitleaks 3 pre-existing), version 0.3.0, phase complete
- STATE.md: Phase 13 marked complete, progress updated, key decisions carried forward
2026-06-23 00:18:31 +02:00
curo1305 e68faf3051 chore(13-11): bump to v0.3.0, update docs, roadmap, and Phase 13 security gate evidence
- Version bump: 0.2.6 → 0.3.0 (Phase 13 complete — full cloud mutation surface shipped)
- CLAUDE.md: update current-state, shared module map, and Phase 13 non-negotiable rules
- README.md: add cloud file management, connection health, and authorized preview features; add Phase 13 mutation API table; mark Phase 13 complete
- ROADMAP.md: mark Phase 13 11/11 plans complete
- SECURITY.md: add Phase 13 threat register (T-13-01 through T-13-34), gate evidence (766 backend + 429 frontend tests pass, bandit 0 HIGH, npm audit 0 high/critical, gitleaks 3 pre-existing)
2026-06-23 00:14:57 +02:00
curo1305 e809df9f51 docs(13-10): complete frontend health UX and rendered-flow plan summary 2026-06-22 23:59:08 +02:00
curo1305 a7e55d1bb0 feat(13-10): reactive mock store in rendered-flow test surfaces health banner and no-probe assertions
- CloudFolderRenderedFlow.test.js: mock store uses Vue refs so folderFreshness propagates
  reactively to StorageBrowser via CloudFolderView's template binding (D-12 GREEN)
- setBrowseState in mock now updates _mockFolderFreshness so cloud-health-banner appears
  when API returns warning freshness (T-13-30 mitigated)
- Added testCloudConnection to API mock so D-13 no-probe assertion can verify it was not called
- beforeEach resets reactive refs for test isolation
- 11 rendered-flow tests pass; 70 total across health/store/view/rendered-flow suites
2026-06-22 23:56:13 +02:00
curo1305 60afb028bf feat(13-10): store-backed health mapping, reconnect UX, no-probe-on-navigation, and Google Drive consent copy
- D-12: connectionHealth ref as single source for browser compact status and Settings diagnostics
- D-13: handleHealthFailure schedules pendingHealthRetest; navigation never triggers probe
- D-13: testConnection method in store (explicit action only, not navigation side-effect)
- D-14: markReconnecting preserves cached browseItems as stale; markReconnectRefreshPending flag
- D-15: degraded vs requires_reauth health states distinguished in store vocabulary
- D-17: Google Drive scope notice in SettingsCloudTab for all connect/reconnect paths
- StorageBrowser: cloud-health-banner (warning/stale) and requires-reauth prompt with reconnect action
- 59 tests passing: store, Settings, and CloudFolderView health/reconnect suites
2026-06-22 23:55:58 +02:00
curo1305 a77b7324aa docs(13-09): complete move and delete mutation plan summary 2026-06-22 20:04:38 +02:00
curo1305 508d27643b feat(13-09): move stale-guard, descendant safety, reconciliation, delete disclosure, and metadata-only auditing
Move endpoint (D-07, D-08, D-09, T-13-27, T-13-28, T-13-29):
- Descendant destination detection via cloud_items ancestor-chain walk (D-09)
- Stale provider result marks source folder non-fresh, returns typed stale body (D-07)
- Success: upsert_cloud_item with new parent_ref before returning
- Success: update_folder_state for both source and destination folders
- Success: write_audit_log 'cloud.item_moved' with metadata-only payload

Delete endpoint (D-10, D-11, T-13-29):
- Pre-fetch item kind for D-10 folder-vs-file disclosure
- Success: update_folder_state for parent folder before returning
- Success: write_audit_log 'cloud.item_deleted' with delete_kind metadata
- Response carries is_folder/item_kind for frontend disclosure
- Failed deletes never emit audit rows

Promote xfail markers in test_cloud_audit.py for move and delete audit rows
2026-06-22 20:02:09 +02:00
curo1305 af7d45f3c4 test(13-09): add failing RED tests for move stale-guard, reconciliation, and delete disclosure/audit
- Move: stale etag returns 409 + refreshes source folder state
- Move: descendant destination rejected (D-09)
- Move: success upserts cloud_item with new parent_ref (reconcile-before-return)
- Move: success marks source + destination folders non-fresh
- Move: success writes metadata-only 'cloud.item_moved' audit row
- Delete: success marks parent folder non-fresh
- Delete: folder disclosure stronger than file (is_folder=True, D-10)
- Delete: success writes metadata-only 'cloud.item_deleted' audit row
- Delete: failed delete must not write false audit event
2026-06-22 19:58:00 +02:00
curo1305 3e9355f42d docs(13-08): complete create-folder and rename collision, stale guard, reconciliation plan summary 2026-06-22 19:53:24 +02:00
curo1305 aaa63c19e4 feat(13-08): implement create-folder and rename collision retry, stale guard, and reconciliation
- create_cloud_folder: bounded collision retry (up to 5 attempts) with keep_both_name counter suffix (D-05, D-06)
- create_cloud_folder: stale precondition marks parent folder non-fresh and returns typed stale result (D-07)
- rename_cloud_item: stale precondition marks parent folder non-fresh via folder state update (D-07)
- create_cloud_folder: reconcile-before-return upserts new folder in cloud_items and invalidates parent (T-13-26)
- rename_cloud_item: reconcile-before-return upserts renamed item and invalidates parent folder (T-13-26)
- Import upsert_cloud_item, update_folder_state, keep_both_name, CloudResource from service modules
2026-06-22 19:51:57 +02:00
curo1305 9ad99461bf test(13-08): add RED tests for create-folder and rename collision retry, stale guard, and reconciliation
- Test 1: collision auto-retry with bounded window (D-05, D-06)
- Test 2: stale guard updates folder state and returns typed stale kind (D-07)
- Test 3: create-folder and rename success upserts CloudItem and invalidates parent folder
- Test 4: failed rename does not mutate CloudItem rows
2026-06-22 19:49:41 +02:00
curo1305 561a40908d docs(13-07): complete cloud queue and preview plan summary 2026-06-22 19:45:55 +02:00
curo1305 3351e63458 feat(13-07): wire binary-only preview and authorized download through shared actions
- CloudFolderView: onFileOpen calls openCloudFile(connectionId, provider_item_id, file) — never window.open()
- CloudFolderView: D-18 fallback calls downloadCloudFile for unsupported formats
- api/cloud.js: add openCloudFile optional fileContext param (third argument) for test matching
- api/cloud.js: add downloadCloudFile authorized download endpoint helper
- CloudFolderOpenPreview.test.js: fix makeBrowserStub missing name (findComponent by name)
- All 8 preview suite tests pass — binary-only preview + authorized fallback download
2026-06-22 19:42:48 +02:00
curo1305 e7e62bbab8 feat(13-07): implement sequential cloud upload queue with typed pause/resume
- StorageBrowser: add conflict dialog (D-03) and error dialog (D-04) for paused queue states
- StorageBrowser: add upload-queue-resolve emit for Keep both / Replace / Skip / Retry / Cancel all actions
- StorageBrowser: add upload-queue-list with upload-queue-item rows for remaining queued items
- StorageBrowser: suppress UploadProgress in cloud mode (replaced by queue dialogs)
- CloudFolderView: replace placeholder onFilesSelected with sequential queue runner
- CloudFolderView: handle upload-queue-resolve events for all conflict/error resolution actions
- api/cloud.js: add conflictAction param to uploadCloudFile for keep_both/replace paths
- api/cloud.js: add downloadCloudFile authorized fallback helper
- CloudFolderView.test.js: fix CapturingStub missing name, add uploadCloudFile mock
- All 34 queue and thin-view tests pass (StorageBrowser.cloud-queue + CloudFolderView)
2026-06-22 19:42:29 +02:00
curo1305 fc28e032be docs(13-06): complete upload follow-through plan 2026-06-22 19:31:38 +02:00
curo1305 d959e0cf42 feat(13-06): emit metadata-only audit rows on authoritative upload success
- Write cloud.file_uploaded audit row in same transaction as reconciliation
- Audit payload is metadata-only: filename, size_bytes, connection_id, provider_item_id, parent_ref
- No provider URLs, tokens, bytes, or document text in audit metadata (T-13-02)
- Non-success paths (conflict, offline, reauth_required) bypass audit write (T-13-21)
- Import get_client_ip from deps.utils and write_audit_log from services.audit
2026-06-22 19:29:46 +02:00
curo1305 33f0498503 test(13-06): add failing upload audit test (RED) — promote from xfail
- Remove xfail marker from test_upload_success_writes_metadata_only_audit_row
- Add mock adapter so test isolates audit write logic without real provider I/O
- Test expects cloud.file_uploaded audit row with metadata-only payload (T-13-20)
2026-06-22 19:28:11 +02:00
curo1305 7ecbec7df9 feat(13-06): route upload success through centralized reconciliation before returning
- Upsert uploaded item into cloud_items for stable row identity and navigation
- Invalidate parent folder state (warning/upload_mutated) so next browse re-fetches
- Reconcile-before-return: session committed before response returned
- Failed/conflict uploads bypass reconciliation path (T-13-19)
2026-06-22 19:26:41 +02:00
curo1305 4cd6499a96 test(13-06): add failing upload reconciliation tests (RED)
- test_upload_success_upserts_cloud_item_before_returning — verifies CloudItem row exists after success
- test_upload_success_marks_folder_freshness_stale — verifies folder state updated on success
- test_upload_failed_does_not_mutate_cloud_items — verifies failed uploads don't create phantom items
2026-06-22 19:25:47 +02:00
curo1305 cad5ef5de2 docs(13-05): complete upload mechanics plan 2026-06-22 19:22:40 +02:00
curo1305 3ddf4da6a8 feat(13-05): add typed upload route mechanics tests (Task 2)
- test_upload_success_returns_typed_uploaded_body: kind/provider_item_id/name/size
- test_upload_provider_retryable_error_returns_offline_kind: typed offline body
- test_upload_provider_conflict_returns_conflict_kind: provider-detected collision
- test_upload_reauth_result_is_typed_and_not_500: CONN-02 credential failure path
- test_upload_queue_control_semantics_are_backend_authored: all 4 queue fields
- test_upload_keep_both_name_format: route can use keep_both_name() from service
- test_upload_foreign_user_blocked: IDOR protection on upload route
- 7 new tests pass; full suite 741 passed
2026-06-22 19:20:18 +02:00
curo1305 e1ce4cbe14 feat(13-05): implement keep_both_name() for D-03/D-05 collision naming
- keep_both_name(filename, counter) inserts counter before first extension
- Handles compound extensions (archive.tar.gz → archive (1).tar.gz)
- Handles extensionless files (README → README (1))
- Lives in services/cloud_operations as shared upload-queue helper
- All 23 upload contract + keep-both naming tests pass
2026-06-22 19:17:59 +02:00
curo1305 f47e36d93d test(13-05): add failing RED tests for upload conflict semantics and keep-both naming
- TestUploadConflictSemantics: typed upload results across all 4 providers
- TestKeepBothNaming: keep_both_name() helper with counter before extension
- Tests verify credentials never appear in upload results (T-13-17)
- Upload kind values must be MUT_KINDS constants
- 16/23 pass (providers already have upload_file); 7 fail (keep_both_name missing)
2026-06-22 19:17:13 +02:00
curo1305 86a4fe0847 docs(13-04): complete authorized cloud mutations plan 2026-06-22 19:12:20 +02:00
curo1305 94a0617b9b feat(13-04): add authorized cloud content and mutation routes with typed bodies
- backend/api/cloud/operations.py: owner-scoped open, preview, download, create-folder,
  rename, move, delete, upload routes with typed kind/reason response bodies (D-02, D-03,
  D-05, D-07, D-08, D-09, D-10, D-11, D-18, T-13-01, T-13-14)
- backend/api/cloud/__init__.py: register operations_router on /api/cloud
- backend/api/cloud/connections.py: Google Drive OAuth scope broadened to 'drive' (D-17)
- backend/api/cloud/schemas.py: ConnectionHealthOut, ReconnectOut, ContentResultOut,
  MutationResultOut, CreateFolderRequest, RenameItemRequest, MoveItemRequest typed schemas
- frontend/src/api/cloud.js: centralized helpers for all Phase 13 routes
- backend/tests/test_cloud_mutations.py: mock adapter + settings key fixture; 21 tests pass
- backend/tests/test_cloud_audit.py: mark 6 RED audit tests as xfail (audit writes are
  T-13-05 scope for a later plan); update credential fixture to use settings key
2026-06-22 19:09:38 +02:00
curo1305 5c0bc2a3b4 feat(13-04): upgrade Google Drive scope to drive, add health/reconnect/content API helpers
- connections.py: Update Google Drive OAuth to broader `drive` scope (D-17)
  instead of `drive.file` so authorized users can operate on all existing Drive
  items, not just files created by this app. Both initiation and callback flows
  updated to keep scopes consistent.
- schemas.py: Add Phase 13 typed response schemas — ConnectionHealthOut, ReconnectOut,
  ContentResultOut, MutationResultOut, and request schemas CreateFolderRequest,
  RenameItemRequest, MoveItemRequest. All credential-free (T-13-14, CONN-03).
- api/cloud.js: Add centralized frontend helpers for getConnectionHealth,
  reconnectCloudConnection, testCloudConnection (D-12, D-13), plus authorized
  cloud content and mutation helpers: openCloudFile, previewCloudFile,
  createCloudFolder, renameCloudItem, moveCloudItem, deleteCloudItem, uploadCloudFile.

All reconnect/health/test tests pass (14/14). Security suite passes (19/19).
2026-06-22 18:49:47 +02:00
curo1305 7501036300 docs(13-03): complete cloud operations seam plan 2026-06-22 18:45:54 +02:00
curo1305 6784d3bdb7 feat(13-03): add cloud operations service and reconnect/health/test routes
- Create backend/services/cloud_operations.py as the single Phase 13 orchestration seam:
  get_connection_health (D-12), test_connection (D-13), reconnect_connection (CONN-01/02/03,
  D-14), disconnect_connection (D-16, explicit CloudItem cascade for SQLite compatibility)
- Add POST /connections/{id}/reconnect route (CONN-01/02/03, D-14)
- Add GET /connections/{id}/health route (D-12, T-13-02)
- Add POST /connections/{id}/test route (D-13, T-13-02)
- Update DELETE /connections/{id} to use service-layer disconnect with explicit
  CloudItem deletion (D-16; covers FK-cascade-less environments like SQLite tests)
- Fix (Rule 2 - T-13-02): add _scrub_audit_metadata() to admin audit log API to
  remove credential fields before returning audit rows to admin callers
- All 14 reconnect tests pass + 110 provider-contract tests pass
- Pre-existing failures in test_cloud_mutations and test_extractor are unrelated
2026-06-22 18:43:50 +02:00
curo1305 88a62da4c4 feat(13-03): extend cloud contract with mutable adapter and provider implementations
- Add MutableCloudResourceAdapter abstract class to cloud_base.py with Phase 13
  mutable-operation vocabulary (MUT_KIND_* / MUT_REASON_* constants, PreviewSupport)
- Add abstract methods: create_folder, rename, move, delete, upload_file + _normalize_error
- Update GoogleDriveBackend to implement MutableCloudResourceAdapter with Drive-scope
  methods; prefer trash() for delete (D-11); update SCOPES to drive (D-17)
- Update OneDriveBackend to implement MutableCloudResourceAdapter; use
  PublicClientApplication for refresh_token flow; Graph DELETE is always permanent (D-11)
- Update WebDAVBackend to implement MutableCloudResourceAdapter; SSRF guard via __init__
  (not per-call) for mutable methods; _validate_destination for MOVE SSRF (T-13-04)
- NextcloudBackend inherits all mutable methods from WebDAVBackend (no changes needed)
- Add build_mutable_cloud_adapter() to cloud_backend_factory.py
- All 184 tests pass (test_cloud_backends.py + test_cloud_provider_contract.py)
2026-06-22 18:31:53 +02:00
curo1305 f2411de85e docs(13-02): complete red frontend test plan for cloud queue, health, and preview 2026-06-22 18:16:47 +02:00
curo1305 8923ed5b3c test(13-02): add red store, health-flow, reconnect, and no-probe tests
- SettingsCloudTab.health.test.js: Test/Reconnect/Disconnect per-connection actions,
  explicit confirmation before credential removal, Google Drive broader scope consent
  copy (D-12/D-13/D-15/D-16/D-17/T-13-09)
- cloudConnections.test.js: connectionHealth state map, setConnectionHealth translation,
  degraded vs requires_reauth distinction, pendingHealthRetest after failure, reconnect
  preserves cached items, auto-test after connect, no-probe-on-navigation (D-12..D-15)
- CloudFolderRenderedFlow.test.js: warning+reconnect banner alongside cached items,
  requires_reauth renders actionable prompt, folder-navigate never triggers health probe
  (D-12/D-13/D-14/CONN-02/T-13-06)
2026-06-22 18:13:39 +02:00
curo1305 514925bd4c test(13-02): add red shared-browser queue/preview and thin-view tests
- StorageBrowser.cloud-queue.test.js: sequential upload queue, paused_conflict
  dialog (Keep both/Replace/Skip/Cancel all), paused_error dialog (Retry/Skip/
  Cancel all), backend-typed conflict/error bodies, no window.open() (D-01/D-03/D-04)
- CloudFolderOpenPreview.test.js: authorized file-open via API, no raw provider
  URLs, Office/Workspace authorized download fallback, no anchor-click download
  hack, no re-emitted file-open to router (D-02/D-18/T-13-07)
- CloudFolderView.test.js: extends thin-view invariants for Phase 13 queue prop
  forwarding and upload-event queue semantics (D-01/D-04)
2026-06-22 18:10:16 +02:00
curo1305 451d30208c docs(13-01): complete red contract suite plan 2026-06-22 18:03:09 +02:00
curo1305 fd6b561899 test(13-01): extend provider contract suites for four-provider mutable-operation parity
- Add Phase 13 mutable-operation RED tests to test_cloud_backends.py:
  TestGoogleDriveMutableContract (D-17 scope, create/rename/move/delete/upload),
  TestOneDriveMutableContract (CONN-02 token handoff, permanent-delete disclosure,
  nextLink SSRF guard), TestNextcloudMutableContract (create-folder SSRF, delete
  normalization), TestWebDAVMutableContract (permanent-delete, move SSRF, no
  cloud_items imports)
- Add Phase 13 mutable-operation RED tests to test_cloud_provider_contract.py:
  TestMutableAdapterContract (method existence, async contract, canonical signatures
  for all four providers), TestMutableAdapterResultNormalization (normalized kind/reason
  return types, conflict normalization documentation, unsupported-capability disclosure)
- All new tests fail against the current codebase — mutable adapter methods do not
  exist yet (expected RED); all prior Phase 12 tests remain green
2026-06-22 18:01:15 +02:00
curo1305 efb596433c test(13-01): add red API and audit contracts for reconnect, content, and mutation flows
- Create test_cloud_mutations.py: IDOR, admin block, credential secrecy, and typed
  kind/reason body coverage for open, preview, upload, create-folder, rename, move,
  and delete endpoint contracts (D-02 through D-11, D-18)
- Create test_cloud_reconnect.py: reconnect patch-in-place (CONN-01), encrypted credential
  persistence (CONN-02), response secrecy (CONN-03), health endpoint, test action,
  cache-preservation on reconnect (D-14), transient-outage data preservation (D-15),
  and disconnect metadata cleanup (D-16)
- Create test_cloud_audit.py: metadata-only audit rows for every successful cloud operation,
  false-overwrite prevention (T-13-05), admin audit log credential exclusion (T-13-02)
- All tests fail against current codebase — Phase 13 routes do not exist yet (expected RED)
2026-06-22 17:57:55 +02:00
curo1305 f01bb181c1 docs(state): record phase 13 context session 2026-06-22 15:46:17 +02:00
curo1305 c7688a52f3 docs(13): capture phase context 2026-06-22 15:46:05 +02:00
curo1305 38900e0ee7 test(12.1): complete UAT - 5 passed, 1 issue (missing modified timestamps), 1 skipped 2026-06-22 14:49:01 +02:00
curo1305 64ddb50cd6 fix(cloud): show provider root items in browser 2026-06-22 13:55:07 +02:00
curo1305 d452dee3f7 docs(phase-12.1): update validation strategy 2026-06-22 12:03:16 +02:00
curo1305 b00218e5c5 test(phase-12.1): repair live browse validation guard 2026-06-22 12:03:06 +02:00
curo1305 d02d5db7c3 docs(phase-12.1): audit Nyquist validation coverage 2026-06-22 11:55:31 +02:00
curo1305 66a7937bd1 docs(phase-12.1): add security threat verification 2026-06-22 10:00:09 +02:00
curo1305 aa1d626187 docs(12.1-04): complete plan 04 summary and state updates 2026-06-22 09:48:33 +02:00
curo1305 46b7ea6c12 test(12.1): verify live cloud browse integration
Phase 12.1 close — docs, version, and security evidence:
- Bump version 0.2.5 → 0.2.6 in backend/main.py, frontend/package.json
- CLAUDE.md: update current state to Phase 12.1 complete v0.2.6
- README.md: add Phase 12.1 corrections, live smoke variable names, Phase 13/14 exclusions
- RUNBOOK.md: add live smoke invocation, warning semantics table, fixture reconciliation procedure
- SECURITY.md: add Phase 12.1 Plan 04 threat table (T-12.1-16..20, T-12.1-SC) and gate evidence
- 12.1-VALIDATION.md: mark Plan 04 complete with final gate evidence
2026-06-22 09:46:25 +02:00
curo1305 6d294ea7e6 test(12.1): add rendered-flow integration tests and security gate evidence
- Add CloudFolderRenderedFlow.test.js: 7 tests mounting real CloudFolderView
  with real StorageBrowser/BreadcrumbBar (only API and router stubbed)
  — mixed root render, opaque-ref folder navigation, breadcrumb lineage,
    warning freshness cached rows, fresh freshness, XSS text escaping
- Update 12.1-VALIDATION.md with Task 3 security gate results:
  bandit 0 HIGH, npm audit 0 critical, no Phase-12.1 gitleaks findings,
  595 backend / 376 frontend tests pass, build clean
2026-06-22 09:41:36 +02:00
curo1305 1ec5158c65 test(12.1): owner-confirmed expected root manifest
- Create backend/tests/fixtures/cloud/nextcloud_expected_root.json with
  owner_confirmed: true and corrected 10-item name/kind manifest
- Add test_nextcloud_expected_root_manifest: exact set and kind equality
  against fixture (T-12.1-19 — count-only acceptance blocked)
- Update 12.1-VALIDATION.md: manifest status OWNER CONFIRMED, add
  exact-acceptance row to Nyquist matrix
2026-06-22 09:35:36 +02:00
curo1305 779b05086b test(12.1-04): add opt-in live Nextcloud smoke test suite
- backend/tests/test_nextcloud_live.py: three read-only live tests behind
  live_nextcloud marker (adapter root metadata, sanitized diagnostic, connection-ID
  browse as testuser@docuvault.example with IDOR/admin negatives)
- backend/pytest.ini: register live_nextcloud marker; addopts excludes it from
  ordinary runs so CI never contacts Nextcloud without explicit selection
- 12.1-VALIDATION.md: live test contract, commands, skip behaviour, sanitized
  7-of-10 probe result, and threat references T-12.1-16 through T-12.1-20
- Manifest status: unconfirmed — Task 2 exact-name gate pending owner decision
2026-06-22 09:02:42 +02:00
curo1305 9ef7f81b3f docs(12.1-03): complete plan 03 summary and state updates 2026-06-22 08:55:02 +02:00
curo1305 7bb046ac41 fix(12.1): align cloud browser contract — kind, provider_item_id, server freshness
Normalized cloud frontend for DocuVault v0.2.5:
- Cloud UI classifies items by kind=folder/file (is_dir removed from all active paths)
- Folder navigation uses provider_item_id (opaque provider ref) — DocuVault id kept for row identity
- Server freshness (refresh_state, last_refreshed_at) mapped verbatim — no browser-clock evidence
- Breadcrumb lineage built from explicit visited nodes — never split(provider_item_id)
- CloudFolderTreeItem: expandable/icon/navigate/loadChildren all use kind and provider_item_id
- Version bump 0.2.4 → 0.2.5
- SECURITY.md: T-12.1-11 through T-12.1-15 closed
- 369 tests pass, npm audit clean, production build clean
2026-06-22 08:51:14 +02:00