Tomáš Dvořák and Devin
5eac4a382b
feat: activity feed — enriched audit events + global/project timelines ( #45 )
...
* feat(branding): white-label — public /branding, admin write, shell theming
app_settings branding.* keys (product name, logo/favicon URLs, accent
color, docs/support links). Public GET /branding so login and shell
theme pre-auth; admin writes via PUT /settings.
useBranding() applies document.title, accent CSS var and favicon;
BrandWordmark replaces hardcoded wordmarks; admin Platform settings
gain a Branding form. MCP containr_branding_get + settings_update.
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(invites): team invite links — admin create/revoke, public accept
Admins mint single-use invite links (sha256-hashed token at rest,
optional email binding, configurable TTL). Public endpoints let the
accept page validate the link and register — working even while
public signup is disabled.
- migration + sqlc queries/model for user_invites
- POST /admin/invites (returns one-time token+url), GET list, DELETE revoke
- GET /auth/invites/:token public validation, POST /auth/accept-invite
- CLI containr invites list|create|revoke; MCP invites tools
- /auth/accept-invite page (expired/used/invalid states, bound-email lock)
- Admin page Team invites section: create, copy link, revoke
- OpenAPI + generated types + CLI guide
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(admin): impersonate user — 15-min token, audit-logged
POST /admin/users/:id/impersonate mints a short-lived bearer token
(impersonated_by claim) for support/debugging. Admin accounts cannot
be impersonated; every mint is audit-logged with actor + target.
- CLI: containr admin impersonate <user-id> (works via CONTAINR_TOKEN)
- MCP: containr_admin_impersonate
- Admin UI: per-user Impersonate action → token modal with usage hint
- OpenAPI + generated types
Verified live: token resolves to target, admin target 403, audit row.
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat(git): GitHub App manifest self-provisioning + app-level webhook
Admins create the instance GitHub App in-browser instead of hand-
setting GITHUB_APP_* env vars:
- POST /admin/git/github-app/manifest builds the manifest + URL;
the frontend auto-submits it to github.com
- /git/github-app/callback page exchanges the code via
POST /admin/git/github-app/convert; credentials persist in
app_settings (precedence over env)
- GET /admin/git/github-app reports configured/source
- POST /api/git/github-app/webhook — single app-level push receiver,
HMAC-verified, dispatches via extracted dispatchPushToServices
- install-url + installation-token paths resolve settings→env
- CLI: containr admin github-app status|manifest|convert; MCP tools
- Git providers UI shows "Set up GitHub App" for admins when
unconfigured
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
* feat: activity feed — enriched audit events, global + per-project timelines
audit_logs gains severity/category/label columns derived from
resource+action at write time; legacy rows are classified on read and
backfilled at boot in batches.
- GET /activity: global feed scoped to the caller's visible projects
(admins see all); severity/category/resource/project_id/since
filters, page+limit
- GET /projects/:id/activity: timeline correlated to the project's
services, deployments, databases and the project record; access
mirrors project read rules
- Retention worker prunes rows older than AUDIT_RETENTION_DAYS
(default 90, 0 disables), running once at boot then daily
- project.create/delete now audited so timelines aren't empty
- CLI `containr activity` with filter flags; MCP tools
containr_activity_list + containr_project_activity
- Frontend: /activity page (severity chips, icon per category) under
Operate nav; project workspace gains an Activity view tab
- OpenAPI + generated types + CLI docs
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
---------
Co-authored-by: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-09 10:52:15 +02:00
Tomas Dvorak
5c2f2861bd
feat: direct docker-compose import into projects
...
POST /projects/:id/import-compose deploys a compose file straight into a
project — no template row required. Well-known DB images become managed
databases attached to the project network under their service name as DNS
alias; other services deploy in dependency order via deployTemplateGraph.
- api: extract composeToSpecs converter (shared by the template
import-compose preview and the new project endpoint); fix dropped env
warnings (pointer receiver); replace insertion sort with sort.Strings
- cascade: database_services.project_id links graph-provisioned DBs to
their project so project delete tears down runtime + row (previously
leaked container + network)
- cli: new `containr import` group, `import compose <project> <file|->`
- mcp: containr_projects_import_compose tool
- openapi + regenerated frontend types; docs snapshot + CLI.md
- frontend: compose import modal on the project workspace toolbar
- tests: composeToSpecs conversion, ordering, db-image map, warnings
2026-10-09 09:33:38 +02:00
Tomas Dvorak and Devin
18f78f00a3
feat(api): error codes, idempotency keys, cursor pagination
...
- Stable machine-readable error codes alongside the error message
(UNAUTHENTICATED, INVALID_TOKEN, ADMIN_REQUIRED, SCOPE_INSUFFICIENT,
IDEMPOTENCY_IN_PROGRESS); CLI renders "CODE: message".
- Idempotency middleware on authed/admin groups: POST requests with an
Idempotency-Key header replay the first response for 24h (Redis-backed,
caller-scoped); concurrent duplicates get 409. X-Idempotent-Replay
header marks replays.
- Shared pagination helpers: ?cursor= (opaque, preferred) alongside
legacy ?page= on projects and deployments lists; pagination meta
includes next_cursor; invalid cursors fail soft to page 1.
- CLI --idempotency-key flag for safe scripted retries.
- OpenAPI updated: error envelope, cursor params, idempotency contract.
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-08 15:38:36 +02:00
Tomas Dvorak and Devin
8b6214a0f5
feat: public platform, admin console, templates, landing docs
...
Projects become publicly browsable after admin approval; management and
secret-adjacent reads (logs, variables, exec, connection URLs) require
owner/member/admin auth, and platform controls sit behind RequireAdmin.
- Backend: OptionalAuth middleware, read/authed/admin route groups,
projects.is_approved + service_templates.owner_id migration,
visibility-aware sqlc queries, admin overview/users/approval endpoints,
EnsureAdminAccount bootstrap (ADMIN_* env), 30 seeded templates with
owner CRUD, managed-database connection URLs gated owner+admin, fix
DB.Stats() infinite recursion.
- Frontend: expandable persisted sidebar + clickable user menu, public
landing page with searchable docs browser (GitHub sync, bundled
snapshot + localStorage fallback), DocsBrowser shared with /docs,
template create/edit/JSON-upload for owned templates, database create
dialog, admin console (stats, approvals, project edit/delete, user
admin toggles), HA/Security/Usage polish with dead CSS tokens mapped
to real theme vars, anonymous-safe gating on every mutation control.
- Tests: safe window.localStorage access fixes happy-dom crashes in
PlatformShell and canvas storage.
Generated with [Devin](https://devin.ai )
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-22 19:58:59 +02:00
Tomas Dvorak and Devin
ff356230fe
feat: real service runtime — private networks, replicas, lifecycle, rollback
...
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>
2026-09-21 19:31:19 +02:00
Tomas Dvorak
08cb5754f3
small fix, don't worry about it
2026-04-10 12:02:36 +02:00