← Back to Tenant
AgentTenant

Skill · Version 1.0.0

Tenant-safe caches, search and files

Extends tenant isolation beyond database rows to caches, search suggestions, derived indexes and stored file access.

tenant-aware-cache-search-files

See how it helps

When is it useful?

Use it when apparently scoped APIs still share cache entries, autocomplete values or object URLs across workspaces.

What does it help you do?

  • Namespaces cache keys with verified tenant identity.
  • Filters search results, suggestions and facets on the server.
  • Partitions storage keys and authorizes signed URL issuance.

Try asking this

Test identical search terms and filenames in two workspaces without cross-tenant results. Warm search and file caches in workspace A, then repeat in B. Counts, suggestions and signed downloads must contain only B's authorized data.

Detailed documentation

Read the skill’s original instructions, examples and checks in their authored language.

Details…Show less

Tenant-Aware Cache, Search & Files

When to Use

Use when integrating or reviewing caching layers (Redis, Memcached, in-memory LRU, HTTP/CDN), search engines (PostgreSQL FTS, Elasticsearch/OpenSearch, Meilisearch, Typesense, Algolia), or file/blob storage in a multi-tenant application.

1. Cache Isolation (Redis, In-Memory & HTTP/CDN)

Unprefixed cache keys (project:123, dashboard:stats, settings) are one of the most frequent sources of cross-tenant data leaks:

  • Mandatory Key Namespacing: Wrap the cache client so every tenant-scoped operation automatically prepends the verified tenantId:
    const cacheKey = `tenant:${ctx.tenantId}:${namespace}:${resourceId}`;
    
  • Fail-Closed Wrapper: If ctx.tenantId is missing or empty, the cache wrapper must throw an error rather than generating tenant:undefined:dashboard:stats (which would become a shared cache key across all unauthenticated/broken calls!).
  • HTTP & CDN Cache Headers:
    • For workspace-authenticated API responses and SSR pages, set Cache-Control: private, no-store (or include Vary: Authorization, Cookie, X-Workspace-Id where private browser caching is intended) so shared CDN or reverse-proxy caches never serve Tenant A's response to Tenant B.

2. Full-Text & Search Index Isolation

Search engines often live outside the primary relational database and do not enforce SQL foreign keys:

  • Index Every Document with tenant_id: Every indexed document must carry a non-nullable, filterable tenant_id (workspace_id) facet/attribute.
  • Server-Enforced Search Filter:
    • Never accept raw filter expressions directly from the client.
    • Inject filter: "tenant_id = '<verified_tenant_id>'" on the server (or issue short-lived, cryptographically signed Scoped Search API Keys in Meilisearch/Typesense/Algolia that embed an immutable tenant_id filter).
  • Autocomplete, Facets & Spellcheck / Suggestions:
    • Ensure facet counts, "did you mean" suggestions, and popular-query completions are Partitioned by tenant_id—global autocomplete dictionaries can leak another customer's confidential project or client names!
  • Synchronous / Outbox Deletion on Workspace or Record Removal:
    • When a record or entire workspace is deleted, remove its documents from the search index via a transactional outbox so deleted or cross-tenant items never linger in search results.

3. File & Object Storage Tenant Boundaries

  • Tenant-Partitioned Storage Keys: Prefix object storage keys with the immutable workspace ID (tenants/${tenantId}/files/${uuidv7}) so storage lifecycle rules, per-tenant byte accounting, and tenant deletion sweeps are cleanly isolated.
  • Authorization Before Presigned URL Issuance:
    • Never allow a user in Tenant A to request a download or upload URL for a fileId without first querying SELECT 1 FROM files WHERE id = $1 AND tenant_id = $2 using the verified tenantId.
    • Do not deduplicate uploaded files across different tenants if doing so exposes whether another tenant already uploaded a given confidential document (cross-tenant hash oracle) or complicates single-tenant erasure.

Included files 1

  • SKILL.md