docs(requests): playtrek prod auto-deploy via Forgejo Actions #2

Open
gmackie wants to merge 1 commit from request/playtrek-prod-autodeploy into main
Owner

PlayTrek team request. The nextjs CF Worker has never auto-deployed: the Forgejo deploy gate used gh (GitHub CLI) which can't read Forgejo (fixed PlayTrek-side, #43), and the wrangler step fails because the repo's Forgejo Actions secrets (CLOUDFLARE_API_TOKEN, FORGEGRAPH_TOKEN) are never provisioned. forge deploy create production --platform cloudflare-workers --target web dry-runs valid. Asking the platform team: should CI call forge deploy directly (with a CI-scoped FORGEGRAPH_TOKEN) or report evidence + ForgeGraph orchestrates — and who provisions the Forgejo Actions secrets? Full detail in the doc.

PlayTrek team request. The nextjs CF Worker has never auto-deployed: the Forgejo deploy gate used `gh` (GitHub CLI) which can't read Forgejo (fixed PlayTrek-side, #43), and the wrangler step fails because the repo's Forgejo Actions secrets (CLOUDFLARE_API_TOKEN, FORGEGRAPH_TOKEN) are never provisioned. `forge deploy create production --platform cloudflare-workers --target web` dry-runs valid. **Asking the platform team:** should CI call `forge deploy` directly (with a CI-scoped FORGEGRAPH_TOKEN) or report evidence + ForgeGraph orchestrates — and who provisions the Forgejo Actions secrets? Full detail in the doc.
Code-verified domain glossary covering 21 design decisions resolved via
/grill-with-docs interrogation. Adds Evidence Plane section (attestations,
stages, readiness, release candidates, hub dispatch, etc.), Tenancy Model
section (team/workspace hierarchy), and updates Package Registry terms to
use changeset terminology instead of Forgejo-specific language.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full design exploration covering git backend, repo types, evidence
pipelines, PR review system, CI/CD, package registry, AI agent workflows,
deploy targets, sidecars, pricing, and execution roadmap. Reviewed across
CEO, Design, Eng, and DX dimensions via /autoplan.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Comprehensive design plans for two new ForgeGraph sidecar products:
- Mobile Sidecar (mobile.forgegraf.com): compliance checking, store
  submission automation, metadata-as-code, Maestro E2E, device farm
- Fabrication Sidecar (fab.forgegraf.com): STL/SVG/G-code preview and
  diff, dimension validation, slicer integration, fabrication queue

Both are monorepo apps (apps/mobile-sidecar, apps/fab-sidecar) with
separate CF Worker deploys, designed to be extractable to standalone
repos later.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expanded from 1,690 to 1,880 lines with additional detail on STL diff
algorithms (voxel occupancy + Hausdorff distance), material estimation
formulas, machine profile JSON schema, and Veritas overlap boundaries.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expanded from 1,789 to 2,248 lines with 15 Drizzle schema tables
(ms_ prefix), full REST API spec, 9 attestation types, tRPC router
listing, forge mobile CLI command tree, and 7-phase roadmap.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add attestation type registry, sidecar registration, failed status,
satisfiedBy tracking, and Preflight/Fabrication sidecar definitions to
CONTEXT.md. Add 4 P1/P2 evidence pipeline wiring TODOs identified
during eng review (dead code: tryAutoDispatch, ensureAttestations,
idempotency key, lane wake-up).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Schema changes:
- Add 'failed' status to attestation_status enum
- Add failureReason and satisfiedBy columns to attestations
- Add attestation_timeout to intervention_type enum
- New sidecar_registrations table (workspace-scoped)
- New attestation_types table with producerId FK to sidecars

Pipeline wiring (fixes dead code):
- Wire tryAutoDispatch into evidence route (build/test events)
- Wire ensureAttestations into changeset creation (3 paths)
- Fix idempotency key: (changesetId, lane) guard replaces evidenceId
- Set satisfiedBy='forgegraph' on built-in auto-satisfy
- Handle failed attestations in readiness computation

New endpoints:
- POST /api/v1/attestations — sidecar attestation submission with
  PAT auth, producer validation, and auto-dispatch trigger
- POST /api/fg/cron/attestation-timeout — sweep pending attestations
  past their timeoutMs, auto-fail with intervention

Infrastructure:
- Extract shared fireWebhook utility from readiness-webhook
- Add sidecar-dispatch module with HMAC-signed outbound webhooks
- Add changeset-lifecycle module for post-creation hooks

15 decisions from /grill-with-docs + /plan-eng-review sessions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add /api/v1/ to middleware PUBLIC_PREFIXES so sidecar endpoints are
  not redirected to /login (they handle their own auth)
- Add attestation_pending, attestation_satisfied, attestation_failed to
  changeset_event_kind enum
- Fix cron timeout query: use now() instead of JS Date param, add
  try/catch with error response

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pin @vitejs/plugin-react peer dep to <6.0.0 (v6 requires vite 8)
- Update otel pushHttpSpan test: function now returns traceId/spanId
  even on fetch failure
- Update changeset-event-kind snapshot with attestation event kinds
- Update control-plane-db-sync test for HOME/PGHOST env vars
- Update apps route test for user/repos endpoint and private flag

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- POST/GET /api/fg/sidecars — list and register sidecar integrations
- GET/PATCH/DELETE /api/fg/sidecars/:id — manage individual sidecars
- POST/GET /api/fg/attestation-types — list and register attestation types
- GET/PATCH/DELETE /api/fg/attestation-types/:id — manage individual types

All endpoints are workspace-scoped with bearer token auth. Sidecar
webhook secrets are stored as-is, auth tokens are SHA-256 hashed.
Attestation type list includes producer sidecar name via LEFT JOIN.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When tryAutoDispatch creates an execution request in "auto" mode, it now
immediately attempts to dispatch to Control Panel if CONTROL_PANEL_URL
and CONTROL_PANEL_TOKEN are configured. This closes the lane-completion
wake-up gap where pending requests were created but never dispatched.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- forge db migrate --file --node --ref: dispatch SQL execution to remote
  nodes via the hub's run-migration command handler. Resolves node slugs
  to UUIDs via resolveNodeID before hub dispatch.
- forge node ping: verify end-to-end hub command routing to a node.
  Diagnoses the discrepancy between heartbeat-online and hub-connected.
- forge node list: show HUB column (connected/disconnected) by querying
  the hub's /api/nodes alongside the database heartbeat status.
- run-migration handler: accept optional dbName param for targeting a
  specific database on the node.

Fixes: docs/requests/veritas-db-migrate-hub-routing.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The agent wrote SQL temp files as root (0600) but ran psql as the
postgres user, causing Permission denied. Also return error data from
dispatchAndWait so callers can display psql output on failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Migrations run as postgres superuser via sudo, so new tables are owned
by postgres and inaccessible to the app user (<dbName>_app). Now
automatically grants SELECT/INSERT/UPDATE/DELETE on all tables and
sequences to the app user after a successful migration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cross-compiles forge CLI for darwin/linux (amd64+arm64), generates
checksums, and auto-publishes a Homebrew formula to
gmackorg/homebrew-forgegraph on tag push.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- turbo 2.9.12 → 2.9.14 (CSRF/session fixation, local code execution)
- uuid 7.x/8.x → 11.1.1 via pnpm.overrides (missing buffer bounds check)
- ws 8.18.0 → 8.20.1 via pnpm.overrides (uninitialized memory disclosure)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add workspace-level GCP service account management with three layers:
- Auth: JWT/RS256 token acquisition via Web Crypto API (CF Workers compatible)
- Service: GCP project lifecycle, API enablement, SA provisioning with
  retry/backoff, LRO polling, and structured error types
- Router: tRPC endpoints for createProject, enableApis, createServiceAccount,
  getProjectStatus, syncState

Also adds gcpAppBindings schema, integration registry entry, verifier,
and unit tests (14 passing).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Throw on failed secret storage instead of silently swallowing
- Add PROJECT_ID_RE validation to prevent path traversal in GCP URLs
- Refresh tokens inside polling loops to handle long-running operations
- Add ON DELETE CASCADE to gcpAppBindings.appId FK
- Handle unique constraint race condition in createProject

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace pgEnum with text for status column — Hyperdrive's connection
pooler fails on custom enum types created after pool initialization.
Replace wdb.workspace() with direct query — Drizzle's relational query
builder generates aliased SQL that fails through Hyperdrive.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds Google as a social provider in better-auth config (conditional on
GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET env vars). Login route accepts
?provider=google param, and login page shows a "Sign in with Google"
button below the existing GitHub button.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implements a dashboard-first UI for starting/stopping Expo dev servers
on remote hetzner VPS nodes with ngrok tunnel support. Includes schema
changes (preparing/stopped status, nullable port/advertisedUrl, repoUrl
on apps), dev_session.prepare job contract and Go agent handler, API
routes for listing/starting/stopping sessions, control plane job
chaining (prepare -> start), and a client-side dashboard with app cards
showing session state transitions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "preparing" case to readDevSessionStatus() to prevent silent status promotion
- Require workspaceId and verify ownership on session detail/list endpoints
- Fix git fetch error handling: use exec.Command directly instead of runGit which swallows errors
- Block ext::/fd:: git remote protocols and path traversal in appSlug/sessionCheckoutId
- Include "stopping" in transitioning poll states for faster UI updates

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixes multiple issues preventing the dev server dashboard from working end-to-end:

- Go agent: skip source binding validation for prepare-originated start jobs
  (devSessionId bypass) since workspace root differs from runner config
- Go agent: don't crash the runner loop on prepare job failures (return nil error)
- Go agent: add heartbeat goroutine for long-running prepare jobs
- Control plane: bypass workspace root check for dev_session.stop jobs
  (checkout dir never matches runner workspace root)
- Control plane: pass devSessionId through start job payload for session identity
- Control plane: look up existing session by devSessionId in recordDevSession
- API routes: restore workflow state from DB before snapshot reads (CF Worker
  cold start has empty in-memory state)
- API routes: persist mutation results for stop/cancel operations
- API routes: update session status in DB on cancel (preparing→stopped)
- Dashboard: pass workspaceId from server component to client shell
- Dashboard: fix runner capability filtering for adapters array format

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hardens input validation and fixes zombie session states:
- Validate repoURL scheme (allowlist: https, http, ssh, scp-style)
- Reject branch names and repoURLs starting with dash
- Add packagePath traversal check with filepath.Clean boundary
- Scope cross-workspace DB queries by workspaceId
- Handle dev_session.start failures to prevent stuck "starting" sessions
- Fix stale closure in dashboard fetchData callback

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add retryable failure codes (git_clone_failed, git_fetch_failed,
  install_failed) to dev_session.prepare contract with jittered backoff
- Map agent prepare errors to specific failure codes for retry matching
- Add null guard in requireForgeGraphWorkspaceAdmin for type safety
- Return empty array from filterForgeGraphWorkspaceScope when unauthenticated
- Add 5 control plane tests: prepare session insertion, prepare job
  queueing, prepare→start chaining, prepare failure, start failure

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Standalone Go binary for Preflight mobile delivery operations:
- CLI commands: run (loop/once), auth, platform detection, config
- Runner loop with job claim/heartbeat/completion lifecycle
- Command plan executor for Expo dev servers, EAS builds, Maestro tests
- Source binding discovery (git, Expo config, EAS config digests)
- Provider management for Apple/Google credential flows
- Setup workflow orchestration for guided app onboarding
- Workflow watch with real-time event streaming
- Comprehensive test coverage for all modules

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Renumber migrations from 0059+ for fabrication and preflight domains
- Add preflight core schema: apps, runners, workflows, dev sessions,
  launches, targets, diagnostics, provider accounts, secret refs
- Add fabrication schema: work orders, jobs, resources, integrations,
  production records, prepared action intents, service submissions
- Add schema tests and vitest config for packages/db

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Preflight:
- Runner control plane with job queueing, completion chaining, and
  snapshot hydration for CF Worker singleton pattern
- Job contracts for all runner job kinds (builds, dev sessions, Maestro,
  capabilities probe, source binding)
- Workflow persistence, launch management, and cockpit projections
- Provider management for Apple/Google credential flows
- Attestation, diagnostics, and target runtime persistence
- Comprehensive test suite (240 tests across 25 files)

Fabrication:
- Service layer with work order lifecycle management
- Integration provider tests for GCP workspace

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Complete Preflight web application deployed to Cloudflare Workers:
- API routes for runners, workflows, launches, apps, dev servers,
  artifacts, capabilities, logs, setup transcripts, and secret refs
- Dev server dashboard with start/stop/status lifecycle
- Cockpit shell for real-time workflow monitoring
- Auth middleware (bearer, session, header-based) with workspace scoping
- Storage layers for workflows, runners, apps, launches, diagnostics,
  providers, and secrets
- Playwright E2E test configuration
- Route-level test suites for all API endpoints
- OpenNext + Wrangler deployment configuration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Update all 22 Maestro test flows for current app state
- Add simulator run script improvements
- Update EAS build configuration

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fabrication API routes: work orders, jobs, resources, integrations,
  runner invocations, status observations, service submissions,
  prepared action intents, production records, checklists
- Fabrication board UI with landing page
- Middleware updates for fabrication and settings routes
- Settings integrations page with connector management
- Test coverage for fabrication routes and middleware

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 65 Architecture Decision Records covering preflight and fabrication
  domains: runner lifecycle, job contracts, provider management,
  work order semantics, prepared action intents, production records
- Design plans: preflight lifecycle, fabrication sidecar, prove-app
  workflow, sidecar extraction
- Contract specifications: preflight capabilities and runner jobs
- Fabrication design document (FAB_DESIGN.md)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add agent/preflight binary to .gitignore
- Update pnpm-lock.yaml with new package dependencies

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Design for adding a Preflight tab to the ForgeGraph mobile app:
- Full companion scope: dev servers, launches, runners
- Direct REST client to preflight.forgegraf.com (shared Bearer auth)
- QR code screen as centerpiece for on-device testing
- Start/stop dev servers from mobile
- Launch approval with haptic feedback
- 13 new files, ~1500-2000 LOC estimated

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Wire the agent deploy loop: `forge deploy create <stage> --agent` streams
JSONL events to stdout, runs health checks with retries, and provides
structured rollback commands on failure.

Schema: extend deployments table with actor, actorType, failureReason,
durationMs, versionId, previousVersionId, completedAt. Add health_checking
and success_unchecked statuses. Create deployment_events table for cursor-
based event streaming.

Server: event writer helper, GET /api/fg/deploy/[id]/events?after=<seq>
endpoint, POST /api/fg/deploy/[id]/rollback endpoint, extended agent
report to accept events and version IDs.

Agent: capture previous CF Worker version before deploy via ListVersions(),
health check retry loop (3 attempts, 5s intervals), wire RollbackWorker()
with previousVersionId for CF Workers, wire Nix rollback via store path
with GC check.

CLI: --agent flag (implies --json --wait), JSONL event streaming in poll
loop, `deploy rollback <id>` subcommand.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full mobile companion for Preflight: REST API client, summary dashboard,
dev server list/detail/start with QR code display, launch pipeline with
approve/submit, and runner fleet health. 13 new files, 3 dependencies added.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The /runners/capacity endpoint returns aggregate capacity, not individual
runner details. Runner data comes from the dev-servers endpoint which
already includes online runners with display names and capabilities.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Replace empty catch blocks with Alert.alert error feedback
- Restart flow polls session status instead of naive 2s delay
- Add error handling to usePreflight hook init
- Implement adaptive polling (5s during transitions, 30s stable)
- Remove unused imports and dead code

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New "Deploys" tab on app detail page showing deployment history as a
vertical timeline. Each deploy card shows status, stage, actor, duration,
changeset context (title, author, branch, SHA), and expandable event
stream from deployment_events. One-click rollback with confirmation
for eligible deployments. Stage filter for multi-stage apps.

TRPC: add deployment.listByAppDetailed endpoint that joins changeset
metadata and batch-fetches deployment events.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Lazy-loaded diff viewer in the Deploys tab — click "View diff" on any
deployment linked to a changeset to see the parsed unified diff inline.
Per-file collapsible sections with +/- line counts, colored added/removed
lines, and hunk headers.

TRPC: add deployment.diffByDeployment endpoint that fetches and parses
the changeset's cachedDiff.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
docs(requests): playtrek prod auto-deploy via Forgejo Actions
Some checks failed
AI Code Review / review (pull_request) Failing after 7s
CI / ci (pull_request) Failing after 5m45s
8cdb588caf
PlayTrek's nextjs CF Worker has never auto-deployed. Diagnosed: the deploy gate
used `gh` against Forgejo (always timed out → deploy skipped; fixed PlayTrek-side),
and with that removed the wrangler step fails because the repo's Forgejo Actions
secrets (CLOUDFLARE_API_TOKEN, FORGEGRAPH_TOKEN) are never provisioned. `forge
deploy create production --platform cloudflare-workers --target web` dry-runs
valid. Asks the platform team how CI should authenticate + trigger a forge CF
Worker deploy (direct `forge deploy` with a CI token, vs evidence + orchestration),
and who provisions the Forgejo Actions secrets.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author
Owner

Update — wired evidence reporting (PlayTrek #46, merged) and it surfaced the real blocker: ForgeGraph has no changeset for the merge commit, so evidence resolution 404s.

PlayTrek now builds the worker and reports build evidence via the vendored report-evidence action (main-only, per the staging→prod auto-promote warning). On the first run (merge commit d57b3efe) the build+evidence job failed.

Diagnosis from the ForgeGraph side: report.sh resolves the changeset with GET /api/evidence/resolve?git_sha=<sha>&repository_id=<id>, but forge changeset list for playtrek shows the most recent changeset is dc0d2736 ("updates", merged 2026-05-06) — none of the recent Forgejo PR-merges (all of this week's work) have changesets. So the resolve has nothing to match → 404 → evidence step fails.

Platform question: PlayTrek merges via Forgejo PRs (git, not the jj/changeset flow). For the evidence→deploy model to work, either (a) ForgeGraph needs to auto-create a changeset on Forgejo push/merge to main, (b) /api/evidence/resolve should auto-create a changeset for an unseen SHA, or (c) PlayTrek must adopt the forge changeset/jj workflow. Which is intended? (Couldn't confirm the exact failing step — Forgejo Actions logs aren't API-reachable — but the missing changeset is the clear gap.)

Interim: PlayTrek deploys manually (pnpm -F nextjs deploy), prod is current + healthy.

**Update — wired evidence reporting (PlayTrek #46, merged) and it surfaced the real blocker: ForgeGraph has no changeset for the merge commit, so evidence resolution 404s.** PlayTrek now builds the worker and reports build evidence via the vendored `report-evidence` action (main-only, per the staging→prod auto-promote warning). On the first run (merge commit `d57b3efe`) the **build+evidence job failed**. Diagnosis from the ForgeGraph side: `report.sh` resolves the changeset with `GET /api/evidence/resolve?git_sha=<sha>&repository_id=<id>`, but `forge changeset list` for playtrek shows the **most recent changeset is `dc0d2736` ("updates", merged 2026-05-06)** — none of the recent Forgejo PR-merges (all of this week's work) have changesets. So the resolve has nothing to match → 404 → evidence step fails. **Platform question:** PlayTrek merges via Forgejo PRs (git, not the jj/changeset flow). For the evidence→deploy model to work, either (a) ForgeGraph needs to auto-create a changeset on Forgejo push/merge to main, (b) `/api/evidence/resolve` should auto-create a changeset for an unseen SHA, or (c) PlayTrek must adopt the `forge changeset`/jj workflow. Which is intended? (Couldn't confirm the exact failing step — Forgejo Actions logs aren't API-reachable — but the missing changeset is the clear gap.) Interim: PlayTrek deploys manually (`pnpm -F nextjs deploy`), prod is current + healthy.
Some checks failed
AI Code Review / review (pull_request) Failing after 7s
CI / ci (pull_request) Failing after 5m45s
This pull request can be merged automatically.
This branch is out-of-date with the base branch
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin request/playtrek-prod-autodeploy:request/playtrek-prod-autodeploy
git switch request/playtrek-prod-autodeploy

Merge

Merge the changes and update on Forgejo.

Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.

git switch main
git merge --no-ff request/playtrek-prod-autodeploy
git switch request/playtrek-prod-autodeploy
git rebase main
git switch main
git merge --ff-only request/playtrek-prod-autodeploy
git switch request/playtrek-prod-autodeploy
git rebase main
git switch main
git merge --no-ff request/playtrek-prod-autodeploy
git switch main
git merge --squash request/playtrek-prod-autodeploy
git switch main
git merge --ff-only request/playtrek-prod-autodeploy
git switch main
git merge request/playtrek-prod-autodeploy
git push origin main
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
gmackie/ForgeGraph!2
No description provided.