Skip to content

Glossary

Shared vocabulary for Rose. Terms here mean the same thing across code, schema, backoffice, and docs. Extend it as concepts stabilise rather than redefining them per page.

Workspaces, sites, knowledge, and routing

See the Client-Scoped Sites ADR for the physical model and its original terminology.

A workspace is the client-facing container that owns configuration, knowledge, agents, and website roots. It is the identity the backoffice selects. The physical schema introduced this container as a row in public.sites; migrations and SQL function bodies still use site for that row. Application code and client-facing copy use workspace, through the aliases below. In ordinary product copy, site means the client's website, not the selectable container.

Ownership is a composition tree (filled diamond = "owns"); attributes such as enabled or corpus_status are fields on a box, not boxes of their own. Multiplicities read how many of the target a source has.

classDiagram direction LR class Client { +bool explicit_routing_enabled } class Workspace { +uuid workspace_id +string config_key +enum status +enum corpus_status } class Config { +json client_base +json site_overrides } class Corpus { +string storage_key +tenant vectors_and_graph +set documents +set faqs } class Root { +string host +string path_prefix +bool is_canonical +bool enabled } class Agent { +string kind } Client "1" *-- "0..*" Workspace : owns Workspace "1" *-- "1" Config : configured by Workspace "1" *-- "1" Corpus : owns Workspace "1" *-- "0..*" Root : placed at Workspace "1" o-- "0..*" Agent : hosts Agent "0..*" --> "1" Corpus : reads note for Root "Exactly one root has is_canonical=true when a workspace has roots.\nenabled means this root routes live visitor traffic;\nallowed only when status=live and corpus_status=ready\n(and, for a path_prefix root, explicit_routing_enabled=true).\nCrawl seeds are derived from the roots — the canonical root\nsets the default scope, enabled aliases widen it — and build the Corpus."
  • Workspace — the client-scoped identity: one configuration, one corpus, one or more roots, and its agents. Everything else is scoped by it. It replaces the domain that used to be configuration target, bot identity, and tenant key all at once. A client may have several workspaces, e.g. one per country, product or business unit.
  • Site (public.sites, public.site_roots, site_id) — the physical storage and routing name for a workspace. It stays in migrations, SQL function bodies, serialized site_id keys, and the site:<uuid> storage key (the MongoDB/Neo4j tenant key — data, never renamed). Application code does not use it: it reads and writes the aliases public.workspaces, public.workspace_roots and workspace_id, which are views over the physical tables. A new column that references a workspace is named workspace_id.
  • Root (root URL) — a placement: an exact hostname plus an optional, normalized path prefix (e.g. example.com/fr/) that resolves to one workspace. A workspace with roots has exactly one canonical root — its user-visible label and the default ingest scope — plus any number of alias roots that resolve to the same workspace and widen what gets crawled. A workspace may also be rootless.
  • config_key — a workspace's stable configuration handle: unique, assigned once, and never derived from a root, so a root can move without re-keying configuration, knowledge, or history. For a workspace at a bare host it equals the registered domain; a path-rooted workspace gets an opaque slug.
  • Corpus — a workspace's knowledge boundary: its documents, FAQs, vectors, and graph. Each workspace owns exactly one. A turn retrieves from the corpus of its resolved workspace and nothing else, so a sibling market's knowledge is never named.
  • Storage key (corpus address) — the opaque key that addresses a corpus in the storage layer (LightRAG working set, Mongo tenant_id, Neo4j tenantId). Retrieval resolves an ordered list of storage keys with exactly one entry.
  • Tenant — the isolation scope in the storage layer, keyed by the storage key. "One corpus per workspace" is "one tenant per workspace."
  • corpus_status — the lifecycle of a workspace's corpus: absent → indexing → ready | failed. Independent of display activation: ingestion never changes a root's enabled flag. Runtime serves an enabled root only when its workspace is live and its corpus is ready in the requested environment; an unready selected workspace does not fall back to a sibling. A demo or video account's workspace (client_type demo or video) also serves before its corpus is ready.
  • Display activation (root.enabled) — whether a placement serves visitors. A placement that is off serves no widget and no chat; its pages never fall back to a shorter route. Staff can still preview it (rose-chat, the Playground). A new client's first workspace is enabled at creation; additional workspaces start disabled. Disabled workspaces can still have their knowledge edited, scraped and indexed. New bare-host aliases inherit the canonical root's activation; existing placements keep their manual choices.
  • Legacy workspace — an existing client migrated to a single public.sites row that owns its existing corpus, backfilled at corpus_status='ready'. Its storage key is its domain and its existing tenant data is reused, never relabelled or re-indexed.
  • Crawl seeds — the start URLs a crawl reads, derived from a workspace's roots: the canonical root sets the default scope even when disabled; explicitly selected alias roots widen it. Display activation is not crawl authorization. Scopes of workspaces on the same host may overlap: a / root covers every path, including a sibling's path prefix. A / root also crawls its www twin and its subdomains, except a subdomain another workspace or client registered as a root. Each subdomain the root's map links to is mapped too, so its own sitemap is read (help.mooncard.co under mooncard.co). Choosing which pages a workspace covers is the job of whoever configures it; each workspace still answers only from its own corpus.
  • Agent — a surface that works in a workspace (Website Agent, Content Agent, …). Agents live in a workspace and read its corpus; they are not an internal LangGraph node or a response-agent prompt, and they own nothing.
  • Vendor agent choice — Rose for Agents and Ask Rose offer the website agent of each available workspace. Internal code uses workspace_id; callers choose an opaque agent_id that identifies that workspace. There is no separate market entity. Choose from the buyer's stated country, product or business context; ask when unclear.
  • Market vs response language — market is business vocabulary (e.g. France, the UK), not a code type. A workspace may carry regional behaviour and facts; the response language follows the visitor or channel and can differ from that region. An English question about French payroll still needs the French workspace.
  • Client type (clients.client_type) — what a client row is. Real customers are client (paying), onboarding and self_serve; former has churned; demo and test are Rose's own; video is a throwaway bot created only to record a product video. Video clients are most rows (945 of 1,037 enabled clients with an enabled domain on 2026-09-24), so any count or list of "clients" filters on client_type first, never on enabled alone.

Knowledge ingestion control plane

See the control-plane overview for the full model; the ADR records the decision and its rationale. The control plane turns a knowledge command into durable, observable background work: Supabase owns workflow state, and the execution systems (Cloud Tasks, the content worker, the document-loader job) only deliver work.

An operation owns its work items, and each work item records its physical attempts. This is the identity trail behind progress, retry, cancellation, and recovery.

classDiagram direction LR class Operation { +uuid operation_id +enum operation_type +enum source_scope +enum status +string idempotency_key } class WorkItem { +enum stage +enum loader_mode +enum status +int max_attempts } class Attempt { +int attempt_number +int dispatch_generation +hash lease_token_digest +enum outcome } class CorpusFreshness { +int shared_revision +int loaded_revision_per_env } Operation "1" *-- "1..*" WorkItem : owns WorkItem "1" *-- "1..*" Attempt : records Operation "0..*" ..> "1" CorpusFreshness : loader coordinates on note for Attempt "Only the claimant holding an unexpired lease can advance state (fenced).\nAn attempt outcome (e.g. duplicate_noop) never becomes the work-item outcome.\ndispatch_generation namespaces GCS artifacts and dispatch identifiers."
  • Control plane vs data plane — the control plane is the orchestration layer that decides and tracks ingestion work and owns its state (the Knowledge API and Supabase). The data plane is what executes the work (the content worker and document-loader job). Execution systems deliver work; they do not own its state.
  • Knowledge API — the private knowledge-api-{environment} service that owns commands, transactional state transitions, dispatch, recovery, document-loader admission, and the sanitized operation status returned to the backoffice. It is the workflow owner; it never calls back into the admin API.
  • Content worker — the private knowledge-content-worker-{environment} service that executes bounded stages (map, triage, discovery finalization, sample, section decision, scrape, clean). It writes artifacts to GCS and reports results; it does not own workflow state or write to RAG.
  • Operation (knowledge.ingestion_operations) — one user or system command (e.g. full refresh, website policy change, retrain). It carries the operation_id that follows the whole flow, its type and scope, aggregate progress, and absolute idempotency identity.
  • Work item (knowledge.ingestion_work_items) — one logical bounded unit of an operation, such as a map, a per-page scrape or clean, or one document-loader run. Its identity survives transient retries.
  • Attempt (knowledge.ingestion_work_item_attempts) — one physical dispatch and execution of a work item. Multiple attempts can back one work item without changing its single logical outcome.
  • Fenced attempt / lease token — a claimed attempt holds a cryptographically unguessable lease. Only the current claimant, presenting the token while its digest matches the unexpired fence, can post progress or terminal state. A stale or duplicate execution cannot advance an item a newer generation already claimed.
  • Dispatch generation — a monotonic counter per work item. It namespaces Cloud Task/Cloud Run dispatch identifiers and GCS artifact paths (generation-<n>/), so a later legitimate attempt is isolated from an earlier one without risking accidental duplicate delivery within a generation.
  • Attempt outcome vs work-item outcome — an attempt outcome describes one physical run; duplicate_noop means that run did no work. It never completes the logical work item or the operation.
  • Guarded snapshot publication — content completion atomically validates the expected current snapshot and policy version before publishing new canonical snapshot metadata, so stale work cannot publish over newer operator intent.
  • Create-only artifacts — worker GCS writes use create-only preconditions. A retry may re-write identical bytes but can never overwrite a different existing body; failed cleaning leaves raw evidence in GCS without publishing a canonical snapshot.
  • Corpus freshness (knowledge.ingestion_corpus_freshness) — a job-level ledger holding one monotonic shared revision per (site, source_scope) and the last revision each environment successfully loaded. Only a completed fenced loader attempt advances an environment's loaded revision; a lagging environment must run the loader even when content hashes are unchanged. It proves an environment still owes a loader run — not that any specific snapshot reached LightRAG.
  • Recovery scheduler — a Cloud Scheduler tick (every minute) that re-dispatches due pending work, resolves ambiguous dispatch, recovers expired leases, and is the automatic producer for dirty source scopes. Retries use bounded max_attempts and exponential backoff, so a deterministic failure cannot become a retry storm.
  • Reviewed re-scan / review — a source-bound website_rescan operation maps the site and publishes an immutable review (added, returning, unchanged, missing URLs against the scanned generation) instead of mutating the catalogue. Applying the review is a second atomic command; dismissal changes nothing. "Missing" means absent from the latest complete map, not a proven HTTP 404.

Rose for Agents

  • Buyer — the person an AI assistant works for. Has the Rose for Agents connector installed and is signed in on id.userose.ai; every tool requires it.
  • Vendor — the company the buyer asks about or buys from.
  • Rose customer — a vendor whose website runs a Rose agent. Only Rose customers can be questioned (ask_vendor) or bought through the connector.
  • Listed — a Rose customer switched on in Rose for Agents, with a backend (none or http); published plans are optional. See the support levels in Rose for Agents.
  • Agent-buyable — a listed vendor on the http backend: an assistant can try, sign up, pay and use it without the buyer visiting a website.