Skip to main content

SWAMP SERVE

swamp serve turns a Swamp repository into a remote API. This page explains the architectural decisions behind the server, the security constraints it enforces, and how admin access is managed.

Architecture

A swamp serve instance is a single process that holds a Swamp repository and exposes it over a WebSocket API. Clients connect to run model methods, execute workflows, query data, and manage access. Workers connect to receive dispatched steps for remote execution.

The server is the single source of truth. It owns the datastore, resolves vault secrets, stores model definitions, and manages the policy snapshot. Clients and workers are stateless — they issue requests and receive responses but hold no durable state.

This is a deliberate centralization. A Swamp repository is a coherent unit: definitions reference each other, workflows chain model outputs, and vault secrets are scoped to the repo. Distributing this state would introduce consistency problems that the current model avoids by not having them.

Hard refusals

swamp serve refuses to start in certain configurations. These are not warnings — they are hard failures that prevent the server from binding.

Off-loopback without TLS and authentication. If --host is set to anything other than 127.0.0.1 or ::1, the server requires both --cert-file / --key-file and --auth-mode other than none. This is not configurable.

The reasoning is straightforward: swamp serve is a control plane. It accepts arbitrary model method execution, workflow runs, and vault reads. An unauthenticated, unencrypted control plane on the network is arbitrary remote execution — anyone who can reach the port can run any command. The hard refusal prevents this misconfiguration from reaching production.

On loopback, the risk model is different. The server is only reachable from the local machine, where the user already has access to the repository. TLS and authentication add friction without meaningful security benefit in this context.

That said, --auth-mode none is deprecated. The loopback exception made sense as a convenience for early adoption, but in practice it creates a gap between local and production setups. Workflows, grants, and token-scoped permissions behave differently under none than under token or oauth — issues that surface only at deployment time. Requiring authentication everywhere, including loopback, closes that gap and makes local development a reliable predictor of production behavior.

Admin materialization

The --admins flag lists principal IDs that receive full admin access. On every server start, the server materializes a grant of admin on access:* for each listed principal. This grant implies all actions on all resources.

Materialization is reconciled on every boot. If a principal is removed from --admins, its materialized grant is removed on the next start. If a new principal is added, it receives the grant on the next start. The config is the source of truth — not the grant store.

This design serves two purposes.

Bootstrap. When a server starts for the first time with --auth-mode token, someone needs to be able to mint the first token and create the first grants. The --admins flag provides that bootstrap identity without requiring a separate setup step.

Recovery. If an admin accidentally revokes their own access or corrupts the grant store, restarting the server with the correct --admins flag restores admin access. The config always wins.

Policy snapshot and reload

Grants and group memberships are compiled into a policy snapshot — a precomputed structure that the server evaluates on every access check. The snapshot is rebuilt on swamp access reload or automatically on every change when --grant-reload auto is active.

The default manual reload mode is a safety mechanism. Grant changes are staged until an admin deliberately applies them. A bad grant — an overly broad allow, a deny that locks out the admin — does not take effect until reload. This gives the admin a chance to review and revoke before applying.

The auto mode removes this safety net in exchange for convenience. Teams that trust their grant-creation workflow and want immediate effect use auto. Teams that prefer a review step use manual.

Deny-wins evaluation

When both allow and deny grants match a request, deny wins. This is not configurable.

The alternative — most-specific-wins or last-writer-wins — creates reasoning problems at scale. With deny-wins, a compliance team can create a deny grant that blocks access to sensitive resources, and no amount of allow grants from other teams can override it. The deny is a hard boundary.

This makes the system predictable: if you see a deny grant, you know it applies regardless of what else exists. See the authorization reference for the full evaluation model.