Changelog
Version v3.0.0
What’s new
BridgePort 3.0.0 is a major release. The web UI is rebuilt on shadcn/ui with a new Deep Slate dark theme and an opt-in light theme; an opt-in MCP server lets you drive BridgePort from your own AI agent; database backups gain a Grandfather-Father-Son (GFS) tiered rotation policy; and a full configuration audit makes dozens of previously-hardcoded knobs tunable. It also completes the 2.x deprecation cycle by removing the sync success alias — the one breaking change (see below).
Migrations apply automatically on container start, and the GFS rollout is designed to prune nothing until you opt in. As always, pull the new image and restart.
Action required before upgrading
Skip this section unless you have external scripts or integrations calling the sync endpoints.
Sync responses no longer include success
The deprecated top-level success: boolean has been removed from the sync result envelope on all three sync endpoints. Read the canonical status field instead — and note it carries information the boolean never could: a zero-target sync returns 200 with status: "no_targets", which you should surface as a warning, not a green success.
if (res.success) { … }if (res.status === "ok") { … } // "partial" / "no_targets" are distinct outcomesAffected: POST /api/config-files/:id/sync-all, POST /api/services/:id/sync-files, POST /api/servers/:serverId/sync-all-files. The BridgePort UI and per-target results[].success are unaffected. This was deprecated in 2.0 and removed on schedule per the API Stability Policy. (#236)
Database migrations
Two migrations, applied automatically and safely on first start:
20260613210010_settings_audit_240— drops 11 per-environment monitoring columns the scheduler silently ignored (and an orphaned registry-token field), and backfills the new retention/timeout system settings on the singleton row. Yourcollect*toggles are preserved. (#241)20260624145904_add_backup_rotation_policy— adds the GFS rotation policy tables/columns. Crucially, it creates an inert policy snapshot for every database that already has backups, so the first post-upgrade sweep deletes nothing. GFS only begins thinning a database once an operator reviews and saves its policy. (#292)
Features
MCP server — drive BridgePort from your AI agent (#237)
An opt-in Model Context Protocol server at POST /mcp exposes a curated slice of the API as agent tools, so you can operate BridgePort from Claude Desktop, Cursor, Claude Code, and other MCP clients. No model or inference runs on the host — you bring your own agent.
- Disabled by default — set
MCP_ENABLED=trueto register the route (fail-closed;MCP_ALLOWED_HOSTSopts into DNS-rebinding protection). - ~55 tools: a comprehensive read/observe surface plus a safe-operate set (
deploy_service,restart_deployment,rollback_deployment_plan,run_database_backup, …). Every call replays a real internal request, so auth, role/scope enforcement, validation, idempotency, and audit logging behave identically to the REST API. - Secrets never leave: a recursive redactor strips every secret-named field from all output; env-scoped tokens only see the tools they can actually call.
- New admin page at
/admin/mcpshows live status, the exposed tool/resource inventory, and client setup guidance.
GFS tiered backup rotation & retention (#292)
Replaces the flat retentionDays model with a Grandfather-Father-Son policy: keep the keepLast most-recent backups plus daily / weekly / monthly / yearly tiers (a backup survives if any tier selects it), with a minFloor safety guard and an optional per-database maxTotalBytes cap.
- Presets (
lean/balanced/long_term/custom) with inheritance: a global default in System Settings → inherited per database → overridable per database. - Pinning & exemptions: manual backups are never auto-pruned, and any backup can be pinned.
- Safe pruning: file-first deletion (artifact → row), fully audit-logged, with a confirmation gate when a policy change would prune more than the configured threshold.
- New instance
timezonesetting (ISO-week bucketing) and two new notification types (backup.rotation_error,backup.policy_first_prune).
UI rebuilt on shadcn/ui + Deep Slate and light themes (#272)
The bespoke component layer is replaced with shadcn/ui (Radix + Tailwind v4 + CSS-variable theming). Ships the Deep Slate dark theme and an opt-in light theme with a user-menu switcher (system default, no flash-of-unstyled-content).
- Semantic design tokens throughout (sky primary, burgundy brand, success/warning/info, themed charts), a ⌘K command palette, collapsible sidebar with a mobile sheet, and react-hook-form + zod forms across editors and modals.
- Every page rewritten; charts, topology, and the code editor re-themed; legacy components and color ramps removed.
- Resolved a backlog of UI-audit findings and rendering bugs along the way.
Configuration audit & deploy-time tunables (#241, #257)
A full pass over the configuration surface — making existing behavior controllable and honest, with no new product behavior by default.
- New admin-editable retention settings (notifications, health logs, webhook deliveries, image digests), read hot by the scheduler each cleanup tick, consolidated into one “Retention” section in System Settings.
- Exposed previously-uncontrollable knobs (
pgDumpTimeoutMs, multipart upload limit) and removed settings the app silently ignored. - 21 new deploy-time environment variables (MySQL/webhook timeouts, response-cache size, SSH exec buffer, and more), each defaulting to today’s value — zero behavior change unless set.
API changes
See the API Stability Policy.
Added
POST /mcp— opt-in MCP transport (off unlessMCP_ENABLED=true). (#237)- Backup-policy endpoints:
PUT/GET …/backup-policy,POST …/backup-policy/preview(viewer-allowed), and idempotentPUT …/backups/:backupId/pin. (#292) - Typed
querystring/paramsschemas added to the remaining untyped routes (incl.audit,events,downloads) — the OpenAPI spec now documents ~42 more query parameters. No behavior change. (#273) - Each GitHub Release now ships the OpenAPI spec as an
openapi.jsonasset, so consumers can diff the contract between versions without a running instance. (#294)
Removed
- Sync response top-level
success: boolean(deprecated in 2.0) — readstatusinstead. See Action required above. (#236) - 11 dead per-environment
MonitoringSettingsfields (monitoring interval/retention/bounce + a no-openabled) andSystemSettings.doRegistryToken— monitoring cadence is global (SCHEDULER_*) and bounce thresholds live on notification types. (#241)
Improvements
Frontend bundle split into route + vendor chunks (#281)
The single ~2.3 MB JS bundle is now ~80 lazy-loaded route and vendor chunks (charts, flow, CodeMirror, Radix, Sentry, React), so pages load on demand and vendor code is long-cacheable — resolved by real code-splitting, not by raising the warning limit.
New port-gantry-crane logo & brand loader (#282)
An SVG-native, monochrome-burgundy port gantry crane mark (a crane carrying a container — orchestration = the port), deliberately name-independent. Doubles as the app’s loading animation (honors prefers-reduced-motion), with a full favicon/PWA icon set.
Fixes
Operator/viewer access to the Secrets & Vars page (#275)
Operators saw an empty “No secrets configured” page because one admin-only fetch in a Promise.all rejected the whole batch (403). The admin-only call is now skipped for non-admins, and viewers no longer see write controls that would only 403 on submit.
Dashboard render loop (“Maximum update depth exceeded”) (#276)
useToast() returned a fresh object every render, which cascaded into an infinite render loop in the topology diagram (surfaced after the UI migration). The toast handle is now a referentially stable module-level singleton, with a regression test.
Duplicate logo icon in the sidebar header (#279)
Security
All resolved via dependency updates:
- form-data → 4.0.6 — CRLF injection (Dependabot #80). (#283)
- @opentelemetry/core → 2.8.0 — unbounded memory allocation (Dependabot #81). (#284)
- nodemailer → 9.0.1 — security-group update. (#285)
- esbuild ≥ 0.28.1 — GHSA-g7r4-m6w7-qqqr (dev-server only; not exploitable in production builds). (#238)
Under the hood
- Quieter CI builds (#278): skip the
ssh2/cpu-featuresnative addon build that can’t compile against Node 26’s V8 (runtime was always on the pure-JS path) and bump pnpm to 11.7.0. - Dependency bumps:
@fastify/swagger-ui6 (#289),@fastify/rate-limit11 (#288),fastify-plugin6 (#290),actions/checkout7 (#286), and the js-minor-and-patch group (#280).
Documentation
- MCP server woven into the cross-cutting docs for the public release (#258), and the branding doc rewritten around the finalized logo system (#282). -----BEGIN SSH SIGNATURE----- U1NIU0lHAAAAAQAAADMAAAALc3NoLWVkMjU1MTkAAAAgEyiv4hf6iBgr34ICjN6HnEP/vs Yr31eNU5HhdkQaYd4AAAADZ2l0AAAAAAAAAAZzaGE1MTIAAABTAAAAC3NzaC1lZDI1NTE5 AAAAQNGQNwQiZVvgQjvkoy6DGLzn3g4fXzhVC/N0uR2QyXZxf0T4Stkq6fKzgcXuMx1vAq Xvu5OSu7ZYix34K4+t2ws= -----END SSH SIGNATURE-----