Repository navigation
feat: analytics enhancements, migration CLI, deployment fixes, and dependency upgrades - #3
Merged
Merged
Conversation
…git projects determine_deployment_source_type() was checking project.source_type before deployment metadata, causing Git projects to always route to the git pipeline even when deployment metadata explicitly specified a Docker image deployment. This meant uploading a Docker image to a Git project triggered download_repo + build_image instead of pull_external_image. Move the metadata check (deployment_source_type, external_image_ref, static_bundle_path) before the project source type fallback so any project type can deploy via Docker image or static bundle through the remote deployment API.
deploy_from_image and deploy_from_static handlers were generating
deployment slugs as {project_slug}-{number}, producing URLs like
my-app-5.preview.domain instead of the expected format
{env_slug}-{number}.preview.domain. This was inconsistent with the
upload_image handler which already used the environment slug.
Align all remote deployment handlers to use environment.slug for the
deployment slug, producing URLs in the format
{env_slug}-{deployment_number}.{preview_domain}.
- Introduced new API endpoints for retrieving the complete visitor journey, including all events across sessions, and for analyzing page flow metrics such as entry/exit pages and drop-off points. - Updated the analytics service to support fetching visitor journey data and page path visitors. - Enhanced data models to include new response structures for visitor journeys and page flow analytics. - Added query parameters for limiting sessions and filtering by device type in performance metrics. This commit enhances the analytics capabilities by providing deeper insights into user interactions and page performance.
…and new assets - Introduced the EarthGlobe component for visualizing visitor data on a 3D globe, utilizing @react-three/fiber and @react-three/drei for rendering. - Added new assets: earth-blue-marble.jpg, earth-night.jpg, and earth-topology.png for the globe's texture. - Updated VisitorGlobe component to integrate EarthGlobe and improve visitor data representation. - Enhanced visitor popover with detailed information including location, last seen time, and device details. This commit significantly improves the analytics interface by providing an interactive 3D visualization of visitor data.
- Added a date filter feature to the VisitorGlobe component, allowing users to select predefined date ranges (Today, Yesterday, Last 7 Days, Last 15 Days, Last 30 Days) or a custom date range. - Introduced a new state management for date filters and updated the visitor data query to reflect the selected date range. - Enhanced the UI with quick filter buttons for desktop and a dropdown for mobile, improving user experience in navigating visitor data over time. This commit significantly enhances the analytics capabilities by providing flexible date filtering options for visitor data visualization.
- Added a new function to ensure the existence of a system user (id=0) in the database, which is necessary for handling webhook-created resources such as GitHub App installations that lack an authenticated user context. - Integrated the system user creation logic into the setup process, ensuring it is created if it does not already exist. - Updated relevant areas in the console API and Git provider manager to reference the system user for app installations and organization-level connections. This commit enhances the setup process by ensuring a consistent user context for webhook interactions.
- Added a new migration command to the CLI, allowing users to migrate projects from platforms like Vercel, Coolify, and Dokploy. - Introduced a comprehensive migration plan that includes project creation, environment variable setup, service management, and domain configuration. - Implemented pre- and post-migration verification checks to ensure successful migrations and catch potential issues early. - Enhanced the user interface for displaying migration plans, including risk assessments and actionable insights. - Added necessary types and utility functions to support the migration process, ensuring a robust and user-friendly experience. This commit significantly enhances the CLI's capabilities by providing a structured approach to project migration, improving user experience and operational efficiency.
…cking - Implemented a new `get_recent_activity` function in the analytics service to fetch recent activity events based on project and environment IDs, with optional pagination. - Created corresponding query parameters and response types for the recent activity endpoint, enhancing the API's capabilities for real-time analytics. - Updated the application state and routing to include the new endpoint, ensuring it is accessible via the API. - Added a seed script to generate fake real-time analytics data for testing the live activity feed. This commit significantly improves the analytics functionality by providing a dedicated endpoint for retrieving recent activity events, facilitating real-time data tracking and visualization.
- Upgraded `pingora`, `pingora-core`, and `pingora-proxy` to version 0.7.0, enhancing the deployment platform's capabilities. - Removed outdated dependencies such as `atty` and `clap` version 3.2.25, replacing them with `clap` version 4.5.50, which no longer relies on `atty`. - Updated `lru` from version 0.14.0 to 0.16.3, ensuring improved performance and compatibility. - Cleaned up `Cargo.lock` by removing unnecessary package entries and ensuring all dependencies are up-to-date. This commit significantly improves the dependency management and overall stability of the project.
- Changed Docker images in various configurations and test utilities from `timescale/timescaledb:latest-pg17` to `timescale/timescaledb-ha:pg18` for improved performance and compatibility. - Updated the contributing guide, docker-compose file, and multiple test files to reflect the new image version. - Removed outdated documentation files related to GitHub installation flow and backup/restore test utilities to streamline the repository. This commit enhances the database setup by ensuring the use of the latest TimescaleDB version, improving overall stability and performance.
- Updated the GitHub Actions workflow for Rust tests to enable triggering on pull requests to the main branch, enhancing CI/CD integration and ensuring tests run for proposed changes before merging.
- Updated the README.md to include the `@temps-sdk/node-sdk` package, providing users with information about its functionality related to blob storage.
Also updates install URL from install.sh to deploy.sh and refreshes screenshots with corrected demo data (monitoring uptime, domains, deployments).
…go.lock - Updated dependencies including `aws-sdk-s3` to version 1.112.0, `aws-config` to version 1.6, and `octocrab` to version 0.49.5 for improved functionality and compatibility. - Upgraded `bytes` to version 1.11.1 across multiple crates to enhance performance. - Removed outdated dependencies and cleaned up `Cargo.lock` to streamline the project and ensure all packages are up-to-date. - Enhanced email validation service to utilize the builder pattern for `CheckEmailInput`, aligning with the latest API changes. This commit improves dependency management and overall stability of the project while ensuring compatibility with the latest versions of key libraries.
All external service providers (postgres, redis, mongodb, s3) had wait_for_container_health with exponential backoff starting at 100ms with factor 1.5x and no cap. By iteration 14 (~28s cumulative), the polling interval was ~15s, causing health checks to miss the container becoming healthy during Docker's 30s start_period. Changes: - Increase initial delay from 100ms to 500ms - Increase max wait from 60s to 90s - Cap individual delay at 2s to maintain responsive polling - Add early exit when container state is EXITED or DEAD - Include exit code in error message for dead containers
Both temps-query-redis and temps-query-s3 doc examples called list_containers() and list_entities() from the DataSource trait without importing it, causing doctest compilation failures.
Resolve version inconsistency where postgres.rs config defaults used 18-alpine but get_default_docker_image(), get_default_version(), and parameter_strategies.rs used 17-alpine. All defaults, examples, schema definitions, UI placeholders, and CLI help text now consistently use postgres:18-alpine. Updated test upgrade paths from v16->v17 to v17->v18, and changed Docker image update tests to use same-major-version variants (18 -> 18-alpine) to avoid data format incompatibility failures.
Wrap both unit and integration test steps in a retry loop (up to 3 attempts) to handle transient failures from Docker container startup races, network timeouts, and testcontainer flakiness. Retries wait 5s between unit test attempts and 10s between integration test attempts to allow Docker resources to stabilize.
…d of PathBuf Modified several command files to change function signatures from PathBuf to Path for improved consistency and performance. This change enhances type handling across the codebase, ensuring better compatibility with Rust's type system. Additionally, adjusted the SetupCommand to use a Box for better memory management.
…dvisory Updated the CI workflow to improve test resilience by implementing targeted retries for failed unit and integration tests, allowing for more efficient handling of transient failures. Additionally, modified the Clippy job to be non-blocking, ensuring that warnings do not fail the build. This change enhances the overall stability and feedback loop of the testing process.
dviejokfs
enabled auto-merge
February 16, 2026 18:58
dviejokfs
disabled auto-merge
February 16, 2026 18:59
dviejokfs
added a commit
that referenced
this pull request
Apr 8, 2026
…way secret Addresses three ship-blocking findings from the feat/autopilot security audit: #1 [CRITICAL] Sandbox passwordless sudo narrowed to package managers only - Replace `NOPASSWD: ALL` with a scoped Cmnd_Alias covering apt-get, apt, dpkg, pip, uv, npm, bun. Validate via `visudo -c` at image build. - Claude can still `sudo apt-get install` mid-session (95% case); arbitrary privilege escalation inside the container is blocked. - Operators must rebuild the sandbox image for the change to take effect. #2 [CRITICAL] Deployment tokens now expire - Workspace session token: 6h TTL (was: never). - Autopilot run token: 2h TTL (was: never). - Wildcard permissions retained for now — the memory/workspace handlers gate on admin Permission, not deployment-token permissions, so real scoping requires new permission variants. Tracked for Phase 2. #3 [HIGH] Preview gateway shared secret is now required + auto-managed - `temps serve` generates `\$TEMPS_DATA_DIR/preview_gateway.secret` on first boot (32 random bytes, hex, 0600) and exports it as `PREVIEW_GATEWAY_SHARED_SECRET` so the Pingora proxy injects it on every forwarded preview request. - `preview_gateway::spawn_reconcile` passes the secret into the container env on create. - `temps-preview-gateway` binary now refuses to start without the secret. - Blocks cross-sandbox/cross-tenant direct hits to 127.0.0.1:8090 that would otherwise bypass the preview-password wall.
dviejokfs
added a commit
that referenced
this pull request
Apr 25, 2026
…autofixer (#58) * feat(agents): AI agents framework + autofixer for error tracking ## Agents Framework (temps-agents crate) - Multiple agents per project via .temps/agents/*.yaml - YAML synced to DB during deployment (source of truth) - Custom prompts, triggers (error/cron/manual), per-agent budget - Claude CLI + Codex CLI support, real-time SSE streaming - Dedup gates: cooldown, budget, concurrency limits - Stuck run recovery, cancel endpoint ## Autofixer (two-phase error fixing) - Analyze → Review → Fix → Review → Create PR workflow - Live streaming of Claude conversation - Interactive context input, workflow timeline - Integrated into error group detail page - Root cause analysis extraction from stream-json ## Git Provider - create_pull_request() for GitHub + GitLab - Auto-creates branch if it doesn't exist ## Data Model - project_agents, agent_runs, agent_run_logs tables - 3 migrations with data migration from autopilot * feat(agents): autopilot cron scheduler and autofixer enhancements Add cron-based autopilot scheduling for recurring AI agent runs, integrate error tracking service into agents crate, and extend autofixer with conversation continuation support for Claude CLI. * docs(changelog): add autopilot agents and autofixer entries to unreleased * feat(agents): pluggable sandbox system, agent detail page, and settings UI - Add SandboxProvider trait with Docker and Local implementations - Add SandboxRegistry for persistent sandbox state across autofixer phases - Add per-agent sandbox_enabled toggle with migration - Add AgentDetailPage showing all agent properties (triggers, limits, AI provider, prompt, sandbox) - Add AgentSettingsDialog for creating/editing agents from dashboard - Add sandbox_enabled to AgentRunResponse for per-run sandbox visibility - Show sandbox badge in runs table and run detail page - Fix run query to match by both agent_id and config_id * feat(agents): add report deliverable, fix SENTRY_RELEASE with commit SHA - Add "report" deliverable type: stores AI output as report without creating branches, PRs, or deployments (for health-check, audit agents) - Fix SENTRY_RELEASE: use actual commit SHA from PR response instead of branch name, which contained slashes that Sentry rejected - Add head_sha field to PullRequest struct (GitHub + GitLab providers) - Add analysis field to AgentRunResponse API so frontend can render reports - Show Report card in run detail UI when analysis is present - Send completion notification for all deliverable types via shared helper * feat(agents): markdown-to-HTML email rendering for agent notifications - Add pulldown-cmark to temps-agents for markdown→HTML conversion - Walk parser events to emit email-safe HTML with inline styles (tables, headings, code blocks, lists, bold, links all styled) - Notification service detects HTML content and passes through directly - Agent reports now render as rich formatted emails instead of raw markdown * fix(agents): capture stderr from Claude CLI so error messages are visible Both run() and continue_conversation() piped stderr but never read it, resulting in empty error messages like "failed with exit code 1:". Now stderr is captured in a parallel task and included in AiCliFailed. Falls back to stdout if stderr is empty (Claude sometimes writes errors to stdout in stream-json mode). * feat(agents): global sandbox settings with UI configuration - Export AgentSandboxSettings from temps-core - Executor reads global sandbox settings (cpu_limit, memory_limit_mb) from DB and applies them to sandbox containers - Global enabled flag: agents run in sandbox by default unless individually overridden - Add Agent Sandbox page to Settings UI with enable toggle, CPU cores input, and memory limit input - Add agent_sandbox to PlatformSettings frontend type - Wire into settings save/load pipeline * feat(agents): complete sandbox settings overhaul Functionality: - sandbox_enabled is now nullable (Option<bool>): None = use global default, Some(true) = force on, Some(false) = force off - Migration makes column nullable, converts existing false to NULL - Global settings add image (custom Docker image), network_mode (full/restricted/none) fields - Docker provider uses per-run image and network overrides - Sandbox status endpoint checks Docker availability and image readiness - SandboxProvider trait gains is_available() and image_status() methods Usability: - Settings page explains what sandbox is and why to use it - Resource presets (Light/Standard/Heavy/Custom) instead of raw inputs - Network access selector with clear descriptions - Custom image field with guidance on requirements - Per-agent dialog uses tri-state select instead of toggle * feat(agents): sandbox lifecycle logs, MCP config mounting, Docker status UI Sandbox logs: - Log resource config (CPU, RAM, network, image) before sandbox creation - Log sandbox creation time in seconds - Log sandbox destruction on cleanup MCP servers in sandbox: - Mount ~/.claude at /root/.claude-host (read-only) instead of /root/.claude - Copy to writable /root/.claude on container start so Claude CLI can write session state while preserving auth tokens and MCP config - MCP servers (npx-based) work in sandbox with network=full Docker status: - Add global /settings/sandbox-status endpoint (no project context needed) - SandboxProvider trait gains is_available() and image_status() methods - Settings UI shows Docker connection status and image readiness - Refresh button to re-check status - Clear indicators: green check / red X for Docker and image * feat(agents): runtime preset sandbox images (Node, Bun, Python, Rust, Go, Full) Replace free-text Docker image field with runtime presets. Each preset generates a Dockerfile dynamically with the right base image and toolchain. All presets include git, curl, and Claude CLI pre-installed. Images built on first use, cached as temps-sandbox-{runtime}:latest. Custom runtime auto-pulls user-provided images. Python preset includes uv package manager. * fix(agents): sandbox runtime changes take effect without server restart The executor now always resolves the sandbox image name from current DB settings instead of relying on the provider's startup-time config. Changing the runtime preset in Settings takes effect on the next agent run without restarting the server. * test(agents): e2e sandbox lifecycle and runtime preset tests Unit tests (14 new): - resolved_image for all 6 runtime presets - resolved_image for custom images and empty custom fallback - Dockerfile generation for each runtime (base image, claude-code, uv) - image_name_for_runtime mapping - Unknown runtime defaults to node Docker e2e tests (3 new, skip gracefully without Docker): - Full lifecycle: create, exec, env vars, recovery, destroy - Image status check per runtime - Custom runtime config * feat(agents): user context for manual agent triggers - Add user_context field to TriggerAgentRequest and create_run - Executor appends user context to the AI prompt when present - UI shows a dialog with a text area when clicking Run on an agent, allowing users to provide instructions or a research topic - Essential for agents like researcher that need user input to be useful * fix(agents): make SourceMapService a required dependency, not optional SourceMapService is always registered by the error-tracking plugin. Using Option silently degrades autofixer quality — the agent gets minified file paths instead of real TypeScript source locations. Changed to require_service and Arc<SourceMapService> (non-optional). * refactor: replace get_service with require_service for required dependencies 28 get_service calls that immediately unwrapped their result replaced with require_service which fails fast at startup with a clear error instead of silently disabling features or panicking with generic messages. * fix(deployments): update workflow planner test for configure_agents job Test expected 8 jobs but the agents feature added a 9th job (configure_agents). Updated assertion to match. * test(agents): integration tests for report deliverable, user context, sandbox, markdown 24 new tests covering recently added features: - Report deliverable: stream-json extraction and fallback - User context: prompt appending with separator - Sandbox override: all Option<bool> vs global combinations - Markdown email: headings, bold, tables, code blocks, empty input - Config service: sandbox_enabled Option<bool> storage Total: 135 tests passing (was 113) * fix(agents): handle root user for Claude CLI and sandbox containers Claude CLI refuses --dangerously-skip-permissions when running as root. Host fix: detect root via euid, drop to temps or nobody user via su. Sandbox fix: Dockerfiles create non-root temps user with passwordless sudo, container runs as USER temps, workspace owned by temps. Also cleans up leftover autofixer work dirs from crashed runs. * feat(agents): rebuild sandbox image button in settings UI - Add rebuild_image() to SandboxProvider trait - Docker provider removes old image then rebuilds from Dockerfile - POST /settings/sandbox-rebuild endpoint - Rebuild Image button in Docker Status section of settings * feat(agents): AI provider setup, auth types, agent management UI AI Provider (Settings > AI Agents): - Provider selector: Claude Code, OpenCode, Codex - Auth type: Subscription (OAuth token) vs API Key - Dynamic model list from installed CLI - Token save with encryption, smoke test - No host ~/.claude mount, auth via env vars only Agent management: - Enable/disable switch on every agent card - Edit dialog: schedule cron, deliverable, form resets on agent change - Enter key submits form - OpenCode CLI provider Fixes: - Sandbox status resolved against global setting in run detail - Duplicate Root Cause Analysis heading stripped from PR body - Raw stream-json filtered from error event display - CLAUDE.md dependency rules * feat(workspace): terminal sessions, sandbox limits, audit logging - Live Docker cgroup updates on session PATCH (cpu/memory/pids) - Default sandbox limits bumped to 4 vCPU / 8 GB for JS frameworks - Audit logging on terminal websocket attach/detach - Workflow memory service + handlers - Fix pre-existing test bitrot in workspace + agents crates * fix(security): phase 1 hardening — sudo allowlist, token expiry, gateway secret Addresses three ship-blocking findings from the feat/autopilot security audit: #1 [CRITICAL] Sandbox passwordless sudo narrowed to package managers only - Replace `NOPASSWD: ALL` with a scoped Cmnd_Alias covering apt-get, apt, dpkg, pip, uv, npm, bun. Validate via `visudo -c` at image build. - Claude can still `sudo apt-get install` mid-session (95% case); arbitrary privilege escalation inside the container is blocked. - Operators must rebuild the sandbox image for the change to take effect. #2 [CRITICAL] Deployment tokens now expire - Workspace session token: 6h TTL (was: never). - Autopilot run token: 2h TTL (was: never). - Wildcard permissions retained for now — the memory/workspace handlers gate on admin Permission, not deployment-token permissions, so real scoping requires new permission variants. Tracked for Phase 2. #3 [HIGH] Preview gateway shared secret is now required + auto-managed - `temps serve` generates `\$TEMPS_DATA_DIR/preview_gateway.secret` on first boot (32 random bytes, hex, 0600) and exports it as `PREVIEW_GATEWAY_SHARED_SECRET` so the Pingora proxy injects it on every forwarded preview request. - `preview_gateway::spawn_reconcile` passes the secret into the container env on create. - `temps-preview-gateway` binary now refuses to start without the secret. - Blocks cross-sandbox/cross-tenant direct hits to 127.0.0.1:8090 that would otherwise bypass the preview-password wall. * fix(agents,proxy,workspace): phase 2 security hardening - LocalSandboxProvider now gated behind TEMPS_ALLOW_LOCAL_SANDBOX env var. Refuses to run agents directly on the host unless explicitly opted in — prevents silent fallback from Docker to host execution. - Terminal WebSocket hardened: 1 MiB max frame, 4 MiB max message, token-bucket rate limit (2 MiB/s, 8 MiB burst) on both binary and text input paths. Blocks trivial DoS from a hijacked session token. - Preview auth cookie fingerprint now SHA-256(argon2_hash)[..16] hex instead of a raw argon2 prefix, so the client-visible cookie no longer leaks hash bytes. Added determinism/uniqueness test. * fix(agents,workspace,proxy): phase 3 security hardening - Sandbox kill_processes now takes a typed KillSignal enum (Term|Kill) instead of a raw i32, constraining callers to SIGTERM/SIGKILL. Stops a future caller from smuggling arbitrary signals (SIGSTOP, SIGUSR1, etc.) through the sandbox exec boundary. Unit tests cover the enum-to-signum mapping and Copy-ness. - PreviewAuthLimiter's failure map is now hard-capped at 65_536 entries with opportunistic expired-entry eviction + oldest-entry fallback. Closes the unbounded-memory-growth vector where an attacker sprays unique (ip, session_id) pairs to OOM the proxy. Test sprays 70k unique keys and asserts the map stays within cap. * test(agents,workspace): add integration + unit tests for security hardening Docker Hub pull-then-build fallback: - ensure_image_for_runtime now tries gotempsh/temps-sandbox-{runtime} from Docker Hub first, falls back to local build if pull fails. Speeds up CI/fresh installs from minutes to seconds when images are published. - Tests: hub_image_for_runtime naming, pull_fallback_on_missing_hub_image Preview gateway shared secret (Phase 1): - 5 unit tests: creation, idempotency, empty-file rejection, 0600 perms on Unix, nested parent dir creation KillSignal integration test: - Docker-gated test spawning real sleep processes, verifying SIGTERM and SIGKILL. Skips when Docker unavailable or temps serve running. Terminal WebSocket rate limiter: - Token-bucket math unit test verifying drain, rejection, refill Sessions handler: - is_safe_tab_id and tmux_cli_for_provider unit tests * fix(agents): update glab to v1.91.0, fix plugin init on image build failure - glab 1.51.0 download URL returns 404 from GitLab — update to 1.91.0 and simplify arch mapping (dpkg --print-architecture already returns amd64/arm64, no x86_64 translation needed) - When Docker is available but image pre-build fails, continue with the Docker provider instead of falling back to ensure_local_sandbox_allowed. The image will be rebuilt on first agent run. This prevents plugin init from crashing in CI where TEMPS_ALLOW_LOCAL_SANDBOX is not set. - Update Dockerfile tests to match current base images and native Claude installer (ubuntu:24.04 for node, golang:1.23-bookworm for go, claude.ai/install.sh instead of npm claude-code) - Add build-sandbox-images.sh script for multi-arch image builds - All 6 sandbox images published to Docker Hub (gotempsh/temps-sandbox-*) * feat(agents): config repos, global secrets, sandbox reliability - Add per-agent config repo (URL + branch) for .claude/ overlay - Add global secrets (agent_secrets table) with AES-256-GCM encryption - Secrets defined at settings level, not per-project - Routes at /settings/secrets with SettingsRead/Write permissions - Migration renames project_secrets → agent_secrets, drops project_id - Add secrets management UI in Agent Sandbox Settings page - Sandbox image rebuild now always builds locally (skip Docker Hub pull) - Add /opt/claude-backup in Dockerfile for named-volume resilience - Post-start exec restores Claude CLI if masked by stale named volume - Use full path /home/temps/.local/bin/claude in exec commands - Stream rebuild progress via SSE to frontend - Log container ID and image name in agent run logs - Add global config repo setting in platform settings * feat(settings): add AI quickstart guide to agent settings page Progressive 4-step setup card at the top of AI Agents settings: choose provider, save credentials, check Docker/sandbox, test connection. Shows next-action cards when complete (open workspace, configure agent). Includes collapsible "how it works" explainer. * feat(agents): implement config repo injection, secrets, and managed-agents-style YAML - Implement inject_config_repos_and_secrets in executor: clones global and per-agent config repos, overlays .claude/ into sandbox via write_directory, resolves ${TEMPS_SECRET:name} placeholders in JSON files, injects env-type secrets as /workspace/.temps/secrets.env and file-type secrets to their mount paths - Add SecretService to AgentExecutor constructor for secret resolution - Add model/system/tools fields to AgentYamlConfig aligned with Claude Managed Agents conventions: model takes precedence over provider, system takes precedence over prompt, tools array for inline tool definitions. Full backward compatibility maintained. - Update quickstart UI to use managed-agents terminology: Agent, Environment, Session, Config & Secrets as core concepts - Update config_service sync to use resolved_provider/resolved_prompt * feat(agents): add MCP servers, skills, tools, and custom tool proxy - Add mcp_servers_config, skills_config, tools_config JSONB columns to project_agents (migration m20260409) - MCP servers injected into sandbox .claude/settings.json with deep-merge - Skills written as .claude/skills/{name}.md files in sandbox - New temps-agents-mcp-proxy crate: lightweight MCP stdio proxy (Bun script) that bridges custom tool definitions to webhook endpoints - Custom tools (type: "custom" with webhook_url) auto-detected from tools_config, proxy script + config injected at runtime, registered in settings.json - API handler exposes new fields with env value masking for MCP servers - UpsertAgentRequest supports mcp_servers_config, skills_config, tools_config - ${TEMPS_SECRET:name} placeholders resolved in MCP env vars and webhook headers - Full YAML roundtrip test for custom tools * feat(agents): project-level skill and MCP definitions with slug-based references Workflows now reference skills and MCP servers by slug instead of inline content. Definitions are managed as shared project-level resources with full CRUD API, resolved at runtime by the executor and injected into the sandbox. - Add project_skill_definitions and project_mcp_definitions tables - Add DefinitionService with CRUD + batch slug resolution - Add REST endpoints for /projects/{id}/skills and /projects/{id}/mcp-servers - Update YAML config to parse slug arrays (skills: [a, b], mcp_servers: [c]) - Executor resolves slugs, writes skills as .claude/skills/*.md, merges MCP configs into .claude/settings.json, warns on unresolved slugs - Frontend dialog uses checkbox pickers instead of inline editors - Add webhook token, AI session tracking, run detail enhancements * feat(agents,cli): global skill/MCP definitions, skill archives, CLI management commands - Add global skill and MCP server definitions (settings/* endpoints) alongside project-scoped ones; combined-scope queries inject both into agent runs - Support skill archives: tar.gz uploaded as BYTEA, extracted into the sandbox at /workspace/.claude/skills/<slug>/ via SandboxRegistry::write_directory - Write merged MCP server config to both /workspace/.claude/settings.json and /home/temps/.claude.json so Claude Code picks it up at user level - Add temps-cli skills and mcp-servers commands (list/create/update/delete) with @path support for files, directories, and tar.gz archives - Make containers list -e optional; aggregates across all environments when omitted, with new Env column in output - Web UI: global + project-scoped Skills and MCP Servers settings panels - Migrations: allow nullable project_id on definitions; add archive BYTEA column - Remove orphaned temps-demo-apps submodule reference * fix(agents): harden skill/MCP definitions against common attack paths - Validate slug format in all create paths (length, charset, leading char) - Replace bulk tar unpack with per-entry unpack_in + 500MB decompression cap and reject symlinks/hardlinks (prevents path traversal + zip bombs) - Layer 50MB DefaultBodyLimit on skill upload routes - CLI skills import: use execFileSync with validated owner/repo/branch regex instead of shell-interpolated execSync (prevents command injection) - Add audit logging to all 14 write handlers via shared DefinitionAudit - Custom Debug impl on ResolvedSecret redacts value field * feat(agents): multi-provider Codex/OpenCode support with sandbox fixes - Fix Codex CLI invocation: use `codex exec --dangerously-bypass-approvals-and-sandbox --json` to disable bwrap nested sandbox (fails in Docker) and emit structured JSONL - Add provider catalog (`ai_cli/catalog.rs`) with credential formats per provider (ApiKey, OauthToken, ConfigFile) and seed paths - Credential injection uses per-provider `provider_config()` instead of legacy flat fields, fixing wrong credential being written for Codex - Add provider-aware MCP config injection (Claude JSON, Codex TOML, OpenCode JSON) via `sandbox_injector::write_mcp_configs()` - Deferred credential file writing for ConfigFile/OauthToken auth types (~/.codex/auth.json, ~/.claude/.credentials.json) - Provider-aware output parsing (Codex vs Claude) for token tracking - Frontend: parse Codex JSONL format in AutopilotRunDetail with agent_message, command_execution, and turn.completed events rendered as readable conversation - Make workflow YAML provider field optional to respect platform default - Multi-provider workspace sessions, AI provider settings UI, sandbox image builder * feat(agents,cli): sandbox preview routing, DB-backed gateway secret, JSON quiet spinners Preview gateway: - Persist shared_secret in settings.preview_gateway (DB), with legacy file migration - Export secret to env from DB on reconcile, eliminating cwd/data_dir fragility - Force rebuild when container missing PREVIEW_GATEWAY_SHARED_SECRET env - Surface real gateway health (restarting/crash_looping/running/stopped) instead of reporting green while container crash-loops CLI: - Suppress ora spinners when leaf command is invoked with --json so stdout stays pipeable to jq/parseable by callers Pre-existing clippy/compile fixes needed to unblock the commit hook: - io::Error::other for openpty failure - allow await_holding_lock on pty-agent integration tests (intentional serial lock) - rewrite preview login/logout guards as Option::filter (no is_some+unwrap) - derive Default on CreateSandboxRequest; drop explicit impl - plain String::from over format! without interpolation - #[allow(too_many_arguments)] on run_git_clone - const_assert on timeout constant sanity checks - mock workspace_sessions::Model: add public_id field - SandboxResponse test fixture: add preview_url_template field - docs: unindent nested list item in message_executor * feat(agents,sandbox,backup,proxy): autopilot runs, preview passwords, PG major upgrades, generic restore Agents / Autopilot: - CLI `temps workflow run` with error-group + ephemeral YAML support - Prompt persistence (`agent_runs.prompt_text`) + frontend viewer - PR deliverable guidelines (<pr_title>/<pr_body>) with sanitization - GitHub credential injection via files only (no env vars; avoids Copilot PAT pickup) - OpenCode tool event parsing + noise reduction in CLI renderer - Multi-provider Claude/Codex/OpenCode stream parsing Sandbox: - Preview password support (client-generated plaintext, argon2 hash stored) - Preview gateway routing for sandboxes + workspace sessions Backup / Postgres: - Generic restore framework (PG/Redis/Mongo/S3) via `restore_runs` - Postgres major version upgrades (`postgres_major_upgrades` + UI) - Default S3 source with partial-unique constraint + fallback resolver Proxy: - Preview wall hardening + structured proxy logs Web: - Autopilot run detail with streaming + prompt viewer - S3 sources management, sandbox preview password card - Major upgrade dialog + detail pages * feat(agents,sdks,web): move injected skills to home, add analytics SDK packages, error-tracking setup wizard - Move Temps-injected Claude/Codex skills from /workspace/.claude/skills to /home/temps/.claude/skills so they no longer pollute the user's git working tree via the /workspace bind mount (executor, sandbox_injector, session_manager). Adds workspace_volume migration for agent_runs to persist /workspace across autopilot runs. - Introduce standalone analytics SDK packages: @temps/analytics-core, @temps/analytics-browser, @temps/svelte-analytics, @temps/vue-analytics, shared across the React SDK. Adds SessionRecorder, SpeedTracker, and EngagementTracker primitives. - Add error-tracking setup wizard (SetupWizardShell + ErrorTrackingSetup) and wire it into ProjectDetail/ProjectOverview. - Harden AutopilotPage YAML example to match WorkflowYamlConfig schema (provider:, on:). Replace confirm() with AlertDialog in IpAccessControl. - Autofixer/trigger/run_service refinements, sandbox_registry plumbing, request_metadata updates, proxy + analytics handler touch-ups. * feat(sdks,web): @temps-sdk/sandbox package, AI Workflows route split, sandbox docs embed - sdks/node/packages/sandbox: new Sandbox SDK mirroring @vercel/sandbox (Sandbox.create/get/list, exec/execDetached, fs read/write/stat/mkdir, domain(port), lifecycle, RFC 7807 SandboxError). 5 unit tests passing. - web: extract /agent-sandbox into layout + dashboard + providers list/detail + sandbox/preview/secrets sub-pages; delete the old AgentSandboxSettings monolith. - web: embed CreateSandboxDocs on /sandboxes (CLI via bunx @temps-sdk/cli, REST, SDK) — full card in empty state, collapsible banner otherwise. - web: sidebar/settings/command palette/error-tracking polish from prior sessions, plus frecency hook + lib. * style(web): apply Vercel Geist palette to light and dark themes Match Vercel's dashboard look — pure white cards with #eaeaea hairline borders in light mode, #0a0a0a background with #1a1a1a cards in dark mode. Swap charts to Vercel accent set (blue/green/amber/red/purple) and use #0070f3 focus ring. * feat(revenue,web,cli): per-project revenue tracking with metered MRR Adds the temps-revenue crate: Stripe/LemonSqueezy webhook ingestion, CSV import, analytics (MRR/ARR/churn), and typed per-provider config for price/product allowlists. Metered/tiered subscriptions derive MRR from paid invoice lines so flat + usage-based revenue doesn't double-count. Ships the Revenue page in the web console with config editor dialog, CSV import, and CLI commands for scripted access. Includes supporting env-vars provider refactor, entity additions, and DB migrations. Also untracks temps_data/auth_secret and temps_data/encryption_key (local runtime secrets that should never have been in the repo). * chore(migrations,web,revenue): squash Apr migrations, add revenue global events, prune unused web components - Squash 34 April migrations (sandbox, workspace, agents, skills, MCP, revenue, restore, PG upgrades) into m20260421_000001_squash_apr_post_v006 - Add global_recent_events service + GET /revenue/events HTTP handler for org-wide transaction queries - Remove ~60 unused web components (onboarding wizards, dashboard, storage/webhooks dialogs, analytics charts, icons) - Add ContainerDetailPage and Revenue page, useContainerMetricsStream hook * fix(notifications): use sort_by_key to satisfy clippy unnecessary_sort_by CI clippy runs with -D warnings and flagged the sort_by closure as clippy::unnecessary_sort_by. Replace with sort_by_key + Reverse. * feat(auth,web): expose email_verified and timestamps on user API, add UserDetail page - Add email_verified, created_at, updated_at fields to UserResponse and internal User type - New UserDetail page with route wired in App.tsx - UsersManagement surfaces verification and timestamps in the list * fix(web,log-aggregator): rewrite settings links and satisfy clippy - Replace /settings/<section> links with /<section> across web app (domains, git-providers, dns-providers, agent-sandbox, etc.); App.tsx redirect routes remain as the old→new bridge - Use sort_by_key in temps-log-aggregator search to fix clippy::unnecessary_sort_by failure * fix(email): count unique bounces/complaints and fix open/click rate rounding Global tracking stats now query email_events for distinct bounce/complaint emails (the emails table has no aggregate column for those), and the web UI no longer multiplies an already-percent rate by 100. * refactor(web): polish traces, container logs, domain detail, email analytics - traces: hide OTel setup when traces exist; toggle via Setup button - container logs: restyle to match the main Logs page (theme-aware, shared LogLine component) - domain detail: drop ui.sh variant picker, keep Split layout, prune dead helpers - email analytics: make event rows clickable to the email detail page - service-logo: inline SVGs instead of external /storage assets * fix(web): pass project_id as path param in ProjectAnalytics query * feat(backup,providers,web): add service restore, external service health monitoring, and data-browser UX - temps-backup: new restore handler/service supporting Postgres, MongoDB, Redis, and S3 sources with streaming progress and audit logging - temps-providers: external service health monitor with per-provider checks (postgres, mongodb, redis, rustfs, s3) and connection pooling - temps-git: connection health service and background checks - temps-entities + migrations: external_service_health_checks table and git_provider_connections health columns - temps-cli: new `services restore` command and refreshed openapi types - web: service data browser with tabs, saved views, smart cells, command bar, service health card, service-type presets, and restored BackupDetail / ServiceDetail / S3SourceDetail flows - web: dashboard sidebar/header polish, plugins page, json-schema form improvements * feat(backup,providers,web): expand S3/RustFS restore, engine compat, and UI polish - providers/s3,rustfs: add restore_capabilities + restore_to_new_service so S3/RustFS services can be provisioned fresh from a backup; update default RustFS image to 1.0.0-alpha.98 - providers/mongodb: capture wal-g stdout/stderr, salvage success-on-exit≠0, add auth-probe loop with _alt_password fallback - backup: classify object-store backups as "mirror" (was "unknown"); skip control-plane backups from service restore picker - backup/restore: engines_compatible() helper treats s3/rustfs/minio/blob as one family so cross-engine restores within the object-store family work - backup/restore: decrypt s3_source credentials once into plaintext clone and pass to trait impls — fixes in-place restore failing with ciphertext-as-key - web/ServiceRestore: mirror engine-compat in UI filter; add helper - web/ServiceTypePresets: make RustFS the default S3 engine (MinIO now legacy) - web: add EmailDomainDetail page + route; refactor EmailDomainsManagement * fix(analytics,web): paginate service backups and satisfy clippy sort_by_key Replace `sort_by` with `sort_by_key(Reverse(...))` in analytics top-pages ranking to clear `clippy::unnecessary_sort_by`, and add paginated backup lists to ServiceDetail and ServiceRestore with responsive page controls. * feat(git,web): add OAuth state store, sync progress counts, and credentials editor UI Adds oauth_states table and migration for secure OAuth flow state, sync_progress_count column on git provider connections, GitLab provider enhancements, and a new CredentialsEditorDialog with supporting git-providers helpers. * fix(git,web): support GitLab nested groups end-to-end via repo-id routing GitLab repositories inside nested groups (e.g. gala-games/chain/platform/ operation-api-next) were stored with only the first path segment as `owner`, so owner/name lookups produced `gala-games/operation-api-next` and the upstream GitLab API returned 404 (surfacing as a 502 from branches). The frontend also couldn't parse the four-segment path back into owner/name. Backend: derive `owner` from `path_with_namespace` minus the trailing slug in all three GitLab provider code paths, use the URL slug (`path`) for `name`, expose `git_provider_connection_id` on `RepositoryResponse`, add `GET /repository/{id}` for symmetric by-id access, and backfill existing rows via a new migration. Frontend: switch the import route to `/projects/import/:repositoryId`, fetch the repo and its branches by id so the browser no longer encodes any repo path, and let the server derive the git provider connection from the row itself. * feat(git,web): fire-and-forget repository sync with guaranteed flag reset Repository sync previously ran inline under the HTTP request. Large GitLab tenants (500+ repos) routinely hit browser/proxy timeouts, leaving the connection stuck at `syncing: true` until the next server restart. The handler now spawns a detached tokio task that owns a drop-guard and a 30-minute deadline, so: - `POST /git-connections/{id}/sync` returns 202 immediately. - `syncing=false` is written on every exit path (success, error, panic, timeout, task cancel) via `SyncFlagGuard::Drop`. - A hard deadline bounds runaway syncs so the flag can never get wedged. - PAT provider creation no longer blocks on the first sync. Also removed the dead 500-preset-broadcast-per-sync loop (nobody subscribed), mapped the new SyncTimeout variant to HTTP 504, and wired real toast feedback on the frontend so failed syncs surface a visible error instead of silently invalidating the query. Bundles in-progress work across temps-blob, temps-error-tracking, temps-providers, temps-deployments (npmrc helper, build_image tweaks), and profile tweaks in Cargo.toml/.gitignore. * fix(git,web): url-encode GitLab refs and add multiline env var support Fix GitLab archive/file/commit endpoints returning 404 for branches containing slashes (e.g. chore/npmrc-gitlab-token) by URL-encoding ref_spec. Also adds multiline textarea UI for env vars (e.g. .npmrc), switches template preview images to hosted URLs. * feat(secrets,web): mount per-project secrets as files at /run/secrets/<KEY> Adds a Secrets feature that delivers sensitive values to user containers as bind-mounted files under /run/secrets/<KEY> (mode 0400, root-owned), matching the Docker Swarm convention. Values are AES-256-GCM encrypted at rest, never appear in `docker inspect`, and are never returned in plaintext from the API after creation. Backend: - New `secrets` and `secret_environments` tables (migration m20260424_000001_create_secrets) mirroring env-var scoping - `SecretService` (temps-environments) with create/list/update/delete /get_for_deploy, 1 MiB cap, key validation, always-encrypted, 17 unit tests covering scoping, validation, encryption roundtrip - `DeployRequest.secrets` HashMap; deployer materializes secrets to a per-container host directory and bind-mounts it into the container (chosen over tmpfs+tar-upload because /run/secrets doesn't exist in most images at create time) - `workflow_planner::gather_secrets` decrypts project+env secrets and routes them through the existing job_config plumbing - `remove_container` cleans up the per-container secrets host dir - HTTP handlers (list/create/update/delete_project_secret) under /projects/{id}/secrets, named with `project_` prefix to avoid collision with temps-agents existing /settings/secrets routes Frontend: - SecretsSettings.tsx with create dialog (key validation, 1 MiB client cap, "cannot be retrieved after save" warning, masked placeholder rows, delete confirmation) - Production+preview environments pre-selected by default - N keyboard shortcut to open the create dialog (mirrors env-vars page) - Settings sidebar entry, command palette entry, route wired in * chore(deps): patch 5 RUSTSEC advisories via cargo update Bumped transitive dependencies to resolve five advisories where a semver-compatible fix was available: - rustls-webpki 0.103.10 → 0.103.13 (RUSTSEC-2026-0098, -0099, -0104) CRL-parsing panic, URI name-constraint bypass, wildcard bypass - rand 0.9.2 → 0.9.4 (RUSTSEC-2026-0097) - rand 0.8.5 → 0.8.6 (RUSTSEC-2026-0097) Unsoundness with custom logger calling rand::rng() Drops `cargo audit` from 9 vulnerabilities down to 4. Remaining items are all transitive deps blocked on upstream maintainers: - rustls-webpki 0.101.7 (3 advisories) — pulled in via aws-smithy-http-client → rustls 0.21. Requires aws-smithy-http-client to migrate to rustls 0.23. Added to Cargo.toml triage notes. - protobuf 2.28.0 (already triaged — pingora → prometheus chain) - remove_dir_all 0.5.3 (already triaged — nixpacks → tempdir chain) - rsa 0.9.10 (already triaged — no upstream fix) No source code changes — only Cargo.lock updates and Cargo.toml documentation refresh. * fix(deployer): chown secrets to image USER with graceful EPERM fallback Secrets mounted at /run/secrets were written mode 0400 root-owned on the host, so containers running as a nonroot user (e.g. distroless nonroot = 65532, node:alpine, USER 1000) got EACCES when reading them. Now: before materializing the secrets dir, inspect the image's Config.User and parse the numeric uid/gid, then chown the dir and each file to match. Handles empty/"root"/"0" → (0,0), "1000" → (1000,1000), "1000:2000" → (1000,2000), ":1000" → (0,1000). Named users are logged with a warning and fall back to root ownership (user should switch to a numeric UID). When Temps itself runs unprivileged (typical on macOS dev, any non-root Linux install), chown(2) to a foreign uid returns EPERM. Instead of failing the deploy, log a warn! once and downgrade to world-readable (0755 dir / 0444 files) so the container can still read its secrets. The trust boundary is still the container (cap_drop ALL, no-new-privileges, ro bind mount); strict per-uid ownership kicks back in automatically when Temps runs as root. Adds tests for the USER spec parser (15 cases) and for the EPERM fallback path. All 65 existing tests still pass. * fix(clippy): resolve sandbox sort_by and log-aggregator unused_mut warnings CI was failing on `cargo clippy --workspace --all-targets --all-features -- -D warnings`. Two errors: - temps-sandbox/job_tracker.rs: `sort_by` with reverse cmp → `sort_by_key` with `std::cmp::Reverse`. - temps-log-aggregator/search.rs: drop unused `mut` on a test binding that is only read after construction. Bundle the previously-unstaged log dedup work (collector.rs `since=N+1` fixes, search.rs HashSet-based dedup + tests, LogStream `Hash` derive) so the branch lands in one coherent state rather than splitting closely related changes across commits. * fix(clippy): use sort_by_key in disk_space and add ci-local.sh - Replace sort_by closure with sort_by_key + Reverse to satisfy clippy::unnecessary_sort_by (was failing CI in temps-monitoring). - Add scripts/ci-local.sh that mirrors the rust-tests workflow (fmt --check, cargo check, clippy -D warnings) so PR-equivalent checks can be reproduced locally with one command. Supports per-step targets and a --fix mode for fmt and clippy autofixes. * fix(clippy): collapse lighthouse match arm and bust ci-local.sh cache - Collapse the nested `if` inside the `None` arm of the score match in lighthouse-plugin into an `if` guard on the arm itself, satisfying clippy::collapsible_match (was failing PR #58 CI on a cold cache). - ci-local.sh clippy step now wipes target/**/.fingerprint/clippy-* before running, so every workspace crate gets re-linted from scratch the same way a fresh CI runner would. Without this, clippy reuses cached lint results and silently skips files (which is exactly how the lighthouse-plugin warning slipped past the previous local run). * fix(clippy): use sort_by_key in temps-otel test_support Replace `sort_by(|a, b| b.start_time.cmp(&a.start_time))` with `sort_by_key(|s| Reverse(s.start_time))` at lines 378 and 532, satisfying clippy::unnecessary_sort_by under -D warnings (was failing CI in the temps-otel test target).
4 of 14 tasks
brunyeestudio
pushed a commit
to brunyeestudio/temps
that referenced
this pull request
Aug 1, 2026
The KV and Blob data endpoints authenticated the caller but never verified that the client-supplied project_id belonged to them (security review finding gotempsh#3). For session/API-key auth the project_id was trusted verbatim, so any authenticated principal could read/write/list/copy/delete another project's KV entries and blobs by passing an arbitrary id. Deployment tokens were already constrained; the session/API-key path was the hole. Route every data-plane handler through the team-based project_access_guard! (the same ADR-028 mechanism every other project-scoped resource uses): - KV: fold the guard into the async extract_project_id chokepoint (covers all 7 data handlers). - Blob: fold it into extract_project_id for the body handlers and add an explicit authorize_project_access() call to the path-based blob_head and blob_download handlers. - Wire an optional ProjectAccessChecker into KvAppState/BlobAppState from the plugin context, and register temps-kv/temps-blob in the ADR-028 coverage snapshot. No-op in plain OSS (no checker registered, matching prior behaviour); enforced when a team-access plugin is present. Regression tests cover the denied/allowed/no-checker paths for both data planes.
7 of 10 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This release brings major new features across analytics, CLI tooling, and deployment infrastructure, alongside critical bug fixes and dependency upgrades.
Analytics & Visualization
@react-three/fiberCLI: Migration Command
migratecommand to import projects from Vercel, Coolify, and DokployDeployment Fixes
determine_deployment_source_type()now checks deployment metadata before project source type fallbackInfrastructure & Dependencies
pg17totimescale/timescaledb-ha:pg18thoughts/filesOther
doctorandupgradeCLI commands@temps-sdk/node-sdkpackage info