Skip to content

Integrate remote sessions and native agent approval notifications - #50

Merged
guohai merged 14 commits into
mainfrom
feat/push-approvals
Oct 17, 2026
Merged

guohai merged 14 commits into
mainfrom
feat/push-approvals

Conversation

@guohai

@guohai guohai commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Astation discovers and controls Claude/Codex sessions through Atem's authenticated registry and reviews r7 approval requests in a native inbox. Recovery now opens a fresh transport instead of sending a second hello, and an opt-in local HTTP API lets scripts exercise the same session, approval and durable receipt paths without a mobile UI.

This consolidates closed #49 and native approval work against main. Protocol, host handoff and shared fixtures pin Atem #72 at 6edda2490f4a4b7634edb446f64aa02748e29fa2 (atem-session r7.1). No Atem checkout was edited or built.

Changes

  • One verified native session client per host serves Connections, terminals and approvals. The registry supplies full target/process/workspace/capability/activity data. Pairing-room credential handoffs never become online Atem rows.
  • Session dots follow process state: running is green even when activity is unknown. Activity is labeled Idle / Working / Waiting / Unknown independently; stopped processes stay unavailable.
  • Native terminals support input/paste, resize, scrolling and explicit control/release. Choosing another agent automatically opens its terminal in viewing mode and releases previous control; late replies cannot switch back to the old session. View remains a retry/reload action. Cmd+V cancels WebKit default handling so it dispatches once. Standard Edit/right-click clipboard actions follow focus; toolbar Paste & Go submits to the selected terminal with one bounded, epoch-guarded paste plus Enter. Empty, oversized, stale and read-only pastes send no Enter, and focus reports remain separate. Owner authentication supports Touch ID and password fallback. Claude supports structured prompts; Codex uses terminal input.
  • Full target/attachment binding, expiring control leases, local takeover and durable receipt recovery. Reconnect queries original requests without replaying effects or inheriting control.
  • Sleep closes transports and fences authority; wake reauthenticates before hello. Retry Session Connection reconnects its transport. Post-welcome unauthorized reconnects once; an initial refusal stops without an automatic loop or misleading verification instruction. A local relay socket generation fences unchanged host connection ids. r7.1 replacement hello is pinned; recreated-client coverage checks same-link replacement, old-grant fencing, durable receipt recovery and original authorization expiry. Retry still reconnects a broken transport.
  • Native approval inbox, stale-card fencing and independent in-app/offline-push preferences. Allow once, exact offered Claude Always allow and Deny use durable atomic approval submissions with acquire:true. Push hints grant no authority.
  • Optional local API for sessions, control, prompts/interrupts, exact-snapshot approval answers and scoped receipts. Disabled by default; requires loopback, a protected same-user bearer file, no browser Origin, bounded JSON and no caching/CORS. Caller UUID retries return the existing request; changed bytes are refused. No enrollment or skip-verification API.
  • APNs token registration, Postgres persistence, generation-fenced invalidation, APNs/FCM provider adapters and notification reconciliation. Host ingress/account-wide dispatch remains gated.
  • Review of Atem #70 records unresolved signed-byte, enrollment/fork and removed-manager freshness issues. A joint host push-proof draft binds authorized host keys, nonce/socket identity, signed events, recipient authority and durable outbox invariants. VisualizeRequest/VisualizeResult are already absent from Astation.

Validation

For this revision:

  • Full Swift suite: 907 tests, 11 environment-dependent skips, zero failures. All ten actual WebKit renderer tests pass, including Cmd+V single dispatch, native Edit/context-menu paste, bracketed Paste & Go, separate focus reports and rejection without a stray Enter. Session/API/approval coverage includes the actual HTTP listener's opt-in/authentication/browser/body-limit behavior. Physical Claude clipboard and selector retesting remain live checks. All 27 focused terminal-controller/session tests pass, including automatic switching from control, late attachment/screen fencing and selection during a list refresh.
  • Relay push-related tests: 16 passed; two database integration tests ignored without their fixture. Provider transports are injected; this does not establish live Apple/Google delivery.
  • Debug build and personal-team provisioned packaging pass strict deep signature, protected Keychain identity and bundled transcription/terminal resource checks. The canonical Astation Local.app is running with its authenticated local API. Bundle identifier, signing team, protected Keychain group and saved pairings are retained.
  • Live Genie discovery completes hello -> welcome -> list -> sessions and shows the existing Claude and Codex joint-test sessions, with one online Atem. A harmless Claude print-only prompt gets a completed receipt; identical UUID retry returns the original request, altered bytes are refused and control is released. The prompt emitted no approval card, so the live permission/answer matrix is still pending.
  • Live disconnect during execution: the original delayed-prompt receipt recovered as completed after quitting/relaunching the provisioned app; both agents stayed running and control was not restored. Pausing renewals for 17 seconds cleared host/client control without sending agent input. The exact accepted-before-executing race and a deliberately delayed renewal reply remain joint timing tests.
  • The r7.1 replacement-hello fixture requests decode/round-trip with a UUID substituted for ${gen2}; all three side:client shared scenarios run against the actual Astation client. Host-only dispatch counters, stale-binding admission and replacement rate limiting still require Atem's host runner; no host conformance claim is made from wire/client tests.
  • Deterministic approval coverage includes independent delivery, exact Claude rules, Codex restrictions, atomic answers, duplicate/closed-first catch-up, context/process changes, reconnect receipt recovery, persistence failure, outcome uncertainty, local input and expiry.

Follow-up Work

Outstanding live acceptance checks, native structured chat/session APIs, multi-device trust and offline push integration are tracked in issue #52. Attachment support remains in issue #51. Browser/account-wide access and host push ingress remain gated in this implementation.

The joint session matrix separates automation from confirmed live results. Full terminal UI/local-input races, interrupt/stop, exact acceptance/disconnect timing, a delayed renewal reply and coordinated unpair/re-pair/verify remain live checks. Existing agents and pairings are retained.

Atem must stage permission-triggering Claude/Codex prompts for the live allow/deny/rule/race/expiry matrix. The local installed Atem is 0.6.9, older than the required PR #72 host. No live approval was answered during this check.

Account-wide enrollment, signed membership/freshness, multiple native controllers, secure browser/QR companions and live channel E2EE remain under the joint security gate. The #70 proposal cannot yet guarantee its stated 24-hour revocation bound against a removed manager signing an old head with fresh nonces. The review/proof documents require joint agreement before enabling those paths.

Offline APNs additionally needs an eligible push-enabled profile, provider credentials, authenticated host proof, authorized recipients and a durable revocation-aware outbox. The current free Personal Team profile has no APNs entitlement. In-app alerts work independently. Phone access, account-wide push and live APNs delivery are not claimed.

No production merge or deployment is included. Memory writes are refused for an account encryption-mode mismatch; the new attachment TODO was not found after the refusal. Use the hosted handoffs and follow-up issue #51 for durable coordination. Issue #51 covers images/audio/PDFs/other files in the separate composer; attachment implementation is outside this PR.

Handoffs

Generated with SMT smt@agora.build

Adopt the published typed host protocol, history and turn lifecycle; bind browser and terminal control to authenticated endpoints and process generations. Preserve the existing native terminal and owner-authentication work while integrating it with current webapp hosting.

🤖 Built with SMT <smt@agora.build>
Limit serialized conversation data to 16 MiB and add native and browser regressions for messages containing many empty parts.

🤖 Built with SMT <smt@agora.build>
Bind native remote terminals to authenticated r5 targets, attachments and expiring control leases. Persist request recovery metadata before submissions, query receipts after reconnect without replay, and gate legacy browser chat when a socket upgrades. Add strict JSON/JCS decoding, shared Swift/JavaScript fixture coverage, lifecycle invariants and the Atem owner integration handoff.

🤖 Built with SMT <smt@agora.build>
Link the stacked draft review to its implementation commit and document the relay encryption-mode rejection so the Atem owner uses the published handoff for coordination.

🤖 Built with SMT <smt@agora.build>
Document the successful macOS, relay and webapp checks for the native implementation commit while retaining the local test-environment limits and joint host integration gate.

🤖 Built with SMT <smt@agora.build>
Record that PR 49 targets main and retains both commits from superseded PR 48, with live Atem integration still required before release.

🤖 Built with SMT <smt@agora.build>
Pin the r6.2 contract and shared fixtures, share one authenticated registry client per host, remove legacy outgoing paths, and handle per-attachment resets and family refusals without replay. Document lifecycle invariants, validation limits and the live host handoff.

🤖 Built with SMT <smt@agora.build>
… delivery

Add durable device token registration, APNs/FCM provider adapters, native opt-in and transport reconciliation, and provisioning documentation. Keep host ingress, member fanout and approval decisions gated on authenticated host/membership proofs and the r7 contract.

🤖 Built with SMT <smt@agora.build>
Use a server-computed SHA-256 digest for token uniqueness so supported 4 KiB FCM tokens fit PostgreSQL indexes. Exercise persistence and reassignment at the maximum length in the isolated database test.

🤖 Built with SMT <smt@agora.build>
@guohai guohai changed the title feat(approvals): prepare native push registration and APNs/FCM delivery Integrate r6.2 remote agent control and push notification transport Oct 17, 2026
@guohai
guohai changed the base branch from feat/session-multiplexing to main October 17, 2026 01:52
Integrate the r7 approval inbox and atomic, durable answers independently of APNs. Preserve separate in-app and offline push preferences and document the remaining offline delivery gates.

Show session connection failures, allow an explicit retry of an unauthorized hello before any accepted welcome, and keep pairing-room sockets out of the online Atem registry.

Validate with 879 Swift tests, 11 environment-dependent skips and no failures; provisioned local discovery shows both Genie sessions.

🤖 Built with SMT <smt@agora.build>
@guohai guohai changed the title Integrate r6.2 remote agent control and push notification transport Integrate remote sessions and native agent approval notifications Oct 17, 2026
…on API

Reconnect before retrying hello, fence sleep and stale sockets, and exercise approvals through the native client and durable journal. Document the account-trust review and proposed host push proof.

🤖 Built with SMT <smt@agora.build>
Record shared fixture provenance, attachment recovery coverage, and live disconnect and lease-expiry results.

🤖 Built with SMT <smt@agora.build>
Cancel WebKit clipboard defaults after xterm shortcuts, keep normal paste focused and unsubmitted, and replace toolbar Copy/Paste with a guarded Paste & Go action. Cover native Edit/context menus, bracketed paste, ownership limits and focus reports with actual WebKit regressions. Document attachment-composer follow-up #51 and current validation.

🤖 Built with SMT <smt@agora.build>
Release the previous session and subscribe to the selected process in viewing mode. Preserve selection through pending registry refreshes, ignore late attachments and retain View for explicit retry. Add switch and control-isolation regressions and update terminal docs.

🤖 Built with SMT <smt@agora.build>
@guohai
guohai marked this pull request as ready for review October 17, 2026 08:04
@guohai
guohai merged commit 9e18407 into main Oct 17, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant