feat: add channel creation flow - #8
Merged
Merged
Conversation
tlongwell-block
added a commit
that referenced
this pull request
Mar 10, 2026
* origin/main: Add desktop Home feed (#12) Add desktop Playwright e2e harness (#11) Update desktop icon and persist window state (#9) feat: add channel creation flow (#8) Improve message markdown display and formatting (#7) feat(desktop): connect chat to relay (#6) docs(readme): clarify desktop setup (#4) feat: add desktop app (#3) # Conflicts: # crates/sprout-test-client/tests/e2e_rest_api.rs
tlongwell-block
added a commit
that referenced
this pull request
Mar 11, 2026
* origin/main: feat: soft-delete for events/channels, enriched API responses, NIP-29 group management (#17) feat: Channel management, messaging, threads, DMs, reactions, and NIP-29 support (#16) Improve chat scrolling and multiline composer (#14) chore: remove redundant inline comments across all crates (#13) Initial backend revisions, workflow expansion (#5) Add desktop Home feed (#12) Add desktop Playwright e2e harness (#11) Update desktop icon and persist window state (#9) feat: add channel creation flow (#8)
tlongwell-block
added a commit
that referenced
this pull request
Mar 12, 2026
…token redaction - CRITICAL: kind:41 now routes to BOTH local (metadata) and upstream (edits) Previously kind:41 was local-only, missing upstream kind:40003 edit events - Validate create_invite: reject empty channels, zero hours/max_uses - Add split_filters_kind41_goes_both test - 79 unit tests + 8 e2e tests passing, clippy clean
tlongwell-block
added a commit
that referenced
this pull request
May 14, 2026
Adds a Settings → Agent Provider panel to the desktop GUI for configuring the `sprout-agent` provider, model, API key, and behavior knobs. Settings are encrypted at rest with NIP-44 self-encryption (the user's own nostr key) and injected into the sprout-agent child's env at spawn time. The panel also gains automatic provider-URL detection based on the API key format the user pastes. ## Backend (`desktop/src-tauri/src/commands/agent_provider_settings/`) - `mod.rs` — IPC types + plaintext `StoredSettings` (Drop zeroizes `api_key`; no Debug derive on input/stored). v2 envelope binds the plaintext to its owner pubkey for rollback / envelope-swap protection. - `storage.rs` — envelope read/write, NIP-44 encrypt/decrypt with `Zeroizing<String>` for plaintext, atomic-rename writes, file-size cap, `normalize_origin` (rejects non-loopback `http://`, userinfo, query, fragment), `validate_input` (provider whitelist, control-char rejection, size caps for key/model/base_url/system_prompt, positive- int knobs). `validate_stored` mirrors the same rules on the decrypted blob at spawn time — fails closed on a rolled-back pre-validation envelope so a redirected `http://api.example.com/v1` cannot escape. - `commands.rs` — `get_*`, `save_*`, `delete_*`, `get_*_env_presence` Tauri commands. The save command trims whitespace + zeroes the input api_key before validation can early-return. - `spawn.rs` — `LoadForSpawn` enum + `EnvPairs` newtype whose Drop zeroizes every value buffer. `apply_to_command` hands each env pair to `Command::env` by reference, zeroizing the local buffer after. Spawn policy: Ok → strip OWNED_AGENT_ENV_VARS + ACP-level vars then inject; None → no-op; IdentityMismatch / Error → fail closed (strip inherited owned vars, inject nothing). - `tests.rs` — round-trip envelope I/O, identity-rotation, save-time validation (oversized prompt, zero timeouts, tiny history bytes, unknown provider, control chars, oversized fields, api-key whitespace trim, owner_pubkey v2), `apply_to_command` × `LoadForSpawn` matrix (Ok/None/IdentityMismatch-fails-closed/Error-fails-closed, openai dialect), `stored_to_env_pairs` for each dialect, R7 `validate_stored` coverage (non-loopback http, control chars in key/model/base_url, userinfo/query in base_url, unknown provider, oversized prompt, empty-key + loopback local accepted). ## Runtime integration (`desktop/src-tauri/src/managed_agents/runtime.rs`) - `build_agent_command` calls `agent_provider_settings::apply_to_command` exactly when the harness is `sprout-agent`. ACP-level vars (SPROUT_AGENT_PROVIDER etc.) are stripped from inherited parent env before injection so a stale shell `ANTHROPIC_API_KEY` never shadows saved settings. `respond-to` gate env (`SPROUT_ACP_RESPOND_TO[_ALLOWLIST]`) threads through with the new `owner_hex: Option<&str>` parameter (origin/main merge). ## Frontend - `lib/detectProvider.ts` — pure key-format detector. Recognizes Anthropic, OpenAI (legacy/proj/svcacct via fixed infix), OpenRouter, Groq, xAI, Cerebras, Together, Perplexity, Fireworks (medium), bare sk- → DeepSeek (low + ambiguity-aware), plus localhost/127.0.0.1 patterns for Ollama / vLLM / llama.cpp. Includes ADMIN_ONLY_PROVIDER_ID sentinel for `sk-ant-admin01-` which we explicitly refuse to save. Key format wins over a prefilled default base URL; an explicit non- default base URL wins back for medium-confidence keys (e.g. Fireworks + api.openai.com host). Fixture strings construct the OpenAI infix via concat so GitHub's secret scanner doesn't regex-match an inline OpenAI-shaped service-account/project key (`detectProvider.test.mjs`, `settings-agent-provider.spec.ts`). - `lib/providerCatalog.ts` — declarative catalog (id, label, dialect, isLocal, default model + base URL, key-shape hint). Drives the picker, the auto-fill on detection, the local-provider placeholder enforcement, and the per-provider model field default. - `lib/agentProviderFormState.ts` — FormState shape + reducers. `applyProviderSwitch` is the single source of truth for what gets reset on a provider change (model when empty or still previous default; baseUrl when new provider has a default OR user hasn't edited it; clears previous default host for null-default providers; drops apiKey on switch TO a local provider). Used by both the manual picker and the auto-detect effect so the policy can't drift. - `lib/agentProviderSettingsApi.ts` + `hooks/useAgentProviderSettings.ts` — typed IPC wrappers + React-Query hooks (load / save / delete / envPresence). - `ui/AgentProviderSettingsCard.tsx` — the panel itself. Empty state with shell-env hint, identity-rotation banner, load-error banner, detected-provider badge, reveal/hide toggle, advanced section, inline provider-change warning, confirm-clear dialog. On save success the plaintext is wiped from form state + reveal toggles off, independent of any React-Query refresh effect (covers the structural- sharing identical-redacted-view edge case). - `ui/AgentProviderAdvancedFields.tsx`, `AgentProviderBanners.tsx`, `AgentProviderClearDialog.tsx` — split components. ## Per-agent dialog (sprout-agent special case) - `agents/ui/CreateAgentDialogSections.tsx` — Model + System prompt inputs are hidden for sprout-agent paths (those are owned globally). A note line points users to Settings → Agent Provider. - `agents/ui/EditAgentDialog.tsx` — passes `selectedProviderId="custom"` to the shared runtime fields so the agent-command input stays editable for existing rows; the system-prompt hide still resolves via `isSproutAgentPath`'s `agentCommand` arm. - `agents/ui/ManagedAgentRow.tsx` — "Model managed by Sprout settings" link is a span with role="button" + stopPropagation (was a nested `<button>` inside the row button — both invalid HTML and double- triggering). - `agents/lib/resolveAcpProviderId.ts` — TS / Rust alignment for inline-args resolution (Rust `known_acp_provider` strips args; TS now matches). ## Tests - Rust: 328 tests passing (R7 added 7; full agent_provider_settings suite at 44/44). - TS / node-test: 55 cases for the form-state reducer + provider detector. - Playwright integration: 12 settings-agent-provider scenarios (empty state + detection + save round-trip, identity-rotation banner, provider-change-warning, key-format-beats-prefilled-baseUrl, load- error banner, clear flow + Escape cancel, rotation banner a11y, local-provider switch with saved key, manual switch reset, detected- provider model reset, post-save key-input clear). ## just ci summary - Rust: 321/321 + 7 new validate_stored tests - Mobile: 336/336 - Desktop / web: format + biome + file-size + ts-check all green - Playwright integration agents + settings-agent-provider: 19/19 green ## Codex review history - Reviews #1, #2, #3, #5, #6 surfaced and fixed: non-loopback HTTP at save AND spawn, identity-mismatch fails closed, local-provider key leak prevention, inline-args resolver alignment, Zeroize on api_key before early-return, no Debug derive, control-char / length caps + trim, owner_pubkey v2 envelope, local-provider switch unblock, EditAgentDialog command field, model reset on detection switch, nested-button fix, `applyProviderSwitch` reducer extraction. - Review #7 (P2-UI + P2-Rust): clear form.apiKey + revealKey on save success; validate decrypted settings at spawn time. - Review #8: 9/10, no blocking findings. Signed-off-by: Tyler Longwell <109685178+tlongwell-block@users.noreply.github.com> Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@sprout-oss.stage.blox.sqprod.co>
wpfleger96
added a commit
that referenced
this pull request
May 22, 2026
…iew findings The original implementation created a second parallel Tauri command (discover_all_acp_providers) alongside the existing one to avoid changing the return type. This produced two commands, two hooks, two query keys, and two raw type converters. Consolidates into a single command returning the full catalog, with a useAvailableAcpProviders hook that type-narrows for callers needing non-null command/binaryPath. Also fixes: pipe deadlock in install command (#1), UTF-8 truncation panic (#2/#4), adds install concurrency guard (#11), exact provider ID match (#15), error display stdout fallback (#5), success banner suppression when already available (#12), misleading re-run text (#13), IIFE refactor in PersonaDialog (#14), hidden internal query lift (#7), configurable e2e mocks (#9), shared raw type exports (#8), and classify_provider unit tests (#10).
wpfleger96
added a commit
that referenced
this pull request
May 22, 2026
…iew findings The original implementation created a second parallel Tauri command (discover_all_acp_providers) alongside the existing one to avoid changing the return type. This produced two commands, two hooks, two query keys, and two raw type converters. Consolidates into a single command returning the full catalog, with a useAvailableAcpProviders hook that type-narrows for callers needing non-null command/binaryPath. Also fixes: pipe deadlock in install command (#1), UTF-8 truncation panic (#2/#4), adds install concurrency guard (#11), exact provider ID match (#15), error display stdout fallback (#5), success banner suppression when already available (#12), misleading re-run text (#13), IIFE refactor in PersonaDialog (#14), hidden internal query lift (#7), configurable e2e mocks (#9), shared raw type exports (#8), and classify_provider unit tests (#10).
wpfleger96
added a commit
that referenced
this pull request
May 22, 2026
…iew findings The original implementation created a second parallel Tauri command (discover_all_acp_providers) alongside the existing one to avoid changing the return type. This produced two commands, two hooks, two query keys, and two raw type converters. Consolidates into a single command returning the full catalog, with a useAvailableAcpProviders hook that type-narrows for callers needing non-null command/binaryPath. Also fixes: pipe deadlock in install command (#1), UTF-8 truncation panic (#2/#4), adds install concurrency guard (#11), exact provider ID match (#15), error display stdout fallback (#5), success banner suppression when already available (#12), misleading re-run text (#13), IIFE refactor in PersonaDialog (#14), hidden internal query lift (#7), configurable e2e mocks (#9), shared raw type exports (#8), and classify_provider unit tests (#10).
themiguelamador
added a commit
to Complear/buzz
that referenced
this pull request
Jul 30, 2026
…precise Scope narrowed to a single deployment — self-hosted, single-tenant, CUI — while keeping a defensible post-quantum claim. Three research findings changed the substance rather than just the framing. **FIPS and PQ converge rather than trade off.** AWS-LC-FIPS 3.0 is the first cryptographic library to include ML-KEM inside a FIPS 140-3 validation, covering ML-KEM-512/768/1024. So the same `ring → aws-lc-rs` switch that enables hybrid key exchange also enables the validated module 800-171 3.13.11 requires. W1 was already the keystone; it is now the keystone for both the compliance floor and the PQ claim. Added a gate: confirm the CMVP certificate is *validated*, not "in process" — an assessor will check, and it was in-process at release. **Corrected the key-exchange recommendation.** Earlier drafts said X25519MLKEM768 because it is the widely deployed hybrid. For a FIPS deployment `SecP256r1MLKEM768` is better — both halves are unambiguously FIPS-approved, which removes an argument you would otherwise have to win. rustls/aws-lc-rs offers seven groups; the spec now names the choice and makes it configurable. **CNSA 2.0 contradicts one of the standing principles.** NSA prefers *pure* ML-KEM over hybrid for national security systems, requires ML-KEM-1024 rather than 768, and sanctions P-384 + ML-KEM-1024 where hybrid is unavoidable. NIST and IETF favour hybrid. "Hybrid, never PQ-only" was stated as universal; it is the NIST/CUI position and is now scoped as such. rustls exposes MLKEM1024 standalone but no P-384 hybrid, so CNSA alignment would be an upstream gap — hence making the group configurable now rather than hardcoding it. **The DM decision turns out to be the PQ story, not just the FIPS one.** Harvest-now-decrypt-later requires stored ciphertext under classical asymmetric keys. Disabling gift-wrapped DMs removes that category entirely: what remains is hybrid-protected transport, AES-256 at rest, and SHA-256 audit chaining — all quantum-safe. What stays classical is signatures, which are categorically different because forgery needs a CRQC at the moment of attack and cannot be done retroactively. That is why a PQ confidentiality claim is available in this profile and would not be in the others. **Added a claims register** (`defence-deployment.md` §7) with the exact wording that may and may not be used, each row tied to the test that unlocks it. Not claimable: "post-quantum secure" unqualified, "quantum-resistant identity", "end-to-end encrypted" (false here by design), "FIPS certified" (modules are validated, products are not), "CNSA 2.0 compliant", "meets CMMC Level 2". Overclaiming is the actual legal risk — the FTC action against Zoom was for claiming E2EE it lacked, not for lacking it. Roadmap gains claim-gating: no claim before its test passes in CI, now also standing principle block#8. **Corrected a conflict I had overstated.** E2EE huddles vs FIPS was recorded as a real conflict; it is not. AES-GCM and HKDF-SHA256 are both FIPS-approved, so a FIPS-compliant E2EE huddle design is possible. It is deferred because this deployment has no third-party host to defend against and huddle audio must be recorded for supervision anyway — not because FIPS forbids it. W8 and W9 are deferred with their specs retained unbuilt. W7 is now conditional: NIP-AB exists to move a private key to a device, but under the enterprise signer the key never leaves the signer, so pairing may carry only a NIP-46 session bootstrap — confirm before building, or the workstream drops out. Profile matrix replaced by a single normative target configuration; conflicts, decisions and milestones re-cut accordingly, with a claim-gating table added. Signed-off-by: Miguel Amador <miguel@amador.one>
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
POST /api/channelsand wire the relay/Tauri clients to return created channel recordsTesting
just ci