After StubEnv was removed, the EnvSource trait had only two impls
(ProcessEnv unit struct and a blanket HashMap impl) and tests already
passed HashMaps. Replace the trait with a free `process_env_snapshot()`
function and take `HashMap<String, String>` by value in
`ServerSecrets::load` and the startup validators.
Also flatten `StartupResolution` to a `(AuthMode, ServerSecrets)` tuple
and drop the `StartupValidationError` wrapper in favor of
`anyhow::Result`, and inline the `*_with_lookup` test-only wrappers in
`spawn_env.rs` so tests call `apply_allowlist` directly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
StubEnv was a thin newtype only used by tests but compiled into every
build. Implementing EnvSource directly on HashMap<String, String> lets
test sites pass a HashMap and removes the type entirely.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clean up clippy -D warnings violations that slipped through in 4bf0c4031:
- envfile.rs: extend the existing module-level #![expect] to also cover clippy::disallowed_types so the intentional std::io::Write usage stops tripping the workspace lint.
- install.rs: import ServerSecrets and EnvFileUpdate at the top and drop the fully-qualified call sites (unused_qualifications); collapse the nested if-let around the post-finish manual-credentials cleanup (collapsible_match); gate the test's std::fs::write with #[expect(clippy::disallowed_methods, reason="...")].
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Derive strum::IntoStaticStr on InstallObjectStoreProvider/CredentialMode and use it in as_session_value instead of a hand-written match.
- Split resolve_install_object_store_state: extract resolve_s3_manual_credentials and fold the redundant outer "missing credentials" guard into its (None, None) arm.
- Replace the per-endpoint installFetch boilerplate with installRequest / installJsonRequest<T> so each install-api wrapper is a single call.
- Extract runStepSubmit inside InstallApp; the LLM, server, object-store, and GitHub step handlers now share the setSubmitting / try / refresh-session / navigate / finally scaffolding.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Derive install stepper's current step from INSTALL_STEPS instead of a hand-maintained pathname if-chain.
- Replace four near-identical picker components with one generic CardPicker plus per-flow option arrays.
- Extract repeated object-store validation error strings into constants and a small helper.
- Run the S3 artifacts/ and slatedb/ prefix probes concurrently via tokio::try_join!.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace hand-written Display/FromStr/as_str boilerplate with strum
derives on Provider, RunStatus, StatusReason, Speed, ReasoningEffort,
SandboxProvider, Fidelity, ModelTestMode, ModelTestStatus. Update a few
downstream callers whose FromStr::Err = String assumption no longer
holds. Net -172 lines, zero wire-format change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`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>
Collapses the identical scopeguard + serve_command block in
`start.rs::execute_foreground` into a single `foreground::serve_with_daemon_record`
helper shared with `server::dispatch`.
Changes `prepare_foreground_server_log`, `acquire_lock`, and
`load_or_create_local_session_secret` to take `&RuntimeDirectory` instead
of `&Path storage_dir`, since each only consumed the path to immediately
rebuild a `RuntimeDirectory`. Callers that still need the raw storage
path for child processes keep it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deduplicates the `match bind { Unix(p) => p.to_string_lossy(), Tcp(a) => format!("http://{a}") }`
formatting shared between `worker_command` and the `server_target` test helper
by moving it onto `Bind` itself. Also surfaces unexpected errors from
`ServerDaemon::remove` via `tracing::warn!` instead of silently discarding
them, while still short-circuiting the common `NotFound` path.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace hand-rolled `format!("{}@{}", node_id_segment.display(), stage_id.visit())`
with `stage_id.to_string()`, matching the pattern already used for the
stages directory at line 61. `StageId`'s Display impl already produces
`{node_id}@{visit}`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The local ensure_test_auth_methods helper in server.rs is reachable from
the pub fn create_app_state_with_store chain, which is compiled in
release builds even though only integration tests call it. After
2cb623561, the helper called SettingsLayer::ensure_test_auth_methods()
— which is gated behind #[cfg(any(test, feature = "test-support"))] —
so cargo build --release broke with E0599.
Inline the auth-methods setup locally. This one helper only needs the
ServerAuthMethod::DevToken default; it doesn't share the "new required
SettingsLayer field" concern that motivated the centralization.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Unauthenticated commands surfaced only `error: Authentication required.`
with no remediation. Add a cyan-bold `hint:` line pointing at
`fabro auth login` in the top-level error printer, keyed off
`ExitClass::AuthRequired` so it covers every command that hits the
server (run, exec, ps, system info, etc.). Suppressed when `--json` is
set.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The assets committed in 537a5125c drifted from what bun 1.3.13 produces
for the current TS source, which broke the nightly release verifier.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Settings::default() and ServerSettings::default() returned values that the
strict resolver rejects (empty server.auth.methods). The Default derives were
load-bearing only for tests that wanted "some" Settings to serialize or
destructure -- production code that wants real settings already goes through
fabro_config::resolve.
Replace with explicit test_default() constructors behind the test-support
feature, gated by cfg(any(test, feature = "test-support")). The compiler now
catches any production "I just need an empty one" site, and the test-only
constructors carry doc comments warning that they don't satisfy resolver
invariants.
The only callers were three sites in fabro-types' own resolved.rs tests;
both Default derives had no other users in the workspace.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add SettingsLayer::test_default() and SettingsLayer::ensure_test_auth_methods()
to fabro-types behind a "test-support" feature, then collapse the five
near-identical ensure_fixture_auth_methods/default_settings/test_default_settings
helpers that the dev-token gating cleanup spread across fabro-config,
fabro-server, and fabro-workflow.
Why: the next required SettingsLayer field would otherwise need updating in
five places. With the canonical helper in fabro-types, adding a required field
becomes a one-line change.
The cfg(any(test, feature = "test-support")) gate keeps the helpers out of
production builds. Consumer crates enable the feature via dev-dependencies.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The dev-token gating commit added ensure_home_server_auth_methods only to
run_cmd/create_cmd helpers, but many integration tests use context.command()
directly to invoke run/start/attach/etc. Patch the offenders rather than
hoisting auth-injection into command() itself, since command() is also used
by tests (e.g. uninstall) that explicitly want a stable settings file.
- attach, start, scenario lifecycle/recovery, json_global graph: call
context.ensure_home_server_auth_methods() up front
- validate(): hoist into the helper itself, since every validate test
needs it
- server_status, uninstall legacy-record tests: bake methods=["dev-token"]
into their hand-written settings.toml fixtures and pass FABRO_DEV_TOKEN
via env so the spawned server actually boots
- install: write_artifact_store_metadata_creates_marker test fixture also
needs explicit methods after the resolver became strict
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After removing the implicit [server.auth] dev-token default, several unit
tests still passed empty SettingsLayer values into paths that resolve
server settings, so they panicked with "server.auth.methods: field is
required". Restore them by injecting dev-token methods in test fixtures
(consistent with the existing fabro-config resolve_server test pattern),
and rescue create_test_app_state_with_session_key, which bypassed the
existing ensure_test_auth_methods helper.
Clippy clean-ups unblock `cargo clippy --workspace -- -D warnings`:
- fabro-config: bring SettingsLayer into scope, flatten single-arm match
- fabro-cli: gate storage_dir unit tests with allow(deprecated), drop
unnecessary borrow, scope effective_settings imports, drop needless
raw-string hashes
- fabro-server: replace Option<Option<String>> test helper with an
EnvOverride enum, widen test unwrap → expect
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`--local` is supposed to render the settings that apply to the local CLI
/ client side, so it has no business resolving server settings. Drop the
server section and the warning path, return only project/workflow/run/
cli/features. Removes the boundary violation that was about to break the
CI boundary check, and restores the legacy_*_silently_ignored tests to
their original silent assertion.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add FABRO_SUPPRESS_OPEN_BROWSER env knob via fabro_util::browser::try_open.
apply_test_isolation now sets it, so install-mode and auth-login tests that
spawn a real fabro binary no longer pop real browser windows. All six
open::that call sites route through the helper; consolidates the direct
open crate dep into fabro-util.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Conflict resolved in fabro-client tests: union both import sets so the
new auth-required classification tests (httpmock-based) and our positive
plain-HTTP refresh test (raw TCP responder) coexist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Route install/uninstall through local_server::storage_dir instead of hand-
rolled copies, drop dead connect_api_client and run_dir plumbing, eliminate
double-resolve in prepare_server_bootstrap, and tighten the boundary
allowlist now that uninstall no longer needs the exemption.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Inline the validate_canonical_origin wrapper, move reload-failure logging
to the single caller with accurate wording, drop a hand-rolled tracing
capture layer from tests, and migrate web_auth OAuth handlers to
state.canonical_origin() so the is_empty/resolve guards fall out.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Simplifies three spots surfaced by a code-reuse pass: use
console::strip_ansi_codes in fatal_error_line, use provider_kind()
instead of re-pattern-matching the LLM error shape in
classify_server_agent_auth, and drop an unused const on Classified::class.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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>
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>
Returns exit code 4 whenever the CLI fails because the user needs to run
fabro auth login, so scripts and the install wizard can distinguish
re-auth from generic failures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>