Bedrock first-startup login: SSO auth, keyring credentials, explicit provider activation - #7
Merged
Merged
Conversation
…xplicit provider activation Adds a Bedrock agent backend authenticated via AWS SSO device-authorization flow (src/aws_sso.rs), with role credentials exchanged fresh on every call through a `gitzi creds-helper aws` credential_process helper and the SSO access token cached in the OS keyring. Provider config (src/config.rs) gains a `kind` discriminator and Bedrock-specific fields, plus an `enabled` flag so discovered providers stay inert until explicitly turned on. Rewrites bootstrap.rs's first-run discovery to be purely informational — it records every found provider (LM Studio, Ollama, Bedrock/SSO sessions) disabled and never auto-wires, starts, or logs into anything, so onboarding can no longer get stuck. The main agent gets two new chat tools, gitzi_rediscover_providers and gitzi_activate_provider, to re-scan and then walk the user through turning a provider on (including the multi-step SSO account/role selection for Bedrock) without blocking the TUI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016D4d2Y4sEXsFwnTr4VRsuY
…shapes Column::Testing/TestBuffer, AgentRole::Tester, and Stage::Testing/TestBuffer/ InTesting were removed upstream (a9f0fd4) without updating the 16 integration test files that referenced them, breaking CI. Also fixes tests/e2e_pipeline.rs, which predated later ProviderDef field additions and the Task.repo parameter on gitzi_create_task. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016D4d2Y4sEXsFwnTr4VRsuY
…startup-login-qc3gpw # Conflicts: # docs/bootstrap-spec.md # docs/bootstrap.md
Collapse nested if/if-let chains into single if-let chains, drop a redundant Ok(x?) wrap, remove needless borrows/to_string calls, add Default for InMemoryStore, and allow too-many-arguments on AgentPool::spawn.
register_client's client_id/client_secret were re-requested on every login. AWS fixes their lifetime at 90 days (independent of the org's session-duration setting) and recommends caching them for reuse, so persist them the same way the access token already is.
OS keyrings (Keychain/Credential Manager/Secret Service) are flat (service, account) maps with no real hierarchy, so structure has to come from a naming convention we enforce ourselves. AWS SSO and LLM API keys had each invented their own ad-hoc scheme. Standardize on service = "gitzi/<domain>/<kind>", account = <resource identity>, via a new secrets::service_name helper, so future cloud/provider integrations (GCP, Azure, more LLM providers) stay consistent and every keyring entry is self-describing.
Records candidate crates (azure-identity-helpers/azure_identity for Azure, yup-oauth2/gcp_auth for GCP) and the architectural differences from AWS SSO (no dynamic client registration, no role-exchange step) to inform future provider implementations.
… ~/.aws/config gitzi no longer writes a credential_process profile to ~/.aws/config (or any other cloud's config files) to get Bedrock credentials to the AWS SDK. SsoCredentialsProvider implements ProvideCredentials directly, reusing the cached SSO token and exchanging role credentials on demand; BedrockAgent builds its aws_sdk_bedrockruntime client with that provider rather than via a named profile. Removes the now-pointless `gitzi creds-helper aws` subcommand and the ProviderDef.profile field along with it.
Combine main's WIP-column-stripping logic with this branch's secret migration and unknown-role stripping in Config::load — all three now trigger a single rewrite if any changed something. Also fixes a clippy useless_format lint in main's error_relay.rs that surfaced once merged.
Capture the agreed design for first-run/every-run LLM setup: a binary setup-or-use state owned by the daemon, a backend setup state machine published over the event bus with the TUI as a thin renderer, a distinguished fallback "control-plane" provider that powers setup and recovery conversations (never transparent failover), and Config::load no longer doing discovery.
Add src/setup.rs: the backend-owned "setup or use" gate. SetupState (Loading/NeedsProvider/Error/Ready), ProviderCandidate, gate_ready (main bound to enabled provider OR distinguished fallback enabled), and shared discover-merge + activate logic. - Config gains fallback_provider (the control-plane brain set on first activation) and Config::load stops discovering — load is now pure read-and-report; discovery is owned by the setup phase. - Daemon runs a setup phase on the socket (setup_state / setup_rescan / setup_select / subscribe streaming SetupState) before the dispatcher is built, so no agents come alive until the gate clears. cmd_daemon gates on this. - gitzi_rediscover_providers / gitzi_activate_provider collapse into thin wrappers over crate::setup, sharing one implementation with the pre-agent setup path. Backend compiles clean, clippy clean, 83 lib tests pass.
The TUI becomes a thin renderer over the daemon-owned SetupState: splash while loading, a provider picker, or an error with a rescan hint — no setup logic in the frontend. New full-screen draw_setup switches on the state; setup input (↑/↓/Enter/r) owns the keyboard until the gate clears. daemon_client gains a reconnect outer loop that probes the daemon phase via setup_state and runs either the setup sub-protocol (subscribe to SetupState, relay SetupSelect/SetupRescan) or the existing board protocol, reconnecting across the setup→board handoff. Build + clippy clean, 83 lib tests pass.
- build_main_agent now resolves a named provider into the concrete endpoint URL the chat harness talks to, so an activated provider (e.g. Ollama on :11434) actually drives chat instead of silently falling back to the localhost default. - Dispatcher gains a fallback control-plane brain (build_fallback_agent): a chat agent bound to the distinguished fallback_provider, built only when it's enabled, OpenAI-compatible, and distinct from main's own provider. run_main_agent_turn falls back to it once, with a recovery preamble, when main's provider is down — an explicit "what do you want to do?" conversation, never a silent swap of the user's real request. - Docs: kb/configuration.md documents fallback_provider + the setup gate; bootstrap module doc + ADR-002 status updated to "implemented". - Updated the four integration tests that construct Dispatcher / call build_main_agent for the new signature + field. Fixed a pre-existing redundant-closure lint in state/review.rs test helper. Build + clippy clean; 86 lib tests and the full integration suite pass.
wparad
added a commit
that referenced
this pull request
Jul 25, 2026
…qc3gpw Bedrock first-startup login: SSO auth, keyring credentials, explicit provider activation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/aws_sso.rs). The SSO access token is cached in the OS keyring; short-lived role credentials are exchanged fresh on every use throughgitzi creds-helper aws --provider, an AWScredential_processhelper invoked by the AWS SDK itself.ProviderDef(src/config.rs) with akinddiscriminator (openai-compatible|bedrock) and Bedrock-specific fields (region, profile, SSO start URL/account/role, model ID), plus anenabledflag so providers can exist in config without being wired into any agent.bootstrap.rs's first-run discovery to be purely informational and non-blocking: every provider found (LM Studio, Ollama, AWS SSO sessions/Bedrock) is recordedenabled = falseand nothing is auto-started, auto-loaded, or auto-logged-into. Onboarding can no longer get stuck waiting on infrastructure.gitzi_rediscover_providers,gitzi_activate_provider—src/agent/main_agent.rs, dispatched insrc/dispatcher/mod.rs) so the user can ask "what providers are available?" and then activate one through conversation. Activating an OpenAI-compatible provider is immediate; activating Bedrock walks through SSO login → account selection → role selection → credential validation across tool calls, then writes acredential_processprofile into~/.aws/config.kb/configuration.mdandplan.md's "Bootstrapping" section to describe the new disabled-by-default/explicit-activation model (replacing the old auto-select/auto-start/force-load language);todo.md's Bootstrapping checklist is updated to match (checked off what this PR delivers, dropped the now-superseded "onboarding selection UI" item since activation is chat-driven instead).Column::Testing/TestBuffer,AgentRole::Tester, andStage::Testing/TestBuffer/InTestingfrom an earlier upstream commit that removed the Tester role;tests/e2e_pipeline.rspredated laterProviderDeffield additions and theTask.repoparameter ongitzi_create_task.cargo test(lib + every integration test file) now passes cleanly.origin/mainto resolve a conflict from upstream's doc consolidation (docs/bootstrap.md/docs/bootstrap-spec.mdwere deleted and folded intoplan.md/todo.mdupstream, but that consolidated content still described the old auto-use/force-load behavior — rewrote it to match this PR's actual non-blocking/explicit-activation implementation).Both new tools read and write
~/.gitzi/config.tomldirectly rather than the daemon's in-memoryConfig(immutable for the daemon's lifetime); activating a provider requires agitzirestart to take effect, which the tool's response states.Test plan
cargo check --lib --bins --tests— cleancargo test— all lib and integration tests pass (0 failed), re-verified after mergingorigin/mainaws-sdk-sso/aws-sdk-ssooidcAPI shapes🤖 Generated with Claude Code
https://claude.ai/code/session_016D4d2Y4sEXsFwnTr4VRsuY
Generated by Claude Code