# Scirium Admin Guide Status: PLANNED Audience: tenant admin and Scirium operator Purpose: provision a tenant and take a channel live end to end. ## 1. Prerequisites - A Microsoft 365 tenant with the Scirium Entra app registered and holding the Sites.Selected application permission. - A Rocket.Chat workspace provisioned for the tenant (one workspace per tenant). - Vaultwarden access for secrets (M365 credentials, bot tokens, webhook secret). - Admin role on the orchestrator. ## 2. Provision a Tenant 1. Create the tenants row: slug, name, branding (logo_url, accent_color), M365 tenant id and client id. 2. Store the M365 client secret in Vaultwarden; put only the reference in m365_credential_ref. 3. Record the Rocket.Chat workspace root URL in rocket_chat_url. 4. Generate a webhook signing secret, store it in Vaultwarden, and set webhook_secret_ref. 5. Set status to provisioning until the workspace and connector are confirmed. The tenant is now the root of the tenancy tree. Every downstream object hangs off it. ## 3. Create a Channel 1. Insert a channels row: name (the knowledge domain, for example "Billing"), slug (unique per tenant), description. 2. Optionally create the matching Rocket.Chat room and store rocket_chat_room_id and rocket_chat_room_name. 3. Leave status = draft. The channel stays draft until the scope is bound and indexed. ## 4. Attach an Agent 1. Insert an agents row: name (for example "Scirium Billing"), system_prompt (the domain persona), model_name (deepseek-v4-pro) and fallback_model, rocket_chat_bot_username. 2. Provision the Rocket.Chat bot user (POST /api/v1/users.create with roles bot), create a personal access token, and store the token reference and bot user id. 3. Invite the bot to the room (POST /api/v1/channels.invite). 4. Set channels.agent_id to the new agent. ## 5. Bind a Scope 1. Insert a kb_scopes row: vector_namespace (tenant_{tenant_id}__scope_{kb_scope_id}), document_libraries (the allowlisted M365 site and drive ids), embedding_model and embedding_dim, chunk_size (512) and chunk_overlap (64). 2. Set channels.kb_scope_id to the new scope. The scope is the allowlist. Only the libraries named here are ever indexed or searched for this channel. ## 6. Run the Initial Sync 1. Trigger the M365 connector for the scope. It pulls the named document libraries, extracts text, chunks, embeds, and writes documents and chunks rows under the namespace. 2. Monitor document status: pending to extracting to indexing to indexed. 3. Confirm nonzero indexed document count and nonzero chunk count in the scope's namespace. 4. The channel stays in draft until this succeeds. This is the only long-running step. Everything before it is fast and idempotent. ## 7. Go Live 1. Set channels.status = active. 2. Configure the outgoing webhook on the channel with the trigger word set to the bot username, pointing at the orchestrator webhook URL. 3. Optionally register a slash command such as /ask. 4. Run an end-to-end smoke test: ask a question in the channel, confirm the agent bot posts a cited answer, and confirm the answer's sources resolve to documents inside the scope. 5. Verify a below-threshold question returns "I could not find an answer in the knowledge base for this question" instead of guessing. ## 8. Operate | Task | Where | |---|---| | Delta sync schedule | kb_scopes.sync_policy | | Document failure triage | documents.status and documents.error | | Audit review | messages table (question, answer, citations, model, latency) | | Secret rotation | Vaultwarden; update only the reference in Postgres | | Suspend a tenant | tenants.status = suspended | ## 9. Rules - Never inline a secret in Postgres or config. References only. - Never index a library outside the scope allowlist. - Never go live on an empty scope. Indexed document count must be nonzero. - Never grant the connector write permission. Read only.