Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
a4d0069
feat(agents): AI agents framework + autofixer for error tracking
dviejokfs Apr 2, 2026
26024e9
feat(agents): autopilot cron scheduler and autofixer enhancements
dviejokfs Apr 3, 2026
50be879
chore(migrations): resolve merge conflict with main migration list
dviejokfs Apr 3, 2026
b8d6519
docs(changelog): add autopilot agents and autofixer entries to unrele…
dviejokfs Apr 3, 2026
999f7a4
feat(agents): pluggable sandbox system, agent detail page, and settin…
dviejokfs Apr 3, 2026
7011d50
feat(agents): add report deliverable, fix SENTRY_RELEASE with commit SHA
dviejokfs Apr 4, 2026
496c24b
feat(agents): markdown-to-HTML email rendering for agent notifications
dviejokfs Apr 4, 2026
92aaa25
fix(agents): capture stderr from Claude CLI so error messages are vis…
dviejokfs Apr 4, 2026
29df0e6
feat(agents): global sandbox settings with UI configuration
dviejokfs Apr 4, 2026
b15f4f5
feat(agents): complete sandbox settings overhaul
dviejokfs Apr 4, 2026
ef43426
feat(agents): sandbox lifecycle logs, MCP config mounting, Docker sta…
dviejokfs Apr 5, 2026
8948199
feat(agents): runtime preset sandbox images (Node, Bun, Python, Rust,…
dviejokfs Apr 5, 2026
4cd9c7c
fix(agents): sandbox runtime changes take effect without server restart
dviejokfs Apr 5, 2026
013d288
test(agents): e2e sandbox lifecycle and runtime preset tests
dviejokfs Apr 5, 2026
0b39355
feat(agents): user context for manual agent triggers
dviejokfs Apr 5, 2026
c876ac3
fix(agents): make SourceMapService a required dependency, not optional
dviejokfs Apr 5, 2026
84fa1c4
refactor: replace get_service with require_service for required depen…
dviejokfs Apr 5, 2026
07ac08b
fix(deployments): update workflow planner test for configure_agents job
dviejokfs Apr 5, 2026
bd88e41
test(agents): integration tests for report deliverable, user context,…
dviejokfs Apr 5, 2026
1d8c7ed
fix(agents): handle root user for Claude CLI and sandbox containers
dviejokfs Apr 5, 2026
822ecf8
feat(agents): rebuild sandbox image button in settings UI
dviejokfs Apr 5, 2026
b9e1641
feat(agents): AI provider setup, auth types, agent management UI
dviejokfs Apr 5, 2026
7b2fc18
feat(workspace): terminal sessions, sandbox limits, audit logging
dviejokfs Apr 7, 2026
2288078
fix(security): phase 1 hardening — sudo allowlist, token expiry, gate…
dviejokfs Apr 8, 2026
bea11ee
fix(agents,proxy,workspace): phase 2 security hardening
dviejokfs Apr 8, 2026
203fbc8
fix(agents,workspace,proxy): phase 3 security hardening
dviejokfs Apr 8, 2026
e6402cf
test(agents,workspace): add integration + unit tests for security har…
dviejokfs Apr 8, 2026
5221cc2
fix(agents): update glab to v1.91.0, fix plugin init on image build f…
dviejokfs Apr 8, 2026
b0a7b5b
feat(agents): config repos, global secrets, sandbox reliability
dviejokfs Apr 8, 2026
9a4e59f
feat(settings): add AI quickstart guide to agent settings page
dviejokfs Apr 9, 2026
82cc750
feat(agents): implement config repo injection, secrets, and managed-a…
dviejokfs Apr 9, 2026
b12e6ed
feat(agents): add MCP servers, skills, tools, and custom tool proxy
dviejokfs Apr 9, 2026
82f2f93
feat(agents): project-level skill and MCP definitions with slug-based…
dviejokfs Apr 10, 2026
cd39f10
feat(agents,cli): global skill/MCP definitions, skill archives, CLI m…
dviejokfs Apr 12, 2026
b121376
chore: merge origin/main into feat/autopilot
dviejokfs Apr 12, 2026
a420548
fix(agents): harden skill/MCP definitions against common attack paths
dviejokfs Apr 12, 2026
5bda0a5
feat(agents): multi-provider Codex/OpenCode support with sandbox fixes
dviejokfs Apr 13, 2026
ed5e59d
feat(agents,cli): sandbox preview routing, DB-backed gateway secret, …
dviejokfs Apr 16, 2026
2314a9e
feat(agents,sandbox,backup,proxy): autopilot runs, preview passwords,…
dviejokfs Apr 17, 2026
208d292
feat(agents,sdks,web): move injected skills to home, add analytics SD…
dviejokfs Apr 18, 2026
e0326a8
feat(sdks,web): @temps-sdk/sandbox package, AI Workflows route split,…
dviejokfs Apr 19, 2026
6b48596
style(web): apply Vercel Geist palette to light and dark themes
dviejokfs Apr 19, 2026
818bb52
feat(revenue,web,cli): per-project revenue tracking with metered MRR
dviejokfs Apr 20, 2026
ece6836
chore(migrations,web,revenue): squash Apr migrations, add revenue glo…
dviejokfs Apr 21, 2026
67210e1
fix(notifications): use sort_by_key to satisfy clippy unnecessary_sor…
dviejokfs Apr 21, 2026
d361227
feat(auth,web): expose email_verified and timestamps on user API, add…
dviejokfs Apr 21, 2026
3794896
fix(web,log-aggregator): rewrite settings links and satisfy clippy
dviejokfs Apr 21, 2026
b549b20
fix(email): count unique bounces/complaints and fix open/click rate r…
dviejokfs Apr 21, 2026
fd799c4
refactor(web): polish traces, container logs, domain detail, email an…
dviejokfs Apr 21, 2026
830710a
fix(web): pass project_id as path param in ProjectAnalytics query
dviejokfs Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
123 changes: 118 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,90 @@ jobs:
temps-linux-amd64.tar.gz
temps-linux-amd64.tar.gz.sha256

build-linux-arm64:
name: Build Linux ARM64
runs-on: ubuntu-24.04-arm
permissions:
contents: write
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install build dependencies
run: |
sudo apt-get update
sudo apt-get install -y cmake pkg-config libssl-dev protobuf-compiler

- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: aarch64-unknown-linux-gnu

- name: Cache dependencies
uses: Swatinem/rust-cache@v2
with:
key: linux-arm64-release

- name: Install Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest

- name: Cache Bun dependencies
uses: actions/cache@v4
with:
path: web/node_modules
key: ${{ runner.os }}-arm64-bun-${{ hashFiles('web/bun.lock') }}
restore-keys: |
${{ runner.os }}-arm64-bun-

- name: Install web dependencies
run: |
cd web
bun install

- name: Install wasm-pack and Build WASM
run: |
cargo install wasm-pack
cd crates/temps-captcha-wasm
bun run build

- name: Build release binary
run: cargo build --release --bin temps
env:
FORCE_WEB_BUILD: 1
CARGO_INCREMENTAL: 0
TEMPS_VERSION: ${{ github.ref_name }}

- name: Strip binary
run: strip target/release/temps

- name: Rename binary
run: cp target/release/temps temps

- name: Create tarball
run: |
tar -czf temps-linux-arm64.tar.gz temps
ls -lh temps-linux-arm64.tar.gz

- name: Generate checksum
run: |
sha256sum temps-linux-arm64.tar.gz > temps-linux-arm64.tar.gz.sha256
cat temps-linux-arm64.tar.gz.sha256

- name: Get binary info
run: |
file temps
./temps --version || echo "Note: Binary may require runtime dependencies"

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: temps-linux-arm64
path: |
temps-linux-arm64.tar.gz
temps-linux-arm64.tar.gz.sha256

build-darwin-amd64:
name: Build macOS AMD64
runs-on: macos-15-intel
Expand Down Expand Up @@ -265,7 +349,7 @@ jobs:

create-release:
name: Create Release
needs: [build-linux-amd64, build-darwin-amd64, build-darwin-arm64]
needs: [build-linux-amd64, build-linux-arm64, build-darwin-amd64, build-darwin-arm64]
runs-on: ubuntu-latest
permissions:
contents: write
Expand All @@ -282,6 +366,7 @@ jobs:
run: |
mkdir -p release
cp artifacts/temps-linux-amd64/* release/
cp artifacts/temps-linux-arm64/* release/
cp artifacts/temps-darwin-amd64/* release/
cp artifacts/temps-darwin-arm64/* release/
ls -lh release/
Expand All @@ -290,6 +375,7 @@ jobs:
run: |
cd release
cat temps-linux-amd64.tar.gz.sha256 > checksums.txt
cat temps-linux-arm64.tar.gz.sha256 >> checksums.txt
cat temps-darwin-amd64.tar.gz.sha256 >> checksums.txt
cat temps-darwin-arm64.tar.gz.sha256 >> checksums.txt
echo "Combined checksums:"
Expand All @@ -304,16 +390,19 @@ jobs:
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
SHA256_LINUX_AMD64=$(awk '{print $1}' release/temps-linux-amd64.tar.gz.sha256)
SHA256_LINUX_ARM64=$(awk '{print $1}' release/temps-linux-arm64.tar.gz.sha256)
SHA256_DARWIN_AMD64=$(awk '{print $1}' release/temps-darwin-amd64.tar.gz.sha256)
SHA256_DARWIN_ARM64=$(awk '{print $1}' release/temps-darwin-arm64.tar.gz.sha256)

echo "Generating Homebrew formula for version $VERSION"
echo "Linux AMD64 SHA256: $SHA256_LINUX_AMD64"
echo "Linux ARM64 SHA256: $SHA256_LINUX_ARM64"
echo "macOS AMD64 SHA256: $SHA256_DARWIN_AMD64"
echo "macOS ARM64 SHA256: $SHA256_DARWIN_ARM64"

sed -e "s/{{VERSION}}/$VERSION/g" \
-e "s/{{SHA256_LINUX_AMD64}}/$SHA256_LINUX_AMD64/g" \
-e "s/{{SHA256_LINUX_ARM64}}/$SHA256_LINUX_ARM64/g" \
-e "s/{{SHA256_DARWIN_AMD64}}/$SHA256_DARWIN_AMD64/g" \
-e "s/{{SHA256_DARWIN_ARM64}}/$SHA256_DARWIN_ARM64/g" \
scripts/homebrew-formula.rb.template > release/temps.rb
Expand Down Expand Up @@ -367,6 +456,21 @@ jobs:
temps --version
```

#### Linux ARM64
```bash
# Download
curl -LO https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/temps-linux-arm64.tar.gz

# Extract
tar -xzf temps-linux-arm64.tar.gz

# Move to PATH
sudo mv temps /usr/local/bin/temps

# Verify
temps --version
```

#### macOS AMD64 (Intel)
```bash
# Download
Expand Down Expand Up @@ -431,6 +535,8 @@ jobs:
$PRERELEASE_FLAG \
release/temps-linux-amd64.tar.gz \
release/temps-linux-amd64.tar.gz.sha256 \
release/temps-linux-arm64.tar.gz \
release/temps-linux-arm64.tar.gz.sha256 \
release/temps-darwin-amd64.tar.gz \
release/temps-darwin-amd64.tar.gz.sha256 \
release/temps-darwin-arm64.tar.gz \
Expand All @@ -446,17 +552,22 @@ jobs:

build-and-push-docker:
name: Build and Push Docker Image (${{ matrix.platform }})
needs: [build-linux-amd64, build-darwin-amd64, build-darwin-arm64]
runs-on: ubuntu-latest
needs: [build-linux-amd64, build-linux-arm64, build-darwin-amd64, build-darwin-arm64]
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
strategy:
matrix:
include:
- platform: linux/amd64
runner: ubuntu-latest
artifact: temps-linux-amd64
tarball: temps-linux-amd64.tar.gz
- platform: linux/arm64
runner: ubuntu-24.04-arm
artifact: temps-linux-arm64
tarball: temps-linux-arm64.tar.gz
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -543,9 +654,11 @@ jobs:
- name: Create and push manifest for latest
run: |
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/temps:latest \
ghcr.io/${{ github.repository_owner }}/temps:latest-linux-amd64
ghcr.io/${{ github.repository_owner }}/temps:latest-linux-amd64 \
ghcr.io/${{ github.repository_owner }}/temps:latest-linux-arm64

- name: Create and push manifest for version
run: |
docker buildx imagetools create -t ghcr.io/${{ github.repository_owner }}/temps:${{ steps.version.outputs.version }} \
ghcr.io/${{ github.repository_owner }}/temps:${{ steps.version.outputs.version }}-linux-amd64
ghcr.io/${{ github.repository_owner }}/temps:${{ steps.version.outputs.version }}-linux-amd64 \
ghcr.io/${{ github.repository_owner }}/temps:${{ steps.version.outputs.version }}-linux-arm64
23 changes: 22 additions & 1 deletion .github/workflows/rust-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -300,15 +300,36 @@ jobs:
name: "Integration Tests (${{ matrix.group }})"
runs-on: ubuntu-latest
needs: [build-tests, unit-tests]
# 45 min covers the postgres-upgrades group worst-case
# (5 tests × ~6 min + pg17/pg18 image pulls on a cold runner).
# Other groups finish well under that.
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
- group: docker-providers
# temps-providers with Docker tests enabled
# temps-providers with Docker tests enabled.
# NOTE: orchestrator_* tests run in a dedicated `postgres-upgrades`
# group below (serial, long timeout, real pg17→pg18 containers).
# Skip them here so this group stays fast and parallel-safe.
command: >-
cargo test --no-fail-fast --lib
-p temps-providers --features docker-tests
--
--skip orchestrator_
- group: postgres-upgrades
# PostgreSQL major-version upgrade orchestrator integration tests.
# Each test pulls pg17 + pg18 images and runs a real dump/restore,
# so they're 2–6 min apiece and must not contend for Docker.
# --test-threads=1 guarantees serial execution.
command: >-
cargo test --no-fail-fast --lib
-p temps-providers --features docker-tests
orchestrator_
--
--nocapture
--test-threads=1
- group: docker-deployments
# Crates that use TestDatabase and/or Docker
command: >-
Expand Down
10 changes: 9 additions & 1 deletion .github/workflows/test-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,20 @@ jobs:
mkdir -p release

# Create dummy binaries
echo "fake linux binary" > release/temps-linux-amd64
echo "fake linux amd64 binary" > release/temps-linux-amd64
echo "fake linux arm64 binary" > release/temps-linux-arm64
echo "fake darwin amd64 binary" > release/temps-darwin-amd64
echo "fake darwin arm64 binary" > release/temps-darwin-arm64

# Generate checksums
sha256sum release/temps-linux-amd64 > release/temps-linux-amd64.sha256
sha256sum release/temps-linux-arm64 > release/temps-linux-arm64.sha256
sha256sum release/temps-darwin-amd64 > release/temps-darwin-amd64.sha256
sha256sum release/temps-darwin-arm64 > release/temps-darwin-arm64.sha256

# Combined checksums
cat release/temps-linux-amd64.sha256 > release/checksums.txt
cat release/temps-linux-arm64.sha256 >> release/checksums.txt
cat release/temps-darwin-amd64.sha256 >> release/checksums.txt
cat release/temps-darwin-arm64.sha256 >> release/checksums.txt

Expand All @@ -47,11 +50,13 @@ jobs:
run: |
VERSION="${GITHUB_REF#refs/tags/test-v}"
SHA256_LINUX_AMD64=$(awk '{print $1}' release/temps-linux-amd64.sha256)
SHA256_LINUX_ARM64=$(awk '{print $1}' release/temps-linux-arm64.sha256)
SHA256_DARWIN_AMD64=$(awk '{print $1}' release/temps-darwin-amd64.sha256)
SHA256_DARWIN_ARM64=$(awk '{print $1}' release/temps-darwin-arm64.sha256)

sed -e "s/{{VERSION}}/$VERSION/g" \
-e "s/{{SHA256_LINUX_AMD64}}/$SHA256_LINUX_AMD64/g" \
-e "s/{{SHA256_LINUX_ARM64}}/$SHA256_LINUX_ARM64/g" \
-e "s/{{SHA256_DARWIN_AMD64}}/$SHA256_DARWIN_AMD64/g" \
-e "s/{{SHA256_DARWIN_ARM64}}/$SHA256_DARWIN_ARM64/g" \
scripts/homebrew-formula.rb.template > release/temps.rb
Expand Down Expand Up @@ -83,6 +88,7 @@ jobs:

## Files Included
- temps-linux-amd64 (dummy binary)
- temps-linux-arm64 (dummy binary)
- temps-darwin-amd64 (dummy binary)
- temps-darwin-arm64 (dummy binary)
- install.sh (real install script)
Expand All @@ -105,6 +111,8 @@ jobs:
--prerelease \
release/temps-linux-amd64 \
release/temps-linux-amd64.sha256 \
release/temps-linux-arm64 \
release/temps-linux-arm64.sha256 \
release/temps-darwin-amd64 \
release/temps-darwin-amd64.sha256 \
release/temps-darwin-arm64 \
Expand Down
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

### Added
- **AI Agents framework**: `temps-agents` crate introducing project-scoped AI agents that run Claude CLI or OpenAI Codex against your codebase; agents are configured per-project with a system prompt, max turns, and a choice of AI provider
- **Autopilot cron scheduling**: agents can be scheduled with a cron expression (e.g. `0 * * * *`) so they run automatically — the `CronScheduler` service manages all active schedules and fires agent runs without manual intervention
- **Autofixer**: agents integrated with error tracking — open an error group and trigger an AI-powered fix that creates a sandboxed agent run, streams the output, and surfaces a diff or summary in the UI
- **Conversation continuation**: Claude CLI backend supports `--continue` to resume an existing conversation in the working directory, enabling multi-turn autopilot sessions that build on prior context
- **Agent run history**: `agent_runs` and `agent_run_logs` tables track every run with status, stdout/stderr output, exit code, and timestamps; browsable from the Autopilot UI
- **Autopilot UI page**: new Autopilot section per project showing run history, run detail with streamed logs, trigger button, and cron schedule configuration
- **Autofixer panel**: dedicated side panel on the Error Group detail page showing autofixer run status and AI-generated fix output
- **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/events` lists tracking events across all emails with optional `email_id` and `event_type` filters; `GET /emails/events/stats` returns aggregated open/click/bounce rates
- **Node SDK regenerated**: includes `tracked_html_body`, `track_opens`, `track_clicks`, `TrackingEventResponse`, `TrackedLinkResponse`, `EmailTrackingResponse` types and SDK functions
Expand All @@ -17,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Documentation for new pool environment variables in the environment variables reference
- **Email tracking — tracked HTML storage**: new `tracked_html_body` column stores the final HTML sent to the provider (with tracking pixel and rewritten links), separate from the original `html_body` to 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
- **Link Project from service detail**: "Link Project" button on the Storage service detail page lets you link a project directly from the Linked Projects section via a searchable combobox

### Security
- **Container exec tenant isolation**: `exec_command` and `container_terminal` handlers now verify the container belongs to the requested project/environment before allowing access, preventing cross-tenant container exec
Expand All @@ -30,9 +38,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bump `next` across examples/fixtures to 15.3.3/16.2.2 (5 CVEs: disk cache growth, request smuggling, postponed buffering DoS, null origin CSRF bypass)
- Bump `testcontainers` 0.27.1 → 0.27.2 / `astral-tokio-tar` 0.5.6 → 0.6.0 (insufficient PAX extension validation, dev-only)

### Changed
- **Audit Logs page redesign**: switched from card-per-row layout to a responsive table matching the rest of the app (filter bar in a card, type badge + icon per category, responsive `hidden md:/lg:table-cell` columns, skeleton loaders, proper empty state, and paginated footer)
- **Audit operation labels**: added human-readable descriptions for the new `SKILL_*`, `MCP_*`, and `SECRET_*` operation types, and a `humanize()` fallback so any future operation type renders as "Something New" instead of "Performed unknown operation"

### Fixed
- **CLI: `environments vars` subcommands ignored `--project` flag**: `get`, `set`, `delete`, `import`, `export` used `cmd.parent!.parent!.opts().project` (traversing to `environments` command level where `--project` isn't defined) instead of `cmd.parent!.opts().project` (the `vars` command where it is). This caused "Project undefined not found" errors. The `list` subcommand was not affected.
- **CLI: `services env` crashed with "envVars is not iterable"**: the API endpoint `GET /external-services/{id}/projects/{project_id}/environment` returns `HashMap<String, String>` but the CLI expected `Array<EnvironmentVariableInfo>`. Added handling to convert the object response into the expected array format.
- Storage "Create" button from empty state navigated to `/storage/create` (404) instead of `/settings/storage/create`
- 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`/`click` vs `opened`/`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
Expand Down
6 changes: 6 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Guidance for Claude Code when working with the Temps codebase.
- Create markdown documentation files unless explicitly requested
- Mark Docker tests with `#[ignore]` -- they MUST skip gracefully at runtime instead
- Create error types with generic messages -- ALWAYS include IDs, names, and operation context
- Expose internal dependencies via public accessors (e.g. `service.db()`) -- pass dependencies directly via constructor or AppState
- Use `Option<T>` for dependencies that are required -- use `Arc<T>` and fail at startup if missing
- Use `get_service` for required dependencies in plugins -- use `require_service` which fails fast with a clear error

### ALWAYS
- Run `cargo check --lib` after every modification
Expand All @@ -35,6 +38,9 @@ Guidance for Claude Code when working with the Temps codebase.
- Use `permission_guard!` macro for authorization in handlers
- Add audit logging for all write operations (CREATE, UPDATE, DELETE)
- Include contextual information (IDs, resource names, paths) in every error message
- Give each component its own copy of shared dependencies (Arc clones) -- never share via accessor methods
- Use `require_service` in plugins for dependencies the app can't function without
- Let the user configure and control their setup -- show status, give instructions, don't do things silently on their behalf

---

Expand Down
Loading
Loading