httpapi

package
v0.0.0-...-34d4359 Latest Latest
Warning

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

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

Documentation

Overview

Package httpapi serves the browser UI (byte-compatible with the old Python beads_ui endpoints), a versioned REST API, and mounts the MCP handler. App routes are guarded by a pluggable Authenticator; operational endpoints (/healthz, /readyz, /version, /metrics) and the login endpoints are public.

Two seams make tasksd embeddable by a larger host (e.g. a multi-tenant control plane) WITHOUT tasksd knowing anything about tenants/SaaS:

  • Config.Auth (Authenticator) — plug in custom request authorization.
  • Config.Resolve (CoreResolver) — choose the *core.Core (i.e. the DB) per request; the default just returns the single global core.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func RequestID

func RequestID(ctx context.Context) string

RequestID extracts the request id from a context ("" if absent).

Types

type Authenticator

type Authenticator interface {
	// Authorize returns the identity for a request and whether it is allowed.
	Authorize(r *http.Request) (Identity, bool)
}

Authenticator authorizes requests. Built-in implementations are none (allow all — loopback/dev) and token (a shared bearer token). Embedders — e.g. a separate multi-tenant control plane — can supply their own (say, a JWT-verifying authenticator) without tasksd knowing anything about it.

type Config

type Config struct {
	Core   *core.Core // the single/default core (nil allowed if Resolve is set)
	Static fs.FS
	Logger *slog.Logger

	// Auth authorizes requests. If nil, one is derived from Token: a shared-token
	// authenticator when Token != "", otherwise no-auth (loopback/dev).
	Auth  Authenticator
	Token string

	// APIKeys enables DB-backed API-key auth (Bearer tasks_<secret>) verified
	// against Core, layered in front of the Token/Auth login flow. Requires Core.
	APIKeys bool

	// Resolve selects the Core per request (for embedders). nil -> always Core.
	Resolve CoreResolver

	// TopicFor maps a request to the tenant/board key its live (WebSocket) updates
	// belong to, so a mutation in one workspace only reaches that workspace's
	// sockets. nil -> a single global topic (single-tenant). It MUST derive the
	// same key used to route Publish calls (typically the org id).
	TopicFor func(r *http.Request) string

	// CSP overrides the Content-Security-Policy header. Set it when the UI must
	// reach an external origin (e.g. a hosted identity provider whose scripts and
	// API calls the default 'self'-only policy would block). Empty -> the strict
	// default. Must be kept in sync with whatever InjectHead loads.
	CSP string

	// LoginURL, when set, is reported by /api/authinfo so the UI redirects an
	// unauthenticated visitor to a hosted sign-in page (used with a custom Auth).
	LoginURL string

	// ResourceMetadataURL, when set, is advertised in the 401 WWW-Authenticate
	// header (RFC 9728) so an OAuth-capable MCP client discovers the authorization
	// server. Generic OAuth-resource-server support; the AS itself lives in the host.
	ResourceMetadataURL string

	// InjectHead, when set, is spliced into index.html before </head>. A host uses
	// it to add e.g. an identity-provider script that keeps a session alive on the
	// board page; the engine stays agnostic about what it injects.
	InjectHead string

	MCP http.Handler

	MaxBodyBytes int64
	RateLimit    float64
	RateBurst    int
	BehindProxy  bool
	CORSOrigins  []string
	Metrics      bool
}

Config configures the server.

type CoreResolver

type CoreResolver func(r *http.Request) (*core.Core, error)

CoreResolver selects the Core (DB) to serve a request. Return an error to reject (e.g. unknown tenant). nil resolver -> the single global core is used.

type Identity

type Identity struct {
	Subject string
	Claims  map[string]string
}

Identity describes an authenticated principal. Subject is a stable id ("token" for shared-token mode, a user id for an embedder's auth); Claims carries extra data (e.g. an org/tenant id) that a CoreResolver can read.

func IdentityFrom

func IdentityFrom(ctx context.Context) (Identity, bool)

IdentityFrom returns the authenticated identity stored in the request context.

type LoginProvider

type LoginProvider interface {
	Login(w http.ResponseWriter, r *http.Request)
	Logout(w http.ResponseWriter, r *http.Request)
}

LoginProvider is an optional interface an Authenticator may implement to power the browser login flow. When present, the server mounts POST /api/login and POST /api/logout to it (both public, ahead of the auth gate).

type Server

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

Server is the HTTP surface.

func New

func New(cfg Config) *Server

New builds a Server.

func (*Server) Handler

func (s *Server) Handler() http.Handler

Handler returns the fully-wired http.Handler (middleware + auth + routes).

func (*Server) Publish

func (s *Server) Publish(topic string, ids []string)

Publish broadcasts a "changed" signal naming the affected task id(s) to every socket subscribed to topic. Wire it to a Core's onChange hook (single-tenant: topic ""; multi-tenant: the org/workspace key). Safe to call from any surface.

func (*Server) Touch

func (s *Server) Touch()

Touch advances the UI's mtime freshness signal. Register it as a core onChange hook so any mutation (HTTP/MCP/CLI) refreshes it.

Jump to

Keyboard shortcuts

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