Commit graph

108 commits

Author SHA1 Message Date
Bryan Helmkamp
cccb557281
feat(api): unify public run shape
Return canonical Run payloads across run list, board, create, and lifecycle endpoints. Move archive state out of RunStatus and into lifecycle metadata, split sandbox runtime from planned sandbox data, and separate static pull request records from live pull request details.

Regenerate the TypeScript API client and migrate web, CLI, server, store, workflow, and API tests to the new contract.
2026-05-10 20:48:55 -04:00
Bryan Helmkamp
b6d4d240ae
feat(auth): add unified session API
Expose browser and CLI auth sessions through a normalized API, and allow revoking active CLI refresh-token chains while keeping browser sessions non-revocable for v1.
2026-05-10 14:16:23 -04:00
Bryan Helmkamp
5209d05623
refactor(sandbox): unify run sandbox identity
Replace the separate sandbox record shape with a typed RunSandbox model shared by projections, API responses, and generated clients. The public contract now uses SandboxProvider plus a non-null id and working_directory, and removes sandbox identifier/name leakage.
2026-05-10 13:16:57 -04:00
Bryan Helmkamp
ac90bb199c
feat(server): add Daytona VNC preview endpoint
Adds the sandbox VNC API contract, Daytona Computer Use startup flow, signed noVNC preview response, and generated TypeScript client support.
2026-05-10 00:06:43 -04:00
Bryan Helmkamp
36c5a86005
refactor(runs): simplify run projection shape
Make run.created the projection anchor and require canonical run spec/status fields in API and clients.

Collapse diff/checkpoint/conclusion payloads around RunDiff and update server, CLI, workflow, store, and generated clients.
2026-05-09 23:31:43 -04:00
Bryan Helmkamp
929ece9f6d
test(run-files): cover commits route envelope 2026-05-09 15:34:36 -04:00
Bryan Helmkamp
010828ae7a
Add run commit diff picker 2026-05-09 14:49:15 -04:00
Bryan Helmkamp
447b94da6d
feat(run-files): add sandbox diff scopes
Add committed, uncommitted, and all scope handling for run files with source reporting for sandbox and final patch responses.

Wire the run files page to persist scope in the URL and cache each scope independently.
2026-05-09 13:00:14 -04:00
Bryan Helmkamp
42fa31244a
test(server): expect project settings without directory 2026-05-09 10:55:56 -04:00
Bryan Helmkamp
5fc9157017
refactor(workflow): remove retro stage (#230)
## Summary

Removes Fabro's automatic retro generation stage so workflow runs go
directly from execution to finalization and optional PR creation. This
drops the retro-specific crate, events, projection fields, config/API
knobs, and user-facing docs in favor of the existing durable run
observability surfaces.

## What Changed

- Deleted the `fabro-retro` crate and the workflow `retro` pipeline
phase, with finalization now consuming `Executed` state directly.
- Removed retro configuration and API surface area, including
`--no-retro`, `[run.execution].retros`, manifest `no_retro`,
`features.retros`, and run projection `retro*` fields.
- Retired typed `retro.*` events while keeping historical event logs
readable by deserializing retired retro event names as `Unknown`.
- Stopped appending retro sections to generated PR bodies and updated
docs, marketing copy, screenshots, and navigation to point users toward
observability/event-stream inspection.

## Testing

Not run during PR creation; this branch already contained the
implementation commit.

---

[![Compound
Engineering](https://img.shields.io/badge/Compound_Engineering-6366f1)](https://github.com/EveryInc/compound-engineering-plugin)
🤖 Generated with GPT-5 (unknown context, reasoning unspecified) via
[Codex](https://openai.com/codex)
2026-05-09 10:18:20 -04:00
Bryan Helmkamp
23cb211cce
feat(runs): surface diff summary counts
Compute cheap diff stats on checkpoint and terminal events, roll them into run summaries, and use them for the Files Changed tab badge without fetching full file diffs.
2026-05-07 17:34:32 -07:00
Bryan Helmkamp
c39ff666ed
fix(server): default foreground logs to stdout
Keep daemon and hidden serve logs on the file destination by default, while making foreground server commands stream logs to the terminal unless the server config explicitly selects file logging.
2026-05-06 12:41:52 -04:00
Bryan Helmkamp
2d7c79de1e
feat(server): validate Daytona API key scopes
Probe the Daytona API at install, `fabro secret set DAYTONA_API_KEY`,
and `fabro doctor` time to confirm the configured key carries the
snapshot/sandbox scopes Fabro needs. Operators now see a precise scope
error against the control plane instead of a generic sandbox-create
failure at first run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 17:09:01 -04:00
Bryan Helmkamp
886173f5ad
refactor(server): gate test app state helpers
Move test-only app state constructors into the gated test_support module
so release builds do not expose or link fixture helpers and secrets.
2026-05-02 13:02:41 -04:00
Bryan Helmkamp
d10e0f5c56
refactor: simplify auth and actor handling
Tighten auth state to remove impossible identity branches and stringly error codes.
Route worker JWTs by header metadata, avoid unnecessary auth context cloning, and reuse shared helpers across tests and Slack payload handling.
Carry typed timeout actor metadata through failures instead of deriving it from display text.
2026-05-02 11:44:17 -04:00
Bryan Helmkamp
8d7b9a804a
Unify run event principals 2026-05-01 21:56:47 -04:00
Bryan Helmkamp
b96647314c
docs(deployment): split into local vs self-hosted, drop Render/Fly/DO
Reframe the deployment docs around the actual product story: Fabro
runs as a server, and the only deployment question is where that
server runs (laptop vs self-hosted Docker). Drop the Render, Fly.io,
and DigitalOcean guides and their config files; keep Railway as the
managed shortcut.

- New: administration/deployment.mdx (overview, two-mode framing)
- New: administration/self-host-docker.mdx (compose-first how-to)
- Move: administration/deploy-server.mdx -> reference/server-operations.mdx
  (it was operational reference, not deploy guidance)
- Delete: deploy-render.mdx, deploy-fly-io.mdx, deploy-digital-ocean.mdx
- Delete: render.yaml, fly.toml, railway.toml, Dockerfile.deploy
- docker-compose.yaml: load .env if present so users can drive the
  stack from a single env file end-to-end
- Update internal links and the docs-test that pinned the old path
2026-05-01 09:26:35 -04:00
Bryan Helmkamp
2abf50f0a5
refactor(server): project precise stage states 2026-04-30 06:26:45 -04:00
Bryan Helmkamp
a6a11cdd82
chore(run-files): fix pre-existing clippy lints
- classify_section now returns FileDiffChangeKind directly (unnecessary_wraps)
- collapse nested Some(...) or-pattern into single arm (unnested_or_patterns)
- replace .unwrap() with .expect() in append_completed_run_with_final_patch test helper (unwrap_used)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:16:40 -04:00
Bryan Helmkamp
6156f65799
fix(run-files): normalize degraded file diffs
Return degraded run files with the same FileDiff[] shape as live responses, using nullable contents and per-file unified patches so the web sidebar and deep links work consistently.
2026-04-29 13:00:55 -04:00
Bryan Helmkamp
9ad47990f4
fix(web): include server URL in auth quick start
Expose the configured server.web.url in system info so the empty runs quick start can show a runnable fabro auth login command instead of a placeholder.
2026-04-29 07:45:17 -04:00
Bryan Helmkamp
2460ffc37a
feat(install): add sandbox provider step to web install wizard
Operators choose Docker (default, zero-config) or Daytona (validated
via Daytona SDK) during browser install. Selection is captured in
settings.toml under [run.sandbox] -- explicitly even for Docker, so the
choice is locked in. Daytona keys land in the vault as DAYTONA_API_KEY
(Environment secret). Step always runs after object_store and before
the LLM step.

Server adds POST /install/sandbox/test (validates Daytona key via
client.list) and PUT /install/sandbox; both reuse the install-token
auth and InstallSecret redaction patterns established by object-store.
A resolve_install_sandbox_state helper preserves a saved Daytona key
when the operator revisits the step without re-entering it. The
in-memory api_key is dropped from PendingInstall after finish, matching
the manual_credentials cleanup for S3 access keys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 14:59:17 -07:00
Bryan Helmkamp
f0d34f6e87
Make Rust tests independent of SPA assets 2026-04-27 08:17:37 -07:00
Bryan Helmkamp
54c5f30586
docs: move published docs under docs/public
Relocate the Mintlify tree to docs/public and consolidate internal docs under docs/internal. Update build scripts, tests, CI filters, README references, and local docs skills to follow the new layout.
2026-04-26 21:19:46 -04:00
Bryan Helmkamp
c28b040c6f
fix(install): reject wildcard public URLs
Normalize bind-address wildcards before presenting install URLs, reject wildcard public origins at CLI and server install boundaries, and surface recovery guidance in the installer and doctor output.
2026-04-25 18:58:00 -04:00
Bryan Helmkamp
f537222372
feat(auth): store dev tokens in auth store
Persist dev-token credentials in auth.json alongside OAuth entries so CLI targets resolve credentials consistently across TCP and Unix socket flows.

Move install-time token minting to runtime storage, add auth login --dev-token, and refresh the embedded SPA after updating the stale dev-token hint.
2026-04-24 16:02:36 -04:00
Bryan Helmkamp
64dbdf2500
fix(ci): resolve workspace test and lint regressions 2026-04-23 20:49:30 -04:00
Bryan Helmkamp
8f47bc9317
migrate server tests off raw settings layers 2026-04-23 18:31:33 -04:00
Bryan Helmkamp
2a60b6c3dc
add workflow settings builder toml entrypoint 2026-04-23 15:12:48 -04:00
Bryan Helmkamp
9220af6e80
migrate remaining run settings consumers to dense snapshots 2026-04-23 11:55:12 -04:00
Bryan Helmkamp
b2bcf0d5a8
refactor settings builders and dense run snapshots 2026-04-23 11:35:21 -04:00
Bryan Helmkamp
37cd8ff45f
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-server/src/lib.rs
#	lib/crates/fabro-server/src/serve.rs
#	lib/crates/fabro-server/src/server.rs
2026-04-23 08:34:44 -04:00
Bryan Helmkamp
e6e091fe8e
refactor(server): lock down server secrets 2026-04-23 07:15:27 -04:00
Bryan Helmkamp
fa62da5d9d
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-api/build.rs
#	lib/crates/fabro-server/src/install.rs
#	lib/crates/fabro-server/src/serve.rs
#	lib/packages/fabro-api-client/src/.openapi-generator/FILES
#	lib/packages/fabro-api-client/src/models/index.ts
2026-04-22 21:18:50 -04:00
Bryan Helmkamp
4bf0c40319
feat(install): add object-store step to web install 2026-04-22 19:31:09 -04:00
Bryan Helmkamp
ebb8bf7add
refactor settings API entrypoints 2026-04-22 18:58:47 -04:00
Bryan Helmkamp
911f957200
refactor(config): move Bind and ServerDaemon into fabro-config
`Bind` and `ServerDaemon` are serde-serialized descriptions of on-disk
server state (the `server.json` record). They belong with
`RuntimeDirectory` in fabro-config rather than in fabro-server's web
layer.

The practical payoff: fabro-test was hand-parsing `server.json` via
`serde_json::Value["pid"]` because fabro-server already depends on
fabro-test (cycle blocked the reverse edge). Moving these types into
fabro-config lets fabro-test call `ServerDaemon::{load_running, read,
remove}` directly, dropping ~20 lines of duplicated record parsing.

fabro-config gains `fabro-proc` and `tempfile` as deps to cover
`ServerDaemon::{is_running, write}`. All 16 `fabro_server::{bind,
daemon}` import sites in fabro-server and fabro-cli are rewritten to
`fabro_config::{bind, daemon}`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-22 16:44:59 -04:00
Bryan Helmkamp
acc6dc49bf
Merge remote-tracking branch 'origin/main' 2026-04-22 16:25:53 -04:00
Bryan Helmkamp
7a58ab4e2b
refactor(server): unify daemon runtime metadata 2026-04-22 16:07:52 -04:00
Bryan Helmkamp
27cc1bb6c2
test(server): make global attach filter deterministic 2026-04-22 16:04:33 -04:00
Bryan Helmkamp
702c18cbb4
Merge remote-tracking branch 'origin/main' 2026-04-22 00:46:59 -04:00
Bryan Helmkamp
537a5125cb
feat(auth): tighten server auth surface with single origin
Implements plan: single origin, drop CLI preflight, gate demo toggle.
Removes loopback client target and CLI auth config preflight endpoint;
adds canonical_origin module on the server; regenerates SPA and TS API
client.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:38:31 -04:00
Bryan Helmkamp
5b1c40764d
refactor(cli): enforce CLI/server settings boundary
Move server-only settings reads out of user-facing CLI commands into a
dedicated local_server module, the install/uninstall exceptions, and the
worker subcommand. Adds bin/dev/check-boundary.sh to prevent regressions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 23:37:15 -04:00
Bryan Helmkamp
3f6cc1f1ba
Merge remote-tracking branch 'origin/main' 2026-04-21 14:47:23 -04:00
Bryan Helmkamp
328bddea33
fix(install): pass GitHub App manifest state as form field, not URL query
GitHub's App Manifest endpoint rejects `redirect_url` values that carry a
query string with "invalid redirect_uri", leaving the web wizard stuck:
the 10-minute pending-setup guard then blocked every retry for ten
minutes. Move the CSRF state out of `redirect_url` and into a hidden
`state` form field on the auto-submit — GitHub preserves it on the
callback, matching the CLI's working Manifest flow. Drop the retry
conflict so a fresh POST to /install/github/app/manifest always replaces
the pending entry and mints a new state token; stale callbacks are
already rejected by the existing state-match check on the redirect
handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 14:21:33 -04:00
Bryan Helmkamp
a3e4e2bd3d
Merge remote-tracking branch 'origin/main' 2026-04-21 09:40:09 -04:00
Bryan Helmkamp
7a70af1e2b
refactor(auth): translate non-jwt auth into bearer tokens
Move session cookie and dev credential handling into middleware so the
real router only sees Bearer JWTs. This also carries profile claims
through /auth/me and requires session signing material whenever auth is
enabled.
2026-04-21 09:05:20 -04:00
Bryan Helmkamp
f75e5c2ef6
refactor(store): extract Record/Repository abstractions
Replaces hand-written K/V stores in fabro-store with a shared Record trait
plus Repository<R> typed K/V layer. Adds KeyedMutex for per-key serialization
and transaction() for all-or-nothing WriteBatch commits. Renames
SlateAuthCodeStore/SlateAuthTokenStore to AuthCodeStore/RefreshTokenStore and
adds BlobStore and RunCatalogIndex wrappers on top of Repository. Deletes
catalog.rs in favor of RunCatalogIndex. Database gains blobs() and
catalog_index() accessors; auth_tokens() is renamed refresh_tokens().

Plan: docs/plans/2026-04-20-003-refactor-fabro-store-record-abstractions-plan.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 08:29:34 -04:00
Bryan Helmkamp
ed6fecfc5a
fix(auth): harden loopback checks and align CSP tests
Tighten CLI loopback target classification to use literal host checks,
update explicit local TCP auth coverage to match the remote-target
contract, and align server CSP assertions with the current external-script
SPA bundle. Also enable reqwest cookies in fabro-http so package-scoped
server tests compile without relying on workspace feature unification.
2026-04-20 13:30:45 -04:00
Bryan Helmkamp
4c35c4b69f
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-server/src/jwt_auth.rs
#	lib/crates/fabro-server/src/serve.rs
#	lib/crates/fabro-server/src/server.rs
#	lib/crates/fabro-server/src/web_auth.rs
2026-04-20 09:47:47 -04:00