api

package
v0.4.0-rc.1 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2026 License: AGPL-3.0 Imports: 71 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewRouter

func NewRouter(cfg RouterConfig) http.Handler

func RealIP

func RealIP(cfg *RealIPConfig) func(http.Handler) http.Handler

RealIP returns middleware that overwrites r.RemoteAddr with the client's real IP extracted from X-Real-IP or X-Forwarded-For, but only when the direct connection comes from a trusted proxy.

func SubdomainProxy

func SubdomainProxy(agentDomain string, database *db.DB, s3 *storage.S3Client, dispatcher *trigger.Dispatcher, bridgeMgr *trigger.BridgeManager, jwtSecret, publicURL string, inner http.Handler) http.Handler

SubdomainProxy wraps the main router and intercepts requests whose Host header matches {slug}.{agentDomain}. Matching requests are authenticated according to the route's access level and reverse-proxied to the agent's container. Non-matching requests fall through to inner.

bridgeMgr is required for the Telegram Web App auto-auth flow: the /__air/tg/auth intercept verifies initData against the bridge's bot token, which bridgeMgr decrypts on demand.

Types

type AuthHandler

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

func NewAuthHandler

func NewAuthHandler(database *db.DB, jwtSecret, activationCodeFile string, logger *zap.Logger) *AuthHandler

func (*AuthHandler) Activate

func (h *AuthHandler) Activate(w http.ResponseWriter, r *http.Request)

Activate performs one-time setup: creates the tenant and first admin user. Returns 409 if a tenant already exists.

func (*AuthHandler) ChangePassword

func (h *AuthHandler) ChangePassword(w http.ResponseWriter, r *http.Request)

ChangePassword updates the current user's password and clears the must_change_password flag.

func (*AuthHandler) Login

func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request)

func (*AuthHandler) Me

func (*AuthHandler) Refresh

func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request)

func (*AuthHandler) Status

func (h *AuthHandler) Status(w http.ResponseWriter, r *http.Request)

Status returns whether the system has been activated (tenant exists). The activation code itself is generated on airlock startup (see ensureActivationCode in cmd/airlock/main.go) — this handler only reports state, never mutates it.

type CaddyAskHandler

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

CaddyAskHandler validates on-demand TLS requests from Caddy. Caddy calls GET /caddy/ask?domain=foo.stage.airlock.run before issuing a certificate. We return 200 if the subdomain belongs to a known agent, 403 otherwise.

func (*CaddyAskHandler) Ask

type GitCredentialsHandler added in v0.4.0

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

GitCredentialsHandler owns the per-user PAT credential surface at /api/v1/me/git/credentials. Thin wrapper over service/gitcredentials: parse + auth principal here; gating, encryption, and DB inside the service.

func NewGitCredentialsHandler added in v0.4.0

func NewGitCredentialsHandler(svc *gitcredssvc.Service) *GitCredentialsHandler

func (*GitCredentialsHandler) Create added in v0.4.0

func (*GitCredentialsHandler) Delete added in v0.4.0

func (*GitCredentialsHandler) List added in v0.4.0

type GitWebhookHandler added in v0.4.0

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

GitWebhookHandler accepts push notifications from external git providers (GitHub, GitLab) at /webhooks/git/{agentID}. No JWT — per the public-webhook-ingress pattern; signature verification gates it.

On a valid push to the agent's configured branch: pulls the new HEAD into the local repo, then enqueues an upgrade with empty instruction (the existing bare-rebuild path: build image at new HEAD, validate migrations, swap container).

func NewGitWebhookHandler added in v0.4.0

func NewGitWebhookHandler(database *db.DB, b *builder.BuildService, logger *zap.Logger) *GitWebhookHandler

func (*GitWebhookHandler) Handle added in v0.4.0

Handle accepts an external git provider's push notification. The wire shape — request bodies, response error envelopes, signature headers — is dictated by GitHub / GitLab, so this endpoint stays on raw JSON (no Principal, no proto): airlockvet:allow-writejson and allow-dbq reasons below point at this contract.

type InboundOAuthGC added in v0.4.0

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

InboundOAuthGC sweeps expired authorization codes, expired/ long-consumed refresh tokens, and ancient grants. Mirrors oauth.RefreshJob in cadence — 5min ticker, started from cmd/airlock/serve.go and stopped via ctx cancellation.

The query files document the retention rules:

  • authz codes: hard delete past expires_at (60s TTL).
  • refresh tokens: past expires_at OR consumed >7d ago.
  • grants: revoked-or-expired more than 1y ago.

Each tick is idempotent and safe to call from multiple replicas (the DELETE is row-level; concurrent deletes harmlessly target disjoint rows because the GC window slides).

func NewInboundOAuthGC added in v0.4.0

func NewInboundOAuthGC(database *db.DB, logger *zap.Logger) *InboundOAuthGC

func (*InboundOAuthGC) Run added in v0.4.0

func (j *InboundOAuthGC) Run(ctx context.Context)

Run blocks until ctx is cancelled, sweeping every 5 minutes.

type ProvidersHandler

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

func NewProvidersHandler

func NewProvidersHandler(svc *providerssvc.Service) *ProvidersHandler

func (*ProvidersHandler) Create

func (h *ProvidersHandler) Create(w http.ResponseWriter, r *http.Request)

func (*ProvidersHandler) Delete

func (h *ProvidersHandler) Delete(w http.ResponseWriter, r *http.Request)

func (*ProvidersHandler) List

func (*ProvidersHandler) Update

func (h *ProvidersHandler) Update(w http.ResponseWriter, r *http.Request)

type RealIPConfig

type RealIPConfig struct {
	// TrustedProxies is a list of CIDR ranges whose X-Forwarded-For / X-Real-IP
	// headers are trusted. If empty, no headers are trusted and r.RemoteAddr is
	// used as-is. A single entry of "*" trusts all sources.
	TrustedProxies []*net.IPNet

	// TrustAll is set when the configured value is "*".
	TrustAll bool

	// Limit is how many rightmost entries in X-Forwarded-For to walk.
	// Default: 1 (single proxy).
	Limit int
}

RealIPConfig configures the real IP extraction middleware.

func ParseRealIPConfig

func ParseRealIPConfig(trustedProxies string, limit int) *RealIPConfig

ParseRealIPConfig builds a RealIPConfig from the raw env values. trustedProxies is a comma-separated list of CIDRs or "*". limit is the number of proxy hops (minimum 1).

func (*RealIPConfig) Enabled

func (c *RealIPConfig) Enabled() bool

Enabled returns true if any proxy trust is configured.

type RouterConfig

type RouterConfig struct {
	DB        *db.DB
	JWTSecret string

	// Real-time
	Hub     *realtime.Hub
	PubSub  *realtime.PubSub
	Handler *realtime.Handler

	// Secrets store. Today wraps a local AES-GCM encryptor; the interface
	// is forward-compatible with a Vault-backed implementation.
	Secrets secrets.Store

	// S3 storage
	S3Client *storage.S3Client

	// Build service
	BuildService *builder.BuildService

	// Public URL (for OAuth callbacks, auth URLs)
	PublicURL string

	// OAuth client
	OAuthClient *oauth.Client

	// Telegram driver (for bridge validation via getMe)
	TelegramDriver *trigger.TelegramDriver

	// Discord driver (for bridge validation via /users/@me)
	DiscordDriver *trigger.DiscordDriver

	// Trigger system
	Dispatcher    *trigger.Dispatcher
	Scheduler     *trigger.Scheduler
	BridgeManager *trigger.BridgeManager

	// Container manager
	Containers container.ContainerManager

	// Prompt proxy (for web conversations)
	PromptProxy *trigger.PromptProxy

	// Agent subdomain routing (e.g. "airlock.host" → {slug}.airlock.host)
	AgentDomain string

	// AgentBaseURL builds an agent's external route base
	// ({scheme}://{slug}.{domain}[:port]). Sourced from config.Config —
	// the single place that derives it; handlers never re-derive.
	AgentBaseURL func(slug string) string

	// LLM debugging proxy (e.g. telescope -watch)
	LLMProxyURL string

	// Dev escape hatch: force base64 attachment delivery regardless of
	// provider URL capability. Useful when the public URL isn't reachable
	// from the model provider (e.g. localhost without a tunnel).
	ForceInlineAttachments bool

	// Path to the on-disk activation code file — cleared after Activate
	// succeeds so the one-time secret doesn't linger on disk.
	ActivationCodeFile string

	// Reverse proxy real IP extraction
	RealIP *RealIPConfig

	// Logger
	Logger *zap.Logger
}

type UsersHandler

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

func NewUsersHandler

func NewUsersHandler(database *db.DB, usersSvc *userssvc.Service) *UsersHandler

func (*UsersHandler) Create

func (h *UsersHandler) Create(w http.ResponseWriter, r *http.Request)

Create provisions a user with a temporary password (must_change_password is set by the service). Admin-gated via the service.

func (*UsersHandler) Delete

func (h *UsersHandler) Delete(w http.ResponseWriter, r *http.Request)

Delete removes a user.

func (*UsersHandler) List

func (h *UsersHandler) List(w http.ResponseWriter, r *http.Request)

List returns all users (admin-only — service gates on TenantUserManage).

func (*UsersHandler) ListSelectable

func (h *UsersHandler) ListSelectable(w http.ResponseWriter, r *http.Request)

ListSelectable returns a slim user directory (id/email/display_name) for member-picker dropdowns. Service gates on TenantUserView so any authenticated user can read it — agent admins who aren't tenant admins still need this list to invite members.

func (*UsersHandler) UpdateRole

func (h *UsersHandler) UpdateRole(w http.ResponseWriter, r *http.Request)

UpdateRole changes a user's tenant role.

type WSHandler

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

WSHandler upgrades HTTP connections to WebSocket.

func NewWSHandler

func NewWSHandler(database *db.DB, hub *realtime.Hub, handler *realtime.Handler, jwtSecret string, logger *zap.Logger) *WSHandler

NewWSHandler creates a new WebSocket upgrade handler.

func (*WSHandler) Upgrade

func (h *WSHandler) Upgrade(w http.ResponseWriter, r *http.Request)

Upgrade handles GET /ws?token=<jwt> — validates the token, upgrades to WebSocket, and auto-subscribes the connection to every agent the user has access to (via agent_members). The client does not issue subscribe messages; authorization is enforced at connect time from durable DB state.

Jump to

Keyboard shortcuts

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