* docs(mobile): capture Connect Mobile design (CONTEXT, ADR, plan) + scope loopback rule (cherry picked from commit 0d3642ec4806faf6d24bbddb00220819d362723b) * feat(mobile): mobilebridge config store + rotating password (cherry picked from commit f2617934cac9f2d681e522c92a380fcc60e8a90b) * feat(mobile): autopick private LAN IPv4 (cherry picked from commit e030474bceff8322cf2a7e814e0a560db1cd8c54) * feat(mobile): bearer auth middleware with per-source lockout (cherry picked from commit 461d3c22be4441e6405286979f3e7b371cb171ae) * feat(mobile): test lockout is per-source (never global) (cherry picked from commit 47e7d9770511c863ad5bd724386e8ab774661700) * feat(mobile): runtime-controlled LAN listener manager (cherry picked from commit a10fd4b6e460f234107a89c4d0fad92932b40bf0) * feat(mobile): mobile control endpoints + bridge service (cherry picked from commit c0bb792f040344a5597fd3190ff035c51a988edf) * feat(mobile): mount loopback-gated mobile control routes + regen API (cherry picked from commit 376b5f1b9041392feb03bff65f8ec85353b9f076) * feat(mobile): wire LAN listener into daemon with restore-on-boot (cherry picked from commit 1a65adbf058db1606d9f8df4c3c794387e08e7dc) * fix(mobile): bound LAN listener shutdown ctx; assert restore happy path (cherry picked from commit a2c051bcff9d1ccf19f1e39d84900d2e69a957aa) * feat(ui): add shadcn dialog primitive (cherry picked from commit 27e690005362a34af9c1d5c41313a4076749bdcd) * feat(mobile): desktop Connect Mobile modal with QR, password, warning (cherry picked from commit 33df1d0fb86a114ce849eb8bdd2e1d672933d445) * feat(mobile): send Authorization bearer on REST + mux (cherry picked from commit b4322a4d2397f07977b8f54fae4fb8a14f949297) * feat(mobile): QR scan pairing + password popup (cherry picked from commit 42d8624efc368eec10e2c7dfed2819a69c318956) * docs(mobile): scope loopback-only rule to loopback listener; document LAN listener (cherry picked from commit 03fd7ac3fdf86566838b5d19d138e58988c88d6d) * fix(mobile): block loopback-only control routes on the LAN listener (cherry picked from commit 0d721a6a4fd448547441631363955aa397f4186d) * fix(mobile): let the desktop renderer reach the mobile control routes The mobile control routes were gated by localControlRequest, which rejects any request carrying an Origin header. The desktop renderer is a browser context and always sends an Origin, so every enable/disable/status call from the desktop got a 403. Drop that gate: the loopback listener protects these routes via CORS like every other API route, and the phone is already blocked from them on the LAN listener by lanControlBlock (a transport-based 404 that cannot be spoofed). (cherry picked from commit 0fbddfecd7bd4b89599d941014f29b83e83cdf13) * feat(mobile): persist the connection password so the desktop can show it State stored only the password hash, so GET /mobile/status returned an empty password and the desktop modal could not display it. Persist the 8-char password in plaintext in ~/.ao/mobile/config.json (0600) and return it from status while the bridge is enabled; derive the auth hash in memory (HashPassword). Restore on boot re-derives the hash from the persisted plaintext, so a paired phone keeps working across restarts with no rotation. (cherry picked from commit 1ff0c35059f2cb4503407507e3af20f714a0f580) * fix(mobile): reset the per-source lockout counter when the cooldown expires Previously the fail counter was only cleared on a successful auth, so after the 60s cooldown the very next failure re-locked immediately for another full minute — and a client that keeps polling with a bad password would stay locked out forever. Clear the counter (and prune the entry) once the cooldown elapses, so each source gets a fresh 5-attempt window. (cherry picked from commit eeb7bd30a7ff42e00037a1232a8a424d231e000a) * feat(mobile): move Connect Mobile to the sidebar Settings menu; toggle modal Connect Mobile is now its own item in the sidebar Settings dropdown (its own section above Project/Global settings, in both expanded and collapsed menus) instead of a card on the Global Settings page. The modal is redesigned around a single 'Enable mobile' toggle: flipping it on starts the bridge and reveals the pairing details (QR, address, password + copy, warning, regenerate) below the toggle row; off tears it down. The QR now encodes the password too, so one scan connects with no typing. Adds a shadcn Switch primitive; removes the old ConnectMobileButton card. (cherry picked from commit 36c617d18573efbf8ba3454ee8bd2e3a965e28ed) * feat(mobile): scan-to-connect and hardened connection UX - Parse the password from the pairing QR and, on scan, save host/port/password and reconnect — one scan connects with no typing. - 'Save' now behaves like connect: it prompts for the password when empty and reports the result, so it can no longer persist a passwordless config silently. - Reload the server config on screen focus so returning from the scanner repaints the fields. - Stop the background poller on an auth failure (401/429) instead of hammering — a bad password otherwise kept the daemon's lockout armed forever. - Clear a stale error banner once the connection goes live. (cherry picked from commit 7cf5db29bd23c4fa9af9c1b3a68dbac399c5f10d) * chore(mobile): drop fork-only shared API schema (upstream generates to frontend/src/api) * chore(mobile): sync lockfiles for qrcode.react (desktop) and expo-camera (mobile) * fix(mobile): store connection password in SecureStore, not AsyncStorage The Bearer secret authorizes terminal input, spawn/kill and PR actions, but was persisted inside the AsyncStorage config blob (unencrypted app sandbox). Split it into expo-secure-store (iOS Keychain / Android Keystore) and keep AsyncStorage for the non-secret host/port/TLS config. loadConfig migrates any legacy password out of the blob on first read. * fix(mobile): roll back LAN listener when enable fails to persist enableWithPassword armed the new hash and opened the 0.0.0.0 listener before saving durable state. If mobilebridge.Save failed, the endpoint returned 500 but the LAN listener stayed live with the new password while persisted state and the UI still reported the bridge as disabled — a network-exposed control surface no state tracked. Snapshot the prior hash and running state, then on the error paths undo the in-memory side effects: restore the hash on a Start failure, and on a Save failure stop a freshly-started listener (a rotate on an already-running listener keeps serving on the prior hash). Add PasswordHash() to LANController for the snapshot and a regression test for the Save-failure rollback. * fix(mobile): satisfy gofmt, golangci-lint, and Prettier CI - gofmt: auth.go, auth_test.go, netiface_test.go - golangci-lint: add doc comments on exported mobile-bridge / LAN-listener symbols (revive), check the LAN listener TCPAddr assertion and drop os.Remove/tmp.Close returns (errcheck), and justify the deliberate 0.0.0.0 bind (G102) and password persistence (G117) with nolint - Prettier: format the 6 changed docs/frontend/mobile files |
||
|---|---|---|
| .. | ||
| adr | ||
| assets/readme | ||
| cli | ||
| plans | ||
| screenshots | ||
| superpowers/plans | ||
| README.md | ||
| STATUS.md | ||
| ao-start-bootstrapper-and-npm-deprecation.md | ||
| architecture.md | ||
| backend-code-structure.md | ||
| daemon-environment.md | ||
| stack.md | ||
| telemetry.md | ||
README.md
agent-orchestrator rewrite docs
The agent-orchestrator is being rebuilt as a long-running Go backend daemon
(backend/) plus an Electron + TypeScript frontend (frontend/). The backend
supervises coding-agent sessions and exposes daemon control, project/session
state, terminal streaming, and CDC/event infrastructure.
Start with architecture.md for the current backend model and
cli/README.md for the CLI surface.
Reference docs
| Doc | What it covers |
|---|---|
| architecture.md | Current backend model, package layout, status derivation, persistence/CDC, and load-bearing rules. |
| backend-code-structure.md | Package ownership rules for the Go backend: domain, services, ports, adapters, storage, HTTP, CLI, and daemon wiring. |
| cli/README.md | CLI commands and daemon control surface. |
| STATUS.md | What is shipped on main today and what is still in flight. |
| stack.md | Accepted library/runtime choices, pending stack decisions, and dependencies explicitly avoided for V1. |
Mental model
Persist durable facts, derive display status:
- session table:
activity_state,is_terminated, identity, metadata - PR tables: PR/CI/review facts
- derived read model:
service.Sessioncomputes display status from session + PR facts