Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 21 additions & 4 deletions docs/plans/integration-readiness-matrix.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ The matrix below is the definition of "ready". A row is ready when every cell is
| Linear (hosted MCP) | yes | **Fresh-account walk 2026-10-15 on `cfe91c21`, green** (connector-ops 77850 and 77962; the build is Deploy Dev's last run before the walk): a new commonly.me account and a new Linear workspace, neither connected before. **C1 green**: connected through the Connectors page. Linear's consent read "Read, Identity", the authorize request asked for `read openid`, and the token response granted `read openid` (`config.grantedScope`). **C3 green in an eligible pod**: a read grant of the 36 pinned tools, made through the grant panel, which offers only Read, in the account's own My Workspace. That pod is private and invite-only, with no bridge and Scout as its only agent, so it passes §12's pod rule in `hosted-mcp-connection-scope.md` (#2211). Scout listed the workspace's one team through the grant, the trail records the call ok, and Scout quoted #2206's untrusted-content marker ahead of the data. #2211 deployed after the walk, and the same call was ok again after it, at 16:22:37Z. The earlier C3 and C4 walks ran in the C4 run pod, which fails that rule: since `ff909fb3` the deployed rule returns `pod_joinable` for both of its grants. Partly walked live 2026-10-01 (Sam's account, Chrome). Before the fresh-account walk, C1 was open: Sam's own operator-led connect succeeded on `cf9b6abf`, through CIMD with scope `read openid`, and the row records its client and the Linear subject. That didn't prove a stranger connects unaided, and no stranger had tried. **C2 green at 1440, the rest unwalked**: in the fresh-account walk the grant panel offered only Read. Earlier, on `cf9b6abf` the grant rendered as GitHub, because the catalogue projected 0 Linear tools. #2068 (`207c68d5`) fixed it, and on the deployed `e370fe9b` (its descendant) the row reads Linear, with its mark and the read eye, at 1200. 390, a failure reaching Activity, and revoke reachability are unwalked. Earlier, C3 was green in the C4 run pod: Scout listed the team and three issues through `grant_c6af31b8`; the trail showed the calls ok, with Sam as credential owner. **C4 refused by design** from #2211 (the C4 column), and c4-smoke is now offered no Linear tool. Before that it was green (2026-10-09): c4-smoke, a public local claude seat confined by Seatbelt, called `linear.list_teams` through its broker on `grant_e3a1507b` at 06:12:57Z, and the trail shows it ok. Its daemon started at 06:11:59Z, after global cli 0.1.84 (npm latest) was installed at 06:11:41Z, so it runs the current build. An earlier run on 2026-09-27 didn't count, because that daemon predated the cli it should have been running. The same spawn showed that TASK-228's headers helper works under the public Seatbelt profile. A by-name scan of the spawn's claude process found `COMMONLY_TOKEN_FILE` set and `COMMONLY_AGENT_TOKEN` absent. The rest of #2067's consumer proof is unmeasured: the child processes' environments, and a credential rotation followed by a 401 retry succeeding. **C8 open**: in a pod with no grant, Scout is offered no `linear.*` tools. That's confinement by projection. An attempted out-of-pod call, refused and recorded in the trail, hasn't been made. **C9 open**, now only for whether a revoke takes effect at Linear. Linear's revoke is page-only. The fresh-account walk reached the page: `https://linear.app/settings/account/security`, whose Authorized applications list shows the connection as "MCP · Read · Revoke". #2230 points the entry's page there. Before #2230 the entry named `https://linear.app/settings/security`, which is Linear's workspace admin page. Before that walk, every linear.app settings URL redirected to the old workspace's unfinished welcome flow, so the page had not been reached. C5, C6, C7 and C10 are unwalked |
| Google Calendar (hosted MCP) | yes | **Built, live, not offered.** #2066 (`e370fe9b`) pins the 5 read tools from Google's unauthenticated `tools/list`, with a pre-registered client and `openid` for the account subject. "Not offered" is a **config fact, not a code fact**. The client values arrived on 2026-10-09 (#2111), and the tile was offered until 2026-10-14. OAuth worked, but every tool call failed Google's Developer Preview gate, which is **per Cloud project** (Google named the project in its error on the 2026-10-09 gate test). Since 2026-10-14 `hostedMcp.googleCalendar.enabled` is `false` in values-dev (Wren's ruling), so the instance holds no client values, the catalogue reports `available: false`, and the page shows "not enabled on this instance" with no Connect. Flip the flag once the project is enrolled and an enrolled `list_calendars` call succeeds. Waiting on Sam: a Workspace seat on the domain and Developer Preview enrollment for the connectors project. The OAuth client already exists in a project of its own (Wren: a revoke withdraws every scope a person granted the project) |
| Atlassian (hosted MCP), writes in #2328 | yes (writes since #2328) | **Deployed, hidden on commonly.me since #2530.** The live build (`19de6035d`, 2026-10-24) carries every change below. `hostedMcp.hiddenEntries` in values-dev leaves the entry out of the catalogue and refuses every connect with `unknown_entry`, a reconnect included (`hostedMcpConnect.ts:251`). **C1 blocked on staging** (2026-10-23, `876870378`, #2536): the site's MCP-server-domain allowlist does not include the staging origin, and only a site admin can add it. The entry pins six Jira and Confluence reads. In a 2026-10-22 walk C3 was red: every call failed with "tools/list could not be verified", which TASK-263 attributed to our client never opening an MCP session. #2397 opens one for each list and call; the C3 re-check after its deploy belongs to TASK-263. #2328 adds five named writers: `update_confluence_content`, `create_jira_issue`, `edit_jira_issue`, `transition_jira_issue` and `add_or_edit_jira_issue_comment`, the last marked irreversible. Each is pinned `write`, so every write parks for the connection's owner with its exact arguments, and runs only under the definition it parked under (#2378). The entry now requests write scopes, so a row connected before #2328 holds a token that cannot write, and its owner must reconnect, which the hide refuses until it is lifted. **C4 refused by design** (the C4 column). The walk's checks are below |
| Sentry (hosted MCP), #2329 | yes (#2329) | **Deployed, hidden on commonly.me since #2530**, the same way as Atlassian. **C0, C1 and C2 green on staging, each with a part #2536 did not record** (2026-10-23, `876870378`). Staging has no agent runtime, so C3, C6 and C9 were not walked. #2329 pins 11 named reads and `update_issue`, an irreversible write that parks for the connection's owner with its exact arguments. `get_sentry_resource` is pinned without the vendor's `url` argument, and the vendor's dispatcher, its catalogue and Seer are left out, as ruled in the PR thread. The client is CIMD, and the entry requests five scopes, four of them write. **C4 refused by design** (the C4 column). The walk's checks are below |
| Sentry (hosted MCP), #2329 | yes (#2329) | **Deployed, hidden on commonly.me since #2530**, the same way as Atlassian. Since #2649 and #2658 the hide has a walk exception for one account. **C0, C1 and C2 green on staging, each with a part #2536 did not record** (2026-10-23, `876870378`). Staging has no agent runtime, so C3, C6 and C9 were not walked there. **C3 green on commonly.me except the page comparison** (2026-10-25, `c9c0d71c1`): a hosted agent read through a pod grant, and the trail records the call ok. **C9's "cannot do more than granted" green for a read grant**: the agent was offered the 11 reads and no write tool. Whether a revoke takes effect, at Sentry included, is not walked, and neither is C6 (the commonly.me walk below). #2329 pins 11 named reads and `update_issue`, an irreversible write that parks for the connection's owner with its exact arguments. `get_sentry_resource` is pinned without the vendor's `url` argument, and the vendor's dispatcher, its catalogue and Seer are left out, as ruled in the PR thread. The client is CIMD, and the entry requests five scopes, four of them write. **C4 refused by design** (the C4 column). The walk's checks are below |
| next app | no | Sam's decision; see below |

## Staging connector walk — 2026-10-23 on `876870378`
Expand All @@ -83,6 +83,23 @@ Walked `staging.commonly.me` with a non-admin walk user in an invite-only pod wh
| Staging had no connector key ring | fixed by #2533 |
| Sentry's Authorized Apps page lists the hosted-MCP client as `mcp.sentry.dev`, not "Commonly (Sentry)"; vendor-side revocation there is per client and cuts every Sentry-MCP session on the account | Commonly disconnect is the supported per-token revoke path: it calls the vendor's RFC 7009 `revocation_endpoint` before deleting the row; staging removal returned 200 |

## Sentry walk on commonly.me — 2026-10-25 on `c9c0d71c1`

Walked 2026-10-25 from 04:15Z to 04:16Z and recorded on Sharpen's TASK-485, with the first attempt on Sharpen's TASK-490. The live build was `c9c0d71c1` (#2658), from Deploy Dev's 00:34Z run; the next run started at 10:57Z. It descends from `4bc63222`, so it carries everything the walk checks below depend on. Sentry is still hidden on commonly.me. A hidden entry's walk exception lets the accounts it names see and connect it (#2649) and mint its grants (#2658). Sentry's names one account, `lily-shen` (values-dev). So the connection and the grant are that account's, the walk was not a stranger session (Method rule 1), and C0 to C2 are not re-recorded here. The pod (`6ad18344`) is invite-only, and the hosted agent `cto-walk-1016` runs on the native engine. Every grant mint applies §12's pod rule in `hosted-mcp-connection-scope.md` (`outsiderGrantPodRefusal`, `backend/routes/grants.ts:396` at `c9c0d71c1`), and the broker re-reads it on every list and call. So the grant's mint and its ok call each show the pod passed the rule.

Evidence: TASK-485's notes on Sharpen's board record the grant, the agent's call, the trail's one row and the revoke. The trail itself is `GET /api/grants/:grantId/calls` (`backend/routes/grants.ts:530` at `c9c0d71c1`), and only an account that can view the pod can read it (`canViewPod`, `backend/routes/grants.ts:521`). TASK-485 records no file, so nothing in the repo holds this walk's evidence.

| cell | result |
|---|---|
| C3 | **green except the page comparison.** `grant_d8b399a9` is a `read` pod grant of the 11 reads, with audience `cto-walk-1016` and a two-hour expiry. Woken by a message in the pod, the agent called `find_organizations`, and its turn reports the organization returned. The trail, the broker's call log, shows that one call, `sentry.find_organizations`, outcome ok. Unverified: whether the answer matches Sentry's own pages, which TASK-485 does not record |
| C9, cannot do more than granted | **green for a read grant.** The agent's turn listed exactly the 11 reads as its `sentry_*` tools and reported no create, update or resolve tool. So neither `update_issue` nor the vendor's dispatcher, its catalogue or Seer was offered. Unverified: the 12 tools under `write-with-confirm`, and whether `get_sentry_resource` was offered without `url` |
| C9, a revoke takes effect | **open.** The grant was revoked at 04:16:08Z, and the record has no call after the revoke, so it does not show the revoke taking effect. Not walked on commonly.me: a parked `update_issue` refused with `grant_revoked` after its grant's revoke, and a disconnect's revocation at Sentry, with what Sentry's Authorized Applications page shows afterwards |
| C6 | **not walked.** It needs a `write-with-confirm` grant, with one `update_issue` approved and one declined |

| finding | status |
|---|---|
| A first grant in the same pod, `grant_22d0c9eb`, named an explicit empty audience, so the agent's turn at 01:00Z was offered no Sentry tool. It first read as an engine defect (Sharpen TASK-490). The cause was the audience, which named nobody | #2661 refuses an explicit empty pod-grant audience at mint with `400 invalid_audience` (`docs/runbooks/connector-grant-audience.md`), deployed by Deploy Dev's 10:57Z run (`cf4164499`) |

## Walk of 2026-09-25

Stranger account `eng-smoke-09255bfe` (role user), builds `9a32fca5`, `0e142135` and `f536fa11`. Evidence: `docs/design/evidence/slack-authorize-409/` and the rows filed in the Connectors lane.
Expand Down Expand Up @@ -159,7 +176,7 @@ The test gate on "Scout (Default)" was switched back off after the walk. On Sam'

## Walk checks: Atlassian writes and Sentry

What a walk checks for the two entries above: C1, C3, C6, C8 and C9 for Atlassian writes, and C0 to C3, C6 and C9 for Sentry. C4 is refused by design for both until TASK-213, so it is not walked. The staging walk of 2026-10-23 (above, #2536) filled the cells staging can reach. Staging has no agent runtime, so a cell that needs an agent to call a tool waits for a walk on commonly.me. #2536 keeps both entries hidden there until that walk passes; the values-dev comment that hides them (#2530) still says a staging walk. A hidden entry refuses every connect, a reconnect included, so the walk needs the hide lifted while it runs. Each result reads `unverified` until a walk replaces it with what it saw and a link to the evidence. Method rules 1 and 2 hold: a stranger account's own session, and every UI cell at 1200 and 390. #2536 does not record which widths it walked.
What a walk checks for the two entries above: C1, C3, C6, C8 and C9 for Atlassian writes, and C0 to C3, C6 and C9 for Sentry. C4 is refused by design for both until TASK-213, so it is not walked. The staging walk of 2026-10-23 (above, #2536) filled the cells staging can reach. Staging has no agent runtime, so a cell that needs an agent to call a tool waits for a walk on commonly.me. #2536 keeps both entries hidden there until that walk passes; the values-dev comment that hides them (#2530) still says a staging walk. A hidden entry refuses every connect, a reconnect included, and every new root grant, from every account but those its walk exception names (#2649, #2658; `docs/runbooks/hosted-mcp-hidden-entry-walks.md`). Sentry's commonly.me walk (above) ran that way, with the hide in place. Each result reads `unverified` until a walk replaces it with what it saw and a link to the evidence. Method rules 1 and 2 hold: a stranger account's own session, and every UI cell at 1200 and 390. #2536 does not record which widths it walked.

**A staging green is not a commonly.me green.** Ready means green on commonly.me against the deployed build, so a cell that passes here is recorded as green on staging. Like "green to the external boundary", it keeps that mark when it is copied into the rows above, and it turns green when the same check passes on commonly.me (Method rule 5).

Expand Down Expand Up @@ -192,9 +209,9 @@ What a walk checks for the two entries above: C1, C3, C6, C8 and C9 for Atlassia
| C0 | A stranger sees the Sentry row on the Connectors page at 1200 and 390, and the catalogue API lists `sentry` with its tools (Method rule 4) | **green on staging except the widths** (2026-10-23, `876870378`, #2536): #2536 does not record whether it walked 1200 and 390 |
| C1 | A stranger connects without an operator, through the CIMD client. At Sentry's consent, select the Triage Issues skill, as #2329 asks. The authorization then appears on Sentry's Authorized Applications page, and the row's `config.grantedScope` records what Sentry granted | **green on staging except the scope** (#2536): consent with only the Inspect and Triage groups, and the row written. Sentry lists the authorization as `mcp.sentry.dev`. Unverified: `config.grantedScope`, which #2536 did not record |
| C2 | The page shows the row connected. A failed call lands as an Activity row that names the failure. Revoke is reachable at 390 | **green on staging except the Activity row** (#2536): a read grant of the 11 reads, made in the walk pod and revoked. Unverified: the Activity row for a failed call, which needs an agent's call, and revoke at 390 |
| C3 | In an eligible pod, a hosted agent completes a read through a pod grant, such as `find_projects`. The trail records it ok, and the answer matches what Sentry's own pages show | unverified |
| C3 | In an eligible pod, a hosted agent completes a read through a pod grant, such as `find_projects`. The trail records it ok, and the answer matches what Sentry's own pages show | **green on commonly.me except the page comparison** (2026-10-25, `c9c0d71c1`, Sharpen TASK-485): `find_organizations` through `grant_d8b399a9`, a `read` pod grant, and the trail records it ok. Unverified: whether the answer matches Sentry's own pages, which TASK-485 does not record |
| C6 | Through a `write-with-confirm` grant, `update_issue` parks, and the card shows the owner its exact arguments. The owner approves one call and declines another. Only the approved one changes the issue in Sentry: it ends `ran` with a receipt in the pod, and the other ends `declined` (`approval_declined`). The seat receives each ending once as `approval.resolved` | unverified |
| C9 | Bounded: the 12 pinned tools are the only ones offered, without the dispatcher, its catalogue or Seer, and `get_sentry_resource` is offered without a `url` argument. Revocable: an `update_issue` call parked before its grant is revoked, then approved, ends `refused` (`grant_revoked`) without changing the issue. A disconnect on the Connectors page calls Sentry's revocation endpoint before deleting the row. Record what Sentry's Authorized Applications page shows afterwards: it lists the client as `mcp.sentry.dev`, and removing it there cuts every Sentry-MCP session on the account (#2536) | unverified. On staging the disconnect's revocation call returned 200 (#2536) |
| C9 | Bounded: the 12 pinned tools are the only ones offered, without the dispatcher, its catalogue or Seer, and `get_sentry_resource` is offered without a `url` argument. Revocable: an `update_issue` call parked before its grant is revoked, then approved, ends `refused` (`grant_revoked`) without changing the issue. A disconnect on the Connectors page calls Sentry's revocation endpoint before deleting the row. Record what Sentry's Authorized Applications page shows afterwards: it lists the client as `mcp.sentry.dev`, and removing it there cuts every Sentry-MCP session on the account (#2536) | **Bounded: green for a read grant on commonly.me** (2026-10-25, `c9c0d71c1`, Sharpen TASK-485). The agent was offered the 11 reads and no other Sentry tool. Unverified: the 12 tools under `write-with-confirm`, `get_sentry_resource` without `url`, and every revocable check. On staging the disconnect's revocation call returned 200 (#2536) |
| C4 | Refused by design until TASK-213 | refused by design |

## Cross-cutting reds
Expand Down
Loading