## Summary
Upgrades all `@remix-run/*` packages in `apps/webapp` from **2.1.0 →
2.17.4** to address security vulnerabilities. Recreation of #2951 on a
fresh checkout of `main`.
**Updated packages (`apps/webapp/package.json`):**
- `@remix-run/express`, `@remix-run/node`, `@remix-run/react`,
`@remix-run/serve`, `@remix-run/server-runtime`: 2.1.0 → 2.17.4
- `@remix-run/router`: ^1.15.3 → ^1.23.2
- `@remix-run/dev`, `@remix-run/eslint-config`, `@remix-run/testing`:
2.1.0 → 2.17.4
**Root `package.json` overrides:**
- `@remix-run/dev@2.17.4>tar-fs`: 2.1.3 → 2.1.4
- `testcontainers@10.28.0>tar-fs`: 3.0.9 → 3.1.1
**Documentation:** Updated Remix version references in `CLAUDE.md`,
`apps/webapp/CLAUDE.md`, and `.cursor/rules/webapp.mdc`.
**Server changes:** Added `.server-changes/upgrade-remix-security.md`
for release tracking per `CONTRIBUTING.md`.
No application code changes — only `package.json` files, documentation,
a server-changes entry, and the regenerated `pnpm-lock.yaml`.
### Updates since last revision
Addressed all 3 Devin Review findings:
1. **Missing `.server-changes/` file** — added
`.server-changes/upgrade-remix-security.md` (commit ce22a0bd4)
2. **Sentry Remix patch (`@sentry/remix@9.46.0`)** — verified the patch
at `patches/@sentry__remix@9.46.0.patch` applies cleanly against 2.17.4.
The patch modifies Sentry's own `RemixInstrumentation` wrapper (removing
`request.clone()` and form data attributes), not Remix internals. The
underlying Remix APIs it hooks into (`callRouteAction`,
`callRouteLoader`) are stable across 2.1→2.17.
3. **`remix-typedjson@0.3.1` compatibility** — peer deps declare
`@remix-run/react: ^1.16.0 || ^2.0`, covering 2.17.4. Confirmed working
at runtime across all 22 tested pages that use it (root.tsx, hooks,
route loaders).
### Verification performed during this session
- **Runtime:** Express+Remix integration, magic link login, client-side
routing, MetaFunction rendering
- **Operational:** hello-world task triggered via API, runs list, run
detail, tasks page
- **Comprehensive UI:** 22 pages, 11 filter types, environment/project
switchers, interactive elements
- **Docker:** Production Dockerfile (`docker/webapp/Dockerfile`) builds
successfully
- **Changelog audit:** All 16 minor versions reviewed — every breaking
change is behind opt-in future flags the webapp doesn't enable
## Review & Testing Checklist for Human
- [ ] **Verify auth flows in staging** — `remix-auth`,
`remix-auth-email-link`, and `remix-auth-github` declare peer deps on
`@remix-run/server-runtime@^1.x`, which is now 2.17.4. Login (magic link
+ OAuth) should be tested in a staging environment since local dev
testing may not exercise all auth code paths.
- [ ] **Verify tar-fs override versions** resolve the targeted security
advisories (2.1.4 and 3.1.1)
- [ ] **Review new transitive dependencies** added by the upgrade:
`turbo-stream@2.4.1`, `undici@6.25.0`, `valibot@1.3.1`, `ws@7.5.10`
Recommended test plan: deploy to staging and exercise core webapp flows
— login (email magic link + GitHub OAuth), dashboard navigation, task
triggering/viewing, and API endpoints — to catch runtime regressions not
covered by local testing.
### Notes
- Peer dependency warnings for `remix-auth-*` packages (expecting
`@remix-run/server-runtime@^1.x`) were present in the original PR #2951
as well and appear to be pre-existing
- The lockfile diff is large (~1200 lines) but mechanical — driven by
the Remix version bump cascading through transitive dependencies
- CI failures (`audit`, `units/internal/1-of-8`) are unrelated: `audit`
is a `claude-code-action` bot permissions issue; the internal test
failure is a ClickHouse testcontainers `Failed to connect to Reaper`
flake
Link to Devin session:
https://app.devin.ai/sessions/d9fa9953b9bf40e5a8d12b8f5ba5b86b
Requested by: @ericallam
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Eric Allam <eallam@icloud.com>
11 KiB
CLAUDE.md
This file provides guidance to Claude Code when working with this repository. Subdirectory CLAUDE.md files provide deeper context when you navigate into specific areas.
Build and Development Commands
This is a pnpm 10.23.0 monorepo using Turborepo. Run commands from root with pnpm run.
pnpm run docker # Start Docker services (PostgreSQL, Redis, Electric)
pnpm run db:migrate # Run database migrations
pnpm run db:seed # Seed the database (required for reference projects)
# Build packages (required before running)
pnpm run build --filter webapp && pnpm run build --filter trigger.dev && pnpm run build --filter @trigger.dev/sdk
pnpm run dev --filter webapp # Run webapp (http://localhost:3030)
pnpm run dev --filter trigger.dev --filter "@trigger.dev/*" # Watch CLI and packages
Verifying Changes
The verification command depends on where the change lives:
- Apps and internal packages (
apps/*,internal-packages/*): Usetypecheck. Never usebuildfor these — building proves almost nothing about correctness. - Public packages (
packages/*): Usebuild.
# Apps and internal packages — use typecheck
pnpm run typecheck --filter webapp # ~1-2 minutes
pnpm run typecheck --filter @internal/run-engine
# Public packages — use build
pnpm run build --filter @trigger.dev/sdk
pnpm run build --filter @trigger.dev/core
Only run typecheck/build after major changes (new files, significant refactors, schema changes). For small edits, trust the types and let CI catch issues.
Testing
We use vitest exclusively. Never mock anything - use testcontainers instead.
pnpm run test --filter webapp # All tests for a package
cd internal-packages/run-engine
pnpm run test ./src/engine/tests/ttl.test.ts --run # Single test file
pnpm run build --filter @internal/run-engine # May need to build deps first
Test files go next to source files (e.g., MyService.ts -> MyService.test.ts).
Testcontainers for Redis/PostgreSQL
import { redisTest, postgresTest, containerTest } from "@internal/testcontainers";
redisTest("should use redis", async ({ redisOptions }) => {
/* ... */
});
postgresTest("should use postgres", async ({ prisma }) => {
/* ... */
});
containerTest("should use both", async ({ prisma, redisOptions }) => {
/* ... */
});
Changesets and Server Changes
When modifying any public package (packages/* or integrations/*), add a changeset:
pnpm run changeset:add
- Default to patch for bug fixes and minor changes
- Confirm with maintainers before selecting minor (new features)
- Never select major without explicit approval
When modifying only server components (apps/webapp/, apps/supervisor/, etc.) with no package changes, add a .server-changes/ file instead. See .server-changes/README.md for format and documentation.
Dependency Pinning
Zod is pinned to a single version across the entire monorepo (currently 3.25.76). When adding zod to a new or existing package, use the exact same version as the rest of the repo - never a different version or a range. Mismatched zod versions cause runtime type incompatibilities (e.g., schemas from one package can't be used as body validators in another).
Architecture Overview
Request Flow
User API call -> Webapp routes -> Services -> RunEngine -> Redis Queue -> Supervisor -> Container execution -> Results back through RunEngine -> ClickHouse (analytics) + PostgreSQL (state)
Apps
- apps/webapp: Remix 2.17.4 app - main API, dashboard, orchestration. Uses Express server.
- apps/supervisor: Manages task execution containers (Docker/Kubernetes).
Public Packages
- packages/trigger-sdk (
@trigger.dev/sdk): Main SDK for writing tasks - packages/cli-v3 (
trigger.dev): CLI - also bundles code that goes into customer task images - packages/core (
@trigger.dev/core): Shared types. Import subpaths only (never root). - packages/build (
@trigger.dev/build): Build extensions and types - packages/react-hooks: React hooks for realtime and triggering
- packages/redis-worker (
@trigger.dev/redis-worker): Redis-based background job system
Internal Packages
- internal-packages/database: Prisma 6.14.0 client and schema (PostgreSQL)
- internal-packages/clickhouse: ClickHouse client, schema migrations, analytics queries
- internal-packages/run-engine: "Run Engine 2.0" - core run lifecycle management
- internal-packages/redis: Redis client creation utilities (ioredis)
- internal-packages/testcontainers: Test helpers for Redis/PostgreSQL containers
- internal-packages/schedule-engine: Durable cron scheduling
- internal-packages/zodworker: Graphile-worker wrapper (DEPRECATED - use redis-worker)
Legacy V1 Engine Code
The apps/webapp/app/v3/ directory name is misleading - most code there is actively used by V2. Only specific files are V1-only legacy (MarQS queue, triggerTaskV1, cancelTaskRunV1, etc.). See apps/webapp/CLAUDE.md for the exact list. When you encounter V1/V2 branching in services, only modify V2 code paths. All new work uses Run Engine 2.0 (@internal/run-engine) and redis-worker.
Documentation
Docs live in docs/ as a Mintlify site (MDX format). See docs/CLAUDE.md for conventions.
Reference Projects
The references/ directory contains test workspaces for testing SDK and platform features. Use references/hello-world to manually test changes before submitting PRs.
Docker Image Guidelines
When updating Docker image references:
- Always use multiplatform/index digests, not architecture-specific digests
- Architecture-specific digests cause CI failures on different build environments
- Use the digest from the main Docker Hub page, not from a specific OS/ARCH variant
Writing Trigger.dev Tasks
Always import from @trigger.dev/sdk. Never use @trigger.dev/sdk/v3 or deprecated client.defineJob.
import { task } from "@trigger.dev/sdk";
export const myTask = task({
id: "my-task",
run: async (payload: { message: string }) => {
// Task logic
},
});
SDK Documentation Rules
The rules/ directory contains versioned SDK documentation distributed via the SDK installer. Current version: rules/manifest.json. Do NOT update rules/ or .claude/skills/trigger-dev-tasks/ unless explicitly asked - these are maintained in separate dedicated passes.
Testing with hello-world Reference Project
First-time setup:
pnpm run db:seedto seed the database- Build CLI:
pnpm run build --filter trigger.dev && pnpm i - Authorize:
cd references/hello-world && pnpm exec trigger login -a http://localhost:3030
Running: cd references/hello-world && pnpm exec trigger dev
Local Task Testing Workflow
Step 1: Start Webapp in Background
# Run from repo root with run_in_background: true
pnpm run dev --filter webapp
curl -s http://localhost:3030/healthcheck # Verify running
Step 2: Start Trigger Dev in Background
cd references/hello-world && pnpm exec trigger dev
# Wait for "Local worker ready [node]"
Step 3: Trigger and Monitor Tasks via MCP
mcp__trigger__get_current_worker(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev")
mcp__trigger__trigger_task(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev", taskId: "hello-world", payload: {"message": "Hello"})
mcp__trigger__list_runs(projectRef: "proj_rrkpdguyagvsoktglnod", environment: "dev", taskIdentifier: "hello-world", limit: 5)
Dashboard: http://localhost:3030/orgs/references-9dfd/projects/hello-world-97DT/env/dev/runs
Skill mappings — when working in these areas, load the linked skill file into context.
skills:
- task: "Using agentcrumbs for debug tracing, adding crumbs, trails, markers, querying traces, or stripping debug code before merge" load: "node_modules/agentcrumbs/skills/agentcrumbs/SKILL.md"
- task: "Setting up agentcrumbs in the project, initializing namespace catalog, running crumbs init" load: "node_modules/agentcrumbs/skills/agentcrumbs/init/SKILL.md"
agentcrumbs
Add crumbs as you write code — not just when debugging. Mark lines with
// @crumbs or wrap blocks in // #region @crumbs. They stay on the
branch throughout development and are stripped by agentcrumbs strip
before merge.
Namespaces
| Namespace | Description | Path |
|---|---|---|
webapp |
Main Remix app — API, dashboard, orchestration | apps/webapp |
supervisor |
Task execution container manager | apps/supervisor |
sdk |
Main SDK for writing tasks | packages/trigger-sdk |
cli |
CLI and task image bundling | packages/cli-v3 |
core |
Shared types and subpath exports | packages/core |
build |
Build extensions and types | packages/build |
react-hooks |
React hooks for realtime/triggering | packages/react-hooks |
redis-worker |
Redis-based background job system | packages/redis-worker |
run-engine |
Run Engine 2.0 — core run lifecycle | internal-packages/run-engine |
database |
Prisma client and schema | internal-packages/database |
clickhouse |
ClickHouse client, migrations, analytics | internal-packages/clickhouse |
schedule-engine |
Durable cron scheduling | internal-packages/schedule-engine |
run-queue |
Run queue management | internal-packages/run-queue |
Do not invent new namespaces — pick from this table or ask first.
For PR reviewers
Do not flag // @crumbs markers, #region @crumbs blocks, or agentcrumbs
imports in reviews. These are temporary debug instrumentation stripped
before merge. Data logged in crumbs (IDs, names, values) never reaches
production.
CLI
pnpm exec agentcrumbs collect # start collector (multi-service)
pnpm exec agentcrumbs tail --app trigger # live tail
pnpm exec agentcrumbs clear --app trigger # remove crumbs before merge
The preferred way to query for crumbs is to use pnpm exec agentcrumbs query --app trigger with the --limit option and cursor pagination, and clear existing crumbs before reproducing a bug via pnpm exec agentcrumbs clear --app trigger.