Services now reconcile into actual Docker containers instead of
bookkeeping rows:
- Per-project bridge network with service-name DNS aliases and
${{service.KEY}} env expansion (HOST/PORT builtins)
- Replicas, published ports, Traefik domain routing, health checks,
restart policies persisted on the service spec; spec-hash drift
recreates containers on redeploy
- Lifecycle API: start/stop/restart/redeploy, live runtime state,
real image rollback (replaces the fake sleep)
- Manual scale and PUT replicas reconcile live containers; service
and project delete remove their containers and the project network
- Canvas: real URLs, replica badges, env filter, right-click
deploy/restart/stop/delete menu, empty state
- Service detail: real lifecycle buttons, live replica/URL strip,
Networking editor, ${{ }} variable helper
- Fix prebuilt-image pulls racing the tag (drain the pull stream)
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
- First registered account becomes admin (users.is_admin, backfilled
to earliest account); better-auth mirror path does the same
- Public registration closes after bootstrap; admin can reopen it via
GET/PUT /api/v1/settings (admin-gated) or SIGNUP_ENABLED env
- In-app settings override env vars; secrets stored in app_settings,
token values never returned by the API
- Saving a Cloudflare Tunnel token pulls and runs a managed
cloudflared sidecar on the backend's networks; clearing removes it;
startup restores it from saved settings
- group_add DOCKER_GID grants the non-root backend user Docker socket
access; install.sh probes the in-container socket gid
- Settings page gains an owner-only Platform section (registration
toggle, tunnel token, link to Cloudflare dashboard); sign-up page
stays reachable while registration is open
- OpenAPI spec + generated types updated; manual user creation now
requires admin
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Adds scaling_policies table and wires the autoscaler: upsert on every
SetScalingPolicy (including delete-as-disable), LoadPolicies hydrates
policies + service states at boot. Persist failures are logged, never
fatal — in-memory state stays authoritative.
Verified live: policy written on POST, survives a full backend restart,
service state re-registers at min_replicas. Also gofmt-fixes the
drifted databases.go struct tags.
Authored By: TDvorak <[email protected]>
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Per-node onboarding tokens replace the placeholder <token> in the agent
connect command: raw cagt_ tokens are returned once at issuance, only
sha256 hashes persist in agent_auth_tokens, and listing exposes metadata
only. Public agent routes accept env-configured shared tokens or any
active DB-issued token; successful validation stamps last_used_at and
revoked tokens are rejected — verified end-to-end against a real stack
(register, heartbeat, revoke → 401, bogus → 401).
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Phase 0 cleanup verified end-to-end:
- Delete vendored APwhy runtime (cmd/apwhy, internal/apwhy) and the
unwired copy (internal/api/server.go + static bundle + cloned
internal/{storage,analytics,auth,rbac}) — ~7.5k lines of dead code.
- Keep Containr's native internal/gateway; move APwhy management
routes under /api/v1/gateway/* so they stop colliding with the
native /services paths. Fix handlers against the real schema:
UUID ids via RETURNING, integer enabled flags, plan validation,
service validate endpoint, unique-violation mapping.
- Port agents.go off GORM onto sqlc (sqlc/queries/agents.sql);
drop gorm dependencies; fix sqlc schema drift (services.environment_id).
- Replace the SELECT 1 goose baseline with the real consolidated
schema (52 tables) minus APwhy's parallel auth/RBAC objects;
idempotent via IF NOT EXISTS / OR REPLACE / guarded DO blocks so it
replays cleanly over legacy installs. Add a drop migration for the
dead objects and delete the legacy filename-tracked migrations/
loader, directory, and Dockerfile copy. Verified via cmd/migrate:
fresh install 53 tables, legacy upgrade clean to 20260917000000.
- Canvas: add invisible React Flow handles to ServiceNode so inferred
auto-connections stop emitting warning #008.
- Remove reactflow dep (superseded by @xyflow/react), test harness
cmds, and legacy 0001_init.sql backups.
Authored By: TDvorak <[email protected]>