Platform Administration

This chapter covers two parts: Platform Management (tenant owner/admin system configuration, path /platform) and the Platform Admin Zone (platform operators, path /admin).

Tenant-side Platform Management

Path: /platform

Platform management provides system configuration for tenant management roles (owner/admin).

🔒 Owner and admin only. Members don't see this menu group; direct URL access is intercepted by route guards showing the "No Access" page; every backend endpoint has an additional require_role hard gate returning 403 — three independent lines of defense; bypassing the frontend doesn't grant access.

LLM Model Management

Path: /platform/llm

Manage the tenant's available LLM model configurations.

Steps:

  1. View the configured LLM provider list
  2. Click Add Model to add a configuration
  3. Fill in model info: provider, model name, API Key, endpoint URL
  4. Click Test Connection to validate
  5. Set the default model and parameters (temperature, max tokens, etc.)

Health status & automatic failover:

  • The provider list has a health status column: Normal (green) / Abnormal (red) / Unknown (gray)
  • Hover the Abnormal tag to see the latest probe failure reason and time
  • The system probes provider availability automatically every 5 minutes in the background (no token cost; marked Abnormal only after 2 consecutive failures; Azure providers aren't probed and stay Unknown)
  • On LLM call failure or when a platform provider isn't open to the current plan, the system automatically switches to the next available provider in candidate order (plan-permission switches are silent); normally no manual intervention is needed

Connector Configuration

Path: /platform/connectors

Manage external system connectors (WeCom, DingTalk, Feishu, WeChat, Telegram, Email, Webhook, generic REST).

Steps:

  1. View the connector list (name/mode/status/last test)
  2. Click Add Connector
  3. Choose connector type and receive mode
  4. Fill in connection parameters (credentials stored encrypted; leave blank when editing = keep current value)
  5. Click Test Connection (WeChat connectors prompt QR binding first when unbound)
  6. Enable/disable connectors; expand rows for runtime details and binding status

WeChat connector (ClawBot):

  • After adding and enabling a WeChat connector, a binding card appears in the expanded row
  • Click the generate button to show a binding QR code (rendered locally in the frontend); scan with the personal WeChat to be connected; only one WeChat account can be bound at a time; re-binding invalidates the old account
  • Once bound, send messages in that WeChat to chat with AI both ways; messages are recorded under the clawbot channel in session management
  • Unbinding clears the credential; you can re-bind by scanning again

Telegram connector:

  • Create a Bot via @BotFather in Telegram and get the Bot Token
  • Add a Telegram connector and choose the receive mode:
    • Long polling (default): the server pulls messages; no public callback needed; works out of the box
    • Webhook: Telegram pushes; the backend needs an HTTPS domain (Telegram accepts ports 443/80/88/8443 only); after saving, fill in the callback root URL in the expanded row and click Register; re-register after changing the token
  • Optional settings: API URL (self-hosted Telegram Bot API or reverse proxy), Proxy URL (restricted networks)
  • The first session that messages the Bot is automatically bound as the receive target; AI replies quote the original message
  • Leaving credentials blank when editing = keep the current token

💡 Personal channels (also for members) are covered in AI Workspace · My Channels.

Tenant Management

Path: /platform/tenants

View and edit tenant info: name, slug, member count, creation time, tenant settings (currency preference, etc.).

User & Permission Management

Path: /platform/users (menu: Users & Roles)

Manage users and roles within the tenant (three roles: owner/admin/member).

Operations by role:

Operation owner admin
View member list (name/email/role/status) ✅ plain email ✅ plain email
Invite new members (admin/member only) ✅ ✅
Resend invitation (inactive members) ✅ ✅
Change user roles ✅ (to admin/member only) ❌ read-only role column
Remove members ✅ ❌

Steps:

  1. View the user list (name, email, role, status)
  2. Invite a member: enter email and role (admin/member); the system sends an invitation email with an initial password (if the email fails, the initial password is shown directly on the page — keep it safe)
  3. Resend invitation to inactive members
  4. Change user roles (owner only; dropdown offers admin/member; the owner's own role can't be changed)
  5. Remove members (owner only)

🔒 Role changes and removals are owner-only (ownership-level operations): prevents admin self-escalation or escalating others — an admin cannot create admins. Backend require_role("owner") hard gate; admin calls get 403 directly.

🔒 Members may see the member list in collaboration scenarios, but emails are masked (first character + *** + @domain); full emails are owner/admin only.

Invite Code Management (Referral Codes)

Path: /platform/invitations

Manage the tenant's referral codes. A referral code is not a member invitation: registrants create a brand-new starter tenant as owner — they don't join your tenant; referral attribution is recorded automatically.

Steps:

  1. View the code list (code, used/remaining, validity, notes)
  2. Generate new codes (each tenant has a generation quota)
  3. Copy and share the code with new users
  4. Revoke (disable) unused codes

💡 To let members join this tenant, use the email invitation in "Users & Roles" — not referral codes.

System Settings

Path: /platform/settings

Setting categories:

  • Currency (✅ persisted): display currency (CNY/USD), default rate 7.2
  • Security: password policy, session timeout (⚠️ UI placeholder, not persisted)
  • Email: configured centrally by platform admins (see Email Settings & Email Templates below); tenants don't need their own SMTP
  • AI: default model, token limits (⚠️ UI placeholder, not persisted)

💡 Currency settings are stored in tenants.settings JSONB — no schema migration needed. Internal storage is always USD; only the display layer converts.

Subscription Management

Path: /platform/subscription (menu: Subscription)

View and upgrade the tenant's subscription plan:

  • Plan cards: purchasable plans with monthly/yearly toggle (unpriced periods can't be purchased online)
  • Current subscription: current plan, status, expiry (perpetual plans have no expiry)
  • Online upgrade (owner only): pick plan & period → order → WeChat QR / Alipay redirect payment → the plan takes effect immediately upon success (pro-rated extension)
  • Order records: this tenant's orders only (pending/paid/closed); visible to owner and admin

🔒 Ordering and upgrades are owner-only (subscription is an ownership-level tenant-asset operation); admin can only view plans and orders.

💡 Subscription status updates immediately on successful payment; after expiry, entitlements fall back to starter and can be re-subscribed anytime.

Audit Log

Path: /platform/audit

Audit records of all tenant operations: operator, operation type, target, time, details.

Platform Admin Zone

Path: /admin

Platform admins land in the admin zone automatically after login; its menus differ completely from tenant menus.

Admin Dashboard

Path: /admin/dashboard

Platform-level statistics: total tenants, total users, total AI interactions, system resource usage.

Tenant Management

Path: /admin/tenants

Manage all platform tenants:

  1. View the tenant list
  2. Click a tenant for details
  3. View/edit tenant info
  4. Assign/change tenant plan (dropdown lists enabled plans only)
  5. Enable/disable tenants

Plan Management (Four-tier Entitlement Model)

Path: /admin/plans (menu: Plan Management)

Manage the tenant plan registry — a plan determines the tenant's four entitlement tiers (L1 center authorization / L2 advanced features / L3 quotas / L4 enterprise policies):

  • Plan list: code (starter tagged "Default")/name/entitlement matrix summary (centers x/8 · advanced y/31 · channels z/7)/static quotas/invite quota/tenant count/enabled status
  • Create/Edit (registry-driven; authoritative code table GET /admin/plans/registry):
    • L1 center & standalone capability authorizations (8 toggles): six centers (assessment/decision/planning/delivery/knowledge/operations) + AI copilot (copilot.chat) + ticket support (support.tickets)
    • Channel authorizations (7 toggles): email/Telegram/WeCom/WeChat (ClawBot)/DingTalk/Feishu/generic REST — when off, corresponding connectors can't be created
    • L2 advanced features (31 toggles, grouped by center): e.g. AI scoring & judging, AI interviews, AI report generation under the assessment center; a group is void when its center is off
    • L3 quotas: 7 static (users/transformation projects/knowledge bases/AI apps/channel connections/KB storage MB/invite quota) + 4 monthly (AI calls/AI tokens/AI cost USD/eval runs) — blank = unlimited; monthly AI cost (monthly_ai_cost_usd) is stored and enforced in USD; edit dialogs and expanded rows show ≈¥ reference at the platform bookkeeping rate (reference only)
    • L4 enterprise policies (5 items, reserved): SSO/audit export/data retention/on-prem/SLA — modeled and displayed but not enforced in the current version
    • Model policy: allowed tiers (free/standard/premium multi-select) + model allowlist/denylist (tag input; typing suggests models of added providers with source annotations to prevent typos — a mistyped denylist entry silently allows the model with no warning; free-form input also allowed); all three empty = unrestricted
  • Delete: only plans with no tenants and no pending orders can be deleted; starter (the default for new tenants) can't be deleted. Deletion is refused while tenants use the plan or pending orders exist (orders time out after 15 minutes) — reassign tenants first or wait for orders. Deleting a plan also cleans the plan key from platform LLM providers' "plan access" maps — the corresponding toggle disappears from the LLM config page with no dangling switches
  • Disable: disabled plans can't be assigned to new tenants; existing tenants are unaffected
  • Expanded row: monthly quotas + L4 policies + model policy + LLM access summary (per platform provider, read-only: available = open / unavailable = closed; edit in "LLM Provider Management")

Built-in four-plan seed matrix (free/starter (default)/pro/enterprise):

  • L1: all four plans enable six centers + copilot.chat + support.tickets
  • L2: pro/enterprise enable 21 advanced features (AI scoring/interviews/report generation, ROI analysis, AI planning artifacts, RAG, AI knowledge governance, etc.); enterprise adds 10 exclusives (assessment/planning/knowledge governance, portfolio analysis, approval countersigning, PMO, knowledge graph, experience reuse, experiment canary, operations governance)
  • Channels: email = starter+; Telegram/WeCom/REST = pro+; WeChat (ClawBot)/DingTalk/Feishu = enterprise exclusives
  • L3 quotas:
Quota free starter pro enterprise
Max users 3 10 50 Unlimited
Max transformation projects 1 3 20 Unlimited
Max knowledge bases 1 2 10 Unlimited
Max AI apps 1 2 10 Unlimited
Max channel connections 0 1 5 Unlimited
KB storage (MB) 512 5,120 51,200 Unlimited
Invite quota 0 10 50 200
Monthly AI calls 100 500 5,000 Unlimited
Monthly tokens 500,000 2,000,000 20,000,000 Unlimited
Monthly AI cost (USD) 1 10 100 Unlimited
Monthly eval runs 5 20 200 Unlimited

Gating semantics (when an entitlement is turned off, applies to tenants on that plan):

  • Frontend: the corresponding menu entry hides automatically; direct route access shows a "Feature not enabled" page
  • Backend: L1 module APIs return 403 (plan_feature_disabled) with a unified frontend toast; L2 is endpoint-enforced (165 advanced-feature endpoints behind require_plan_feature)
  • Agent fallback: if a routed agent's center isn't enabled, it falls back to chat_agent; SSE metadata carries entitlement_fallback
  • Channel sessions: inbound channel messages require copilot.chat to be enabled; otherwise events are dropped and logged (soft enforcement); existing connectors aren't retroactively deleted
  • Event-type entries like AI operations re-evaluation/experience replay are soft-enforced (logged as warning and skipped, without interrupting main flows)
  • Quota enforcement: exceeding static quotas (7 items) blocks creation (403); exceeding monthly quotas returns 429 (plan_limit_exceeded) with a unified toast; monthly quotas reset per calendar month — monthly_ai_calls/tokens/cost_usd (3 items) are pre-checked at the LLM gateway (including cache hits); monthly_eval_runs is checked at eval creation by counting this month's runs; blank values = unlimited (uniform across all codes, incl. invite_quota)
  • Soft enforcement: existing over-quota data is preserved; only new additions are blocked

Model policy: plans can constrain the available model range, applying only to platform providers (tenant-built providers are unrestricted):

  • Precedence: denylist (denied_models) > allowlist (allowed_models) > tiers (allowed_tiers); all three empty = unrestricted (zero behavior change for existing plans)
  • Tiers are maintained in "LLM Provider Management - Model Price Catalog" (free/standard/premium); models absent from the catalog are treated as standard
  • Enforcement surface: the LLM gateway call entry (including cache-hit re-checks — restricted models hitting cache are treated as misses and finally rejected); tenant-visible model/provider lists filtered by policy
  • Calls naming a restricted model return 403 (model_not_allowed); the main chat stream (SSE) reports via an error frame; calls without a named model auto-select the first allowed model
  • The plan's monthly AI cost quota (monthly_ai_cost_usd) is unaffected — still booked at actual platform cost (see the pricing chain under LLM Provider Management); on the tenant side, "Organization Settings" shows this quota in the tenant's currency (same basis as the usage page) while enforcement stays in USD

Tenant-level overrides: super admins can configure entitlement_overrides for individual tenants (three isomorphic maps), taking precedence over plan values (effective after deployment; for temporary expansion/narrowing without creating new plans).

Invite quota migration: the invite-code quota formerly on the "Branding" page has migrated here per plan (the branding page keeps a redirect notice); free-tier invite quota is now configurable (it wasn't in historical versions).

Branding

Path: /admin/brand

Configure platform branding: platform name, logo, login page copy, theme color.

Invite Code Management

Path: /admin/invitations

Platform-level invite codes for new tenant registration, in two types:

  • PLATFORM codes: can specify a target plan (target_plan); new tenants registered with the code get that plan directly (falls back to starter if unspecified or unavailable)
  • TENANT codes: referral semantics — registration creates a new starter tenant (platform-created codes have no referral attribution)

⚠️ The extra options the page offers for TENANT codes (target tenant, member type) don't take effect in the current registration flow — registration always creates a brand-new tenant, never joining a specified one.

User Management

Path: /admin/users

Manage all platform users: cross-tenant user list, user details, role adjustment, disable/enable users.

LLM Provider Management

Path: /admin/llm

Manage platform-level LLM providers:

  • Add/edit/delete LLM providers
  • Configure API keys and endpoints
  • Set the global default model
  • Monitor API call volumes and costs
  • Configure plan access toggles: per-plan control of whether tenants on that plan may use this platform provider (new providers default to enterprise only); tenants on non-open plans automatically switch to a permitted provider; tenant-built providers are unaffected
  • No per-provider monthly token limits anymore — plan monthly AI usage (calls/tokens/cost) is governed uniformly by "Plan Management" monthly quotas
  • Model price catalog: maintain list prices (input/output/cache-hit, in USD or CNY per row, per million tokens) and tiers (free/standard/premium):
    • Pricing chain (cost accounting): catalog row (active when both input+output prices set) → litellm built-in prices → gateway fallback → 0; the catalog stores exceptions only (custom models litellm doesn't know, price corrections, cache differentials); uncatalogued models go straight to litellm
    • Pricing currency (per row USD/CNY): CNY-listed domestic providers can be entered directly (table price columns show a ¥ prefix; unit labels switch with currency); bookkeeping is always USD — CNY rows convert to USD at the platform bookkeeping rate at pricing time before entering the accounting chain (llm_calls.cost, monthly ledger, quota enforcement); USD rows are booked as-is
    • Platform bookkeeping rate (1 USD = X CNY, default 7.2): view via the "Bookkeeping Rate" button at the top-right of the catalog card; edit (limited to 0.5-25; saving requires super-admin and is audit-logged); affects future pricing only — never rewrites historical call costs, monthly ledgers or stored plan quotas
    • Model association: the "Model" input suggests models of added providers (options annotated with the source provider name, filterable as you type) to avoid typos (a mistyped name never matches the catalog and silently falls back to litellm); free-form entry also allows forward pricing of unconfigured models
    • Cache awareness: OpenAI-style prompt_tokens_details.cached_tokens / Anthropic-style cache_read_input_tokens are extracted automatically into usage (llm_calls.cached_tokens); cache hits are priced at the cache price when set (input price otherwise)
    • Tiers feed "Plan Management - Model Policy"; uncatalogued models are standard; deleting a row reverts that model's cost to litellm prices
  • View each provider's health status (Normal/Abnormal/Unknown; hover Abnormal for failure reason and last probe time)

Health probing & failover:

  • Background probes every 5 minutes (zero token cost; marked Abnormal after 2 consecutive failures; Azure isn't probed and stays Unknown)
  • Abnormal providers aren't disabled — they remain last-resort candidates (soft degradation) and return to priority automatically once recovered
  • On call failure the gateway switches automatically along the candidate sequence: other providers of the same model → default provider → fallback model
  • Provider-level failures enter a 60-second cooldown (skipped during cooldown, not consuming attempt slots); plan-permission denials don't enter cooldown (that state is plan-level, avoiding impact on other tenants)

Ticket Management

Path: /admin/tickets (menu: Ticket Management, headset icon)

Handle tenant-submitted tickets across tenants:

  • List: all tenant tickets (number/tenant/submitter/type/title/status/time), filterable by status and type
  • Processing: click "Process" to open the detail drawer — full description, enlarged screenshot previews, tenant and submitter info
  • Flow: set status (Submitted → Processing → Resolved / Closed) + fill in the reply (visible to the tenant)
  • Email notification: every new ticket emails all active platform admins automatically (requires SMTP configured in "Email Settings"; without it, only a log is written — tenant submission is unaffected; copy customizable via ticket_notify in "Email Templates")

Handling tips: after the email reminder, set the status to "Processing" promptly; when done, fill in the conclusion reply and set "Resolved" — the tenant sees the result in real time in their "My Tickets".

Payment Management

Path: /admin/payments (menu: Payment Management)

Configure payment channels and manage cross-tenant subscription orders:

  • Payment settings: WeChat Pay V3 (appid/merchant ID/APIv3 key/cert serial/private key/callback URL) and Alipay Face-to-face Payment (app ID/app private key/Alipay public key/callback URL); keys stored encrypted with masked echo; master switch Enable Online Payments (when off, tenants can't order online; plan changes are manual by super admins)
  • Order management: cross-tenant order list (tenant/plan/period/amount/status/time), filterable by status
  • Manual reconciliation: orders paid off-channel (e.g. bank transfer) can be marked paid via "Manual Reconcile" with a note — operator and note persist with the order (audit trail); the tenant plan takes effect immediately

💡 Channel callbacks reconcile automatically; manual reconciliation is for bank transfers/offline payments, with notes kept long-term as reconciliation evidence.

Email Settings

Path: /admin/email (menu: Email Settings)

Platform-level SMTP runtime configuration (no server .env changes needed):

  • SMTP config: server / port (default 465) / account / password (encrypted, masked echo) / sender / TLS
  • Frontend URL: prefix for login links in invitation emails (blank = server default FRONTEND_URL)
  • Send test email: send a test to the admin mailbox to verify connectivity
  • Priority: configured here (platform settings) the whole group takes effect; falls back to server .env SMTP_* when unset; delivery failure doesn't affect business (best-effort)

Email Templates

Path: /admin/email-templates (menu: Email Templates)

Edit system email copy (custom content wins; deleting restores the built-in template):

Template Purpose Required variables
member_invite Member invitation email (login URL + initial password) email, password
ticket_notify New-ticket alert email (to all active platform admins) none (all optional)
  • Syntax: {{variable}} placeholders + {{#if variable}}...{{/if}} blocks (hidden entirely when empty); click variable tags to insert at the cursor
  • Validation: missing required variables block saving (preventing silent failures like invitation emails losing the password); variable values are pre-escaped by the system
  • Restore default: delete the custom content to fall back to the built-in template