Skip to content

Glossary ​

Rewritten 2026-08-08. The previous version defined Tier as a directory under src/tiers/, Pillar as one of three products including BioLink, and UI Hybrid System as the UI model — all three belong to the retired Vite SPA (legacy/) or to retired product framing. Index of truth: current architecture state.

Platform model ​

TermMeaning
Setu CardThe universal public identity for every user, at qrsetu.com/:slug. The platform's core differentiator, not a module. Supersedes "Service Card" and retires "BioLink" (QRS-172, 2026-07-23).
IndustryWho you are — dairy, salon, car_sales. One industries row with a stable TEXT key, never an integer (integer ids promoted across environments caused QRS-249). Open set: adding one is a row.
ArchetypeWhat you sell. Exactly three: goods (a stocked item) · time (a slot) · expertise (an enquiry). ecommerce_cart and catalog_informational were compositions, not archetypes (QRS-392).
PrimitiveHow you run. The closed set of eleven that carries all the platform's cost: Catalogue · Party · Schedule · Recurrence · Fulfilment · Ledger · Balance · Location · Resource · Asset · Campaign. A new primitive requires a written justification that it serves ≥3 industries — the governing gate of the whole architecture.
CompositionAn industry's enabled_primitives[]. Dairy includes Recurrence, boutique does not — which is why archetype-only gating fails, and why applicability is derived from composition rather than stored in a matrix.
The cost equationO(primitives), not O(industries). Eleven primitives compose into ~45 industries. Never build a dense industry × feature matrix.

Users and tenancy ​

TermMeaning
PrincipalThe user. One users row per person, id = auth.users.id. There is no second account type.
WorkspaceThe business tenant — the thing that owns a card, a catalogue, and money. Named workspaces and not businesses because the tree legitimately contains non-businesses (a region, a division, a brand shell). The UI still says "your business".
The three user categoriesDistinguished by membership count: consumer 0, solo owner 1 (member_owned), enterprise employee 1 (org_owned). See user ecosystem.
primary_contextA preference on users choosing the landing route. Never an authorization input — a user-mutable column that grants access is a privilege-escalation primitive. Renamed from account_type for exactly that reason.
ownership_modelmember_owned | org_owned. Does three jobs: seat-revocation behaviour, who keeps the leads, and the oversight privacy boundary.
LocationAn address, not a business unit. If a place needs its own card and its own P&L it is a workspace; if it is only an address it is a location.
Sharing vs oversightSharing flows DOWN (opt-in share_* flags, default off — a child may use an ancestor's resources). Oversight flows UP (an ancestor may read, never write, org_owned descendants). Two mechanisms, never symmetric.
SeatA licence for a USER, not a workspace. 8 showrooms + 30 agents = 39 cards but 30 seats.

Feature control ​

TermMeaning
The three axesApplicability (does this workflow apply at all — structural) AND entitlement (is it unlocked, and capped how — commercial) AND availability (is it actually shipped). effective = all three.
Grant scopeOne of 8 kinds in feature_grant_scopes, precedence 10→80: platform · archetype · industry · plan · workspace_group · workspace · workspace_member · user.
Sparse grantsfeature_grants holds deviations only. Defaults come from composition. ~30 industries × ~40 features = 1,200 cells nobody maintains — so that matrix is never built.
Feature grant ≠ RBAC permissionIs this workflow available vs can this role do this action on it. "Agents may view stock but not edit prices" is RBAC (ADR-0024), not a grant.
on_exceedWhat happens at a limit: block_new · soft_warn · degrade. A cap with no defined overflow behaviour is an outage waiting for a busy Saturday.

Data access ​

TermMeaning
The one hard rulesupabase.from() is banned in app code. Keeps table names off the network wire.
packages/dataThe data seam: a typed {Domain}Service interface + a stub impl per domain. Presentation depends only on the interface.
RPCA Postgres function called via supabase.rpc('get_…') from a service, never a component. Read-only. SECURITY DEFINER + SET search_path = public + revoked from public/anon/authenticated by name, then granted explicitly.
Edge Function (EF)A Deno/TS function called via functions.invoke() from a service. Writes, secrets, external HTTP, multi-step. The primary write-enforcement layer; RLS is defense-in-depth. Both always required.
Type A / Type B / Webhook EFType A = user-facing, JWT verified, domain-action. Type B = cron/internal, --no-verify-jwt, domain-noun-verb. Webhook = HMAC + timestamp window + constant-time compare + idempotency via a UNIQUE event id.
EDGE_FN mapA per-domain *_EDGE_FN constant exported by the service. EF names are never inline strings at a call site.
idempotencyKeyRequired, not optional, on every mutation. Generated when the user commits and reused across retries — a fresh key per retry defeats the mechanism.
OutboxThe transactional outbox table + worker. How a write reaches Cloudflare cache purge without a distributed transaction. Also how a scheduled campaign boundary purges.
my_* functionAn RLS helper scoped to auth.uid(), called from inside a policy: workspace_id = any (my_workspace_ids()).

SQL naming — five families ​

FamilyMeansExamples
get_*Retrieve stored rowsget_industries · get_public_setu_card
resolve_*Derive by computation over several sourcesresolve_features · resolve_workspace_plan
is_*Predicate, bare booleanis_slug_reserved
my_*RLS helper scoped to auth.uid()my_workspace_ids · my_oversight_workspace_ids
{table}_{action}Trigger function, named for what it guardsworkspaces_maintain_path · setu_cards_slug_write_once

Anything outside these five is a naming violation, not a sixth family. Table names must be domain-specific: setu_cards not cards, platform_plans not plans, process_primitives not primitives. The test is "will a second thing plausibly want this name?"

Process and governance ​

TermMeaning
Design-governance asymmetrySystemic surface (packages/tokens/** + apps/*/src/ui/**) is design-first, no exceptions. Screen composition is code-first, freely. Record every divergence in the drift ledger in the same PR (ADR-0015, check:design fails closed).
ParityA feature ships on Android native · iOS native · Web PWA together. The exception path is retired — there is no pre-approved deferral. Scope is the pressure valve: a feature that cannot reach all three does not enter the release.
Divergence seamAnything backed by a native module or browser-only API — camera, push, storage, share, clipboard, deep links, offline. Named at G0, not discovered at G3.
Expand-contractThe only safe migration shape: add-nullable → backfill → switch → drop. Never a breaking change in one step.
Change RecordEvery production change, declared in release.json. deploy-prod.yml refuses to apply one that is not — documentation is load-bearing, not a chore.
QRS-###A permanent tracker id for every confirmed issue / risk / debt / decision. See the Dev Tracker.
PromotionDeliberately applying every migration / EF / secret / storage / cron change to both Supabase projects, Dev first. Dev/UAT does not self-sync.
Wave 1 / Wave 2Wave 1 = the schema Store needs (identity, tenancy, cards, catalogue, grants, media, outbox). Wave 2 = Party · Schedule · Recurrence · Fulfilment · Ledger · Balance · Asset · Campaign · RBAC · billing · analytics.
docs:gennode tools/generate-docs.js — regenerates this portal's auto-generated pages (currently the EF index).

Retired vocabulary — do not reintroduce ​

Retired termReplaced byRetired on
BioLink · bio_pages · bio_links · /b/:slugThe Setu Card at /:slug2026-07-23 (QRS-172); tables dropped 2026-08-08
Studio / My Setu website builder · /w/:slug · setu_pages · studio_*Not in R1. The Setu Card carries the public presenceDropped 2026-08-08
Pillar (three products)One platform, one card, industries × archetypes × primitives2026-08-08
profiles · profile_items · business_domain_id (integer)users · workspaces · catalog_items · industry_key (text)ADR-0020, 2026-08-07
capabilities · get_my_capabilities()features · feature_grants · resolve_features()ADR-0021
subscription_tiers · user_subscriptions · profiles.subscription_tierplatform_plans + feature_grants at plan scopeADR-0021; tables dropped 2026-08-08
public_page_ops_*The transactional outboxDropped 2026-08-08
UI Hybrid System (src/components/ui + per-tier overrides)apps/mobile/src/ui (RN primitives) + shadcn/ui in apps/web, both over @qrsetu/tokensADR-0011
Tier as a src/tiers/ directoryTwo stacks first, tiers inside each (see tier system)ADR-0011/0012
Vitest / Vite / import.meta.env / VITE_* in app codejest-expo (mobile) · vitest (web) · node --test (packages) · EXPO_PUBLIC_*ADR-0012
Green baselineThe gate layers in CLAUDE.md § Commands—