Lewati ke konten utama
Versi: v0.0.66

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-invite page, set a password, and join. Existing-account invites add a user_orgs row 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. The host_org middleware resolves the host to the same org_id it would for an <slug>.app.honeyframe.io hit, so auth / license / branding / RBAC work identically. Six-state machine: pending → verifying → active / failed / removed. DNS TXT verify, nginx vhost render + reload, certbot --nginx for 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 flipping is_public on 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 flipped status='deleted'. Six-phase cascade: honeyframe.* deletes in FK-safe order, DROP per-tenant t<pid>_* schemas, rm -rf {DATA_DIR}/orgs/<org_id>/, nginx vhost remove + reload, certbot revoke + delete. Each phase emits a provisioning_event so the SpaceDetail timeline shows progress. Failure marks status='failed_deletion' and keeps the row for inspection.
  • Cloud-tier license recognition. Cloud signups bill via honeyframe.subscriptions, not org_licenses — the gate now synthesizes a permissive license payload from an active subscriptions row when org_licenses is empty. Subscription state still controls revocation: past_due flips 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_validator bundled in Nuitka. v0.0.43 crash-looped hub-platform on first request: ImportError: email-validator is not installed. Pydantic lazy-imports it on EmailStr validation; Nuitka standalone analysis missed the import. Fix is two-pronged — added to the requirements files for vendor wheels AND --include-module=email_validator in the Nuitka compile script.
  • honeyframe update preserves nested .env files. The 2026-05-04 v0.0.41→v0.0.42 prod deploy crash-looped because the CLI's update flow wiped paas/backend/.env (symlink) and saas/backend/.env (real file: SaaS DB creds + JWT secret). The skip set only protected root-level files; the per-tier rmtree wiped 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 each rmtree and restores after. Backup walks recursively.
  • Tarball completeness. compile_nuitka() had been stripping paas/backend/*.py after producing dist/run.bin. SaaS and hub-scheduler import safe_sql / patch_passlib / services.* / middleware.* from PaaS via PYTHONPATH at runtime — the strip broke both. paas/scripts/ was migrations-only (hub-scheduler runs scheduler.py from this dir). controlplane/ was missing entirely. All three closed in v0.0.42, with a 7-test regression guard (two static-inspect compile_nuitka source 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.sql
  • 2026-05-04_add_org_llm_credentials.sql
  • 2026-05-04_add_org_custom_domains.sql
  • 2026-05-04_add_dashboard_public_links.sql
  • 2026-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.