Documentation
¶
Index ¶
- func NewRouter(cfg RouterConfig) http.Handler
- func RealIP(cfg *RealIPConfig) func(http.Handler) http.Handler
- func SubdomainProxy(agentDomain string, database *db.DB, s3 *storage.S3Client, ...) http.Handler
- type AuthHandler
- func (h *AuthHandler) Activate(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) ChangePassword(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) ListSessions(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) RevokeSession(w http.ResponseWriter, r *http.Request)
- func (h *AuthHandler) Status(w http.ResponseWriter, r *http.Request)
- type GitCredentialsHandler
- type GitWebhookHandler
- type GrantsHandler
- func (h *GrantsHandler) GrantModel(w http.ResponseWriter, r *http.Request)
- func (h *GrantsHandler) GrantResource(w http.ResponseWriter, r *http.Request)
- func (h *GrantsHandler) ListModelGrants(w http.ResponseWriter, r *http.Request)
- func (h *GrantsHandler) ListResourceGrants(w http.ResponseWriter, r *http.Request)
- func (h *GrantsHandler) ModelUsage(w http.ResponseWriter, r *http.Request)
- func (h *GrantsHandler) RevokeModelGrant(w http.ResponseWriter, r *http.Request)
- func (h *GrantsHandler) RevokeResourceGrant(w http.ResponseWriter, r *http.Request)
- type InboundOAuthGC
- type NeedsHandler
- type PasskeyHandler
- func (h *PasskeyHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) LoginBegin(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) LoginFinish(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) RegisterBegin(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) RegisterFinish(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) RemovePassword(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) Rename(w http.ResponseWriter, r *http.Request)
- func (h *PasskeyHandler) SetPassword(w http.ResponseWriter, r *http.Request)
- type ProvidersHandler
- type RealIPConfig
- type ResourcesHandler
- type RouterConfig
- type UsageHandler
- type UsersHandler
- func (h *UsersHandler) Create(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) Delete(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) List(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) ListSelectable(w http.ResponseWriter, r *http.Request)
- func (h *UsersHandler) UpdateRole(w http.ResponseWriter, r *http.Request)
- type WSHandler
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 (*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) ListSessions ¶ added in v0.4.0
func (h *AuthHandler) ListSessions(w http.ResponseWriter, r *http.Request)
func (*AuthHandler) Login ¶
func (h *AuthHandler) Login(w http.ResponseWriter, r *http.Request)
func (*AuthHandler) Logout ¶ added in v0.4.0
func (h *AuthHandler) Logout(w http.ResponseWriter, r *http.Request)
func (*AuthHandler) Me ¶
func (h *AuthHandler) Me(w http.ResponseWriter, r *http.Request)
func (*AuthHandler) Refresh ¶
func (h *AuthHandler) Refresh(w http.ResponseWriter, r *http.Request)
func (*AuthHandler) RevokeSession ¶ added in v0.4.0
func (h *AuthHandler) RevokeSession(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 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 (h *GitCredentialsHandler) Create(w http.ResponseWriter, r *http.Request)
func (*GitCredentialsHandler) Delete ¶ added in v0.4.0
func (h *GitCredentialsHandler) Delete(w http.ResponseWriter, r *http.Request)
func (*GitCredentialsHandler) List ¶ added in v0.4.0
func (h *GitCredentialsHandler) List(w http.ResponseWriter, r *http.Request)
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
func (h *GitWebhookHandler) Handle(w http.ResponseWriter, r *http.Request)
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 GrantsHandler ¶ added in v0.4.0
type GrantsHandler struct {
// contains filtered or unexported fields
}
GrantsHandler serves resource-grant and model-grant management. Resource grants are authorized by the manage capability on the resource (in the service); model grants are tenant-admin only.
func NewGrantsHandler ¶ added in v0.4.0
func NewGrantsHandler(svc *grantssvc.Service) *GrantsHandler
func (*GrantsHandler) GrantModel ¶ added in v0.4.0
func (h *GrantsHandler) GrantModel(w http.ResponseWriter, r *http.Request)
GrantModel handles POST /api/v1/model-grants.
func (*GrantsHandler) GrantResource ¶
func (h *GrantsHandler) GrantResource(w http.ResponseWriter, r *http.Request)
GrantResource handles POST /api/v1/resources/{type}/{id}/grants.
func (*GrantsHandler) ListModelGrants ¶ added in v0.4.0
func (h *GrantsHandler) ListModelGrants(w http.ResponseWriter, r *http.Request)
ListModelGrants handles GET /api/v1/model-grants.
func (*GrantsHandler) ListResourceGrants ¶
func (h *GrantsHandler) ListResourceGrants(w http.ResponseWriter, r *http.Request)
ListResourceGrants handles GET /api/v1/resources/{type}/{id}/grants.
func (*GrantsHandler) ModelUsage ¶ added in v0.4.0
func (h *GrantsHandler) ModelUsage(w http.ResponseWriter, r *http.Request)
ModelUsage handles GET /api/v1/model-grants/usage?providerId=&model= — how a (provider, model) is configured, so the UI can confirm a disable.
func (*GrantsHandler) RevokeModelGrant ¶ added in v0.4.0
func (h *GrantsHandler) RevokeModelGrant(w http.ResponseWriter, r *http.Request)
RevokeModelGrant handles DELETE /api/v1/model-grants/{id}.
func (*GrantsHandler) RevokeResourceGrant ¶
func (h *GrantsHandler) RevokeResourceGrant(w http.ResponseWriter, r *http.Request)
RevokeResourceGrant handles DELETE /api/v1/resources/{type}/{id}/grants/{grantID}.
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, ancient grants, and expired WebAuthn login/registration ceremonies. 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 NeedsHandler ¶ added in v0.4.0
type NeedsHandler struct {
// contains filtered or unexported fields
}
NeedsHandler serves the agent resource-need surface: list needs, list shape-compatible candidate resources for a need, bind an existing resource, or create a new one from the need's spec.
func NewNeedsHandler ¶ added in v0.4.0
func NewNeedsHandler(svc *needssvc.Service) *NeedsHandler
func (*NeedsHandler) BindNeed ¶ added in v0.4.0
func (h *NeedsHandler) BindNeed(w http.ResponseWriter, r *http.Request)
BindNeed handles POST /api/v1/agents/{agentID}/needs/{type}/{slug}/bind.
func (*NeedsHandler) CreateForNeed ¶ added in v0.4.0
func (h *NeedsHandler) CreateForNeed(w http.ResponseWriter, r *http.Request)
CreateForNeed handles POST /api/v1/agents/{agentID}/needs/{type}/{slug}/create.
func (*NeedsHandler) ListCandidates ¶ added in v0.4.0
func (h *NeedsHandler) ListCandidates(w http.ResponseWriter, r *http.Request)
ListCandidates handles GET /api/v1/agents/{agentID}/needs/{type}/{slug}/candidates.
func (*NeedsHandler) ListNeeds ¶ added in v0.4.0
func (h *NeedsHandler) ListNeeds(w http.ResponseWriter, r *http.Request)
ListNeeds handles GET /api/v1/agents/{agentID}/needs.
type PasskeyHandler ¶ added in v0.4.0
type PasskeyHandler struct {
// contains filtered or unexported fields
}
PasskeyHandler owns the WebAuthn surface: the public login ceremony at /auth/passkey/* and the authenticated self-service at /api/v1/me/passkeys/* and /api/v1/me/password. Ceremony begin/finish exchange raw WebAuthn JSON (browser-produced attestation/assertion that go-webauthn parses directly); the management responses are proto.
func NewPasskeyHandler ¶ added in v0.4.0
func NewPasskeyHandler(svc *passkeyssvc.Service, database *db.DB, jwtSecret string) *PasskeyHandler
func (*PasskeyHandler) Delete ¶ added in v0.4.0
func (h *PasskeyHandler) Delete(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) List ¶ added in v0.4.0
func (h *PasskeyHandler) List(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) LoginBegin ¶ added in v0.4.0
func (h *PasskeyHandler) LoginBegin(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) LoginFinish ¶ added in v0.4.0
func (h *PasskeyHandler) LoginFinish(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) RegisterBegin ¶ added in v0.4.0
func (h *PasskeyHandler) RegisterBegin(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) RegisterFinish ¶ added in v0.4.0
func (h *PasskeyHandler) RegisterFinish(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) RemovePassword ¶ added in v0.4.0
func (h *PasskeyHandler) RemovePassword(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) Rename ¶ added in v0.4.0
func (h *PasskeyHandler) Rename(w http.ResponseWriter, r *http.Request)
func (*PasskeyHandler) SetPassword ¶ added in v0.4.0
func (h *PasskeyHandler) SetPassword(w http.ResponseWriter, r *http.Request)
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 (h *ProvidersHandler) List(w http.ResponseWriter, r *http.Request)
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 ResourcesHandler ¶ added in v0.4.0
type ResourcesHandler struct {
// contains filtered or unexported fields
}
ResourcesHandler serves the per-user owned-resource inventory at /api/v1/resources. Thin wrapper over service/resources: parse + auth principal here; the owner-scoping and DB live in the service.
func NewResourcesHandler ¶ added in v0.4.0
func NewResourcesHandler(svc *resourcessvc.Service) *ResourcesHandler
func (*ResourcesHandler) Delete ¶ added in v0.4.0
func (h *ResourcesHandler) Delete(w http.ResponseWriter, r *http.Request)
Delete handles DELETE /api/v1/resources/{type}/{id} — remove an owned resource.
func (*ResourcesHandler) List ¶ added in v0.4.0
func (h *ResourcesHandler) List(w http.ResponseWriter, r *http.Request)
List handles GET /api/v1/resources — the connections / MCP servers / exec endpoints the caller owns, with each one's agent-bind count.
func (*ResourcesHandler) Revoke ¶ added in v0.4.0
func (h *ResourcesHandler) Revoke(w http.ResponseWriter, r *http.Request)
Revoke handles POST /api/v1/resources/{type}/{id}/revoke — clear an owned connection's / MCP server's stored credentials (affects every agent binding it).
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
// 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
// Non-public CIDRs available to Airlock-brokered agent HTTP calls.
HTTPPrivateCIDRs []netip.Prefix
// 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 UsageHandler ¶ added in v0.4.0
type UsageHandler struct {
// contains filtered or unexported fields
}
UsageHandler serves the admin LLM spend-ledger rollups at /api/v1/usage.
func NewUsageHandler ¶ added in v0.4.0
func NewUsageHandler(svc *usagesvc.Service) *UsageHandler
func (*UsageHandler) Get ¶ added in v0.4.0
func (h *UsageHandler) Get(w http.ResponseWriter, r *http.Request)
Get handles GET /api/v1/usage?days=N — the spend rollups over the last N days (N=0 means all time; default 30).
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 holds an explicit per-user grant on (via agent_grants). The client does not issue subscribe messages; authorization is enforced at connect time from durable DB state.
Source Files
¶
- agent_exec_admin.go
- agent_sdk.go
- agents.go
- agents_git.go
- agents_source.go
- auth.go
- bridges.go
- catalog.go
- conv_mutex.go
- conversations.go
- credentials.go
- credentials_mcp.go
- device_login.go
- env_vars.go
- git_credentials.go
- grants.go
- health.go
- helpers.go
- identity.go
- integrations.go
- managed_bot_sessions.go
- middleware.go
- models.go
- needs.go
- oauth_server.go
- oauth_server_gc.go
- passkeys.go
- principal.go
- providers.go
- proxy.go
- realip.go
- relay.go
- resources.go
- router.go
- runs.go
- secured.go
- settings.go
- siblings.go
- sysagent.go
- tg_webapp.go
- usage.go
- user_sessions.go
- users.go
- webhook_git.go
- webhook_ingress.go
- ws.go