Feat v0.5.0 realtime primitive + dialog audit + permissions UI
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 18s
CI/CD / test-frontend (pull_request) Successful in 5s
CI/CD / test-go-pg (pull_request) Successful in 2m42s
CI/CD / test-sqlite (pull_request) Successful in 2m59s
CI/CD / build-and-deploy (pull_request) Successful in 1m24s

Add realtime pub/sub: Starlark realtime.publish() module gated by
new realtime.publish permission, WS room protocol (room.subscribe/
room.unsubscribe intercepted in readPump with 100-room cap), and
SDK sw.realtime.subscribe() with auto room join/leave and reconnect
recovery.

Migrate 5 bare confirm() calls to sw.confirm() with destructive
styling in tasks, schedules, notes (×2), and editor packages.

Add admin permissions UI: per-permission grant/revoke drawer,
Grant All bulk action, pending_review/suspended status badges,
disabled enable toggle when pending. Closes v0.4.7 permissions
UI gap.

8 new Go tests, all passing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-30 10:40:24 +00:00
parent eb9a2d7d27
commit 0af1c51ae9
21 changed files with 680 additions and 22 deletions

View File

@@ -33,6 +33,7 @@ import (
starlarkjson "go.starlark.net/lib/json"
"switchboard-core/events"
"switchboard-core/models"
"switchboard-core/store"
)
@@ -62,6 +63,7 @@ type Runner struct {
db *sql.DB // nil = db module unavailable
dbPostgres bool // true = use $N placeholders; false = use ?
allowPrivateIPs bool // v0.38.5: disable SSRF private IP check
bus *events.Bus // v0.5.0: event bus for realtime module
}
// NewRunner creates a runner with the given sandbox and dependencies.
@@ -97,6 +99,11 @@ func (r *Runner) SetPackagesDir(dir string) {
r.packagesDir = dir
}
// SetBus attaches the event bus for the realtime module (v0.5.0).
func (r *Runner) SetBus(bus *events.Bus) {
r.bus = bus
}
// SetAllowPrivateIPs disables the SSRF check that blocks connections to
// private/loopback IPs. For self-hosted environments where extensions
// reach internal services. Controlled by EXT_ALLOW_PRIVATE_IPS env var.
@@ -327,6 +334,11 @@ func (r *Runner) buildModulesWithLibCtx(ctx context.Context, packageID string, m
if r.connResolver != nil && rc != nil && rc.UserID != "" {
modules["connections"] = BuildConnectionsModule(ctx, r.connResolver, rc.UserID)
}
case models.ExtPermRealtimePublish:
if r.bus != nil {
modules["realtime"] = BuildRealtimeModule(ctx, r.bus, packageID)
}
}
}