Skip to content

Chroma allocation for the shared A2A server (tenant fuzeagent / database a2a) #643

Description

@izzywdev

@claude — one serviceChromaCollections[] entry, please. This is a delegation from FuzeAgent, which never edits FuzeInfra.

The ask

Add to helm/fuzeinfra/values-contabo.yaml:

- name: fuzeagent-a2a
  enabled: true
  tenant: fuzeagent
  database: a2a
  credentialSecret:
    name: fuzeagent-a2a-chroma-credentials
    key: token
  networkPolicy:
    namespace: fuzeagent
    podLabels:
      app.kubernetes.io/name: a2a-shared
  collections: []

plus the sealed fuzeagent-a2a-chroma-credentials Secret in the fuzeinfra namespace (the existing deploy/sealed-secrets/ pattern), and the same secret — or its token — reachable in the fuzeagent namespace so the a2a-shared Deployment can mount it as deploy.rag.authTokenSecretRef.

That last part is the only bit I'm unsure how you prefer to do: the consumer pod is in fuzeagent, not fuzeinfra. fuzeplan-repo-digester has the same shape, so whatever it does is presumably the answer.

Why this is one entry and not a new capability

The mechanism already exists and is the right one. templates/service-chroma-provisioning.yaml provisions an isolated tenant/database per consumer, binds the bearer token to it, and — the part worth calling out — verifies cross-tenant denial as part of the provisioning job, by attempting a foreign-tenant get_or_create_collection with each token and requiring it to be rejected. That is a provisioning step that actually proves the boundary rather than asserting it.

fuzeplan-repo-digester and fuzequality are the live precedents. This is a third of the same shape.

collections: [] is deliberate

The A2A server creates one collection per A2A tenant inside the a2a database, named a2a-<tenant> — so the set grows as products onboard and there is no meaningful bootstrap list. Per the values.yaml comment ("Only bootstrap collections belong in this list"), an empty list is the correct entry rather than a stale one.

Isolation inside the database is by collection, not by a where filter: a filter is one forgotten argument away from returning another A2A tenant's chunks; a separate collection cannot be read by omission.

Both tenant and database are load-bearing

chroma-authz.yaml's TenantDatabaseAuthorizationProvider binds each token to exactly one (tenant, database) pair, and the Chroma client resolves both eagerly at construction. A mismatch is not a subtle permission error on some later call — it is a failure to connect at all. The consumer chart projects both (CHROMA_TENANT, CHROMA_DATABASE).

What's ready on the consumer side

FuzeAgent PR #194 ships agent-templates/a2a/rag/ in the fuze-a2a image with deploy.rag.enabled: false. When enabled, helm template fails unless host, tenant, database and the token secret ref are all present — verified by running each case, not by reading the template. So nothing here can half-work: until this allocation exists, the flag stays off; once it exists, flipping it either connects or refuses to start.

That PR also fixes why this matters now. FuzeAgent's existing RAG has been inert in production — CHROMA_HOST unset and defaulted to localhost, chroma_client_auth_provider set to the literal "basic" (which Chroma resolves as an import path, so it resolved to nothing and the client was built unauthenticated), an empty credential, and a broad except that turned all of it into an empty result no caller could distinguish from an empty corpus.

Worth noting for confidence: the provider string I moved it to — chromadb.auth.token_authn.TokenAuthClientProvider — is exactly what service-chroma-provisioning.yaml already uses against this same server.

Not blocking anything else

Nothing else in FuzeAgent waits on this. If the answer is "not now" or "different shape", say so and the flag simply stays off.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions