You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found while implementing #6216 (PR #7259). Filed unassigned, out of that PR's scope on purpose — converging this face would change its output, which #6216's ruling forbids for the faces it names, and this face was not in that card's inventory at all.
The fact
#6216 inventoried three assembly sites (dispatcher, REST, share-link) and converged the two that still assemble. There is a fourth, and it is still hand-written after PR #7259:
packages/mcp/src/plugin.ts — resolveStdioExecutionContext (roughly lines 23-45 at 0caf122f0) builds an ExecutionContext from resolveAuthzContext by hand:
resolves no localization at all (timezone / locale / currency absent), so a write rejected on this face renders in the engine default rather than the caller's workspace language.
Its anonymous contract is the fail-closed one (if (!authz.userId) return undefined), i.e. exactly assembleExecutionContext's default entry.
The shape is the same defect class that produced #6071 (field drift) and #6206 / #6551 (dropped fields, real 403s): a field exists on ExecutionContext, one copy carries it, another silently does not. But converging this site onto the shared assembler would make it start emitting tabPermissions, which is a behaviour change on a surface the ruling did not weigh, so it belongs in its own card with its own argument.
Impact: UNMEASURED, deliberately stated as such
I could not demonstrate a consumer on the stdio surface that reads tabPermissions today (MCP tools do not render tabs), so I am filing this as finding rather than as a defect — but I also could not rule it out, and severity judged at filing time is unreliable in both directions. Please re-grade at triage rather than inheriting my label. The accessToken gap in particular is the one that changed meaning after PR #7259: on the two HTTP faces it is now an explicit per-face decision, and on this one it is still an omission.
Suggested shape if it is taken up
Adopt assembleExecutionContext (the fail-closed default entry, @objectstack/core) here too, and decide tabPermissions / accessToken / localization explicitly rather than by omission — the assembler's input type already forces the accessToken and oauth decisions to be written down.
Found while implementing #6216 (PR #7259). Filed unassigned, out of that PR's scope on purpose — converging this face would change its output, which #6216's ruling forbids for the faces it names, and this face was not in that card's inventory at all.
The fact
#6216 inventoried three assembly sites (dispatcher, REST, share-link) and converged the two that still assemble. There is a fourth, and it is still hand-written after PR #7259:
packages/mcp/src/plugin.ts—resolveStdioExecutionContext(roughly lines 23-45 at0caf122f0) builds anExecutionContextfromresolveAuthzContextby hand:positions,permissions,systemPermissions,isSystem,principalKind: 'human',userId,tenantId,email,posture,org_user_ids,accessible_org_ids;tabPermissions— present onResolvedAuthzContext, carried by both HTTP faces;accessToken— carried by the runtime / MCP HTTP face, and named-as-withheld by REST after PR refactor(core,runtime,rest): one ExecutionContext assembler, two named anonymous entries (#6216) #7259; here it is neither, just absent;timezone/locale/currencyabsent), so a write rejected on this face renders in the engine default rather than the caller's workspace language.Its anonymous contract is the fail-closed one (
if (!authz.userId) return undefined), i.e. exactlyassembleExecutionContext's default entry.Why it is a finding rather than a fix in PR #7259
The shape is the same defect class that produced #6071 (field drift) and #6206 / #6551 (dropped fields, real 403s): a field exists on
ExecutionContext, one copy carries it, another silently does not. But converging this site onto the shared assembler would make it start emittingtabPermissions, which is a behaviour change on a surface the ruling did not weigh, so it belongs in its own card with its own argument.Impact: UNMEASURED, deliberately stated as such
I could not demonstrate a consumer on the stdio surface that reads
tabPermissionstoday (MCP tools do not render tabs), so I am filing this asfindingrather than as a defect — but I also could not rule it out, and severity judged at filing time is unreliable in both directions. Please re-grade at triage rather than inheriting my label. TheaccessTokengap in particular is the one that changed meaning after PR #7259: on the two HTTP faces it is now an explicit per-face decision, and on this one it is still an omission.Suggested shape if it is taken up
Adopt
assembleExecutionContext(the fail-closed default entry,@objectstack/core) here too, and decidetabPermissions/accessToken/ localization explicitly rather than by omission — the assembler's input type already forces theaccessTokenandoauthdecisions to be written down.Related: #6216 / PR #7259, #6071, #6206 / PR #6552, #6551 / PR #6647.