Skip to content

P14 — AI-workspace adoption: native category views + additive tag adoption #67

Description

@ehsan6sha

P14 — AI-workspace adoption in FxFiles

Surface the AI assistant's (MCP server's) workspace files in FxFiles' native category views, and additively adopt its tags — gated so non-AI users are unaffected.

Background

P13 lets a user pair an AI client (MCP). The AI writes encrypted objects to bucket fula-ai-workspace under keys ai/<category>/... (category ∈ images/videos/audio/documents) and a tag doc at ai/tag-metadata/ai-workspace.json, encrypted under a dedicated workspace secret = blake3DeriveKey('fula:ai-workspace-secret:v1', KEK). FxFiles re-derives the same secret and reads that forest with a separate client.

Per product decision #3, AI files appear in the native category views (carrying sourceBucket='fula-ai-workspace' so the UI can badge / route them).

Scope

  • Workspace client: a second EncryptedClient (_workspaceClient) in FulaApiService, built lazily + single-flight, gated on an existing AI connection, decrypted under the workspace secret. Its EncryptionConfig exactly mirrors the MCP's EncryptionConfig::from_secret_key (enableMetadataPrivacy: true, obfuscationMode: flatNamespace).
  • listWorkspaceObjects(bucket, {prefix}) + downloadWorkspaceObject(bucket, key) (the latter needed to read the AI tag doc, which the user's own client cannot decode).
  • Category-view merge: the AI workspace is an additional live source for each category (prefix ai/<category>/), merged into the same native view across all three merge seams (listCategoryMerged, listCategoryCached (mobile), listCategoryMergedCached (web)). AI items are seeded first so the user's own files always win a key collision; only ai/<base>/...-shaped keys are admitted.
  • Tag adoption (additive): restoreFromCloud reads the AI tag doc and additive-merges by id — a colliding (already-local) id is discarded entirely (untrusted-writer model); never clobbers a user's own tag.

Safety invariants

  • No-op for non-AI users — every workspace read is gated behind hasAiConnection().
  • Never clobber the user's own files or tags (user-wins ordering; discard-colliding-tag-row).
  • Error-isolated — any AI-side failure is tolerated as empty / swallowed, so it can never hide or block the user's own content.

Tests

Unit tests over the FulaApi fake + the category_listing pattern: images/documents views include their respective ai/<cat>/... items (sourceBucket carried); the gate (no connection ⇒ no workspace list call); the additive tag rule keeps a pre-existing local id and adds new ones.

Out of scope (follow-ups)

  • Routing an AI item's download/thumbnail tap to the workspace client (the merge carries sourceBucket; a follow-up wires the read path).
  • A visible "AI" badge (carrying sourceBucket is the requirement; badge is optional polish).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions