diff --git a/README.md b/README.md index 42293e3f..68c3cd3b 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # Wayfinder -Wayfinder is a local-first model router and native macOS chat app. It scores each -request locally, chooses a configured destination, and keeps delivery policy -separate from the application making the request. +Wayfinder is a local-first model router and native Apple AI environment. It +scores each request locally, chooses an eligible destination, and keeps delivery +policy separate from the application making the request. The production router is implemented in Rust. Wayfinder Desktop embeds that router inside the signed application bundle; no Python runtime, package, or @@ -24,6 +24,18 @@ The native Swift macOS app provides: Desktop releases use SemVer and `desktop-v*` tags. See [`macos/WayfinderMac/Packaging/RELEASE.md`](macos/WayfinderMac/Packaging/RELEASE.md). +### Wayfinder for iPhone and iPad + +Native standalone iPhone and iPad apps are planned for v0.2.0. They embed the +same authoritative Rust routing core and execute approved on-device or direct +cloud providers without requiring a Mac or localhost gateway. Optional Mac +pairing follows in v0.2.1 as an additional provider. + +The governing contracts are +[`WF-ROADMAP-0016`](roadmaps/WF-ROADMAP-0016-native-mobile-v0.2.md), +[`WF-ADR-0047`](decisions/WF-ADR-0047-native-mobile-independence.md), and +[`WF-ADR-0048`](decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md). + ### Rust gateway The Rust workspace contains the deterministic scoring core, configuration @@ -83,6 +95,8 @@ node clients/shared/test/parity.mjs ```text rust/ native router, gateway, providers, and service crates +apple/ planned shared Apple packages after bridge validation +ios/ planned native iPhone and iPad product macos/WayfinderMac/ native Swift macOS app and release packaging clients/ retained thin-client contract code and fixtures decisions/ architecture decisions diff --git a/decisions/WF-ADR-0042-desktop-menu-bar-client.md b/decisions/WF-ADR-0042-desktop-menu-bar-client.md index 2cef52e4..7bf310b3 100644 --- a/decisions/WF-ADR-0042-desktop-menu-bar-client.md +++ b/decisions/WF-ADR-0042-desktop-menu-bar-client.md @@ -30,6 +30,13 @@ Accepted > notarized, stapled app in a ZIP; the universal DMG and automatic-updater decisions below remain > historical Tauri targets, not v0.1.0 requirements. The optional ChatGPT account provider requires > the separately installed verified ChatGPT app. Wayfinder does not bundle Codex in this release. +> +> Rust-only amendment (WF-ADR-0046): Python, PyPI, and delegated-command language below records the +> migration history. Rust is now the sole production router and gateway. +> +> Mobile amendment (WF-ADR-0047/0048): this ADR remains the macOS constitution. Native iPhone and +> iPad are independently useful, embed the shared pure routing core, own their credentials and +> threads, and do not run or require this desktop gateway. That is not a second routing algorithm. ## Category @@ -203,3 +210,5 @@ menu-bar utility and keeps the binary small. - WF-DESIGN-0012 (the popover design contract) · WF-ROADMAP-0009 (the delivery plan) - WF-DESIGN-0018 (external verified ChatGPT-app provider boundary) - WF-ROADMAP-0015 (Apple Silicon desktop v0.1.0 release contract) +- WF-ADR-0046 (Rust-only runtime) +- WF-ADR-0047 / WF-ADR-0048 (native mobile independence and shared routing core) diff --git a/decisions/WF-ADR-0045-rust-gateway-helper-architecture.md b/decisions/WF-ADR-0045-rust-gateway-helper-architecture.md index 026ecac9..2ee9c188 100644 --- a/decisions/WF-ADR-0045-rust-gateway-helper-architecture.md +++ b/decisions/WF-ADR-0045-rust-gateway-helper-architecture.md @@ -9,13 +9,24 @@ tags: [rust, gateway, router, helper, macos, compatibility, security, packaging] ## Status -Accepted for staged implementation; Rust is not yet accepted as the default backend. +Superseded for runtime-selection and migration state by WF-ADR-0046. Retained +as the architecture and threat-model record for the separately running macOS +gateway helper. > Desktop v0.1.0 release amendment (WF-ROADMAP-0015): the native app explicitly ships its bundled > Rust gateway as a thin arm64 helper on Apple Silicon. This desktop-product selection does not make > Rust the default for standalone, Homebrew, container, or PyPI installations and does not authorize > Python removal. The originally accepted universal arm64/x86_64 artifact remains a future broader > distribution gate rather than a requirement for the first desktop release. +> +> Rust-only cutover (WF-ADR-0046): Python coexistence, delegation, PyPI, and +> Python verification gates below are historical migration constraints, not +> current runtime requirements. +> +> Mobile amendment (WF-ADR-0048): the rejection of an in-process Swift/Rust +> bridge remains correct for the macOS gateway-first product. Native iPhone and +> iPad have no gateway helper and therefore embed a separately extracted pure +> routing core through generated bindings. ## Category @@ -328,3 +339,5 @@ omitted from a default-readiness recommendation. - WF-ADR-0042/0044 (thin native client and CLI-owned configuration) - `docs/rust-migration-capability-matrix.md` - WF-ROADMAP-0015 (Apple Silicon desktop v0.1.0 release contract) +- WF-ADR-0046 (completed Rust-only cutover) +- WF-ADR-0048 (mobile shared-core embedding) diff --git a/decisions/WF-ADR-0046-rust-only-runtime.md b/decisions/WF-ADR-0046-rust-only-runtime.md index 0444b9e0..d2e45a22 100644 --- a/decisions/WF-ADR-0046-rust-only-runtime.md +++ b/decisions/WF-ADR-0046-rust-only-runtime.md @@ -53,3 +53,10 @@ contract and its own tests; a hidden compatibility fallback is not allowed. The deterministic decision path remains offline, keyless, and free of delivery dependencies (WF-ADR-0001). This decision does not broaden the credential broker, change Automatic routing preferences, or make Apple a global default. + +## Mobile amendment + +WF-ADR-0047 and WF-ADR-0048 extend the Rust-only decision to native mobile: +Wayfinder extracts a pure routing library from this workspace and embeds it in +iPhone and iPad rather than running the gateway executable or recreating the +algorithm in Swift. The macOS product remains gateway-first. diff --git a/decisions/WF-ADR-0047-native-mobile-independence.md b/decisions/WF-ADR-0047-native-mobile-independence.md new file mode 100644 index 00000000..89b154e3 --- /dev/null +++ b/decisions/WF-ADR-0047-native-mobile-independence.md @@ -0,0 +1,137 @@ +--- +schema_version: 1 +id: WF-ADR-0047 +type: decision +status: accepted +date: 2026-07-24 +tags: [ios, ipados, native, mobile, pairing, routing, privacy] +--- + +# iPhone and iPad are independent Wayfinder products; pairing is optional + +## Context + +Wayfinder Desktop v0.1.0 established a native macOS Chat experience over a +bundled Rust gateway. A companion-only mobile app would inherit the Mac's +availability, trust, and lifecycle without giving an iPhone or iPad an +independently useful product. + +Mobile devices can legitimately execute work in two domains without a Mac: + +- Apple's on-device Foundation Models framework when the current device reports + it available; and +- approved hosted providers called directly with a Keychain-held API key or an + official provider account flow. + +A trusted Mac can still contribute larger local models and desktop-only account +helpers, but that is an extension of the eligible destination set rather than +the foundation of mobile Wayfinder. + +## Decision + +Wayfinder v0.2.0 ships as a fully native iPhone and iPad application. It embeds +the authoritative deterministic routing core, owns local threads and +configuration, executes approved providers, and remains useful when every Mac +is off. + +The product has three execution domains: + +1. **On this device** — execution occurs on the current iPhone or iPad. +2. **Direct cloud** — the current device contacts an approved hosted provider. +3. **Paired Wayfinder host** — an optional trusted Mac or self-hosted Wayfinder + runtime contributes destinations through a bounded provider adapter. + +Pairing is deferred from the v0.2.0 release gate to v0.2.1. It is represented as +a provider and never owns the mobile app's settings, credentials, conversations, +or identity. + +## Product invariants + +- First launch leads with standalone use. Connecting a Mac is secondary. +- Chat, routing, direct provider setup, Apple on-device execution, and thread + retention never require a Mac or a localhost gateway. +- Connecting an account or adding a key publishes eligible destinations but + never silently changes `Automatic` or rewrites a user route. +- A paired host joins a route only after explicit per-host opt-in. +- Removing or powering off a paired host cannot prevent launch, thread access, + direct cloud execution, or on-device execution. +- Existing macOS behavior remains gateway-first. Mobile work does not broaden + the macOS credential broker or replace its ChatGPT/Codex helper boundary. + +## Execution-boundary truth + +Every destination declares one current content-execution boundary: + +- `on-device` — prompt content remains on the current iPhone or iPad; +- `local-network` — a trusted nearby Wayfinder device receives the request; +- `hosted` — a cloud provider receives the request. + +Transport and execution are recorded separately for paired hosts. A request +sent to a Mac and then to ChatGPT is **hosted via the Mac**. A request sent to a +Mac-local Qwen instance is **Mac local over the local network**. Neither is +described as on-device on the phone. + +The runtime enforces three user postures: + +| Posture | Eligible boundaries | +| --- | --- | +| On-Device Only | `on-device` | +| Local Devices | `on-device`, `local-network` | +| Hosted Allowed | all | + +No failure may cross a denied boundary. A pinned destination fails specifically +rather than silently switching. + +## Platform experience + +After onboarding, iPhone launches into a `TabView` with separate navigation +stacks for Chat, Threads, Destinations, and Settings. iPad uses an adaptive +`NavigationSplitView` with transcript and composer as the primary surface and +an optional route inspector. + +The macOS window hierarchy is not copied into a smaller display. Standard Apple +navigation, forms, lists, sheets, typography, accessibility, and platform +materials take precedence over custom chrome. + +## Consequences + +### Positive + +- Mobile Wayfinder has a clear value proposition even with no Mac or signal. +- A Mac can add capabilities without becoming a synchronization or identity + authority. +- Privacy language follows actual prompt movement. +- The same deterministic product signature applies across Apple devices. + +### Negative + +- iOS must own provider execution, credentials, persistence, and lifecycle + behavior rather than reusing the desktop HTTP process shape. +- Direct providers may require native Swift adapters even when desktop delivery + remains implemented in Rust. +- Pairing requires a separate authenticated protocol and revocation model. + +## Rejected alternatives + +### Companion-only iOS client + +Rejected because onboarding, routing, Chat, and retention would all fail when a +Mac is unavailable. + +### Internal localhost gateway on iOS + +Rejected because it preserves a desktop deployment shape rather than a mobile +product boundary. iOS embeds the routing library and calls provider adapters +directly. + +### Mac as the mobile configuration authority + +Rejected because pairing must remain optional and revocable. Mobile +configuration and threads are locally owned. + +## Related + +- WF-ADR-0048 — shared routing core and Apple embedding +- WF-DESIGN-0019 — provider, authentication, and credential contract +- WF-ROADMAP-0016 — native mobile v0.2 delivery +- `docs/apple-platform-capability-matrix.md` diff --git a/decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md b/decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md new file mode 100644 index 00000000..5e4d3813 --- /dev/null +++ b/decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md @@ -0,0 +1,147 @@ +--- +schema_version: 1 +id: WF-ADR-0048 +type: decision +status: accepted-for-phase-0-spikes +date: 2026-07-24 +tags: [rust, swift, ios, ipados, ffi, routing, providers, persistence] +--- + +# Share one pure Rust routing core and embed it natively on Apple platforms + +## Context + +WF-ADR-0046 made Rust Wayfinder's sole router and gateway runtime. The current +workspace still combines pure deterministic routing with host, HTTP-server, +provider, service, and macOS integration responsibilities. + +iOS cannot run the macOS helper topology and should not launch an internal +loopback server merely to preserve it. Reimplementing score, thresholds, +exclusions, tie-breaks, or receipts in Swift would create a second routing +authority. + +## Decision + +Extract a platform-neutral Rust library that owns all authoritative route +planning. The gateway and the mobile bridge consume that same library and +shared fixtures. + +Target ownership: + +```text +rust/crates/ + wayfinder-routing-core/ pure deterministic planning and receipts + wayfinder-runtime-contracts/ requests, destinations, errors, usage + wayfinder-provider-core/ portable provider orchestration where proven + wayfinder-apple-ffi/ generated Swift-facing bridge + wayfinder-gateway/ Axum/server host consuming the same core +``` + +`wayfinder-routing-core` performs no filesystem, Keychain, process, UI, +HTTP-server, Apple-framework, or provider-secret work. Eligibility inputs are +typed destination snapshots supplied by the host runtime. It owns: + +- compatibility exclusions and stable reason codes; +- score and threshold semantics; +- tier and ordered-route selection; +- stable tie-breaks and fallback planning; +- route explanations and compact receipts. + +The mobile app calls the library in-process. The macOS product may remain a +thin client over its bundled gateway for v0.2. + +## Bridge contract + +Phase 0 tests generated UniFFI Swift bindings first. A narrow generated C ABI is +the fallback only if UniFFI fails measured device, simulator, concurrency, +cancellation, binary-size, or maintenance gates. + +The runtime bridge remains small: + +```swift +protocol WayfinderRoutingEngine: Sendable { + func validate(configuration: RoutingConfiguration) async throws + func score(_ request: RoutingRequest) async throws -> ComplexityResult + func plan( + _ request: RoutingRequest, + candidates: [DestinationSnapshot] + ) async throws -> RoutePlan + func explain(_ plan: RoutePlan) async throws -> RouteExplanation +} +``` + +Do not hand-maintain a broad JSON-over-FFI runtime. JSON remains the canonical +portable fixture and debugging format. Provider streaming belongs to the +execution layer, not the pure scorer. + +## Provider execution placement gate + +The routing-core language is decided; provider execution placement is not. +Phase 0 compares: + +1. shared Rust HTTP execution with a narrow Swift credential callback; and +2. Rust route planning with Swift `URLSession` provider execution. + +The selected v0.2 path must demonstrate: + +- correct cancellation before and during streaming; +- fragmented SSE and terminal-event behavior; +- system TLS and ATS compatibility; +- bounded memory and event queues; +- usable error classification; +- acceptable binary size and launch cost; +- no secret crossing an unnecessary language boundary. + +Apple frameworks, Authentication Services, Keychain, and Apple on-device model +execution remain in Swift regardless of this result. A Swift provider adapter +is acceptable when it implements the shared contracts and fixtures. + +## Accepted mobile foundation choices + +- **Deployment floor:** iOS 18 and iPadOS 18. Foundation Models remains + separately availability-gated to the OS/device states that actually support + it. +- **Route configuration:** typed native data with a versioned export/import + schema; mobile does not edit desktop TOML. +- **Provider catalog:** executable adapters are built in and reviewed. Remote + signed metadata may update labels and model catalogs only after a separate + schema/signature implementation. +- **Credential backup:** provider secrets use device-only Keychain + accessibility by default and are not silently synchronized. +- **Mac adoption:** shared Apple packages are introduced incrementally after + the mobile seams are proven; the existing macOS target is not moved first. + +## Decisions still requiring measured Phase 0 artifacts + +| Decision | Required artifact | Gate | +| --- | --- | --- | +| UniFFI vs generated C ABI | simulator and physical-device bridge spike | typed call, errors, concurrency, lifetime, size | +| Rust HTTP vs Swift `URLSession` | two execution spikes | streaming, cancellation, TLS, memory, size | +| SwiftData vs SQLite | persistence prototype | migration, deterministic tests, export/delete | + +These are bounded choices inside the accepted architecture. None may change +mobile independence or introduce a Swift routing implementation. + +## Parity and release gates + +- Gateway and embedded calls consume the same golden corpus. +- Serialized decisions and reason codes are byte-identical where serialization + applies. +- Simulator and physical-device architecture builds are required. +- Malformed/oversized input, version skew, concurrency, callback release, and + cancellation races fail safely. +- Core extraction lands without provider or UI behavior changes. +- XCFramework/bridge work lands separately from the extraction. + +## Consequences + +The router remains one inspectable authority while each Apple host can use the +native lifecycle and security APIs appropriate to it. The cost is an explicit +FFI build/test lane and shared-contract discipline across Swift and Rust. + +## Related + +- WF-ADR-0046 — Rust-only runtime +- WF-ADR-0047 — native mobile independence +- WF-DESIGN-0019 — provider and authentication framework +- WF-ROADMAP-0016 — mobile delivery sequence diff --git a/designs/WF-DESIGN-0017-apple-foundation-models-provider.md b/designs/WF-DESIGN-0017-apple-foundation-models-provider.md index 50ffad5c..a5778085 100644 --- a/designs/WF-DESIGN-0017-apple-foundation-models-provider.md +++ b/designs/WF-DESIGN-0017-apple-foundation-models-provider.md @@ -14,6 +14,11 @@ Setup preselects the Apple Local preset only after a live `available` response. route default: existing configuration and route ladders remain unchanged, and Chat still opens on `Automatic`. +> Mobile amendment (WF-ROADMAP-0016): this document remains authoritative for the macOS XPC +> topology. iPhone and iPad use the same provider identity and normalized availability semantics, +> but call Foundation Models in-process behind a Swift actor. Mobile never requires the macOS +> gateway or inference XPC service. + ## Decision WAYFINDER will represent Apple's on-device system model as the typed provider kind @@ -111,7 +116,7 @@ bounds, accounting, breaker/cache/offline semantics, and signed caller authentic v0.1.0 still requires final signed app-closed inference and clean Apple Silicon release evidence. The accepted setup preference is limited to never-configured Macs with confirmed live availability; Ollama/manual local setup remains supported, existing configuration is preserved, and no global -`Automatic` route is changed. This decision does not remove the standalone Python distribution. +`Automatic` route is changed. ## Related @@ -120,3 +125,6 @@ Ollama/manual local setup remains supported, existing configuration is preserved - WF-ADR-0039 - `docs/apple-foundation-models-handoff.md` - `docs/rust-migration-capability-matrix.md` +- WF-ADR-0047 +- WF-ADR-0048 +- WF-ROADMAP-0016 diff --git a/designs/WF-DESIGN-0018-codex-chatgpt-provider.md b/designs/WF-DESIGN-0018-codex-chatgpt-provider.md index ce0081af..b10fb951 100644 --- a/designs/WF-DESIGN-0018-codex-chatgpt-provider.md +++ b/designs/WF-DESIGN-0018-codex-chatgpt-provider.md @@ -17,6 +17,11 @@ Accepted > claim this provider is self-contained. Release discovery ignores development overrides and rejects > colocated or sibling executables; only the fixed ChatGPT-app runtime may pass the production trust > checks. A bundled runtime remains possible only through a later reviewed packaging decision. +> +> Mobile amendment (WF-ROADMAP-0016): ChatGPT/Codex is not a native iOS account provider. OpenAI +> Platform remains a separate direct API-key provider. Until an official permitted mobile account +> execution contract exists, iPhone and iPad may access this destination only through an explicitly +> paired Mac, where it is labelled `hosted via `. No Codex credential or helper moves to iOS. ## Summary @@ -204,3 +209,4 @@ isolation cases above. - WF-ADR-0042 (one backend, thin native client) - WF-ROADMAP-0012 (focused native Chat and routing inspector) - WF-ROADMAP-0015 (Apple Silicon desktop v0.1.0 release contract) +- WF-ROADMAP-0016 (standalone native mobile and optional paired-host contract) diff --git a/designs/WF-DESIGN-0019-mobile-providers-accounts-and-credentials.md b/designs/WF-DESIGN-0019-mobile-providers-accounts-and-credentials.md new file mode 100644 index 00000000..809d4b43 --- /dev/null +++ b/designs/WF-DESIGN-0019-mobile-providers-accounts-and-credentials.md @@ -0,0 +1,222 @@ +--- +schema_version: 1 +id: WF-DESIGN-0019 +type: design +status: accepted-for-implementation +date: 2026-07-24 +tags: [ios, ipados, providers, accounts, oauth, keychain, privacy, kimi] +--- + +# Mobile provider, account, and credential framework + +## Summary + +Wayfinder mobile publishes concrete destinations from built-in provider +adapters. Authentication, model discovery, execution, routing eligibility, and +route mutation are separate concerns. + +Accounts are official vendor entitlements. Keys are developer/API credentials. +On-device providers need neither. Paired hosts use revocable device trust. +Connecting any of them makes destinations available but never silently changes +`Automatic`. + +## Normalized types + +Every provider declares typed authentication, execution, and billing: + +```swift +enum ProviderAuthenticationMode: String, Codable, Sendable { + case none + case apiKey + case oauthAuthorizationCodePKCE + case oauthDeviceCode + case verifiedDesktopRuntime + case pairedHost +} + +enum ExecutionBoundary: String, Codable, Sendable { + case onDevice + case localNetwork + case hosted +} + +enum BillingClass: String, Codable, Sendable { + case onDevice + case subscription + case apiMetered + case unknown +} +``` + +`ProviderDescriptor` contains stable identity, display metadata, +implementation version, supported platforms, auth modes, boundary, billing, +capabilities, documentation, and a concise privacy summary. + +Readiness is normalized as checking, signed out, authorizing, ready, +reauthentication required, usage limited, model unavailable, network +unavailable, unsupported platform, unavailable, or failed. + +No snapshot contains access tokens, refresh tokens, keys, cookies, raw provider +payloads, credential paths, or authorization headers. + +## Runtime seams + +Authentication, catalog, and execution remain separately testable: + +```swift +protocol ProviderAccountController: Sendable { + var descriptor: ProviderDescriptor { get } + func state() async -> ProviderAccountState + func beginAuthorization() async throws -> AuthorizationChallenge + func pollAuthorization( + _ authorizationID: AuthorizationID + ) async throws -> ProviderAccountState + func cancelAuthorization(_ authorizationID: AuthorizationID) async + func refresh() async throws -> ProviderAccountState + func signOut() async throws +} + +protocol ProviderModelCatalog: Sendable { + func models( + account: ProviderAccountSnapshot? + ) async throws -> [ModelDescriptor] +} + +protocol ProviderExecutor: Sendable { + func stream( + _ request: ProviderExecutionRequest + ) -> AsyncThrowingStream + func cancel(requestID: RequestID) async +} +``` + +The root `AppModel` observes value snapshots. Actors own provider registry, +credentials, conversations, and execution. SwiftUI views never read Keychain +or contact providers from `body`. + +## Credential custody + +- Secrets live only in Keychain with a device-only accessibility class suitable + for foreground use. +- Non-secret provider configuration is stored separately. +- Explicit sign-out deletes the credential and verifies that subsequent reads + fail. +- Credentials never enter SwiftData/SQLite, UserDefaults, route receipts, + logs, analytics, crashes, previews, screenshots, or accessibility labels. +- Reads occur only inside the provider/runtime boundary. +- The existing macOS credential broker is unchanged. + +## Authorization code + +Official authorization-code providers use `ASWebAuthenticationSession`, PKCE, +exact `state` validation, exact callback ownership, minimum scopes, and an +approved HTTPS redirect or reviewed custom scheme. Cancellation, denial, +callback mismatch, timeout, and token exchange failure are distinct terminal +states. A general `WKWebView` is not an authentication agent. + +## Device authorization + +Documented RFC 8628 providers expose verification URL, user code, expiry, and +provider identity with copy, open, cancel, and retry actions. Polling respects +the provider interval and distinguishes pending, slow-down, expiry, denial, and +success. Partial token responses are rejected. Polling ends when the +authorization UI ends or the challenge expires. + +A provider-required device identifier is random, app-scoped, and stored in +Keychain. Wayfinder does not fingerprint hardware, use IDFA, imitate another +client, or import another client's identifier. + +## Provider catalog + +Executable adapter logic is compiled into the reviewed App Store binary. +Bundled or separately signed metadata may define display information, model +aliases, documented auth endpoints/scopes, required headers, model catalog +shape, capability defaults, minimum adapter version, and deprecation state. + +Metadata cannot add executable behavior, change credential custody, enable an +adapter absent from the binary, or authorize an unreviewed auth flow. + +## Initial provider set + +Phase 3 implements API-key providers in this order: + +1. generic OpenAI-compatible endpoint; +2. OpenAI Platform preset; +3. Moonshot/Kimi Platform preset; +4. OpenRouter preset. + +Anthropic and Gemini follow only after their distinct request and streaming +contracts have shared fixtures. + +OpenAI Platform and ChatGPT/Codex remain separate: + +- OpenAI Platform is a direct iOS API-key provider. +- ChatGPT/Codex is a macOS-only verified desktop-runtime provider. +- iOS may see ChatGPT/Codex only through a paired Mac until an official, + permitted native account-execution contract exists. + +No consumer subscription is treated as general API entitlement. + +## Kimi boundary + +Official Kimi Code documentation confirms that `kimi login` uses an RFC 8628 +device-code flow. It does not establish that Wayfinder may reuse Kimi Code's +client identity or model endpoint. + +`docs/qualifications/WF-QUAL-0001-kimi-account-auth.md` therefore classifies +Kimi account authentication as **blocked pending provider approval**. v0.2.0 +may ship the Moonshot/Kimi Platform API-key preset. “Sign in with Kimi” remains +absent unless every qualification gate is closed. + +## Apple on-device provider + +The iOS adapter calls Foundation Models in-process behind an actor. It queries +actual availability, context, languages, capabilities, and readiness. It +distinguishes unsupported OS, ineligible device, Apple Intelligence disabled, +model not ready, and unknown unavailability. + +The adapter streams ordered output, supports cancellation, persists no native +session, and translates only parameters supported by the framework. Under +On-Device Only it can never fall back to a hosted or paired destination. + +Apple on-device is eligible for appropriate local/easy work when available; it +is not injected into existing routes. Onboarding may recommend it only with +visible confirmation. + +## Logging + +Allowed metadata: provider/model IDs, execution boundary, latency, bounded +usage, request status, cancellation, sanitized error class, score/reason codes, +and app/runtime version. + +Forbidden: content, system instructions, authorization material, identity, +paired credentials, raw catalog payloads containing account metadata, or raw +provider errors. + +## Required deterministic coverage + +- Keychain create/read/update/delete and secret-leak scans; +- PKCE/state/callback mismatch and cancellation; +- RFC 8628 pending/slow-down/expiry/denial/cancel/success; +- refresh rotation, revocation, partial token rejection, and sign-out; +- fragmented/malformed streaming and exactly one terminal event; +- timeout, network transition, usage limit, removed model, and cancellation; +- eligibility refresh after account state changes; +- connecting a provider never mutates routes; +- pinned unavailable destinations never fall back. + +## References + +- Apple `ASWebAuthenticationSession`: + https://developer.apple.com/documentation/authenticationservices/aswebauthenticationsession +- Apple Foundation Models: + https://developer.apple.com/documentation/foundationmodels +- OAuth PKCE (RFC 7636): + https://www.rfc-editor.org/rfc/rfc7636 +- OAuth device authorization (RFC 8628): + https://www.rfc-editor.org/rfc/rfc8628 +- Kimi Code `kimi login`: + https://www.kimi.com/code/docs/en/kimi-code-cli/reference/kimi-command +- WF-ADR-0047 +- WF-ADR-0048 +- WF-DESIGN-0018 diff --git a/docs/apple-foundation-models-handoff.md b/docs/apple-foundation-models-handoff.md index 3b2df82c..300b79e1 100644 --- a/docs/apple-foundation-models-handoff.md +++ b/docs/apple-foundation-models-handoff.md @@ -2,6 +2,13 @@ Status snapshot: 2026-07-13 +> Scope amendment (2026-07-24): this handoff remains the implementation record +> for the macOS gateway/XPC provider. It does not define the mobile topology. +> Native iPhone and iPad v0.2 uses the same typed provider and availability +> truth but executes Foundation Models in-process behind a Swift actor, embeds +> the shared Rust routing core, and does not require a Mac. See WF-ADR-0047, +> WF-ADR-0048, WF-DESIGN-0019, and WF-ROADMAP-0016. + ## Goal Add Apple's on-device `SystemLanguageModel` as WAYFINDER's preferred local provider on eligible @@ -204,4 +211,5 @@ The availability-gated new-setup preference must retain these gates: - Ollama/manual local configuration remains usable; - the capability matrix links direct evidence. -This feature does not by itself permit Rust to become the default backend or Python to be removed. +Rust subsequently became the sole router and gateway runtime under WF-ADR-0046. +That cutover does not change the macOS XPC security boundary described here. diff --git a/docs/apple-platform-capability-matrix.md b/docs/apple-platform-capability-matrix.md new file mode 100644 index 00000000..b551bd86 --- /dev/null +++ b/docs/apple-platform-capability-matrix.md @@ -0,0 +1,60 @@ +# Apple platform capability matrix + +Status: Phase 0 contract, 2026-07-24 + +This matrix records product ownership and release claims. A capability marked +planned is not implemented merely because a platform API or desktop equivalent +exists. + +| Capability | macOS v0.1 | iPhone/iPad v0.2.0 | Paired host v0.2.1 | +| --- | --- | --- | --- | +| Product independence | Shipping native app | Required; no Mac/gateway | Optional extension only | +| Authoritative routing | Bundled Rust gateway | Embedded shared Rust core | Mobile plans; host advertises candidates | +| Route algorithm in Swift | Forbidden | Forbidden | Forbidden | +| Conversation owner | macOS app | Mobile app | Mobile app; host keeps bounded request records | +| Configuration | Gateway TOML through bounded native seams | Typed native store/export | Host config remains host-owned | +| Provider API keys | macOS Keychain/XPC boundary | Device-only Keychain actor | Never transferred | +| Direct cloud execution | Rust gateway | Planned direct provider adapter | Host may contribute hosted destinations | +| Apple Foundation Models | macOS XPC service | In-process Swift actor | Mac advertises its own provider separately | +| OpenAI Platform | API key | API key | Optional hosted-via-Mac destination | +| ChatGPT/Codex account | Verified desktop runtime | Not native | Available only through approved paired host | +| Kimi/Moonshot API | Not yet | Planned API-key preset | May be host-provided | +| Kimi Code account | Not implemented | Blocked by WF-QUAL-0001 | Not inferred from host installation | +| OAuth authorization code | Not generalized | Planned with PKCE | No remote login control | +| OAuth device code | Codex helper-owned for desktop provider | Planned generic engine | No remote login control | +| On-Device Only posture | Desktop offline closure | Required runtime enforcement | Host excluded | +| Local Devices posture | Not applicable | Planned | Allows opted-in local-network destinations | +| Hosted Allowed posture | Gateway policy | Planned | May include cloud-via-Mac | +| Streaming/cancellation | Shipping gateway contract | Release gate | Request reconciliation gate | +| Background completion | Gateway may outlive UI | Not promised for direct mobile | Host-owned request may reconcile | +| Thread persistence | Native macOS store | Native durable mobile store | Not host-owned | +| Local discovery | Not a client feature | Deferred to v0.2.1 | Bonjour plus manual endpoint | +| Pairing/trust | Future host service | Deferred to v0.2.1 | Revocable device credential | +| Remote account control | Loopback desktop UI only | Not permitted | Not permitted | +| Tools/filesystem/shell | Not exposed by Chat | Explicit non-goal | Explicitly denied | + +## Deployment floors + +- macOS remains 14 or later. +- iOS and iPadOS begin at 18 or later. +- Foundation Models is independently gated by compile-time API availability and + the live `SystemLanguageModel` availability state. The base mobile app does + not require a Foundation Models-capable OS or device. + +## Execution-boundary examples + +| Destination | Boundary rendered on iPhone/iPad | +| --- | --- | +| Apple On-Device on this iPhone | On device | +| OpenAI Platform called by iPhone | Hosted | +| Qwen running locally on Tom's Mac | Local network; Mac local | +| ChatGPT through Tom's Mac | Hosted via Tom's Mac | + +## Governing documents + +- WF-ADR-0047 — product independence and optional pairing +- WF-ADR-0048 — routing-core ownership and embedding +- WF-DESIGN-0019 — provider/auth/credential framework +- WF-ROADMAP-0016 — delivery and acceptance gates +- WF-DESIGN-0017 — current macOS Foundation Models topology +- WF-DESIGN-0018 — current macOS ChatGPT/Codex topology diff --git a/docs/qualifications/WF-QUAL-0001-kimi-account-auth.md b/docs/qualifications/WF-QUAL-0001-kimi-account-auth.md new file mode 100644 index 00000000..eb6f7cdd --- /dev/null +++ b/docs/qualifications/WF-QUAL-0001-kimi-account-auth.md @@ -0,0 +1,74 @@ +--- +schema_version: 1 +id: WF-QUAL-0001 +type: provider-qualification +status: blocked-pending-provider-approval +date: 2026-07-24 +tags: [kimi, oauth, device-code, account, ios, provider] +--- + +# Kimi account authentication qualification + +## Decision + +Kimi account authentication is **blocked pending provider approval**. + +Wayfinder v0.2.0 may implement Moonshot/Kimi Platform API-key support. It must +not display or ship “Sign in with Kimi” until the unresolved gates below are +closed with provider-owned documentation or written approval. + +## Verified public evidence + +As checked on 2026-07-24: + +- Kimi Code documents `kimi login` as an RFC 8628 device-code flow. +- The command requests a device authorization, presents a verification URL and + user code, polls until completion, and persists the resulting token for the + Kimi Code client. +- Kimi documents Kimi Code membership separately from the Kimi Platform API. +- The official Kimi Code repository is publicly available. + +This proves that Kimi operates an account-authenticated first-party CLI flow. It +does not prove that: + +- third-party clients may use the same client identifier; +- Kimi Code membership authorizes Wayfinder model execution; +- the token audience/scopes authorize a documented general model endpoint; +- the endpoint, required headers, catalog, refresh, revocation, and usage-limit + contracts are available for a third-party App Store client. + +## Required approval gates + +| Gate | Current result | +| --- | --- | +| Provider-approved Wayfinder client ID or explicit public-client permission | Blocked | +| Documented token audience and scopes for intended model execution | Blocked | +| Documented/approved model and discovery endpoints | Blocked | +| Kimi-specific required headers and client identity contract | Blocked | +| Refresh, revocation, expiry, usage-limit, and account-state contract | Blocked | +| Regional and App Review implications | Blocked | +| Product/legal confirmation that membership permits this client | Blocked | + +## Implementation rule + +No engineer may copy client identifiers, headers, tokens, device identifiers, +or private endpoints from Kimi Code. Wayfinder must identify itself truthfully. +Reverse engineering is not a qualification artifact. + +If approval arrives, implementation still lands after: + +- the generic account framework and fake OAuth server harness; +- device-code pending, slow-down, expiry, denial, cancel, and success tests; +- Keychain and secret-leak tests; +- model catalog and usage-limit fixtures; +- physical-device authorization evidence; +- product copy that distinguishes subscription from API-metered usage. + +## Sources + +- Kimi Code command reference: + https://www.kimi.com/code/docs/en/kimi-code-cli/reference/kimi-command +- Kimi Code membership guide: + https://www.kimi.com/help/kimi-code/membership-guide +- Official Kimi Code repository: + https://github.com/MoonshotAI/kimi-code diff --git a/docs/rust-migration-capability-matrix.md b/docs/rust-migration-capability-matrix.md index dc2f69f3..41569698 100644 --- a/docs/rust-migration-capability-matrix.md +++ b/docs/rust-migration-capability-matrix.md @@ -8,6 +8,9 @@ Rust parity: Phases 1–3 complete; operations, CLI, and distribution gates rema > distribution guidance. WF-ADR-0046 completes the Rust-only cutover, removes the legacy package > and fallback, and sets `gateway_ready: true`. Historical rows below remain migration evidence. > +> Mobile amendment (2026-07-24): WF-ADR-0048 and WF-ROADMAP-0016 govern pure-core extraction and +> native iOS embedding. No Python-era row in this matrix is a mobile requirement. +> > Current Desktop amendment (2026-07-19): this document preserves the 2026-07-11 discovery baseline. > WF-ROADMAP-0015 supersedes its native packaging/default rows for Desktop v0.1.0. The Desktop app > explicitly selects a bundled arm64 Rust gateway with authenticated credential and Foundation diff --git a/macos/README.md b/macos/README.md index 880035b6..75de5bbb 100644 --- a/macos/README.md +++ b/macos/README.md @@ -1,15 +1,17 @@ # Wayfinder Native macOS App This directory contains the shipping native macOS product. Wayfinder Desktop is a thin SwiftUI and -AppKit client over its bundled Rust gateway; the standalone Python distribution remains available -for compatibility and delegated commands during the migration period. +AppKit client over its bundled Rust gateway. Rust is the sole router and gateway runtime under +WF-ADR-0046. + +Native iPhone and iPad work follows a different host topology: v0.2 embeds the shared routing core +and remains independently useful without this app or its gateway. That does not change the current +macOS gateway-first boundary. See WF-ADR-0047, WF-ADR-0048, and WF-ROADMAP-0016. ## Inspection Summary - The bundled Rust implementation lives under `rust/crates/`; `wayfinder-gateway` owns native routing and OpenAI-compatible delivery. -- The Python package remains the compatibility implementation and owns explicitly delegated - commands until the later removal decision. - The macOS app never computes an authoritative route, calls a provider directly, or owns provider secrets. It consumes the bundled gateway contract. - `clients/desktop` is the retained legacy Tauri client, not the current native product. @@ -93,7 +95,8 @@ Recommended path: 1. Keep the native app behind the `WayfinderClient` protocol. 2. Use `GatewayWayfinderClient` as the real source-of-truth integration for menu-bar status, routing mix, and savings data. -3. Keep `LocalWayfinderClient` as a prototype/degraded preview only unless a parity test is added against the Python golden corpus. +3. Keep `LocalWayfinderClient` as a prototype/degraded preview only; it is not an authoritative + route implementation. 4. Avoid storing provider keys in the app. Follow the existing gateway and Keychain pattern from the Tauri client. The first UI patch ran with `MockWayfinderClient` so the menu-bar, chat, and settings surfaces could be shaped without bootstrapping the gateway. The native menu now starts with `AppDelegate(client: GatewayWayfinderClient())` in `Sources/WayfinderMacApp/WayfinderMacMain.swift`. @@ -109,6 +112,8 @@ The first UI patch ran with `MockWayfinderClient` so the menu-bar, chat, and set - Provider-key writes and reads stay behind the existing narrow Keychain and authenticated XPC boundaries. Chat does not broaden either broker. - The bundled gateway remains the routing source of truth, matching WF-ADR-0042. +- Mobile extraction may introduce shared Apple packages incrementally, but v0.2 does not move the + macOS provider, credential, or lifecycle boundaries merely for code uniformity. ## Run diff --git a/roadmaps/WF-ROADMAP-0015-desktop-v0.1.0-release.md b/roadmaps/WF-ROADMAP-0015-desktop-v0.1.0-release.md index 7ab5980f..8bc569f7 100644 --- a/roadmaps/WF-ROADMAP-0015-desktop-v0.1.0-release.md +++ b/roadmaps/WF-ROADMAP-0015-desktop-v0.1.0-release.md @@ -129,7 +129,8 @@ and honest about its supported platform and external provider dependency. - Expanding `WayfinderCredentialBroker` or moving gateway/provider ownership into Swift. - A DMG, Homebrew cask, Sparkle/Tauri updater, Mac App Store package, or automatic promotion. - Standalone package-manager distribution; any future channel needs its own native support contract. -- iOS implementation; that begins as a separate roadmap after the desktop release gate closes. +- iOS implementation; it is governed separately by WF-ROADMAP-0016 and does not change this + desktop release gate. ## Verification record @@ -148,3 +149,4 @@ Repository evidence lives in: - WF-DESIGN-0018 — ChatGPT-authenticated Codex app-server provider - WF-ADR-0042 — thin native desktop client over one gateway - WF-ADR-0045 — Rust gateway/helper architecture +- WF-ROADMAP-0016 — standalone native iPhone/iPad v0.2 diff --git a/roadmaps/WF-ROADMAP-0016-native-mobile-v0.2.md b/roadmaps/WF-ROADMAP-0016-native-mobile-v0.2.md new file mode 100644 index 00000000..16d73294 --- /dev/null +++ b/roadmaps/WF-ROADMAP-0016-native-mobile-v0.2.md @@ -0,0 +1,325 @@ +--- +schema_version: 1 +id: WF-ROADMAP-0016 +type: roadmap +status: accepted +date: 2026-07-24 +tags: [ios, ipados, v0.2.0, v0.2.1, swiftui, rust, routing, providers, pairing] +--- + +# Roadmap: standalone native Wayfinder v0.2 for iPhone and iPad + +## Release thesis + +Wayfinder runs natively wherever the user is. Each Apple device contributes the +capabilities it can legitimately execute; a paired Mac expands the available +set rather than making the mobile app possible. + +The mobile product combines one deterministic router with on-device execution, +direct approved providers, local threads, explicit privacy boundaries, and +optional trusted-host destinations. + +## Status + +Accepted for phased implementation. Phase 0 documentation is the first pull +request. No UI, provider, FFI, or pairing implementation belongs in that PR. + +## Releases + +### v0.2.0 — standalone iOS and iPadOS + +Release-gating scope: + +- native iPhone and iPad app, requiring iOS/iPadOS 18 or later; +- authoritative embedded Rust routing core; +- direct provider execution without a Mac or local gateway; +- API-key credentials held in Keychain; +- generalized account/authentication framework; +- Kimi account auth only if WF-QUAL-0001 becomes approved; +- Apple Foundation Models when the live device reports it available; +- Chat, threads, destinations, settings, route receipts, streaming, + cancellation, recovery, retention, export, and deletion; +- enforced on-device, local-network, and hosted privacy boundaries. + +### v0.2.1 — optional paired Mac provider + +- QR/manual pairing and nearby discovery; +- authenticated encrypted transport and revocable device trust; +- normalized destination/route inventory; +- Mac-owned Chat execution and reconciliation; +- Mac-local and desktop-helper destinations; +- explicit per-host Automatic opt-in. + +Pairing may be developed in parallel but cannot delay or weaken v0.2.0. + +## Product requirements + +### First launch + +Standalone choices lead: + +```text +Welcome to Wayfinder + +Use AI from this iPhone or iPad + +[ Use Apple On-Device ] when currently available +[ Connect an Account ] +[ Add an API Key ] + +More ways to use Wayfinder +[ Connect a Mac ] +``` + +The user may skip every option and enter a useful no-destination state. +Connecting a hosted provider does not itself select Hosted Allowed. + +### Information architecture + +iPhone uses a `TabView` with separate `NavigationStack` state for: + +1. Chat; +2. Threads; +3. Destinations; +4. Settings. + +iPad uses `NavigationSplitView`: threads and shortcuts in the sidebar, +transcript/composer in the primary detail, and an optional route inspector. +Single-window lifecycle is proven before multiwindow support. + +### Destination and receipt truth + +Destinations are grouped as On This Device, Direct Cloud, and Macs. Detail +shows provider/model, boundary, auth, readiness, capabilities, context, billing +class, Automatic participation, and remediation. + +Every terminal turn has a compact receipt: + +```text +Ran on this iPhone · Apple On-Device +Ran in hosted cloud · Kimi API · score 0.71 +Ran on Tom's Mac · Qwen 3 · local network +``` + +Receipts do not become large inline dashboards. + +## Native runtime topology + +```text +SwiftUI + -> AppModel / NativeWayfinderRuntime + -> ConversationStore + -> ProviderRegistry + -> CredentialStore + -> embedded wayfinder-routing-core + -> Swift and/or portable provider adapters + -> Apple Foundation Models actor + -> direct hosted providers + -> optional PairedHost provider +``` + +The app runs no internal localhost server. Views consume snapshots and never +call providers or Keychain directly. + +## Routing contract + +Eligibility precedes scoring. Exclusions include: + +- provider not ready, signed out, expired, or usage limited; +- denied privacy boundary; +- missing network; +- unsupported platform, context, modality, or tools; +- explicit route deny; +- removed model; +- unavailable paired host. + +`Automatic` filters candidates, scores with the shared core, maps the result to +the configured route/tier, chooses the first ready destination using stable +tie-breaks, and emits a receipt. + +A pinned destination never falls back. Automatic falls back only inside the +configured route and privacy posture, and only before response content begins. +Cancellation is not provider-health failure. + +## Phase 0 — source of truth and risky seams + +Deliverables: + +- WF-ADR-0047: independent mobile product and optional pairing; +- WF-ADR-0048: shared routing-core ownership and native embedding; +- WF-DESIGN-0019: provider, account, OAuth, Keychain, and execution boundaries; +- this roadmap and the Apple-platform capability matrix; +- Kimi qualification note; +- supersession links from current macOS, Rust, Apple, ChatGPT, and old mobile + planning documents; +- UniFFI versus generated C ABI bridge spike; +- Rust HTTP versus Swift `URLSession` execution spike; +- SwiftData versus SQLite persistence spike. + +Exit: + +- no current document describes mobile as companion-only; +- ownership of routing, credentials, providers, Apple calls, persistence, and + pairing is explicit; +- simulator and physical-device prototypes score a prompt through the shared + core; +- Kimi remains classified as approved, API-key-only, or blocked. + +## Phase 1 — extract the portable routing core + +- isolate pure routing and runtime-contract crates; +- remove host/server assumptions from route planning; +- add typed request, candidate, plan, explanation, and receipt contracts; +- share the golden corpus between gateway and bridge; +- add gateway-versus-embedded parity; +- assemble iOS static library/XCFramework output. + +Exit: identical fixtures produce identical decisions/reason codes through both +hosts; no Swift routing implementation exists; simulator and device targets +build. + +## Phase 2 — native shell and local data + +- create iPhone/iPad Xcode targets; +- add adaptive navigation and root `AppModel`; +- implement the selected conversation store, draft restoration, retention, + export/delete seams, and migrations; +- add deterministic mock providers; +- implement the Chat state machine without live providers. + +Exit: the app launches with no Mac/gateway; primary states render on iPhone and +iPad; lifecycle, restoration, cancellation UI, and accessibility tests pass. + +## Phase 3 — Keychain and direct API providers + +- implement `CredentialStore`; +- API-key lifecycle UI; +- generic OpenAI-compatible direct provider; +- OpenAI Platform, Moonshot/Kimi Platform, and OpenRouter presets; +- streaming, cancellation, bounds, timeout, retry classification, usage, and + model inventory; +- eligibility updates from provider snapshots. + +Exit: add key, discover/configure model, route, stream, stop, retry, remove key, +and prove no secret leakage; Automatic works with two direct destinations. + +## Phase 4 — generalized account providers + +- normalized account state and challenge UI; +- PKCE authorization-code and RFC 8628 device-code engines; +- fake OAuth server harness; +- refresh, reauthentication, usage-limit, and sign-out; +- model discovery and destination publication; +- Kimi adapter only if WF-QUAL-0001 is approved. + +Exit: physical-device lifecycle passes; tokens remain in Keychain; cancelled, +expired, and denied flows leave no partial credential; account connection does +not mutate routes. + +## Phase 5 — Apple Foundation Models + +- native availability and execution actor; +- capability/context discovery, buffered generation, streaming, cancellation; +- deterministic fake provider for CI; +- on-device-only posture and no-egress tests; +- physical-device availability and prompt-version evidence; +- contract reconciliation with the existing macOS provider. + +Exit: an eligible device completes Chat with network unavailable; ineligible +states are truthful; On-Device Only cannot egress; receipts identify +on-device execution. + +## Phase 6 — integrated routing and product polish + +- destination inventory/detail, route editor, privacy control, receipts, and + inspector; +- no-provider, single/multi-provider, expired auth, offline, usage-limited, and + Apple-unavailable state matrix; +- Dynamic Type, VoiceOver, keyboard/iPad, Reduced Motion, contrast, and + screenshot review. + +Exit: all v0.2.0 acceptance criteria pass and no release path or screenshot +requires a Mac. + +## Phase 7 — paired Mac provider + +- one-time challenge, QR/manual discovery, shared verification value; +- device-bound credentials, host records, revocation, encrypted authenticated + transport; +- least-privilege inventory and request APIs; +- streaming, cancel, and resume reconciliation; +- truthful local-Mac versus cloud-via-Mac receipts; +- explicit route and Automatic participation. + +Exit: removing the Mac leaves mobile intact; no provider credentials cross; +revocation works; remote clients cannot access account control, files, tools, +shell, or raw logs. + +## Phase 8 — release hardening + +- privacy manifest/disclosures; +- physical-device matrix and adversarial network/auth tests; +- install/update/rollback/migration evidence; +- crash, memory, launch, and binary-size budgets; +- TestFlight external plan and support/recovery docs. + +## Pull-request sequence + +1. docs/ADRs/roadmap/capability/qualification; +2. routing-core extraction; +3. Apple FFI/XCFramework; +4. iOS shell; +5. conversation store; +6. credential store; +7. generic direct provider; +8. provider presets; +9. OAuth engines with fake server; +10. qualified Kimi adapter, if approved; +11. Apple Foundation Models; +12. integrated routing UI; +13. pairing trust protocol; +14. PairedHost inventory/execution; +15. release hardening. + +Core extraction, new auth, Apple execution, and pairing never share one PR. + +## v0.2.0 acceptance + +1. A user completes a real conversation without owning or pairing a Mac. +2. The shared Rust core makes the authoritative route. +3. One direct API provider streams and cancels end-to-end. +4. Secrets exist only in Keychain and are absent from ordinary logs/app data. +5. Foundation Models works on an eligible device and degrades truthfully. +6. Automatic chooses across on-device/hosted while enforcing capabilities and + privacy. +7. On-Device Only cannot send content to cloud or a paired host. +8. Connecting providers never silently changes `Automatic`. +9. A pinned unavailable destination fails without fallback. +10. Threads, drafts, replies, failures, and receipts restore correctly. +11. Backgrounding never duplicates a turn or claims false completion. +12. iPhone/iPad layouts pass accessibility and state-matrix review. +13. No companion-only language or disabled host-only controls ship. +14. Existing macOS routing, keys, Chat, Apple, and ChatGPT behavior remains + compatible. +15. Privacy manifest and product copy match actual behavior. + +Kimi account auth is optional and does not gate the release. + +## Explicit exclusions + +- requiring a Mac or running the desktop gateway/helper on iOS; +- importing tokens from CLIs, browsers, ChatGPT, Kimi, or filesystem state; +- undocumented subscription access or downloadable executable connectors; +- an always-running mobile gateway/background daemon; +- cloud egress described as local because transport first reached a Mac; +- tools, shell, filesystem, MCP, browser automation, or agent approvals; +- CloudKit before retention/conflict/encryption/deletion are specified; +- replacing macOS gateway-first architecture for uniformity. + +## Related + +- WF-ADR-0047 +- WF-ADR-0048 +- WF-DESIGN-0019 +- `docs/apple-platform-capability-matrix.md` +- `docs/qualifications/WF-QUAL-0001-kimi-account-auth.md` diff --git a/roadmaps/v0.2.0-wayfinder-chat.md b/roadmaps/v0.2.0-wayfinder-chat.md index 775c62e5..f868f716 100644 --- a/roadmaps/v0.2.0-wayfinder-chat.md +++ b/roadmaps/v0.2.0-wayfinder-chat.md @@ -9,7 +9,12 @@ tags: [v0.2.0, wayfinder-chat, librechat, gateway, routing] ## Status -Planned +Superseded by WF-ROADMAP-0016. + +This file is retained as historical evidence for the earlier LibreChat-fork +direction. It does not govern Wayfinder product version v0.2.0. Native iPhone +and iPad apps, embedded shared routing, direct providers, Apple on-device +execution, and optional later Mac pairing are governed by WF-ROADMAP-0016. The direction is decided in WF-ADR-0010. This roadmap sequences the first milestone. It spans **two repositories** and therefore two version lines: diff --git a/rust/README.md b/rust/README.md index 6f9c5263..2525ecb7 100644 --- a/rust/README.md +++ b/rust/README.md @@ -1,65 +1,61 @@ -# Wayfinder Rust migration workspace +# Wayfinder Rust workspace -This is the additive, parity-gated Rust implementation selected by WF-ADR-0045. Desktop v0.1.0 -explicitly selects this gateway as the arm64 helper embedded in `Wayfinder.app`. The independently -distributed router keeps Python as its compatibility oracle and retained fallback. The -`gateway_ready: false` handshake remains conservative cross-distribution migration metadata; it -does not override the Desktop product's explicit verified-helper selection. +Rust is Wayfinder's sole production router and gateway runtime under +WF-ADR-0046. This workspace contains: -## Verified checkpoint (2026-07-11) +- `wayfinder-core` — deterministic feature extraction, scoring, tiers, and + explanations; +- `wayfinder-config` — typed routing/gateway configuration and preserved + mutations; +- `wayfinder-providers` — bounded provider clients and streaming translation; +- `wayfinder-gateway` — Axum data plane, policy, reliability, limits, metrics, + and provider orchestration; +- `wayfinder-service` — service units, pricing/ledger logic, and secret seams; +- `wayfinder-cli` — the `wayfinder-router` executable; +- macOS XPC clients for credentials and Apple Foundation Models; +- checked fixtures retained as immutable migration evidence. -- `wayfinder-core` implements deterministic feature extraction, scoring, explanations, tiers, - classifier inference, schema-version-3 decisions, and all ten stock lexicon profiles. -- `wayfinder-config` implements routing and gateway TOML discovery, parsing, validation, emission, - and line-preserving supported mutations. Strict ascending tier order matches the current Python - product contract; legacy sorting remains available only for explicit migration tooling. -- `wayfinder-gateway` provides bounded Axum health, metrics, model/profile/recent/savings/config, - dry-run/decision-only chat, and buffered OpenAI-compatible delivery. Request-scoped tuning, - route scope, sticky routing, slash directives, offline fail-closed delivery, prompt-free recent - state, in-memory cost accounting, constant-time virtual-key authentication, model allowlists, - global/per-key RPM and TPM, global/per-key spend budgets, rate and budget headers, key - attribution, the opt-in bounded exact-response cache, and buffered retry/fallback/circuit-breaker - delivery are covered. Buffered Anthropic `/v1/messages` and `/messages` requests reuse that same - chat path. Request-atomic last-good config reload, bounded graceful drain, and real-process HTTP - lifecycle coverage complete the Phase 2 skeleton. Phase 3 adds pre-commit upstream status - handling, pre-first-byte plan failover, cancellation-safe OpenAI SSE, and incremental Anthropic - Messages SSE translation. Several operational policies are not yet fully parity-gated, so this is - not a replacement gateway. -- `wayfinder-providers` provides a hardened Reqwest buffered client, bounded SSE decoding, - reliability policy primitives, and buffered plus streaming Anthropic translation. Streaming - translation is tested as a state machine but is not yet connected to the HTTP transport. -- `wayfinder-service` provides deterministic pricing/ledger logic, bounded legacy command-secret - resolution, and byte-compatible launchd/systemd unit rendering. -- `wayfinder-cli` implements `route`, real `serve`, `service install|uninstall|status`, the bounded - Desktop setup/config operations, and the versioned capability handshake. `config read-routing` - and `config apply-routing` are native; other coexistence config actions remain Python-delegated. - Environment credentials take precedence over bounded startup `api_key_cmd` compatibility values; - neither path serializes or logs the secret. -- `wayfinder-compat-tests` currently passes ten integration tests covering 21 Python golden - prompts, eight routing boundaries, 32 routing-config cases, 74 gateway-config cases, 20 ordered - HTTP exchanges, and byte-exact service-unit output. The seeded differential runner has also - passed 506 generated prompts. +The runtime never launches or delegates to Python. Unsupported legacy commands +fail closed. -Focused checkpoint evidence: +## Build and test ```sh cargo fmt --manifest-path rust/Cargo.toml --all -- --check -cargo clippy --manifest-path rust/Cargo.toml --workspace --all-targets \ - --all-features --locked --offline -- -D warnings -cargo test --manifest-path rust/Cargo.toml -p wayfinder-compat-tests \ - --all-features --locked --offline -cargo test --manifest-path rust/Cargo.toml -p wayfinder-providers \ - --locked --offline anthropic::tests -cargo audit --file rust/Cargo.lock --no-fetch +cargo test --manifest-path rust/Cargo.toml --workspace --all-features --locked +cargo clippy --manifest-path rust/Cargo.toml \ + --workspace --all-targets --all-features --locked -- -D warnings ``` -The complete workspace suite contains temporary-loopback tests and therefore needs permission to -bind local sockets in restricted environments. `cargo-audit` is installed and the current lockfile -has no known advisory; `cargo-deny` and the x86_64 macOS target are still unavailable locally. +Build the executable: -## Standalone migration remains parity-gated +```sh +cargo build \ + --manifest-path rust/Cargo.toml \ + --package wayfinder-cli \ + --bin wayfinder-router \ + --locked +``` + +## Apple-platform direction + +Wayfinder Desktop continues to embed `wayfinder-router` as a separately running +signed helper. Native iPhone and iPad v0.2 does not run that executable or an +internal HTTP server. + +WF-ADR-0048 extracts a pure `wayfinder-routing-core` and typed runtime contracts +from this workspace. The gateway and generated Swift bridge will consume the +same core and golden fixtures. The pure core may not perform filesystem, +Keychain, process, provider, HTTP-server, UI, or Apple-framework work. + +The extraction, bridge/XCFramework, provider execution choice, iOS shell, auth, +Apple model, and pairing remain separate pull requests under +WF-ROADMAP-0016. + +## Governing documents -The broader standalone migration still requires retained/delegated CLI decisions and complete -cross-platform evidence before Python removal. Desktop v0.1.0 has a separate Apple Silicon-only -release gate in WF-ROADMAP-0015; x86_64 and universal packaging are future claims, not blockers for -that release. +- `decisions/WF-ADR-0046-rust-only-runtime.md` +- `decisions/WF-ADR-0048-shared-routing-core-apple-embedding.md` +- `roadmaps/WF-ROADMAP-0014-rust-gateway-migration.md` +- `roadmaps/WF-ROADMAP-0016-native-mobile-v0.2.md` +- `docs/apple-platform-capability-matrix.md`