v0.0.48 — Governance UX + project-slug URLs + updater verify
Released: 2026-05-05. Eight commits, dominated by a multi-part governance surface built on top of the v0.0.47 dashboards admin override, plus an additive project-slug URL routing scheme (Dataiku-style /projects/<slug>/<page>), plus the install-time follow-ups that close out the cmd_update hardening from v0.0.47.
This is the first release where every layer of v0.0.47's cmd_update hardening fired without manual intervention on both test and prod ECS.
Governance surface — admin overrides, end-to-end
v0.0.47 introduced the dashboard admin role-shortcut. v0.0.48 builds the operator workflow around it so a multi-org admin who pastes a cross-org URL gets a friendly recovery, every override leaves a usable trail, and compliance teams can subscribe to overrides as a dedicated channel.
Cross-resource recovery: NotFoundBanner
A new NotFoundBanner component replaces the silent navigate('/<list>') on 404 / 403 across Dashboards, Datasets, Agent Builder, and Notebook detail pages. Renders org-switcher buttons (org list fetched on 404 only, not on 403) so an admin who pasted the wrong-org URL can flip orgs and reload in one click. New Playwright spec 59-cross-org-banner.spec.ts pins the round-trip end-to-end.
Audit page: filters, timeline, KPI tiles, deep-links
The audit viewer at /audit gains a substantial workflow upgrade:
- URL-persisted filters — every filter (user, category, action prefix, date range, search) lives in
useSearchParams. Bookmarkable, browser back/forward works. - 30-day per-user activity sparkline — inline SVG (no chart bundle) above the table when
filterUserIdis set. NewGET /api/audit/timelineendpoint withgenerate_series+ LEFT JOIN so quiet days survive. - 90-day stacked breakdown —
GET /api/audit/timeline?group_by=actionreturns per-category daily buckets driving an inline<StackedActivityChart>. Categories:admin_override,auth,dashboard,dataset,notebook,agent,entity,other.admin_overrideis its own bucket, not folded intodashboard, so the chart answers "is this user spiking on overrides specifically, or just busy?". Click-to-expand to keep the default audit page cheap. - Clickable timeline legend — legend pills are now buttons. Click highlights the active pill and pins
filterCategory. Click the active pill to clear. Backed by?category=on/api/auditwith a curated WHERE fragment per category (authis an IN-list;dashboardisLIKE 'dashboard%' AND NOT LIKE '%.admin_override_%'). Unknown values are silently ignored — a stale bookmark shouldn't 422 the page. - Admin overrides KPI tile —
GET /api/audit/summarynow carriesadmin_overrides_7d. Drives a 5th rose tile so an org owner can answer "are we trending up on overrides?" at a glance. Clicking the tile pinsfilterCategory='admin_override'. Zero-state polish: at 0, the tile renders white + neutral grey "Clean week" sub-label rather than alarming rose; at >0, rose styling fires (the eye-catching is desired here). - Per-row deep-links — username and resource cells route through
resourceHref(). Notebook rows link to/notebooks?id=...; recipe rows parse the composite<project_id>:<model_name>resource_id and route to/recipes/prepare?model=...&project_id=.... Explicit ↗ icon next to deep-linkable cells withtarget=_blank+rel=noopener noreferrerfor the "open three at once, scan, close" triage pattern. - CSV export — carries an
action_labelcolumn with friendly admin-override phrasing ("Admin override · read"); rawactionstays alongside for tooling. Timeline breakdown CSV (/api/audit/timeline/export) returns 3 columns (date,category,count); quiet days emit(date,'',0)so the X-axis survives in Excel.
Webhook channel: audit.admin_override
A new event type in _SUPPORTED_EVENTS. Emitted from _audit_admin_override (dashboards + notebooks + recipes) alongside the existing audit.event firehose. Compliance teams can now subscribe to only overrides without filtering audit traffic.
The webhook deliveries panel on /webhooks gains:
- Event-type filter —
GET /api/org/webhooks/{id}/deliveries?event_type=audit.admin_override, catalog-validated. Pills built from the catalog; theaudit.admin_overridepill is rose-tinted + 🛡️ prefixed to mirror the audit page's governance signal. - URL-persisted state —
?endpoint=<id>&event_type=<key>. A reviewer can paste/webhooks?endpoint=42&event_type=audit.admin_overridein#governanceand the recipient lands on the same view.
A new paas/docs/webhook-events.md (in-repo) documents the wire envelope, HMAC verification pattern, and per-event payload shape for every supported event type. audit.admin_override is called out with its action-code matrix.
Notebook + recipe admin shortcuts (mirror dashboards)
GET /api/notebooks/{id} and GET /api/flow/recipe/{model_name}?project_id= now accept the same admin role-shortcut as dashboards:
- Org admins resolve cross-project reads with audit + the dedicated
audit.admin_overridewebhook channel. - Cross-org admins → 404 (mask).
- Non-admins / same-project reads keep original behavior.
- Superadmin bypasses audit (incident-response support).
- Response carries
is_admin_overrideso the FE renders the rose 🛡️ "Admin access · audited" badge in the page toolbar (NotebookPage, PrepareRecipePage, RecipeEditorPage).
Project-slug URLs (Phase 1, additive)
Dataiku-style /projects/<slug>/<page> routes mount alongside the existing top-level paths. Both /flow and /projects/<slug>/flow render — legacy URLs are untouched, new URLs are shareable deep-links scoped to a specific project.
GET /api/projects/by-key/{slug}— frontend hits this on/projects/...URLs to convert slug → numericproject_idfor theX-Project-Idheader. Org-scoped, runscheck_project_access.- Slug regex + reserved-word list (
new,admin,api,by-key,public,static,assets) so a slug can never collide with a sub-route mounted under/projects/. Malformed slugs 400 instead of looking like a duplicate-on-retry. useProjectKeySynchook reads the URL slug, GETs by-key, and writesselected_project_id. Reload only fires when the resolved id differs from stored — no loop on deep-linking the active project.- ~35 nested page routes wrapped: flow, dashboards, datasets, recipes/*, jobs, scenarios, schedules, agent-builder, etc. Org-level pages (members, audit, storage, …) intentionally stay top-level.
- Selecting a project on
/projectsnow navigates to/projects/<slug>/flowinstead of/dashboard.
Phase 2 (a future release) will collapse the recipe-type-per-route paths and add /scenarios/:name/steps, /jobs/:runId, etc.
Install: schema_sync auto-loads .env + honeyframe verify
Two install-time follow-ups that close gaps surfaced during the v0.0.47 deploy.
schema_sync was a silent no-op for 2+ releases
systemd-spawned honeyframe doesn't export DB_USER / DB_PASSWORD / DB_NAME, so on every honeyframe update the schema_sync auto-heal step hit ERROR DB_USER / DB_PASSWORD / DB_NAME env vars must be set and never applied any drift. Drift was detected but never applied.
schema_sync.py now loads /opt/honeyframe/paas/backend/.env at the top of main(). Auto-detected relative to __file__; can be overridden with --env-file <path>. cmd_update passes --env-file explicitly. Uses os.environ.setdefault() so an operator who pre-sets DB_HOST=foo on the command line still wins over the file.
Validated on the v0.0.47 → v0.0.48 deploy: 7 columns of accumulated drift actually applied (4 prod + 3 test) across the chain. The auto-heal feature is now real.
honeyframe verify command
A stricter post-deploy check than honeyframe status:
honeyframe verify
- Exits non-zero on any failure — suitable for CI / cron / smoke scripts.
- Cross-checks live
/api/versionagainst on-disk VERSION — catches stale-process deploys where the binary swapped but the process didn't restart. - Runs
schema_sync --dry-runto confirm the parser still works against the shippedinit_schema.sql. - Confirms nginx + every detected
hub-*service is healthy. Services that don't expose HTTP (e.g.hub-control-plane,hub-scheduler) are gated gracefully — they get an OK without a port check.
Wire it into your deploy script as the final gate. Combined with v0.0.47's service autodetect + full-tree backup + self-update re-exec, the upgrade pipeline now has end-to-end verification in one command.
What's not in this release
- Phase 2 of project-slug URLs — recipe-type-per-route consolidation,
/scenarios/:name/steps,/jobs/:runId, etc. land in a follow-up. - Audit category drill-down for the
otherbucket — read-only by design (its SQL would be a NOT-of-everything-else compound with little operator value). - Webhook channel on more resource types —
audit.admin_overridecovers dashboards / notebooks / recipes today. Datasets follow when the cross-project read path lands. - HelpTip on more pages — only the v0.0.47 SSO / Webhooks / SMTP coverage; Backups / Custom Domains / AI Keys remain on the backlog.