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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions