- Remove managed connection seeding: platform-postgres/dragonfly carried the backend's own DATABASE_URL/DRAGONFLY_URL into tenant projects where any member could run arbitrary DBX queries against core tables (Codex P1). NewPlatformService loses the seeds param; firstPartyDBSeeds deleted. - Seal db_connections passwords with the existing AES-256-GCM encryptor (enc:v1:<b64> marker); decrypted only in dbxArgsFor. Legacy plaintext values still read, but migration 00008 strips them (Codex P1). - Migration 00008: delete is_managed rows, drop plaintext password keys. - dbxConnectionName uses the full project UUID — the 8-hex prefix could collide and alias another project's credentials (Codex P2). - ci.yml triggers on master, not the nonexistent main/develop branches. - demo-mode stubs renamed to user-managed connections; CHANGELOG notes under Unreleased. Authored By: TDvorak <[email protected]> Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
9.6 KiB
Changelog
All notable changes to Primora. Format follows Keep a Changelog; versions follow SemVer.
[Unreleased]
Security
- Managed platform connections removed —
platform-postgres/platform-dragonflyseeds carried the backend's ownDATABASE_URL/DRAGONFLY_URLinto every project, where any member could run arbitrary queries through DBX againstcoretables. The seeds are gone and migration 00008 deletes existing managed rows. Operators keep directpsql/redis-cliaccess. - Connection passwords encrypted at rest —
core.db_connections.config.passwordis now AES-256-GCM sealed (enc:v1:marker) viaPRIMORA_ENCRYPTION_KEY; decrypted only when registering the connection with DBX. Migration 00008 strips pre-existing plaintext passwords. - DBX naming — connection names now prefix the full project UUID; the previous 8-hex prefix could collide across projects and alias the wrong credentials.
[0.5.0] - 2026-09-16
Added
-
Desktop app (
apps/desktop) — Tauri 2 thin shell for Linux/Windows/macOS. First run shows a connect screen asking for the deployment URL (validated, stored in~/.config/dev.tdvorak.primora/config.json); the webview then renders the same SolidJS bundle the server serves. System-tray icon (Show / Change Server / Quit), close-to-tray, single-instance. No embedded backend or database — the self-hosted model is preserved. -
PWA support —
vite-plugin-pwagenerates a Workbox service worker andmanifest.webmanifestin every frontend build. The app shell (JS/CSS/icons/index.html) is precached;/api,/auth, and/mailpitareNetworkOnlyand excluded from the SPA navigation fallback; Google Fonts assets are cached for a year. Installability icons (192/512/maskable + apple-touch-icon) rasterized from the existing SVG mark. -
Install prompt —
PwaInstallBannercapturesbeforeinstallpromptand offers an in-app install action inside the shell; dismissal persists inlocalStorage. -
Desktop release artifacts —
release.ymlgains adesktopjob (ubuntu/macos/windows matrix) producing AppImage/deb/rpm, dmg, and msi/nsis bundles, attached to the GitHub Release alongside the existing images and CLI binaries. -
Connector framework —
core.integrations(migration 00005) stores per-project external services with type, base URL,has_credentialsflag, health status/last_health_at. Credentials are AES-256-GCM encrypted at rest (PRIMORA_ENCRYPTION_KEY, hex/base64, 32 bytes; dev fallback outside production) and are never serialized to the client. Endpoints under/projects/:id/integrations: list, create, delete,POST …/test(5s health check against the base URL with stored credentials). -
Rybbit connector —
GET …/integrations/:id/analyticsproxies a self-hosted Rybbit instance server-side (/api/organizationssite discovery,/api/sites/:site/overview, time series, top pages/referrers) and returns a normalized shape. The API key never leaves the server; read-only, no tracking proxy. Site selection via?site=or the integration's configuredsite_id. -
Outbound webhooks —
core.webhooks+core.webhook_deliveries. Endpoints: list/create/update/delete under/projects/:id/webhooks,GET …/deliveries,POST …/test. Events:issue.created(new error fingerprint on ingest),deploy.marker(POST …/deploy-markers, records version/ref/environment/note in the audit log),webhook.test. HTTPS required for public targets; plain HTTP allowed for private/self-hosted sinks. Deliveries are signedX-Primora-Signature: sha256=<hmac-sha256(body)>and retried by an in-process dispatcher (buffered queue, 3 attempts, quadratic backoff, 10s timeout, crash recovery on boot). Generated secrets are returned exactly once. -
Integrations page — SolidJS view (Connectors + Webhooks tabs): connector table with status/test/inline Rybbit analytics panel, webhook table with per-endpoint delivery log, secret-shown-once banner, deploy-marker form. Demo-mode stubs included.
-
New
primora_*MCP tools —primora_list_integrations,primora_create_integration,primora_delete_integration,primora_test_integration,primora_integration_analytics,primora_list_webhooks,primora_create_webhook,primora_update_webhook,primora_delete_webhook,primora_list_webhook_deliveries,primora_test_webhook,primora_create_deploy_marker. -
Telemetry (IMS merge) —
POST /api/v1/ingestaccepts a single event or a ≤500-event batch, authenticated by existing projectprm_API keys viaX-Primora-Key(orX-API-Key);OPTIONSpreflight + permissive CORS for browser SDKs. Components auto-register on first use (frontend,backend,database,android,desktop,web,other). Event types:error,metric,log,heartbeat,event; missing fingerprints are derived from component + first message line. -
Issue grouping —
GET /projects/:id/issuesgroups errors by fingerprint (count, severity, first/last seen, latest component). -
Telemetry read APIs —
GET …/events(type/component/fingerprint filters,beforecursor),GET …/components,DELETE …/components/:id,GET …/telemetry/stats(bucketed series + component health + totals + metric names over 1h/24h/7d/30d),GET …/telemetry/metrics/series(avg/p50/p95/max per bucket). -
Live SSE stream —
GET …/telemetry/streampushes inserted events through an in-process hub (buffered subs, drop-on-slow, 25s keepalives).?api_key=/?token=query auth forEventSourceclients. -
Telemetry page — SolidJS view: health tab (totals, activity histogram, component status table), issues with drill-through to filtered events, event list with payload modal, metric series table, and an Integrate tab with SDK/cURL snippets. Live badge driven by the SSE stream; demo-mode stubs included.
-
@primora/clientSDK —createPrimoraClient({ endpoint, key, component, kind, base })withcaptureError,captureMetric,captureLog,captureEvent,heartbeat,installAuto, queued batching andkeepaliveflushes. -
New
primora_*MCP tools —primora_list_issues,primora_list_events,primora_telemetry_stats,primora_metric_series.
Fixed
- Workspace dependency pins updated to
0.3.0(@primora/api-client,@primora/shared-types) —npm ciin the frontend image was resolving the unpublished0.2.0spec from the registry.
[0.3.0] - 2026-09-16
Added
- Databases (DBX integration) — the Go backend keeps
dbx-mcpas a persistent stdio subprocess (internal/dbx, lazy start, one retry on failure) and exposes its tools as REST under/projects/:id/db-connections/*(list/create/delete/test, databases, tables, describe, schema context, SQL query, Redis command). DBX tool/subprocess failures surface as 502. - Connection registry —
core.db_connections(migration 00003). Credentials are stored server-side and never serialized to the browser (has_passwordflag only). Non-defaultssl,driver_profilesupported. - First-party connections —
platform-postgresandplatform-dragonflyauto-register on every project (derived fromDATABASE_URL/DRAGONFLY_URL) and cannot be deleted (409managed_connection). - Databases page — SolidJS view with connection list, database/schema/table browser, column inspector, SQL editor (⌘/Ctrl+Enter), result grid with row-detail modal, and a Redis console. Demo mode stubs included.
- Backend image now Debian-based —
dbx-mcprequires glibc; the Dockerfile installs the pinnedpackages-v0.4.88release with SHA256 verification.
[0.2.0] - 2026-09-15
Added
primoraCLI (apps/cli) —cac-parsed,@clack/promptsinteractive UX. Login (session or API key), org/project context,orgs,projects,buckets,objects(list/upload/download/rm),keys,audit list --follow. Every command accepts--json. Bothprimora orgs listandprimora orgs:listspellings.@primora/mcpserver (apps/mcp) — stdio MCP server exposing 14primora_*tools (whoami, orgs, projects, buckets, objects up/download/delete, API keys, audit query) over the generated client. Shares the CLI's~/.config/primora/config.jsoncredentials.- Authentication → Users panel — better-auth
adminplugin on the auth service (list/set-role/ban/unban/remove users) plus a dashboard view with search, role selects, and ban/delete actions. Bootstrap admins withAUTH_ADMIN_EMAILSin.env. - Mobile bottom navigation — Instagram-style tab bar below 1024px (Overview · Storage · Collections · Auth · Menu), safe-area aware; Menu opens the full drawer. Fixes a dead-navigation gap at 768–1023px.
- Release pipeline — semver tag → GitHub Release with changelog notes, GHCR images (
primora-backend/auth/frontend), compiledprimora/primora-mcpbinaries for Linux/macOS/Windows, npm tarballs, optionalnpm publishviaNPM_TOKENsecret.
Fixed
- Object downloads broken for all gzip-negotiating clients — the compression middleware left the handler's
Content-Length(raw size) on gzipped bodies, so undici/browsers saw truncated streams.gzipWriter.Writenow dropsContent-Length. - nginx 502s after every container restart — upstreams were resolved once at startup. nginx now resolves
backend/auth/frontend/mailpitthrough Docker's embedded DNS (127.0.0.11) per request.
Changed
- API keys now document the real
prm_<prefix>_<secret>format (README previously claimedpk_live_).
[0.1.0] - Initial commit
- Phase 0 foundation: Go/Gin backend, Better Auth service, SolidJS dashboard, Postgres + Dragonfly, nginx gateway, Docker Compose stack.