Releases
SparkLabX follows semantic versioning. Pre-1.0 means minor versions may introduce breaking changes; patches are always backwards-compatible.
0.3.1
Latest2026-06-19Backend hardening — same connectors & SSO from v0.3.0, on a sturdier foundation.
Backend hardening — same connectors & SSO from v0.3.0, on a sturdier foundation.
Backend
- Native
pgxdriver replaceslib/pq, with versioned, embedded schema migrations (golang-migrate) that adopt an existing database or provision a fresh one with no manual step. - Routes split by concern (auth / admin / notebooks / kernel / connectors) — a leaner entrypoint and a route map that’s easy to scan.
Fixes & polish
- Connector labels in the sidebar now line up regardless of each source’s icon shape (fixed-width icon box).
Security & CI
- Cleared the high-severity frontend advisories (
npm auditclean at high), CodeQL upgraded to v4 and run on the default branch, andgolangci-lintgates only newly-introduced issues.
0.3.0
Stable2026-06-17UI-managed data connectors + SSO — query Trino / Postgres / MySQL as your own identity.
UI-managed data connectors + SSO — query Trino / Postgres / MySQL as your own identity.
Data connectors
- Add a source from the UI — structured Host / Port / Database / SSL, no JDBC string to memorize, for Trino, PostgreSQL and MySQL. Browse its catalog → schema → table → columns, and query from any notebook with one helper in both languages:
query("<id>", "SELECT ..."). - Personal & per-user identity — each connector is owned by you and authenticates as your SSO identity. The app mints a short-lived RS256 JWT that the source validates via the app’s JWKS (app-as-issuer), so Trino’s own access control keys off the real user. Optional broker-mapped username/password (AES-GCM at rest) for sources without SSO.
SSO
- Google / Microsoft / generic OIDC (Keycloak, Okta, Auth0) alongside username/password, gated by the email allowlist.
Spark & kernel
- Per-notebook Spark UI — each notebook’s Spark UI binds its own port, so the in-app Spark UI proxy always shows the right kernel.
- DataFlint on by default for PySpark and Scala — a performance tab in the Spark UI that flags slow stages, skew, and oversized scans.
Security
- SSRF guard on connector requests (blocks cloud-metadata endpoints), hardened Spark-UI cookie, and repo-wide scanning (CodeQL / Dependabot / npm audit / golangci-lint).
0.2.0
Stable2026-06-12Pick your kernel's CPU & RAM per session — admin-curated presets plus capped custom sizing.
Pick your kernel’s CPU & RAM per session — admin-curated presets plus capped custom sizing.
Resource presets
- Resources picker in the Connect Kernel dialog — a vertical radio list of admin-defined sizes (e.g. Medium 1 vCPU · 2 GB, Large 2 · 4, XLarge 4 · 8) with the default badged, plus an optional Custom row taking plain numbers (cores / GB) under admin-set ceilings. Fixes #41.
- Kubernetes: the picked size is applied as request and limit — Guaranteed QoS, the user gets exactly what they picked. Docker: applied as the container’s CPU/memory limits.
- Resize on connect — picking a size different from the running kernel restarts it at the new size. The dialog shows the running kernel’s size with an explicit warning (the kernel is per-user, so other notebooks on it reconnect with cleared variables).
- Server-side validation — unknown preset ids, malformed quantities, sizes over the admin caps, and sub-floor values (<0.1 core, <128Mi) are rejected with clear 400s.
- Opt-in via
kernel.resources.presetsinvalues.yaml— with no presets defined the picker is hidden and upgrading changes nothing.
Library feedback
- Failed library installs are no longer silent (#33). A bad Maven coordinate now raises a toast naming the coordinate(s) that failed to resolve — on connect and on Manage Libraries → Apply & Restart — instead of a later cryptic
ClassNotFoundException. Detected from the kernel log (PySpark) and the init-cell error (Scala/Almond), so neither kernel slips through. - Honest failure state: a resolution failure shows a red Spark not ready badge (not a misleading green Connected), blocks Run / Run All, and offers a Fix libraries action. The kernel stays alive for a fast in-pod fix — no teardown, and no more Booting Spark… / starting badge stuck until a page reload.
Fixes
- Resources picker shows the running kernel’s size immediately after a connect/resize — previously it stayed hidden on k8s until metrics-server scraped (~15s).
- Resource-usage widget (docker) read the CPU quota from static config — now reads the live per-container limit, so per-session sizes report correctly.
- “Disconnecting…” badge could spin forever when the backend was unreachable — the disconnect request now has a timeout and the local state always lands.
- Kernel pod termination grace cut 30s → 5s — kernels hold no durable state, so resize/restart now completes in ~12s instead of ~40s.
- Spawn no longer re-reads pod sizes from the DB row mid-spawn — a concurrent destroy could race the read and silently revert the pod to default sizes.
0.1.5
Stable2026-06-11Persistent kernel recorder — tab close no longer loses cell output.
Persistent kernel recorder — tab close no longer loses cell output.
Recorder
- Per-kernel singleton WebSocket to JKG, independent of any client. Captures every iopub message, attributes it to a cell via
metadata.sparklabx_cell_idregistered onexecute_request, and persists output tonotebook_cells.last_outputwith a 500 ms debounce. Closing the tab no longer drops in-flight output — the next page load shows it. - State restore on reload via
GET /kernel/active-executionsfired before the WebSocket opens. Running cells come back with their original startedAt, queued cells stay queued. No envelope ordering races because the restore is HTTP, not WS. - Completion detected via iopub
status:idle(broadcast) instead ofexecute_reply(shell channel, session-scoped). A reloaded tab can now clean up cell state when the original execution finishes or gets interrupted.
Run All
- Queues every cell upfront instead of chaining via
onComplete. The kernel’s native FIFO +stop_on_errortakes over, so closing the tab mid-batch no longer halts the rest of the cells.iopub status:busypromotes a queued cell into running when the kernel picks it up;KernelStartedAton the backend record measures runtime from real start, excluding queue wait.
UX polish
- Spark re-init skipped on tab reload when the kernel pod is unchanged (kernel_id persisted in localStorage). Eliminates the spurious “Booting Spark…” badge and fake “Stop All” button after Cmd+R during a running cell.
- “Disconnecting…” badge during the kernel disconnect / shutdown round-trip, with a 500 ms floor so the state stays visible on fast backends.
flushSync+ status guard so the badge transition isn’t clobbered byws.onclose. - Toolbar stability: fixed-width language badge, connection-status badge, Connect/Disconnect button, and notebook name input — switching notebooks or connection states no longer reflows the toolbar.
- Sidebar files panel: stable row + breadcrumb heights, scope prefix stripped from the path (My Space / Public is already shown in the tabs), back arrow always renders (disabled at root).
- Admin Storage page: renamed “Buckets” → “Spaces” for consistency with the sidebar, friendly bucket names (My Space / Public), correct s3a:// path on Copy (resolves via
getUserDataPath()instead of emitting the logical name), table-fixed rows so long filenames don’t bump row heights. - Drop interrupt-on-leave — the warning prompt + auto-interrupt are gone, the recorder makes them unnecessary.
0.1.4
Stable2026-06-10Notebook UX overhaul + idle-reaper safety net.
Notebook UX overhaul + idle-reaper safety net.
Notebook UX
- Interrupt running cell without restarting the kernel. Per-cell Run morphs into Stop while executing; toolbar ‘Run All’ morphs into ‘Stop All’. SIGINT cancels the active Spark job — SparkSession, imports, variables, and cached DataFrames all survive. Fixes #45.
- Live elapsed-time timer ticks every 100 ms while a cell runs (
N.NNsformat, matches the final badge). - Final execution time shows immediately on
execute_reply(previously relied on a DB write that never happened automatically). - Refuses Run on a second cell while another is executing — toast ‘Kernel is busy’ instead of two cells sharing one SIGINT.
Reliability
- Idle reaper no longer kills pods mid-execution when the browser tab is closed during a long Spark job. Checks Jupyter
execution_statebefore deleting. Applies to bothk8s_per_useranddocker_per_usermodes. Fixes #44.
0.1.3
Stable2026-06-08Backend reliability + security release.
Backend reliability + security release.
Reliability
- Backend DB retry — wrap startup
db.Ping()in a 30-attempt loop (~2 min budget). Freshhelm installno longer crashloops while postgres warms up. Same loop also absorbs network blips and postgres failovers during runtime. Fixes #37.
Security
- 17 Go stdlib CVEs cleared via toolchain bump (
go 1.26.0 → 1.26.4) andgolang.org/x/net v0.54.0 → v0.55.0. Includescrypto/x509(×6),crypto/tlsKeyUpdate DoS,net/http2infinite loop,html/templateXSS,net/mailquadratic parsing.govulncheck ./...reports clean.
CI
- Bump
actions/setup-go@v5 → @v6andactions/checkout@v5 → @v6for Node 24 compatibility.
0.1.2
Stable2026-06-07Frontend lint + UX cleanup.
Frontend lint + UX cleanup.
UX
- Login UI: drop Student/Admin button label dichotomy; placeholder uses
admin@sparklabx.com - README: embed login screenshot after the quickstart block
Code quality
- ESLint: 119 warnings cleared to 0 errors / 0 warnings
- Removed CRA leftovers (nginx-kubernetes.conf, docker-entrypoint.sh, reportWebVitals) — net -440 lines
- Squash-merge workflow for dev → test → main promotion chain
0.1.1
Stable2026-06-07CORS, kernel pre-pull, CI pipeline.
CORS, kernel pre-pull, CI pipeline.
- CORS wildcard handling + WebSocket bypass for dev/staging custom domains
- Kernel image pre-pull: docker-compose
kernel-cache+ Helmkernel-prepullerDaemonSet. Fixes #26. - Frontend Service type configurable — ClusterIP / NodePort / LoadBalancer
- CI pipeline — build/lint/test on PR + push to dev/test
0.1.0
Stable2026-06-04First public release.
First public release.
- PySpark + Scala (Almond) kernels bundled and configured
- Per-user kernel pod isolation (Kubernetes) or per-user container (Docker)
- OAuth login (Google + Microsoft) with email allow-list
- MinIO IAM per-user prefix enforcement
- Single Helm install or
docker compose up