The RECENT DEPLOYMENTS section queried the builds table, so
image-sourced services — which deploy without building — never
appeared and the dashboard reported "no deployments yet" while
containers were running.
- GET /api/v1/deployments lists latest deployments across the
caller's services, joined with service + project names, ordered
newest-first with a bounded limit
- ProjectsPage consumes it via listRecentDeployments; the DEPLOYS
stat card now counts real deployments
- is_admin is now projected in register/upsert user responses, and
the Better Auth mirror grants admin to the first mirrored account
(previously only the legacy register path did)
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>
- Replace redis:7-alpine with Dragonfly (Redis-protocol compatible; go-redis
client unchanged) in root, infra, and backend-dev compose files. Bounded
defaults --proactor_threads/--maxmemory so it boots on small VPSs.
- Frontend now defaults to same-origin API calls; nginx proxies /api/* to the
backend (WebSocket-aware, docker DNS resolver for upstream re-resolution).
Removes the baked localhost:8082 that broke installs reached by IP/domain.
- /auth/bootstrap returns configured OAuth providers; the UI hides
GitHub/Google buttons unless real credentials exist. Self-hosted stays
email/password only - OAuth reserved for a future managed offering.
- Sidecar ignores PLACEHOLDER_* OAuth credentials and trusts same-host
origins dynamically (Origin host == request Host) so remote installs pass
origin checks without config; cross-origin requests still rejected.
- install.sh writes ENVIRONMENT=production; COOKIE_SECURE=false in
production is now a startup warning instead of fatal (plain-HTTP installs).
- Bootstrap failure surfaces an error notice instead of silently rendering
the sign-in page.
Authored By: TDvorak <[email protected]>
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign-ups through the Better Auth proxy write to auth_users, but the
bootstrap gate counted users — which only mirrors on the first
authenticated call. In that window a second public registration was
accepted on both the proxied sign-up and the native register endpoint.
countLocalUsers now unions users with auth_users (guarded by
to_regclass so backend-only installs still work), and handleRegister
uses it instead of its own inline count.
e2e-verified on a live stack: users=0/auth_users=1 already reports
mode=login and 403s both public paths; internal-token bypass works,
wrong token refused, authed POST /users creates users (201), and the
users mirror still populates on first authenticated call.
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Backend:
- GET /services/:id/metrics with real Docker container stats
- DELETE /git/providers/:id and GET repo branches endpoint
Frontend:
- Service detail shows real telemetry or honest empty states
- Live status distinguishes idle/polling/reconnecting
- Git providers section in Settings; repo+branch pickers in Add Service
- Real logo, compact Projects header, canvas fitView fix
- index.css deduplicated (1725 -> 1384 lines)
- Fixed smoke tests, lint errors, ToastProvider/context unification
Repo hygiene:
- Added LICENSE (MIT), CONTRIBUTING.md, SECURITY.md; rewrote README
- Untracked .env.prod and data/letsencrypt secrets; fixed .gitignore
- Removed legacy root src/internal/cmd and stale configs/docs/artifacts
- Moved guides and design references under docs/
Generated with [Devin](https://devin.ai)
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>