Skip to content

permissions: type ApprovalContext.toolOrigin as OwnerKind#32339

Merged
dvargasfuertes merged 1 commit into
mainfrom
apollo/tool-origin-as-owner-kind
May 27, 2026
Merged

permissions: type ApprovalContext.toolOrigin as OwnerKind#32339
dvargasfuertes merged 1 commit into
mainfrom
apollo/tool-origin-as-owner-kind

Conversation

@vellum-apollo-bot
Copy link
Copy Markdown
Contributor

Follow-up to PR #32294 review. The toolOrigin field on
ApprovalContext was carrying a lossy projection ("skill" | "builtin")
of the registry's OwnerKind ("skill" | "plugin" | "mcp"):

  • skill + plugin → projected to "skill"
  • mcp + core → projected to "builtin"

The projection was implemented as an IIFE on the construction site in
checker.ts, which obscured the underlying source of truth and forced
every downstream consumer to reason about a custom union that doesn't
match what the rest of the codebase uses.

This PR matches the consumer's type to the source of truth:

  • ApprovalContext.toolOrigin?: OwnerKind — same union the registry
    exposes via getToolOwner(name)?.kind.
  • checker.ts drops the IIFE — toolOrigin: getToolOwner(toolName)?.kind
    is a one-liner that exposes the full ownership signal.
  • approval-policy.ts section 6 ("third-party skill tool") now spells
    out the disjunction the projection was hiding:
    toolOrigin === "skill" || toolOrigin === "plugin"
    Behavior preserved: skill and plugin tools are both treated as
    extension-class for approval; MCP and core tools fall through to the
    risk-based path. Section 8 ("bundled skill") stays as
    toolOrigin === "skill" — gated by isSkillBundled which is
    skill-only by construction.

Test changes

  • approval-policy.test.ts: the one toolOrigin: "builtin" literal —
    testing "non-extension owner with manifest override falls through" —
    reframed to toolOrigin: "mcp", which preserves the intent ("the
    third-party clause doesn't fire when toolOrigin is set to a
    non-extension kind") under the richer type.
  • Added a toolOrigin: "plugin" case that locks in the plugin →
    extension-owned routing the disjunction now expresses explicitly.
    Without it, a future refactor could silently drop the || "plugin"
    arm and the existing skill-only tests wouldn't catch it.

Verification

  • bunx tsc --noEmit clean across assistant.
  • bunx eslint clean on all three touched files.
  • bun test src/permissions/approval-policy.test.ts src/__tests__/checker.test.ts
    → 212 / 212 pass.

Follow-up to PR #32294 review. The `toolOrigin` field on
`ApprovalContext` was carrying a lossy projection ("skill" | "builtin")
of the registry's `OwnerKind` ("skill" | "plugin" | "mcp"):

- skill + plugin → projected to "skill"
- mcp + core → projected to "builtin"

The projection was implemented as an IIFE on the construction site in
`checker.ts`, which obscured the underlying source of truth and forced
every downstream consumer to reason about a custom union that doesn't
match what the rest of the codebase uses.

This PR matches the consumer's type to the source of truth:

- `ApprovalContext.toolOrigin?: OwnerKind` — same union the registry
  exposes via `getToolOwner(name)?.kind`.
- `checker.ts` drops the IIFE — `toolOrigin: getToolOwner(toolName)?.kind`
  is a one-liner that exposes the full ownership signal.
- `approval-policy.ts` section 6 ("third-party skill tool") now spells
  out the disjunction the projection was hiding:
    `toolOrigin === "skill" || toolOrigin === "plugin"`
  Behavior preserved: skill and plugin tools are both treated as
  extension-class for approval; MCP and core tools fall through to the
  risk-based path. Section 8 ("bundled skill") stays as
  `toolOrigin === "skill"` — gated by `isSkillBundled` which is
  skill-only by construction.

## Test changes

- `approval-policy.test.ts`: the one `toolOrigin: "builtin"` literal —
  testing "non-extension owner with manifest override falls through" —
  reframed to `toolOrigin: "mcp"`, which preserves the intent ("the
  third-party clause doesn't fire when toolOrigin is set to a
  non-extension kind") under the richer type.
- Added a `toolOrigin: "plugin"` case that locks in the plugin →
  extension-owned routing the disjunction now expresses explicitly.
  Without it, a future refactor could silently drop the `|| "plugin"`
  arm and the existing skill-only tests wouldn't catch it.

## Verification

- `bunx tsc --noEmit` clean across assistant.
- `bunx eslint` clean on all three touched files.
- `bun test src/permissions/approval-policy.test.ts src/__tests__/checker.test.ts`
  → 212 / 212 pass.
@vellum-apollo-bot vellum-apollo-bot Bot requested a review from noanflaherty as a code owner May 27, 2026 22:10
@dvargasfuertes dvargasfuertes merged commit 3112c21 into main May 27, 2026
13 checks passed
@dvargasfuertes dvargasfuertes deleted the apollo/tool-origin-as-owner-kind branch May 27, 2026 22:39
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