Skip to content

feat: add local Orchestra Console - #178

Open
tbrownio wants to merge 8 commits into
mainfrom
gui
Open

feat: add local Orchestra Console#178
tbrownio wants to merge 8 commits into
mainfrom
gui

Conversation

@tbrownio

@tbrownio tbrownio commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a loopback-only Orchestra Console for observing daemon health, runs, sub-agent timelines, MCP servers, skills, and harnesses; safely previewing and confirming a bounded set of daemon operations; and managing fixed-interval declarative agent loops.

This replaces routine SSH-only inspection and configuration work while preserving the local machine trust boundary: the console binds only to 127.0.0.1, rejects invalid Host/Origin/CSRF contexts before reading mutations, never exposes stored secrets, and offers no arbitrary command surface. The daemon remains the authority for execution, capacity, recovery, and audit state.

Done means: a logged-in Mac Mini user can use http://localhost:8790 to observe and safely operate the daemon, while remote URL access, arbitrary execution, synthetic Linear traffic, and unbounded scheduling remain impossible.

Visual overview

Approved console direction used to implement the local control plane:

Approved Orchestra Console overview

After-shots: landing with the QA drive.

User journeys

J1 — Observer: open the local console, understand aggregate health, inspect a run and its invocation timeline, then follow an exact Linear or artifact link only when one exists.

J2 — Operator: review dependency/configuration state, draft a supported operation, inspect the redacted before/after and impact, supply a reason, then confirm one audited operation with health acceptance or rollback.

J3 — Automation owner: define a bounded fixed-interval agent loop, confirm and enable it, observe deduplicated occurrences in normal run history, and recover retained cleanup before explicitly re-enabling.

localhost:8790
├── J1 Observe → Overview → Runs → Invocation timeline / exact resource
├── J2 Operate → Configuration → Redacted draft → Confirm → Accept or rollback
└── J3 Automate → Loops → Bounded definition → Confirm → Run → Cleanup gate
                                                    └→ policy stop → audited recovery
Journey Risk Manual coverage
J1 Important Overview/offline, run detail, exact-link, and responsive checks
J2 Must Authorization, preview/confirm, secret redaction, concurrency, and rollback checks
J3 Must Definition bounds, stale confirmation, scheduling, policy stop, and cleanup recovery checks

Coverage gap: direct access from a second logged-in Mini account and real LaunchDaemon operation are intentionally left to the human because this run does not mutate the live Mini.

Verification

  • P1-AC1: provisioning tests converge a root-owned LaunchDaemon whose browser endpoint is available to local desktop sessions; live multi-account proof remains in Manual tests.
  • P1-AC2: listener/config tests require exactly 127.0.0.1, reject non-loopback values, and expose no LAN/public route.
  • P1-AC3: real HTTP tests reject invalid Host and cross-origin requests before management data or mutation callbacks.
  • P1-AC4: overview/run projections and component tests cover healthy, degraded, empty, and active states without raw prompts, payloads, environments, or secrets.
  • P1-AC5: component tests render persisted invocations on labeled role/time axes, including overlap, duration, runtime, and terminal state.
  • P1-AC6: projection and UI tests expose exact persisted Linear/artifact URLs and omit actions when either resource is absent.
  • P1-AC7: component tests render timestamped daemon-unavailable state and recover through polling without affecting daemon ingestion.
  • P1-AC8: the full 590-test daemon regression keeps signed webhook ingress and session behavior green.
  • P1-AC9: pnpm install --frozen-lockfile, backend/console typecheck, and the production build pass from the one pinned pnpm workspace.
  • P1-AC10: browser contracts and build inspection prove the console serves compiled local assets without a Vite server or runtime CDN.
  • P2-AC1: dependency monitor and projection tests expose bounded MCP health/capability summaries while rejecting oversized or secret-bearing detail.
  • P2-AC2: inventory generation/validation tests expose installed skill provenance, revision, version, compatibility, and availability without edit endpoints.
  • P2-AC3: monitor truth-table tests cover disabled, missing, stale, timeout, recovery, and aggregate degraded states with bounded timestamps/codes.
  • P2-AC4: HTTP method matrices and component tests prove MCP and Skills remain read-only with no enable, credential, or execution control.
  • P3-AC1: broker tests prove drafts are side-effect-free and present normalized redacted before/after and restart impact.
  • P3-AC2: operation tests prove one digest/version-bound audited operation, exclusive mutation, durable stages, and idempotent control recovery.
  • P3-AC3: authorization matrices reject invalid capability, peer/listener, Host, Origin, cookie, CSRF, and content type before parsing or mutation.
  • P3-AC4: crash-seam tests cover failed health acceptance, exact-byte rollback, restart bounds, and recovery across every durable stage.
  • P3-AC5: schemas and executor tests reject executable/path/service/argv injection, arbitrary commands, malformed files, symlinks, and digest mismatch.
  • P3-AC6: tests submit all supported write-only secret fields and prove values never enter read APIs, audits, logs, browser responses, or retained transients.
  • P4-AC1: strict parser/schema tests reject duplicate keys, arbitrary commands, invalid intervals, missing budget/timeout, and out-of-bound concurrency/retries before mutation.
  • P4-AC2: scheduler/session tests prove one deduplicated occurrence enters normal capacity and invocation observability with explicit loop lineage and no Linear identity/callback.
  • P4-AC3: direct SQLite tests prove policy/cleanup blocking, revision-bearing audits, retry/timeout/budget stops, idempotency, and cleanup-gated resumption.
  • P4-AC4: guarded HTTP and durable receipt tests prove unauthorized loop writes leave state unchanged and valid confirmations replay exactly across restart.
  • X-AC1: 18 component tests and 2 browser-contract tests cover keyboard operation, narrow layouts, dialogs, tables, timelines, and error states; natural browser proof follows in QA.
  • X-AC2: final independent verification passed 262 focused backend tests, all 590 runnable backend tests, 18 console tests, typecheck, production build, shell syntax, and diff hygiene. The existing guarded proxy integration test remains the sole skip. Code review completed 3/3 passes; every Must Fix was repaired and independently reverified.

Manual tests

Must (auth/data/process safety):

  • [J2] Send invalid Host, Origin, missing CSRF, and non-local capability mutations → no draft, operation, spool artifact, or callback is created.
  • [J2] Draft a configuration change → inspect a redacted no-write preview → confirm it once → one audited operation reaches accepted health.
  • [J2] Submit a write-only secret rotation → the value is absent from page source, responses, history, logs, and configuration projection.
  • [J2] Force a health-acceptance failure in a safe test setup → prior accepted configuration is restored and recovery is visible.
  • [J3] Submit arbitrary command/path fields and out-of-bound loop policy → validation rejects the definition before scheduler state changes.
  • [J3] Open a loop confirmation, trigger an automatic policy/cleanup block, then confirm the stale draft → loop_revision_changed and blocked state remain intact.
  • [J3] Run a due loop through retry exhaustion or cleanup retention → no further work is claimed; the revision-bearing reason is visible.

Important (user-facing):

  • [J1] Open Overview and navigate to a run → health, elapsed state, invocation timeline, and polling updates remain coherent.
  • [J1] Inspect runs with and without Linear/artifact resources → only exact persisted links are rendered.
  • [J1] Stop the local daemon health dependency temporarily → one timestamped degraded warning remains visible across navigation and clears on recovery.
  • [J2] Inspect MCP and Skills → status/provenance are useful and bounded, with no edit or execute controls.
  • [J3] Define, enable, disable, and recover a loop entirely by keyboard → confirmation/reason state survives errors and no Run now control exists.
  • [J1/J2/J3] Exercise desktop and narrow widths in light/dark appearance → no page-level horizontal clipping or inaccessible controls.

Areas not affected: the public webhook hostname, Cloudflare tunnel routing, Linear webhook signatures, and consumer-repo skill sync.

QA results

Pending — the three-pass correctness/security loop is repaired, including deploy command parity. The required paired refactor audit then reproduced two additional blockers (runtime/snapshot default drift and a reload path that restarted without deploying) plus state-freshness, confirmation, inventory, and maintainability warnings. Their merged repair is in progress before scoped adversarial review and the single Playwright QA drive.

Deploy notes

  • Mac Mini production: ⛔ not changed by this run. After merge, review the local trust choice and set DAEMON_CONSOLE_BIND_ADDR=127.0.0.1, DAEMON_CONSOLE_PORT=8790 (or another free loopback port), and DAEMON_CONSOLE_CAPABILITY_MODE=read-only or explicitly local-trusted in the site config. Leave LINEAR_WORKSPACE_BASE_URL unset until the exact workspace base is confirmed; links fail closed when absent.
  • Mac Mini production: ⛔ provision/deploy after configuration review. The normal provision/deploy path installs the console and fixed-operation LaunchDaemons, private request spool, sudoers entries, compiled assets, and health acceptance. No live Mini service, database, or configuration was touched here.
  • SQLite: automatic on daemon start. Additive console, dependency, operation, loop, audit, receipt, and lineage tables/columns migrate inside EventLog; there is no manual external database SQL or staging environment for this local daemon.
  • Dependencies: included in the frozen pnpm workspace. React/Vite/Tailwind console packages build into local assets; production continues to install with the checked-in lifecycle allowlist and pnpm --frozen-lockfile.

Residual risks

  • Browser QA before merge exercises a local fixture-backed console, not the live FileVault-encrypted Mini or a second user session.
  • local-trusted intentionally trusts every logged-in local desktop user; remote identities and RBAC belong to the separate remote-access item.

Tyler Brown added 4 commits August 29, 2026 13:00
- add durable loop scheduling, policy, audit, receipt, and cleanup state\n- isolate loop harness execution and expose safe loop observability\n- add guarded console controls, UI coverage, and operational docs
@socket-security

socket-security Bot commented Aug 29, 2026

Copy link
Copy Markdown

@socket-security

socket-security Bot commented Aug 29, 2026

Copy link
Copy Markdown

Warning

Review the following alerts detected in dependencies.

According to your organization's Security Policy, it is recommended to resolve "Warn" alerts. Learn more about Socket for GitHub.

Action Severity Alert  (click "▶" to expand/collapse)
Warn High
Obfuscated code: npm data-urls is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: daemon/pnpm-lock.yamlnpm/jsdom@27.0.1npm/data-urls@6.0.1

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/data-urls@6.0.1. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

Warn High
Obfuscated code: npm rrweb-cssom is 90.0% likely obfuscated

Confidence: 0.90

Location: Package overview

From: daemon/pnpm-lock.yamlnpm/jsdom@27.0.1npm/rrweb-cssom@0.8.0

ℹ Read more on: This package | This alert | What is obfuscated code?

Next steps: Take a moment to review the security alert above. Review the linked package source code to understand the potential risk. Ensure the package is not malicious before proceeding. If you're unsure how to proceed, reach out to your security team or ask the Socket team for help at support@socket.dev.

Suggestion: Packages should not obfuscate their code. Consider not using packages with obfuscated code.

Mark the package as acceptable risk. To ignore this alert only in this pull request, reply with the comment @SocketSecurity ignore npm/rrweb-cssom@0.8.0. You can also ignore all packages with @SocketSecurity ignore-all. To ignore an alert for all future pull requests, use Socket's Dashboard to change the triage state of this alert.

View full report

@tbrownio

Copy link
Copy Markdown
Contributor Author

Post-PR review — pass 1/3

Request changes: 2 Must Fix (1 security), 1 Should Fix.

  • Loop detail returned the stored task objective instead of the existing safe {kind, role} projection.
  • Default read-only mode still rendered configuration and loop mutation controls whose requests could only be rejected.
  • Confirmation/reason dialogs need focus containment, Escape dismissal, and opener-focus restoration.

All three are being repaired before browser QA. The full report is retained in the run artifacts; this comment records the PR state, not acceptance proof.

@tbrownio

Copy link
Copy Markdown
Contributor Author

Post-PR review pass 2/3: request changes — the three pass-1 findings are independently verified fixed, and the full gate remains green (591 backend + 21 console tests, one existing guarded skip).

One remaining Must Fix security boundary was reproduced: POST /api/loops/drafts still serializes the private full declaration, including task.objective, while list/detail/receipts and the frontend type are redacted. The repair will keep the full declaration only in broker-private draft state and return the allow-listed projection, with a real authenticated HTTP sentinel regression.

Evidence: .codex-dispatches/local/code-reviewer-postpr2-1788039000-root-82.md.

@tbrownio

Copy link
Copy Markdown
Contributor Author

Post-PR review pass 3/3: request changes — all prior findings, including authenticated loop-draft response redaction, are verified fixed. The final full gate is green (593 backend + 21 console tests; one existing guarded skip).

One new Must Fix deployment issue remains: deploy.sh runs sudo launchctl kickstart -k system/$CONSOLE_LABEL, but the permanent narrow sudoers command alias lacks the exact .orchestra-console restart while allowing daemon, proxy, and operation-executor commands. After the temporary provisioning grant is removed, unattended deploy would abort before console health acceptance. A narrow allowlist + rendered command-parity regression is being applied now.

Evidence: .codex-dispatches/local/code-reviewer-postpr3-1788043000-root-84.md.

@tbrownio

Copy link
Copy Markdown
Contributor Author

Post-review paired refactor audit: 2 Critical, 7 Warning after max-severity merge.

Reproduced blockers:

  • configuration snapshots default to 2/30/60 while runtime defaults to 5/100/300;
  • confirmed daemon.reload records success after restart without invoking the established deploy path.

Important repairs also queued: reason + confirmation for retry/cancel, abortable loop polling, post-terminal config refresh, slash-command-safe skill inventory, revision-bound fresh loop capacity, truthful run-id navigation, and decomposition of the dense loop UI.

Both audit plans and the merged dispatch are retained under tmp/orchestra-console-gui/; the original reports are .codex-dispatches/local/refactor-{simple,deep}-1788047000-root-{86,87}.md. No live Mini action was taken.

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