Problem
P14 surfaced the AI/MCP workspace forest (fula-ai-workspace) in the native category views, tagging each item sourceBucket = fula-ai-workspace. But the open/download call sites still route every tap to the user master-KEK cloud client, which cannot decrypt a workspace-secret-encrypted file. Result: adopted AI files list correctly in the category views but FAIL when opened or downloaded.
Root cause
FulaApiService.downloadWorkspaceObject(bucket, key) (added in P14) is the decrypting path for AI files (workspace client, auto-init, gated by hasAiConnection()). The download call sites call downloadObject / downloadWithLocalFallback and ignore the object sourceBucket, so AI files never reach the workspace client.
Fix (P14.1)
Add sourceBucket-aware routing helpers on the FulaApi surface and switch the open/download call sites to them:
downloadBySourceBucket(bucket, key, sourceBucket) — routes AI files to downloadWorkspaceObject, everything else to downloadObject.
downloadBySourceBucketWithLocalFallback(...) — same, but the non-AI branch keeps the LAN-first fallback. The AI branch skips the LAN fallback by design (the AI workspace is cloud-only).
Native (file_browser_screen) + web (web_bucket_screen, 6 open/preview/download/share paths) call sites switch to the helpers. The sync path is unchanged: AI files are adopted FOR VIEW and are never enqueued as SyncTasks, so it cannot carry them. The native download path also no longer records a synced SyncState row for the read-only AI bucket (view, not sync).
Gated + non-AI-safe throughout: a user with no AI connection pays zero cost and sees no behavior change. Normal/legacy file opens are byte-identical to before.
Problem
P14 surfaced the AI/MCP workspace forest (
fula-ai-workspace) in the native category views, tagging each itemsourceBucket = fula-ai-workspace. But the open/download call sites still route every tap to the user master-KEK cloud client, which cannot decrypt a workspace-secret-encrypted file. Result: adopted AI files list correctly in the category views but FAIL when opened or downloaded.Root cause
FulaApiService.downloadWorkspaceObject(bucket, key)(added in P14) is the decrypting path for AI files (workspace client, auto-init, gated byhasAiConnection()). The download call sites calldownloadObject/downloadWithLocalFallbackand ignore the objectsourceBucket, so AI files never reach the workspace client.Fix (P14.1)
Add
sourceBucket-aware routing helpers on theFulaApisurface and switch the open/download call sites to them:downloadBySourceBucket(bucket, key, sourceBucket)— routes AI files todownloadWorkspaceObject, everything else todownloadObject.downloadBySourceBucketWithLocalFallback(...)— same, but the non-AI branch keeps the LAN-first fallback. The AI branch skips the LAN fallback by design (the AI workspace is cloud-only).Native (
file_browser_screen) + web (web_bucket_screen, 6 open/preview/download/share paths) call sites switch to the helpers. The sync path is unchanged: AI files are adopted FOR VIEW and are never enqueued asSyncTasks, so it cannot carry them. The native download path also no longer records asyncedSyncState row for the read-only AI bucket (view, not sync).Gated + non-AI-safe throughout: a user with no AI connection pays zero cost and sees no behavior change. Normal/legacy file opens are byte-identical to before.