Workspace
The Workspace nav section (sitting above Administration in the app shell) holds the pages a tenant admin needs to operate their org without filing a support ticket. All five pages are admin-gated and scoped to the caller's org — there is no cross-tenant view here.
Added in v0.0.44.
Members
/members — Invite teammates by email. Recipients receive a link, land on a public /accept-invite page, set their own password, and join the org with the assigned role.
- Existing accounts — invites for an email that already has a Honeyframe account add a
user_orgsrow instead of creating a duplicate user. The recipient signs in with their existing password and sees the new org in their account picker. - Token TTL — 7 days. Past expiry the link 410s.
- Revoke — open the invite row and click Revoke. Effective immediately.
- Dedup — the platform refuses a duplicate open invite for the same email; revoke the old one first.
- Storage — sha256-hashed at rest in
honeyframe.invites. The bare token is never stored.
Usage
/usage — Read-only KPI roll-up over your org. Period switcher: Today / 7d / 30d / All.
| KPI | What it counts |
|---|---|
| LLM calls | Chat + agent calls in the period (split by source) |
| dbt runs | Successful + failed dbt runs |
| Datasets | Active datasets in the org |
| Dashboards | Active dashboards in the org |
| Members | Active users + open-invite count |
| Storage | Bytes on disk under DATA_DIR/orgs/<org_id>/ + file count |
Storage is walked from disk and cached server-side for 5 minutes — click Refresh storage after a large upload to drop the cache and re-walk.
There is no write surface on this page. Quota policy decisions (e.g. limits, alerts) belong to the operator, not this view.
AI Keys
/ai-keys — Bring your own LLM keys. Paste an OpenAI / Anthropic / Ollama key and that org's chat / SQL / agent traffic bills against your account instead of the platform default.
- Provider list — OpenAI, Anthropic, Ollama (with a
base_urlfield for self-hosted Ollama). - Model override — optional. If unset the platform falls through to its own default per provider.
- Fallback — when a provider key is unset for an org, that org continues to use the platform default. Existing tenants on a v0.0.43+ deploy see no behavior change.
The plaintext key never appears on screen after save:
- The form input is
type=password. - The list shows only
••••<last_4>. - The server returns
{provider, masked_key, last_4, model_override}. Plaintext is never read back, even by the page that wrote it. - Remove is gated behind a confirm dialog. Removing reverts that provider to the platform default.
Encryption: AES-GCM over the plaintext key. The encryption key is derived from the existing platform JWT secret (no new operator env required). Decrypt failure on a key (e.g. JWT secret rotated) falls through to the platform default — the LLM stays available even with half-rotated keys.
Custom Domains
/custom-domains — Map your own domain (data.acme.com) to your Honeyframe Space.
State machine:
pending → verifying → active
↘ failed ↘ removed
- Add domain. Enter the hostname. Honeyframe rejects its own apex + reserved hostnames; gives you a verification token.
- Set DNS TXT. Add the TXT record on your DNS provider. Honeyframe polls; once the record is visible the row flips
verifying → active. - Cert + nginx. On
active, Honeyframe renders an nginx vhost, reloads, and runscertbot --nginxfor HTTP-01. - Live. The
host_orgmiddleware resolves the host to the sameorg_idit would for a<slug>.app.honeyframe.iohit, so auth / license / branding / RBAC work identically.
Failure at any phase flips status to failed with last_error captured. Click Retry to re-run from the failure point. Removing a domain triggers nginx vhost teardown + certbot revoke; the row stays for audit with status='removed'.
Health
/health — Six-probe operator dashboard. Polls every 30 seconds and rolls up the worst probe status into an overall badge.
| Probe | What it checks |
|---|---|
| db | SELECT 1 round-trip on the platform DB |
| dbt | dbt --version subprocess (5-second timeout) |
| disk | shutil.disk_usage(DATA_DIR) against 15% (warn) / 5% (error) free thresholds |
| scheduler | honeyframe.app_config heartbeat freshness (5 min warn, 30 min error) |
| llm | Boolean presence of OpenAI / Anthropic / local provider keys (never echoes the keys) |
| smtp | Boolean presence of SMTP password (no test-send) |
Status colors: emerald = ok, amber = warn, red = error. Each card shows the probe message, latency in ms, and a key/value meta panel (provider booleans, free-disk %, heartbeat age, etc.). Click Refresh to force an out-of-cycle fetch.
Crash isolation: a single probe raising never 500s the endpoint. The aggregator catches and surfaces the failure in that component's status, so the rest of the dashboard keeps rendering.
Distinct from /api/health (the 3-line liveness check used by the load balancer + license-gate allowlist) — the one at /api/system/health is admin-only, richer, and never echoes secret values.
Replay welcome tour
The user-avatar menu has a Show welcome tour again item that resets your onboarding state and reloads the app. The 5-step first-login wizard re-mounts on the next route, walking you through Welcome dashboard → Connectors → Members → AI Keys → Usage. Reset is self-only — there is no admin surface to reset another user's tour.