Tomáš Dvořák
0dc5857b5f
refactor(db): port operations, settings, audit, and misc metadata to sqlc ( #84 )
...
* refactor(db): port operations, settings, audit, activity, and misc service metadata to sqlc
Covers the cross-cutting surface: operations board reads, app settings,
notification producers, activity/audit inserts, builds upsert/cancel,
git clone credential resolution, invites, environments, registry auth,
project/service variables, HA resolver, boot sweeps, and admin user ops.
Dynamic filtered lists and Better Auth table probes stay raw by design.
Authored By: TDvorak <[email protected] >
* refactor(db): port apwhy gateway handlers and proxy data plane to sqlc
Final tranche — every static call site now uses generated queries. Raw SQL
remains only where the statement is assembled at runtime (filtered lists,
sparse updates, admin count closure) or probes Better Auth's auth_users
table, which lives outside the local schema.
Authored By: TDvorak <[email protected] >
2026-10-10 09:27:30 +02:00
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