Documentation
¶
Overview ¶
Package server provides the server-side runtime for Vango's server-driven architecture.
The server package manages WebSocket connections, component state, event handling, and patch generation. It is the integration layer that brings together the reactive system (pkg/vango), virtual DOM (pkg/vdom), and binary protocol (pkg/protocol).
Architecture ¶
The server runtime consists of several key components:
- Session: Per-connection state container managing component tree, handlers, and reactive ownership
- SessionManager: Manages all active sessions with cleanup and lifecycle hooks
- ComponentInstance: A mounted component with its reactive state and render capability
- Handler: Event handler functions that respond to client events
- Server: HTTP/WebSocket server with handshake and graceful shutdown
Session Lifecycle ¶
Each WebSocket connection creates a Session that manages:
- Component tree and hydration IDs
- Event handler registry (HID -> handler mapping)
- Reactive ownership for signals and effects
- Sequence numbers for reliable delivery
The session runs three goroutines:
- ReadLoop: Receives WebSocket frames, decodes events, queues for processing
- EventLoop: Processes events, runs handlers, generates patches
- WriteLoop: Sends heartbeat pings
Event Processing ¶
When a client sends an event:
- ReadLoop decodes the binary event frame
- Event is queued for the EventLoop
- Handler is found by HID and executed
- Pending effects are run
- Dirty components are re-rendered
- Diff generates patches
- Patches are encoded and sent to client
Example Usage ¶
server := server.MustNew(&server.ServerConfig{
Address: ":8080",
})
server.HandleFunc("/", func(ctx server.Ctx) *vdom.VNode {
count := vango.NewIntSignal(0)
return vdom.Div(
vdom.H1(vdom.Textf("Count: %d", count.Get())),
vdom.Button(
vdom.OnClick(func() { count.Inc() }),
vdom.Text("+"),
),
)
})
server.Run()
Thread Safety ¶
The server package is designed for concurrent access:
- Session.mu protects WebSocket writes
- Events channel serializes event processing
- Signal access uses Phase 1 synchronization
- SessionManager uses RWMutex for session map
Performance Targets ¶
- Memory per session: < 3MB default budget
- Concurrent sessions per GB: 5,000+
- Event processing latency: < 10ms
- WebSocket reconnect: < 500ms
Session Resume and Authentication ¶
When a WebSocket connection drops and reconnects within ResumeWindow, Vango attempts to resume the existing session. For authenticated sessions, Vango enforces auth revalidation by default via AuthResumePolicy.
## Auth Resume Policy
AuthResumePolicyStrict (default): Requires authFunc or OnSessionResume to be configured for authenticated sessions. Without these, authenticated session resume is rejected and the client receives a HandshakeNotAuthorized error, triggering re-authentication. This prevents session IDs from acting as bearer tokens that could be exploited if leaked via XSS, logging, etc.
AuthResumePolicyTrustSessionID: Allows authenticated sessions to resume using only the session ID for in-memory sessions. Use this only if you understand the security implications: a leaked session ID grants authenticated access. Note: Persisted sessions (Redis, NATS) still require auth rehydration because user objects are not serialized.
## Configuring Auth Revalidation
The recommended approach is to configure Server.SetAuthFunc():
server.SetAuthFunc(func(r *http.Request) (any, error) {
return myauth.ValidateRequest(r)
})
This validates auth credentials on WebSocket handshakes:
- new session: non-nil user auto-hydrates via auth.Set(session, user)
- resume: auth.Set(session, user) rehydrates current auth projection
If authFunc returns (nil, nil), resume is rejected for previously authenticated sessions.
Alternatively, configure OnSessionResume for custom rehydration:
cfg.OnSessionResume = func(ctx context.Context, session *Session) error {
user, err := myauth.ValidateFromContext(ctx)
if err != nil {
return err
}
if user != nil {
auth.Set(session, user) // Rehydrate user projection when your app uses it
auth.SetPrincipal(session, auth.Principal{
ID: user.ID,
}) // Rehydrate principal projection for auth freshness/principal-first flows
}
return nil
}
IMPORTANT: A no-op OnSessionResume that just returns nil does NOT provide security. In strict mode (without authFunc), resume clears runtime auth projection before this hook runs, so previously authenticated sessions are rejected unless the hook actually revalidates and rehydrates auth projection via auth.Set and/or auth.SetPrincipal.
Index ¶
- Constants
- Variables
- func AllowAllOriginsCheck(*http.Request) bool
- func AllowedOriginsCheck(allowedOrigins []string) func(*http.Request) bool
- func BootstrapConfigFromContext(ctx context.Context) (bootstrap.Config, bool)
- func BuildCSP(opts CSPOptions) string
- func CSRFCtxToken(ctx Ctx) string
- func CanonicalizePath(path string) (canonPath, query string, changed bool, err error)
- func CurrentMemoryUsage() int64
- func EstimateAnyMemory(value any) int64
- func EstimateMapMemory(length, keySize, valueSize int) int64
- func EstimateSliceMemory(length, elementSize int) int64
- func EstimateStringMemory(s string) int64
- func HostedSurfaceProofSignature(secret []byte, method, requestURI string, info surface.Info, ...) string
- func InspectState(session *Session) vruntime.StateInspection
- func IsAuthError(err error) bool
- func LoggerForEvent(ctx Ctx, base *slog.Logger) *slog.Logger
- func NormalizeAuthCheckConfig(cfg *AuthCheckConfig)
- func RunRouteMiddleware(ctx Ctx, middleware []RouteMiddleware, final func() error) (ranFinal bool, err error)
- func RuntimeUnsafePermissionsFromContext(ctx context.Context) (vdom.RuntimeUnsafePermissions, bool)
- func SameOriginCheck(r *http.Request) bool
- func SetCSRFCtxToken(ctx Ctx, token string)
- func SetGlobalPrefetchLimit(limit int)
- func ShellBridgeFromContext(ctx context.Context) shell.Bridge
- func SurfaceInfoFromContext(ctx context.Context) surface.Info
- func ThinClientHash() string
- func TotalSystemMemory() int64
- func UserFromContext(ctx context.Context) any
- func UserFromContextAs[T any](ctx context.Context) (T, bool)
- func ValidateExternalRedirectURL(rawURL string, allowedHosts []string) (string, bool)
- func WithBootstrapConfig(ctx context.Context, cfg bootstrap.Config) context.Context
- func WithRuntimeUnsafePermissions(ctx context.Context, perms vdom.RuntimeUnsafePermissions) context.Context
- func WithShellBridge(ctx context.Context, bridge shell.Bridge) context.Context
- func WithSurfaceInfo(ctx context.Context, info surface.Info) context.Context
- func WithUser(ctx context.Context, user any) context.Context
- type AppliedNavigateOptions
- type AuthCheckConfig
- type AuthExpiredAction
- type AuthExpiredConfig
- type AuthExpiredReason
- type AuthFailureMode
- type AuthResumePolicy
- type BudgetExceededMode
- type ByteSize
- type CSPOptions
- type CSRFError
- type Component
- type ComponentInstance
- func (c *ComponentInstance) AddChild(child *ComponentInstance)
- func (c *ComponentInstance) ClearDirty()
- func (c *ComponentInstance) Dispose()
- func (c *ComponentInstance) GetProp(key string) any
- func (c *ComponentInstance) ID() uint64
- func (c *ComponentInstance) IsDirty() bool
- func (c *ComponentInstance) LastTree() *vdom.VNode
- func (c *ComponentInstance) ListKeyPath() []string
- func (c *ComponentInstance) MarkDirty()
- func (c *ComponentInstance) MemoryUsage() int64
- func (c *ComponentInstance) RemoveChild(child *ComponentInstance)
- func (c *ComponentInstance) Render() *vdom.VNode
- func (c *ComponentInstance) Session() *Session
- func (c *ComponentInstance) SetLastTree(tree *vdom.VNode)
- func (c *ComponentInstance) SetProp(key string, value any)
- func (c *ComponentInstance) TrackDependency(dep vango.Dependency)
- type CookieOption
- type CookiePolicy
- type CookiePolicyOptions
- type Ctx
- type Event
- type EventRateLimiter
- type FormData
- type FuncComponent
- type Handler
- type HandlerError
- type HealthCheck
- type HookEvent
- type HostedSurfaceAllowedSurface
- type HostedSurfaceIdentity
- type HostedSurfaceVerifierConfig
- type HostedSurfaceVerifyFunc
- type InstancePath
- type KeyboardEvent
- type LayoutHandler
- type ManagerStats
- type MemoryMonitor
- func (m *MemoryMonitor) ForceCheck()
- func (m *MemoryMonitor) Pause()
- func (m *MemoryMonitor) Resume()
- func (m *MemoryMonitor) SetOnHardLimit(fn func(current, limit int64))
- func (m *MemoryMonitor) SetOnSoftLimit(fn func(current, limit int64))
- func (m *MemoryMonitor) Start()
- func (m *MemoryMonitor) Stop()
- type MemoryMonitorConfig
- type MemoryPressureLevel
- type MemoryStats
- type MetricsCollector
- func (m *MetricsCollector) RecordActionDuration(action string, ms int64)
- func (m *MetricsCollector) RecordActionError(action string)
- func (m *MetricsCollector) RecordBytesReceived(n int)
- func (m *MetricsCollector) RecordBytesSent(n int)
- func (m *MetricsCollector) RecordColdDeployAck(source string)
- func (m *MetricsCollector) RecordEventDropped()
- func (m *MetricsCollector) RecordEventLatency(latencyUs int64)
- func (m *MetricsCollector) RecordEventProcessed()
- func (m *MetricsCollector) RecordEventReceived()
- func (m *MetricsCollector) RecordHandlerPanic()
- func (m *MetricsCollector) RecordPatchBytes(route string, bytes int)
- func (m *MetricsCollector) RecordPatchMismatch(reason string)
- func (m *MetricsCollector) RecordPatchesSent(count int, bytes int)
- func (m *MetricsCollector) RecordPersistBytes(stableID string, bytes int64)
- func (m *MetricsCollector) RecordPersistBytesWritten(primitiveID string, bytes int64)
- func (m *MetricsCollector) RecordPersistWriteRejected(reason string, primitiveID string)
- func (m *MetricsCollector) RecordReadError()
- func (m *MetricsCollector) RecordResourceDuration(resource string, ms int64)
- func (m *MetricsCollector) RecordResourceError(resource string)
- func (m *MetricsCollector) RecordResumeFailure(reason string)
- func (m *MetricsCollector) RecordResumeSuccess()
- func (m *MetricsCollector) RecordSchemaMismatch(reason string)
- func (m *MetricsCollector) RecordSessionActive(delta int)
- func (m *MetricsCollector) RecordSessionDetached(delta int)
- func (m *MetricsCollector) RecordSessionPersistBytes(sessionID string, bytes int64)
- func (m *MetricsCollector) RecordSignalWriteViolation(operation, reason string)
- func (m *MetricsCollector) RecordWriteError()
- func (m *MetricsCollector) Reset()
- func (m *MetricsCollector) Snapshot() *ServerMetrics
- type Middleware
- type MouseEvent
- type NavigateEvent
- type NavigateOption
- type NavigateResult
- type OriginPolicyMode
- type PageHandler
- type PatchHistory
- func (h *PatchHistory) Add(seq uint64, frame []byte)
- func (h *PatchHistory) CanRecover(lastSeq uint64) bool
- func (h *PatchHistory) Clear()
- func (h *PatchHistory) Count() int
- func (h *PatchHistory) GarbageCollect(ackSeq uint64)
- func (h *PatchHistory) GetFrames(afterSeq, toSeq uint64) [][]byte
- func (h *PatchHistory) MaxSeq() uint64
- func (h *PatchHistory) MemoryUsage() int64
- func (h *PatchHistory) MinSeq() uint64
- type PatchHistoryEntry
- type PrefetchCache
- type PrefetchCacheEntry
- type PrefetchConfig
- type PrefetchRateLimiter
- type PrefetchSemaphore
- type PrimitiveInfo
- type ProtocolError
- type RenderMode
- type ResizeEvent
- type RouteMatch
- type RouteMiddleware
- type RouteNavigator
- type Router
- type RuntimeLogEvent
- type RuntimeLogEventSpec
- type SchemaError
- type ScrollEvent
- type Server
- func (s *Server) CSRFMiddleware() Middleware
- func (s *Server) Config() *ServerConfig
- func (s *Server) CookiePolicy() *CookiePolicy
- func (s *Server) EnsureCSRFCookie(w http.ResponseWriter, r *http.Request) (string, error)
- func (s *Server) GenerateCSRFToken() string
- func (s *Server) HandleWebSocket(w http.ResponseWriter, r *http.Request)
- func (s *Server) Handler() http.Handler
- func (s *Server) IsHealthPath(path string) bool
- func (s *Server) Logger() *slog.Logger
- func (s *Server) Metrics() *ServerMetrics
- func (s *Server) PageHandler() http.Handler
- func (s *Server) RequestHostAllowed(r *http.Request) bool
- func (s *Server) Router() Router
- func (s *Server) Run() error
- func (s *Server) RunContext(ctx context.Context) error
- func (s *Server) RuntimeBootstrap(r *http.Request) bootstrap.Config
- func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (s *Server) Sessions() *SessionManager
- func (s *Server) SetAuthFunc(fn func(*http.Request) (any, error))
- func (s *Server) SetCSRFCookie(w http.ResponseWriter, r *http.Request, token string) error
- func (s *Server) SetHandler(h http.Handler)
- func (s *Server) SetLogger(logger *slog.Logger)
- func (s *Server) SetMetricsSink(sink vango.MetricsSink)
- func (s *Server) SetRootComponent(factory func() Component)
- func (s *Server) SetRouter(r Router)
- func (s *Server) Shutdown(ctx context.Context) error
- func (s *Server) UnsafeConfigReport() UnsafeConfigReport
- func (s *Server) UploadHandler(store upload.Store, config *upload.Config) http.Handler
- func (s *Server) Use(mw Middleware)
- func (s *Server) ValidateCSRFRequest(w http.ResponseWriter, r *http.Request) error
- func (s *Server) WebSocketHandler() http.Handler
- func (s *Server) WebSocketURL(r *http.Request) string
- type ServerConfig
- func (c *ServerConfig) Clone() *ServerConfig
- func (c *ServerConfig) GetConfigWarnings() []string
- func (c *ServerConfig) IsSecure() bool
- func (c *ServerConfig) UnsafeConfigReport() UnsafeConfigReport
- func (c *ServerConfig) ValidateConfig() error
- func (c *ServerConfig) WithAddress(addr string) *ServerConfig
- func (c *ServerConfig) WithAllowedHosts(hosts ...string) *ServerConfig
- func (c *ServerConfig) WithAllowedOrigins(origins ...string) *ServerConfig
- func (c *ServerConfig) WithCSRFSecret(secret []byte) *ServerConfig
- func (c *ServerConfig) WithCanonicalHost(host string) *ServerConfig
- func (c *ServerConfig) WithCookieDomain(domain string) *ServerConfig
- func (c *ServerConfig) WithCookieHTTPOnly(httpOnly bool) *ServerConfig
- func (c *ServerConfig) WithDevMode() *ServerConfig
- func (c *ServerConfig) WithEvictOnIPLimit(evict bool) *ServerConfig
- func (c *ServerConfig) WithEvictionPolicy(policy SessionEvictionPolicy) *ServerConfig
- func (c *ServerConfig) WithHostedSurfaceTokenSecret(secret []byte) *ServerConfig
- func (c *ServerConfig) WithHostedSurfaceVerifier(v HostedSurfaceVerifyFunc) *ServerConfig
- func (c *ServerConfig) WithMaxConcurrentHandshakes(max int) *ServerConfig
- func (c *ServerConfig) WithMaxConcurrentHandshakesPerIP(max int) *ServerConfig
- func (c *ServerConfig) WithMaxDetachedSessions(max int) *ServerConfig
- func (c *ServerConfig) WithMaxSessions(max int) *ServerConfig
- func (c *ServerConfig) WithMaxSessionsPerIP(max int) *ServerConfig
- func (c *ServerConfig) WithPersistInterval(d time.Duration) *ServerConfig
- func (c *ServerConfig) WithPreUpgradeCheck(check func(r *http.Request) error) *ServerConfig
- func (c *ServerConfig) WithPublicRuntimePrefix(prefix string) *ServerConfig
- func (c *ServerConfig) WithResumeWindow(d time.Duration) *ServerConfig
- func (c *ServerConfig) WithSameSiteMode(mode http.SameSite) *ServerConfig
- func (c *ServerConfig) WithSecureCookies(secure bool) *ServerConfig
- func (c *ServerConfig) WithSessionConfig(sc *SessionConfig) *ServerConfig
- func (c *ServerConfig) WithSessionStore(store session.SessionStore) *ServerConfig
- type ServerMetrics
- type Session
- func (s *Session) BroadcastAuth(channel, typ string, reason AuthExpiredReason)
- func (s *Session) BudgetTracker() *vango.BudgetTracker
- func (s *Session) BytesReceived(n int)
- func (s *Session) Close()
- func (s *Session) Config() *SessionConfig
- func (s *Session) Conn() *websocket.Conn
- func (s *Session) CurrentRoutePath() string
- func (s *Session) Delete(key string)
- func (s *Session) Deserialize(data []byte) error
- func (s *Session) DeserializeForSessionID(expectedSessionID string, data []byte) error
- func (s *Session) Dispatch(fn func())
- func (s *Session) Done() <-chan struct{}
- func (s *Session) EventLoop()
- func (s *Session) Events() <-chan *Event
- func (s *Session) Get(key string) any
- func (s *Session) GetAllData() map[string]any
- func (s *Session) GetInt(key string) int
- func (s *Session) GetString(key string) string
- func (s *Session) HandleNavigate(path string, replace bool) error
- func (s *Session) Has(key string) bool
- func (s *Session) IsClosed() bool
- func (s *Session) IsDetached() bool
- func (s *Session) Logger() *slog.Logger
- func (s *Session) MemoryUsage() int64
- func (s *Session) MountRoot(component Component)
- func (s *Session) Navigator() *RouteNavigator
- func (s *Session) NeedsRestart() bool
- func (s *Session) Owner() *vango.Owner
- func (s *Session) PersistErrorHandler() func(*vango.PersistBudgetError)
- func (s *Session) PrefetchCache() *PrefetchCache
- func (s *Session) PrimitiveRegistry() *SessionPrimitiveRegistry
- func (s *Session) QueueEvent(event *Event) error
- func (s *Session) ReadLoop()
- func (s *Session) RebuildHandlers() error
- func (s *Session) RegisterIslandHandler(id string, handler vango.IslandMessageHandler) func()
- func (s *Session) RegisterPrimitives(regs []vango.PrimitiveRegistration, component *ComponentInstance)
- func (s *Session) RegisterValidatedIslandHandler(id string, validate vango.IslandMessageValidator, ...) func()
- func (s *Session) RegisterValidatedWasmHandler(id string, validate vango.WasmMessageValidator, ...) func()
- func (s *Session) RegisterWasmHandler(id string, handler vango.WasmMessageHandler) func()
- func (s *Session) RestoreData(values map[string]any)
- func (s *Session) Resume(conn *websocket.Conn, lastSeq uint64)
- func (s *Session) RouteID() string
- func (s *Session) SendClose(reason protocol.CloseReason, message string)
- func (s *Session) SendHookRevert(hid string)
- func (s *Session) SendIslandMessage(id string, payload any) error
- func (s *Session) SendIslandMessageToHID(hid string, payload any) error
- func (s *Session) SendPatches(patches []protocol.Patch)
- func (s *Session) SendResyncFull() error
- func (s *Session) SendSessionRefresh(cmd *protocol.SessionRefreshCommand)
- func (s *Session) SendWasmMessage(id string, payload any) error
- func (s *Session) SendWasmMessageToHID(hid string, payload any) error
- func (s *Session) Serialize() ([]byte, error)
- func (s *Session) SessionID() string
- func (s *Session) Set(key string, value any)
- func (s *Session) SetAssetResolver(r assets.Resolver)
- func (s *Session) SetInitialURL(path string, params map[string]string)
- func (s *Session) SetInt(key string, value int)
- func (s *Session) SetJSON(key string, value any)
- func (s *Session) SetPersistErrorHandler(fn func(*vango.PersistBudgetError))
- func (s *Session) SetRouter(r Router)
- func (s *Session) SetShellBridge(bridge shell.Bridge)
- func (s *Session) SetString(key string, value string)
- func (s *Session) SetSurfaceInfo(info surface.Info)
- func (s *Session) SetUserID(id string)
- func (s *Session) ShellBridge() shell.Bridge
- func (s *Session) ShowPersistErrorBanner(err *vango.PersistBudgetError)
- func (s *Session) Start()
- func (s *Session) Stats() SessionStats
- func (s *Session) StormBudget() vango.StormBudgetChecker
- func (s *Session) SurfaceInfo() surface.Info
- func (s *Session) TriggerSchemaRefresh(reason protocol.SchemaRefreshReason, debug string)
- func (s *Session) UnregisterPrimitives(regs []vango.PrimitiveRegistration, component *ComponentInstance)
- func (s *Session) UpdateLastActive()
- func (s *Session) UserID() string
- func (s *Session) WriteLoop()
- type SessionConfig
- type SessionError
- type SessionEvictionPolicy
- type SessionLimits
- type SessionManager
- func (sm *SessionManager) CheckIPLimit(ip string) error
- func (sm *SessionManager) CheckMemoryPressure()
- func (sm *SessionManager) Close(id string)
- func (sm *SessionManager) Count() int
- func (sm *SessionManager) Create(conn *websocket.Conn, userID, ip string) (*Session, error)
- func (sm *SessionManager) DispatchAll(fn func(*Session))
- func (sm *SessionManager) EvictLRU(count int) int
- func (sm *SessionManager) ForEach(fn func(*Session) bool)
- func (sm *SessionManager) Get(id string) *Session
- func (sm *SessionManager) HasPersistence() bool
- func (sm *SessionManager) MarkResumed(sessionID string)
- func (sm *SessionManager) OnSessionDisconnect(sess *Session)
- func (sm *SessionManager) OnSessionReconnect(sessionID string) (*Session, error)
- func (sm *SessionManager) PersistenceManager() *session.Manager
- func (sm *SessionManager) ResumeWindow() time.Duration
- func (sm *SessionManager) SetBudgetTracker(tracker *vango.BudgetTracker)
- func (sm *SessionManager) SetCleanupInterval(d time.Duration)
- func (sm *SessionManager) SetMetricsSink(sink vango.MetricsSink)
- func (sm *SessionManager) SetOnSessionClose(fn func(*Session))
- func (sm *SessionManager) SetOnSessionCreate(fn func(*Session))
- func (sm *SessionManager) Shutdown()
- func (sm *SessionManager) ShutdownWithContext(ctx context.Context) error
- func (sm *SessionManager) Stats() ManagerStats
- func (sm *SessionManager) TotalMemoryUsage() int64
- func (sm *SessionManager) UpdateSessionIP(session *Session, newIP string) error
- type SessionManagerOptions
- type SessionPrimitiveRegistry
- func (r *SessionPrimitiveRegistry) All() []*PrimitiveInfo
- func (r *SessionPrimitiveRegistry) AllPersisted() []*PrimitiveInfo
- func (r *SessionPrimitiveRegistry) FindByDebugName(debugName string) []*PrimitiveInfo
- func (r *SessionPrimitiveRegistry) FindByNameOrID(nameOrID string) (*PrimitiveInfo, bool)
- func (r *SessionPrimitiveRegistry) FindByStableID(stableID string) []*PrimitiveInfo
- func (r *SessionPrimitiveRegistry) Register(reg vango.PrimitiveRegistration, instancePath string)
- func (r *SessionPrimitiveRegistry) SignalValue(nameOrID string) (any, bool)
- func (r *SessionPrimitiveRegistry) Unregister(instancePath string)
- type SessionStats
- type StormBudgetConfig
- type TouchEvent
- type TouchPoint
- type UnsafeConfigCode
- type UnsafeConfigEntry
- type UnsafeConfigReport
- type UnsafeConfigSeverity
- type UnsafeConfigState
Constants ¶
const ( // DevModeRiskAcceptanceV1 is the required explicit acknowledgement token // for non-local/non-dev-like DevMode usage. DevModeRiskAcceptanceV1 = "I_UNDERSTAND_DEV_MODE_RISK_V1" // TrustSessionIDRiskAcceptanceV1 is the required explicit acknowledgement token // for non-Dev AuthResumePolicyTrustSessionID configuration. TrustSessionIDRiskAcceptanceV1 = "I_UNDERSTAND_TRUST_SESSION_ID_RISK_V1" // UnsafeRawHTMLRiskAcceptanceV1 is the required explicit acknowledgement token // for non-dev raw HTML sanitization bypass. UnsafeRawHTMLRiskAcceptanceV1 = "I_UNDERSTAND_UNSAFE_RAW_HTML_RISK_V1" // InsecureModuleOriginsRiskAcceptanceV1 is the required explicit acknowledgement token // for non-dev insecure cross-origin module origins. InsecureModuleOriginsRiskAcceptanceV1 = "I_UNDERSTAND_INSECURE_MODULE_ORIGINS_RISK_V1" // HeuristicEventPayloadRiskAcceptanceV1 is the required explicit acknowledgement // token for non-dev heuristic-only hook/island/WASM payload handling. HeuristicEventPayloadRiskAcceptanceV1 = "I_UNDERSTAND_HEURISTIC_EVENT_PAYLOAD_RISK_V1" )
const ( // DefaultLivenessPath is the built-in liveness probe endpoint. DefaultLivenessPath = "/_vango/health/live" // DefaultReadinessPath is the built-in readiness probe endpoint. DefaultReadinessPath = "/_vango/health/ready" )
const CSPHeaderName = "Content-Security-Policy"
CSPHeaderName is the header for Content Security Policy.
const CSPReportOnlyHeaderName = "Content-Security-Policy-Report-Only"
CSPReportOnlyHeaderName is the header for report-only CSP.
const CSRFCookieName = "__vango_csrf"
CSRFCookieName is the name of the CSRF cookie.
const CSRFHeaderName = "X-CSRF-Token"
CSRFHeaderName is the default header used for CSRF tokens on HTTP requests.
const DefaultAuthSessionKey = auth.SessionKey
DefaultAuthSessionKey is the conventional session key for an authenticated user. The vango/pkg/auth helpers use this key, and server.Ctx.User() falls back to it.
const RuntimeLogEventAttr = "event"
const RuntimeLogEventCatalogSchemaVersion = "vango.runtime_log_events.v1"
RuntimeLogEventCatalogSchemaVersion is the schema version for RuntimeLogEventCatalog.
Variables ¶
var ( // ErrSessionClosed is returned when an operation is attempted on a closed session. ErrSessionClosed = errors.New("server: session closed") // ErrSessionNotFound is returned when a session ID does not exist. ErrSessionNotFound = errors.New("server: session not found") // ErrHandlerNotFound is returned when no handler is registered for an HID. ErrHandlerNotFound = errors.New("server: handler not found") // ErrEventQueueFull is returned when the event queue is full and an event is dropped. ErrEventQueueFull = errors.New("server: event queue full") // ErrInvalidHandshake is returned when the WebSocket handshake fails. ErrInvalidHandshake = errors.New("server: invalid handshake") // ErrMaxSessionsReached is returned when the maximum number of sessions is reached. ErrMaxSessionsReached = errors.New("server: max sessions reached") // ErrTooManySessionsFromIP is returned when the per-IP session limit is exceeded. ErrTooManySessionsFromIP = errors.New("server: too many sessions from this IP address") // ErrTooManyConcurrentHandshakes is returned when the global pre-auth handshake // concurrency limit is exceeded. ErrTooManyConcurrentHandshakes = errors.New("server: too many concurrent handshakes") // ErrTooManyConcurrentHandshakesFromIP is returned when the per-IP pre-auth // handshake concurrency limit is exceeded. ErrTooManyConcurrentHandshakesFromIP = errors.New("server: too many concurrent handshakes from this IP address") // ErrInvalidCSRF is returned when CSRF token validation fails. ErrInvalidCSRF = errors.New("server: invalid CSRF token") // ErrSecureCookiesRequired is returned when secure cookies are required but the request is not secure. ErrSecureCookiesRequired = errors.New("server: secure cookies require HTTPS or trusted proxy headers") // ErrSessionExpired is returned when a session has expired due to inactivity. ErrSessionExpired = errors.New("server: session expired") // ErrConnectionClosed is returned when the WebSocket connection is closed. ErrConnectionClosed = errors.New("server: connection closed") // ErrWriteTimeout is returned when a write operation times out. ErrWriteTimeout = errors.New("server: write timeout") // ErrReadTimeout is returned when a read operation times out. ErrReadTimeout = errors.New("server: read timeout") // ErrAuthCheckPanicked is returned when an AuthCheck provider panics. // The panic is recovered and surfaced as an error so it cannot terminate // the server process. ErrAuthCheckPanicked = errors.New("server: auth check panicked") // ErrNoConnection is returned when attempting to send on a nil connection. ErrNoConnection = errors.New("server: no connection") )
Sentinel errors for common session and server error conditions.
var ErrForbidden = auth.ErrForbidden
ErrForbidden is returned when authentication is present but insufficient. This is defined in the auth package and re-exported here for convenience.
ErrUnauthorized is returned when authentication is required but not present. This is defined in the auth package and re-exported here for convenience.
Functions ¶
func AllowAllOriginsCheck ¶
AllowAllOriginsCheck allows any origin. Use only in development.
func AllowedOriginsCheck ¶
AllowedOriginsCheck validates that the request Origin matches an allowlist. Origins are normalized by scheme + lowercase host + effective port (default port omitted/explicit forms are equivalent) and must not include path, query, or fragment. Requests without an Origin header are allowed.
func BootstrapConfigFromContext ¶ added in v0.0.3
BootstrapConfigFromContext retrieves the thin-client bootstrap payload from a stdlib context.
func BuildCSP ¶
func BuildCSP(opts CSPOptions) string
BuildCSP constructs a policy string from options.
func CSRFCtxToken ¶
CSRFCtxToken retrieves the CSRF token from the request-scoped context values.
func CanonicalizePath ¶
CanonicalizePath normalizes a URL path for navigation.
func CurrentMemoryUsage ¶
func CurrentMemoryUsage() int64
CurrentMemoryUsage returns the current heap memory usage in bytes.
func EstimateAnyMemory ¶
EstimateAnyMemory approximates the memory usage of a value. It is depth-limited to avoid runaway recursion on complex graphs.
func EstimateMapMemory ¶
EstimateMapMemory estimates memory usage of a map.
func EstimateSliceMemory ¶
EstimateSliceMemory estimates memory usage of a slice.
func EstimateStringMemory ¶
EstimateStringMemory estimates memory usage of a string.
func HostedSurfaceProofSignature ¶ added in v0.2.0
func HostedSurfaceProofSignature(secret []byte, method, requestURI string, info surface.Info, capabilities, timestamp, nonce string) string
HostedSurfaceProofSignature returns the lowercase hex HMAC used by native hosted surfaces and HostedSurfaceVerifier.
func InspectState ¶
func InspectState(session *Session) vruntime.StateInspection
InspectState returns inspection data for a session.
func IsAuthError ¶
IsAuthError returns true if the error is an authentication or authorization error.
func LoggerForEvent ¶
LoggerForEvent returns a context-rich logger for an event. If ctx.Logger() is present, it is returned as-is; otherwise, it is enriched with available session/user/event details.
func NormalizeAuthCheckConfig ¶
func NormalizeAuthCheckConfig(cfg *AuthCheckConfig)
NormalizeAuthCheckConfig applies defaults to an auth check config in-place.
func RunRouteMiddleware ¶
func RunRouteMiddleware(ctx Ctx, middleware []RouteMiddleware, final func() error) (ranFinal bool, err error)
RunRouteMiddleware executes a route middleware chain and then calls final.
Middleware can short-circuit by returning nil without calling next. In that case ranFinal will be false and err will be nil.
func RuntimeUnsafePermissionsFromContext ¶ added in v0.2.0
func RuntimeUnsafePermissionsFromContext(ctx context.Context) (vdom.RuntimeUnsafePermissions, bool)
RuntimeUnsafePermissionsFromContext retrieves validated runtime unsafe permissions from a stdlib context.
func SameOriginCheck ¶
SameOriginCheck validates that the WebSocket request origin matches the host. This is the secure default for CheckOrigin. SECURITY: Uses strict URL/authority parsing, case-insensitive host comparison, and default-port normalization while keeping scheme checks strict (http != https).
func SetCSRFCtxToken ¶
SetCSRFCtxToken stores the CSRF token in the request-scoped context values. This allows SSR handlers to render CSRF-protected forms.
func SetGlobalPrefetchLimit ¶
func SetGlobalPrefetchLimit(limit int)
SetGlobalPrefetchLimit sets the global prefetch concurrency limit. Should be called at server startup before any prefetch operations.
func ShellBridgeFromContext ¶ added in v0.0.3
ShellBridgeFromContext retrieves the shell bridge from a stdlib context.
func SurfaceInfoFromContext ¶ added in v0.0.3
SurfaceInfoFromContext retrieves normalized surface metadata from a stdlib context.
func ThinClientHash ¶ added in v0.1.0
func ThinClientHash() string
ThinClientHash returns the current thin-client build hash used for WebSocket handshakes.
func TotalSystemMemory ¶
func TotalSystemMemory() int64
TotalSystemMemory returns the total system memory seen by the Go runtime.
func UserFromContext ¶
UserFromContext retrieves the authenticated user stored by WithUser. Returns nil when no user is present.
func UserFromContextAs ¶ added in v0.1.0
UserFromContextAs retrieves and type-asserts the authenticated user stored by WithUser. It returns the zero value of T and false when no user is present or the value has a different type.
func ValidateExternalRedirectURL ¶
ValidateExternalRedirectURL validates an absolute redirect URL against an allowlist. Returns the canonical URL and true when allowed; otherwise returns ("", false).
func WithBootstrapConfig ¶ added in v0.0.3
WithBootstrapConfig stores the thin-client bootstrap payload in a stdlib context.
func WithRuntimeUnsafePermissions ¶ added in v0.2.0
func WithRuntimeUnsafePermissions(ctx context.Context, perms vdom.RuntimeUnsafePermissions) context.Context
WithRuntimeUnsafePermissions stores validated runtime unsafe permissions in a stdlib context.
func WithShellBridge ¶ added in v0.0.3
WithShellBridge stores a shell bridge in a stdlib context.
func WithSurfaceInfo ¶ added in v0.0.3
WithSurfaceInfo stores normalized surface metadata in a stdlib context.
Types ¶
type AppliedNavigateOptions ¶
type AppliedNavigateOptions struct {
}
AppliedNavigateOptions is the concrete, inspected result of applying NavigateOption closures. This is useful in contexts outside server.ctx (e.g. SSR adapters) where NavigateOption is opaque.
func ApplyNavigateOptions ¶
func ApplyNavigateOptions(opts ...NavigateOption) AppliedNavigateOptions
ApplyNavigateOptions applies NavigateOption closures to the default option set.
func BuildNavigateURL ¶
func BuildNavigateURL(path string, opts ...NavigateOption) (fullPath string, applied AppliedNavigateOptions)
BuildNavigateURL builds the final navigation URL by applying NavigateOption params and validating the resulting path against the navigation security rules.
Returns an empty string if the path is invalid (e.g. absolute URL).
type AuthCheckConfig ¶
type AuthCheckConfig struct {
// Interval between active checks (0 disables periodic checks).
Interval time.Duration
// Timeout caps how long a Check may take.
// Default: 5 seconds.
Timeout time.Duration
// FailureMode controls transient failure handling.
// Default: FailOpenWithGrace.
FailureMode AuthFailureMode
// MaxStale caps how long a session may go without a successful active check
// when FailureMode is fail-open.
// Default: 15 minutes.
MaxStale time.Duration
// Check is called periodically and on-demand.
// This runs off the session loop; do not mutate session state directly.
// Panics are recovered and treated as check failures.
Check func(ctx context.Context, p auth.Principal) error
// OnExpired defines what happens when auth fails.
OnExpired AuthExpiredConfig
}
AuthCheckConfig configures periodic active revalidation.
type AuthExpiredAction ¶
type AuthExpiredAction int
AuthExpiredAction defines what happens when auth expires.
const ( // ForceReload triggers browser reload (re-enters HTTP pipeline). ForceReload AuthExpiredAction = iota NavigateTo // Custom invokes a caller-provided handler. Custom )
type AuthExpiredConfig ¶
type AuthExpiredConfig struct {
Action AuthExpiredAction
Path string
Reason AuthExpiredReason
Handler func(s *Session)
}
AuthExpiredConfig defines behavior when auth expires.
type AuthExpiredReason ¶
type AuthExpiredReason int
AuthExpiredReason provides structured context for auth expiry.
const ( AuthExpiredUnknown AuthExpiredReason = iota AuthExpiredPassiveExpiry AuthExpiredResumeRehydrateFailed AuthExpiredActiveRevalidateFailed AuthExpiredOnDemandRevalidateFailed AuthExpiredNoRevalidationHooks // No authFunc/OnSessionResume configured for authenticated session AuthExpiredResumeIdentityMismatch )
func (AuthExpiredReason) String ¶
func (r AuthExpiredReason) String() string
type AuthFailureMode ¶
type AuthFailureMode int
AuthFailureMode controls what happens when active checks fail.
const ( // FailOpenWithGrace keeps the session alive on transient failures. // Default: availability-first, bounded by MaxStale. FailOpenWithGrace AuthFailureMode = iota // FailClosed expires the session on any check failure. FailClosed )
type AuthResumePolicy ¶
type AuthResumePolicy int
AuthResumePolicy controls how authenticated session resumes are validated.
const ( // AuthResumePolicyStrict (default) requires authFunc or OnSessionResume to be // configured for authenticated sessions to resume. If neither is set and the // session was previously authenticated, resume is rejected. // // This is the secure default: session ID alone is NOT sufficient to resume // an authenticated session. The original auth (cookie, token, etc.) must be // revalidated on every resume. // // IMPORTANT: Simply configuring OnSessionResume is not sufficient for security. // The hook MUST actually revalidate authentication and call auth.Set() to // rehydrate the user. In strict mode, resume clears runtime auth projection // before OnSessionResume when authFunc is not configured, so a no-op hook // is rejected as unauthenticated resume. See documentation for proper implementation. AuthResumePolicyStrict AuthResumePolicy = iota // AuthResumePolicyTrustSessionID treats the session ID as a credential. // Authenticated sessions can resume without revalidation if the session // data is still in server memory. // // IMPORTANT: This policy ONLY applies to in-memory session resume. For sessions // restored from persistence (Redis, NATS, etc.), the user object is not serialized, // so the ghost auth check will still reject resume unless authFunc or OnSessionResume // rehydrates the user. This is by design - persisted sessions should always // revalidate auth on restore. // // SECURITY WARNING: Use this policy ONLY if ALL of the following are true: // - You generate cryptographically strong session IDs (Vango does this) // - Session IDs are NEVER logged, exposed in URLs visible to users, or // accessible to client-side JavaScript beyond the thin client // - Runtime logs in non-debug mode use fingerprinted session IDs (sidfp:...); // raw IDs are only emitted when DebugMode=true // - You accept the risk that a leaked session ID grants authenticated access // - You have additional protections (short ResumeWindow, IP binding, etc.) // // This policy is appropriate for: // - Internal tools with trusted networks // - Apps where session continuity UX outweighs security concerns // - Apps with very short ResumeWindow (< 10 seconds) // // IMPORTANT: This policy weakens "logout elsewhere" and revocation semantics. // A detached in-memory session may still resume with only the session ID until // ResumeWindow expires or the session is evicted/closed. AuthResumePolicyTrustSessionID )
func (AuthResumePolicy) IsValid ¶
func (p AuthResumePolicy) IsValid() bool
IsValid returns true if the policy is a known valid value.
func (AuthResumePolicy) String ¶
func (p AuthResumePolicy) String() string
String returns the string representation of the auth resume policy.
type BudgetExceededMode ¶
type BudgetExceededMode int
BudgetExceededMode determines behavior when a storm budget is exceeded.
const ( // BudgetThrottle drops excess operations silently (default). // Operations that exceed the budget are not executed. BudgetThrottle BudgetExceededMode = iota // BudgetTripBreaker pauses effect execution until cleared. // Like a circuit breaker, stops all effect processing until reset. BudgetTripBreaker )
type CSPOptions ¶
type CSPOptions struct {
ReportOnly bool
AllowInlineStyles bool
AllowInlineScripts bool
AllowDataImages bool
AllowHTTPSImages bool
// IncludeWSS allows scheme-wide secure websocket egress in connect-src.
// Prefer exact websocket origins via AdditionalConnectSrc when possible.
IncludeWSS bool
// IncludeWS allows scheme-wide insecure websocket egress in connect-src.
// Prefer exact websocket origins via AdditionalConnectSrc when possible.
IncludeWS bool
AdditionalConnectSrc []string
AdditionalScriptSrc []string
AdditionalStyleSrc []string
AdditionalImgSrc []string
AdditionalFontSrc []string
AdditionalDirectives []string
}
CSPOptions configures the CSP middleware helper.
func DefaultCSPOptions ¶
func DefaultCSPOptions() CSPOptions
DefaultCSPOptions returns a strict CSPOptions baseline. App-level security header generation may append the exact runtime websocket origin separately when needed.
func HardenedCSPOptions ¶
func HardenedCSPOptions() CSPOptions
HardenedCSPOptions returns a stricter CSP profile for production hardening. It disables inline styles while preserving other defaults.
type CSRFError ¶
type CSRFError struct {
Reason string
}
CSRFError represents an HTTP CSRF validation error.
func (CSRFError) StatusCode ¶
type Component ¶
type Component interface {
// Render returns the VNode tree for this component.
Render() *vdom.VNode
}
Component is the interface for renderable components. Components produce VNode trees that represent the UI.
type ComponentInstance ¶
type ComponentInstance struct {
// InstanceID is the unique instance identifier.
InstanceID string
// Component is the component being rendered.
Component Component
// HID is the hydration ID of the root element.
HID string
// Owner manages signal ownership for this component.
Owner *vango.Owner
// Parent is the parent component instance (nil for root).
Parent *ComponentInstance
// Children are child component instances.
Children []*ComponentInstance
// Props are the current props passed to the component.
Props map[string]any
// contains filtered or unexported fields
}
ComponentInstance represents a mounted component with its state. It holds the component's reactive ownership, tracking, and rendering context.
func (*ComponentInstance) AddChild ¶
func (c *ComponentInstance) AddChild(child *ComponentInstance)
AddChild adds a child component instance.
func (*ComponentInstance) ClearDirty ¶
func (c *ComponentInstance) ClearDirty()
ClearDirty clears the dirty flag.
func (*ComponentInstance) Dispose ¶
func (c *ComponentInstance) Dispose()
Dispose disposes the component instance and all its children.
func (*ComponentInstance) GetProp ¶
func (c *ComponentInstance) GetProp(key string) any
GetProp gets a prop value.
func (*ComponentInstance) ID ¶
func (c *ComponentInstance) ID() uint64
ID implements vango.Listener and returns a globally unique identifier.
func (*ComponentInstance) IsDirty ¶
func (c *ComponentInstance) IsDirty() bool
IsDirty returns whether the component needs re-rendering.
func (*ComponentInstance) LastTree ¶
func (c *ComponentInstance) LastTree() *vdom.VNode
LastTree returns the last rendered VNode tree.
func (*ComponentInstance) ListKeyPath ¶
func (c *ComponentInstance) ListKeyPath() []string
ListKeyPath returns a copy of the list key path for this instance.
func (*ComponentInstance) MarkDirty ¶
func (c *ComponentInstance) MarkDirty()
MarkDirty marks the component as needing re-render.
func (*ComponentInstance) MemoryUsage ¶
func (c *ComponentInstance) MemoryUsage() int64
MemoryUsage returns an estimate of memory used by this instance.
func (*ComponentInstance) RemoveChild ¶
func (c *ComponentInstance) RemoveChild(child *ComponentInstance)
RemoveChild removes a child component instance.
func (*ComponentInstance) Render ¶
func (c *ComponentInstance) Render() *vdom.VNode
Render renders the component and returns the VNode tree. It sets up the tracking context so signals are properly tracked, and sets the runtime context so UseCtx() works during render.
func (*ComponentInstance) Session ¶
func (c *ComponentInstance) Session() *Session
Session returns the owning session.
func (*ComponentInstance) SetLastTree ¶
func (c *ComponentInstance) SetLastTree(tree *vdom.VNode)
SetLastTree sets the last rendered tree (used after diffing).
func (*ComponentInstance) SetProp ¶
func (c *ComponentInstance) SetProp(key string, value any)
SetProp sets a prop value.
func (*ComponentInstance) TrackDependency ¶
func (c *ComponentInstance) TrackDependency(dep vango.Dependency)
type CookieOption ¶
type CookieOption func(*CookiePolicyOptions)
CookieOption configures cookie policy application.
func WithCookieHTTPOnly ¶
func WithCookieHTTPOnly(enabled bool) CookieOption
WithCookieHTTPOnly overrides the default HttpOnly behavior for a cookie.
type CookiePolicy ¶
type CookiePolicy struct {
// contains filtered or unexported fields
}
CookiePolicy enforces cookie defaults and security requirements.
func (*CookiePolicy) Apply ¶
func (p *CookiePolicy) Apply(r *http.Request, cookie *http.Cookie, opts ...CookieOption) (*http.Cookie, error)
Apply applies cookie defaults and enforces SecureCookies requirements. Returns ErrSecureCookiesRequired if secure cookies are enabled but the request is not secure.
func (*CookiePolicy) ApplyCookiePolicy ¶
func (p *CookiePolicy) ApplyCookiePolicy(r *http.Request, cookie *http.Cookie) (*http.Cookie, error)
ApplyCookiePolicy applies defaults without overrides. This is a compatibility hook for external packages that accept a generic cookie policy interface.
func (*CookiePolicy) IsRequestSecure ¶
func (p *CookiePolicy) IsRequestSecure(r *http.Request) bool
IsRequestSecure reports whether the request is considered secure (HTTPS), honoring trusted proxy headers when configured.
type CookiePolicyOptions ¶
type CookiePolicyOptions struct {
// contains filtered or unexported fields
}
CookiePolicyOptions configures optional overrides for cookie policy.
type Ctx ¶
type Ctx interface {
// Request returns the underlying HTTP request.
Request() *http.Request
// Path returns the URL path.
Path() string
// Method returns the HTTP method.
Method() string
// Query returns the URL query parameters as url.Values.
Query() url.Values
// QueryParam returns a single query parameter value by key.
// Returns an empty string if the key is not present.
QueryParam(key string) string
// Param returns a route parameter by key.
Param(key string) string
// Header returns a request header value.
Header(key string) string
// Cookie returns a cookie by name.
Cookie(name string) (*http.Cookie, error)
// Status sets the HTTP response status code.
Status(code int)
// Redirect redirects to the given URL with the given status code.
// Redirects are relative-only and reject absolute URLs.
Redirect(url string, code int)
// RedirectExternal redirects to an absolute URL with the given status code.
// External redirects require an explicit allowlist.
RedirectExternal(url string, code int)
// SetHeader sets a response header.
SetHeader(key, value string)
// SetCookie sets a response cookie.
SetCookie(cookie *http.Cookie)
// SetCookieStrict sets a response cookie with enforced security defaults.
// Returns ErrSecureCookiesRequired if secure cookies are enabled and the request is not secure.
SetCookieStrict(cookie *http.Cookie, opts ...CookieOption) error
// Session returns the WebSocket session (nil for SSR-only requests).
Session() vango.Session
// Surface returns normalized metadata for the current connected surface.
Surface() surface.Info
// Shell returns the shell bridge for the current surface.
Shell() shell.Bridge
// AuthSession returns the WebSocket session as an auth.Session interface.
// This allows auth helpers to persist to the session without importing server.
AuthSession() auth.Session
// User returns the authenticated user (set by auth middleware).
User() any
// SetUser sets the authenticated user.
SetUser(user any)
// Principal returns the authenticated principal, if any.
Principal() (auth.Principal, bool)
// MustPrincipal returns the principal or panics if not set.
MustPrincipal() auth.Principal
// RevalidateAuth forces an immediate active check if configured.
// Returns any error from the check, including ErrAuthCheckPanicked when
// the configured check panics.
// If authenticated session projection exists but principal is missing,
// this fails closed with auth.ErrSessionExpired.
RevalidateAuth() error
// BroadcastAuthLogout notifies other tabs that auth was cleared and they should reload.
BroadcastAuthLogout()
// Logger returns the request-scoped logger.
Logger() *slog.Logger
// Done returns a channel that's closed when the request is canceled.
// It does not represent the SSR page render budget.
Done() <-chan struct{}
// SetValue stores a request-scoped value.
// These values are only available for the duration of the current event/request.
SetValue(key, value any)
// Value retrieves a request-scoped value.
Value(key any) any
// Emit dispatches a custom event to the client.
// The event will be dispatched as a CustomEvent with the given name and detail.
// Use this for notifications, toast messages, analytics, etc.
Emit(name string, data any)
// Focus moves browser focus to a mounted element with the given DOM id.
// It is a live-session side effect and is ignored during SSR-only requests.
Focus(id string)
// Blur removes browser focus from a mounted element with the given DOM id.
// It is a live-session side effect and is ignored during SSR-only requests.
Blur(id string)
// FocusHID moves browser focus to a mounted element by Vango HID.
// Prefer Focus with a stable DOM id in application code; use FocusHID when
// intentionally targeting the current event element via ctx.Event().HID.
FocusHID(hid string)
// BlurHID removes browser focus from a mounted element by Vango HID.
// Prefer Blur with a stable DOM id in application code; use BlurHID when
// intentionally targeting the current event element via ctx.Event().HID.
BlurHID(hid string)
// Dispatch queues a function to run on the session's event loop.
// This is safe to call from any goroutine and is the correct way to
// update signals from asynchronous operations (database calls, timers, etc.).
//
// The function will be executed synchronously on the event loop, ensuring
// signal writes are properly serialized. After the function completes,
// pending effects will run and dirty components will re-render.
//
// Example:
//
// go func() {
// user, err := db.Users.FindByID(ctx.StdContext(), id)
// ctx.Dispatch(func() {
// if err != nil {
// errorSignal.Set(err)
// } else {
// userSignal.Set(user)
// }
// })
// }()
//
// IMPORTANT: This method MUST be safe to call from any goroutine.
Dispatch(fn func())
// Unlike Redirect(), this updates the browser URL and re-renders the page
// without a full HTTP redirect. The navigation is queued and processed
// after the current handler completes.
//
// Options can be provided to customize behavior:
// - WithReplace() - replace current history entry instead of pushing
// - WithNavigateParams(map[string]any) - add query parameters to the URL
// - WithoutScroll() - disable scrolling to top after navigation
//
// Example:
//
// func handleSave(ctx vango.Ctx) {
// project := saveProject()
// ctx.Navigate("/projects/" + project.ID)
// }
//
// For HTTP-only requests (SSR without WebSocket), this falls back to
// an HTTP redirect.
Navigate(path string, opts ...NavigateOption)
// StdContext returns the standard library context with trace propagation.
// Use this when calling external services or database drivers.
//
// Example:
// row := db.QueryRowContext(ctx.StdContext(), "SELECT * FROM users WHERE id = $1", userID)
// req, _ := http.NewRequestWithContext(ctx.StdContext(), "GET", url, nil)
//
// The context includes any trace spans injected by middleware (e.g., OpenTelemetry).
// During SSR, it may also carry the configured page render deadline.
StdContext() context.Context
// WithStdContext updates the standard context used by StdContext().
// This is used by middleware to inject trace spans for downstream calls.
//
// This is typically called by observability middleware:
// spanCtx, span := tracer.Start(ctx.StdContext(), "operation")
// defer span.End()
// ctx = ctx.WithStdContext(spanCtx)
// return next()
WithStdContext(stdCtx context.Context) Ctx
// Event returns the current WebSocket event being processed.
// Returns nil for HTTP-only requests (SSR).
//
// Example:
// if event := ctx.Event(); event != nil {
// log.Printf("Processing %s event on %s", event.Type, event.HID)
// }
Event() *Event
// PatchCount returns the number of patches sent during this request.
// This is updated after each render cycle.
PatchCount() int
// AddPatchCount increments the patch count for this request.
// Called internally by the render system.
AddPatchCount(count int)
// StormBudget returns the storm budget checker for this session.
// Used by primitives (Action, Resource, GoLatest) to check rate limits.
// Returns nil if storm budgets are not configured.
//
// See SPEC_ADDENDUM.md §A.4 for storm budget configuration.
StormBudget() vango.StormBudgetChecker
// Mode returns the current render mode as int.
// Returns 0 (ModeNormal) for regular requests, 1 (ModePrefetch) during prefetch.
//
// Primitives like Effect, Interval, and signal.Set() check this to
// enforce read-only behavior during prefetch:
// - ModePrefetch (1): Signal writes are dropped, effects are no-ops
// - ModeNormal (0): All operations proceed normally
//
// This method implements vango.PrefetchModeChecker interface.
//
// Example (for primitive implementations):
// if ctx := UseCtx(); ctx != nil && ctx.Mode() == 1 {
// if DevMode { panic("signal write forbidden in prefetch") }
// return // drop in prod
// }
Mode() int
// Asset resolves a source asset path to its fingerprinted path.
// Returns the original path if no manifest is configured or the asset is not found.
//
// This enables cache-busting via content-hashed filenames while keeping
// templates simple:
//
// Example:
//
// <script src={ctx.Asset("vango.js")}></script>
// // In dev: "/public/vango.js"
// // In prod: "/public/vango.a1b2c3d4.min.js"
Asset(source string) string
}
Ctx provides access to request data within components. It is passed to route handlers and can be used to access the request, session, and response control methods.
func NewTestContext ¶
NewTestContext creates a context for testing with the given session. This allows testing components that require a valid context.
func NewTestContextWithDebug ¶
NewTestContextWithDebug creates a test context with an explicit debug flag.
type Event ¶
type Event struct {
// Seq is the sequence number of the event.
Seq uint64
// Type is the type of event (click, input, submit, etc.).
Type protocol.EventType
// HID is the hydration ID of the target element.
HID string
// Payload contains type-specific event data.
Payload any
// Session is the session that received the event.
Session *Session
// Time is when the event was received by the server.
Time time.Time
// contains filtered or unexported fields
}
Event represents a decoded event from the client with runtime context.
func (*Event) TypeString ¶
TypeString returns the string representation of the event type. Used for logging and tracing.
type EventRateLimiter ¶
type EventRateLimiter struct {
// contains filtered or unexported fields
}
EventRateLimiter implements token bucket rate limiting for events.
func (*EventRateLimiter) Allow ¶
func (r *EventRateLimiter) Allow() bool
Allow returns true if the event is allowed.
type FormData ¶
type FormData struct {
// contains filtered or unexported fields
}
FormData represents submitted form data.
type FuncComponent ¶
FuncComponent wraps a render function as a Component.
func (FuncComponent) Render ¶
func (f FuncComponent) Render() *vdom.VNode
Render calls the wrapped function.
type Handler ¶
type Handler func(event *Event)
Handler is the internal event handler function type. It receives a decoded event and processes it.
type HandlerError ¶
HandlerError wraps a panic that occurred in an event handler.
func NewHandlerError ¶
func NewHandlerError(sessionID, hid, eventType string, panicVal any, stack []byte) *HandlerError
NewHandlerError creates a new HandlerError.
type HealthCheck ¶ added in v0.2.0
HealthCheck is called by built-in liveness/readiness endpoints. Return nil for healthy/ready; return an error to make the endpoint return 503.
type HookEvent ¶
HookEvent represents a client hook event.
type HostedSurfaceAllowedSurface ¶ added in v0.2.0
HostedSurfaceAllowedSurface identifies a native surface allowed to submit a hosted surface proof.
type HostedSurfaceIdentity ¶ added in v0.2.0
HostedSurfaceIdentity is trusted hosted surface metadata accepted by the server. Surface.Capabilities remains the canonical shell capability manifest.
func ParseHostedSurfaceRequestHints ¶ added in v0.2.0
func ParseHostedSurfaceRequestHints(r *http.Request) (*HostedSurfaceIdentity, bool)
ParseHostedSurfaceRequestHints extracts adapter-private hosted surface hints from request headers or query parameters. The returned data is untrusted.
type HostedSurfaceVerifierConfig ¶ added in v0.2.0
type HostedSurfaceVerifierConfig struct {
// ProofSecret verifies the native host's X-Vango-Surface-Proof-* headers.
// Use at least 32 random bytes and keep it separate from the server-only
// HostedSurfaceTokenSecret.
ProofSecret []byte
// AllowedOrigins are the trusted hosted web origins that may receive native
// hosted surface bootstrap. Entries must be origins, for example
// "https://app.example.com".
AllowedOrigins []string
// AllowedSurfaces restricts which native hosted surfaces may assert trust.
// Defaults to the first-party Vango native hosts: macOS desktop and iOS mobile.
AllowedSurfaces []HostedSurfaceAllowedSurface
// MaxClockSkew bounds signed proof freshness. Defaults to 5 minutes.
MaxClockSkew time.Duration
// Now is injectable for tests. Defaults to time.Now.
Now func() time.Time
}
HostedSurfaceVerifierConfig configures verification of signed native hosted surface requests before the server enables hosted shell/bootstrap behavior.
type HostedSurfaceVerifyFunc ¶ added in v0.2.0
type HostedSurfaceVerifyFunc func(r *http.Request) (*HostedSurfaceIdentity, error)
HostedSurfaceVerifyFunc validates hosted surface identity for an incoming page request. Returning (nil, nil) means the request should be treated as an ordinary web surface.
func NewMacOSHostedSurfaceVerifier ¶ added in v0.2.0
func NewMacOSHostedSurfaceVerifier(cfg HostedSurfaceVerifierConfig) (HostedSurfaceVerifyFunc, error)
NewMacOSHostedSurfaceVerifier returns a verifier for first-party hosted macOS desktop requests signed by the native host.
func NewNativeHostedSurfaceVerifier ¶ added in v0.2.0
func NewNativeHostedSurfaceVerifier(cfg HostedSurfaceVerifierConfig) (HostedSurfaceVerifyFunc, error)
NewNativeHostedSurfaceVerifier returns a verifier for first-party native hosted requests signed by the native host.
type InstancePath ¶
InstancePath uniquely identifies a primitive instance.
func ComputeInstancePath ¶
func ComputeInstancePath(session *Session, component *ComponentInstance, stableID string) InstancePath
ComputeInstancePath builds the full path for a primitive.
func (InstancePath) String ¶
func (p InstancePath) String() string
type KeyboardEvent ¶
KeyboardEvent represents a keyboard event with key and modifiers.
type LayoutHandler ¶
LayoutHandler wraps child content in a layout.
type ManagerStats ¶
type ManagerStats struct {
Active int
TotalCreated uint64
TotalClosed uint64
Peak int
TotalMemory int64
}
ManagerStats contains aggregated session manager statistics.
type MemoryMonitor ¶
type MemoryMonitor struct {
// contains filtered or unexported fields
}
MemoryMonitor monitors system memory and triggers actions when thresholds are exceeded.
func NewMemoryMonitor ¶
func NewMemoryMonitor(config *MemoryMonitorConfig) *MemoryMonitor
NewMemoryMonitor creates a new memory monitor.
func (*MemoryMonitor) ForceCheck ¶
func (m *MemoryMonitor) ForceCheck()
ForceCheck performs an immediate memory check.
func (*MemoryMonitor) Pause ¶
func (m *MemoryMonitor) Pause()
Pause temporarily pauses memory checking.
func (*MemoryMonitor) SetOnHardLimit ¶
func (m *MemoryMonitor) SetOnHardLimit(fn func(current, limit int64))
SetOnHardLimit sets the callback for hard limit breach.
func (*MemoryMonitor) SetOnSoftLimit ¶
func (m *MemoryMonitor) SetOnSoftLimit(fn func(current, limit int64))
SetOnSoftLimit sets the callback for soft limit breach.
type MemoryMonitorConfig ¶
type MemoryMonitorConfig struct {
SoftLimit int64 // Bytes at which to start evicting (default: 80% of system memory)
HardLimit int64 // Bytes at which to aggressively evict (default: 90% of system memory)
CheckInterval time.Duration // How often to check memory (default: 10s)
GCCooldown time.Duration // Minimum time between forced GCs (default: 30s)
}
MemoryMonitorConfig configures the memory monitor.
func DefaultMemoryMonitorConfig ¶
func DefaultMemoryMonitorConfig() *MemoryMonitorConfig
DefaultMemoryMonitorConfig returns sensible defaults.
type MemoryPressureLevel ¶
type MemoryPressureLevel int
MemoryPressureLevel indicates the current memory pressure.
const ( MemoryPressureNone MemoryPressureLevel = iota // Below soft limit MemoryPressureLow // Between soft and hard limit MemoryPressureHigh // Above hard limit MemoryPressureCritical // Near OOM )
func GetMemoryPressureLevel ¶
func GetMemoryPressureLevel(softLimit, hardLimit int64) MemoryPressureLevel
GetMemoryPressureLevel returns the current memory pressure level.
func (MemoryPressureLevel) String ¶
func (l MemoryPressureLevel) String() string
String returns the string representation of the pressure level.
type MemoryStats ¶
type MemoryStats struct {
HeapAlloc int64 // Bytes allocated on heap
HeapSys int64 // Bytes obtained from OS for heap
HeapIdle int64 // Bytes in idle spans
HeapInuse int64 // Bytes in non-idle spans
HeapReleased int64 // Bytes released to OS
StackInuse int64 // Bytes used by stack
NumGC uint32 // Number of completed GC cycles
LastGC time.Time // Time of last GC
GCPauseTotal time.Duration // Total GC pause time
}
MemoryStats returns detailed memory statistics.
func GetMemoryStats ¶
func GetMemoryStats() *MemoryStats
GetMemoryStats returns current memory statistics.
type MetricsCollector ¶
type MetricsCollector struct {
// contains filtered or unexported fields
}
MetricsCollector collects and aggregates metrics over time.
func NewMetricsCollector ¶
func NewMetricsCollector() *MetricsCollector
NewMetricsCollector creates a new MetricsCollector.
func (*MetricsCollector) RecordActionDuration ¶
func (m *MetricsCollector) RecordActionDuration(action string, ms int64)
RecordActionDuration records action duration.
func (*MetricsCollector) RecordActionError ¶
func (m *MetricsCollector) RecordActionError(action string)
RecordActionError records an action error.
func (*MetricsCollector) RecordBytesReceived ¶
func (m *MetricsCollector) RecordBytesReceived(n int)
RecordBytesReceived records bytes received.
func (*MetricsCollector) RecordBytesSent ¶
func (m *MetricsCollector) RecordBytesSent(n int)
RecordBytesSent records bytes sent.
func (*MetricsCollector) RecordColdDeployAck ¶
func (m *MetricsCollector) RecordColdDeployAck(source string)
RecordColdDeployAck records a cold deploy acknowledgment.
func (*MetricsCollector) RecordEventDropped ¶
func (m *MetricsCollector) RecordEventDropped()
RecordEventDropped records an event dropped.
func (*MetricsCollector) RecordEventLatency ¶
func (m *MetricsCollector) RecordEventLatency(latencyUs int64)
RecordEventLatency records event processing latency in microseconds.
func (*MetricsCollector) RecordEventProcessed ¶
func (m *MetricsCollector) RecordEventProcessed()
RecordEventProcessed records an event processed.
func (*MetricsCollector) RecordEventReceived ¶
func (m *MetricsCollector) RecordEventReceived()
RecordEventReceived records an event received.
func (*MetricsCollector) RecordHandlerPanic ¶
func (m *MetricsCollector) RecordHandlerPanic()
RecordHandlerPanic records a handler panic.
func (*MetricsCollector) RecordPatchBytes ¶
func (m *MetricsCollector) RecordPatchBytes(route string, bytes int)
RecordPatchBytes records patch bytes by route.
func (*MetricsCollector) RecordPatchMismatch ¶
func (m *MetricsCollector) RecordPatchMismatch(reason string)
RecordPatchMismatch records a patch mismatch by reason.
func (*MetricsCollector) RecordPatchesSent ¶
func (m *MetricsCollector) RecordPatchesSent(count int, bytes int)
RecordPatchesSent records patches sent.
func (*MetricsCollector) RecordPersistBytes ¶
func (m *MetricsCollector) RecordPersistBytes(stableID string, bytes int64)
RecordPersistBytes records bytes written by stable ID.
func (*MetricsCollector) RecordPersistBytesWritten ¶
func (m *MetricsCollector) RecordPersistBytesWritten(primitiveID string, bytes int64)
RecordPersistBytesWritten records bytes successfully written.
func (*MetricsCollector) RecordPersistWriteRejected ¶
func (m *MetricsCollector) RecordPersistWriteRejected(reason string, primitiveID string)
RecordPersistWriteRejected records a rejected persist write.
func (*MetricsCollector) RecordReadError ¶
func (m *MetricsCollector) RecordReadError()
RecordReadError records a read error.
func (*MetricsCollector) RecordResourceDuration ¶
func (m *MetricsCollector) RecordResourceDuration(resource string, ms int64)
RecordResourceDuration records resource duration.
func (*MetricsCollector) RecordResourceError ¶
func (m *MetricsCollector) RecordResourceError(resource string)
RecordResourceError records a resource error.
func (*MetricsCollector) RecordResumeFailure ¶
func (m *MetricsCollector) RecordResumeFailure(reason string)
RecordResumeFailure records a failed resume with a reason.
func (*MetricsCollector) RecordResumeSuccess ¶
func (m *MetricsCollector) RecordResumeSuccess()
RecordResumeSuccess records a successful resume.
func (*MetricsCollector) RecordSchemaMismatch ¶
func (m *MetricsCollector) RecordSchemaMismatch(reason string)
RecordSchemaMismatch records a schema mismatch event.
func (*MetricsCollector) RecordSessionActive ¶
func (m *MetricsCollector) RecordSessionActive(delta int)
RecordSessionActive records an active session delta.
func (*MetricsCollector) RecordSessionDetached ¶
func (m *MetricsCollector) RecordSessionDetached(delta int)
RecordSessionDetached records a detached session delta.
func (*MetricsCollector) RecordSessionPersistBytes ¶
func (m *MetricsCollector) RecordSessionPersistBytes(sessionID string, bytes int64)
RecordSessionPersistBytes records total persisted bytes per session.
func (*MetricsCollector) RecordSignalWriteViolation ¶
func (m *MetricsCollector) RecordSignalWriteViolation(operation, reason string)
RecordSignalWriteViolation records an invalid signal write attempt.
func (*MetricsCollector) RecordWriteError ¶
func (m *MetricsCollector) RecordWriteError()
RecordWriteError records a write error.
func (*MetricsCollector) Snapshot ¶
func (m *MetricsCollector) Snapshot() *ServerMetrics
Snapshot returns current metrics.
type Middleware ¶
Middleware is a function that wraps an HTTP handler.
func CSPHeaderMiddleware ¶
func CSPHeaderMiddleware(policy string, reportOnly bool) Middleware
CSPHeaderMiddleware sets a CSP header with the provided policy string.
func CSPMiddleware ¶
func CSPMiddleware(opts CSPOptions) Middleware
CSPMiddleware sets a Content-Security-Policy header using a default policy with optional tweaks from CSPOptions.
type MouseEvent ¶
type MouseEvent struct {
ClientX int
ClientY int
Button int
CtrlKey bool
ShiftKey bool
AltKey bool
MetaKey bool
}
MouseEvent represents a mouse event with position and modifiers.
type NavigateOption ¶
type NavigateOption func(*navigateOptions)
NavigateOption is a functional option for Navigate.
func WithNavigateParams ¶
func WithNavigateParams(params map[string]any) NavigateOption
WithNavigateParams adds query parameters to the navigation URL.
func WithReplace ¶
func WithReplace() NavigateOption
WithReplace replaces the current history entry instead of pushing.
func WithoutScroll ¶
func WithoutScroll() NavigateOption
WithoutScroll disables scrolling to top after navigation.
type NavigateResult ¶
type NavigateResult struct {
Path string
Matched bool
Patches []vdom.Patch
NavPatch protocol.Patch
Error error
}
NavigateResult contains the result of a navigation operation.
type OriginPolicyMode ¶
type OriginPolicyMode int
OriginPolicyMode describes how WebSocket origins are validated.
const ( OriginPolicyUnset OriginPolicyMode = iota OriginPolicySameOrigin OriginPolicyAllowedOrigins OriginPolicyCustom OriginPolicyAllowAll )
type PageHandler ¶
PageHandler handles a page request, returning a component to render.
type PatchHistory ¶
type PatchHistory struct {
// contains filtered or unexported fields
}
PatchHistory is a thread-safe ring buffer for storing sent patch frames. It supports:
- Fast insertion at head
- Lookup by sequence range for resync
- Garbage collection based on acknowledged sequence
The ring buffer overwrites oldest entries when full, maintaining a sliding window of recent patches that can be replayed if a client misses some.
func NewPatchHistory ¶
func NewPatchHistory(capacity int) *PatchHistory
NewPatchHistory creates a new patch history ring buffer with the given capacity.
func (*PatchHistory) Add ¶
func (h *PatchHistory) Add(seq uint64, frame []byte)
Add stores a patch frame in the buffer. This should be called ONLY after a successful write to the WebSocket. The frame bytes are copied to prevent issues with buffer reuse.
func (*PatchHistory) CanRecover ¶
func (h *PatchHistory) CanRecover(lastSeq uint64) bool
CanRecover checks if the buffer can provide frames to recover from lastSeq. Returns true if all sequences from lastSeq+1 to maxSeq are available.
func (*PatchHistory) Clear ¶
func (h *PatchHistory) Clear()
Clear removes all entries from the buffer. This is useful during session resume when starting fresh.
func (*PatchHistory) Count ¶
func (h *PatchHistory) Count() int
Count returns the number of entries in the buffer.
func (*PatchHistory) GarbageCollect ¶
func (h *PatchHistory) GarbageCollect(ackSeq uint64)
GarbageCollect updates minSeq based on the acknowledged sequence. Entries with sequence <= ackSeq are no longer needed for resync and will be overwritten naturally by the ring buffer.
func (*PatchHistory) GetFrames ¶
func (h *PatchHistory) GetFrames(afterSeq, toSeq uint64) [][]byte
GetFrames returns frames for sequences (afterSeq, toSeq]. Returns nil if any sequence in the requested range is not available. The returned frames are in sequence order, ready to be replayed.
func (*PatchHistory) MaxSeq ¶
func (h *PatchHistory) MaxSeq() uint64
MaxSeq returns the maximum sequence in buffer.
func (*PatchHistory) MemoryUsage ¶
func (h *PatchHistory) MemoryUsage() int64
MemoryUsage estimates the memory used by the patch history, including frame bytes.
func (*PatchHistory) MinSeq ¶
func (h *PatchHistory) MinSeq() uint64
MinSeq returns the minimum recoverable sequence.
type PatchHistoryEntry ¶
type PatchHistoryEntry struct {
Seq uint64 // Patch sequence number
Frame []byte // Pre-encoded FramePatches for fast replay
SentAt time.Time // When the frame was sent
}
PatchHistoryEntry stores a sent patch frame for potential replay.
type PrefetchCache ¶
type PrefetchCache struct {
// contains filtered or unexported fields
}
PrefetchCache is an LRU cache for prefetched route renders. Each session has its own cache instance.
Per Section 8.2:
- Keyed by canonical path
- TTL: 30 seconds (configurable)
- Max entries: 10 (LRU eviction)
func NewPrefetchCache ¶
func NewPrefetchCache(config *PrefetchConfig) *PrefetchCache
NewPrefetchCache creates a new prefetch cache.
func (*PrefetchCache) Delete ¶
func (c *PrefetchCache) Delete(path string)
Delete removes a cached entry.
func (*PrefetchCache) Get ¶
func (c *PrefetchCache) Get(path string) *PrefetchCacheEntry
Get retrieves a cached prefetch result. Returns nil if not found or expired.
func (*PrefetchCache) Len ¶
func (c *PrefetchCache) Len() int
Len returns the number of cached entries.
func (*PrefetchCache) MemoryUsage ¶
func (c *PrefetchCache) MemoryUsage() int64
MemoryUsage estimates the memory used by the prefetch cache.
type PrefetchCacheEntry ¶
type PrefetchCacheEntry struct {
// Tree is the rendered VNode tree
Tree *vdom.VNode
// CreatedAt is when this entry was created
CreatedAt time.Time
// ExpiresAt is when this entry expires
ExpiresAt time.Time
}
PrefetchCacheEntry holds a cached prefetch result.
func (*PrefetchCacheEntry) IsExpired ¶
func (e *PrefetchCacheEntry) IsExpired() bool
IsExpired returns true if the entry has expired.
type PrefetchConfig ¶
type PrefetchConfig struct {
// TTL is how long a prefetched result is valid.
// Default: 30 seconds
TTL time.Duration
// MaxEntries is the maximum number of cached entries per session.
// Uses LRU eviction when exceeded.
// Default: 10
MaxEntries int
// Timeout is the maximum time to wait for a prefetch to complete.
// If exceeded, the prefetch is aborted and result is not cached.
// Default: 100ms
Timeout time.Duration
// RateLimit is the maximum prefetch requests per second per session.
// Excess requests are silently dropped.
// Default: 5
RateLimit float64
// SessionConcurrency is the max simultaneous prefetch evaluations per session.
// Default: 2
SessionConcurrency int
// GlobalConcurrency is the max simultaneous prefetch evaluations globally.
// Default: 50
GlobalConcurrency int
}
PrefetchConfig holds configuration for the prefetch system. These defaults are per Section 8.2-8.3 of the Routing Spec.
func DefaultPrefetchConfig ¶
func DefaultPrefetchConfig() *PrefetchConfig
DefaultPrefetchConfig returns the default prefetch configuration. Per Section 8.2 and 8.3.3 of the Routing Spec.
type PrefetchRateLimiter ¶
type PrefetchRateLimiter struct {
// contains filtered or unexported fields
}
PrefetchRateLimiter implements token bucket rate limiting for prefetch requests. Per Section 8.5:
- Max 5 prefetch requests per second per session
- Excess requests are silently dropped
func NewPrefetchRateLimiter ¶
func NewPrefetchRateLimiter(ratePerSecond float64) *PrefetchRateLimiter
NewPrefetchRateLimiter creates a new rate limiter.
func (*PrefetchRateLimiter) Allow ¶
func (r *PrefetchRateLimiter) Allow() bool
Allow returns true if a prefetch request is allowed. Returns false if rate limit is exceeded (request should be dropped).
type PrefetchSemaphore ¶
type PrefetchSemaphore struct {
// contains filtered or unexported fields
}
PrefetchSemaphore limits concurrent prefetch operations. Used both per-session and globally.
func GlobalPrefetchSemaphore ¶
func GlobalPrefetchSemaphore() *PrefetchSemaphore
GlobalPrefetchSemaphore returns the global prefetch semaphore. Used by sessions to check global concurrency limits.
func NewPrefetchSemaphore ¶
func NewPrefetchSemaphore(limit int) *PrefetchSemaphore
NewPrefetchSemaphore creates a new semaphore with the given limit.
func (*PrefetchSemaphore) Acquire ¶
func (s *PrefetchSemaphore) Acquire() bool
Acquire tries to acquire a slot. Returns true if successful. If the semaphore is full, returns false immediately (non-blocking).
type PrimitiveInfo ¶
type PrimitiveInfo struct {
StableID string
DebugName string
AnchorKey string
Kind string
Class string
Persisted bool
InstancePath string
Primitive any
}
PrimitiveInfo contains inspection data for a registered primitive.
type ProtocolError ¶
ProtocolError represents an error in the binary protocol.
func NewProtocolError ¶
func NewProtocolError(sessionID, op, message string) *ProtocolError
NewProtocolError creates a new ProtocolError.
func (*ProtocolError) Error ¶
func (e *ProtocolError) Error() string
Error returns the error message.
type RenderMode ¶
type RenderMode int
RenderMode indicates the rendering context for a request. This is used by the prefetch system to enforce read-only behavior.
const ( // ModeNormal is the default rendering mode for regular requests. // All operations are allowed. ModeNormal RenderMode = iota // ModePrefetch is used when prefetching a route for caching. // In this mode, side effects are forbidden: // - Signal.Set() panics in dev / drops in prod // - Effect/Interval/Timeout panic in dev / no-op in prod // - SetUser() panics // - Navigate() is ignored // // Per Routing Spec Section 8.3.1, prefetch uses "bounded I/O": // synchronous work is allowed, but no async work may outlive the prefetch. ModePrefetch )
func (RenderMode) String ¶
func (m RenderMode) String() string
String returns a human-readable name for the render mode.
type ResizeEvent ¶
ResizeEvent represents a resize event with dimensions.
type RouteMatch ¶
type RouteMatch interface {
// GetParams returns the extracted route parameters.
GetParams() map[string]string
// GetPageHandler returns the page handler, if any.
GetPageHandler() PageHandler
// GetLayoutHandlers returns the layout handlers in order (root to leaf).
GetLayoutHandlers() []LayoutHandler
// GetMiddleware returns the middleware chain.
GetMiddleware() []RouteMiddleware
}
RouteMatch contains the result of matching a path against the router. This interface is implemented by router.MatchResult.
type RouteMiddleware ¶
RouteMiddleware processes requests before they reach the handler. This is different from HTTP middleware - it operates on the routing level.
type RouteNavigator ¶
type RouteNavigator struct {
// contains filtered or unexported fields
}
RouteNavigator handles route-based navigation for sessions. It is responsible for matching routes, invoking page handlers, and managing the page component lifecycle during navigation.
func NewRouteNavigator ¶
func NewRouteNavigator(session *Session, r Router) *RouteNavigator
NewRouteNavigator creates a new route navigator for a session.
func (*RouteNavigator) CurrentParams ¶
func (rn *RouteNavigator) CurrentParams() map[string]string
CurrentParams returns the current route parameters.
func (*RouteNavigator) CurrentPath ¶
func (rn *RouteNavigator) CurrentPath() string
CurrentPath returns the current route path.
func (*RouteNavigator) Navigate ¶
func (rn *RouteNavigator) Navigate(path string, replace bool) *NavigateResult
Navigate handles navigation to a new path. This is called when:
- ctx.Navigate() is called and pending navigation is processed
- EventNavigate is received from the client
The navigation process:
- Canonicalize the path
- Determine if NAV_PUSH or NAV_REPLACE should be used
- Match the route
- Create the new page component
- Mount and render the new page
- Diff against the old tree
- Return patches
Per Section 4.4 (Programmatic Navigation), this is ONE transaction - NAV_* patch and DOM patches are returned together.
type Router ¶
type Router interface {
// Match finds the handler for a path.
// Returns the match result and whether a match was found.
Match(method, path string) (RouteMatch, bool)
// NotFound returns the 404 handler, if configured.
NotFound() PageHandler
}
Router defines the interface for route matching. This interface is implemented by router.Router.
type RuntimeLogEvent ¶ added in v0.2.0
type RuntimeLogEvent string
RuntimeLogEvent is a stable machine-readable event name emitted on runtime server logs using the "event" slog attribute.
const ( RuntimeLogEventWebsocketHostedSurfaceAuthInvalid RuntimeLogEvent = "vango.server.websocket.hosted_surface_auth.invalid" RuntimeLogEventEventDecodeRejected RuntimeLogEvent = "vango.server.event.decode.rejected" RuntimeLogEventEventTargetRejected RuntimeLogEvent = "vango.server.event.target.rejected" RuntimeLogEventEventQueueFull RuntimeLogEvent = "vango.server.event.queue.full" RuntimeLogEventDOMEventRateLimited RuntimeLogEvent = "vango.server.event.dom.rate_limited" RuntimeLogEventHookEventRateLimited RuntimeLogEvent = "vango.server.event.hook.rate_limited" RuntimeLogEventHookEventRejected RuntimeLogEvent = "vango.server.event.hook.rejected" RuntimeLogEventIslandEventRateLimited RuntimeLogEvent = "vango.server.event.island.rate_limited" RuntimeLogEventIslandEventRejected RuntimeLogEvent = "vango.server.event.island.rejected" RuntimeLogEventWasmEventRateLimited RuntimeLogEvent = "vango.server.event.wasm.rate_limited" RuntimeLogEventWasmEventRejected RuntimeLogEvent = "vango.server.event.wasm.rejected" RuntimeLogEventSessionReconnectFailed RuntimeLogEvent = "vango.server.session.reconnect.failed" RuntimeLogEventSessionResumeSchemaMismatch RuntimeLogEvent = "vango.server.session.resume.schema_mismatch" RuntimeLogEventSessionResumeExpired RuntimeLogEvent = "vango.server.session.resume.expired" RuntimeLogEventSessionResumeHostedAuthNeeded RuntimeLogEvent = "vango.server.session.resume.hosted_auth_required" RuntimeLogEventSessionResumeHostedAuthMismatch RuntimeLogEvent = "vango.server.session.resume.hosted_auth_mismatch" RuntimeLogEventSessionResumeHostedAuthUnexpected RuntimeLogEvent = "vango.server.session.resume.hosted_auth_unexpected" RuntimeLogEventSessionResumeNoAuthHooks RuntimeLogEvent = "vango.server.session.resume.no_auth_revalidation_hooks" RuntimeLogEventSessionResumeTrustSessionID RuntimeLogEvent = "vango.server.session.resume.trust_session_id" RuntimeLogEventSessionResumeAuthInvalid RuntimeLogEvent = "vango.server.session.resume.auth_invalid" RuntimeLogEventSessionResumeHookError RuntimeLogEvent = "vango.server.session.resume.hook_error" RuntimeLogEventSessionResumeGuestHookError RuntimeLogEvent = "vango.server.session.resume.guest_hook_error" RuntimeLogEventSessionResumeAuthNotRehydrated RuntimeLogEvent = "vango.server.session.resume.auth_not_rehydrated" RuntimeLogEventSessionResumeAuthIdentityMismatch RuntimeLogEvent = "vango.server.session.resume.auth_identity_mismatch" RuntimeLogEventSessionResumeRouteRemountFailed RuntimeLogEvent = "vango.server.session.resume.route_remount_failed" RuntimeLogEventSessionResumeRebuildFailed RuntimeLogEvent = "vango.server.session.resume.rebuild_failed" RuntimeLogEventSessionResumeResyncFailed RuntimeLogEvent = "vango.server.session.resume.resync_failed" RuntimeLogEventSessionResumeSucceeded RuntimeLogEvent = "vango.server.session.resume.succeeded" )
type RuntimeLogEventSpec ¶ added in v0.2.0
type RuntimeLogEventSpec struct {
Event RuntimeLogEvent
Level slog.Level
Message string
RequiredAttrs []string
Description string
}
RuntimeLogEventSpec describes a runtime log event emitted by Vango server.
func RuntimeLogEventCatalog ¶ added in v0.2.0
func RuntimeLogEventCatalog() []RuntimeLogEventSpec
RuntimeLogEventCatalog returns the stable runtime log event catalog.
func RuntimeLogEventSpecFor ¶ added in v0.2.0
func RuntimeLogEventSpecFor(event RuntimeLogEvent) (RuntimeLogEventSpec, bool)
RuntimeLogEventSpecFor returns the catalog entry for event.
type SchemaError ¶
type SchemaError struct {
Reason string
Message string
Reasons []string
IsCold bool
SchemaHash string
SchemaVersion uint16
}
SchemaError represents a schema-related resume failure.
func (*SchemaError) Error ¶
func (e *SchemaError) Error() string
type ScrollEvent ¶
ScrollEvent represents a scroll event with position.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is the main HTTP/WebSocket server for Vango.
func MustNew ¶
func MustNew(config *ServerConfig) *Server
MustNew creates a new Server and panics if the configuration is invalid.
func New ¶
func New(config *ServerConfig) (*Server, error)
New creates a new Server with the given configuration. Returns an error if the configuration is invalid for non-DevMode environments.
func (*Server) CSRFMiddleware ¶
func (s *Server) CSRFMiddleware() Middleware
CSRFMiddleware enforces CSRF for state-changing HTTP requests.
func (*Server) Config ¶
func (s *Server) Config() *ServerConfig
Config returns the server configuration.
func (*Server) CookiePolicy ¶
func (s *Server) CookiePolicy() *CookiePolicy
CookiePolicy returns the server cookie policy helper.
func (*Server) EnsureCSRFCookie ¶
EnsureCSRFCookie ensures a valid CSRF cookie exists for the request. Returns the token value when present or generated.
func (*Server) GenerateCSRFToken ¶
GenerateCSRFToken generates a new cryptographically secure CSRF token. If CSRFSecret is set, the token is HMAC-signed for additional security. This should be: 1. Set as a cookie with path=/, SameSite from config, Secure when required 2. Embedded in the initial HTML page for the client to send in handshake
func (*Server) HandleWebSocket ¶
func (s *Server) HandleWebSocket(w http.ResponseWriter, r *http.Request)
HandleWebSocket handles WebSocket upgrade and connection.
func (*Server) Handler ¶
Handler returns an http.Handler for mounting in external routers. This is the primary integration point for ecosystem compatibility with Chi, Gorilla, Echo, stdlib mux, etc.
The handler dispatches based on path:
- /_vango/ws, /_vango/live → WebSocket upgrade
- /_vango/* → Internal routes (future: CSRF, assets)
- /* → Page routes via SSR/handler
Example:
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(authMiddleware)
r.Handle("/*", app.Handler())
http.ListenAndServe(":3000", r)
func (*Server) IsHealthPath ¶ added in v0.2.0
IsHealthPath reports whether path is one of the configured built-in health endpoints.
func (*Server) Metrics ¶
func (s *Server) Metrics() *ServerMetrics
Metrics collects and returns server metrics.
func (*Server) PageHandler ¶
PageHandler returns an http.Handler for page routes only. Use when you want to handle /_vango/* routes separately.
func (*Server) RequestHostAllowed ¶ added in v0.2.0
RequestHostAllowed reports whether r's Host header may reach application handlers. DevMode and empty AllowedHosts preserve compatibility and allow the request; production applications should configure AllowedHosts so this check can reject unknown authorities before routing.
func (*Server) RunContext ¶
RunContext starts the server and blocks until:
- the HTTP server returns an error (including unexpected exit), or
- ctx is canceled (graceful shutdown).
When ctx is canceled, RunContext attempts a graceful shutdown and returns nil unless shutdown fails.
func (*Server) RuntimeBootstrap ¶ added in v0.0.3
RuntimeBootstrap returns the normalized thin-client runtime bootstrap for the current request, including any existing request-scoped bootstrap overrides.
func (*Server) ServeHTTP ¶
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP implements http.Handler.
func (*Server) Sessions ¶
func (s *Server) Sessions() *SessionManager
Sessions returns the session manager.
func (*Server) SetAuthFunc ¶
SetAuthFunc sets the authentication function for validating WebSocket handshakes.
The function is called during:
- new WebSocket sessions
- WebSocket session resume
For new sessions:
- (user, nil): handshake allowed; when user is non-nil, auth.Set(session, user) is applied automatically before OnSessionStart.
- (nil, nil): handshake allowed as guest.
- (nil, err): handshake rejected (not authorized).
For session resume:
- (user, nil): auth valid, auth.Set(session, user) rehydrates auth projection.
- (nil, nil): auth invalid/absent, resume rejected if session was previously authenticated.
- (nil, err): auth failed, resume rejected if session was previously authenticated.
IMPORTANT: Returning (nil, nil) for a previously authenticated session rejects the resume. This is expected for sessions where auth is no longer valid (for example, expired cookie or logout elsewhere).
func (*Server) SetCSRFCookie ¶
SetCSRFCookie sets the CSRF cookie on the response. Call this when rendering the initial page. Uses request TLS or trusted proxy headers to decide the Secure flag. Returns ErrSecureCookiesRequired if secure cookies are enabled and the request is not secure.
func (*Server) SetHandler ¶
SetHandler sets the HTTP handler for non-WebSocket requests.
func (*Server) SetMetricsSink ¶
func (s *Server) SetMetricsSink(sink vango.MetricsSink)
SetMetricsSink updates the metrics sink used by the server and new sessions. Call this during setup before accepting connections.
func (*Server) SetRootComponent ¶
SetRootComponent sets the root component factory.
func (*Server) SetRouter ¶
SetRouter sets the router for route-based navigation. When set, this router is passed to all new sessions to enable:
- Client-side navigation via EventNavigate (link clicks, popstate)
- Programmatic navigation via ctx.Navigate()
The router must implement the Router interface (defined in navigation.go). Use router.NewRouterAdapter to wrap a router.Router for use with Server.
Example:
r := router.NewRouter()
r.AddPage("/", index.IndexPage)
r.AddPage("/about", about.AboutPage)
r.AddPage("/projects/:id", projects.ShowPage)
r.SetNotFound(notfound.NotFoundPage)
app.SetRouter(router.NewRouterAdapter(r))
func (*Server) UnsafeConfigReport ¶ added in v0.2.0
func (s *Server) UnsafeConfigReport() UnsafeConfigReport
func (*Server) UploadHandler ¶
UploadHandler returns an upload handler wrapped with CSRF middleware. Use this when you need fine-grained control over routing, or when mounting upload handlers on a custom mux.
The handler is automatically wrapped with CSRF middleware when CSRF is enabled. Clients must include the CSRF token in the X-CSRF-Token header.
Example:
mux.Handle("POST /api/upload", srv.UploadHandler(store, nil))
With custom config:
mux.Handle("POST /api/upload", srv.UploadHandler(store, &upload.Config{
MaxFileSize: 5 * 1024 * 1024,
AllowedTypes: []string{"image/png", "image/jpeg"},
}))
For most applications, prefer using app.HandleUpload() instead, which handles routing automatically.
func (*Server) ValidateCSRFRequest ¶
ValidateCSRFRequest validates CSRF for an HTTP request. It enforces CSRF for state-changing methods (POST, PUT, PATCH, DELETE).
func (*Server) WebSocketHandler ¶
WebSocketHandler returns an http.Handler for WebSocket upgrade only. Use when you want fine-grained control over routing.
func (*Server) WebSocketURL ¶
WebSocketURL returns the WebSocket URL for this server and request. It respects TLS and trusted proxy headers when determining scheme.
SECURITY: This function validates the Host header against AllowedHosts to prevent Host header poisoning attacks. If the host is not in the allowlist, it returns an empty string (fail secure).
If CanonicalHost is configured and the request host is valid, the canonical host is used instead of the request host.
type ServerConfig ¶
type ServerConfig struct {
// Address is the address to listen on (e.g., ":8080" or "localhost:3000").
// Default: ":8080".
Address string
// ReadBufferSize is the WebSocket read buffer size.
// Default: 4096.
ReadBufferSize int
// WriteBufferSize is the WebSocket write buffer size.
// Default: 4096.
WriteBufferSize int
// CheckOrigin is called to validate the request origin.
// Default: same-origin validation.
// For allowlist policies, configure via WithAllowedOrigins or AllowedOriginsCheck.
CheckOrigin func(r *http.Request) bool
// OriginPolicy describes how WebSocket origin checks are configured.
// Used for validation and guardrails in production.
OriginPolicy OriginPolicyMode
// AllowedOrigins lists domains allowed for WebSocket connections.
// Entries must be valid origins (scheme + host + optional port) with no path,
// query, or fragment. Origin matching is normalized by scheme + lowercase host
// + effective port (default ports may be omitted or explicit).
// Used for validation when OriginPolicy is OriginPolicyAllowedOrigins.
AllowedOrigins []string
// AllowSameOrigin enables same-origin validation.
// Used for validation when OriginPolicy is OriginPolicySameOrigin.
AllowSameOrigin bool
// AllowCustomOriginPolicy explicitly permits custom origin checks in production.
AllowCustomOriginPolicy bool
// SessionConfig is the configuration for individual sessions.
// Default: DefaultSessionConfig().
SessionConfig *SessionConfig
// SessionLimits overrides the default session limits when non-nil.
// Values in this struct are authoritative, including zero values
// (for example, MaxSessions=0 means unlimited).
SessionLimits *SessionLimits
// ShutdownTimeout is the maximum time to wait for graceful shutdown.
// Default: 30 seconds.
ShutdownTimeout time.Duration
// ReadHeaderTimeout is the maximum time to read request headers.
// Default: 5 seconds.
ReadHeaderTimeout time.Duration
// ReadTimeout is the maximum time to read the entire request.
// Default: 30 seconds.
ReadTimeout time.Duration
// WriteTimeout is the maximum time to write the response.
// Default: 30 seconds.
WriteTimeout time.Duration
// IdleTimeout is the maximum time to wait for the next request
// when keep-alives are enabled.
// Default: 60 seconds.
IdleTimeout time.Duration
// LivenessPath is the built-in liveness endpoint path.
// Default: /_vango/health/live.
LivenessPath string
// ReadinessPath is the built-in readiness endpoint path.
// Default: /_vango/health/ready.
ReadinessPath string
// LivenessCheck optionally gates the liveness endpoint.
// Return nil for live; return an error to respond with 503.
LivenessCheck HealthCheck
// ReadinessCheck optionally gates the readiness endpoint.
// Return nil for ready; return an error to respond with 503.
ReadinessCheck HealthCheck
// MaxSessions is a legacy convenience override for the global session cap.
// Used only when SessionLimits is nil.
// Values > 0 override DefaultSessionLimits().MaxSessions.
// Values <= 0 leave the default effective cap unchanged.
// Default: 0 (no legacy override).
MaxSessions int
// MaxMemoryPerSession is the approximate memory limit per session.
// Sessions exceeding this may be evicted under memory pressure.
// Default: 3MB.
MaxMemoryPerSession int64
// MaxConcurrentHandshakes is the maximum number of concurrent WebSocket
// connections waiting to complete handshake/auth/session admission.
// Helps bound pre-auth resource usage (FDs/goroutines/memory).
// 0 means no limit.
// Default: 1024.
MaxConcurrentHandshakes int
// MaxConcurrentHandshakesPerIP is the maximum number of concurrent
// pre-auth handshakes from a single client IP.
// Helps prevent per-IP pre-auth socket exhaustion.
// 0 means no limit.
// Default: 64.
MaxConcurrentHandshakesPerIP int
// CSRFSecret is the secret key for CSRF token generation.
// If nil and CSRF is enabled in non-DevMode, a random secret is generated
// at startup (tokens won't survive server restarts).
// To disable CSRF protection entirely, set CSRFEnabled = false explicitly.
// For production, prefer a stable 32+ byte secret.
CSRFSecret []byte
// CSRFEnabled enables CSRF protection for state-changing HTTP endpoints.
// Default: true.
CSRFEnabled bool
// PreUpgradeCheck runs before upgrading HTTP to WebSocket.
//
// Use this as a lightweight pre-upgrade gate (for example:
// token/header/query/subprotocol checks) to reject unauthenticated
// or malformed upgrade attempts before a WebSocket socket is allocated.
//
// Return nil to allow the upgrade. Return an error to reject with HTTP 403.
// If the returned error implements `StatusCode() int`, that status code is used
// when it is in the 4xx/5xx range.
// Default: nil (disabled).
PreUpgradeCheck func(r *http.Request) error
// HostedSurfaceVerifier validates hosted surface identity for SSR/bootstrap
// requests. When nil, hosted/native surface claims from raw request metadata
// are ignored by default.
HostedSurfaceVerifier HostedSurfaceVerifyFunc
// HostedSurfaceTokenSecret signs short-lived hosted-auth tokens embedded in
// bootstrap responses for verified hosted surfaces.
HostedSurfaceTokenSecret []byte
// AllowedRedirectHosts lists hostnames (and optional ports) allowed for
// external redirects.
// Hostname-only entries authorize only the default ports (80 for http, 443
// for https). Use host:port for non-default ports.
// When empty, external redirects are rejected.
// Example: []string{"accounts.example.com", "auth.example.com:8443"}
AllowedRedirectHosts []string
// AllowedHosts lists hostnames (and optional ports) that are valid for this
// server.
// Hostname-only entries authorize only the request scheme's default port
// (80 for insecure requests, 443 for secure requests). Use host:port for
// non-default ports.
// Used outside DevMode to validate the Host header before app request
// routing, and in WebSocketURL() to prevent Host header poisoning. If empty,
// WebSocketURL() returns an empty string (fail secure), while request routing
// remains compatible for deployments that enforce hosts at an external proxy.
// Example: []string{"myapp.com", "www.myapp.com", "myapp.com:8443"}
AllowedHosts []string
// CanonicalHost is the preferred hostname to use when generating URLs.
// This must be host or host:port. If set and the request Host matches any
// AllowedHosts entry, this value is used instead. Useful for normalizing
// "www" vs non-"www" hosts.
// If empty, the validated request host is used as-is.
CanonicalHost string
// PublicRuntimePrefix is the public mount prefix used when generating
// runtime endpoint URLs for the thin client bootstrap.
//
// Examples:
// "" -> /_vango/live and /_vango/client.js
// "/app" -> /app/_vango/live and /app/_vango/client.js
//
// This affects generated public URLs only. Internal handler routing remains
// rooted at /_vango/* and any external router or reverse proxy is responsible
// for applying or stripping the configured prefix.
PublicRuntimePrefix string
// CleanupInterval is the interval for the session cleanup loop.
// Default: 30 seconds.
CleanupInterval time.Duration
// OnSessionStart is called during WebSocket upgrade, BEFORE the handshake completes.
// Use this to copy data from the HTTP context (e.g., authenticated user) to the Vango session.
// This runs SYNCHRONOUSLY before the WebSocket upgrade completes, while r.Context() is still alive.
// After this callback returns, the HTTP context is dead and cannot be accessed.
//
// Example:
// OnSessionStart: func(httpCtx context.Context, session *Session) {
// if user := myauth.UserFromContext(httpCtx); user != nil {
// auth.Set(session, user) // Rehydrate user projection when your app uses it
// auth.SetPrincipal(session, auth.Principal{
// ID: user.ID,
// }) // Rehydrate principal projection for auth freshness/principal-first flows
// }
// }
OnSessionStart func(httpCtx context.Context, session *Session)
// OnSessionResume is called during WebSocket session resume, BEFORE the handshake completes.
// Use this to rehydrate session data from the HTTP context (e.g., re-validate and restore user).
//
// Unlike OnSessionStart, this is called when resuming an existing session after disconnect.
// The session's signal state is preserved, but auth data should be revalidated from cookies/headers.
//
// Return nil to allow the resume, or an error to reject it.
// If an error is returned and the session was previously authenticated (auth.WasAuthenticated),
// the resume is rejected with HandshakeNotAuthorized. If the session was not authenticated,
// an error is logged but the resume continues as a guest session.
//
// IMPORTANT: Simply returning nil is NOT sufficient for security. The hook MUST
// actually revalidate authentication and rehydrate auth projection via
// auth.Set() and/or auth.SetPrincipal(), depending on your app.
// In strict mode without authFunc, resume clears runtime auth projection before
// this hook runs, so a no-op OnSessionResume is rejected for previously
// authenticated sessions.
//
// Example:
// OnSessionResume: func(httpCtx context.Context, session *Session) error {
// user, err := myauth.ValidateFromContext(httpCtx)
// if err != nil {
// return err // Reject resume if previously authenticated
// }
// if user != nil {
// auth.Set(session, user) // Rehydrate user projection when your app uses it
// auth.SetPrincipal(session, auth.Principal{
// ID: user.ID,
// }) // Rehydrate principal projection for auth freshness/principal-first flows
// }
// return nil
// }
OnSessionResume func(httpCtx context.Context, session *Session) error
// AuthResumePolicy controls how authenticated session resumes are validated.
//
// Default: AuthResumePolicyStrict (requires authFunc or OnSessionResume for
// authenticated sessions to resume).
//
// SECURITY: The strict default ensures that leaked session IDs cannot be used
// to hijack authenticated sessions. If a session ID leaks via XSS, logging,
// or other vectors, the attacker cannot resume the session without also
// presenting valid authentication credentials.
//
// Set to AuthResumePolicyTrustSessionID only if you understand the security
// implications and have compensating controls in place.
AuthResumePolicy AuthResumePolicy
// AllowTrustSessionIDInProduction acknowledges the security tradeoff of
// AuthResumePolicyTrustSessionID in non-DevMode.
//
// When false (default), non-Dev configs that set TrustSessionID are rejected.
// TrustSessionID also requires:
// - TrustSessionIDRiskAcceptance = TrustSessionIDRiskAcceptanceV1
// - ResumeWindow <= 10s
// - Session.AuthCheck hardening:
// * Check configured
// * Interval > 0 and <= ResumeWindow
// * FailureMode = FailClosed
// * MaxStale <= ResumeWindow
AllowTrustSessionIDInProduction bool
// AllowDevModeInNonLocalEnvironment acknowledges the security tradeoff of
// enabling DevMode alongside non-local / production-like server settings.
//
// Localhost development remains allowed without this flag. Non-local binds,
// non-local host/origin config, trusted proxies, hosted verification, and
// similar production-like settings require both this flag and
// DevModeRiskAcceptance in DevMode.
AllowDevModeInNonLocalEnvironment bool
// DevModeRiskAcceptance is a required explicit acknowledgement token for
// DevMode with non-local / production-like config.
DevModeRiskAcceptance string
// TrustSessionIDRiskAcceptance is a required explicit acknowledgement token
// for non-Dev AuthResumePolicyTrustSessionID usage.
//
// Set to TrustSessionIDRiskAcceptanceV1 when you intentionally accept the
// weaker logout/revocation semantics of TrustSessionID.
// Default: "" (not acknowledged).
TrustSessionIDRiskAcceptance string
// AllowUnsafeRawHTMLInProduction acknowledges the security tradeoff of
// disabling raw-HTML sink sanitization in non-DevMode.
//
// When false (default), non-Dev configs that set SessionConfig.URLPolicy.AllowUnsafeRawHTML
// are rejected.
//
// SECURITY: AllowUnsafeRawHTML disables framework sanitization for raw HTML sinks and
// can enable "gadget injection" of Vango runtime attributes (hooks/islands/WASM) when
// attacker-controlled HTML reaches a raw sink. Use only for fully trusted HTML with a
// strong CSP.
AllowUnsafeRawHTMLInProduction bool
// UnsafeRawHTMLRiskAcceptance is a required explicit acknowledgement token for
// non-dev raw HTML sink sanitization bypass.
UnsafeRawHTMLRiskAcceptance string
// AllowInsecureModuleOriginsInProduction acknowledges the security tradeoff of
// allowing insecure http: cross-origin island/WASM module imports on https:
// pages in non-dev environments.
AllowInsecureModuleOriginsInProduction bool
// InsecureModuleOriginsRiskAcceptance is a required explicit acknowledgement
// token for non-dev insecure cross-origin module origin allowance.
InsecureModuleOriginsRiskAcceptance string
// TrustedProxies lists trusted reverse proxy IPs for X-Forwarded-* headers.
// If set, the server will trust forwarded headers (including X-Forwarded-Proto)
// from these IPs when determining request security.
// Default: nil (don't trust proxy headers).
TrustedProxies []string
// DebugMode enables extra validation and logging for development.
// When true:
// - Session.Set() panics on unserializable types (func, chan)
// - auth.Get() logs warnings on type mismatches
// Default: false.
DebugMode bool
// DevMode disables security checks for local development.
// SECURITY: NEVER use in production - this disables:
// - Origin checking (allows all origins)
// - CSRF validation
// - Secure cookie requirements
// Default: false (secure by default)
DevMode bool
// SecureCookies enforces Secure flag on cookies set by the server.
// Should be true when using HTTPS.
// Default: true
SecureCookies bool
// CookieHTTPOnly sets the HttpOnly flag on cookies set by the server.
// Prevents JavaScript access to cookies that should not be read by JS.
// Default: true (except for cookies that explicitly opt out like CSRF).
CookieHTTPOnly bool
// SameSiteMode sets the SameSite attribute for cookies.
// Lax is safe for most use cases and allows OAuth flows.
// Default: http.SameSiteLaxMode
SameSiteMode http.SameSite
// CookieDomain sets the Domain attribute for cookies set by the server.
// Empty string uses the current domain (most secure).
// Default: "" (current domain)
CookieDomain string
// SessionStore is the persistence backend for sessions.
// If nil, sessions are only stored in memory (lost on restart).
// Use session.NewMemoryStore(), session.NewRedisStore(), or session.NewSQLStore().
// Default: nil (in-memory only).
SessionStore session.SessionStore
// GlobalSignalPubSub is the broadcast backend for global signals.
// When nil, global signals update via eventual consistency only.
GlobalSignalPubSub corevango.GlobalBroadcastBackend
// GlobalSignalRefreshInterval controls the periodic anti-entropy refresh
// cadence for global signals from persistence.
// When persistence is available, this still runs with pubsub enabled so
// instances converge after missed broadcasts.
// 0 disables refresh entirely.
// Default: 30 seconds.
GlobalSignalRefreshInterval time.Duration
// ResumeWindow is how long a detached session remains resumable after disconnect.
// After this window, the session is permanently expired.
// 0 disables resumption entirely.
// Default: 5 minutes.
ResumeWindow time.Duration
// MaxDetachedSessions is the maximum number of disconnected sessions to keep in memory.
// When exceeded, the least recently used sessions are evicted (and persisted if store is configured).
// Default: 10000.
MaxDetachedSessions int
// MaxSessionsPerIP is the maximum number of concurrent sessions from a single IP address.
// Helps prevent DoS attacks from IP exhaustion.
// 0 means no limit.
// Default: 100.
MaxSessionsPerIP int
// EvictionPolicy determines how detached sessions are evicted when limits are exceeded.
// Default: EvictionLRU.
EvictionPolicy SessionEvictionPolicy
// EvictOnIPLimit controls whether hitting MaxSessionsPerIP evicts the oldest
// detached session for that IP instead of rejecting the new session.
// Default: true when MaxSessionsPerIP > 0.
EvictOnIPLimit bool
// PersistInterval is how often to persist dirty sessions to the store.
// Set to 0 to only persist on disconnect.
// Default: 30 seconds.
PersistInterval time.Duration
// AssetResolver is the resolver for fingerprinted asset paths.
// When set, ctx.Asset() will use this resolver to map source paths
// to their fingerprinted versions (e.g., "vango.js" → "vango.a1b2c3d4.min.js").
//
// If nil, ctx.Asset() returns paths unchanged.
//
// Example:
//
// manifest, _ := vango.LoadAssetManifest("dist/manifest.json")
// config.AssetResolver = vango.NewAssetResolver(manifest, "/public/")
//
// For development (no fingerprinting):
//
// config.AssetResolver = vango.NewPassthroughResolver("/public/")
//
// Default: nil (passthrough behavior).
AssetResolver assets.Resolver
// contains filtered or unexported fields
}
ServerConfig holds configuration for the HTTP/WebSocket server.
func DefaultServerConfig ¶
func DefaultServerConfig() *ServerConfig
DefaultServerConfig returns a ServerConfig with sensible defaults. SECURITY: All security features are ENABLED by default. SECURITY: CheckOrigin enforces same-origin by default to prevent CSWSH. SECURITY: CSRFSecret is nil by default; explicit production environments must provide a stable 32+ byte secret. Non-production runs may receive an ephemeral fallback for local ergonomics. SECURITY: SecureCookies is true by default for HTTPS environments.
func (*ServerConfig) Clone ¶
func (c *ServerConfig) Clone() *ServerConfig
Clone returns a copy of the ServerConfig.
func (*ServerConfig) GetConfigWarnings ¶
func (c *ServerConfig) GetConfigWarnings() []string
GetConfigWarnings returns a list of configuration warnings. Useful for displaying warnings in a custom way.
func (*ServerConfig) IsSecure ¶
func (c *ServerConfig) IsSecure() bool
IsSecure returns true if the configuration has all security features enabled. Useful for startup checks.
func (*ServerConfig) UnsafeConfigReport ¶ added in v0.2.0
func (c *ServerConfig) UnsafeConfigReport() UnsafeConfigReport
func (*ServerConfig) ValidateConfig ¶
func (c *ServerConfig) ValidateConfig() error
ValidateConfig validates the server configuration. Called automatically by Server.New() and Server.Run(). Returns any fatal configuration errors.
func (*ServerConfig) WithAddress ¶
func (c *ServerConfig) WithAddress(addr string) *ServerConfig
WithAddress sets the server address and returns the config for chaining.
func (*ServerConfig) WithAllowedHosts ¶
func (c *ServerConfig) WithAllowedHosts(hosts ...string) *ServerConfig
WithAllowedHosts sets the allowed hostnames for WebSocketURL validation. This prevents Host header poisoning attacks.
func (*ServerConfig) WithAllowedOrigins ¶
func (c *ServerConfig) WithAllowedOrigins(origins ...string) *ServerConfig
WithAllowedOrigins sets the allowed WebSocket origins and configures the origin policy. This enforces an allowlist-based CheckOrigin in production.
func (*ServerConfig) WithCSRFSecret ¶
func (c *ServerConfig) WithCSRFSecret(secret []byte) *ServerConfig
WithCSRFSecret sets the CSRF secret and returns the config for chaining.
func (*ServerConfig) WithCanonicalHost ¶
func (c *ServerConfig) WithCanonicalHost(host string) *ServerConfig
WithCanonicalHost sets the canonical hostname for URL generation.
func (*ServerConfig) WithCookieDomain ¶
func (c *ServerConfig) WithCookieDomain(domain string) *ServerConfig
WithCookieDomain sets the domain for session cookies.
func (*ServerConfig) WithCookieHTTPOnly ¶
func (c *ServerConfig) WithCookieHTTPOnly(httpOnly bool) *ServerConfig
WithCookieHTTPOnly sets whether cookies should be HttpOnly by default.
func (*ServerConfig) WithDevMode ¶
func (c *ServerConfig) WithDevMode() *ServerConfig
WithDevMode enables development mode which disables security checks. SECURITY WARNING: NEVER use in production. This disables:
- Origin checking (allows all origins)
- CSRF validation (disabled)
- Secure cookie requirements (disabled)
Only use for local development:
config := server.DefaultServerConfig().WithDevMode()
func (*ServerConfig) WithEvictOnIPLimit ¶
func (c *ServerConfig) WithEvictOnIPLimit(evict bool) *ServerConfig
WithEvictOnIPLimit sets whether to evict the oldest detached session on IP limit.
func (*ServerConfig) WithEvictionPolicy ¶
func (c *ServerConfig) WithEvictionPolicy(policy SessionEvictionPolicy) *ServerConfig
WithEvictionPolicy sets the detached session eviction policy.
func (*ServerConfig) WithHostedSurfaceTokenSecret ¶ added in v0.2.0
func (c *ServerConfig) WithHostedSurfaceTokenSecret(secret []byte) *ServerConfig
WithHostedSurfaceTokenSecret sets the hosted surface auth token signing secret.
func (*ServerConfig) WithHostedSurfaceVerifier ¶ added in v0.2.0
func (c *ServerConfig) WithHostedSurfaceVerifier(v HostedSurfaceVerifyFunc) *ServerConfig
WithHostedSurfaceVerifier sets the hosted surface verifier.
func (*ServerConfig) WithMaxConcurrentHandshakes ¶
func (c *ServerConfig) WithMaxConcurrentHandshakes(max int) *ServerConfig
WithMaxConcurrentHandshakes sets the global pre-auth concurrent handshake cap.
func (*ServerConfig) WithMaxConcurrentHandshakesPerIP ¶
func (c *ServerConfig) WithMaxConcurrentHandshakesPerIP(max int) *ServerConfig
WithMaxConcurrentHandshakesPerIP sets the per-IP pre-auth concurrent handshake cap.
func (*ServerConfig) WithMaxDetachedSessions ¶
func (c *ServerConfig) WithMaxDetachedSessions(max int) *ServerConfig
WithMaxDetachedSessions sets the maximum detached sessions and returns the config for chaining.
func (*ServerConfig) WithMaxSessions ¶
func (c *ServerConfig) WithMaxSessions(max int) *ServerConfig
WithMaxSessions sets the maximum sessions and returns the config for chaining.
func (*ServerConfig) WithMaxSessionsPerIP ¶
func (c *ServerConfig) WithMaxSessionsPerIP(max int) *ServerConfig
WithMaxSessionsPerIP sets the per-IP session limit and returns the config for chaining.
func (*ServerConfig) WithPersistInterval ¶
func (c *ServerConfig) WithPersistInterval(d time.Duration) *ServerConfig
WithPersistInterval sets the persist interval and returns the config for chaining.
func (*ServerConfig) WithPreUpgradeCheck ¶
func (c *ServerConfig) WithPreUpgradeCheck(check func(r *http.Request) error) *ServerConfig
WithPreUpgradeCheck sets the pre-upgrade check callback.
func (*ServerConfig) WithPublicRuntimePrefix ¶ added in v0.0.3
func (c *ServerConfig) WithPublicRuntimePrefix(prefix string) *ServerConfig
WithPublicRuntimePrefix sets the public mount prefix used for generated runtime endpoint URLs such as the thin-client script and live websocket path.
func (*ServerConfig) WithResumeWindow ¶
func (c *ServerConfig) WithResumeWindow(d time.Duration) *ServerConfig
WithResumeWindow sets the resume window duration and returns the config for chaining.
func (*ServerConfig) WithSameSiteMode ¶
func (c *ServerConfig) WithSameSiteMode(mode http.SameSite) *ServerConfig
WithSameSiteMode sets the SameSite attribute for cookies.
func (*ServerConfig) WithSecureCookies ¶
func (c *ServerConfig) WithSecureCookies(secure bool) *ServerConfig
WithSecureCookies sets whether cookies should have the Secure flag.
func (*ServerConfig) WithSessionConfig ¶
func (c *ServerConfig) WithSessionConfig(sc *SessionConfig) *ServerConfig
WithSessionConfig sets the session configuration and returns the config for chaining.
func (*ServerConfig) WithSessionStore ¶
func (c *ServerConfig) WithSessionStore(store session.SessionStore) *ServerConfig
WithSessionStore sets the session persistence backend and returns the config for chaining.
type ServerMetrics ¶
type ServerMetrics struct {
// Sessions
ActiveSessions int64
TotalSessions int64
SessionCreates int64
SessionCloses int64
PeakSessions int64
// Events
EventsReceived int64
EventsProcessed int64
EventsDropped int64
// Patches
PatchesSent int64
PatchBytes int64
// Network
BytesSent int64
BytesReceived int64
// Errors
HandlerPanics int64
WriteErrors int64
ReadErrors int64
// Signal write enforcement
SignalWriteViolationTotal int64
// Latency (microseconds)
EventLatencyP50 int64
EventLatencyP99 int64
// Memory
TotalMemory int64
// Persistence
PersistWriteRejectedTotal int64
PersistBytesTotal int64
SchemaMismatchTotal int64
// Timestamp
CollectedAt time.Time
}
ServerMetrics aggregates metrics across the server.
type Session ¶
type Session struct {
// Identity
ID string
CreatedAt time.Time
LastActive time.Time // Guarded by metaMu after initialization.
// Phase 12: Session persistence fields
IP string // Client IP address for per-IP limits
CurrentRoute string // Current page route for restoration. Guarded by metaMu after initialization.
DetachedAt time.Time // Time when the session detached (per-IP eviction ordering). Guarded by metaMu after initialization.
// contains filtered or unexported fields
}
Session represents a single WebSocket connection and its state. Each session has its own component tree, reactive ownership, and handler registry.
func NewMockSession ¶
func NewMockSession() *Session
NewMockSession creates a session without a WebSocket connection for testing. The session has all fields initialized except conn.
func (*Session) BroadcastAuth ¶
func (s *Session) BroadcastAuth(channel, typ string, reason AuthExpiredReason)
BroadcastAuth sends an auth broadcast control message to the client. This should be called on the session loop.
func (*Session) BudgetTracker ¶
func (s *Session) BudgetTracker() *vango.BudgetTracker
BudgetTracker returns the state budget tracker for this session.
func (*Session) BytesReceived ¶
BytesReceived adds to the bytes received counter.
func (*Session) Config ¶
func (s *Session) Config() *SessionConfig
Config returns the session configuration.
func (*Session) Conn ¶
Conn returns the underlying WebSocket connection. Use with caution - prefer session methods when possible.
func (*Session) CurrentRoutePath ¶ added in v0.0.3
CurrentRoutePath returns the current route path for the session.
func (*Session) Deserialize ¶
Deserialize restores session state from bytes. Phase 7: Validates schema compatibility before restoring.
func (*Session) DeserializeForSessionID ¶
DeserializeForSessionID restores session state and enforces that the persisted session payload identity matches the requested persistence key.
func (*Session) Dispatch ¶
func (s *Session) Dispatch(fn func())
Dispatch queues a function to run on the session's event loop. This is safe to call from any goroutine and is the correct way to update signals from asynchronous operations (database calls, timers, etc.).
The function will be executed synchronously on the event loop, ensuring signal writes are properly serialized. After the function completes, pending effects will run and dirty components will re-render.
Example:
go func() {
user, err := db.Users.FindByID(ctx.StdContext(), id)
ctx.Dispatch(func() {
if err != nil {
errorSignal.Set(err)
} else {
userSignal.Set(user)
}
})
}()
func (*Session) Done ¶
func (s *Session) Done() <-chan struct{}
Done returns a channel that's closed when the session is done.
func (*Session) EventLoop ¶
func (s *Session) EventLoop()
EventLoop processes queued events, dispatch callbacks, and render signals. It runs handlers, schedules effects, and triggers re-renders.
func (*Session) Get ¶
Get retrieves a value from session data. Returns nil if key doesn't exist. This is thread-safe and can be called from any goroutine.
func (*Session) GetAllData ¶
GetAllData returns a copy of all session data. Persistence helpers enforce which keys are durable. Returns nil if no data has been set.
func (*Session) GetInt ¶
GetInt is a convenience method that returns value as int. Returns 0 if key doesn't exist or value is not numeric. Handles int, int64, and float64 conversions.
func (*Session) GetString ¶
GetString is a convenience method that returns value as string. Returns empty string if key doesn't exist or value is not a string.
func (*Session) HandleNavigate ¶
HandleNavigate processes a navigation request and returns patches. This is called from handleEvent when an EventNavigate is received, or from flush() when ctx.Navigate() was called during event handling.
Per Section 4.4 (Programmatic Navigation), navigation is ONE transaction: NAV_* patch + DOM patches are sent together in a single frame.
Parameters:
- path: The target path (may include query string)
- replace: If true, use NAV_REPLACE instead of NAV_PUSH
Returns:
- error if navigation failed (no route matched and no NotFound handler)
func (*Session) IsDetached ¶
IsDetached reports whether the session currently has no active WebSocket connection but is still kept in memory for ResumeWindow.
func (*Session) MemoryUsage ¶
MemoryUsage estimates the memory used by this session.
func (*Session) Navigator ¶
func (s *Session) Navigator() *RouteNavigator
Navigator returns the route navigator for this session. Returns nil if no router has been set.
func (*Session) NeedsRestart ¶
NeedsRestart returns true if session goroutines need to be restarted. This should be checked after Resume() to decide whether to call Start(). If the session's done channel was closed, goroutines have exited and need to be restarted for the session to function.
func (*Session) PersistErrorHandler ¶
func (s *Session) PersistErrorHandler() func(*vango.PersistBudgetError)
PersistErrorHandler returns the current persist error handler.
func (*Session) PrefetchCache ¶
func (s *Session) PrefetchCache() *PrefetchCache
PrefetchCache returns the prefetch cache for this session. Returns nil if prefetch is not initialized.
func (*Session) PrimitiveRegistry ¶
func (s *Session) PrimitiveRegistry() *SessionPrimitiveRegistry
PrimitiveRegistry returns the session's primitive registry.
func (*Session) QueueEvent ¶
QueueEvent queues an event for processing.
func (*Session) ReadLoop ¶
func (s *Session) ReadLoop()
ReadLoop continuously reads messages from the WebSocket connection. It decodes frames, processes control messages, and queues events. This method blocks until the connection is closed or an error occurs.
func (*Session) RebuildHandlers ¶
RebuildHandlers clears and rebuilds the handler map with fresh HIDs. This is called on session resume to match SSR-rendered DOM.
Unlike a full remount, this preserves:
- Owner (signals stay alive with their values)
- Component instances (state preserved)
It regenerates:
- HID assignments (reset to h1, h2... matching SSR)
- Handler map (rebuilt from fresh render)
- Component ownership map
func (*Session) RegisterIslandHandler ¶
func (s *Session) RegisterIslandHandler(id string, handler vango.IslandMessageHandler) func()
RegisterIslandHandler registers a handler for island messages within this session. Returns a cleanup function that unregisters the handler.
func (*Session) RegisterPrimitives ¶
func (s *Session) RegisterPrimitives(regs []vango.PrimitiveRegistration, component *ComponentInstance)
RegisterPrimitives adds primitives from a component's setup.
func (*Session) RegisterValidatedIslandHandler ¶ added in v0.2.0
func (s *Session) RegisterValidatedIslandHandler(id string, validate vango.IslandMessageValidator, handler vango.IslandMessageHandler) func()
RegisterValidatedIslandHandler registers a handler plus exact-sink validator coverage for island messages within this session.
func (*Session) RegisterValidatedWasmHandler ¶ added in v0.2.0
func (s *Session) RegisterValidatedWasmHandler(id string, validate vango.WasmMessageValidator, handler vango.WasmMessageHandler) func()
RegisterValidatedWasmHandler registers a handler plus exact-sink validator coverage for WASM messages within this session.
func (*Session) RegisterWasmHandler ¶
func (s *Session) RegisterWasmHandler(id string, handler vango.WasmMessageHandler) func()
RegisterWasmHandler registers a handler for WASM messages within this session. Returns a cleanup function that unregisters the handler.
func (*Session) RestoreData ¶
RestoreData restores session data from serialized values. This is used during session restoration after server restart or reconnection. Values are merged into existing data (doesn't clear existing keys).
func (*Session) Resume ¶
Resume resumes a session after reconnect. It swaps the WebSocket connection, resets sequence numbers, and reinitializes channels if the session was previously closed. Call NeedsRestart() after Resume() to check if Start() should be called to restart goroutines.
func (*Session) SendClose ¶
func (s *Session) SendClose(reason protocol.CloseReason, message string)
SendClose sends a close control message to the client.
func (*Session) SendHookRevert ¶
SendHookRevert requests the client to revert a hook's optimistic UI change. The client will invoke the revert callback registered for the given HID.
func (*Session) SendIslandMessage ¶
SendIslandMessage sends a message to the client-side island.
func (*Session) SendIslandMessageToHID ¶ added in v0.0.2
SendIslandMessageToHID sends a message to a specific island instance, addressed by HID.
func (*Session) SendPatches ¶
SendPatches is a public wrapper for sendPatches.
func (*Session) SendResyncFull ¶
SendResyncFull sends the full HTML tree to the client. This is used as a fallback when HIDs may not align between SSR and remount. The client will replace its entire body content with this HTML.
func (*Session) SendSessionRefresh ¶
func (s *Session) SendSessionRefresh(cmd *protocol.SessionRefreshCommand)
SendSessionRefresh sends a session refresh control message to the client.
func (*Session) SendWasmMessage ¶
SendWasmMessage sends a message to the client-side WASM component.
func (*Session) SendWasmMessageToHID ¶ added in v0.0.2
SendWasmMessageToHID sends a message to a specific wasm instance, addressed by HID.
func (*Session) Serialize ¶
Serialize converts the session state to bytes for persistence. Phase 7: Uses schema-gated, HMAC-signed blobs with stable IDs.
func (*Session) Set ¶
Set stores a value in session data. Value must be safe to access concurrently (immutable or properly synchronized).
Session.Set stores runtime-only KV by default. Durable session state should use vango.SessionKey[T], setup.SharedSignal, or setup.GlobalSignal.
In debug mode (SessionConfig.DebugMode = true), this panics on obviously unserializable types like func and chan.
func (*Session) SetAssetResolver ¶
SetAssetResolver sets the asset resolver for this session. This is called by the server when a session is created or resumed.
func (*Session) SetInitialURL ¶
SetInitialURL sets the initial URL parameters from the client handshake. This is called when processing the initial handshake message from the client. URLParam hydration reads this state snapshot during setup.
func (*Session) SetJSON ¶
SetJSON stores runtime-only KV with JSON-oriented intent. This is equivalent to Set(); it does not make the value durable.
func (*Session) SetPersistErrorHandler ¶
func (s *Session) SetPersistErrorHandler(fn func(*vango.PersistBudgetError))
SetPersistErrorHandler registers a persist error handler for this session.
func (*Session) SetRouter ¶
SetRouter sets the router for this session and creates a navigator. This enables route-based navigation via ctx.Navigate() and EventNavigate. The router must implement the Router interface (defined in navigation.go).
func (*Session) SetShellBridge ¶ added in v0.0.3
SetShellBridge stores the shell bridge for the session.
func (*Session) SetSurfaceInfo ¶ added in v0.0.3
SetSurfaceInfo stores normalized surface metadata for the session.
func (*Session) SetUserID ¶ added in v0.0.2
SetUserID updates the session's user identifier. It is safe to call concurrently with session loops.
func (*Session) ShellBridge ¶ added in v0.0.3
ShellBridge returns the shell bridge for the session.
func (*Session) ShowPersistErrorBanner ¶
func (s *Session) ShowPersistErrorBanner(err *vango.PersistBudgetError)
ShowPersistErrorBanner triggers the default persist banner for this session.
func (*Session) Start ¶
func (s *Session) Start()
Start starts all session loops. This should be called after the handshake is complete.
func (*Session) StormBudget ¶
func (s *Session) StormBudget() vango.StormBudgetChecker
StormBudget returns the storm budget checker for this session. Returns nil if storm budgets are not configured.
func (*Session) SurfaceInfo ¶ added in v0.0.3
SurfaceInfo returns normalized surface metadata for the session.
func (*Session) TriggerSchemaRefresh ¶
func (s *Session) TriggerSchemaRefresh(reason protocol.SchemaRefreshReason, debug string)
TriggerSchemaRefresh invalidates the session and forces a client reload. This is used when the running binary detects persisted-state corruption or incompatibility after the session is already mounted (e.g., SharedSignal restore failure).
It is safe to call multiple times; only the first invocation sends the control message.
func (*Session) UnregisterPrimitives ¶
func (s *Session) UnregisterPrimitives(regs []vango.PrimitiveRegistration, component *ComponentInstance)
UnregisterPrimitives removes primitives for a component instance.
func (*Session) UpdateLastActive ¶
func (s *Session) UpdateLastActive()
UpdateLastActive updates the last activity timestamp.
type SessionConfig ¶
type SessionConfig struct {
// ReadTimeout is the maximum time to wait for a message from the client.
// Default: 60 seconds.
ReadTimeout time.Duration
// WriteTimeout is the maximum time to wait when sending a message.
// Default: 10 seconds.
WriteTimeout time.Duration
// IdleTimeout is the time after which an inactive session is closed.
// Default: 5 minutes.
IdleTimeout time.Duration
// HandshakeTimeout is the maximum time for the initial handshake.
// Default: 5 seconds.
HandshakeTimeout time.Duration
// InitialMountResourcePreload keeps the first live session tree aligned with the
// SSR HTML by preloading setup.Resource/setup.ResourceKeyed reads during
// Session.MountRoot.
//
// This mirrors SSR resource-preload behavior for the initial websocket mount so
// the browser's SSR DOM and the session's currentTree start from the same data
// state. When disabled, the initial live tree mounts cold and resources resolve
// later through the normal effect/dispatch path.
//
// Default: true.
InitialMountResourcePreload bool
// InitialMountResourceTimeout bounds how long initial live-mount resource
// preloading waits before falling back to the component's loading shell.
//
// When > 0, initial mount preload work uses a timeout child context derived from
// the session stdlib context. Eligible resources are started before waiting and
// share that one timeout budget. If the timeout expires, the mount keeps the
// resource in Loading and the normal post-commit resource effect retries on the
// live session loop.
//
// 0 disables waiting, but resources still start opportunistically during the
// initial live mount.
//
// Default: 300ms.
InitialMountResourceTimeout time.Duration
// HeartbeatInterval is the time between heartbeat pings.
// Default: 30 seconds.
HeartbeatInterval time.Duration
// MaxMessageSize is the maximum size of an incoming WebSocket message.
// Default: 64KB.
MaxMessageSize int64
// MaxHandshakePathBytes limits the size of the `?path=` query parameter
// used during the WebSocket handshake (decoded bytes, includes query string).
// 0 means no limit (not recommended).
// Default: 8KB.
MaxHandshakePathBytes int
// MaxPatchHistory is the number of recent patches to keep for resync.
// Default: 100.
MaxPatchHistory int
// MaxEventQueue is the maximum number of queued client events per session.
// When full, new events are dropped and QueueEvent returns ErrEventQueueFull.
// Default: 256.
MaxEventQueue int
// MaxDispatchQueue is the maximum number of queued dispatch callbacks per session.
//
// Dispatch callbacks are framework-critical (they apply Resource/Action results and
// other off-loop work back onto the session loop). They MUST NOT be silently dropped.
// If the dispatch queue is full and a callback cannot be enqueued, the session will
// self-heal (fatal error + reload).
//
// If zero, it defaults to MaxEventQueue for backwards compatibility.
// Default: 2048.
MaxDispatchQueue int
// MaxDetachedSessions limits the number of detached sessions retained in memory.
// 0 means unlimited, which is not recommended for production.
// Default: 10000.
MaxDetachedSessions int
// EvictionPolicy controls which detached session is evicted when MaxDetachedSessions is reached.
// Default: EvictionLRU.
EvictionPolicy SessionEvictionPolicy
// EnableCompression enables WebSocket compression.
// Default: true.
EnableCompression bool
// EnableOptimistic enables optimistic updates on the client.
// Default: true.
EnableOptimistic bool
// DebugMode enables extra validation and logging for development.
// When true:
// - Session.Set() panics on unserializable types (func, chan)
// - auth.Get() logs warnings on type mismatches
// Default: false.
DebugMode bool
// URLPolicy controls scheme allowlists for URL-bearing attributes.
// If zero-valued, defaults are used.
URLPolicy vdom.URLPolicy
// StormBudget configures rate limits for effect primitives to prevent
// amplification bugs (e.g., effect triggers resource refetch triggers effect).
// See SPEC_ADDENDUM.md §A.4.
StormBudget *StormBudgetConfig
// AuthCheck configures authentication freshness checks for the session.
// When nil, no passive or active auth checks are performed.
AuthCheck *AuthCheckConfig
// StateBudget configures persisted state size limits.
StateBudget *corevango.StateBudgetConfig
// Observability controls optional logging for mutations.
Observability corevango.ObservabilityConfig
// Metrics is the sink for runtime metric emissions.
// Nil disables metric emission (safe default).
Metrics corevango.MetricsSink
// EventMiddleware runs for every WebSocket event before handler execution.
// Use this for tracing, logging, or rate limiting (e.g., middleware.OpenTelemetry()).
EventMiddleware []RouteMiddleware
// PersistenceSecret signs persisted blobs.
// This includes session persistence and global-signal blobs when
// global persistence/pubsub paths are enabled.
// Must be 32+ bytes of cryptographically random data.
PersistenceSecret []byte
// PersistenceSecretPrevious allows secret rotation.
// If set, blobs signed with this secret are accepted on resume.
PersistenceSecretPrevious []byte
// MaxBlobAgeMs sets the maximum age in milliseconds for persisted session resume blobs.
// Blobs older than this are rejected during resume, triggering a fresh session.
// This applies to session resume only (not global signals).
// This helps prevent replay attacks with stale session data.
// 0 means no limit (default).
MaxBlobAgeMs int64
// HookEventValidator validates client hook event payloads.
// Return an error to reject the event.
// In production, startup warnings are emitted when this is unset.
HookEventValidator corevango.HookEventValidator
// DOMEventRateLimit applies per-session rate limiting to standard DOM events
// (click/input/scroll/etc., including navigation).
// RatePerSecond <= 0 disables rate limiting.
DOMEventRateLimit *corevango.EventRateLimitConfig
// HookEventRateLimit applies per-session rate limiting to hook events.
// RatePerSecond <= 0 disables rate limiting.
HookEventRateLimit *corevango.EventRateLimitConfig
// HookEventMaxPayloadBytes limits JSON size of hook event payloads.
// 0 means no limit.
HookEventMaxPayloadBytes int
// HookEventMaxNameBytes limits hook event name length in bytes.
// 0 means no limit.
HookEventMaxNameBytes int
// EventHIDMaxBytes limits inbound event HID length in bytes.
// Applies to all event types at ingress and session-loop fallback.
// 0 means no limit.
EventHIDMaxBytes int
// IslandMessageValidator validates island message payloads.
// Return an error to reject the message.
// In production, startup warnings are emitted when this is unset.
IslandMessageValidator corevango.IslandMessageValidator
// IslandEventRateLimit applies per-session rate limiting to island messages.
// RatePerSecond <= 0 disables rate limiting.
IslandEventRateLimit *corevango.EventRateLimitConfig
// IslandEventMaxPayloadBytes limits JSON size of island message payloads.
// 0 means no limit.
IslandEventMaxPayloadBytes int
// IslandEventMaxWrapperBytes limits JSON size of island wrapper payloads.
// Wrapper payloads are the custom event JSON object containing `id` + `payload`.
// 0 means no limit.
IslandEventMaxWrapperBytes int
// IslandEventMaxJSONDepth limits maximum JSON nesting depth for island
// wrapper and payload JSON structures.
// 0 means no limit.
IslandEventMaxJSONDepth int
// IslandEventMaxIDBytes limits island identifier length in bytes.
// 0 means no limit.
IslandEventMaxIDBytes int
// WasmMessageValidator validates WASM message payloads.
// Return an error to reject the message.
// In production, startup warnings are emitted when this is unset.
WasmMessageValidator corevango.WasmMessageValidator
// WasmEventRateLimit applies per-session rate limiting to WASM messages.
// RatePerSecond <= 0 disables rate limiting.
WasmEventRateLimit *corevango.EventRateLimitConfig
// WasmEventMaxPayloadBytes limits JSON size of WASM message payloads.
// 0 means no limit.
WasmEventMaxPayloadBytes int
// WasmEventMaxWrapperBytes limits JSON size of WASM wrapper payloads.
// Wrapper payloads are the custom event JSON object containing `id` + `payload`.
// 0 means no limit.
WasmEventMaxWrapperBytes int
// WasmEventMaxJSONDepth limits maximum JSON nesting depth for WASM
// wrapper and payload JSON structures.
// 0 means no limit.
WasmEventMaxJSONDepth int
// WasmEventMaxIDBytes limits WASM identifier length in bytes.
// 0 means no limit.
WasmEventMaxIDBytes int
// AllowRawHTMLInEventPayloads permits raw HTML or executable strings in
// hook/island/WASM payloads. Default: false.
// NOTE: Vango's unsafe-payload check is a heuristic substring filter,
// not a sanitizer. Always validate and/or sanitize untrusted payloads.
AllowRawHTMLInEventPayloads bool
// AllowHeuristicEventPayloadsInProduction keeps hook/island/WASM payload
// handling in heuristic-only mode in non-dev environments.
//
// This is a break-glass escape hatch. When false (default), non-dev sessions
// reject reachable hook/island/WASM sinks unless they are covered by a
// session-level validator or an exact-sink validated helper.
AllowHeuristicEventPayloadsInProduction bool
// HeuristicEventPayloadRiskAcceptance is a required explicit acknowledgement
// token for non-dev heuristic-only hook/island/WASM payload handling.
//
// Set to HeuristicEventPayloadRiskAcceptanceV1 when you intentionally accept
// heuristic-only event payload screening for reachable sinks in non-dev mode.
HeuristicEventPayloadRiskAcceptance string
// ResyncRateLimitConfig applies per-session rate limiting to resync requests.
// Resync requests can trigger expensive full HTML renders (SendResyncFull) when
// the patch history is exhausted, making them a DoS amplification vector.
//
// A malicious client can repeatedly send resync requests to:
// - Consume CPU (rendering full component tree to HTML)
// - Consume bandwidth (sending large HTML payloads)
// - Amplify per-session cost across many concurrent sessions
//
// Default: 2/sec with burst 5 (conservative, resync should be rare).
// RatePerSecond <= 0 disables rate limiting (NOT RECOMMENDED in production).
ResyncRateLimitConfig *corevango.EventRateLimitConfig
}
SessionConfig holds configuration for individual sessions.
func DefaultSessionConfig ¶
func DefaultSessionConfig() *SessionConfig
DefaultSessionConfig returns a SessionConfig with sensible defaults.
func (*SessionConfig) Clone ¶
func (c *SessionConfig) Clone() *SessionConfig
Clone returns a copy of the SessionConfig.
type SessionError ¶
type SessionError struct {
SessionID string
Op string // Operation that failed
Err error // Underlying error
}
SessionError wraps an error with session context for debugging.
func NewSessionError ¶
func NewSessionError(sessionID, op string, err error) *SessionError
NewSessionError creates a new SessionError.
func (*SessionError) Error ¶
func (e *SessionError) Error() string
Error returns the error message with session context.
func (*SessionError) Unwrap ¶
func (e *SessionError) Unwrap() error
Unwrap returns the underlying error for errors.Is/As.
type SessionEvictionPolicy ¶
type SessionEvictionPolicy int
SessionEvictionPolicy determines which detached sessions are evicted first.
const ( // EvictionLRU evicts the least recently accessed detached sessions first. EvictionLRU SessionEvictionPolicy = iota // EvictionOldest evicts the oldest sessions first (by creation time). EvictionOldest // EvictionRandom evicts sessions randomly (faster but less fair). EvictionRandom )
type SessionLimits ¶
type SessionLimits struct {
// MaxSessions is the maximum number of concurrent sessions.
MaxSessions int
// MaxMemoryPerSession is the approximate memory limit per session.
MaxMemoryPerSession int64
// MaxTotalMemory is the total memory budget for all sessions.
// If exceeded, least recently used sessions are evicted.
MaxTotalMemory int64
}
SessionLimits defines limits for session management.
func DefaultSessionLimits ¶
func DefaultSessionLimits() *SessionLimits
DefaultSessionLimits returns default session limits.
type SessionManager ¶
type SessionManager struct {
// contains filtered or unexported fields
}
SessionManager manages all active sessions. It handles session creation, lookup, cleanup, and lifecycle callbacks.
func NewSessionManager ¶
func NewSessionManager(config *SessionConfig, limits *SessionLimits, logger *slog.Logger) *SessionManager
NewSessionManager creates a new SessionManager with the given configuration.
func NewSessionManagerWithOptions ¶
func NewSessionManagerWithOptions(config *SessionConfig, limits *SessionLimits, logger *slog.Logger, opts *SessionManagerOptions) *SessionManager
NewSessionManagerWithOptions creates a SessionManager with Phase 12 persistence options.
func (*SessionManager) CheckIPLimit ¶
func (sm *SessionManager) CheckIPLimit(ip string) error
CheckIPLimit checks if the IP has exceeded the session limit. Returns ErrTooManySessionsFromIP if the limit is exceeded. This should be called before creating a new session.
func (*SessionManager) CheckMemoryPressure ¶
func (sm *SessionManager) CheckMemoryPressure()
CheckMemoryPressure checks if memory usage exceeds limits and evicts if needed.
func (*SessionManager) Close ¶
func (sm *SessionManager) Close(id string)
Close closes a session by ID and removes it from the manager.
func (*SessionManager) Count ¶
func (sm *SessionManager) Count() int
Count returns the number of active sessions.
func (*SessionManager) DispatchAll ¶
func (sm *SessionManager) DispatchAll(fn func(*Session))
DispatchAll dispatches a function to every active session.
func (*SessionManager) EvictLRU ¶
func (sm *SessionManager) EvictLRU(count int) int
EvictLRU evicts the least recently used sessions. This is called when memory pressure is high.
func (*SessionManager) ForEach ¶
func (sm *SessionManager) ForEach(fn func(*Session) bool)
ForEach iterates over all sessions. The callback should not perform long-running operations as it holds the read lock.
func (*SessionManager) Get ¶
func (sm *SessionManager) Get(id string) *Session
Get retrieves a session by ID.
func (*SessionManager) HasPersistence ¶
func (sm *SessionManager) HasPersistence() bool
HasPersistence returns true if session persistence is configured.
func (*SessionManager) MarkResumed ¶
func (sm *SessionManager) MarkResumed(sessionID string)
MarkResumed removes a session from detached tracking after a successful resume.
func (*SessionManager) OnSessionDisconnect ¶
func (sm *SessionManager) OnSessionDisconnect(sess *Session)
OnSessionDisconnect is called when a WebSocket connection closes. It persists the session state for potential reconnection.
func (*SessionManager) OnSessionReconnect ¶
func (sm *SessionManager) OnSessionReconnect(sessionID string) (*Session, error)
OnSessionReconnect attempts to restore a session after reconnection. Returns ErrSessionNotFound if the session cannot be resumed.
func (*SessionManager) PersistenceManager ¶
func (sm *SessionManager) PersistenceManager() *session.Manager
PersistenceManager returns the underlying persistence manager for advanced use. Returns nil if persistence is not configured.
func (*SessionManager) ResumeWindow ¶
func (sm *SessionManager) ResumeWindow() time.Duration
ResumeWindow returns the configured resume window duration. This is how long detached sessions remain resumable.
func (*SessionManager) SetBudgetTracker ¶
func (sm *SessionManager) SetBudgetTracker(tracker *vango.BudgetTracker)
SetBudgetTracker configures the budget tracker for new sessions.
func (*SessionManager) SetCleanupInterval ¶
func (sm *SessionManager) SetCleanupInterval(d time.Duration)
SetCleanupInterval sets the cleanup interval.
func (*SessionManager) SetMetricsSink ¶
func (sm *SessionManager) SetMetricsSink(sink vango.MetricsSink)
SetMetricsSink updates the metrics sink used for session lifecycle metrics. Call this before creating sessions to ensure they inherit the sink.
func (*SessionManager) SetOnSessionClose ¶
func (sm *SessionManager) SetOnSessionClose(fn func(*Session))
SetOnSessionClose sets the callback for session close.
func (*SessionManager) SetOnSessionCreate ¶
func (sm *SessionManager) SetOnSessionCreate(fn func(*Session))
SetOnSessionCreate sets the callback for session creation.
func (*SessionManager) Shutdown ¶
func (sm *SessionManager) Shutdown()
Shutdown gracefully shuts down all sessions.
func (*SessionManager) ShutdownWithContext ¶
func (sm *SessionManager) ShutdownWithContext(ctx context.Context) error
ShutdownWithContext gracefully shuts down all sessions with context for timeout.
func (*SessionManager) Stats ¶
func (sm *SessionManager) Stats() ManagerStats
Stats returns aggregated session statistics.
func (*SessionManager) TotalMemoryUsage ¶
func (sm *SessionManager) TotalMemoryUsage() int64
TotalMemoryUsage returns the total memory usage of all sessions.
func (*SessionManager) UpdateSessionIP ¶
func (sm *SessionManager) UpdateSessionIP(session *Session, newIP string) error
UpdateSessionIP updates the session's IP address and enforces per-IP limits. Returns ErrTooManySessionsFromIP if the new IP bucket is full.
type SessionManagerOptions ¶
type SessionManagerOptions struct {
// SessionStore is the persistence backend for sessions.
SessionStore session.SessionStore
// ResumeWindow is how long detached sessions remain resumable.
// nil means use the default (5 minutes).
// 0 disables resumption entirely.
ResumeWindow *time.Duration
// MaxDetachedSessions is the maximum detached sessions before LRU eviction.
MaxDetachedSessions int
// MaxSessionsPerIP is the maximum sessions per IP address.
MaxSessionsPerIP int
// EvictOnIPLimit controls whether to evict the oldest detached session
// for a full IP bucket instead of rejecting new sessions.
EvictOnIPLimit bool
// EvictionPolicy determines how detached sessions are evicted when limits are exceeded.
EvictionPolicy SessionEvictionPolicy
// PersistInterval is how often to persist dirty sessions.
PersistInterval time.Duration
// GlobalSignalPubSub is the broadcast backend for global signals.
GlobalSignalPubSub vango.GlobalBroadcastBackend
// GlobalSignalRefreshInterval controls the periodic anti-entropy refresh
// cadence from persistence. When persistence is available, this still runs
// with pubsub enabled to heal missed broadcasts.
GlobalSignalRefreshInterval time.Duration
// RedirectAllowlist is the normalized allowlist for external redirects.
// When nil or empty, external redirects are rejected.
RedirectAllowlist map[allowedAuthority]struct{}
}
SessionManagerOptions contains optional Phase 12 configuration.
type SessionPrimitiveRegistry ¶
type SessionPrimitiveRegistry struct {
// contains filtered or unexported fields
}
SessionPrimitiveRegistry tracks all primitives in a session for inspection.
func NewSessionPrimitiveRegistry ¶
func NewSessionPrimitiveRegistry() *SessionPrimitiveRegistry
NewSessionPrimitiveRegistry creates a new registry.
func (*SessionPrimitiveRegistry) All ¶
func (r *SessionPrimitiveRegistry) All() []*PrimitiveInfo
All returns all registered primitives.
func (*SessionPrimitiveRegistry) AllPersisted ¶
func (r *SessionPrimitiveRegistry) AllPersisted() []*PrimitiveInfo
AllPersisted returns only persisted primitives.
func (*SessionPrimitiveRegistry) FindByDebugName ¶
func (r *SessionPrimitiveRegistry) FindByDebugName(debugName string) []*PrimitiveInfo
FindByDebugName returns all primitives with the given debug name.
func (*SessionPrimitiveRegistry) FindByNameOrID ¶
func (r *SessionPrimitiveRegistry) FindByNameOrID(nameOrID string) (*PrimitiveInfo, bool)
FindByNameOrID resolves a primitive by debugName, stableID, or anchorKey.
func (*SessionPrimitiveRegistry) FindByStableID ¶
func (r *SessionPrimitiveRegistry) FindByStableID(stableID string) []*PrimitiveInfo
FindByStableID returns all primitives with the given stable ID.
func (*SessionPrimitiveRegistry) Register ¶
func (r *SessionPrimitiveRegistry) Register(reg vango.PrimitiveRegistration, instancePath string)
Register adds a primitive to the registry.
func (*SessionPrimitiveRegistry) SignalValue ¶
func (r *SessionPrimitiveRegistry) SignalValue(nameOrID string) (any, bool)
SignalValue returns the current value of a signal by nameOrID.
func (*SessionPrimitiveRegistry) Unregister ¶
func (r *SessionPrimitiveRegistry) Unregister(instancePath string)
Unregister removes a primitive instance by instance path.
type SessionStats ¶
type SessionStats struct {
ID string
UserID string
CreatedAt time.Time
LastActive time.Time
EventCount uint64
PatchCount uint64
BytesSent uint64
BytesRecv uint64
HandlerCount int
ComponentCount int
}
SessionStats contains session statistics.
type StormBudgetConfig ¶
type StormBudgetConfig struct {
// MaxResourceStartsPerSecond limits how many Resource fetches can start per second.
// 0 means no limit.
// Default: 50.
MaxResourceStartsPerSecond int
// MaxActionStartsPerSecond limits how many Action runs can start per second.
// 0 means no limit.
// Default: 100.
MaxActionStartsPerSecond int
// MaxGoLatestStartsPerSecond limits how many GoLatest work items can start per second.
// 0 means no limit.
// Default: 50.
MaxGoLatestStartsPerSecond int
// MaxEffectRunsPerTick limits effect runs within a single event/dispatch tick.
// Helps catch infinite loops where effects trigger effects.
// 0 means no limit.
// Default: 1000.
MaxEffectRunsPerTick int
// WindowDuration is the sliding window for per-second limits.
// Default: 1 second.
WindowDuration time.Duration
// OnExceeded determines what happens when a budget is exceeded.
// Default: BudgetThrottle (drop excess operations).
OnExceeded BudgetExceededMode
}
StormBudgetConfig configures rate limits for effect primitives. These limits help prevent amplification bugs where effects cascade into more effects, potentially causing performance issues or infinite loops.
func DefaultStormBudgetConfig ¶
func DefaultStormBudgetConfig() *StormBudgetConfig
DefaultStormBudgetConfig returns a StormBudgetConfig with sensible defaults. These defaults are conservative but should handle most applications.
type TouchEvent ¶
type TouchEvent struct {
Touches []TouchPoint
}
TouchEvent represents a touch event with touch points.
type TouchPoint ¶
TouchPoint represents a single touch point.
type UnsafeConfigCode ¶ added in v0.2.0
type UnsafeConfigCode string
const ( UnsafeConfigCodeDevMode UnsafeConfigCode = "dev_mode" UnsafeConfigCodeTrustSessionID UnsafeConfigCode = "trust_session_id" UnsafeConfigCodeUnsafeRawHTML UnsafeConfigCode = "unsafe_raw_html" UnsafeConfigCodeInsecureModuleOrigins UnsafeConfigCode = "insecure_module_origins" UnsafeConfigCodeHeuristicEventPayloads UnsafeConfigCode = "heuristic_event_payloads" )
type UnsafeConfigEntry ¶ added in v0.2.0
type UnsafeConfigEntry struct {
Code UnsafeConfigCode
State UnsafeConfigState
Severity UnsafeConfigSeverity
Summary string
Detail string
}
type UnsafeConfigReport ¶ added in v0.2.0
type UnsafeConfigReport struct {
Entries []UnsafeConfigEntry
}
func (UnsafeConfigReport) Empty ¶ added in v0.2.0
func (r UnsafeConfigReport) Empty() bool
type UnsafeConfigSeverity ¶ added in v0.2.0
type UnsafeConfigSeverity string
const ( UnsafeConfigSeverityCritical UnsafeConfigSeverity = "critical" UnsafeConfigSeverityHigh UnsafeConfigSeverity = "high" UnsafeConfigSeverityModerate UnsafeConfigSeverity = "moderate" )
type UnsafeConfigState ¶ added in v0.2.0
type UnsafeConfigState string
const ( UnsafeConfigStateActive UnsafeConfigState = "active" UnsafeConfigStatePermission UnsafeConfigState = "permission" )
Source Files
¶
- client_ip.go
- component.go
- config.go
- context.go
- cookie_security.go
- csp.go
- csrf_http.go
- current_tree_sync.go
- custom_event_security.go
- doc.go
- errors.go
- event_keys.go
- event_security.go
- global_signal_store.go
- handler.go
- handshake_admission.go
- handshake_path.go
- hosted_surface_auth.go
- hosted_surface_verifier.go
- log_events.go
- log_safety.go
- logging_context.go
- manager.go
- memory.go
- metrics.go
- navigate_helpers.go
- navigation.go
- origin_context.go
- patch_history.go
- patch_validation.go
- prefetch.go
- redirect.go
- route_middleware.go
- route_root.go
- runtime_bootstrap.go
- runtime_context.go
- schema_refresh.go
- server.go
- session.go
- session_event_security.go
- session_event_validation_policy.go
- session_initial_mount.go
- session_primitives.go
- session_signal_store.go
- shell_relay.go
- surface_request.go
- test_bypass.go
- thin_client.go
- unsafe_config_report.go
- url_params.go
- user_context.go
- websocket.go