Commit graph

613 commits

Author SHA1 Message Date
Bryan Helmkamp
28d4242df0
Route Daytona sandboxes through the sandbox driver
The `daytona` provider kind now maps onto the sandbox-driver Daytona
provider instead of fabro's own SDK client. Fabro keeps what is its own:
the HMAC-named snapshot built from the environment's image or Dockerfile,
the explicit 120 minute auto-stop default, the managed labels that gate
destructive operations, the clone decision and layout, and push
credentials. The driver creates the sandbox, clones natively, and serves
exec, files, search, terminal, SSH, preview, and VNC through its facets.

- `daytona.rs` builds the driver `SandboxSpec` (snapshot source,
  `/home/daytona/workspace`, labels, timers, network policy, run name),
  ensures the snapshot through the driver `SnapshotProvider`, attaches by
  persisted id with fabro's label guard, and probes credentials through
  the provider health check under fabro's 20 second budget.
- `DriverSandbox` gains a create plan that settles the spec right before
  the provider call, records the snapshot a sandbox came from, and
  reports the provider console URL on `Ready`.
- Terminals use the driver `Pty` facet; the server's SSH, preview, and
  VNC endpoints use the `SshAccess`, `PreviewUrls`, and `Vnc` facets
  through the driver-typed reconnect. The preview endpoint now answers
  for every provider with a preview facet, so the local sandbox returns
  its loopback URL.
- Daytona credentials travel as `DaytonaCredentials` built from the
  vault key plus configured URL and organization; nothing reads the
  process environment implicitly. The inventory registry uses the shared
  `DriverInventoryProvider`.
- The SDK-based `daytona/mod.rs`, `provider/daytona.rs`, the Daytona
  terminal, the `daytona` cargo feature, and the direct daytona-sdk,
  git2 (in fabro-sandbox), tungstenite, and rustls dependencies are
  gone. The live Daytona tests run against the driver-backed sandbox.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 19:14:13 -06:00
Bryan Helmkamp
3d33935fba
Route Docker sandboxes through the sandbox driver
Fabro's Docker provider kind now maps onto the sandbox-driver Docker
provider instead of its own bollard implementation. Fabro keeps what is
its own: the clone decision and repository layout, the GitHub App push
credentials embedded in origin, git retry classification, the managed
labels that gate destructive operations, and the run-facing events.

- `clone.rs` performs fabro's clone over the driver `Git` and `Exec`
  facets. An exact commit goes through the driver's pinned clone; a tag
  pin runs fabro's init/fetch/attach sequence through `Exec` so the
  fully qualified tag ref is the only revision consulted. Network
  failures retry through `git_retry`, which now classifies driver errors
  (exec output, provider retryability) and never replays an operation
  whose outcome is unknown.
- `DriverSandbox` gains a pending-create state, a `RepoWorkspace` with
  push-credential state, path resolution against the cloned working
  directory, git lifecycle methods, image-pull progress mapped from
  driver events, and an embedded terminal over the driver `Pty` facet.
- `docker.rs` builds the driver `SandboxSpec` (image, `/workspace`,
  fabro labels, env, cpu/memory, network policy, run name) and attaches
  by persisted container id, refusing containers without fabro's labels.
- Inventory, details, diagnostics, terminal, and reconnect run over the
  driver: a `DriverInventoryProvider` lists by fabro's managed label and
  projects `SandboxStatus` into fabro's inventory and details shapes.
- The bollard-based `docker.rs`, `provider/docker.rs`, Docker terminal,
  Docker error variants, the `docker` cargo feature, and the bollard and
  tar dependencies are gone. The Docker integration tests, the agent
  shell test, the workflow artifact test, and the driver benchmark run
  against the driver-backed sandbox.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 17:07:51 -06:00
Bryan Helmkamp
4dcbcec400
Add the single sandbox provider construction function
fabro_sandbox::driver::connect_provider turns one
[server.sandbox.providers.<kind>] entry into an Arc<dyn SandboxProvider>
from the sandbox-driver crates. Bundled kinds link the driver's Host,
Docker, and Daytona providers in-process; Daytona receives its API key
and endpoint explicitly through connect_explicit with a
fabro-sandbox/<version> user agent, never from the process environment.
Any other kind launches the configured plugin executable through a
PluginSupervisor and returns a wrapper that replaces a crashed plugin
for new work only, never replaying a failed call. Disabled entries are
refused at the construction point.

The Host and Docker providers also ship as fabro-sandbox-host and
fabro-sandbox-docker plugin executables so CI can drive the bundled
providers over stdio and a deployment can move one out of process by
configuration alone. An integration test registers the Host executable
under the non-bundled kind `host`, creates a sandbox and runs a command
over the wire, then attaches to it by persisted id from a fresh plugin
process, and checks that a plugin declaring a different kind is refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 15:23:56 -06:00
Bryan Helmkamp
07c52b07ca
Depend on the sandbox-driver crates by git revision
Fabro pins the sandbox-driver workspace the same way it pins the
Daytona SDK: every crate at one commit on main. The bundled Host,
Docker, and Daytona provider libraries link in-process, and the
protocol crate reaches third-party providers over stdio. Nothing uses
the crates yet; the following commits move fabro onto them one layer
at a time.

The driver pins tracing-subscriber exactly, so the lockfile settles on
that version for the whole workspace.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 14:18:58 -06:00
Bryan Helmkamp
aa8b919f1c
Pin daytona-sdk-rust to the merged main commit
Both fabro and sandbox-driver now pin the same daytona-sdk-rust commit
on main. The newer SDK adds region and sandbox class fields to snapshot
creation; fabro leaves both unset and keeps its current behavior.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 13:45:44 -06:00
fabro-releases[bot]
2f326a13c4 Bump version to 0.348.0-nightly.0
Some checks failed
Rust / Format (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Generated Docs (push) Has been cancelled
Rust / Test (Linux) (push) Has been cancelled
Rust / Test (macOS) (push) Has been cancelled
2026-09-06 09:29:10 +00:00
fabro-releases[bot]
efa0d16588 Bump version to 0.347.0-nightly.0 2026-09-05 09:31:42 +00:00
fabro-releases[bot]
86101748da Bump version to 0.346.0-nightly.0 2026-09-04 09:35:05 +00:00
fabro-releases[bot]
a468125ab3 Bump version to 0.345.0-nightly.0 2026-09-03 09:33:32 +00:00
fabro-releases[bot]
2bf41d908b Bump version to 0.344.0-nightly.0 2026-09-02 09:36:17 +00:00
Scott Werner
0fd4714da7
Merge pull request #825 from swerner/codex/automation-workflow-sources
Add independent workflow sources to automations
2026-09-01 12:22:20 -04:00
fabro-releases[bot]
285d485de7 Bump version to 0.343.0-nightly.0 2026-09-01 09:36:51 +00:00
Scott Werner
7a3f58c87e Tighten automation Git validation types 2026-08-31 18:02:08 -04:00
Scott Werner
0b46e1d735 Simplify local RunIntent producer support
Share canonicalize_location and resolve_existing_workflow_location
between the local package resolver and the version collector, drop the
redundant package-root pre-check and the PackageFileReadError enum in
favor of anyhow context, and read HEAD's SHA from git2 instead of a
separate rev-parse subprocess.

Make GitRunTargetObservation a plain struct, replace the repo-info
tuple with a named struct, tighten the closure view trait, avoid
deep-cloning the root workflow during collected validation, remove the
unused into_closure accessor, and dedupe test helpers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 14:08:35 -04:00
fabro-releases[bot]
3a5c683fbf Bump version to 0.342.0-nightly.0 2026-08-31 09:41:11 +00:00
Scott Werner
03f81d1f25 Add independent workflow sources to automations 2026-08-30 13:14:11 -04:00
fabro-releases[bot]
775b62b500 Bump version to 0.339.0-nightly.1 2026-08-28 20:41:40 +00:00
Scott Werner
5cd69e9c66
Merge pull request #820 from fabro-sh/codex/automation-run-intent
Move automation runs to workflow versions and RunIntent
2026-08-28 15:43:31 -04:00
fabro-releases[bot]
f87ece704b Bump version to 0.339.0-nightly.0 2026-08-28 13:11:14 +00:00
Scott Werner
e86dd3bea4 Move automation runs to workflow versions 2026-08-27 15:24:07 -04:00
fabro-releases[bot]
88185f0bd9 Bump version to 0.338.0-nightly.0 2026-08-27 12:48:55 +00:00
Scott Werner
34014e6dce
Merge pull request #790 from fabro-sh/codex/run-intent-folder-target
Add local folder run target
2026-08-26 10:34:59 -04:00
fabro-releases[bot]
ff29795dd8 Bump version to 0.337.0-nightly.1 2026-08-26 13:41:21 +00:00
Bryan Helmkamp
b3d112b206
Harden succeed failure policy routing 2026-08-26 09:13:04 -04:00
fabro-releases[bot]
1289144f03 Bump version to 0.337.0-nightly.0 2026-08-26 09:31:24 +00:00
Bryan Helmkamp
32d6be7ea5
refactor(model): simplify model test plumbing
Review cleanups for the tools/reasoning-effort model test change:

- Extract a shared parse_query_enum helper in the models handler in
  place of two copy-pasted parse-or-400 match blocks.
- Collapse the duplicated basic-probe pipeline in fabro-llm behind a
  single basic_probe core; name the shared EXPANDED_MAX_TOKENS budget.
- Pass &ModelTestArgs to test_models_via_server instead of threading
  five of its fields positionally.
- Dedupe the two forwarding CLI integration tests behind a helper.
- Derive clap::ValueEnum for ReasoningEffort behind a feature-gated
  clap dep (same pattern as MergeStrategy in fabro-types) so --help,
  cli.mdx, and error output list effort values from the enum instead
  of a hand-written list that drifts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TDdjG18d2AHh7mFWXFkBLn
2026-08-25 14:49:34 -04:00
Scott Werner
c396a6cf6f Add local folder run target 2026-08-25 11:59:37 -04:00
Scott Werner
679d20cb52
Merge pull request #792 from fabro-sh/codex/sqlite-authorization-codes
Move pending CLI authorizations to SQLite
2026-08-25 11:46:10 -04:00
fabro-releases[bot]
e74f3c6c4b Bump version to 0.336.0-nightly.1 2026-08-25 13:26:02 +00:00
fabro-releases[bot]
7ae7ca9ead Bump version to 0.336.0-nightly.0 2026-08-25 09:31:30 +00:00
Scott Werner
05999036aa Move pending CLI authorizations to SQLite 2026-08-24 17:25:19 -04:00
Scott Werner
2d292c28f8
Merge pull request #783 from fabro-sh/codex/sqlite-blob-startup-activation
Activate verified SQLite blob storage at server startup
2026-08-24 16:32:59 -04:00
fabro-releases[bot]
330d0f8984 Bump version to 0.335.0-nightly.1 2026-08-24 18:48:34 +00:00
Scott Werner
e067de9382 Share one SQLite snapshot-staging helper between fabro-db and activation
create_backup re-implemented the staging half of fabro-db's
pre-migration snapshot (remove stale staging file, UTF-8 check,
VACUUM INTO, private permissions), and remove_file_if_exists and
set_private_permissions had been made pub precisely to hand-copy that
sequence. Any future hardening of snapshot staging would have had to
land in two crates and could drift.

fabro-db now exposes write_snapshot_to_staging with a typed
SnapshotStagingError; both the pre-migration snapshot and the
pre-activation backup stage through it, and the hand-copied helpers are
private again. The publish halves stay separate on purpose: migrations
overwrite their snapshot, activation publishes with persist_noclobber
plus integrity validation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 14:02:35 -04:00
fabro-releases[bot]
2bf86327c0 Bump version to 0.335.0-nightly.0 2026-08-24 09:36:45 +00:00
fabro-releases[bot]
7200d437e9 Bump version to 0.333.0-nightly.0
Some checks failed
Rust / Format (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Generated Docs (push) Has been cancelled
Rust / Test (Linux) (push) Has been cancelled
Rust / Test (macOS) (push) Has been cancelled
TypeScript / Typecheck (push) Has been cancelled
TypeScript / Test (push) Has been cancelled
TypeScript / Build (push) Has been cancelled
2026-08-22 04:04:57 +00:00
Bryan Helmkamp
3217a05aad
Merge origin/main into feat/venice-search-provider 2026-08-21 21:04:28 -04:00
Bryan Helmkamp
45e06d2a6e
Merge pull request #775 from fabro-sh/claude/additional-github-repositories
Additional GitHub repository access
2026-08-21 18:55:31 -04:00
Bryan Helmkamp
4c467cd6ba
refactor(github): simplify repository access checks 2026-08-21 17:12:27 -04:00
Bryan Helmkamp
438bab29f0
feat: support shallow sandbox clones 2026-08-21 17:11:24 -04:00
Jesse Proudman
53efde3930 feat(search): add Venice backend for web_search
Brave stays the default. Shops that already vault VENICE_API_KEY
can drop BRAVE_SEARCH_API_KEY by setting
[server.integrations.search] provider = "venice".

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-21 12:31:03 -07:00
fabro-releases[bot]
346e81f400 Bump version to 0.332.0-nightly.1 2026-08-21 11:40:10 +00:00
fabro-releases[bot]
f8879d13c4 Bump version to 0.332.0-nightly.0
Some checks are pending
Rust / Generated Docs (push) Waiting to run
Rust / Test (Linux) (push) Waiting to run
Rust / Test (macOS) (push) Waiting to run
TypeScript / Typecheck (push) Waiting to run
TypeScript / Test (push) Waiting to run
TypeScript / Build (push) Waiting to run
Rust / Format (push) Waiting to run
Rust / Clippy (push) Waiting to run
2026-08-21 02:31:24 +00:00
Bryan Helmkamp
579f3db26f
Add a cached GitHub installation-token source for push credentials
Every push previously re-minted a fresh GitHub App installation token and
embedded it in the origin URL, so pushes routinely landed inside GitHub's
token-replication lag window (run 01M0DH033P2XSTHAGVBHG6922F failed
terminally on four consecutive fresh-token 404s). Reusing mature tokens
removes the failure trigger and saves two GitHub API calls plus one sandbox
exec per push.

- New fabro_github::token_source::InstallationTokenSource: one cached,
  single-flight source per origin repo. Static credentials pass through
  (generation 0); App credentials mint through the cache and reuse tokens
  until REFRESH_MARGIN (10 min) before expiry. Every resolve returns a
  non-secret TokenSnapshot (generation + Minted/Reused/Static provenance),
  and the source logs mints at INFO and reuses at DEBUG.
- Docker and Daytona share the source through PushCredentialState: an embed
  mutex serializes compare -> set-url -> record, a matching generation skips
  the set-url exec, and the generation is recorded only after a successful
  exec. The clone still mints its own token, but now seeds the source cache
  (generation 1) and the last-embedded state, so a refresh mint failure
  falls back to the known embedded token instead of believing nothing was
  ever embedded.
- RefreshOutcome now reports the remote action (embedded/unchanged/none)
  separately from the token snapshot; git_push_via_exec logs token age and
  provenance with each push, and refresh failures log the last embedded
  generation.
- The run-metadata writer resolves through the sandbox's shared source
  instead of minting per snapshot (with its own cached source on resume).
- The ACP refresh-ahead loop reschedules from the embedded token's
  expires_at minus the margin instead of a fixed 45-minute interval, which
  a cached source would have broken for long turns; static credentials stop
  the loop.

Plan: .ai/plans/git-push-token-resilience.md (PR 1: items 3 and 6).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-20 09:33:43 -04:00
fabro-releases[bot]
03c3412e51 Bump version to 0.331.0-nightly.0 2026-08-20 09:26:14 +00:00
fabro-releases[bot]
519e456b28 Bump version to 0.330.0-nightly.0 2026-08-19 09:28:39 +00:00
fabro-releases[bot]
400be9f2dc Bump version to 0.329.0-nightly.0 2026-08-18 09:28:05 +00:00
fabro-releases[bot]
535e333970 Bump version to 0.325.0-nightly.0
Some checks failed
Rust / Format (push) Has been cancelled
Rust / Clippy (push) Has been cancelled
Rust / Generated Docs (push) Has been cancelled
Rust / Test (Linux) (push) Has been cancelled
Rust / Test (macOS) (push) Has been cancelled
2026-08-14 09:41:55 +00:00
Scott Werner
178320e7a5 Add immutable workflow version resource
Add the WorkflowVersion domain resource with exactly entrypoint, files,
and workflow_dependencies, plus strict WorkflowPath validation and
deterministic canonical raw JSON. Semantic validation of graph imports,
templates, file references, workflow.toml rules, Dockerfile paths, and
exact child-workflow dependency bindings lives in the new
fabro-workflow-version crate, which validates the complete stored
dependency closure through the shared blob store before writing a root.
The authenticated create-only POST /api/v1/workflow-versions endpoint
ships with its OpenAPI contract, Rust type replacements, and generated
TypeScript client.

Squashed from the resource commits of the original combined branch;
the walker unification this builds on landed separately.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-13 16:34:52 -04:00
fabro-releases[bot]
d5b3da87fc Bump version to 0.324.0-nightly.0 2026-08-13 09:41:35 +00:00