PARITY: every UI action via API, CLI, MCP and WebMCP — generated matrix + per-surface toggles in Settings → AI #395

Closed
opened 2026-09-29 04:36:13 +00:00 by kayg · 26 comments
Owner

Request (owner, 2026-09-29)

"everything the UI is able to do, MCP/CLI/API/WebMCP should be able to do as well and in Settings → AI, I should be able to turn support for each of those things off or on with CLI / API on by default. so i'd like an issue opened for the feature parity matrix!"

Decisions (owner)

  • Parity: every action the web UI can perform is available through the HTTP API, the CLI, MCP and WebMCP. DESIGN §41 (one action, one route) already makes the API the single implementation; the other surfaces are thin adapters over it (#175 audit, #329 MCP, #350 CLI, WebMCP #160).
  • Toggles in Settings → AI: one switch per surface: API, CLI, MCP, WebMCP. CLI and API are on by default; MCP and WebMCP are off by default (owner said "CLI / API on by default"; confirm if MCP/WebMCP should also default on). A surface that is off rejects its requests (API/CLI: 403 with a clear reason; MCP: tools hidden and calls refused; WebMCP: tools not registered). The web UI itself always works (it uses the API through the session, which the API toggle must not break: the toggle covers app-password/token access, not the signed-in browser).
  • Per User, with an admin override to disable a surface instance-wide.

Deliverables

  1. Generated parity matrix: docs/parity-matrix.md generated from sources, not hand-written: every UI action (from the shortcut/command registry, context menus, ⋯ menus, settings forms) × {API route, CLI command, MCP tool, WebMCP tool}. A CI check fails when a UI action has no API route or a surface is missing an adapter (with an explicit, reviewed exception list).
  2. Fill the gaps the matrix finds: CLI commands, MCP tools and WebMCP tools for every uncovered action (thin adapters, scopes enforced by app passwords #328).
  3. Settings → AI toggles as decided, with deep links, audit events on change, and tests that each off-switch really blocks its surface (cross-user rule: a User's toggles never affect another User unless an admin sets the instance-wide override).
  4. Docs: docs/mcp.md, CLI README and an "Automate calternal" page listing the surfaces.
## Request (owner, 2026-09-29) "everything the UI is able to do, MCP/CLI/API/WebMCP should be able to do as well and in Settings → AI, I should be able to turn support for each of those things off or on with CLI / API on by default. so i'd like an issue opened for the feature parity matrix!" ## Decisions (owner) - **Parity:** every action the web UI can perform is available through the HTTP API, the CLI, MCP and WebMCP. DESIGN §41 (one action, one route) already makes the API the single implementation; the other surfaces are thin adapters over it (#175 audit, #329 MCP, #350 CLI, WebMCP #160). - **Toggles in Settings → AI:** one switch per surface: API, CLI, MCP, WebMCP. **CLI and API are on by default**; MCP and WebMCP are off by default (owner said "CLI / API on by default"; confirm if MCP/WebMCP should also default on). A surface that is off rejects its requests (API/CLI: 403 with a clear reason; MCP: tools hidden and calls refused; WebMCP: tools not registered). The web UI itself always works (it uses the API through the session, which the API toggle must not break: the toggle covers app-password/token access, not the signed-in browser). - Per User, with an admin override to disable a surface instance-wide. ## Deliverables 1. **Generated parity matrix**: `docs/parity-matrix.md` generated from sources, not hand-written: every UI action (from the shortcut/command registry, context menus, ⋯ menus, settings forms) × {API route, CLI command, MCP tool, WebMCP tool}. A CI check fails when a UI action has no API route or a surface is missing an adapter (with an explicit, reviewed exception list). 2. **Fill the gaps** the matrix finds: CLI commands, MCP tools and WebMCP tools for every uncovered action (thin adapters, scopes enforced by app passwords #328). 3. **Settings → AI toggles** as decided, with deep links, audit events on change, and tests that each off-switch really blocks its surface (cross-user rule: a User's toggles never affect another User unless an admin sets the instance-wide override). 4. Docs: `docs/mcp.md`, CLI README and an "Automate calternal" page listing the surfaces.
Author
Owner

Started job/parity from dev at 00015e652a. I am inventorying the existing API, CLI, MCP and WebMCP actions, then building the generated matrix and surface controls before filling adapter gaps. No merge or deployment is planned.

Started job/parity from dev at 00015e652a153485d9e7adda1c5ee61bc17300db. I am inventorying the existing API, CLI, MCP and WebMCP actions, then building the generated matrix and surface controls before filling adapter gaps. No merge or deployment is planned.
Author
Owner

Owner correction (2026-09-29): the per-surface toggles live in Settings → Apps, not Settings → AI. 'AI should be for how AI works within our app. Apps is more like clients/frontend.' Settings → Apps is the home for API, CLI, MCP and WebMCP (clients and front-ends).

Owner correction (2026-09-29): the per-surface toggles live in **Settings → Apps**, not Settings → AI. 'AI should be for how AI works within our app. Apps is more like clients/frontend.' Settings → Apps is the home for API, CLI, MCP and WebMCP (clients and front-ends).
Author
Owner

Finding: the CLI uses the same Installation Bearer credential class as other non-browser clients. The existing credential cannot prove that a request came from the CLI; a User-Agent or custom header is forgeable. I am keeping the API gate on external Bearer access and will not claim that the CLI switch independently blocks only the CLI until credentials can identify that Installation type. The Settings correction is being applied to route names and UI copy.

Finding: the CLI uses the same Installation Bearer credential class as other non-browser clients. The existing credential cannot prove that a request came from the CLI; a User-Agent or custom header is forgeable. I am keeping the API gate on external Bearer access and will not claim that the CLI switch independently blocks only the CLI until credentials can identify that Installation type. The Settings correction is being applied to route names and UI copy.
Author
Owner

Owner decision (2026-09-29): App Passwords move to Settings → Apps (from Settings → Account), next to the API/CLI/MCP/WebMCP toggles: they are the credentials those clients use. Keep the old deep link /settings/account/app-passwords redirecting to the new section (links never break), update the setup screen, e2e and docs.

Owner decision (2026-09-29): **App Passwords move to Settings → Apps** (from Settings → Account), next to the API/CLI/MCP/WebMCP toggles: they are the credentials those clients use. Keep the old deep link /settings/account/app-passwords redirecting to the new section (links never break), update the setup screen, e2e and docs.
Author
Owner

Finding: the current web source has 160 distinct literal apiFetch method/route pairs. The existing OpenAPI contract covers 157; the three new Apps routes are awaiting contract generation. The Settings and WebMCP focused tests pass (12 tests). The browser-facing WebMCP adapter now checks effective access before tool registration and on each tool call, so a later admin override refuses calls from an already registered document. A two-User adversarial probe for API/CLI off switches and the browser escape path has been added. The Rust build and full gates are still in progress on the shared host.

Finding: the current web source has 160 distinct literal `apiFetch` method/route pairs. The existing OpenAPI contract covers 157; the three new Apps routes are awaiting contract generation. The Settings and WebMCP focused tests pass (12 tests). The browser-facing WebMCP adapter now checks effective access before tool registration and on each tool call, so a later admin override refuses calls from an already registered document. A two-User adversarial probe for API/CLI off switches and the browser escape path has been added. The Rust build and full gates are still in progress on the shared host.
Author
Owner

Finding from the generated matrix: the web source now exposes 162 distinct literal API method/route pairs and 106 shortcut actions. The source scan finds 157 API actions without at least one CLI, MCP, or WebMCP adapter. The reviewed exception snapshot is docs/parity-exceptions.json; CI rejects a new uncovered literal web API route or an unreviewed change to that snapshot. This is an explicit remaining parity backlog, not a claim that deliverable 2 is complete. The first daily-action gap filled here is Task creation/completion via CLI, plus Task completion via MCP and WebMCP, all through the existing Notes API routes.

Finding from the generated matrix: the web source now exposes 162 distinct literal API method/route pairs and 106 shortcut actions. The source scan finds 157 API actions without at least one CLI, MCP, or WebMCP adapter. The reviewed exception snapshot is `docs/parity-exceptions.json`; CI rejects a new uncovered literal web API route or an unreviewed change to that snapshot. This is an explicit remaining parity backlog, not a claim that deliverable 2 is complete. The first daily-action gap filled here is Task creation/completion via CLI, plus Task completion via MCP and WebMCP, all through the existing Notes API routes.
Author
Owner

Owner (2026-09-29): MCP and WebMCP are off by default and enabled manually in Settings → Apps; API and CLI on by default.

Owner (2026-09-29): MCP and WebMCP are **off by default and enabled manually** in Settings → Apps; API and CLI on by default.
Author
Owner

Finding: the initial API App Password gate also matched CalDAV and WebDAV Bearer passwords, because those protocols share the App Password verifier. I changed the gate to match only API and MCP protocols. The adversarial Apps round now checks that a CalDAV Basic credential still reaches /dav/ when API access is off. The gate reads User and Instance flags in one SQL query per surface, reducing the request-path reader round trips. The Rust build is still compiling on the shared host; the focused server test and live probe are pending.

Finding: the initial API App Password gate also matched CalDAV and WebDAV Bearer passwords, because those protocols share the App Password verifier. I changed the gate to match only API and MCP protocols. The adversarial Apps round now checks that a CalDAV Basic credential still reaches /dav/ when API access is off. The gate reads User and Instance flags in one SQL query per surface, reducing the request-path reader round trips. The Rust build is still compiling on the shared host; the focused server test and live probe are pending.
Author
Owner

Progress: commits through 3b068786 include the generated matrix and CI check, Settings → Apps and App Passwords relocation, WebMCP gate/Task action, docs, screenshots, and the security-state migration. bun run check returned svelte-check found 0 errors and 0 warnings; bun run test returned Test Files 123 passed (123) and Tests 788 passed (788); the production Vite build completed. cargo fmt --all --check returned exit 0. The shared host is still compiling first-run Rust dependencies for the focused server test; live API probing has not started. The remaining uncommitted server and CLI edits are preserved in this worktree.

Progress: commits through 3b068786 include the generated matrix and CI check, Settings → Apps and App Passwords relocation, WebMCP gate/Task action, docs, screenshots, and the security-state migration. `bun run check` returned `svelte-check found 0 errors and 0 warnings`; `bun run test` returned `Test Files 123 passed (123)` and `Tests 788 passed (788)`; the production Vite build completed. `cargo fmt --all --check` returned exit 0. The shared host is still compiling first-run Rust dependencies for the focused server test; live API probing has not started. The remaining uncommitted server and CLI edits are preserved in this worktree.
Author
Owner

Finding: DESIGN §41 limits agent tokens to data scope. Several Settings Account and Admin actions require account/admin scope and a recent passkey assertion. I kept those authorization checks on the existing API routes and left their MCP gaps in the explicit exception snapshot; a thin adapter cannot safely supply the missing authority. The matrix generator now recognizes formatted CLI routes, reducing the counted adapter gaps from 157 to 156. No auth scope was widened.

Finding: DESIGN §41 limits agent tokens to data scope. Several Settings Account and Admin actions require account/admin scope and a recent passkey assertion. I kept those authorization checks on the existing API routes and left their MCP gaps in the explicit exception snapshot; a thin adapter cannot safely supply the missing authority. The matrix generator now recognizes formatted CLI routes, reducing the counted adapter gaps from 157 to 156. No auth scope was widened.
Author
Owner

Build progress: the focused cargo test -p calternal-server app_surface_flags_are_per_user_with_instance_override process is still compiling first-run dependencies on the shared host (calternal-db, calternal-plugin, calternal-fs, calternal-notes-core and their dependencies have built). It has emitted no compiler diagnostic. Commit fe47f44e updates the parity generator to match formatted CLI routes; python3 scripts/parity_matrix.py --check passes with 156 recorded adapter gaps. The pending server and CLI edits remain intact. I am continuing to the live gate checks after compilation; no merge or push has occurred.

Build progress: the focused `cargo test -p calternal-server app_surface_flags_are_per_user_with_instance_override` process is still compiling first-run dependencies on the shared host (calternal-db, calternal-plugin, calternal-fs, calternal-notes-core and their dependencies have built). It has emitted no compiler diagnostic. Commit fe47f44e updates the parity generator to match formatted CLI routes; `python3 scripts/parity_matrix.py --check` passes with 156 recorded adapter gaps. The pending server and CLI edits remain intact. I am continuing to the live gate checks after compilation; no merge or push has occurred.
Author
Owner

Progress at about one hour: the focused Rust test remains active and is compiling the shared workspace dependencies; no compiler error has appeared. New commit e12c7abc adds production screenshot capture for Account and WebMCP confirmation at 390/820/1440 px in light and dark (the scripts pass node --check; browser execution follows the server build). The generated matrix check still passes and records 156 reviewed adapter gaps. The branch has not been pushed or merged.

Progress at about one hour: the focused Rust test remains active and is compiling the shared workspace dependencies; no compiler error has appeared. New commit e12c7abc adds production screenshot capture for Account and WebMCP confirmation at 390/820/1440 px in light and dark (the scripts pass `node --check`; browser execution follows the server build). The generated matrix check still passes and records 156 reviewed adapter gaps. The branch has not been pushed or merged.
Author
Owner

Progress: the focused server test is still compiling the server's search, embedding, and document dependencies in the isolated parity target. It has emitted no error. Commit f1f19554 polishes WebMCP write confirmation; bun run test -- src/lib/webmcp/tools.test.ts passed 5 tests and bun run check reported 0 errors/0 warnings. The Apps adversarial probe now exercises Installation Bearer, API App Password, browser cookie, CalDAV Basic, cross-User access, malformed payloads, concurrency, and admin override. Live results remain pending the binary build.

Progress: the focused server test is still compiling the server's search, embedding, and document dependencies in the isolated parity target. It has emitted no error. Commit f1f19554 polishes WebMCP write confirmation; `bun run test -- src/lib/webmcp/tools.test.ts` passed 5 tests and `bun run check` reported 0 errors/0 warnings. The Apps adversarial probe now exercises Installation Bearer, API App Password, browser cookie, CalDAV Basic, cross-User access, malformed payloads, concurrency, and admin override. Live results remain pending the binary build.
Author
Owner

Build progress: Cargo has reached Compiling calternal-server v0.0.1 after compiling the relevant plugin and MCP dependencies. It has emitted no diagnostic. The focused server test remains running; I will commit the server/API slice after it passes, then run the CLI focus test, merge dev once, and run the final gates plus one live Apps adversarial round. The branch remains local and unmerged.

Build progress: Cargo has reached `Compiling calternal-server v0.0.1` after compiling the relevant plugin and MCP dependencies. It has emitted no diagnostic. The focused server test remains running; I will commit the server/API slice after it passes, then run the CLI focus test, merge dev once, and run the final gates plus one live Apps adversarial round. The branch remains local and unmerged.
Author
Owner

Gate result: cargo test -p calternal-server app_surface_flags_are_per_user_with_instance_override completed with:

running 1 test
test wire::tests::app_surface_flags_are_per_user_with_instance_override ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 83 filtered out; finished in 0.01s

Commits 87761764 and c863797e record the server Apps gate/audit and MCP Task adapter separately. The CLI focused test is compiling. No merge or push has occurred.

Gate result: `cargo test -p calternal-server app_surface_flags_are_per_user_with_instance_override` completed with: running 1 test test wire::tests::app_surface_flags_are_per_user_with_instance_override ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 83 filtered out; finished in 0.01s Commits 87761764 and c863797e record the server Apps gate/audit and MCP Task adapter separately. The CLI focused test is compiling. No merge or push has occurred.
Author
Owner

Progress: the focused Apps server test passed and its gate/audit implementation is committed. The CLI focused test is still compiling the CLI's separate keyring/TLS dependency graph with no diagnostic. The current API client was regenerated from contracts/openapi.json successfully (openapi-typescript 7.13.0), and the parity matrix check passes with 156 recorded adapter gaps. I am continuing toward the required single dev merge and final gates; no push has occurred.

Progress: the focused Apps server test passed and its gate/audit implementation is committed. The CLI focused test is still compiling the CLI's separate keyring/TLS dependency graph with no diagnostic. The current API client was regenerated from `contracts/openapi.json` successfully (`openapi-typescript 7.13.0`), and the parity matrix check passes with 156 recorded adapter gaps. I am continuing toward the required single dev merge and final gates; no push has occurred.
Author
Owner

Gate result: cargo test -p calternal-cli task_new_is_a_json_capable_remote_command completed with:

running 1 test
test tests::task_new_is_a_json_capable_remote_command ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 21 filtered out; finished in 0.00s

Commit 767c42c6 records the Task CLI commands. The server OpenAPI generator is now running so the contract and TypeScript client can be committed from generated output before the single dev merge. No push has occurred.

Gate result: `cargo test -p calternal-cli task_new_is_a_json_capable_remote_command` completed with: running 1 test test tests::task_new_is_a_json_capable_remote_command ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 21 filtered out; finished in 0.00s Commit 767c42c6 records the Task CLI commands. The server OpenAPI generator is now running so the contract and TypeScript client can be committed from generated output before the single dev merge. No push has occurred.
Author
Owner

Merged dev at c4651504 into job/parity as 558? (merge commit; see branch head). The merge combined Settings layout/plugin toggle changes with Apps without conflicts. Generated OpenAPI and client types are committed at 611abcf0. Post-merge cargo fmt --all --check and the parity matrix CI check pass; bun run check reports 0 errors and 0 warnings. Workspace Clippy and web tests are running. The Apps defaults in DESIGN §48 match the implementation (API/CLI on, MCP/WebMCP off); §49 distinguishes external Integrations from Apps clients.

Merged dev at c4651504 into job/parity as 558? (merge commit; see branch head). The merge combined Settings layout/plugin toggle changes with Apps without conflicts. Generated OpenAPI and client types are committed at 611abcf0. Post-merge `cargo fmt --all --check` and the parity matrix CI check pass; `bun run check` reports 0 errors and 0 warnings. Workspace Clippy and web tests are running. The Apps defaults in DESIGN §48 match the implementation (API/CLI on, MCP/WebMCP off); §49 distinguishes external Integrations from Apps clients.
Author
Owner

Post-merge live Apps adversarial round: ROUND2_SECTIONS=apps completed with ROUND 2 FINDINGS 0 and ROUND 2 SLOW 0. The initial 3 MiB probe saw a 502 from the test proxy while the Rust server stayed alive; the probe now addresses the Rust server directly (46d0c0df), and the round passes.

The 390 px production screenshot exposed a sticky sheet title regression: App Passwords still used the single-group hideTitleOnSheet setting after moving into the two-group Apps section. That hidden heading could override the visible Access title. I restored the App Passwords heading and am rebuilding and rerunning the browser script. The merge commit is fc990049 (correcting the placeholder SHA in my prior comment). Workspace Cargo test is running; Clippy was terminated by the shared host with exit 143 and will be retried after Cargo test.

Post-merge live Apps adversarial round: `ROUND2_SECTIONS=apps` completed with `ROUND 2 FINDINGS 0` and `ROUND 2 SLOW 0`. The initial 3 MiB probe saw a 502 from the test proxy while the Rust server stayed alive; the probe now addresses the Rust server directly (46d0c0df), and the round passes. The 390 px production screenshot exposed a sticky sheet title regression: App Passwords still used the single-group `hideTitleOnSheet` setting after moving into the two-group Apps section. That hidden heading could override the visible Access title. I restored the App Passwords heading and am rebuilding and rerunning the browser script. The merge commit is fc990049 (correcting the placeholder SHA in my prior comment). Workspace Cargo test is running; Clippy was terminated by the shared host with exit 143 and will be retried after Cargo test.
Author
Owner

Browser validation on the production build now passes. bun run test:e2e:app-passwords: app password e2e: calendar profiles, scoped PhotoSync access, and responsive settings passed. It captured Apps, Admin Apps, Account, and App Passwords at 390/820/1440 px in light and dark under artifacts/parity/app-passwords/ (kept out of Git). The phone capture exposed two related title issues after the Apps move; commit 85033d7b keeps the App Passwords group heading visible and stable while a credential is ready. bun apps/web/e2e/webmcp.mjs --screenshots ... passes: WebMCP e2e: 8 tools called through stub modelContext and CSP REPORTS webmcp: 0 across 1 pages. The confirmation screenshots are under artifacts/parity/webmcp/. Search indexing visibility was intermittent on this shared host; the assertion still requires the Note and now waits up to 30 seconds (f092d64a). Final bun run test: 123 files and 788 tests passed. Rust workspace test is compiling.

Browser validation on the production build now passes. `bun run test:e2e:app-passwords`: `app password e2e: calendar profiles, scoped PhotoSync access, and responsive settings passed`. It captured Apps, Admin Apps, Account, and App Passwords at 390/820/1440 px in light and dark under `artifacts/parity/app-passwords/` (kept out of Git). The phone capture exposed two related title issues after the Apps move; commit 85033d7b keeps the App Passwords group heading visible and stable while a credential is ready. `bun apps/web/e2e/webmcp.mjs --screenshots ...` passes: `WebMCP e2e: 8 tools called through stub modelContext` and `CSP REPORTS webmcp: 0 across 1 pages`. The confirmation screenshots are under `artifacts/parity/webmcp/`. Search indexing visibility was intermittent on this shared host; the assertion still requires the Note and now waits up to 30 seconds (f092d64a). Final `bun run test`: 123 files and 788 tests passed. Rust workspace test is compiling.
Author
Owner

Found and fixed two browser parity defects in the production screenshots/live WebMCP run. (1) WebMCP confirmations were clipped at 820 px and 1440 px because the desktop dialog had a 50% left position without a matching horizontal offset; caa7bd25 centres this confirmation, with 390/820/1440 light/dark captures refreshed. (2) WebMCP Search sometimes returned [] for a just-created Note although direct /api/v1/search?semantic=false returned one hit: the full-text provider supplied /notes?path=..., and the adapter discarded it as rename-fragile. 6142a7ce resolves the path with the shared Note index to /n/<id> and remembers Notes it creates; the same live E2E now passes all eight tools and reports zero CSP violations. The direct diagnostic response was HTTP 200, timed_out=false, one hit from the search provider. bun run check and production build pass after the fix. Cargo workspace test is still compiling on the shared host.

Found and fixed two browser parity defects in the production screenshots/live WebMCP run. (1) WebMCP confirmations were clipped at 820 px and 1440 px because the desktop dialog had a 50% left position without a matching horizontal offset; `caa7bd25` centres this confirmation, with 390/820/1440 light/dark captures refreshed. (2) WebMCP Search sometimes returned `[]` for a just-created Note although direct `/api/v1/search?semantic=false` returned one hit: the full-text provider supplied `/notes?path=...`, and the adapter discarded it as rename-fragile. `6142a7ce` resolves the path with the shared Note index to `/n/<id>` and remembers Notes it creates; the same live E2E now passes all eight tools and reports zero CSP violations. The direct diagnostic response was HTTP 200, `timed_out=false`, one hit from the `search` provider. `bun run check` and production build pass after the fix. Cargo workspace test is still compiling on the shared host.
Author
Owner

Final post-fix web gates: bun run check printed svelte-check found 0 errors and 0 warnings; bun run test printed Test Files 123 passed (123) and Tests 788 passed (788); production bun run build wrote build and completed. The parity CI check printed Parity matrix: 162 web API actions, 106 shortcuts, 2 static commands, 107 menu actions, 30 settings groups, 156 actions with adapter gaps. Worktree is clean at 6142a7ce. cargo test is still compiling the full workspace dependency graph; cargo clippy --all-targets -- -D warnings is queued behind its build lock. No Rust diagnostic has appeared. I will report their exact outcomes or the time limit rather than claim an unrun pass.

Final post-fix web gates: `bun run check` printed `svelte-check found 0 errors and 0 warnings`; `bun run test` printed `Test Files 123 passed (123)` and `Tests 788 passed (788)`; production `bun run build` wrote `build` and completed. The parity CI check printed `Parity matrix: 162 web API actions, 106 shortcuts, 2 static commands, 107 menu actions, 30 settings groups, 156 actions with adapter gaps`. Worktree is clean at 6142a7ce. `cargo test` is still compiling the full workspace dependency graph; `cargo clippy --all-targets -- -D warnings` is queued behind its build lock. No Rust diagnostic has appeared. I will report their exact outcomes or the time limit rather than claim an unrun pass.
Author
Owner

Full cargo test finished compiling, then stopped on an expected migration-count assertion in calternal-auth: left: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], right: [1, 2, 3, 4, 5, 6, 7, 8, 9]; summary: test result: FAILED. 62 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 33.51s. #395 adds migration 0010 for App surface flags, so this issue explicitly changes the expected migration set. I updated the assertion to 1–10 without changing any other expectation. cargo fmt --all --check passes. Clippy is running; a focused auth test and full cargo test retry are queued behind its build lock. The CLI binary build was cancelled to prioritize required gates within the job time limit.

Full `cargo test` finished compiling, then stopped on an expected migration-count assertion in `calternal-auth`: `left: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`, `right: [1, 2, 3, 4, 5, 6, 7, 8, 9]`; summary: `test result: FAILED. 62 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 33.51s`. #395 adds migration 0010 for App surface flags, so this issue explicitly changes the expected migration set. I updated the assertion to 1–10 without changing any other expectation. `cargo fmt --all --check` passes. Clippy is running; a focused auth test and full `cargo test` retry are queued behind its build lock. The CLI binary build was cancelled to prioritize required gates within the job time limit.
Author
Owner

Final report for #395 — branch job/parity, head dab9d2fbdd. Merged dev once into the job branch (fc990049). No push, deploy, or merge into dev.

Built: generated source-derived parity matrix and CI check (scripts/parity_matrix.py, docs/parity-matrix.md, docs/parity-exceptions.json); Settings → Apps User and Instance surface controls and audit events, with API/CLI on and MCP/WebMCP off by default; moved App Passwords beside the controls and redirected the old Account deep link; server credential gates preserving signed-in browser and CalDAV/WebDAV access; WebMCP registration/call revocation and Task completion; CLI Task create/done/reopen and MCP Task completion; stable Note links in WebMCP Search; generated OpenAPI/client types; automation docs; cross-User, browser, and adversarial probes. Main files: crates/calternal-auth/migrations/0010_app_surfaces.sql, crates/calternal-auth/src/store.rs, crates/calternal-server/src/{wire,mcp}.rs, crates/calternal-cli/src/{main,remote_commands}.rs, apps/web/src/routes/settings/, apps/web/src/lib/{webmcp,components/ConfirmSheet.svelte}, contracts/openapi.json, packages/api-client/src/generated.ts, tests/adversarial/, apps/web/e2e/, docs/{mcp,automate,parity-matrix}.md, CLI README. Atomic commits are in the branch history.

Gate output (verbatim result lines):
cargo fmt --all --check: exit 0, no output.
bun run check: svelte-check found 0 errors and 0 warnings.
bun run test: Test Files 123 passed (123) / Tests 788 passed (788).
bun run build: Wrote site to "build" / ✔ done.
python3 scripts/parity_matrix.py --check: Parity matrix: 162 web API actions, 106 shortcuts, 2 static commands, 107 menu actions, 30 settings groups, 156 actions with adapter gaps.
Apps live adversarial round: ==== ROUND 2 FINDINGS 0 / ==== ROUND 2 SLOW 0.
App Password browser E2E: app password e2e: calendar profiles, scoped PhotoSync access, and responsive settings passed.
WebMCP browser E2E: WebMCP e2e: 8 tools called through stub modelContext / CSP REPORTS webmcp: 0 across 1 pages.
First cargo test: test result: FAILED. 62 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 33.51s. Cause: the auth migration-count test expected 1–9 after this issue added migration 10; corrected in dab9d2fb. Retry confirmed test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 38.99s for calternal-auth and test result: ok. 22 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s for calternal-cli, then was interrupted at the four-hour job limit while running later workspace suites (exit 130). Full workspace cargo test is therefore incomplete. cargo clippy --all-targets -- -D warnings was interrupted while compiling on the shared host (exit 130); its first attempt was host-terminated with exit 143. It has no passing final result.

Known gaps: the generated matrix records 156 missing CLI/MCP/WebMCP adapters; deliverable 2 is incomplete. Current Installation Bearer credentials cannot prove a request came from the CLI, so the CLI toggle cannot independently distinguish the actual CLI binary from another Installation client. DESIGN §41 data-only Agent scopes and recent-passkey requirements leave Account/Admin MCP actions as explicit exceptions. The CLI live adversarial section was not run; the Apps round was run and passed. Full Rust workspace test and Clippy need a follow-up gate run. Production screenshots for 390/820/1440 px, light/dark are in ignored artifacts/parity/app-passwords/ and artifacts/parity/webmcp/; fj issue has no attachment command, so they are available in this worktree for the orchestrator. I inspected the captures and fixed a clipped confirmation dialog and incorrect phone sheet title. cargo clean printed Removed 14385 files, 14.7GiB total; generated web build output was deleted. Worktree is clean.

Decisions where the design was silent: API App Password gating applies to API/MCP protocols only, preserving CalDAV/WebDAV protocol credentials; browser cookies bypass external-client switches so Users can restore access. WebMCP Search resolves path-based Search hits through the shared Note index and returns stable /n/<id> links. The App Passwords group title remains stable while one-use credentials are shown. No authorization scope was widened.

Final report for #395 — branch job/parity, head dab9d2fbdd5687f1a87f31acbba81822e13c0f61. Merged dev once into the job branch (fc990049). No push, deploy, or merge into dev. Built: generated source-derived parity matrix and CI check (`scripts/parity_matrix.py`, `docs/parity-matrix.md`, `docs/parity-exceptions.json`); Settings → Apps User and Instance surface controls and audit events, with API/CLI on and MCP/WebMCP off by default; moved App Passwords beside the controls and redirected the old Account deep link; server credential gates preserving signed-in browser and CalDAV/WebDAV access; WebMCP registration/call revocation and Task completion; CLI Task create/done/reopen and MCP Task completion; stable Note links in WebMCP Search; generated OpenAPI/client types; automation docs; cross-User, browser, and adversarial probes. Main files: `crates/calternal-auth/migrations/0010_app_surfaces.sql`, `crates/calternal-auth/src/store.rs`, `crates/calternal-server/src/{wire,mcp}.rs`, `crates/calternal-cli/src/{main,remote_commands}.rs`, `apps/web/src/routes/settings/`, `apps/web/src/lib/{webmcp,components/ConfirmSheet.svelte}`, `contracts/openapi.json`, `packages/api-client/src/generated.ts`, `tests/adversarial/`, `apps/web/e2e/`, `docs/{mcp,automate,parity-matrix}.md`, CLI README. Atomic commits are in the branch history. Gate output (verbatim result lines): `cargo fmt --all --check`: exit 0, no output. `bun run check`: `svelte-check found 0 errors and 0 warnings`. `bun run test`: `Test Files 123 passed (123)` / `Tests 788 passed (788)`. `bun run build`: `Wrote site to "build"` / `✔ done`. `python3 scripts/parity_matrix.py --check`: `Parity matrix: 162 web API actions, 106 shortcuts, 2 static commands, 107 menu actions, 30 settings groups, 156 actions with adapter gaps`. Apps live adversarial round: `==== ROUND 2 FINDINGS 0` / `==== ROUND 2 SLOW 0`. App Password browser E2E: `app password e2e: calendar profiles, scoped PhotoSync access, and responsive settings passed`. WebMCP browser E2E: `WebMCP e2e: 8 tools called through stub modelContext` / `CSP REPORTS webmcp: 0 across 1 pages`. First `cargo test`: `test result: FAILED. 62 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 33.51s`. Cause: the auth migration-count test expected 1–9 after this issue added migration 10; corrected in dab9d2fb. Retry confirmed `test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 38.99s` for calternal-auth and `test result: ok. 22 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.24s` for calternal-cli, then was interrupted at the four-hour job limit while running later workspace suites (exit 130). Full workspace `cargo test` is therefore incomplete. `cargo clippy --all-targets -- -D warnings` was interrupted while compiling on the shared host (exit 130); its first attempt was host-terminated with exit 143. It has no passing final result. Known gaps: the generated matrix records 156 missing CLI/MCP/WebMCP adapters; deliverable 2 is incomplete. Current Installation Bearer credentials cannot prove a request came from the CLI, so the CLI toggle cannot independently distinguish the actual CLI binary from another Installation client. DESIGN §41 data-only Agent scopes and recent-passkey requirements leave Account/Admin MCP actions as explicit exceptions. The CLI live adversarial section was not run; the Apps round was run and passed. Full Rust workspace test and Clippy need a follow-up gate run. Production screenshots for 390/820/1440 px, light/dark are in ignored `artifacts/parity/app-passwords/` and `artifacts/parity/webmcp/`; `fj issue` has no attachment command, so they are available in this worktree for the orchestrator. I inspected the captures and fixed a clipped confirmation dialog and incorrect phone sheet title. `cargo clean` printed `Removed 14385 files, 14.7GiB total`; generated web build output was deleted. Worktree is clean. Decisions where the design was silent: API App Password gating applies to API/MCP protocols only, preserving CalDAV/WebDAV protocol credentials; browser cookies bypass external-client switches so Users can restore access. WebMCP Search resolves path-based Search hits through the shared Note index and returns stable `/n/<id>` links. The App Passwords group title remains stable while one-use credentials are shown. No authorization scope was widened.
Author
Owner

Superseded scope and settings location: the later owner request in #484 re-frames this parity work around one action registry, generated adapters and a fail-closed gate. DESIGN §50 puts the surface controls in Settings → Apps & Devices; this issue says Settings → AI. Recommend keeping #484 as the current source of truth and linking #395 as the earlier owner request. Do not close this issue in the audit.

Superseded scope and settings location: the later owner request in #484 re-frames this parity work around one action registry, generated adapters and a fail-closed gate. DESIGN §50 puts the surface controls in Settings → Apps & Devices; this issue says Settings → AI. Recommend keeping #484 as the current source of truth and linking #395 as the earlier owner request. Do not close this issue in the audit.
Author
Owner

Superseded by #484, the current action-registry scope. #484 remains open and queued for merge.

Superseded by #484, the current action-registry scope. #484 remains open and queued for merge.
kayg closed this issue 2026-10-03 11:55:12 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#395
No description provided.