v0.0.44 — Self-serve workspace, public sharing, system health
Released: 2026-05-04
The biggest user-facing release since v0.0.39. The cumulative window covers v0.0.42 (tarball-completeness fix), v0.0.43 (eight self-serve features, broken in the field by an email_validator bundling miss in Nuitka), and v0.0.44 (the email-validator fix + System Health surface + connector credential vault + Cloud-tier license fix). v0.0.42 and v0.0.43 doc snapshots are skipped — v0.0.44 is the new canonical anchor.
Self-serve workspace surfaces
A new Workspace nav section sits above Administration with five tenant-admin pages:
- Members (
/members) — invite teammates by email with a role; recipients land on a public/accept-invitepage, set a password, and join. Existing-account invites add auser_orgsrow instead of duplicating the user (they sign in with their existing password). 7-day token TTL, sha256-hashed at rest, partial unique index dedupes open invites per email. - Usage (
/usage) — read-only KPI roll-up: LLM calls (chat/agent split), dbt runs, datasets, dashboards, members + pending invites, storage on disk + file count. Period switcher (Today / 7d / 30d / All). 5-minute server cache on the storage walk with a manual "Refresh storage" button after big uploads. - AI Keys (
/ai-keys) — BYO LLM keys: paste an OpenAI / Anthropic / Ollama key and that org's chat / SQL / agent traffic bills against the tenant's account. Falls through to the platform default when not set, so existing tenants are unaffected. Plaintext is never read back — server returns mask + last-4 only. AES-GCM ciphertext, JWT-derived encryption key (no new env required). - Custom Domains (
/custom-domains) — map your own domain (data.acme.com) to your Honeyframe Space. Thehost_orgmiddleware resolves the host to the sameorg_idit would for an<slug>.app.honeyframe.iohit, so auth / license / branding / RBAC work identically. Six-state machine:pending → verifying → active / failed / removed. DNS TXT verify, nginx vhost render + reload, certbot--nginxfor HTTP-01. - Health (
/health, admin-only) — six-probe operator dashboard: db / dbt / disk / scheduler / LLM / SMTP. Each probe returns{status, message, ms?, meta?}rolled up into a worst-of overall badge. 30-second poll, manual refresh, color-coded cards (emerald / amber / red). Crash-isolated — a single probe raising never 500s the endpoint. Distinct from the existing/api/health(3-line liveness for load balancers).
A 5-step first-login wizard also lands in this release. New users see a modal that walks them through Welcome dashboard → Connectors → Members → AI Keys → Usage. Server-driven visibility — completed / dismissed users never see it again. The user-avatar menu gains a "Show welcome tour again" item that resets and re-mounts the wizard.
Public dashboard sharing
Replaces the naive is_public BOOLEAN model with per-link share tokens carrying optional expiry, revocation, and view counts. The legacy is_public path stays for back-compat with already-shared dashboards.
- The dashboard Share dropdown now has a "Public Links" entry that opens a modal listing existing links (status badges + view counts + revoke), letting you mint new links with optional label +
expires_days, and showing the raw URL once in a one-time reveal panel with a copy button. The modal clears on close so a stale revealed URL can't leak. - Visitor-side:
/public/<dashboard_id>?token=…threads the token through both the metadata GET and the execute-all POST so anonymous viewers see data without flippingis_publicon the row. Tokens are sha256-hashed at rest; the bare token is never stored. - Cross-dashboard token isolation is pinned by integration tests (a link valid for dashboard A used against dashboard B must 404).
Connector credential vault
Every connector's password / api_key / auth_token had lived plaintext in honeyframe.data_connectors.config (JSONB) since v0.0.1. A DB read leak (RLS bypass, accidental dump, debug query) leaked every tenant's downstream-system secrets. v0.0.44 moves recognized secret fields into an AES-GCM encrypted blob in a sibling column (connection_secrets_enc).
- Coverage map: postgres / mysql / oracle / snowflake / bigquery / mongo / s3 / oss / gcs / twilio / openai_llm / anthropic_llm / n8n / etc. Unknown connector types are passthrough — the system never silently encrypts the wrong fields.
- API behavior: POST/PUT encrypt secrets before write; GET masks via the explicit field map AND the legacy substring sweep — never exposes plaintext, even mid-migration. PUT preserves
••••••••sentinels so unchanged secrets stay untouched. - High-traffic consumers (
dataset_resolver,query_executor,chat_service) merge decrypted secrets at runtime; legacy plaintext-config rows still work via passthrough fall-through, so the migration is non-breaking.
Operator action: run paas/scripts/migrations/2026-05-04_encrypt_connector_secrets.py once per tenant after deploy. --dry-run flag for preview; idempotent on re-run.
Cloud lifecycle
- Sample-data seed on new spaces. Provisioner now seeds a generic e-commerce starter pack (customers / products / orders) and a 7-card Welcome dashboard (3 KPIs, revenue trend, top categories, top customers, recent orders) on every new cloud-tier space. New tenants land on "wow this works" instead of an empty Datasets page. Self-contained, idempotent, opt-out via
CLOUD_STARTER_SEED=false. A failure to seed is non-fatal — a blank space is still a working space. - True cascade deprovisioning (
DELETE /api/v1/spaces/{id}?confirm_slug=<slug>) — replaces the v1 stub that just flippedstatus='deleted'. Six-phase cascade:honeyframe.*deletes in FK-safe order, DROP per-tenantt<pid>_*schemas,rm -rf {DATA_DIR}/orgs/<org_id>/, nginx vhost remove + reload, certbot revoke + delete. Each phase emits aprovisioning_eventso the SpaceDetail timeline shows progress. Failure marksstatus='failed_deletion'and keeps the row for inspection. - Cloud-tier license recognition. Cloud signups bill via
honeyframe.subscriptions, notorg_licenses— the gate now synthesizes a permissive license payload from an activesubscriptionsrow whenorg_licensesis empty. Subscription state still controls revocation:past_dueflips back to the gate, exactly the right escalation path.
Build & deploy reliability
The two intermediate releases existed to close concrete prod-deploy regressions. v0.0.44 is the first version where they all hold:
email_validatorbundled in Nuitka. v0.0.43 crash-looped hub-platform on first request:ImportError: email-validator is not installed. Pydantic lazy-imports it onEmailStrvalidation; Nuitka standalone analysis missed the import. Fix is two-pronged — added to the requirements files for vendor wheels AND--include-module=email_validatorin the Nuitka compile script.honeyframe updatepreserves nested.envfiles. The 2026-05-04 v0.0.41→v0.0.42 prod deploy crash-looped because the CLI's update flow wipedpaas/backend/.env(symlink) andsaas/backend/.env(real file: SaaS DB creds + JWT secret). The skip set only protected root-level files; the per-tierrmtreewiped nested ones, and the backup loop looked at the wrong path so the safety net was silently empty. Now snapshots every nested.env(real + symlink, mode-preserving) before eachrmtreeand restores after. Backup walks recursively.- Tarball completeness.
compile_nuitka()had been strippingpaas/backend/*.pyafter producingdist/run.bin. SaaS and hub-scheduler importsafe_sql/patch_passlib/services.*/middleware.*from PaaS viaPYTHONPATHat runtime — the strip broke both.paas/scripts/was migrations-only (hub-scheduler runsscheduler.pyfrom this dir).controlplane/was missing entirely. All three closed in v0.0.42, with a 7-test regression guard (two static-inspectcompile_nuitkasource so any re-introduction of the strip pattern fails CI).
Tooling
CircleCI docs job. On a v* tag push, after build succeeds, a new docs job runs git log v<prev>..v<new>, cuts a Docusaurus snapshot in honeyframe-portal, builds the portal, and pushes a release-docs/v<new> branch. NO auto-PR — humans click "Create PR" in GitHub UI so titles/bodies land in their voice and the review/triage workflow stays a human gate. NO auto-merge, NO auto-deploy. Wired in commit 578893e; v0.0.45 will be the first release the docs job auto-fires for.
Migrations
Five idempotent SQL migrations land in this release. All are ADD COLUMN IF NOT EXISTS / CREATE TABLE IF NOT EXISTS and auto-applied via init_schema.sql on fresh deploys. Existing deploys run them once via scripts/migrate.py:
2026-05-04_add_invites.sql2026-05-04_add_org_llm_credentials.sql2026-05-04_add_org_custom_domains.sql2026-05-04_add_dashboard_public_links.sql2026-05-04_add_onboarding_tracking.sql
Plus the Python backfill for connector credential encryption (2026-05-04_encrypt_connector_secrets.py).
No new env keys, no new ports.
What's not in this release
- Per-card auto-refresh in public dashboards — the v0.0.40 dropdown still applies to authenticated dashboards only. Public-link viewers get a single render, no live-refresh.
- Custom-domain wildcard certificates — current path is per-domain HTTP-01 via certbot. Wildcards (DNS-01) require operator DNS-API plumbing, deferred.
- Onboarding wizard customization — five fixed steps; per-tenant step config lands later if asked.