Feat v0.6.3 dead code sweep (#38)
All checks were successful
All checks were successful
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #38.
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
package handlers
|
||||
|
||||
// v0.38.1: Extension connection handlers — admin/global scope.
|
||||
// Methods on AdminHandler, mirrors admin provider config pattern.
|
||||
|
||||
import (
|
||||
|
||||
@@ -345,7 +345,6 @@ func hashToken(token string) string {
|
||||
// - AdminHandler.destroyVault (admin-initiated reset)
|
||||
//
|
||||
// Does NOT evict from UEK cache or write audit logs — callers handle that.
|
||||
// v0.29.0: accepts stores instead of using database.DB directly.
|
||||
func DestroyVaultDB(ctx context.Context, stores store.Stores, userID string) (deleted int64) {
|
||||
if err := stores.Users.ClearVaultKeys(ctx, userID); err != nil {
|
||||
log.Printf("⚠ DestroyVaultDB: failed to clear vault columns for user %s: %v", userID, err)
|
||||
@@ -366,8 +365,6 @@ func DestroyVaultDB(ctx context.Context, stores store.Stores, userID string) (de
|
||||
// sessions survive server restarts.
|
||||
//
|
||||
// Used by BootstrapAdmin and SeedUsers where the password is known at startup.
|
||||
// v0.29.0: accepts stores instead of using database.DB directly.
|
||||
// v0.30.2: accepts optional uekCache to pre-warm vault on restart.
|
||||
func ProbeAndRepairVault(ctx context.Context, stores store.Stores, userID, password string, uekCache ...*crypto.UEKCache) {
|
||||
vaultSet, encryptedUEK, salt, nonce, err := stores.Users.GetVaultKeys(ctx, userID)
|
||||
if err != nil || !vaultSet {
|
||||
@@ -493,7 +490,7 @@ func BootstrapAdmin(cfg *config.Config, s store.Stores, uekCache ...*crypto.UEKC
|
||||
})
|
||||
// If the actual password changed, the vault seal is stale. Probe it
|
||||
// with the current password and destroy only if unwrap fails.
|
||||
// Ensure handle exists (backfill for pre-v0.24.0 users)
|
||||
// Ensure handle exists (backfill for users)
|
||||
if existing.Handle == "" {
|
||||
handle := auth.UniqueHandle(ctx, s.Users, models.HandleFromName(cfg.AdminUsername))
|
||||
s.Users.Update(ctx, existing.ID, map[string]interface{}{"handle": handle})
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package handlers
|
||||
|
||||
// v0.38.1: ConnectionResolver bridges the sandbox connections module
|
||||
// to the store + vault layers. Implements sandbox.ConnectionResolver.
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package handlers
|
||||
|
||||
// v0.38.4: Connection type discovery endpoint.
|
||||
// Returns merged connection types from all active packages.
|
||||
// Library declarations take precedence over non-library declarations.
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package handlers
|
||||
|
||||
// v0.38.1: Extension connection handlers — personal scope + resolution.
|
||||
// Pattern follows apiconfigs.go (ProviderConfigHandler).
|
||||
|
||||
import (
|
||||
@@ -28,7 +27,6 @@ func NewConnectionHandler(s store.Stores, vault *crypto.KeyResolver) *Connection
|
||||
// ListConnections returns the user's personal connections.
|
||||
func (h *ConnectionHandler) ListConnections(c *gin.Context) {
|
||||
userID := getUserID(c)
|
||||
// v0.38.5: Show all accessible connections (personal + team + global)
|
||||
// so users can see which connections are available to them.
|
||||
conns, err := h.stores.Connections.ListAccessible(c.Request.Context(), userID)
|
||||
if err != nil {
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"switchboard-core/models"
|
||||
)
|
||||
|
||||
// ── Extension Dependencies (v0.38.2) ──────────────────
|
||||
// ── Extension Dependencies ──────────────────
|
||||
// Admin-only read endpoints for dependency graph visibility.
|
||||
// Dependencies are created/deleted implicitly by InstallPackage/DeletePackage.
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Package handlers — ext_api.go
|
||||
//
|
||||
// v0.29.1 CS1: Extension API routes. Starlark packages serve custom
|
||||
// JSON endpoints via the existing Gin router. Mounted at
|
||||
// /s/:slug/api/*path with JWT auth.
|
||||
//
|
||||
@@ -332,7 +331,7 @@ func hasPermission(granted []string, perm string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ── api_schema support (v0.6.2) ─────────────────────────────────────
|
||||
// ── api_schema support ─────────────────────────────────────
|
||||
|
||||
// APISchemaEntry represents one route's OpenAPI-level documentation
|
||||
// declared via the optional manifest "api_schema" array.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package handlers
|
||||
|
||||
// ext_db_schema.go — v0.29.2
|
||||
// ext_db_schema.go
|
||||
//
|
||||
// DDL generation and lifecycle management for extension-owned database tables.
|
||||
// Tables are namespaced as ext_{pkg_slug}_{logical_name} and tracked in the
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
)
|
||||
|
||||
// ExtPermHandler serves extension permission management endpoints.
|
||||
// v0.29.0 CS2: Admin reviews and grants/revokes declared permissions.
|
||||
type ExtPermHandler struct {
|
||||
stores store.Stores
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
)
|
||||
|
||||
// ExtSecretsHandler serves extension secret management endpoints.
|
||||
// v0.29.0 CS3: Admin sets key-value secrets that Starlark extensions
|
||||
// can read via the secrets.get() module.
|
||||
//
|
||||
// Secrets are stored in GlobalConfig under key "ext_secrets:{packageID}"
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
)
|
||||
|
||||
// ExtensionHandler serves extension management endpoints.
|
||||
// v0.28.7: Backed by PackageStore (packages table) instead of ExtensionStore.
|
||||
type ExtensionHandler struct {
|
||||
stores store.Stores
|
||||
}
|
||||
@@ -94,7 +93,6 @@ func (h *ExtensionHandler) UpdateUserExtensionSettings(c *gin.Context) {
|
||||
|
||||
settings := json.RawMessage("{}")
|
||||
if body.Settings != nil {
|
||||
// v0.2.0: enforce user_overridable — strip locked keys before saving
|
||||
schema := store.ParseSettingsSchema(pkg.Manifest)
|
||||
if len(schema) > 0 {
|
||||
var incoming map[string]any
|
||||
@@ -229,18 +227,15 @@ func (h *ExtensionHandler) AdminInstallExtension(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// v0.29.0: Parse manifest permissions and declare them.
|
||||
// If permissions are declared, package moves to pending_review.
|
||||
SyncManifestPermissions(c, h.stores, pkg.ID, manifestMap)
|
||||
|
||||
// v0.29.2: Create namespaced DB tables declared in the manifest.
|
||||
if tables, ok := ParseDBTables(manifestMap); ok {
|
||||
if err := CreateExtTables(c.Request.Context(), database.DB, database.IsPostgres(), h.stores, pkg.ID, tables); err != nil {
|
||||
log.Printf("[ext-db] schema create failed for %s: %v", pkg.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// v0.2.2: Sync triggers from manifest
|
||||
SyncManifestTriggers(c.Request.Context(), h.stores, triggers.GlobalEngine(), pkg.ID, manifestMap)
|
||||
|
||||
c.JSON(201, gin.H{"data": pkg})
|
||||
@@ -403,7 +398,6 @@ func (h *ExtensionHandler) AdminUninstallExtension(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// v0.29.2: Drop namespaced DB tables before removing the package record.
|
||||
if err := DropExtTables(c.Request.Context(), database.DB, h.stores, id); err != nil {
|
||||
log.Printf("[ext-db] schema drop failed for %s: %v", id, err)
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ func (h *GroupHandler) AddMember(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Notify the added user (v0.20.0)
|
||||
// Notify the added user
|
||||
if svc := notifications.Default(); svc != nil {
|
||||
notifications.NotifyGroupMemberAdded(svc, req.UserID, groupID, group.Name)
|
||||
}
|
||||
@@ -273,7 +273,7 @@ func (h *GroupHandler) RemoveMember(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// Notify the removed user (v0.20.0)
|
||||
// Notify the removed user
|
||||
if svc := notifications.Default(); svc != nil && group != nil {
|
||||
notifications.NotifyGroupMemberRemoved(svc, userID, groupID, group.Name)
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ func setupNotifHarness(t *testing.T) *notifHarness {
|
||||
protected.PUT("/notifications/preferences/:type", notifH.SetPreference)
|
||||
protected.DELETE("/notifications/preferences/:type", notifH.DeletePreference)
|
||||
|
||||
// Admin broadcast route (v0.28.6)
|
||||
// Admin broadcast route
|
||||
admin := api.Group("/admin")
|
||||
admin.Use(middleware.Auth(cfg, stores.Users, userCache))
|
||||
admin.Use(middleware.RequireAdmin(stores))
|
||||
@@ -560,7 +560,7 @@ func TestNotifications_Unauthenticated(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Admin Broadcast (v0.28.6) ────────────
|
||||
// ── Admin Broadcast ────────────
|
||||
|
||||
func TestBroadcast_Success(t *testing.T) {
|
||||
h := setupNotifHarness(t)
|
||||
|
||||
@@ -175,7 +175,7 @@ func (h *NotificationHandler) Delete(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
// ── Notification Preferences (v0.20.0 Phase 3) ──
|
||||
// ── Notification Preferences ──
|
||||
|
||||
// GET /api/v1/notifications/preferences
|
||||
func (h *NotificationHandler) ListPreferences(c *gin.Context) {
|
||||
@@ -282,7 +282,7 @@ func (h *NotificationHandler) DeletePreference(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"ok": true})
|
||||
}
|
||||
|
||||
// ── Admin Broadcast (v0.28.6) ───────────────
|
||||
// ── Admin Broadcast ───────────────
|
||||
|
||||
// POST /api/v1/admin/notifications/broadcast
|
||||
// Admin-only: sends a system.announcement notification to all active users.
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Package handlers — openapi.go
|
||||
//
|
||||
// v0.6.2: Dynamic OpenAPI spec generation. Merges the static kernel spec
|
||||
// with extension-declared API routes. Extensions with api_schema get rich
|
||||
// path items; others get auto-generated stubs.
|
||||
//
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package handlers
|
||||
|
||||
// package_registry.go — v0.30.0 CS4
|
||||
// package_registry.go
|
||||
//
|
||||
// Package registry (marketplace discovery). Admin browses available
|
||||
// packages from an external JSON registry and installs them by URL.
|
||||
|
||||
@@ -27,12 +27,12 @@ import (
|
||||
var validPackageID = regexp.MustCompile(`^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$`)
|
||||
|
||||
// PackageHandler manages unified package lifecycle (admin-only).
|
||||
// Replaces SurfaceHandler (v0.28.7).
|
||||
// Replaces SurfaceHandler.
|
||||
type PackageHandler struct {
|
||||
stores store.Stores
|
||||
packagesDir string // e.g. /data/packages — where archives are extracted
|
||||
sandbox *sandbox.Sandbox // v0.30.0: for schema migration scripts
|
||||
runner *sandbox.Runner // v0.38.2: for test-tool execution
|
||||
sandbox *sandbox.Sandbox
|
||||
runner *sandbox.Runner
|
||||
}
|
||||
|
||||
func NewPackageHandler(s store.Stores, packagesDir ...string) *PackageHandler {
|
||||
@@ -43,12 +43,12 @@ func NewPackageHandler(s store.Stores, packagesDir ...string) *PackageHandler {
|
||||
return &PackageHandler{stores: s, packagesDir: dir}
|
||||
}
|
||||
|
||||
// SetSandbox attaches a Starlark sandbox for schema migrations (v0.30.0).
|
||||
// SetSandbox attaches a Starlark sandbox for schema migrations.
|
||||
func (h *PackageHandler) SetSandbox(sb *sandbox.Sandbox) {
|
||||
h.sandbox = sb
|
||||
}
|
||||
|
||||
// SetRunner attaches the Starlark runner for test-tool execution (v0.38.2).
|
||||
// SetRunner attaches the Starlark runner for test-tool execution.
|
||||
func (h *PackageHandler) SetRunner(r *sandbox.Runner) {
|
||||
h.runner = r
|
||||
}
|
||||
@@ -95,7 +95,6 @@ func (h *PackageHandler) GetPackage(c *gin.Context) {
|
||||
func (h *PackageHandler) EnablePackage(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// v0.3.7: Block enabling dormant packages (unmet requires).
|
||||
pkg, err := h.stores.Packages.Get(c.Request.Context(), id)
|
||||
if err != nil || pkg == nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "package not found"})
|
||||
@@ -149,7 +148,6 @@ func (h *PackageHandler) DeletePackage(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// v0.38.2: Libraries with active consumers cannot be uninstalled.
|
||||
if pkg.Type == "library" && h.stores.Dependencies != nil {
|
||||
hasConsumers, _ := h.stores.Dependencies.HasConsumers(c.Request.Context(), id)
|
||||
if hasConsumers {
|
||||
@@ -158,12 +156,10 @@ func (h *PackageHandler) DeletePackage(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// v0.38.2: Clean up dependency records when uninstalling a consumer.
|
||||
if h.stores.Dependencies != nil {
|
||||
h.stores.Dependencies.DeleteAllForConsumer(c.Request.Context(), id)
|
||||
}
|
||||
|
||||
// v0.29.2: Drop namespaced DB tables before removing the package record.
|
||||
if err := DropExtTables(c.Request.Context(), database.DB, h.stores, id); err != nil {
|
||||
log.Printf("[ext-db] schema drop failed for %s: %v", id, err)
|
||||
}
|
||||
@@ -195,7 +191,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
var tmpPath string
|
||||
var cleanupTmp bool
|
||||
|
||||
// v0.30.0: Check for pre-downloaded file from registry install
|
||||
if regFile, ok := c.Get("_registry_file"); ok {
|
||||
tmpPath = regFile.(string)
|
||||
// Don't remove — caller manages lifecycle
|
||||
@@ -278,7 +273,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
|
||||
// v0.38.0: Entry point validation for starlark-tier packages.
|
||||
// Scripts are loaded from disk at runtime — no _starlark_script injection.
|
||||
if manifestTier, _ := manifest["tier"].(string); manifestTier == "starlark" {
|
||||
entryPoint := "script.star"
|
||||
@@ -380,7 +374,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "full packages require a route"})
|
||||
return
|
||||
}
|
||||
// v0.31.0: full packages need either server-side behavior (tools/pipes/hooks)
|
||||
// or a settings schema. A surface-with-settings is a valid "full" package
|
||||
// (e.g. editor: browser-tier surface + admin-configurable settings).
|
||||
if !hasExtBehavior && !hasSettings {
|
||||
@@ -393,7 +386,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
return
|
||||
}
|
||||
case "library":
|
||||
// v0.38.2: Libraries must declare exports, cannot have tools/pipes/route.
|
||||
exports, _ := manifest["exports"].([]any)
|
||||
if len(exports) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "library packages require an 'exports' array"})
|
||||
@@ -471,7 +463,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
|
||||
userID := c.GetString("user_id")
|
||||
|
||||
// v0.30.0: use registry source if set by registry install handler
|
||||
pkgSource := "extension"
|
||||
if src, ok := c.Get("_registry_source"); ok {
|
||||
pkgSource = src.(string)
|
||||
@@ -509,22 +500,18 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
log.Printf("[packages] Failed to update package metadata for %s: %v", pkgID, err)
|
||||
}
|
||||
|
||||
// v0.29.2: Create namespaced DB tables declared in the manifest.
|
||||
if tables, ok := ParseDBTables(manifest); ok {
|
||||
if err := CreateExtTables(c.Request.Context(), database.DB, database.IsPostgres(), h.stores, pkgID, tables); err != nil {
|
||||
log.Printf("[ext-db] schema create failed for %s: %v", pkgID, err)
|
||||
}
|
||||
}
|
||||
|
||||
// v0.38.5: Declare manifest permissions (same as AdminInstallExtension).
|
||||
// This creates the permission rows and sets status to pending_review
|
||||
// if the package declares permissions.
|
||||
SyncManifestPermissions(c, h.stores, pkgID, manifest)
|
||||
|
||||
// v0.2.2: Sync triggers from manifest
|
||||
SyncManifestTriggers(c.Request.Context(), h.stores, triggers.GlobalEngine(), pkgID, manifest)
|
||||
|
||||
// v0.30.0: Run schema migrations if declared.
|
||||
newSchemaVersion := ParseSchemaVersion(manifest)
|
||||
if newSchemaVersion > 0 && h.sandbox != nil {
|
||||
oldSchemaVersion := 0
|
||||
@@ -553,7 +540,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// v0.30.2: Install workflow definition from package manifest.
|
||||
if pkgType == "workflow" {
|
||||
if err := InstallWorkflowFromManifest(c, h.stores, pkgID, manifest); err != nil {
|
||||
log.Printf("[packages] workflow install failed for %s: %v", pkgID, err)
|
||||
@@ -562,7 +548,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// v0.38.2: Create dependency records from manifest "dependencies" map.
|
||||
// Libraries must be installed first; consumers declare them.
|
||||
if deps, ok := manifest["dependencies"].(map[string]any); ok && len(deps) > 0 {
|
||||
// Clear stale dependency records from a previous install of the same consumer.
|
||||
@@ -603,7 +588,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
log.Printf("[packages] %s: %d dependencies recorded", pkgID, len(deps))
|
||||
}
|
||||
|
||||
// v0.2.1: Auto-set default_surface when the first extension surface is installed.
|
||||
if (pkgType == "surface" || pkgType == "full") && pkgSource != "core" {
|
||||
if raw, err := h.stores.GlobalConfig.Get(c.Request.Context(), "default_surface"); err != nil || raw == nil {
|
||||
dflt := models.JSONMap{"id": pkgID}
|
||||
@@ -615,7 +599,6 @@ func (h *PackageHandler) InstallPackage(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// v0.3.7: Auto-set dormant for packages with unmet requires.
|
||||
// Known capabilities: (none yet — chat and legacy-sdk are future/removed).
|
||||
knownCaps := map[string]bool{}
|
||||
var unmetReqs []string
|
||||
@@ -689,7 +672,7 @@ func extractableRelPath(name string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// ── Package settings (v0.30.0 CS2) ──────────────
|
||||
// ── Package settings ──────────────
|
||||
|
||||
// GetPackageSettings returns the settings schema from the manifest merged
|
||||
// with current admin-configured values.
|
||||
@@ -823,7 +806,7 @@ func (h *PackageHandler) ListEnabledSurfaces(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"data": enabled})
|
||||
}
|
||||
|
||||
// ── Test Tool (v0.38.2) ─────────────────────────
|
||||
// ── Test Tool ─────────────────────────
|
||||
// POST /admin/packages/:id/test-tool
|
||||
// Invokes a starlark extension's on_tool_call entry point directly,
|
||||
// without going through the AI chat loop. Admin-only test harness.
|
||||
@@ -898,7 +881,7 @@ func (h *PackageHandler) TestTool(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// ── Package update (v0.5.4) ──────────────────────
|
||||
// ── Package update ──────────────────────
|
||||
|
||||
// UpdatePackage applies an in-place update to an existing package.
|
||||
// POST /api/v1/admin/packages/:id/update
|
||||
@@ -1175,7 +1158,7 @@ func mergePackageSettings(existing *store.PackageRegistration, manifest map[stri
|
||||
return data
|
||||
}
|
||||
|
||||
// ── Package export (v0.5.4) ──────────────────────
|
||||
// ── Package export ──────────────────────
|
||||
|
||||
// ExportPackage exports an installed package as a downloadable .pkg archive.
|
||||
// GET /api/v1/admin/packages/:id/export
|
||||
|
||||
@@ -23,23 +23,16 @@ import (
|
||||
)
|
||||
|
||||
// defaultBundledPackages is the curated set of packages installed by default.
|
||||
// This is the dev/test bundle — includes demos and workflow examples.
|
||||
// Other packages still ship in the Docker image but require BUNDLED_PACKAGES
|
||||
// to be set explicitly (or "*" for all).
|
||||
//
|
||||
// Recommended production override (lean):
|
||||
// BUNDLED_PACKAGES=notes,chat,chat-core,cluster-dashboard
|
||||
// Recommended production override: BUNDLED_PACKAGES=notes,chat,chat-core,mermaid-renderer,schedules
|
||||
var defaultBundledPackages = map[string]bool{
|
||||
"notes": true,
|
||||
"chat": true,
|
||||
"chat-core": true,
|
||||
"workflow-chat": true,
|
||||
"dashboard": true,
|
||||
"cluster-dashboard": true,
|
||||
"workflow-demo": true,
|
||||
"bug-report-triage": true,
|
||||
"content-approval": true,
|
||||
"employee-onboarding": true,
|
||||
"notes": true,
|
||||
"chat": true,
|
||||
"chat-core": true,
|
||||
"mermaid-renderer": true,
|
||||
"schedules": true,
|
||||
}
|
||||
|
||||
// InstallBundledPackages scans bundledDir for .pkg archives and installs
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package handlers
|
||||
|
||||
// presence.go — Heartbeat upsert and status query (v0.23.1)
|
||||
// presence.go — Heartbeat upsert and status query
|
||||
//
|
||||
// Clients POST /api/v1/presence/heartbeat every 30s while active.
|
||||
// GET /api/v1/presence?users=id1,id2 returns current status.
|
||||
// Online = last_seen within 90s.
|
||||
//
|
||||
// v0.29.0: Raw SQL replaced with PresenceStore + UserStore methods.
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
@@ -8,7 +8,6 @@ package handlers
|
||||
// (profile, permissions, teams/mine, settings) into one call.
|
||||
// The SDK calls this at startup and on token refresh.
|
||||
//
|
||||
// v0.37.15
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
@@ -51,7 +51,7 @@ func (s *jsonScanner) Scan(src interface{}) error {
|
||||
// memory on the next rows.Scan() call, corrupting our data after the
|
||||
// fact. This caused intermittent SafeJSON 500s on paginated list
|
||||
// endpoints where row N's Settings pointed to row N+1's overwritten
|
||||
// buffer. Fixed in v0.21.7.
|
||||
// buffer. Fixed.
|
||||
cp := make([]byte, len(v))
|
||||
copy(cp, v)
|
||||
*s.dest = json.RawMessage(cp)
|
||||
|
||||
@@ -185,7 +185,7 @@ func TestSafeJSON_PaginatedWithCorrupt(t *testing.T) {
|
||||
}
|
||||
|
||||
// ── Driver buffer aliasing tests ────────────
|
||||
// These verify the fix for the v0.21.7 corruption bug: scanJSON must
|
||||
// These verify the fix for the buffer-aliasing corruption bug: scanJSON must
|
||||
// copy []byte from the database driver, not alias it. Without the copy,
|
||||
// rows.Next() can overwrite the buffer and corrupt previously-scanned
|
||||
// json.RawMessage values in a paginated list.
|
||||
|
||||
@@ -2,7 +2,6 @@ package handlers
|
||||
|
||||
// settings.go — User profile, preferences, and password management.
|
||||
//
|
||||
// v0.29.0: Raw SQL replaced with UserStore methods.
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package handlers
|
||||
|
||||
// team_package_settings.go — v0.2.0
|
||||
// team_package_settings.go
|
||||
//
|
||||
// Team-admin endpoints for managing team-scoped package settings.
|
||||
// These sit in the settings cascade between global (admin) and user.
|
||||
|
||||
@@ -419,7 +419,7 @@ func (h *TeamHandler) ListTeamAuditActions(c *gin.Context) {
|
||||
c.JSON(http.StatusOK, gin.H{"actions": actions})
|
||||
}
|
||||
|
||||
// ── Team Roles API (v0.3.4) ─────────────────
|
||||
// ── Team Roles API ─────────────────
|
||||
|
||||
// builtinRoles are always present in every team's role list.
|
||||
var builtinRoles = []string{"admin", "member"}
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
// ═══════════════════════════════════════════════
|
||||
// Upgrade Tests — v0.5.5
|
||||
// Upgrade Tests
|
||||
//
|
||||
// Schema edge cases, settings migration, and
|
||||
// package compatibility across kernel upgrades.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package handlers
|
||||
|
||||
// user_packages.go — v0.30.0 CS5
|
||||
// user_packages.go
|
||||
//
|
||||
// Non-admin package management. Users install personal-scoped packages;
|
||||
// team admins install team-scoped packages.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package handlers
|
||||
|
||||
// workflow_packages.go — v0.30.2 CS1
|
||||
// workflow_packages.go
|
||||
//
|
||||
// Handles workflow-specific package operations:
|
||||
// - ExportWorkflowPackage: bundles a workflow definition + stages into a .pkg
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"switchboard-core/workflow"
|
||||
)
|
||||
|
||||
// ── Public Workflow Handlers (v0.3.3) ───────
|
||||
// ── Public Workflow Handlers ───────
|
||||
|
||||
// WorkflowPublicHandler manages unauthenticated workflow entry endpoints.
|
||||
type WorkflowPublicHandler struct {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"switchboard-core/workflow"
|
||||
)
|
||||
|
||||
// ── Signoff Handlers (v0.3.4) ─────────────────
|
||||
// ── Signoff Handlers ─────────────────
|
||||
|
||||
// WorkflowSignoffHandler manages signoff HTTP endpoints.
|
||||
type WorkflowSignoffHandler struct {
|
||||
|
||||
@@ -603,7 +603,7 @@ func TestWorkflowAssignment_Cancel(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── v0.3.3 Store Tests ──────────────────────
|
||||
// ── Instance Lifecycle Store Tests ──────────────────────
|
||||
|
||||
func TestWorkflowInstance_MarkStale(t *testing.T) {
|
||||
database.RequireTestDB(t)
|
||||
@@ -779,7 +779,7 @@ func TestWorkflowAssignment_ListByTeam(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Signoff store tests (v0.3.4) ──────────────
|
||||
// ── Signoff store tests ──────────────
|
||||
|
||||
func TestWorkflowSignoff_CreateAndList(t *testing.T) {
|
||||
database.RequireTestDB(t)
|
||||
@@ -862,7 +862,7 @@ func TestWorkflowSignoff_ListEmpty(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Clone tests (v0.3.5) ──────────────────
|
||||
// ── Clone tests ──────────────────
|
||||
|
||||
func TestWorkflow_Clone(t *testing.T) {
|
||||
database.RequireTestDB(t)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"switchboard-core/models"
|
||||
)
|
||||
|
||||
// ── Team-Scoped Workflow Wrappers (v0.31.2) ────────────────
|
||||
// ── Team-Scoped Workflow Wrappers ────────────────
|
||||
//
|
||||
// Thin wrappers that enforce team ownership before delegating
|
||||
// to the existing WorkflowHandler methods. Follows the same
|
||||
|
||||
@@ -106,7 +106,6 @@ func (h *WorkflowHandler) Create(c *gin.Context) {
|
||||
|
||||
w.CreatedBy = c.GetString("user_id")
|
||||
|
||||
// v0.31.2: team-scoped route injects force_team_id via CreateTeamWorkflow
|
||||
if ftid, ok := c.Get("force_team_id"); ok {
|
||||
tid := ftid.(string)
|
||||
w.TeamID = &tid
|
||||
@@ -417,7 +416,6 @@ func (h *WorkflowHandler) Clone(c *gin.Context) {
|
||||
CreatedBy: c.GetString("user_id"),
|
||||
}
|
||||
|
||||
// v0.31.2: team-scoped route injects force_team_id
|
||||
if ftid, ok := c.Get("force_team_id"); ok {
|
||||
tid := ftid.(string)
|
||||
clone.TeamID = &tid
|
||||
|
||||
Reference in New Issue
Block a user