Lewati ke konten utama
Versi: v0.0.68

v0.0.47 — Updater hardening + admin & operator polish

Released: 2026-05-04. Six commits: one structural fix to the updater (the most consequential change), plus five user-visible features that fall out of operator and admin feedback on the v0.0.43+ workspace surface.

cmd_update hardening

Three changes that close the rough edges flagged after v0.0.45 and v0.0.46 deploys. Net effect: from this release onward, every fix to the updater applies to itself on the next deploy — no more "fix-takes-effect-NEXT-update" lag.

Service autodetect

Previous releases restarted only the three tier services from the built-in paas/saas/iaas map. Recent prod deploys also needed a manual systemctl restart hub-control-plane hub-scheduler afterwards. cmd_update now discovers every hub-*.service unit on the host and restarts them all. Falls back to the built-in map on non-systemd hosts (Mac dev, slim containers).

Full-tree backup

cmd_backup now writes a backups/<name>/full-install.tgz alongside the existing per-file snapshots. When v0.0.45 wiped iaas/backend/ on the prod ECS deploy, the only thing that saved the host was a hand-made tarball that happened to still be on disk. From now on every update writes a complete recovery artifact. Excludes node_modules, vendor/, __pycache__, .git, and backups/ itself so the archive stays sane.

Self-update re-exec

cmd_update now splits into two phases:

  1. Phase 1 (running on the OLD CLI): backup, extract the new tarball.
  2. Phase 2 (running on the NEW CLI, via os.execv): apply files, schema_sync, migrate, restart.

Phase 1 hands off with hidden flags --continued-from <path> --old-version <X> so phase 2 doesn't re-do extract or backup. This finally closes the pattern that delayed v0.0.43's .env preservation by one release and v0.0.46's iaas-wipe protection by one release. From v0.0.47 onward, every cmd_update improvement applies to the very next update.

Dashboard admin override (Dataiku-parity)

Users with role='admin' can now read and edit every dashboard in any org they belong to — not just dashboards they own or were explicitly shared on. Cross-tenant access is still gated by org-intersection: the override only applies within the orgs the admin is already a member of.

  • _get_dashboard_with_access and _require_editor short-circuit the share-row lookup for admins.
  • access_level reporting honors the admin override, so the UI surfaces "edit" affordances correctly.
  • New tab=all on the dashboard listing surfaces every dashboard in the admin's orgs in one view, alongside the existing Owned / Shared tabs.
  • Frontend replaces the silent redirect-on-403 with a friendly error banner + Try again button — non-admins who lose access get a recoverable state instead of a confusing bounce.

Members: bulk revoke + bulk resend

The Members page already supported per-row Revoke. Operators handing off a tenant — or cleaning up after a project ended — were stuck clicking 30 times in a row. v0.0.47 adds checkbox multi-select with two bulk actions:

  • Bulk revoke — single SQL UPDATE, idempotent, reports {requested, revoked, revoked_ids} so the UI renders "Revoked 3 of 5 (2 already accepted)".
  • Bulk resend — walks the selected rows, categorizes each into sent / skipped (accepted, revoked, expired, send_failed), and re-fires the invite email through the existing send path. Per-row failures are caught — the rest of the batch keeps going.

Per-row checkboxes render only on pending rows (accepted/revoked/expired rows are never re-actionable). A header select-all toggles every pending row. The bulk action bar appears on first selection. Both endpoints are admin-only with a defensive max_length=200 cap so a runaway selection can't UPDATE every row in one call. Audit-log writes summarize batch outcomes, so Audit Log surfaces bulk operations clearly.

The /api/branding overlay already covered logo, primary color, and app name. The login page's hero tagline, footer fine-print, and (most visibly) the browser-tab favicon were still platform defaults — a Cloud-tier customer with a branded login URL saw "Honeyframe" in the tab bar.

v0.0.47 extends the overlay:

FieldWhere it shows
taglineLogin-page hero copy
footer_textLogin-page footer fine-print
favicon_urlBrowser tab + <meta name="theme-color"> for mobile chrome tinting

A new useDocumentBranding hook applies the tab title + favicon + theme-color before first paint so the right brand is visible immediately, not after /branding resolves. Empty / NULL overrides fall through to global defaults (partial override safety). Unknown slugs return global defaults, never 404 — the login page must never break on a typo'd hostname.

Schema: honeyframe.organizations gains three nullable columns (tagline, footer_text, favicon_url) via an idempotent ALTER ADD COLUMN IF NOT EXISTS in init_schema.sql, with a standalone migration at paas/scripts/migrations/2026-05-04_add_org_login_branding.sql. Existing rows are unaffected.

Recently-visited list in CMD+K

Pages had no easy "jump back" surface. The ⌘K palette empty state showed the first 12 static pages — useful the first time, less so when you just spent 10 minutes editing a dashboard and want to get back to it. Every user now gets a 6-row recents header that updates as they navigate.

  • Backed by honeyframe.recently_visited — PK (user_id, kind, target_id), indexed on (user_id, last_visited_at DESC). Visit-count + last-visited-at upsert on every visit.
  • Allowed kinds: dashboard, dataset, project, recipe, agent, notebook (CHECK-constrained).
  • User-scoped, not org-scoped — operators on multiple orgs expect recents to follow them across orgs. The (kind, target_id) pair is unique enough.
  • Best-effort writes — a DB write failure returns {ok:true} so the page that's loading never blocks on a recents write.
  • The palette empty-query view shows recents at the top, then static pages, deduped by path. Cap at 12 visible.

DashboardsPage is the first writer; other surfaces follow incrementally. The helper is lazy-imported so the recents wiring doesn't bloat the dashboards-page bundle on first load.

Inline help tooltips on jargon-heavy admin fields

OIDC, SAML, Webhooks, and SMTP pages had a forest of opaque labels (IdP entity ID, SP entity ID, JWKS issuer, signing certificate, HMAC secret, etc.). Operators wired things wrong because the UI gave no clue what each value should look like. v0.0.47 ships a shared <HelpTip> component:

  • "?" icon next to high-confusion field labels. Click toggles, hover opens, hover-out closes (hover-pinning preserved when click-opened). Escape and click-outside both dismiss.
  • Real <button type="button"> with aria-label, aria-expanded, and aria-describedby tying to the popover; popover is role="tooltip". Theme-aware via the v0.0.46 var(--hf-*) token system — adapts to dark mode without code changes.

Pages instrumented:

  • OIDC providers — Slug, Issuer URL, Client ID, Allowed email domains.
  • SAML providers — Slug, IdP entity ID, IdP SSO URL, IdP signing certificate (multi-line PEM advice), SP entity ID, Allowed email domains.
  • Webhooks — URL, Secret (HMAC explanation + Stripe/GitHub parity note).
  • SMTP — Host (vendor examples), Port (587 vs 465 vs 25 guidance), Username (apikey-vs-email vendor quirks), Password (app-password caveat for Gmail / Office 365), From email (SPF/DKIM/DMARC implication).

What's not in this release

  • Recents writers beyond DashboardsPage — datasets / recipes / agents / notebooks / projects are wired in the schema and API but the UI hooks land incrementally.
  • g r chord for recents — the keyboard quick-nav layer from v0.0.46 doesn't gain a recents jump; use ⌘K to surface them.
  • HelpTip on the v0.0.43+ workspace surface — only the SSO / Webhooks / SMTP pages are instrumented in v0.0.47. Backups, Custom Domains, AI Keys follow as the copy is finalized.