Files
kite/.planning/phases/14-selective-analysis-and-byte-cache/14-01-SUMMARY.md
T

9.3 KiB

phase, plan, subsystem, tags, status, requires, provides, affects, tech-stack, key-files, decisions, metrics
phase plan subsystem tags status requires provides affects tech-stack key-files decisions metrics
14 01 cloud-analysis
tests
contract
tdd
analysis
cache
red
complete
phases/13-virtual-local-cloud-operations
test contract for Phase 14 analysis and cache implementation
backend/tests/test_cloud_analysis_contract.py
backend/tests/test_cloud_cache.py
backend/tests/test_cloud_analysis_api.py
frontend/src/components/storage/__tests__/StorageBrowser.analysis-queue.test.js
frontend/src/stores/__tests__/cloudConnections.analysis.test.js
added patterns
FakeCloudAdapter counter pattern for T-14-03/T-14-04 mutation/byte-download guards
version-key precedence helper (version > etag > fingerprint > content hash)
Dynamic import avoidance in Vitest (Vite resolves imports at transform time)
created modified
backend/tests/test_cloud_analysis_contract.py
backend/tests/test_cloud_cache.py
backend/tests/test_cloud_analysis_api.py
frontend/src/components/storage/__tests__/StorageBrowser.analysis-queue.test.js
frontend/src/stores/__tests__/cloudConnections.analysis.test.js
D-06
translateAnalysisStatus must be a single-source function in the store — components never translate statuses independently (same pattern as D-12 health state map)
D-11
Default failure_behavior is pause_batch — tests assert the default and verify continue_item can be set
T-14-04
estimate and already-current checks must never call get_object — FakeCloudAdapter byte_call_count remains zero in all analysis paths
Vite dynamic import resolution
cloudAnalysis.js companion store tested via cloudConnections store directly (dynamic import of non-existent file fails at transform time even in try/catch)
duration completed tasks files
~15 minutes 2026-06-23 2 5

Phase 14 Plan 01: Red Test Contract Summary

One-liner: RED backend and frontend test contract establishing analysis scope selection, estimates without byte downloads, duplicate-version skips, cache ownership/quota semantics, cancellation/retry controls, and shared-browser queue surface.

What Was Built

This plan creates the executable test contract for Phase 14 before any implementation begins. All tests are intentionally RED — they fail because Phase 14 modules do not yet exist. They define the implementation contract that subsequent plans must satisfy.

Backend Tests (3 files, 42 tests)

test_cloud_analysis_contract.py (16 tests):

  • ANALYZE-01: single-file estimate returns supported_count + total_provider_bytes, zero byte_call_count
  • ANALYZE-02: selection estimate aggregates multiple files, reports unsupported count
  • ANALYZE-03: whole-connection estimate always returns recursive response; folder scope accepts recursion flag
  • ANALYZE-06: already-indexed item with unchanged etag marked already_current without get_object call; changed etag triggers requeue
  • ANALYZE-07: analysis job never calls any provider mutation method (FakeCloudAdapter.mutation_call_count stays zero)
  • T-14-01: foreign user cannot estimate/enqueue/read-status/cancel — 403/404
  • T-14-01: admin cannot enqueue another user's analysis job
  • T-14-02: job status response excludes credentials_enc, access_token, refresh_token, object_key
  • ANALYZE-05: cancel transitions to "cancelled"/"cancelling"; retry transitions to "queued"

test_cloud_cache.py (12 tests):

  • CACHE-03: cache entry created during analysis; browse never creates cache entries
  • CACHE-04: eviction skips pinned entries (pin_count > 0 protected, D-16); LRU evicts oldest unpinned first
  • T-14-05: quota increment/decrement seam — increment_quota_for_cache and decrement_quota_for_cache function signatures verified
  • CACHE-05 / T-14-01: list_cache_entries is owner-scoped — foreign user sees zero entries
  • T-14-02: cache API response never includes object_key; admin blocked from cache status endpoint
  • ANALYZE-06 / D-19: compute_version_key precedence: version > etag > metadata fingerprint; content_hash=None accepted without byte-fetch fallback; deterministic output

test_cloud_analysis_api.py (14 tests):

  • Route registration gates for estimate/jobs/status/cancel endpoints (RED: 404 until router wired)
  • ANALYZE-04 / D-06: job status includes simplified aggregate counts (default) and detailed per-stage counts (detail=true)
  • ANALYZE-05: skip item transitions to skipped status
  • Security: unauthenticated requests blocked (401/403/404)
  • T-14-02: enqueue response excludes sensitive fields
  • D-13: check_scan_quota function signature exists (scan quota seam distinct from storage quota)
  • D-11: failure_behavior="continue_item" accepted; invalid failure_behavior rejected

Frontend Tests (2 files, 41 tests)

StorageBrowser.analysis-queue.test.js (22 tests, 21 RED):

  • D-01: each cloud file row has [data-test="analyze-file"] button; click emits analyze-file with item payload
  • D-01: Analyze row action absent in local mode
  • D-01: toolbar [data-test="analyze-selection"] present when files selected; emits analyze-selection with array
  • D-01/ANALYZE-03: toolbar [data-test="analyze-connection"] present; emits analyze-connection with connection id
  • D-01/ANALYZE-02: [data-test="analyze-folder"] present when inside a folder
  • D-02/D-03: analysisEstimate prop triggers [data-test="analysis-estimate-modal"]; modal shows supported/unsupported counts and [data-test="estimate-start"]; clicking Start emits analysis-confirmed
  • D-05/D-07: analysisQueue prop accepted; [data-test="analysis-aggregate-progress"] rendered; simplified labels shown by default; expandable [data-test="analysis-queue-item-list"] with per-item rows
  • D-08: detailed mode shows stage indicators (download/extracting/classifying)
  • D-09: [data-test="analysis-item-cancel"] per row; click emits analysis-item-cancel with item_id
  • D-10: failed items show [data-test="analysis-item-retry"] and [data-test="analysis-item-skip"]
  • D-09: [data-test="analysis-cancel-all"] present; click emits analysis-cancel-all with job_id
  • Architecture: StorageBrowser renders cloud files (no parallel grid motivation)

cloudConnections.analysis.test.js (17 tests, 15 RED):

  • Analysis state (analysisJobs/activeAnalysisJob/analysisQueue) exposed from store
  • translateAnalysisStatus: simplified mode maps 10 internal statuses to 5 labels; detailed mode maps 1:1
  • requestEstimate calls api.estimateAnalysis without credential fields
  • enqueueAnalysis, cancelJob, retryItem, skipItem call correct API functions
  • Default failureBehavior is "pause_batch"; can be changed to "continue_item"
  • detailedAnalysisProgress defaults falsy; can be set to true
  • localStorage spy confirms no credential values written during analysis actions
  • fetchJobStatus: analysisQueue items contain no credentials or object_key
  • Cache limit exposed with positive default; updateCacheSettings calls API

Threat Coverage

Threat Tests
T-14-01 IDOR 6 backend negative tests (estimate/enqueue/status/cancel foreign + admin)
T-14-02 Credential/key disclosure 4 backend tests; 1 frontend credential-storage guard
T-14-03 Hidden provider mutation FakeCloudAdapter.mutation_call_count == 0 in 3 tests
T-14-04 Hidden byte download FakeCloudAdapter.byte_call_count == 0 in 5 tests (estimate + already-current)
T-14-05 Cache quota corruption increment_quota_for_cache + decrement_quota_for_cache seam tests

RED Failure Modes

All failures are due to missing Phase 14 modules — not syntax/import errors in the tests themselves:

Backend:

  • ModuleNotFoundError: No module named 'api.cloud.analysis'
  • ImportError: cannot import name 'create_cache_entry' from 'services.cloud_cache'
  • ImportError: cannot import name 'CloudByteCacheEntry' from 'db.models'
  • ImportError: cannot import name 'compute_version_key' from 'services.cloud_cache'
  • ImportError: cannot import name 'check_scan_quota' from 'services.cloud_analysis'

Frontend:

  • Missing analysisQueue prop on StorageBrowser (Vue prop validation)
  • Missing [data-test="analyze-file"] in file rows
  • Missing [data-test="analysis-aggregate-progress"] container
  • Missing translateAnalysisStatus, requestEstimate, cancelJob, retryItem, skipItem on cloudConnections store
  • Missing failureBehavior / detailedAnalysisProgress store state

Deviations from Plan

[Rule 3 - Blocking Fix] Dynamic import issue in Vitest store tests

  • Found during: Task 2 frontend test implementation
  • Issue: cloudConnections.analysis.test.js originally used dynamic import('../cloudAnalysis.js') inside try/catch to allow for a companion store. Vite resolves dynamic imports statically at transform time; even with try/catch, a non-existent module path causes the whole test file to fail at import-resolution (before any tests run).
  • Fix: Rewrote all store tests to use the synchronous useCloudConnectionsStore() import directly. Missing properties/methods produce the expected RED failures without import errors. If Phase 14 uses a companion store, it must re-export from cloudConnections.js.
  • Files modified: frontend/src/stores/__tests__/cloudConnections.analysis.test.js
  • Commit: 7f2f570

Known Stubs

None — this plan creates only tests; no production code stubs exist.

Threat Flags

None — this plan adds test files only. No new network endpoints, auth paths, or schema changes.

Self-Check: PASSED