All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- Email tracking analytics UI: event timeline on email detail page showing individual open/click/bounce/delivery events with IP, user-agent, and metadata; new Analytics tab with delivery rate cards and global event log
- Global email events endpoint:
GET /emails/eventslists tracking events across all emails with optionalemail_idandevent_typefilters;GET /emails/events/statsreturns aggregated open/click/bounce rates - Node SDK regenerated: includes
tracked_html_body,track_opens,track_clicks,TrackingEventResponse,TrackedLinkResponse,EmailTrackingResponsetypes and SDK functions - Multi-preset detection:
detect_all_presets_from_filesreturns all matching presets per directory (e.g., Dockerfile + Next.js + Docker Compose in the same root), letting users choose their preferred deployment method instead of silently picking the highest-priority match - Database pool configuration: env vars
TEMPS_DB_MAX_CONNECTIONS(default 100),TEMPS_DB_MIN_CONNECTIONS(default 1),TEMPS_DB_ACQUIRE_TIMEOUT(default 30s), andTEMPS_DB_IDLE_TIMEOUT(default 600s) for tuning the SQLx connection pool on resource-constrained servers - Enter-submit in wizards:
useEnterSubmithook added to Domain, DNS Provider, Domain Creation, and Import wizards — pressing Enter advances to the next step or submits on the final step - Documentation for new pool environment variables in the environment variables reference
- Email tracking — tracked HTML storage: new
tracked_html_bodycolumn stores the final HTML sent to the provider (with tracking pixel and rewritten links), separate from the originalhtml_bodyto avoid triggering fake opens in dashboard previews - Email tracking — per-link click breakdown: email detail page now shows each tracked link with its individual click count
- Container exec tenant isolation:
exec_commandandcontainer_terminalhandlers now verify the container belongs to the requested project/environment before allowing access, preventing cross-tenant container exec - Path traversal protection:
FilesystemStorage::resolve_pathrejects storage keys containing..components, preventing potential directory escape - Bump
aws-lc-sys0.38.0 → 0.39.1 (RUSTSEC-2026-0044, RUSTSEC-2026-0048: X.509 name constraints bypass) - Bump
rustls-webpki0.103.7 → 0.103.10 (RUSTSEC-2026-0049: CRL distribution point matching) - Bump
tar0.4.44 → 0.4.45 (RUSTSEC-2026-0067, RUSTSEC-2026-0068: symlink follow and PAX header issues) - Bump
rkyv0.7.45 → 0.7.46 (RUSTSEC-2026-0001: undefined behavior on OOM) - Bump
rustls0.23.34 → 0.23.37 - Bump
aiohttp≥3.11 → ≥3.13.5 in Python SDK (10 CVEs: duplicate Host headers, null bytes, response splitting, cookie leaks, memory DoS, multipart bypass, CRLF injection, DNS cache DoS, trailer headers, SSRF) - Bump
nextacross examples/fixtures to 15.3.3/16.2.2 (5 CVEs: disk cache growth, request smuggling, postponed buffering DoS, null origin CSRF bypass) - Bump
testcontainers0.27.1 → 0.27.2 /astral-tokio-tar0.5.6 → 0.6.0 (insufficient PAX extension validation, dev-only)
- CLI:
environments varssubcommands ignored--projectflag:get,set,delete,import,exportusedcmd.parent!.parent!.opts().project(traversing toenvironmentscommand level where--projectisn't defined) instead ofcmd.parent!.opts().project(thevarscommand where it is). This caused "Project undefined not found" errors. Thelistsubcommand was not affected. - CLI:
services envcrashed with "envVars is not iterable": the API endpointGET /external-services/{id}/projects/{project_id}/environmentreturnsHashMap<String, String>but the CLI expectedArray<EnvironmentVariableInfo>. Added handling to convert the object response into the expected array format. - Email event timeline returned 404: UI fetched from
/emails/{id}/events(unregistered plugin route) instead of/emails/{id}/tracking/events; also fixed event type mismatches (open/clickvsopened/clicked) and added client-side pagination for flat array response - Gmail image proxy misidentified as "Firefox" in email tracking events; now shows "Gmail (Google Proxy)"
- Email detail back button navigated to default Providers tab instead of Sent Emails tab
- Empty headers tab showed blank content instead of empty state message
- Email analytics crashed with
Cannot read properties of undefined (reading 'substring')due to missingemail_idinTrackingEventResponse - External URL in platform settings accepted invalid values with
#or?characters; now validated on both client and server - Email tracking open/click endpoints returned 500 (
RequestMetadataextension not found) because public routes lacked the middleware; now gracefully falls back to extracting IP/UA from headers - Email tracking events failed with
column "link_url" does not existon databases where the column was missing; added migration to backfill - Database connections could accumulate without recycling due to missing
idle_timeouton the connection pool; now defaults to 10 minutes gh release createfailure on duplicate tags: removed invalid--clobberflag, then re-added correctly- Install script and Homebrew formula pointed to
davidviejo/tempsinstead ofgotempsh/temps, causing 404s on binary download
0.0.7 - 2026-03-29
- Docker Compose as a first-class deployment preset: deploy multi-container apps via git-push with
DownloadRepo → DeployCompose → MarkCompletepipeline - Compose override: user-provided YAML merged at deploy time for port remapping, volume overrides, and command changes without modifying the repository compose file
- Public ports model: explicit control over which compose service ports are proxied publicly; each public port gets its own subdomain
- Service-specific custom domain routing:
service_namecolumn onproject_custom_domainslets custom domains target a specific compose service (e.g.,api.example.com→api:3000) - Compose file picker in project creation: filters files by root directory, shows only compose files within the selected subfolder
- Compose Service selector in domain settings UI for docker-compose projects
- Per-service URLs in container list and detail views
- Screenshot capture for Docker Compose deployments
- Temps system environment variables injected into all compose services via auto-generated
docker-compose.temps-env.ymloverride - Volume preservation across redeployments (
docker compose downwithout--volumes); full cleanup on project/environment deletion
temps edgeCLI command: lightweight, stateless CDN proxy node powered by Pingora — no database required- Automatic registration with the control plane via
POST /api/internal/nodes/registerwith X25519 public key exchange - Route table sync every 15 seconds from
GET /api/internal/edge/routes - ECIES-encrypted TLS certificate delivery: X25519 ECDH + HKDF-SHA256 + AES-256-GCM with forward secrecy (fresh ephemeral keypair per sync)
- Certificates stored in memory only, never written to disk
- Content-addressable local cache with LRU eviction (90% trigger, 80% target, 60s eviction cycle)
- Heartbeat reporting every 30 seconds with cache statistics (hit rate, disk usage, entry count)
- Configurable via CLI flags and environment variables (
TEMPS_ORIGIN_URL,TEMPS_EDGE_TOKEN, etc.) - Persistent config at
~/.temps/edge.json(0600 permissions) with node ID and private key - Region labels for analytics grouping (
--region us-east) - SSRF protection for edge node
api_addressvalidation: blocks loopback, link-local, metadata, and unspecified IPs
- Static asset caching via SHA-256 content hashing with git-style blob sharding (
blobs/{prefix}/{hash}) - DB-backed URL→hash mapping in
static_asset_cachetable for proxy-level asset resolution - Stale-chunk fallback: old deployment assets remain accessible until GC runs
- Asset cache purge API:
DELETE /projects/{id}/asset-cacheand per-environment variant - Purge Asset Cache button in environment settings UI
- Nightly garbage collection for unreferenced blobs
- One-shot command execution:
POST /projects/{id}/environments/{env_id}/containers/{container_id}/exec - Persistent terminal via WebSocket upgrade (xterm.js compatible) with PTY resize support
- Opt-in per project (
container_exec_enabled),ContainersExecpermission guard
temps deploy image: deploy pre-built Docker images from any registrytemps deploy static: deploy static file directories or archives (.tar.gz,.zip); auto-creates tar.gz from directoriestemps deploy git: trigger the build pipeline from a specific commit, branch, or tag- All three support
--waitwith configurable--timeoutand 5-second polling - Authentication via
TEMPS_API_URL/TEMPS_API_TOKENenvironment variables
- Email open tracking: 1x1 transparent tracking pixel injected before
</body>in outgoing HTML emails whentrack_opens: trueis set on the send API; pixel hitsGET /api/emails/{id}/track/openwhich returns a GIF and records the open event with IP and user-agent - Email click tracking: all
<a href="http(s)://...">links in HTML emails are rewritten to route throughGET /api/emails/{id}/track/click/{link_index}whentrack_clicks: trueis set; the endpoint records the click event and 302-redirects to the original URL;mailto:,tel:,#anchor, andjavascript:links are preserved unchanged email_eventstable for granular tracking event storage (event_type, link_url, link_index, ip_address, user_agent) with foreign key cascade toemailsemail_linkstable mapping link indices to original URLs with per-link click countstrack_opens,track_clicks,open_count,click_count,first_opened_at,first_clicked_atcolumns on theemailstableTrackingServiceintemps-emailcrate: HTML transformation (pixel injection + link rewriting), event recording, counter management, and link/event queries- Authenticated tracking data endpoints:
GET /api/emails/{id}/tracking(summary with unique open/click counts),GET /api/emails/{id}/tracking/events(filterable by event_type),GET /api/emails/{id}/tracking/links(per-link click stats) configure_public_routes()on theTempsPlugintrait for unauthenticated endpoints (tracking pixel and click redirect), served under/apiwithout auth middlewaretrack_opensandtrack_clicksfields on thePOST /api/emailssend API request body (default: false)- Open/click count columns in the Sent Emails table (frontend) with eye and click icons
- Tracking stats card on the Email Detail page showing open count, click count, and first-event timestamps
- 116 tests: 12 tracking service integration tests, 14 HTTP handler tests (tower::oneshot), including a full E2E flow test (send → open pixel → click redirect → query tracking summary → verify DB state)
- Health monitors now accept 404/405 as healthy status codes and support custom check paths via
.temps.yaml - E2E deployment test workflow for CI/CD validation
- Public repo improvements: URL input in Git Settings, "Public" badge,
git_urlandis_public_repoAPI fields - Authenticated GitHub API calls for public repos (5000 req/hr instead of 60)
- Infrastructure pages consolidated under Settings layout with sidebar navigation
- Command palette (Cmd+K) synchronized with actual routes and settings structure
- Workflow context clobbering: parallel jobs overwrote each other's outputs; executor now merges outputs — root cause of containers not registering after deployment
- Container registration silently skipped:
persist_static_assetsblockingmark_deployment_complete; now runs as non-blocking best-effort - Orphaned container teardown: added slug-based fallback cleanup for containers with no database records
- SQL injection surface: ORDER BY identifiers now quoted for CamelCase PostgreSQL column support; static asset cache DELETE parameterized
temps deploy staticruntime panic: duplicate-pshort alias between--pathand--projectcaused clap to panic; removed short alias from--path- Edge proxy
.unwrap()calls: replaced with?error propagation in Pingora header insertion methods - Compose override port parsing: handles both quoted and unquoted port entries
- Public port suggestions use host port (left side of mapping) instead of container port
- GitHub API rate limiting on public repos: all endpoints use authenticated tokens
- TimescaleDB Docker volume path corrected to
/home/postgres/pgdata/dataacross all docs - CPU stats always showing 0.0%: Docker stats API switched from
one_shottostreammode - Docker Registry icon changed from Globe to Boxes in Settings
- Email events query now uses deterministic ordering to prevent flaky test results
- Duplicate
email_eventsCREATE TABLE migration converted to ALTER TABLE to fix migration errors - Next.js Docker preset E2E test reliability improvements
- Compose label injection for log collection now uses correct Docker label keys
- Network throughput display now shows actual rate instead of cumulative total
- Container name truncation fixed in monitoring UI
- Removed erroneous
--from git checkout command (fixes #40) persist_static_assetsnow includes Dockerfile preset and skips pull for local images- Backend presets correctly skip
persist_static_assetsstep
FsFileStorerewritten as content-addressable store: identical content shares a single blobpersist_static_assetsjob no longer blocksmark_deployment_complete; runs in parallel- Replaced all
Command::new("git")CLI calls withgit2(libgit2); git CLI is no longer a runtime dependency - Standalone
temps-composecrate and Stacks UI removed; Docker Compose is now a deployment preset alongside Dockerfile, Next.js, etc.
0.0.6 - 2026-03-19
- Multi-node cluster support: distribute deployments across a control plane and multiple worker nodes connected via WireGuard private networking
temps-agentcrate: worker node agent with Docker runtime, token-based authentication, and deploy/status/stop/logs API endpointstemps-wireguardcrate: WireGuard tunnel management for secure node-to-node networkingtemps agentCLI command to start a worker node agenttemps joinCLI command to register a worker node with the control plane (direct or relay mode)temps nodeCLI subcommand withlist,show,drain, andremoveoperations for managing cluster nodes--private-addressflag ontemps serveto set the control plane's private/WireGuard IP for cross-node service connectivity- Node scheduler with
LeastLoaded(default) andRoundRobinscheduling strategies; resource-aware replica placement preferring nodes with lowest CPU+memory utilization; configurable max load threshold (default 90%) with graceful fallback - Remote container deployer via agent HTTP API with health checks and log streaming support
- Cross-node service connectivity: environment variables are rewritten for remote containers so they reach external services (Postgres, Redis, MongoDB, S3, RustFS) on the control plane via private IP and host port instead of Docker container names
- Multi-node-aware route table: proxy resolves worker node private addresses for containers deployed on remote nodes, enabling traffic routing across the cluster with round-robin load balancing
- Node health check job that monitors worker heartbeats and marks stale nodes as offline
- Node drain operation: stops scheduling new containers on a node and migrates existing workloads to other nodes; CLI supports
--waitwith configurable timeout (default 600s) - Node labels: persist in database, sent with every heartbeat, configurable via
--labelsCLI flag (comma-separatedkey=valuepairs) - Agent
/healthendpoint now returns real system metrics (CPU usage, memory used/total, disk used/total, running container count) viasysinfo - Nodes management page in the web UI under Settings with resource usage visualization, per-node container listing with project/environment context, drain and remove operations with confirmation dialogs
- Database migrations:
nodestable,node_idcolumns ondeployment_containersanddeployment_config,alarmstable - Alarm and monitoring system:
AlarmServicewith support for container restarts, OOM kills, high CPU/memory, outages, and deployment failures; alarm cooldown mechanism to prevent duplicate rapid-fire alerts; integration with notification and job queue systems viaAlarmFiredJobandAlarmResolvedJob ContainerHealthMonitor: periodic health checks on all active containers detecting restart count increases, OOM state changes, and resource threshold breaches- Encryption at rest for environment variables: all values are now encrypted with AES-256-GCM (via
EncryptionService) before being stored in the database; existing unencrypted rows are transparently decrypted at read time via anis_encryptedcompatibility flag; theWorkflowPlannerdecrypts values before injecting them into deployment containers - Container restart count tracking: container detail API now returns
restart_countfrom Docker, surfacing container instability in the UI - Downstream connection keepalive limit (Pingora 0.8.0): connections are closed after 1024 requests to prevent slow memory leaks from long-lived keep-alive connections
- Upstream write pending time diagnostics (Pingora 0.8.0):
X-Upstream-Write-Pendingresponse header exposes how long the upstream took to accept the request body; captured in proxy context for observability - Preview environment flag support in environment variable settings UI
- GenAI OTel tracing: collect and visualize AI conversations from OpenTelemetry
gen_ai.*spans with support for Vercel AI SDKai.*attribute fallbacks; includes conversation view, token usage aggregation, and tool call detail - Deployment promotion: promote deployments between environments with environment protection settings (required reviewers, branch restrictions)
- On-demand scale-to-zero environments: environments sleep after configurable idle timeout and wake automatically on incoming HTTP requests via proxy integration
- AI usage analytics: per-model token tracking with agent/session context, BYOK vs platform key breakdown
- Vercel AI SDK tracing examples (Node.js) and Python GenAI tracing examples
- AI tracing documentation page
- Environment password protection: cookie-based password wall for environments with HMAC-signed cookies, argon2 password hashing, and HTML password form served by the proxy; set via environment settings API with automatic cookie invalidation on password change
- Funnel card step pipeline: funnel list cards now show a horizontal pipeline of steps with completions count and conversion rate per step (e.g.,
page_view 1,234 → signup 890 (72%)) alongside the existing summary metrics - Automatic
CRON_SECRETinjection into deployed containers: the deployment token is now set asCRON_SECRETin the container environment on every deployment, and the cron scheduler sendsAuthorization: Bearer <CRON_SECRET>when invoking endpoints — no manual configuration needed - Analytics overview drill-down filters for property breakdowns:
filter_country,filter_region,filter_browser, andfilter_osquery parameters on the/events/properties/breakdownendpoint enable hierarchical navigation (country → region → city, browser → version, OS → version) - Analytics overview charts: Channels, Devices, Languages, Operating Systems, and UTM Campaigns — each with bar visualization and visitor counts
- Drill-down navigation in Browsers, Locations, and Operating Systems charts: click a row to see versions (browsers/OS) or regions/cities (locations) with breadcrumb navigation and back button
- OpenAPI schema propagation for external plugins: plugins can return an OpenAPI schema during handshake, which Temps merges into the unified API docs with
/x/{plugin_name}/path prefixing utoipaOpenAPI annotations on all example plugin handlers (SEO Analyzer, Google Indexing, IndexNow, Lighthouse) with typed request/response schemasPropertyBreakdownFiltersstruct intemps-analytics-eventsfor type-safe drill-down filter propagation through the service layer- Server-side domain pagination with search:
list_domainsendpoint now acceptspage,page_size, andsearchquery parameters, returningtotalcount alongside results; default page size is 20, max 100 - Reusable
DomainSelectorcombobox component for searching and selecting domains across the app; uses server-side search with debounce, displays domain status badges, and shows "X of Y" overflow hints ProxyLogBatchWriterfor proxy request logging: boundedmpsc::channel(8192)with batch INSERT (up to 200 rows per flush, 500ms interval) running on a dedicated OS thread; includes backpressure for HTML responses and graceful shutdown with drain- Paginated domain management UI with debounced search bar, numbered pagination controls, and mobile-responsive layout
- Structured log aggregator (
temps-log-aggregatorcrate): real-time Docker container log collection with automatic container discovery viash.temps.*labels, compressed NDJSON chunk storage (zstd) on filesystem or S3, dual search paths (TimescaleDB index for ERROR/WARN, archive scan for full-text), live tail via Server-Sent Events with project/service/level filtering, automatic retention cleanup with configurable policies, and permission-guarded handlers (LogsRead/LogsDelete) with audit logging - Frontend log history viewer with search filters, pagination, and virtualized rendering; accessible via new History tab in project runtime logs page
- OpenTelemetry (OTel) ingest and query system (
temps-otelcrate) with OTLP/protobuf support for traces, metrics, and logs; header-based and path-based ingest routes;tk_API key anddt_deployment token authentication;OtelRead/OtelWritepermissions; TimescaleDB storage with hypertables; OpenAPI-documented query endpoints for traces, spans, metrics, and logs; web UI with filterable trace list, waterfall span visualization, and setup instructions deployment_idfield on deployment tokens, allowing OTel ingest to associate telemetry with specific deploymentsprotobuf-compilerinstallation in CI workflow fortemps-otelproto compilation- External plugin system: standalone binaries in
~/.temps/plugins/are auto-discovered, spawned, and integrated at boot via stdout JSON handshake (manifest + ready) over Unix domain sockets; Temps reverse-proxies/api/x/{plugin_name}/*to each plugin and serves/api/x/pluginsfor manifest listing temps-plugin-sdkcrate for plugin authors:ExternalPlugintrait,main!()macro,PluginContext(direct Postgres access, data dir),TempsAuthextractor, and hyper-over-Unix-socket runtimetemps-external-pluginscrate following the standardTempsPluginpattern with service layer, utoipa-annotated handler, and OpenAPI schema registration- Frontend dynamic plugin integration: sidebar nav entries (platform, settings, project-level), command palette search, and generic
PluginPagecomponent at/plugins/:pluginName/*— all driven by plugin manifests - Example "Cron Jobs" plugin (
examples/example-plugin/) demonstrating full CRUD API with the SDK - Graceful shutdown for external plugins via
ExternalPluginsServicein the console API shutdown handler - PostgreSQL backup now runs
pg_dumpinside a disposable sidecar container (same image as the service) attached to the shared Docker network, eliminating OOM kills (exit code 137) that occurred whenpg_dumpallwas exec'd inside the live service container; TimescaleDB databases are supported via--format=customwith advisory circular-FK warnings suppressed - All preset providers (Next.js, Vite, Rsbuild, Docusaurus v1/v2, NestJS, Angular, Astro, Dockerfile, Nixpacks) are now registered in
PresetProviderRegistry::new(); Dockerfile and Nixpacks are registered first to take detection precedence - Proxy now converts HTML responses to Markdown on the fly when clients send
Accept: text/markdown, compatible with Cloudflare's Markdown for Agents standard; responses includeContent-Type: text/markdown,Vary: Accept, andX-Markdown-Tokensheaders; SSE, WebSocket, and responses over 2 MB pass through unchanged - MCP (Model Context Protocol) server with 210 tools across 30 domain modules (
mcp/) - OpenAPI SDK auto-generated via
@hey-api/openapi-tsfor MCP server - WebSocket support for container runtime logs in MCP server
- 103 integration tests for MCP server
- RustFS service logo and improved service type detection in web UI
- Auto-generate
secret_keyfor MinIO service creation - Analytics seed data utilities (
scripts/seed-data/) - Web UI build integration via
build.rs - GitHub Actions release workflow for Linux AMD64, macOS AMD64, macOS ARM64, and Docker
- Release automation script (
scripts/release.sh) - Resource monitoring tab in project sidebar and monitoring settings page with per-environment CPU, memory, and disk metrics
- Browse Data button on linked service cards in the project storage page
status_code_classquery parameter (1xx/2xx/3xx/4xx/5xx) for proxy log stats endpoints- TimescaleDB compression (7-day) and retention (30-day) policies for
proxy_logshypertable cargo clippypre-commit hook enabled to catch lint issues before CI- Service clusters: HA PostgreSQL via pg_auto_failover (monitor + primary + N replicas), multi-host connection strings with
target_session_attrs=read-write, cluster member tracking inservice_memberstable - Remote managed service creation on worker nodes via agent API with auto-assigned ports and Docker volume management
- DNS-based email validation service with SMTP verification
- CLI
temps project createenhanced with--repo,--branch,--directory,--preset,--connection, and--yesflags for non-interactive CI/scripting usage
- Embedded userspace WireGuard via defguard/boringtun: replaced shell-out to
wgandipCLI with pure Rust implementations (defguard_wireguard_rs+x25519-dalek); eliminateswireguard-toolssystem package dependency entirely EnvVarService(intemps-environmentsandtemps-projects) now requiresArc<EncryptionService>in its constructor; plugin registration injects it from the service registry- Upgraded Pingora from 0.7.0 to 0.8.0; proxy service now uses
ProxyServiceBuilderinstead ofhttp_proxy_service()for explicitHttpServerOptionsconfiguration - Security headers are now disabled by default for new installations; existing installations with saved settings are unaffected
- External service containers (Postgres, Redis, MongoDB, S3/MinIO, RustFS) now bind to
0.0.0.0instead of127.0.0.1, making them reachable from worker nodes via the private network; only affects newly created containers - Cron scheduler now sends
Authorization: Bearer <token>header alongsideX-Cron-Job: truewhen invoking cron endpoints; previously onlyX-Cron-Job: truewas sent DatabaseCronConfigServiceconstructor now requires aDeploymentTokenServicedependency for retrieving cron secrets- Locations chart replaced static Country/Region/City tab selector with interactive drill-down: clicking a country shows its regions, clicking a region shows its cities
- Browsers chart now supports click-to-drill into browser versions with back navigation
PluginReadyhandshake message extended with optionalopenapifield for plugin OpenAPI schemasExternalPluginProcessstruct extended withopenapi_schemafieldExternalPluginsPlugincaches OpenAPI schemas at startup for synchronous access during schema merging- Domain selection throughout the app now uses the
DomainSelectorcombobox instead of plain<Select>dropdowns, making it possible to find domains when there are many; integrated inDomainForm,AddRoute, and domain dialogs DomainFormis now self-contained: fetches wildcard domains internally for initial state matching when editing, removing thedomainsprop dependency from parent components- All
listDomainsOptions()call sites now use proper pagination or targeted search queries instead of fetching all domains - Proxy
LoadBalancerno longer holds arequest_loggerfield or calls synchronouslog_request()per request; logging is fully delegated to the async batch writer via channel send - Upgraded Bollard (Docker API client) to 0.20.1 with bollard-stubs 1.52.1; migrated all crates to new API
temps-coreno longer depends onreqwest,hyper,hyper-util,flat2, ortar; these were moved totemps-external-pluginsor dropped entirelyServiceRegistryandPluginStateRegistrynow useRwLockinstead ofMutex, allowing concurrent reads during request handlingBackupErrorvariants converted to structured variants with named fields for richer error messagesFrom<BackupError> for Problemupdated to exhaustive match (no catch-all_ =>) with correct HTTP status codes per variant- Service detail header reorganized: data actions separated from destructive actions with a visual divider
- Vulnerability scanner now uses
--pkg-types libraryfor image scans and filters outgobinary/rustbinaryresult types, reporting only project dependency CVEs
- Deleted legacy
web/src/pages/CreateService.tsxandCreateServiceRefactored.tsx(superseded by current service creation flow)
- Duplicate live visitors: proxy double-decrypted the visitor cookie —
ensure_visitor_sessiondecrypted the cookie and passed the plaintext UUID toget_or_create_visitor, which tried to decrypt it again; the second decryption always failed silently, causing a new visitor record on every returning page load; now passes the raw encrypted cookie directly - Static deployment visitor duplication:
ensure_visitor_sessionwas called for every static file request (JS, CSS, images); concurrent first-visit requests without cookies each created separate visitors; now skips visitor creation for static asset paths - Proxy returned incorrect
Content-Lengthfor HEAD responses over HTTP/2, causing clients to wait for a body that never arrives; the header is now stripped for HEAD responses - Upstream connections could silently fail when reusing stale pooled connections (TCP RST); added explicit connection/read/write/idle timeouts and single automatic retry on connection failure
- Deployment lock contention: replaced PostgreSQL advisory lock with a process-level
tokio::Mutex, eliminating cross-process lock conflicts and moving container teardown outside the lock scope - Docker container names are now used instead of Docker network aliases for cross-node environment variable rewriting, fixing service connectivity on remote worker nodes
- Deployment "marking complete" step could hang for the full 60-second timeout when the job queue was busy; the poll now runs on every loop iteration regardless of queue activity
- Remote environment variables are no longer built when no active worker nodes exist, avoiding unnecessary work in single-node deployments
- Phantom deployments on node drain/failover: drain and failover previously called
trigger_pipelinewith no branch/tag/commit, creating broken "preview" deployments with empty git context; now uses smart drain logic that retires containers on the draining node when healthy replicas exist on other nodes - GenAI trace token counts showed as zero: PostgreSQL
SUM(bigint)returnsnumerictype, causing Sea-ORMtry_get::<Option<i64>>to silently fail; added::bigintcast to all SUM expressions - Funnel edit page always showed "Funnel Not Found":
EditFunneluseduseParams()to readfunnelId, but no matching route parameter was defined; now parsed from the URL and passed as a numeric prop - Funnel card metrics never loaded:
formatDateForAPIproducedyyyy-MM-dd HH:mm:ssformat but the backend expects ISO 8601; changed todate.toISOString() - Proxy memory leak caused by unbounded
tokio::spawnfire-and-forget INSERT per request; replaced with bounded batch writer that prevents unbounded task growth under high traffic - Domain list pages no longer silently truncate results when there are more domains than the default page size; all consumers now paginate or use targeted search
- Dockerfile path not saved when changed in project settings;
preset_configwas never sent in the API request - Fix incorrect
corepackcommand used for pnpm in the Next.js preset - BuildKit build log output now emits vertex names (build step descriptions) in addition to command output, making cached layers visible in deployment logs
- Install script command in documentation now uses
bashinstead ofsh, fixing failures on Ubuntu 24 where/bin/shisdash - CPU percentage calculation in container stats now uses delta between
cpu_statsandprecpu_statsinstead of absolute values avg_response_timecast tofloat8in proxy log time bucket stats for correct type handling
- Patched critical HTTP Request Smuggling vulnerabilities in
pingora-core(0.7.0 → 0.8.0) - Patched high-severity
aws-lc-sysvulnerabilities: PKCS7 signature validation bypass, certificate chain validation bypass, and AES-CCM timing side-channel (0.32.3 → 0.38.0) - Patched
jsonwebtokentype confusion authorization bypass in google-indexing-plugin (9 → 10.3.0) - Patched
quinn-protounauthenticated remote DoS via panic in QUIC transport parameter parsing (0.11.13 → 0.11.14) - Updated Vercel AI SDK to 5.x to fix file upload whitelist bypass vulnerability
- Updated Flask in example app to 3.1.3 (session cookie fix)
0.1.0 - 2024-10-22
- Initial project structure
- Core architecture with 30+ workspace crates
- Analytics engine with funnels and session replay
- Error tracking (Sentry-compatible)
- Git provider integrations (GitHub, GitLab)
- Deployment orchestration with Docker
- Reverse proxy with automatic TLS/ACME
- Managed services (PostgreSQL, Redis, S3)
- Status page and uptime monitoring
- Web UI built with React and Rsbuild