Skip to content

P7: list_files + search (scoped enumeration over the AI workspace forest) #61

@ehsan6sha

Description

@ehsan6sha

Phase 7 of the fula-mcp line — scoped enumeration

Build the AI-workspace enumeration operations as library functions (MCP-protocol wiring is later, in P9):

  • list_files(cap, filter) -> Vec<FileEntry> — list the AI''s own workspace forest, scope-confined to ai/, with optional category and sub-prefix narrowing.
  • search(cap, query) -> Vec<FileEntry>list_files over the whole ai/ scope, then filter where the filename contains query case-insensitively.

FileEntry { key, size, content_type, category, modified_at } (category derived from the ai/<category>/ key segment, falling back to classify).

Security: scope confinement (the crux)

Results MUST be limited to the AI''s ai/ workspace scope. The AI fully owns its workspace but must never enumerate the user''s real buckets. Enumeration is confined by the P3 segment-boundary geometry (reusing assert_in_scope(key, ai, Read) per entry), NOT a substring match — so ai-evil/... and any non-ai/ key can never leak. The scope gate runs BEFORE any client/I/O.

Builds on

  • P3 capability.rs (assert_in_scope, workspace_client, Permission)
  • P4 category.rs (Category, classify)
  • P5 store.rs (WORKSPACE_BUCKET, WORKSPACE_KEY_PREFIX, key convention)
  • P6 read.rs (gate-before-I/O pattern, error style)
  • SDK EncryptedClient::list_files_from_forest(bucket) -> Vec<FileMetadata>

Tests

  • Offline (scope confinement): construct forest entries directly (both ai/... and non-ai/ keys, no network); assert list_files returns ONLY ai/ ones; category filter narrows; the gate is provably called before I/O (drive the real async fn against an unreachable endpoint and assert a Capability error, not a network error); search matches case-insensitively on the filename and never leaks non-ai/ keys.
  • Gated e2e (#[ignore] + FULA_E2E=1): store a few files across categories into a disposable workspace bucket, then list_files (all + by category) and search by a filename fragment; assert the stored keys appear with the right category and nothing else; cleanup.

Out of scope

Tag-based search/filter is P8; MCP tool wiring is P9. No new crypto.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    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