package pages import ( "context" "log" "net/http" "github.com/gin-gonic/gin" ) // SeedSurfaces writes core surface manifests to the registry table. // Called once at startup. Does NOT overwrite the enabled flag — admin // toggles survive restarts. func (e *Engine) SeedSurfaces() { if e.stores.Packages == nil { log.Printf("[pages] Surface registry not available — skipping seed") return } ctx := context.Background() for _, s := range e.surfaces { manifest := map[string]any{ "route": s.Route, "alt_routes": s.AltRoutes, "template": s.Template, "components": s.Components, "data_requires": s.DataRequires, "auth": s.Auth, "layout": s.Layout, } if err := e.stores.Packages.Seed(ctx, s.ID, s.Title, s.Source, manifest); err != nil { log.Printf("[pages] Failed to seed surface %q: %v", s.ID, err) } } log.Printf("[pages] Seeded %d core surfaces into registry", len(e.surfaces)) // v0.31.0: Clean up old "editor" core surface row. // Editor is now an installable package — the old seed row would show a // broken nav link until the package .pkg is uploaded via admin UI. if sr, err := e.stores.Packages.Get(ctx, "editor"); err == nil && sr != nil && sr.Source == "extension" { if sr.Type == "" || sr.Type == "surface" { if delErr := e.stores.Packages.Delete(ctx, "editor"); delErr != nil { log.Printf("[pages] Failed to clean up old editor surface: %v", delErr) } else { log.Printf("[pages] Cleaned up old editor core surface — install editor .pkg via admin UI") } } } } // IsSurfaceEnabled checks if a surface is enabled in the registry. // Chat and Admin are always enabled (system-critical). // Returns true if the surface is not found (fail-open for backward compat). func (e *Engine) IsSurfaceEnabled(surfaceID string) bool { // Chat and Admin cannot be disabled — they're system-critical if surfaceID == "chat" || surfaceID == "admin" { return true } if e.stores.Packages == nil { return true // No registry = all surfaces enabled (backward compat) } ctx := context.Background() sr, err := e.stores.Packages.Get(ctx, surfaceID) if err != nil || sr == nil { return true // Not in registry = assume enabled (backward compat) } return sr.Enabled } // EnabledSurfaceIDs returns a list of enabled surface IDs for nav rendering. func (e *Engine) EnabledSurfaceIDs() []string { if e.stores.Packages == nil { // No registry — return all core surface IDs var all []string for _, s := range e.surfaces { all = append(all, s.ID) } return all } ctx := context.Background() ids, err := e.stores.Packages.ListEnabled(ctx) if err != nil { log.Printf("[pages] Failed to load enabled surfaces: %v", err) // Fallback: return all core surface IDs var all []string for _, s := range e.surfaces { all = append(all, s.ID) } return all } return ids } // disabledRedirect returns a handler that redirects to the root. func (e *Engine) disabledRedirect() gin.HandlerFunc { return func(c *gin.Context) { c.Redirect(http.StatusTemporaryRedirect, e.cfg.BasePath+"/") } }