Documentation
¶
Index ¶
- Constants
- func AuthMappings(ms []config.GroupRoleMapping) []auth.GroupRoleMapping
- func LandingPageCSP() string
- func RecoverPanic(logger *slog.Logger, next http.Handler) http.Handler
- func RequestIDFromContext(ctx context.Context) string
- func SecurityHeaders(trustedNets []*net.IPNet, scriptSources, styleSources []string, ...) http.Handler
- type FargateBundleHandler
- type FirstFireRef
- type ManifestAccessGroupResult
- type ManifestApplied
- type ManifestScheduleResult
- type Server
- func (s *Server) ClientIP(r *http.Request) string
- func (s *Server) ColocationPins(app *db.App) []string
- func (s *Server) Config() *config.Config
- func (s *Server) DeployInFlight(slug string) bool
- func (s *Server) HandleAppsJSON(w http.ResponseWriter, r *http.Request)
- func (s *Server) HandleBrandingJSON(w http.ResponseWriter, r *http.Request)
- func (s *Server) Observe(next http.Handler) http.Handler
- func (s *Server) Router() http.Handler
- func (s *Server) ScaleDown(slug string, grace time.Duration) (bool, error)
- func (s *Server) ScaleUp(slug string) (bool, error)
- func (s *Server) SetCluster(instanceID string)
- func (s *Server) SetDeployRunForTest(fn func(deploy.Params) (*deploy.PoolResult, error))
- func (s *Server) SetDeployToken(t *auth.DeployToken)
- func (s *Server) SetGitHubProvider(g *oauth.GitHub)
- func (s *Server) SetGoogleProvider(g *oauth.Google)
- func (s *Server) SetHistory(h *history.Store)
- func (s *Server) SetJobs(j *jobs.Manager, sc *scheduler.Scheduler)
- func (s *Server) SetLoginLimiterWindowForTest(window time.Duration)
- func (s *Server) SetMetrics(m *metrics.Registry)
- func (s *Server) SetNodeForTier(fn func(tier string) string)
- func (s *Server) SetOIDCProvider(p *oauth.OIDCProvider)
- func (s *Server) SetOwnership(isOwner func() bool)
- func (s *Server) SetRenderPacingCores(cores float64, source string)
- func (s *Server) SetSampler(sampler process.Sampler)
- func (s *Server) SetSecretsCleaner(c appSecretsCleaner)
- func (s *Server) SetSecretsKey(k []byte)
- func (s *Server) SetTraceBuffer(b *tracing.Buffer)
- func (s *Server) SetTracer(t *servertrace.Tracer)
- func (s *Server) SetVersion(v string)
- func (s *Server) SetWorkerRegistry(reg *worker.Registry)
- func (s *Server) WarmExpand(slug string) (bool, error)
- func (s *Server) WarmShrink(slug string, floor int, grace time.Duration) (bool, error)
- type WorkerAPI
Constants ¶
const RequestIDHeader = "X-Request-Id"
RequestIDHeader carries the per-request correlation ID. It is honored on inbound requests (so an ID minted by a trusted edge proxy survives through ShinyHub) and echoed on every response so clients and log aggregators can stitch a single request together across tiers.
Variables ¶
This section is empty.
Functions ¶
func AuthMappings ¶ added in v0.8.2
func AuthMappings(ms []config.GroupRoleMapping) []auth.GroupRoleMapping
AuthMappings converts config group-role mappings into the auth-package type.
func LandingPageCSP ¶ added in v0.8.29
func LandingPageCSP() string
LandingPageCSP is the policy for an operator-configured custom landing page (branding.landing_page). That file is operator-supplied, trusted HTML that may use inline scripts/styles, so - unlike the strict, inline-free SPA policy - it permits 'unsafe-inline' (the pre-hash behavior, reused via the same builder). The landing handler sets it on that one response only; the SPA shell, assets, and API keep the strict policy.
func RecoverPanic ¶ added in v0.9.6
RecoverPanic wraps next so a panic in a downstream handler is logged and converted to a 500 instead of crashing the connection (and, on paths without their own recovery, escaping to the stdlib server's per-connection default which bypasses structured logging). chi.Recoverer already guards /api/*; this covers the outer mux paths - notably the /app/* reverse proxy.
http.ErrAbortHandler is re-panicked so the stdlib server aborts the connection as intended (used to silently drop a hijacked/streaming connection).
func RequestIDFromContext ¶ added in v0.6.2
RequestIDFromContext returns the correlation ID assigned to the request, or "" when the access-log middleware did not run (e.g. a handler exercised directly in a test). Handlers use it to tag their own structured logs with the same ID the access log records.
func SecurityHeaders ¶ added in v0.7.1
func SecurityHeaders(trustedNets []*net.IPNet, scriptSources, styleSources []string, next http.Handler) http.Handler
SecurityHeaders sets defensive response headers on control-plane responses. Proxied app responses under /app/ are intentionally left untouched: they are separate, operator-supplied content that may legitimately be embedded in an iframe and run their own inline scripts/styles, so imposing the control-plane CSP/framing policy on them would break working apps. trustedNets is the configured trusted-proxy CIDR list (cfg.TrustedProxyNets), used to decide the request scheme for HSTS the same way session cookies decide their Secure flag. scriptSources/styleSources are the CSP hash allowances for the active branding inline blocks (ui.CSPInlineSources); both empty when branding is off.
Types ¶
type FargateBundleHandler ¶ added in v0.7.0
type FargateBundleHandler struct {
// contains filtered or unexported fields
}
FargateBundleHandler serves bundle zips to Fargate tasks that authenticate with a short-lived HMAC capability token (Authorization: Bearer). It is mounted on GET /internal/fargate-bundle/{digest} directly on the main mux so large bundle streams are not subject to the apiTimeoutHandler's 30s cap. Per-source-IP rate limiting bounds invalid-token probing.
func NewFargateBundleHandler ¶ added in v0.7.0
func NewFargateBundleHandler(store *db.Store, appsDir string, tokenKey []byte) *FargateBundleHandler
NewFargateBundleHandler constructs a handler with production rate-limit settings (10 requests per minute per source IP).
func (*FargateBundleHandler) Handle ¶ added in v0.7.0
func (h *FargateBundleHandler) Handle(w http.ResponseWriter, r *http.Request)
Handle verifies the bearer token, then delegates to serveBundleByDigest.
type FirstFireRef ¶ added in v0.8.2
type FirstFireRef struct {
RunID int64 `json:"run_id"`
}
FirstFireRef points the CLI at the run dispatched by run_on_register so it can report it and (under --wait-for-warm) poll it to completion.
type ManifestAccessGroupResult ¶ added in v0.8.2
type ManifestAccessGroupResult struct {
Group string `json:"group"`
Role string `json:"role"`
Skipped bool `json:"skipped,omitempty"` // true when a manual rule preempted this manifest rule
}
ManifestAccessGroupResult records the outcome of one [access] group rule reconciled from the manifest into app_group_access.
type ManifestApplied ¶ added in v0.5.0
type ManifestApplied struct {
App map[string]any `json:"app,omitempty"`
Schedules []ManifestScheduleResult `json:"schedules,omitempty"`
AccessGroups []ManifestAccessGroupResult `json:"access_groups,omitempty"`
}
ManifestApplied summarises what the manifest changed during this deploy. Returned alongside the app in the deploy response so CLI / UI can show the operator a concrete record of what landed.
func (*ManifestApplied) IsEmpty ¶ added in v0.5.0
func (m *ManifestApplied) IsEmpty() bool
IsEmpty reports whether nothing was applied. The handler omits the field from the response in that case so the wire shape stays clean.
type ManifestScheduleResult ¶ added in v0.5.0
type ManifestScheduleResult struct {
Name string `json:"name"`
Action string `json:"action"` // "created" or "updated"
ScheduleID int64 `json:"schedule_id,omitempty"`
FirstFire *FirstFireRef `json:"first_fire,omitempty"`
}
ManifestScheduleResult records the outcome of one [[schedule]] upsert so callers can surface a per-schedule action in their response.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server holds the dependencies shared by all API handlers.
func New ¶
New constructs a Server and wires up all routes. manager and prx may be nil when running in test contexts that exercise only auth/data handlers.
func (*Server) ClientIP ¶ added in v0.2.3
ClientIP returns the best-effort client IP, honouring X-Forwarded-For only when the direct peer is in the configured trusted-proxy CIDRs. Exposed so other subsystems (e.g. the reverse proxy access log) share the same trust policy without duplicating it.
func (*Server) ColocationPins ¶ added in v0.7.0
ColocationPins returns the worker node ids a shared-mount consumer must be pinned to so each replica co-locates with its source data, or nil when there is no colocation constraint or it cannot currently be satisfied. It is the best-effort form of resolveColocation (it swallows the infeasibility error) exposed so the lifecycle watchdog's single-replica restart pins a recovered replica to the same worker set the full deploy uses; an unsatisfiable pin falls back to unconstrained placement rather than wedging recovery.
func (*Server) Config ¶ added in v0.2.1
Config returns the server's configuration. Exposed for tests that need to locate temp directories (e.g. AppsDir, AppDataDir) created by the test helper.
func (*Server) DeployInFlight ¶ added in v0.10.8
DeployInFlight reports whether this instance currently holds the per-slug deploy lock for slug (a deploy, rollback, restart, stop, or delete is executing). The proxy's miss-status lookup combines it with the pending deployment row to tell a live deploy window apart from a stale pending row left by a PromoteDeployment failure. Cheap: one small map read.
func (*Server) HandleAppsJSON ¶ added in v0.5.4
func (s *Server) HandleAppsJSON(w http.ResponseWriter, r *http.Request)
HandleAppsJSON returns the minimal DTO for exactly the apps the caller may see:
- anonymous -> public apps only (via ListPublicApps, separate query)
- admin/operator -> all apps (via ListApps)
- other authenticated users -> public + shared + owned + member apps
func (*Server) HandleBrandingJSON ¶ added in v0.5.4
func (s *Server) HandleBrandingJSON(w http.ResponseWriter, r *http.Request)
HandleBrandingJSON is always public (no auth required). Returns an empty object when branding is not configured.
func (*Server) Observe ¶ added in v0.6.0
Observe wraps the API handler chain (timeout handler included) with server tracing and Prometheus instrumentation so both record the status and latency the client actually observes - covering recovered panics (the inner chi Recoverer writes the 500 before observation reads it) and timeout responses (http.TimeoutHandler writes the 503 below observation). Both layers are no-ops when their dependency (tracer / metrics registry) is nil, so observation is opt-in.
The matched route pattern is resolved once, before the inner chain runs, by calling Match on a private route context. The resulting pattern string is stashed in the request context via httproute.WithPattern so metrics and tracing can read it as an immutable value after the inner handler returns. This avoids sharing a mutable chi.RouteContext across an http.TimeoutHandler boundary: under a timeout, the TimeoutHandler returns (writing the 503) while the inner chi mux goroutine is still mutating the same RouteContext's RoutePatterns slice, causing a data race on the outer read.
Must be wired before the server begins handling requests.
func (*Server) ScaleDown ¶ added in v0.7.0
ScaleDown gracefully removes the highest-index replica. It marks the proxy slot draining (the least-connections picker stops routing new cookie-less sessions to it while sticky-cookie sessions keep flowing), waits up to grace for active sessions to finish, then stops the replica, shrinks the proxy pool, deletes the replica row, and decrements the app's replica count. It returns (false, nil) when the app is already at one replica (the floor) and (true, nil) when a replica was removed. Serialized via the per-slug deploy lock. When grace elapses with sessions still active the replica is stopped anyway: the operation is deadline-bounded so the controller never stalls.
func (*Server) ScaleUp ¶ added in v0.7.0
ScaleUp boots one additional replica at the next trailing index, growing the pool by one without cycling the existing replicas. It returns (true, nil) when a replica was added and (false, nil) for the benign no-op cases the autoscale controller treats as "already at the ceiling": the app is not running, or it is already at the runtime max-replicas limit. Errors are reserved for genuine failures (missing deployment, boot failure, persistence error). The whole operation is serialized against deploy/restart/rollback/ redeploy through the per-slug deploy lock.
func (*Server) SetCluster ¶ added in v0.8.1
SetCluster marks this instance as part of a multi-instance cluster and records its unique identity. In clustered mode, ScaleDown also writes desired_state to the DB before the drain wait and polls the fleet-wide session count (excluding this instance) alongside the local count. Must be called before the server begins handling requests; not safe to call concurrently with live traffic.
func (*Server) SetDeployRunForTest ¶ added in v0.2.1
SetDeployRunForTest replaces the deploy.Run hook used by maybeRestartForChange. Must be called before the server begins handling requests; intended for tests.
func (*Server) SetDeployToken ¶ added in v0.4.0
func (s *Server) SetDeployToken(t *auth.DeployToken)
SetDeployToken installs a pre-shared deploy credential. Must be called before the server begins handling requests; it is not safe to call concurrently with ServeHTTP.
func (*Server) SetGitHubProvider ¶ added in v0.9.6
SetGitHubProvider replaces the GitHub OAuth provider after the server is constructed. Must be called before the server begins handling requests. Production wiring happens in New via cfg.OAuth.GitHub; this setter exists so tests can point a GitHub provider at a fake server (see SetTestEndpoints on oauth.GitHub).
func (*Server) SetGoogleProvider ¶ added in v0.9.6
SetGoogleProvider replaces the Google OAuth provider after the server is constructed. Must be called before the server begins handling requests. Production wiring happens in New via cfg.OAuth.Google; this setter exists so tests can point a Google provider at a fake server (see SetTestEndpoints on oauth.Google).
func (*Server) SetHistory ¶ added in v0.8.14
SetHistory wires the in-memory metrics-history store that serves the Trends endpoint. nil (the default) means history collection is disabled: the endpoint returns an empty series. Must be called before the server begins handling requests.
func (*Server) SetJobs ¶ added in v0.2.1
SetJobs wires the schedule-runner and the cron scheduler into the API server. Must be called before the server begins handling requests.
func (*Server) SetLoginLimiterWindowForTest ¶ added in v0.10.13
SetLoginLimiterWindowForTest rebuilds the login limiter with a different window, keeping the production limit.
The limiter is a FIXED window bucketed on floor(now/window), not a sliding one, so a burst of attempts that straddles a window boundary starts a fresh count and the over-limit attempt is legitimately allowed. At the production window of one minute, a test firing a burst of logins has a real chance of crossing a minute tick - roughly the burst duration over sixty seconds. That is what made TestLoginRateLimit_BlocksAfterThreshold flaky on Postgres, where every attempt pays a database round trip on top of bcrypt.
A long window removes the straddle without changing the behaviour under test: the limit, the backend, and the code path are all still the production ones. Must be called before the server begins handling requests.
func (*Server) SetMetrics ¶ added in v0.6.0
SetMetrics wires the Prometheus registry whose middleware records per-request counters and latencies for the API router. May be nil (the default) to leave metrics disabled. Must be called before the server begins handling requests; it is not safe to call concurrently with ServeHTTP.
func (*Server) SetNodeForTier ¶ added in v0.6.1
SetNodeForTier injects the tier-to-node resolver used to reject cross-node shared mounts. Wired at startup from the worker registry; left nil when worker hosting is disabled. Must be called before the server begins handling requests.
func (*Server) SetOIDCProvider ¶
func (s *Server) SetOIDCProvider(p *oauth.OIDCProvider)
SetOIDCProvider sets the OIDC provider after the server is constructed. Must be called before the server begins handling requests.
func (*Server) SetOwnership ¶ added in v0.7.4
SetOwnership wires the predicate reporting whether this instance holds the control-plane ownership lease. Mutating API requests are rejected with 503 on a non-owner so that during a zero-downtime handoff only the lease owner mutates cluster state. Call this once during startup before the server begins handling requests; it is not safe to call concurrently with live traffic.
func (*Server) SetRenderPacingCores ¶ added in v0.10.16
SetRenderPacingCores records the effective host cores (and the source that won) used to compute the render-pacing cap suggestion. Called once at startup; Detect is never invoked on the request path.
func (*Server) SetSampler ¶
SetSampler replaces the metrics sampler. Must be called before the server begins handling requests; it is not safe to call concurrently with ServeHTTP.
func (*Server) SetSecretsCleaner ¶ added in v0.7.2
func (s *Server) SetSecretsCleaner(c appSecretsCleaner)
SetSecretsCleaner wires the external secret-backend cleanup invoked on app delete. Called at startup when a Fargate secrets backend is configured; left nil otherwise. Must be called before the server handles requests.
func (*Server) SetSecretsKey ¶
SetSecretsKey sets the AES-256 key used to decrypt per-app secret env vars. Must be called before the server begins handling requests.
func (*Server) SetTraceBuffer ¶ added in v0.4.1
SetTraceBuffer wires the proxy's ring buffer of recent slow/error spans into the API server so the /api/apps/{slug}/traces handler can surface them. May be nil when tracing is disabled — the handler then returns an empty list. Must be called before the server begins handling requests.
func (*Server) SetTracer ¶ added in v0.6.0
func (s *Server) SetTracer(t *servertrace.Tracer)
SetTracer wires the OpenTelemetry tracer whose middleware records one server span per API request, exported to the configured OTLP endpoint. May be nil (the default) to leave server tracing disabled. Must be called before the server begins handling requests; it is not safe to call concurrently with ServeHTTP.
func (*Server) SetVersion ¶ added in v0.7.0
SetVersion records the binary version string advertised by GET /api/server-info. The parent binary calls this at startup so the server and the CLI subcommands report the same version.
func (*Server) SetWorkerRegistry ¶ added in v0.6.2
SetWorkerRegistry injects the worker registry backing the admin fleet endpoints (list and revoke). Wired at startup from the worker registry; left nil when worker hosting is disabled. Must be called before the server begins handling requests.
func (*Server) WarmExpand ¶ added in v0.8.6
WarmExpand boots every warm-parked replica (desired_state='warm') back to running, restoring full configured capacity after a warm shrink. Runs under the per-slug deploy lock. Manual stops (desired_state='stopped') are never touched. A victim that fails to boot is handed to the watchdog (row marked crashed/running) and the error is returned alongside any successfully restored capacity. Returns (false, nil) when no warm rows exist.
func (*Server) WarmShrink ¶ added in v0.8.6
WarmShrink drains and stops every running replica above floor, marking the rows desired_state='warm' so reconcile, recovery, and warm-expansion can distinguish them from crash-stopped and manually-stopped replicas. app.Replicas is not touched: configured capacity is immutable here; only runtime state changes. Runs under the per-slug deploy lock, serializing against deploys, ScaleDown, and restarts.
Returns (false, nil) when the app is not running/degraded, or when nothing above the (replica-clamped) floor is running. On a partial failure the loop stops and returns the error; rows already written as stopped/warm survive so a re-run can complete idempotently.
type WorkerAPI ¶ added in v0.6.1
type WorkerAPI struct {
// contains filtered or unexported fields
}
WorkerAPI serves the worker-facing endpoints (register, heartbeat, bundle fetch). It is mounted on a dedicated mTLS listener; the register path is the only one reachable before a client cert exists and is rate-limited per source.
func NewWorkerAPI ¶ added in v0.6.1
NewWorkerAPI constructs the worker API with a default short cert TTL. appsDir is the root directory under which per-app bundle zips are stored; it may be empty during tests that override appsDir directly.
func (*WorkerAPI) HandleBundleFetch ¶ added in v0.6.1
func (a *WorkerAPI) HandleBundleFetch(w http.ResponseWriter, r *http.Request)
HandleBundleFetch streams the stored bundle zip for a content digest. The caller (worker agent) presents a mTLS client certificate for authentication. Bundle serving is delegated to the shared serveBundleByDigest helper so both the mTLS worker path and the Fargate capability-token path have identical behavior.
func (*WorkerAPI) HandleHeartbeat ¶ added in v0.6.1
func (a *WorkerAPI) HandleHeartbeat(w http.ResponseWriter, r *http.Request)
func (*WorkerAPI) HandleRegister ¶ added in v0.6.1
func (a *WorkerAPI) HandleRegister(w http.ResponseWriter, r *http.Request)
func (*WorkerAPI) SetOwnership ¶ added in v0.8.0
SetOwnership wires the control-plane ownership-and-readiness predicate. Until it is set (tests, or a single-node build that never constructs an elector) the worker mutation endpoints serve unconditionally; the production boot path sets a reject-all predicate before the listener serves and upgrades it afterward.
Source Files
¶
- access_log.go
- apps.go
- audit.go
- auth.go
- authorization.go
- branding.go
- bundle_handler.go
- data.go
- deployfail.go
- durable_data.go
- env.go
- fleet_health.go
- headers.go
- helpers.go
- icons.go
- logs.go
- manifest_apply.go
- metrics_history.go
- oauth.go
- oidc_handler.go
- precondition.go
- recover.go
- redeploy.go
- render_pacing.go
- router.go
- scale.go
- schedules.go
- schedules_status.go
- serverinfo.go
- traces.go
- upload.go
- users.go
- warm.go
- workers.go
- workers_admin.go