Commit graph

69 commits

Author SHA1 Message Date
Bryan Helmkamp
6fc7251471
close config boundary audit and settings snapshot naming 2026-04-23 19:30:30 -04:00
Bryan Helmkamp
44296f233e
plan 2026-04-23 11:02:26 -04:00
Bryan Helmkamp
e210fe9fed
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-cli/src/command_context.rs
#	lib/crates/fabro-cli/src/main.rs
2026-04-23 08:56:40 -04:00
Bryan Helmkamp
a770eb8e12
Merge remote-tracking branch 'origin/main' 2026-04-23 08:52:44 -04:00
Bryan Helmkamp
da9453cbd1
refactor(config): move settings combine into types 2026-04-23 08:42:19 -04:00
Bryan Helmkamp
4ad4d8fd36
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-cli/src/commands/dump.rs
#	lib/crates/fabro-cli/src/commands/store/mod.rs
#	lib/crates/fabro-cli/src/main.rs
2026-04-23 08:42:16 -04:00
Bryan Helmkamp
7f96069345
docs 2026-04-23 08:35:43 -04:00
Bryan Helmkamp
f5758d99d0
refactor(config): collapse settings resolver 2026-04-23 08:00:56 -04:00
Bryan Helmkamp
5041669d6d
plans 2026-04-23 07:45:26 -04:00
Bryan Helmkamp
fbe0bdfbc1
refactor: align cli command boundaries on CommandContext 2026-04-23 01:08:14 -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
10a9038dcc
plan 2026-04-22 17:20:35 -04:00
Bryan Helmkamp
28a1a01a41
plan 2026-04-22 10:31:10 -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
0d2be41e57
Merge remote-tracking branch 'origin/main' 2026-04-21 08:38:37 -04:00
Bryan Helmkamp
bf1aa6eed5
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-store/src/lib.rs
#	lib/crates/fabro-store/src/slate/mod.rs
#	lib/crates/fabro-store/src/slate/run_store.rs
2026-04-21 08:35:07 -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
705dccdea7
Merge remote-tracking branch 'origin/main'
# Conflicts:
#	lib/crates/fabro-store/src/lib.rs
#	lib/crates/fabro-store/src/run_state.rs
2026-04-21 07:53:10 -04:00
Bryan Helmkamp
7dd058cc40
refactor: unify run vocabulary and metadata snapshot layout
Implements the plan at
docs/plans/2026-04-20-003-refactor-unify-run-vocabulary-metadata-plan.md.

- Rename RunRecord to RunSpec and RunProjection.run to .spec everywhere
  in Rust source, tests, helpers, test names, and error messages.
- Introduce SerializableProjection wrapper that trims bulky node text
  fields (prompt, response, diff, stdout, stderr) for run.json snapshots.
- Collapse metadata-branch and CLI export to one RunDump::from_projection
  builder emitting run.json + graph.fabro + stages/{stage_id}/... and
  drop legacy top-level start/status/checkpoint/sandbox/retro/conclusion
  split files.
- Replace MetadataStore::write_checkpoint with write_snapshot returning
  the commit SHA; add read_run_projection/read_run_spec; demote
  read_checkpoint/read_start_record to projection-field extractors.
- Switch fork, rewind, rebuild_meta, CLI rewind recovery, and retro
  upload to read the unified projection layout.
- Add additive query methods on RunSpec and RunProjection.

Serde-level `alias = "spec"` shim dropped; `rename = "run"` retained to
keep the server API wire format stable per the plan's scope boundary.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 22:17:23 -04:00
Bryan Helmkamp
f0f04abf44
refactor(client): extract fabro-client crate
Lift shared client DTOs into fabro-types, move auth/target/error/session
logic into fabro-client, and reduce fabro-cli to orchestration around the
builder-based client path.

This also lands the remaining plan cleanup for ApiError, ServerTarget
canonicalization, and the RunEventStream rename at the CLI boundary.
2026-04-20 20:42:20 -04:00
Bryan Helmkamp
90b911c927
docs(plan): clarify unknown-event handling in client extraction
Document that unknown Fabro run events already fall back through
EventBody::Unknown, and that the refactor only needs to preserve
that behavior during the EventEnvelope move.
2026-04-20 18:26:46 -04:00
Bryan Helmkamp
381a186557
docs(plan): add fabro-client extraction plan
Capture the technical plan for extracting a new fabro-client crate from
fabro-cli, lifting domain DTOs (RunSummary, EventEnvelope, RunProjection,
ArtifactUpload) to fabro-types, and applying a set of OOP-style naming
cleanups along the way. Ran through ce-plan deepening and document-review
with feedback integrated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 17:37:31 -04:00
Bryan Helmkamp
41135dd9d1
fix(cli): remove explicit remote same-host auth fallbacks 2026-04-20 14:17:01 -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
Bryan Helmkamp
8259b7445e
feat(web): add run lifecycle actions
Expose cancel, archive, and unarchive from the run detail view,
surface blocked-question context, and route run-detail and run-files
notifications through a single shared toast provider.

This also refreshes the embedded SPA bundle and marks the lifecycle
actions plan complete.
2026-04-20 08:43:30 -04:00
Bryan Helmkamp
9b1f08f0d4
docs(plan): ratify SHA-256 for user_agent_fingerprint
SHA-256 is already a workspace dep and is what the implementation uses at
server_client.rs:792-795. Avoids adding blake3 as a new dep for a use where
the algorithms are equivalent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 08:26:13 -04:00
Bryan Helmkamp
be74f91b7a
plans 2026-04-20 08:14:53 -04:00
Bryan Helmkamp
a62d06da4c
docs(plan): revert invented multi-node constraint; fabro-server is single-node
Reverts the `single_node_ack` acknowledgment flag and all the cross-node /
multi-node qualifier text introduced in the previous two commits. fabro-server
is single-node by design; there is no multi-node deployment model to design
against. The in-process per-hash and per-code mutexes in Units 9 and 10
provide the full atomicity guarantees R3 requires. R12 restored to the
original web-enabled + SESSION_SECRET-length check. No ack flag, no
config-surface EULA, no cross-node tests, no multi-node risks-table row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 19:51:19 -04:00
Bryan Helmkamp
83d712db24
docs(plan): enforce v1 single-node constraint via required acknowledgment flag
Adds `server.auth.github.single_node_ack: bool` (default `false`) as a new
config field required by startup validation when `github` is in
`auth.methods`. Without the flag, the server refuses to boot. This turns the
previously documentation-only single-node constraint into a fail-closed
startup check — an operator can still misdeploy to multi-node after setting
the flag, but they must affirmatively acknowledge the tradeoff first.

Alternative (auto-detect via SlateDB boot-heartbeat) deferred as future
work; explicit acknowledgment is lower-complexity and avoids rolling-deploy
false positives. Enforcement lives in Unit 5 startup validation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 19:51:19 -04:00
Bryan Helmkamp
e08e0163f8
docs(plan): add CLI auth login (GitHub OAuth + JWT) implementation plan
Adds a 22-unit implementation plan for `fabro auth login`/`logout`/`status`
with GitHub OAuth + PKCE, HS256 JWT access tokens, rotating opaque refresh
tokens, and a typed `IdpIdentity` flowing across fabro-types / fabro-store /
fabro-server. v1 is scoped to single-node deployments with `github` in
`auth.methods` (distributed refresh-token rotation coordination is deferred).

Origin spec: docs/superpowers/specs/2026-04-19-cli-auth-login-design.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 19:51:19 -04:00
Bryan Helmkamp
1f6eb5b336
Merge origin/main into Run Files Changed feature branch
Integrates 39 commits from origin/main (archive/unarchive feature, UI
unification, theme/light-mode polish, Settings nav promotion, server
and CLI hardening).

Conflict resolutions:

- apps/fabro-web/app/routes/run-detail.tsx: origin removed the
  `broken` field from the tab config; local added the Files Changed
  tab. Kept the Files Changed tab, dropped the broken field per
  origin's shape.
- lib/crates/fabro-store/src/run_state.rs: both sides added tests
  in the same region. Kept local's two final_patch tests and all
  four of origin's archive/unarchive tests.
- lib/crates/fabro-spa/assets/: embedded SPA bundle rebuilt from
  the merged web source.
- lib/crates/fabro-workflow/src/operations/archive.rs: origin's new
  archive tests construct Event::WorkflowRunFailed{..}; added the
  final_patch: None field that local's lifecycle change introduced.

Workspace verification after merge: 4247 Rust tests + 95 web tests
all pass; clippy clean; fmt clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 19:30:36 -04:00
Bryan Helmkamp
46813e3b05
docs(plan): mark Run Files tab plan completed
All 13 units shipped. Follow-ups noted inline: globset-based denylist
extraction and Virtualizer wrapping for very large runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 17:13:40 -04:00
Bryan Helmkamp
b589b581ff
docs(plan): mark Run Files tab plan partially completed
Captures what landed in this session (Units 1-10, 13) vs what's
deferred (Units 11-12) so follow-up work can pick up from a clean
baseline.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 17:06:44 -04:00
Bryan Helmkamp
bdf645a774
docs: changelog entry and plan status=completed for archived runs 2026-04-19 16:59:46 -04:00
Bryan Helmkamp
b849738a5b
plans 2026-04-19 15:18:25 -04:00
Bryan Helmkamp
a1c816724b
plans 2026-04-19 15:18:21 -04:00
Bryan Helmkamp
dae8b635fc
plans 2026-04-18 12:36:41 -04:00
Bryan Helmkamp
bc3dcf3505
plan 2026-04-18 10:51:43 -04:00
Bryan Helmkamp
c24b78d18d
plans 2026-04-16 07:43:01 -04:00
Bryan Helmkamp
4a3549e8da docs(plans): commit stage 6 handoff 2 (previously untracked)
This doc was written at the end of the session that landed Stages
6.1-6.5 but never committed; it's been sitting untracked for three
follow-up sessions. Handoff docs 3 and 4 both point at it as their
predecessor, so it belongs in the tree alongside them.

No content change; the file is committed as originally written.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 18:51:44 -04:00
Bryan Helmkamp
0930c38602 docs(plans): write Stage 6 wrap-up handoff — all substages complete
Captures the full end-state after this session finished the
consumer-migration pass through 6.3b, flattened the v2 directory
(6.5b), rewrote the auth resolver (6.6g), and closed out the last
scoped TODOs from handoff-2.

Nothing left in Stage 6. Next work is either from the deferred list
(setup_register toml_edit upgrade, ModelRegistry for fallback
chains, goal_file schema decision, fail-closed server posture,
centralized env interp pass, optional OpenAPI formalization) or
driven by new requirements.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 18:44:13 -04:00
Bryan Helmkamp
edd5a27a36 docs(plans): write stage 6.6 + 6.3b-partial handoff
Captures what landed in this session:

- Stage 6.6a/b/c: OpenAPI DTO collapse (commit 78c57d585)
- Stage 6.6d/e/f/i: Server handlers + CLI + demo migration (40c9aae29)
- Stage 6.6h: fabro-web literal rewrite (999f2a11c)
- Stage 6.3b first pass: delete fabro_types::Settings (fb04e1732)

Plus what still remains:

- Stage 6.3b runtime type module cleanup (blocked on consumer migration)
- Stage 6.5b directory flatten (blocked on 6.3b)
- Stage 6.6g auth resolver rewrite
- Stage 6.6j setup_register review
- 5 of 12 scoped TODOs still open; 7 resolved

Also records the consumer migration map — ~33 import sites across
8 crates that need individual per-crate migration. This is the bulk
of the remaining Stage 6 work.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 17:35:23 -04:00
Bryan Helmkamp
41ab919959 feat(settings): stage 6.1 consumer migration builds workspace-wide
Extends the stage 6.1 WIP into a compiling state across the workspace.
Most crates and their unit/integration tests now read run.* / cli.* /
server.* v2 layers directly or through targeted bridge helpers.

Key moves in this commit:

fabro-server
- AppState.settings: Arc<RwLock<SettingsFile>> -- all helpers,
  create_app_state_with_* factories, and tests updated.
- api_server_settings bridges SettingsFile -> legacy Settings via the
  transitional bridge so /api/v1/settings still emits the legacy DTO
  shape until Stage 6.6 replaces it with an allow-list DTO.
- get_system_info, get_system_df, get_github_repo, webhook startup, and
  other read sites use the v2 accessors (github_app_id_str,
  server_web, run_sandbox, run_model_*).
- web_auth.rs wraps each oauth / register / setup-status handler in a
  local `bridged` helper that produces a legacy Settings from the v2
  state, so the complex oauth mutation flow keeps working until its
  Stage 6.6 rewrite.
- diagnostics::check_github_app reads via github_*_str accessors;
  check_crypto bridges to the legacy shape inline.
- serve.rs: load_settings returns SettingsFile; apply_serve_overrides /
  apply_runtime_settings mutate v2 subtrees directly; the config poll
  loop and TLS/webhook startup use bridged() for legacy-shape reads.
- Tests in tests/it/{helpers,api/*,scenario/*} rewritten to construct
  SettingsFile via ConfigLayer::parse or v2 struct literals.

fabro-workflow
- Every test fixture in pipeline/{finalize,initialize,pull_request,retro,
  execute,persist}, operations/{create,rebuild_meta,start}, run_lookup,
  runtime_store, handler/manager_loop, and tests/it/{integration,
  daytona_integration}.rs now uses SettingsFile.
- start.rs hooks into the bridge helpers directly via use-imports.
- run_graph / run_graph_from_checkpoint / initialize / finalize /
  pull_request calls are Box::pin'd to stay under clippy's large-future
  threshold after the v2 tree brought RunOptions size up.
- resolve_run_settings writes resolved model/provider back into
  run.model as InterpStrings; tests assert via run_model_*_str().
- preprocess_and_validate pulls vars from run_inputs_as_strings().

fabro-cli
- manifest_builder uses ConfigLayer.combine(...).into() to get a v2
  SettingsFile for the manifest goal resolution path; file-based
  goal_file handling is deferred to 6.6 when the manifest schema catches
  up.
- runner::maybe_build_github_app_credentials and
  tests/it/cmd/{create,runner}.rs read from v2 accessors.
- commands/config/mod.rs::merged_config returns SettingsFile; the
  server-side retrieve_server_settings is bridged via a stopgap
  legacy_settings_to_v2 shim that Stage 6.6 replaces.
- commands/store/dump.rs sample_run_record constructs SettingsFile.

fabro-store, fabro-checkpoint
- Test fixtures constructing RunRecord values updated to SettingsFile.
- fabro-checkpoint/src/author.rs stays (v2 From impl landed in a
  previous additive commit).

fabro-config
- effective_settings.rs rewrite compiles and passes its unit tests.
- project::resolve_working_directory takes &SettingsFile.

Build status: `cargo build --workspace --tests`, `cargo clippy
--workspace -- -D warnings`, and `cargo fmt --check --all` all pass.
`cargo nextest run --workspace` passes 3,749 of 3,764 tests; the 15
remaining failures are fabro-cli integration tests whose snapshot +
TOML fixture shapes still need manual updates:

- cmd::config::* (seven tests): fixture TOML files still use v1
  top-level keys and the snapshot outputs expect the legacy flat JSON
  shape.
- cmd::inspect::* (four tests): run-record JSON snapshots embed the
  flat Settings shape.
- cmd::run::dry_run_persists_event_history_in_store and
  json_run_implies_auto_approve_for_human_gates: check `settings.dry_run
  == Some(true)` directly on the v2 file; should assert
  dry_run_enabled() instead.
- cmd::attach::attach_json_errors_without_prompting_for_human_input:
  unrelated insta snapshot drift caused by the new SettingsFile JSON
  shape leaking into an events-log snapshot.

Follow-up work for this stage also includes:
- Rewriting web_auth.rs register flow to emit v2 TOML directly and to
  re-parse the written file back into state.settings so in-memory
  state doesn't lag the on-disk file.
- Removing the legacy_settings_to_v2 shim in fabro-cli/config once
  the server-side settings endpoint returns v2 shapes (Stage 6.6).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:25:59 -04:00
Bryan Helmkamp
57d0132273 docs(plans): write Stage 6 handoff for settings TOML redesign
Comprehensive handoff document that the engineer picking up the
settings redesign can use to continue the work. Captures:

- TL;DR of what's landed vs what remains
- Source document references (brainstorm, plan, canonical example)
- Current-state tree map with file-level annotations
- Full dependency chain from TOML -> v2 -> bridge -> consumers
- Commit log for Stages 1-5 (13 commits, 76 files, +6413/-2151)
- Stage 6 broken into six independent subtasks: consumer migration,
  bridge deletion, legacy type deletion, fabro-config shim deletion,
  v2 namespace flattening, OpenAPI + clients + fabro-web rewrite
- Concrete before/after migration patterns with InterpString examples
- Testing gotchas I hit during Stages 1-5: fabro-cli parallel test
  daemon FD limit, insta snapshot pending review, hook shorthand vs
  #[serde(flatten)] duplicate-command collision, fabro-test managed
  marker detection, apply_server_defaults full-shape propagation,
  user layer trust boundary, pre-existing fabro-interview test clippy
  warnings
- Open design questions the next engineer needs to decide: ConfigLayer
  resolve naming, post-layering interpolation pass, fail-closed auth,
  ModelRegistry runtime wiring, run.scm provider depth, serde flatten+
  HashMap+deny_unknown_fields constraint
- Verification recipes (full gate, legacy key sanity grep, bridge
  caller sanity grep)
- Explicit success criteria for Stage 6 completion
2026-04-09 11:54:44 -04:00
Bryan Helmkamp
166b60e3b1 feat(cli): add fabro uninstall command
Adds a top-level `fabro uninstall` command that reverses `fabro install`
and `install.sh`. Defaults to dry-run (preview) mode, requiring `--yes`
to execute.

Features:
- Inventory and dry-run preview with sizes and `--json` support
- Server shutdown (guarded — only when server is running)
- Safety guardrails (refuses to delete /, $HOME, or dirs without markers)
- Shell config cleanup (exact `# fabro` sentinel match, PATH validation,
  atomic write via temp+rename)
- Binary status reporting with tailored brew/cargo/manual hints
- Exit code: 0 on success, 1 on critical failure

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 16:31:32 -04:00
Bryan Helmkamp
30e63b270f Merge remote-tracking branch 'origin/main' 2026-04-08 16:30:26 -04:00
Bryan Helmkamp
911831fc23 plan 2026-04-08 16:24:11 -04:00
Bryan Helmkamp
708473e2be docs(plan): add optional web ui server plan 2026-04-08 16:09:42 -04:00
Bryan Helmkamp
f7d86d72e2 Merge remote-tracking branch 'origin/main' into production-web-ui 2026-04-08 14:44:35 -04:00