Commit graph

20 commits

Author SHA1 Message Date
Bryan Helmkamp
ecdfdd82d8
feat(install): add browser-based setup flow
Implement the web-first install experience across the server, CLI, API spec,
web app, and packaged SPA assets.

This also removes test-side process env mutation by pushing env-dependent
decision points behind explicit helpers and test wiring.
2026-04-19 11:20:58 -04:00
Bryan Helmkamp
0f029d6b02
feat(docker): switch runtime image to Alpine on musl
Now that the release workflow publishes musl binaries, the runtime
image can drop the debian:trixie-slim base for alpine:3.22. The
image shrinks from ~287 MB to ~96 MB (66% smaller) with a smaller
attack surface.

- Dockerfile: alpine:3.22 base, apk packages (ca-certificates git
  tini su-exec), BusyBox adduser/addgroup, tini at /sbin/tini.
- entrypoint.sh: replace runuser with su-exec, Alpine's idiomatic
  drop-privileges helper.
- release.yml docker job: pull the two linux-musl artifacts instead
  of linux-gnu. The docker image and the Alpine install.sh path now
  ship the same binary.
- bin/dev/docker-build.sh: compile fabro-cli for the host's musl
  target in rust:1-bookworm with musl-tools, the matching CC/LINKER
  env vars, and LIBZ_SYS_STATIC=1. Same pattern as CI.

Verified locally on aarch64: Alpine image builds, server binds on
$PORT (default 32276), endpoints return 200, fabro server process
runs as unprivileged UID 1000 under tini.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-18 02:10:18 -04:00
Bryan Helmkamp
a00abd8970
feat(docker): reorganize compose, add Caddy reverse proxy for prod
Move docker-compose.yaml to the repo root and add docker-compose.prod.yaml
that stands up a Caddy 2 sidecar on 80/443 proxying to the fabro service
on 32276 (the CLI's default port). Auto-HTTPS is handled by Caddy when
FABRO_DOMAIN is set; certs persist in named volumes.

Switch the container's internal listener from 80 to 32276, which lets us
drop libcap2-bin and the CAP_NET_BIND_SERVICE file capability.
2026-04-18 00:33:11 -04:00
Bryan Helmkamp
d52e6829c2
feat(docker): publish multi-arch server image to GHCR
Replace the docker/Dockerfile-based api+web compose setup with a
single root Dockerfile that runs the fabro server with the embedded
web UI on port 80, persists state under /storage, and drops to a
non-root fabro user with CAP_NET_BIND_SERVICE.

The release workflow stages the prebuilt Linux binaries from the
compile job into a buildx context and publishes multi-arch images
to ghcr.io/fabro-sh/fabro as :<version> (always), :latest (stable
tags only), and :nightly (nightly tags only).

Also address zizmor findings in nightly.yml (pinned
create-github-app-token, persist-credentials: false with explicit
remote URL setup) and release.yml (no-cache on tag-triggered
setup-bun to close the cache-poisoning path).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 19:39:10 -04:00
Bryan Helmkamp
51d764f6e3 Pin GHA action, Docker base images, and mintlify version
Addresses supply chain hardening items from #160:
- Pin taiki-e/install-action to commit SHA
- Pin rust:1-bookworm and oven/bun:1 to image digests
- Pin mintlify to 4.2.507

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-12 17:52:53 -04:00
Bryan Helmkamp
6d94f93e44 refactor(config): unify machine config as settings.toml
Consolidate CLI and server machine defaults under settings.toml,
including loader renames, writer preservation fixes, same-machine
manifest handling, and docs/test updates for the new config model.
2026-04-05 23:55:28 -04:00
Bryan Helmkamp
ddc57d458c Rename SessionConfig to SessionOptions and McpServerConfig to McpServerSettings
Aligns naming with the convention that "Config" is for file-level configuration
while "Options" and "Settings" describe runtime parameters. Also applies
rustfmt formatting fixes in web_auth.rs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 06:47:42 -07:00
brynary-fabro[bot]
a7faf32e01 Rename [feature_flags] to [features] (#11)
This PR renames the `[feature_flags]` configuration section to
`[features]` and the corresponding `FeatureFlags` type to `Features`
across the entire stack. The change touches the OpenAPI spec (source of
truth), Rust config/API crates, the generated TypeScript API client, the
web application, and the demo config file to ensure consistency.

On the Rust side, the `FeatureFlags` struct becomes `Features` in
`fabro-config`, and all field references (`config.feature_flags` →
`config.features`) are updated in `fabro-api` demo/test code along with
the relevant unit tests. On the TypeScript side, the generated client
reflects the OpenAPI rename (`feature-flags.ts` → `features.ts`,
`FeatureFlags` → `Features`), and manual edits in `fabro-web` update the
`AppConfig` interface, defaults constant (`FEATURES_DEFAULTS`), loader
data destructuring, and template usage throughout `config.server.ts`,
`app-shell.tsx`, and `start.tsx`.

The regeneration also picked up an unrelated new `GitHubConfiguration`
schema that was already present in the OpenAPI spec but hadn't been
generated yet, resulting in the new `git-hub-configuration.ts` file and
its addition to the server configuration type.

### Fabro Details

<details>
<summary>Ran 7 stages in 15m 4s for $3.08</summary>

| Stage | Duration | Cost | Retries |
|---|---|---|---|
| start | 0s | – | 0 |
| toolchain | 0s | – | 0 |
| preflight_compile | 0s | – | 0 |
| preflight_lint | 0s | – | 0 |
| implement | 0s | $2.18 | 0 |
| simplify | 0s | $0.90 | 0 |
| verify | 0s | – | 0 |
| **Total** | **15m 4s** | **$3.08** | **0** |

</details>

<details>
<summary>Ran <code>ImplementAndSimplify.fabro</code> (10 nodes and 13
edges)</summary>

```dot
digraph ImplementAndSimplify {
    graph [
        goal="Implement and simplify",
        model_stylesheet="
            * { backend: api; model: claude-opus-4-6;}
        "
    ]
    rankdir=LR

    start [shape=Mdiamond, label="Start"]
    exit  [shape=Msquare, label="Exit"]

    toolchain         [label="Toolchain", shape=parallelogram, script="command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1", max_retries=0]
    preflight_compile [label="Preflight Compile", shape=parallelogram, script="cargo check 2>&1", max_retries=0]
    preflight_lint    [label="Preflight Lint", shape=parallelogram, script="cargo clippy -- -D warnings 2>&1", max_retries=0]
    fix_lints         [label="Fix Lints", prompt="The preflight lint step failed. Read the build output from context and fix all clippy lint warnings.", max_visits=3]
    implement         [label="Implement", prompt="Read the plan file referenced in the goal and implement every step. Make all the code changes described in the plan."]
    simplify          [label="Simplify", prompt="@prompts/simplify.md"]
    verify            [label="Verify", shape=parallelogram, script="cargo clippy -- -D warnings 2>&1 && cargo test 2>&1", goal_gate=true, retry_target="fixup"]
    fixup             [label="Fixup", prompt="The verify step failed. Read the build output from context and fix all clippy lint warnings and test failures.", max_visits=3]

    start -> toolchain
    toolchain -> preflight_compile [condition="outcome=success"]
    toolchain -> exit
    preflight_compile -> preflight_lint [condition="outcome=success"]
    preflight_compile -> exit
    preflight_lint -> implement [condition="outcome=success"]
    preflight_lint -> fix_lints
    fix_lints -> preflight_lint
    implement -> simplify -> verify
    verify -> exit  [condition="outcome=success"]
    verify -> fixup
    fixup -> verify
}

```

</details>

⚒️ Generated with [Fabro](https://fabro.sh)

---------

Co-authored-by: Fabro <noreply@fabro.sh>
Co-authored-by: Bryan Helmkamp <bryan@brynary.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 19:54:40 -04:00
Bryan Helmkamp
28884ae093 rename Arc to Fabro in all Rust crates, symbols, env vars, and supporting files
- Rename 20 crate directories lib/crates/arc-* → fabro-*
- Update all Cargo.toml: crate names, dep paths, feature flags, bin name
- Rename arc_server module → fabro_server in fabro-llm
- ArcError → FabroError across 30+ files
- ARC_VERSION/ARC_GIT_SHA/ARC_BUILD_DATE → FABRO_* constants
- All use/qualified paths: arc_agent:: → fabro_agent::, etc. (~1500 occurrences)
- Env vars ARC_* → FABRO_* in string literals and shell scripts
- String literals: X-Arc-Demo, arc-bot, arc@local, arc-web, arc-mcp, etc.
- Path strings: .arc/ → .fabro/, arc.toml → fabro.toml, refs/arc/ → refs/fabro/
- arc-api.yaml → fabro-api.yaml (OpenAPI spec)
- skills/arc-create-workflow → fabro-create-workflow
- trycmd fixtures: $ arc → $ fabro
- Inline snapshots (insta) updated
- CI, Docker, install.sh, scripts, CLAUDE.md, AGENTS.md
- TypeScript app: env vars, headers, JWT issuer
- Docs: page slugs, git refs, config paths, sandbox names, repo URLs
- Repo references: brynary/arc → fabro-sh/fabro

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 12:25:58 -04:00
Bryan Helmkamp
3a6ec9b9ef Rename Arc to Fabro in TypeScript/JavaScript
Rename directories (arc-web → fabro-web, arc-api-client → fabro-api-client),
update package names, import paths, TS-only identifiers (theme key, session
cookie, demo cookie, OAuth state, db filename, mock data), and supporting
files (Dockerfile, docker-compose, entrypoint, CI workflow, CLAUDE.md).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:13:18 -04:00
Bryan Helmkamp
f6554ca689 Add web UI screenshots to docs, update branding to Fabro, simplify Quick Start
- Add 10 screenshots of the Fabro web UI to docs pages (workflows, runs,
  retros, observability, steering)
- Update arc-web logos from Arc to Fabro (logotype.svg, logotype-light.svg)
- Hide Start and Settings nav items in arc-web for cleaner screenshots
- Mount arc-web public/ as Docker volume for logo hot-swapping
- Combine "Run agents 24/7" and "Scale infinitely" use cases
- Replace clone-and-build Quick Start with curl installer from README
- Add internal docs for updating web screenshots

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 09:08:51 -04:00
Bryan Helmkamp
c2b40b4cfc Move packages/ to lib/packages/ and update all references
Updated: package.json workspaces, tsconfig path alias, CI workflow
paths, Dockerfile COPY, AGENTS.md, and doc references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:13:56 -04:00
Bryan Helmkamp
9e3b73dbe4 Move crates/ to lib/crates/ and update all references
Updated: Cargo.toml workspace members, CI workflow paths, Dockerfile
COPY, AGENTS.md, skill mapping, and doc references.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:12:35 -04:00
Bryan Helmkamp
743786e741 Move Dockerfile, docker-compose.yaml, and entrypoint.ts into docker/
Update build context, dockerfile path, and volume mounts in
docker-compose.yaml to account for the new location.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:09:54 -04:00
Bryan Helmkamp
314ee9be99 Add checkpoint exclude globs to skip bulky artifacts from git checkpoint commits
Introduces a [checkpoint] config table with exclude_globs in both run.toml
(per-run) and server.toml (defaults). Globs are merged (union + dedup) when
both are present. Non-empty excludes use git pathspec :(glob,exclude) syntax
to prevent staging matching files during checkpoint commits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 12:25:27 -05:00
Bryan Helmkamp
3fe77b6d5f Add session_sandboxes feature flag to gate project/branch pickers
Add a FeatureFlags config section with a session_sandboxes boolean
(default false) to both the Rust server config and web app config.
Gate the project/branch picker UI behind this flag. Set it to false
in the Docker demo config.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 07:34:32 -05:00
Bryan Helmkamp
d0c7ac342e Remove unused per-service Dockerfiles
These are superseded by the unified root Dockerfile with entrypoint router.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 00:34:03 -05:00
Bryan Helmkamp
129b8b98c4 Add Docker Compose demo setup for local development
Multi-stage Dockerfile builds Rust API binary and bundles the web app
and docs into a single image. docker-compose.demo.yaml orchestrates
the three services (api, web, docs) with a shared entrypoint router.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 00:32:48 -05:00
Bryan Helmkamp
e0f33e072e Fix Dockerfile.agent to use apt ripgrep for multi-arch support
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:31:19 -05:00
Bryan Helmkamp
60dad3c1cd Add DockerExecutionEnvironment for sandboxed agent tool execution
Implements ExecutionEnvironment trait backed by Docker containers via
bollard. Host working directory is bind-mounted; all file ops, commands,
grep, and glob execute inside the container via docker exec. Extracts
shared format_lines_numbered() helper from LocalExecutionEnvironment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:29:38 -05:00