app

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 20, 2026 License: MIT Imports: 27 Imported by: 0

Documentation

Overview

Package app is the maping-server composition root. It wires the storage writer, ingest guardrails, control plane, auth layer, and dashboard from the environment and runs the HTTP server until a shutdown signal.

The wiring lives here rather than in package main so the control-plane- dependent decisions — whether the dashboard is auth-gated, the self-serve key-admin adapter, and the CSRF/session-key plumbing — are unit-testable against fakes without a live Postgres. main is a thin shell over Run.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(log *slog.Logger, opts ...Option) error

Run builds the collector and serves it until a shutdown signal, then drains gracefully. It is the whole of what func main delegates to.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

App is the built composition root: the fully-assembled HTTP mux plus the resources Serve runs and shutdown releases. build performs every wiring decision (infra construction + assembleMux); Serve runs the listener until a signal and drains gracefully. The split lets a test assert the wiring (via assembleMux) with fakes, without binding a socket or a live ClickHouse.

func (*App) Serve

func (a *App) Serve() error

Serve runs the HTTP listener until SIGINT/SIGTERM, then drains gracefully: mark not-ready, stop accepting, drain the ingest->ClickHouse batcher (final flush with bounded retry) before releasing the control-plane pool so the last buffered summaries are not lost on a deploy restart, and cancel background jobs.

type BackgroundJob

type BackgroundJob func(JobContext)

BackgroundJob is a long-running task started after boot and stopped at shutdown via JobContext.Ctx.

type InviteInfo

type InviteInfo = web.InviteInfo

InviteInfo is a listed pending invite rendered in the team panel.

type JobContext

type JobContext struct {
	Ctx  context.Context
	Pool *pgxpool.Pool
	Log  *slog.Logger
}

JobContext is what a WithBackgroundJob task receives. Ctx is cancelled at shutdown, so a well-behaved job runs until Ctx.Done(). Pool is nil in dev mode.

type LimitProvider

type LimitProvider = guardrail.LimitProvider

LimitProvider is the per-tenant limits source the ingest guardrails resolve through. A composing build implements it to layer its own behavior (e.g. an account lifecycle) over the core plan budget.

type LimitProviderFactory

type LimitProviderFactory func(base LimitProvider, pool *pgxpool.Pool) LimitProvider

LimitProviderFactory decorates the core LimitProvider with the injecting build's own behavior — e.g. an account lifecycle (suspend/trial) the composing build reads from its own schema. base is the plain plan-budget provider; pool is the control-plane pool (never nil when this factory runs, since limits require a control plane). It returns the provider the ingest guardrails resolve through. It names the public LimitProvider alias so a composing module (which cannot import server/internal/guardrail) can implement it.

type Limits

type Limits = guardrail.Limits

Limits is a tenant's resolved guardrail budget (rate, burst, cardinality, payload, retention).

func DefaultLimits

func DefaultLimits() Limits

DefaultLimits is the free-tier budget a provider falls back to for an unknown plan. Re-exported so a composing provider can return it without importing the internal guardrail package.

type LoginInterceptor

type LoginInterceptor = auth.LoginInterceptor

LoginInterceptor is the post-authentication hook the OIDC callback consults before the default first-login path. A composing build implements it to bind an identity resolved out of band (e.g. an accepted invite) and finish login.

type LoginInterceptorFactory

type LoginInterceptorFactory func(pool *pgxpool.Pool) LoginInterceptor

LoginInterceptorFactory builds the composed post-auth hook once the control- plane pool exists (the invite store the hook drives needs it). pool is never nil when this runs, since the hook is only constructed with a control plane.

type MemberAdmin

type MemberAdmin = web.MemberAdmin

MemberAdmin is the self-serve team surface (members + invites) the Setup page renders. A composing build supplies one to expose the team panel.

type MemberAdminFactory

type MemberAdminFactory func(pool *pgxpool.Pool) MemberAdmin

MemberAdminFactory builds the team-panel admin once the control-plane pool exists. pool is never nil when this runs.

type MemberInfo

type MemberInfo = web.MemberInfo

MemberInfo is a listed org member rendered in the team panel.

type Option

type Option func(*options)

Option configures Run.

func WithAccountLink(href string) Option

WithAccountLink turns the dashboard sidebar's user-identity block into a link to href — a composing build points it at the account page it owns (e.g. "/account"). Public default: empty, so the block stays a non-interactive display element. The composing build should only set it when it actually mounts that route (e.g. gating on the control plane) so the link never points at a 404.

func WithBackgroundJob

func WithBackgroundJob(j BackgroundJob) Option

WithBackgroundJob registers a task launched after boot in its own goroutine and cancelled at shutdown. Multiple jobs each get their own goroutine.

func WithDocHeaderLinks(links ...docs.Link) Option

WithDocHeaderLinks adds site links to the /doc top bar (e.g. Pricing, Sign in), so a visitor who reached the documentation from the marketing site can navigate back to it. A composing build injects the links to its own public routes; the community build injects none (the top bar then shows only the home brand), so no link ever points at a route the build does not serve.

func WithDocSections

func WithDocSections(sections ...docs.Section) Option

WithDocSections adds entries to the shared /doc table of contents (the left rail on every documentation page). A composing build registers its own doc topics here so they appear alongside the core product pages; it mounts the pages themselves via WithRoutes, rendering each through RouteContext.RenderDoc. Public default: none, so the community build shows only the core product sections.

func WithExtraMigrations

func WithExtraMigrations(fsys fs.FS, dir string) Option

WithExtraMigrations registers an additional control-plane migration source applied, in lexical filename order, AFTER the embedded core migrations. A composing build passes its own schema (its own plan rows and tables) here so the public core never carries it. Multiple sources apply in registration order. Files must be additive and idempotent, exactly like the core migrations. It has no effect in static dev mode (no control plane to migrate).

func WithLimitProvider

func WithLimitProvider(factory LimitProviderFactory) Option

WithLimitProvider decorates the core LimitProvider that drives the ingest guardrails (rate, payload, cardinality). The composing build passes its own provider to layer its own limit policy on top; the public default (no option) resolves the plain plan budget. It has no effect in static dev mode, where there is no control plane to resolve limits.

func WithLoginInterceptor

func WithLoginInterceptor(factory LoginInterceptorFactory) Option

WithLoginInterceptor wires a post-authentication hook (e.g. an invitation accept flow) the OIDC callback consults before the default first-login path. The factory receives the control-plane pool the hook's store needs. Public default: none (plain login). No effect in static dev mode (no control plane).

func WithMemberAdmin

func WithMemberAdmin(factory MemberAdminFactory) Option

WithMemberAdmin wires the self-serve team panel (members + invites) the Setup page renders. The factory receives the control-plane pool the admin's store needs. Public default: nil, so the dashboard hides the team panel. No effect in static dev mode (no control plane).

func WithPublicHome

func WithPublicHome(home http.HandlerFunc) Option

WithPublicHome wires the anonymous landing page served at "/". When set, an unauthenticated visitor to "/" gets this handler while signed-in users and every dashboard sub-path fall through to the gated dashboard; a composing build registers any companion routes via WithRoutes. Public default: nil, so anonymous "/" redirects to /login (the self-host/OSS surface serves no landing page).

func WithRoutes

func WithRoutes(r RouteRegistrar) Option

WithRoutes registers a RouteRegistrar mounted after the core routes. Multiple registrars run in registration order.

type PostAuthContext

type PostAuthContext = auth.PostAuthContext

PostAuthContext is the capability a LoginInterceptor receives to start a dashboard session for the member it resolved.

type RouteContext

type RouteContext struct {
	Mux  *http.ServeMux
	Pool *pgxpool.Pool
	Log  *slog.Logger
	// Gate wraps a handler in the dashboard auth middleware (session-cookie
	// verification, redirect/401 on failure) so an extension can mount its own
	// authenticated routes with the same gate the dashboard uses. It is nil when
	// auth is off (no control plane) — a registrar that needs auth must check and
	// mount nothing.
	Gate func(http.Handler) http.Handler
	// SessionOrg reads the caller's verified org id from a request that has passed
	// through Gate. It is the ONLY sanctioned way for an extension to learn the
	// caller's org (never the request body), keeping the session context key
	// private to auth. Nil when auth is off.
	SessionOrg func(*http.Request) (orgID string, ok bool)
	// RenderShell writes a full dashboard page (sidebar + top bar chrome) wrapping
	// the given content, so an extension's own page looks native to the dashboard
	// instead of a detached page. content is trusted HTML the caller produced from a
	// template; title sets the top-bar heading and browser tab. Always non-nil.
	RenderShell func(w http.ResponseWriter, r *http.Request, title string, content template.HTML)
	// RenderDoc writes a full public documentation page (the /doc dark shell with the
	// shared table of contents in the left rail) wrapping the given body, so an
	// extension's own doc page is indistinguishable from a core one. body is trusted
	// HTML — a composing build produces it from its embedded Markdown via
	// docs.MarkdownToHTML. Unlike RenderShell the page is public (no auth chrome), so
	// this is the seam for extension /doc/* pages. Always non-nil.
	RenderDoc func(w http.ResponseWriter, r *http.Request, title string, body template.HTML)
}

RouteContext is what a WithRoutes registrar receives to mount extra routes. Pool is the control-plane pool, nil in static dev mode (no MAPING_POSTGRES_DSN).

type RouteRegistrar

type RouteRegistrar func(RouteContext)

RouteRegistrar mounts additional routes on the server mux. It runs after the core routes, so its patterns must not collide with the core surfaces (/healthz, /, the /login and /auth routes, and the ingest path).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL