ADR-0008 — one knowledge base per community, behind an alias per embedding model
Date: 2026-10-02 Status: accepted
Context
One deployment serves several renewable energy communities, as onboarding already does.
Retrieval did not: every document lived in one Qdrant collection, scoped only system /
user, so a document an administrator shared was read by members of every REC, and the
only reference material was one git repository, the same for everyone.
Separately, changing the embedding model meant naming a new QDRANT_COLLECTION and
re-ingesting by hand — and nothing could re-ingest uploads, whose extracted text sat in
the database with no path back into the index.
Decision
- The community is the REC organization in the caller's token. Its Keycloak alias is
the community id (and the Digital Twin's). A member belongs to exactly one; a token
naming several is refused rather than resolved. A REC's knowledge is managed by
its own
managers/adminsorganization groups or by a platform administrator — the rule onboarding applies — and an organization group never makes a platform administrator. (Since 2026-10-03 a platform administrator is the holder of theplatform-adminrealm role, REQ-0004; it was the realm groupADMIN_GROUP.) - Each community has a knowledge base of its own: a Qdrant alias
<QDRANT_COLLECTION>__<community_id>__<fingerprint>over a timestamped collection. There is no shared corpus collection; reference material is a source — a git repository or a directory — registered for one community in the database. - The fingerprint hashes the embedding model and vector size. Two models read two
aliases, so a new model's knowledge bases are built while the old ones serve, and the
deploy that changes
LLM_EMBED_MODELis the switch. The service refuses to start on a model no knowledge base was built for. - A rebuild never copies vectors.
celine-assistant kb reindexbuilds a new generation from the sources and the attachment rows, verifies it, and moves the alias in one operation; changes made during the build are reconciled after the move. - Legacy data moves by a command,
kb migrate-legacy --community <id>. No community id is a default in this repository, which is public.
Consequences
- A member's retrieval touches one collection; the
community_idmetadata term stays in the filter as well, so a point in the wrong collection is still not returned. - Every write path names a community. An upload by a caller with no REC is stored, not indexed; there is nowhere to index it.
- Operating the knowledge bases is a CLI in the service image, not a startup side
effect: sources are registered and synced with
celine-assistant kb, andKB_SYNC_ON_STARTis off by default. The infra chart'sTRAINING_MATERIALS_*are read by nothing and are reported at startup until removed. - Old generations accumulate until
kb prune; that is the rollback window, and the cost. - The upload API gained
community_idon/admin/uploads(a platform administrator's), and/admin/training-materials/syncbecame/admin/kb/sync.