Release Notes -- 2026-05-02¶
Databricks Forge v0.40.0 → v1.0.0
BREAKING -- DATA WIPE REQUIRED. This release introduces true per-user isolation across the entire system. The schema migration adds a NOT NULL
owner_emailcolumn to every root table, so all existing rows must be wiped before deploy. There is no in-place upgrade path. Run the factory reset (Settings -> Factory Reset, or thedeleteAllData()startup hook) before flippingFORGE_USER_ISOLATION=true. Customers should export any wanted artefacts (Excel/PDF/PPTX exports, deployed Genie spaces are kept in Databricks and survive the wipe) prior to upgrading.
v1.0.0 -- User Isolation & Team-Shared Refactor¶
New Features¶
Per-user isolation across every surface¶
Forge moves from a single-tenant-shared Lakebase model to true per-user
isolation. Every root entity (ForgeRun, ForgeEnvironmentScan,
ForgeGenieSpace, ForgeMetadataGenieSpace, ForgeSpaceBenchmarkRun,
ForgeSpaceHealthScore, ForgeDemoSession, ForgeCommentJob,
ForgeConnection, ForgeFabricScan, ForgeFabricMigration,
ForgeStrategyDocument, ForgeDocument, ForgeQualityMetric) carries an
ownerEmail column. List, detail, update, delete, and export paths are
scoped through a single visibility rule:
WHERE owner_email = $user
OR id IN (SELECT resource_id FROM forge_resource_acl
WHERE resource_type = $type AND viewer_email = $user)
Outcome maps, benchmarks, prompt templates, and metadata cache stay global by design.
Team-shared sharing model¶
A new ForgeResourceAcl table holds opt-in per-resource permissions
(view / edit). Owners share a run, scan, Genie space, demo session,
comment job, strategy document, connection, or document with another
teammate via a reusable <ShareDialog> component (shadcn). The dialog is
backed by POST/DELETE/GET /api/share.
| Permission | Read | Re-run | Edit | Delete | Re-share |
|---|---|---|---|---|---|
view |
yes | no | no | no | no |
edit |
yes | yes | yes | no | no |
owner |
yes | yes | yes | yes | yes |
Delete and re-share are owner-only by design.
Vector search isolation¶
searchByVector() and retrieveContext() now require userEmail and an
explicit kind-to-scope mapping (lib/embeddings/kind-scope.ts). Readers
resolve accessible parent ids via listAccessibleIds(...) and pass them
through; writers stay unchanged. RAG, semantic search, run suggestions,
and Ask Forge no longer leak embeddings across user boundaries.
Single mandatory auth seam¶
A new lib/auth/route-user.ts exports requireUser() and ForgeUser.
Next root middleware (middleware.ts) enforces 401 on every /api/** route
that lacks identity. Server Components call requireUser() directly at the
top of each render. Local dev supports a request-scoped ?as_user= query
param (gated to NODE_ENV !== "production") so a single tab can swap
identities without restarting the server.
Per-user fairness, quotas, and queueing¶
Per-user active-resource caps (configurable via env, default 1 for
pipelines / scans / demo engines, 2 for Genie deploys) are enforced at
every fire-and-forget kickoff. ForgeRun.status adds a new queued
state. When a user exceeds their cap, the run is enqueued instead of
rejected; a process-local scheduler (lib/pipeline/scheduler.ts) ticks
every 5s plus on-demand and atomically promotes the oldest queued run to
pending when free capacity opens up. Cancel-from-queued is supported.
The pool rate limiter (lib/dbx/rate-limiter.ts) now keeps a per-user
inflight tally per endpoint; the foundation for max-min fair-share is in
place. ForgeUsage records per-user daily counters (runs, LLM calls,
embed tokens) for future chargeback.
Queue & load visibility (Phase 5c)¶
- A new
<SystemLoadBanner />(visible only when the system is busy) readsGET /api/system-loadevery ~8s and surfaces total active runs, per-endpoint LLM in-flight/queued counts, and 429 throttle states. Anonymous -- never exposes other users' identities. - The runs list and run detail page show a
Queuedbadge with hover position and a cancel-from-queue button. - Activity log captures
pipeline_queued,pipeline_promoted, andendpoint_throttledevents.
Improvements¶
- Owner badges + "My / Shared" filters -- every list view shows a
small owner chip and a
Sharedicon when the current viewer is not the owner. Run, scan, Genie space, demo, and comment-job lists ship with aMy / Shared with me / All visibleselector. - Background job context -- every fire-and-forget engine entrypoint
now requires a
user: ForgeUserfield. The OBO token is captured at the request boundary and threaded through the entire async closure (mandatory for the Genie Conversation API; rule generalised to all fire-and-forget routes -- see.cursor/rules/genie-obo-auth.mdc). ForgeAssistantLog.userIdis now required -- the feedback endpoint validates ownership before recording thumbs up/down.- Activity log scoped to caller --
getRecentActivity()filters byuserEmail; the per-user feed shows their own queue events and shares. - Stats are per-user -- the dashboard and
/api/statscount only the caller's resources. FORGE_USER_ISOLATIONflag -- a new env-var feature flag controls the visibility of the sharing dialog and per-user quota enforcement. Data-layer filtering byownerEmailis unconditional and not gated by the flag.- Factory reset coverage --
deleteAllData()now wipesForgeFabricMigration,ForgeConnection,ForgeQualityMetric,ForgeSpaceBenchmarkRun,ForgeSpaceHealthScore,ForgeHealthCheckConfig,ForgeResourceAcl, andForgeUsagein addition to the existing tables.
Breaking Changes¶
- Schema migration is forward-only.
owner_emailisNOT NULLon every root table. The migration runs on first boot post-deploy viaensureMigrated()and assumes the database has been wiped.FORGE_USER_ISOLATION=falsedoes not restore pre-isolation behaviour because the data layer always filters byownerEmail. Real rollback requires a Lakebase point-in-time restore. - Local dev requires
FORGE_LOCAL_USER_EMAIL..deploy_local.shsets it from$USER_EMAILautomatically; manual local runs must export the variable themselves. - Direct-ID API access checks ownership.
getRunById, update, delete, export, and per-resource action routes return 403 for non-owners (resolved vialib/auth/route-guards.ts). - Wipe does not delete external Databricks resources. Demo Mode UC
schemas and deployed Genie spaces are not Lakebase rows. Demo sessions
are iterated through
cleanupDemoSession()before wipe; Genie spaces remain in Databricks and re-attach on next sync.
New Deploy Flags¶
./deploy.sh --disable-user-isolation # Run with isolation flag off (data layer still scopes)
./deploy.sh --max-pipeline-runs-per-user 2 # Default 1
./deploy.sh --max-scans-per-user 2 # Default 1
./deploy.sh --max-genie-deploys-per-user 4 # Default 2
./deploy.sh --max-demo-engines-per-user 2 # Default 1
New Tables / Columns¶
forge_resource_acl-- per-resource sharing permissionsforge_usage-- per-user daily countersowner_emailon every root tablequeuedvalue added to theForgeRun.statusvalue set
New Files¶
lib/auth/route-user.ts,lib/auth/route-guards.tslib/lakebase/acl.ts,lib/lakebase/usage.tslib/embeddings/kind-scope.tslib/pipeline/scheduler.tslib/dbx/system-load.tslib/config/isolation-flag.tslib/quotas.tsapp/api/share/route.tsapp/api/system-load/route.tsapp/api/me/route.tscomponents/share/share-dialog.tsxcomponents/system-load-banner.tsxlib/hooks/use-current-user.tsmiddleware.ts
Test Coverage¶
- 919 tests passing across unit + integration suites.
- New:
__tests__/auth/require-user.test.ts,__tests__/lakebase/acl.test.ts,__tests__/embeddings/kind-scope.test.ts,__tests__/rate-limiter/fair-share.test.ts,__tests__/pipeline/scheduler.test.ts.
All Commits¶
| Hash | Summary |
|---|---|
| (this release) | feat: user isolation and team-shared refactor (Phases 1-8) |