From 259ac688a3a46a9851f1e68925e67ef0a44a4cfd Mon Sep 17 00:00:00 2001 From: Kavya Katal Date: Wed, 21 Oct 2026 10:07:29 +0530 Subject: [PATCH 1/4] fix(setup): reconcile security issue-import caller grants --- plugins/magpie-setup/skills/setup/config.md | 16 ++++++++ .../magpie-setup/skills/setup/reconcile.md | 38 +++++++++++++++++-- tools/skill-evals/README.md | 2 +- tools/skill-evals/evals/setup/README.md | 4 +- .../case-4-import-policy-grants/expected.json | 24 ++++++++++++ .../case-4-import-policy-grants/report.md | 31 +++++++++++++++ .../step-reconcile/fixtures/output-spec.md | 19 ++++++---- .../fixtures/user-prompt-template.md | 2 +- 8 files changed, 121 insertions(+), 15 deletions(-) create mode 100644 tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json create mode 100644 tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md diff --git a/plugins/magpie-setup/skills/setup/config.md b/plugins/magpie-setup/skills/setup/config.md index 82ce7e630..b520156c6 100644 --- a/plugins/magpie-setup/skills/setup/config.md +++ b/plugins/magpie-setup/skills/setup/config.md @@ -270,6 +270,22 @@ When a vetted-ops policy exists, show the `[tracker]` table it needs — and write it only on the user's confirmation; the policy is a security control, not configuration this step may change unasked. Grant the security callers `issue-create`, `issue-search`, `issue-list-label`, `issue-reopen`, `issue-body`, `issue-attach`, `tracker-doctor`, `tracker-pending` and `tracker-publish` in the same diff. +For the security issue-import workflows, also check the policy's `[callers]` +table. When those workflows are configured, propose exactly these grants: + +| Caller | Required operations | +|---|---| +| `security-issue-import` | `rollup-append` | +| `security-issue-import-from-md` | `rollup-append` | +| `security-issue-import-from-pr` | `pr-view-with-body`, `rollup-append` | + +These are separate caller identities. Do not substitute one for another or +grant `body-field-set` to an import caller: none of these workflows invokes it. +Show the proposed policy diff and apply it **only on explicit user confirmation**. +Merge missing operations into an existing caller array; never duplicate a TOML +key, remove existing grants, or change unrelated callers. If no vetted-ops +policy exists, do not create one implicitly. + ## Step 3b — Record what this run reconciled For every skill in scope (Step 1) whose `requires_config:` set now fully diff --git a/plugins/magpie-setup/skills/setup/reconcile.md b/plugins/magpie-setup/skills/setup/reconcile.md index a2ef8cb57..8c4d0cbdf 100644 --- a/plugins/magpie-setup/skills/setup/reconcile.md +++ b/plugins/magpie-setup/skills/setup/reconcile.md @@ -150,6 +150,29 @@ baseline required. name>` requires ``, which is not configured"* — propose `/magpie-setup:setup config ` for it. +3a. **Import caller policy grants.** When an existing vetted-ops policy + is present and a security issue-import skill is in scope (step 1), + read its `[callers]` table. Compare the applicable caller against + the minimum permissions used by the skill: + + Use the exact caller-to-operation mapping in [`config.md` § Step 3a](config.md) for the three security import workflows. Do not infer or add other permissions. + + A missing caller or missing required operation is a finding. Name the + caller, the missing operations, and the existing policy path. Propose + adding only those grants; do not grant `body-field-set`, which these + import workflows do not use. When a caller already exists, merge + missing operations into its existing TOML array rather than creating + a duplicate key. Preserve comments, unrelated callers and existing + permissions. + + This is a security-control change, not an automatic repair. Show the + exact proposed diff and obtain item-by-item confirmation before + writing anything. A declined change leaves the policy unchanged and + the finding unresolved; do not report or stamp that configuration + as clean. If the policy does not exist, mark this check not applicable: + do not create a vetted-ops policy during reconciliation. If the + policy cannot be read or parsed, report it as unchecked, not clean. + 4. **Sandboxed sessions cover what they can reach.** Resolving a skill's anchors (check 2) needs that skill's `SKILL.md` **and its sibling detail files**. On a pinned-snapshot install they sit inside @@ -182,8 +205,8 @@ baseline required. ## Step 1 — Present the findings -List every finding from checks 2–3 as a numbered proposal, one item per -override or `requires_config` gap: +List every finding from checks 2–3a as a numbered proposal, one item per +override, `requires_config` gap, or missing import caller policy grant: ```text 1. .apache-magpie-overrides/issue-triage.md anchors to @@ -195,8 +218,8 @@ override or `requires_config` gap: → /magpie-setup:setup config pr-management-code-review ``` -No findings → say so plainly (*"every configured skill's anchors and -`requires_config` entries resolve"*), name any `unchecked` skills from +No findings → say so plainly (*"every configured skill's anchors, +`requires_config` entries and applicable vetted-ops caller grants resolve"*), name any `unchecked` skills from check 4, and go straight to Step 2 with nothing to confirm — writing the stamp needs no confirmation when nothing is changing. @@ -209,6 +232,13 @@ maintainer's judgement call, not pattern-matching. A `requires_config` gap can be closed mechanically by chaining into `/magpie-setup:setup config `; offer it per item. +For an import caller policy finding (check 3a), show the minimum-grant +TOML diff before asking. Apply it only after confirmation. A refusal does +not authorize a policy edit or a clean reconciliation stamp for that +unresolved configuration. Do not treat resolved `requires_config` files +alone as proof of a clean skill when its required caller grants are missing. +Preserve existing policy content not covered by the confirmed change. + Both `acknowledged` writes below fire **on decline**, not on show — unlike the pre-flight block's own per-skill check ([`tools/dev/preflight-block.md`](../../../../tools/dev/preflight-block.md) diff --git a/tools/skill-evals/README.md b/tools/skill-evals/README.md index 01238f6ca..817b82daa 100644 --- a/tools/skill-evals/README.md +++ b/tools/skill-evals/README.md @@ -11,7 +11,7 @@ Behavioral eval harness for Apache Magpie skills. Each eval suite tests a skill Suites are currently implemented for: -- **setup** — 150 cases across 32 steps (step-verify-drift, step-overrides-surface, step-override-bypass, step-m3-baseline-pick, step-m4-install-gates, step-m5-no-repo-offer, step-m5-companion-offer, step-upgrade-companion-offer, step-adopt-settings-merge, verify-default-set, uninstall-default-set, lock-marketplace-parse, adopt-write-floor, setup-prefill-from-floor, preflight-floor, upgrade-adoption-split, verify-floor, adopt-review-process, adopt-security-list, step-reconcile, step-verify, step-config-stamp, step-config-adversarial, step-config-mail, step-adopt-stamp, step-upgrade-stamp, step-delegate-propose, config-vcs-backend, config-local-custom-parser) +- **setup** — 151 cases across 32 steps (step-verify-drift, step-overrides-surface, step-override-bypass, step-m3-baseline-pick, step-m4-install-gates, step-m5-no-repo-offer, step-m5-companion-offer, step-upgrade-companion-offer, step-adopt-settings-merge, verify-default-set, uninstall-default-set, lock-marketplace-parse, adopt-write-floor, setup-prefill-from-floor, preflight-floor, upgrade-adoption-split, verify-floor, adopt-review-process, adopt-security-list, step-reconcile, step-verify, step-config-stamp, step-config-adversarial, step-config-mail, step-adopt-stamp, step-upgrade-stamp, step-delegate-propose, config-vcs-backend, config-local-custom-parser) - **setup-isolated-setup-install** — 19 cases across 5 steps (runtime-routing, step-snapshot-drift, step-scope-confirm, step-hardware-key, step-roborev-exclusion) - **setup-privacy-llm** — 6 cases across 2 steps (step-1-resolve, step-4-gate) - **setup-shared-config-sync** — 12 cases across 2 steps (step-3-decide-action, step-5-draft-commit) diff --git a/tools/skill-evals/evals/setup/README.md b/tools/skill-evals/evals/setup/README.md index 41e7271e8..1ce628793 100644 --- a/tools/skill-evals/evals/setup/README.md +++ b/tools/skill-evals/evals/setup/README.md @@ -5,7 +5,7 @@ Behavioral evals for the `setup` skill. -## Suites (150 cases total) +## Suites (151 cases total) | Suite | Step | Cases | What it covers | |---|---|---|---| @@ -28,7 +28,7 @@ Behavioral evals for the `setup` skill. | preflight-floor | preflight-block.md § Pre-flight | 22 | at floor (silent), below floor (update), plugin missing (install), foreign marketplace (ask first, run nothing), no `claude` CLI (print), unadopted (propose setup), `apache/magpie` in an alarming context (update anyway, unasked), unreadable `claude plugin list --json` (silent, treated as unknown not absent), first Magpie run (show the general welcome guide, record it, carry on), first utilities run (show the utilities welcome guide, record it, carry on), first mentoring run (show the mentoring welcome guide, record it, carry on), first pairing run (show the pairing welcome guide, record it, carry on), first issue run (show the issue welcome guide, record it, carry on), first pr-management run (show the pr-management welcome guide, record it, carry on), first contributor-growth run (show the contributor-growth welcome guide, record it, carry on), below floor on Codex (marketplace upgrade), below floor on Gemini (update the extension once), at floor on Gemini (silent), first repo-health run (show the repo-health welcome guide, record it, carry on), first setup run (show the setup welcome guide, record it, carry on), first release-management run (show the release-management welcome guide, record it, carry on) | | upgrade-adoption-split | upgrade.md § Step 0b | 4 | not adopted (nothing staged), adopted (floor raised and staged), already ahead (floor unchanged), snapshot method (falls through) | | verify-floor | verify.md § Adoption floor | 4 | no lock (not a fault), ahead of floor with extra plugins (not a fault), a shortfall (a fault), a floor plugin the marketplace no longer ships (a fault, not installed around) | -| step-reconcile | reconcile.md § The sweep | 3 | a clean sweep on a pinned-snapshot install (anchor present, config resolved — stamp written, nothing proposed), a renamed step heading stranding an override's anchor (one re-anchor proposal named), a marketplace install whose plugin cache is sandbox-denied (anchor resolution left `unchecked`, config resolution still completes) | +| step-reconcile | reconcile.md § The sweep | 4 | a clean sweep on a pinned-snapshot install (anchor present, config resolved — stamp written, nothing proposed), a renamed step heading stranding an override's anchor (one re-anchor proposal named), a marketplace install whose plugin cache is sandbox-denied (anchor resolution left `unchecked`, config resolution still completes), a configured security import policy with missing callers and operations (propose minimum grants, do not stamp clean) | | step-verify | verify.md § 12. Latest available plugin version | 2 | a dev-to-dev delta where the marketplace clone is one dev build ahead of an installed plugin (`update_available` carries the newer dev version — pins decision 7: nothing strips `.devN`), and a sandbox-denied marketplace clone (`update_available: null` **and** `unchecked: ["latest-version"]`, distinguishing *nothing newer* from *could not look*) | | step-config-stamp | config.md § Step 3b | 6 | `config` on an already-adopted project where Step 3 wrote the skill's last missing file this run, which records `acknowledged.skills` locally and never touches the committed lock; `config` on an unadopted one, whose entries land in the git-directory home's (`/apache-magpie/reconciled.json`) `skills` map with `version`/`at` regardless of whether this run touched a file; the R2 skip on a repo where nothing has ever been configured or adopted (`write_stamp: false`); and an already-adopted project where the one skill in scope was already fully configured *before* this run, so nothing is recorded even though the lock exists (`write_stamp: false` for a different reason — the narrowed acknowledged-write trigger); a linked worktree of an adopted project with no `.apache-magpie-local/` of its own, which records into the main checkout's (`write_location: main-checkout`); and a linked worktree of an unadopted clone, which records into the shared git-directory home (`write_location: git-dir`) | | config-vcs-backend | config.md § Step 3g | 5 | an SVN working copy as the `` clone beside a Git tracker repo (propose `vcs_backend: svn`, the URLs and `trunk`, written only on confirmation); a plain Git project (write `git`, ask nothing); a git-svn mirror on GitHub (propose svn with the repository root left `TODO`, say an `svn checkout` is needed, never run it); a checkout outside `trunk`/`branches`/`tags` (no default branch proposed); and an SVN checkout whose URLs could not be read (propose `svn`, leave both URLs `TODO` rather than guess) | diff --git a/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json new file mode 100644 index 000000000..49f0aff9b --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json @@ -0,0 +1,24 @@ +{ + "proposals": [ + { + "kind": "policy", + "skill": "security-issue-import", + "override_file": null, + "detail": "Missing caller security-issue-import in .apache-magpie-overrides/tools/vetted-ops/config.toml; propose rollup-append only." + }, + { + "kind": "policy", + "skill": "security-issue-import-from-md", + "override_file": null, + "detail": "Existing caller security-issue-import-from-md lacks rollup-append; preserve its issue-view grant." + }, + { + "kind": "policy", + "skill": "security-issue-import-from-pr", + "override_file": null, + "detail": "Existing caller security-issue-import-from-pr lacks pr-view-with-body; preserve its rollup-append grant." + } + ], + "unchecked": [], + "stamp_written": false +} diff --git a/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md new file mode 100644 index 000000000..0672ac509 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md @@ -0,0 +1,31 @@ + + +Install method: `git-branch` (pinned snapshot). + +Scope: 3 configured security import skills, no override files. +All three skills' `requires_config:` entries resolve from the personal +layer or committed overrides. All their SKILL.md files are readable. +No anchor or required-configuration findings exist. + +Existing vetted-ops policy: +`.apache-magpie-overrides/tools/vetted-ops/config.toml` +The policy is valid TOML and has this `[callers]` section: + +```toml +[callers] +"security-issue-import-from-md" = ["issue-view"] +"security-issue-import-from-pr" = ["rollup-append"] +"security-issue-sync" = ["issue-view", "rollup-append"] +``` + +The following workflows are configured and in scope: + +- `security-issue-import` requires `rollup-append`. +- `security-issue-import-from-md` requires `rollup-append`. +- `security-issue-import-from-pr` requires `pr-view-with-body` + and `rollup-append`. + +No one has confirmed changes to the vetted-ops policy. +Do not modify the policy or write a clean reconciliation stamp. +Return the missing caller/grant proposals only. diff --git a/tools/skill-evals/evals/setup/step-reconcile/fixtures/output-spec.md b/tools/skill-evals/evals/setup/step-reconcile/fixtures/output-spec.md index 8e6d7e623..6bfb5a1db 100644 --- a/tools/skill-evals/evals/setup/step-reconcile/fixtures/output-spec.md +++ b/tools/skill-evals/evals/setup/step-reconcile/fixtures/output-spec.md @@ -9,27 +9,32 @@ Return ONLY valid JSON with this structure: { "proposals": [ { - "kind": "reanchor" | "config", + "kind": "reanchor" | "config" | "policy", "skill": "", - "override_file": "", + "override_file": "", "detail": "" } ], - "unchecked": ["anchor-resolution" | "requires_config"], + "unchecked": ["anchor-resolution" | "requires_config" | "policy-grants"], "stamp_written": true | false } ``` -- `proposals` — one entry per finding from the two checks. `kind: "reanchor"` +- `proposals` — one entry per finding from the reconciliation checks. `kind: "reanchor"` when an override's referenced anchor no longer resolves in the target skill's current `SKILL.md`; `kind: "config"` when a `requires_config` - entry does not resolve through the lookup chain. Empty when both checks - pass cleanly for everything in scope. + entry does not resolve through the lookup chain; `kind: "policy"` when + an applicable import caller or required operation is absent from an + existing vetted-ops policy. Use the caller name as `skill` and name + the exact missing operations in `detail`. Empty when all applicable + checks pass cleanly for everything in scope. - `unchecked` — which check(s) could not be completed for at least one skill in scope, because that skill's `SKILL.md` was not readable this session (a marketplace install's plugin cache, denied under the sandbox). `requires_config` resolution needs only files already in the - repository, so it is never unchecked. Empty when nothing was skipped. + repository, so it is never unchecked. Use `policy-grants` when an + existing vetted-ops policy cannot be read or parsed. A missing + policy is not applicable, not unchecked. Empty when nothing was skipped. - `stamp_written` is `true` only when `proposals` and `unchecked` are both empty — nothing changed, so the stamp is written immediately with no confirmation needed. Any finding, or anything left unchecked, means diff --git a/tools/skill-evals/evals/setup/step-reconcile/fixtures/user-prompt-template.md b/tools/skill-evals/evals/setup/step-reconcile/fixtures/user-prompt-template.md index 57c8c3c8c..0b237e5e4 100644 --- a/tools/skill-evals/evals/setup/step-reconcile/fixtures/user-prompt-template.md +++ b/tools/skill-evals/evals/setup/step-reconcile/fixtures/user-prompt-template.md @@ -5,4 +5,4 @@ {report} -Apply the sweep's two checks and return JSON only. +Apply the reconciliation sweep checks, including applicable vetted-ops import caller grants, and return JSON only. From 3b13bfd336c76b386e0674a954f631c3ff1c20b7 Mon Sep 17 00:00:00 2001 From: Kavya Katal Date: Sat, 31 Oct 2026 03:08:09 +0530 Subject: [PATCH 2/4] fix(setup): reconcile import grants from canonical policy --- plugins/magpie-setup/skills/setup/SKILL.md | 4 +- plugins/magpie-setup/skills/setup/config.md | 46 +++++++++++-------- .../magpie-setup/skills/setup/reconcile.md | 6 ++- .../tools/vetted-ops/README.md | 12 ++++- tools/skill-evals/README.md | 2 +- tools/skill-evals/evals/setup/README.md | 4 +- .../case-4-import-policy-grants/report.md | 22 +++++---- .../expected.json | 12 +++++ .../case-5-declined-import-grant/report.md | 25 ++++++++++ tools/vetted-ops/README.md | 12 ++++- 10 files changed, 110 insertions(+), 35 deletions(-) create mode 100644 tools/skill-evals/evals/setup/step-reconcile/fixtures/case-5-declined-import-grant/expected.json create mode 100644 tools/skill-evals/evals/setup/step-reconcile/fixtures/case-5-declined-import-grant/report.md diff --git a/plugins/magpie-setup/skills/setup/SKILL.md b/plugins/magpie-setup/skills/setup/SKILL.md index 4db647a4f..7f791c847 100644 --- a/plugins/magpie-setup/skills/setup/SKILL.md +++ b/plugins/magpie-setup/skills/setup/SKILL.md @@ -20,9 +20,9 @@ when_to_use: >- to the `welcome-guide` skill. argument-hint: "[install|config|adopt|unadopt|upgrade|worktree-init|verify|reconcile|override skill-name|delegate [skill-name]|welcome|uninstall]" capability: capability:platform -surface_hash: sha256:2557a934f9ea5576 +surface_hash: sha256:cfae279d2c143532 license: Apache-2.0 -measured_tokens: 5307 +measured_tokens: 5306 --- + +Install method: `git-branch` (pinned snapshot). + +Scope: `security-issue-import-from-md` is configured. +Its `requires_config:` entries resolve, and its skill files are readable. +There are no override-anchor or missing-configuration findings. + +Tracker backend: `github`. + +Existing vetted-ops policy: +`.apache-magpie-overrides/tools/vetted-ops/config.toml` + +The policy is valid TOML. Its caller entry is: + "security-issue-import-from-md" = ["issue-view"] + +The vetted-ops README configuration example contains: + "security-issue-import-from-md" = ["rollup-append"] + +During confirmation, the operator declined the proposal +to add `rollup-append` to this caller. +The policy remains unchanged. + +The current reconciliation stamp contains no entry for this skill. diff --git a/tools/vetted-ops/README.md b/tools/vetted-ops/README.md index 152e50f6f..969955825 100644 --- a/tools/vetted-ops/README.md +++ b/tools/vetted-ops/README.md @@ -216,9 +216,19 @@ board_status_field_id = "PVTSSF_…" # its Status field id "body-field-get", "body-field-set"] "security-issue-fix" = ["rollup-append", "rollup-fold", "body-field-get", "body-field-set"] -"security-issue-import" = ["rollup-append"] +"security-issue-import" = ["issue-list-with-bodies", "rollup-append"] "security-issue-import-from-md" = ["rollup-append"] "security-issue-import-from-pr" = ["pr-view-with-body", "rollup-append"] + +# Backend-specific additions for EACH of the three security-issue-import +# callers above (keep all operations already listed for that caller): +# github: no backend-specific additions +# jira: tracker-doctor, issue-body, issue-attach +# local-files: tracker-doctor, issue-body, issue-attach, +# tracker-pending, tracker-publish +# These are conditional additions, not permissions for every backend. +# Derive setup/reconcile proposals from this single example, preserving +# existing grants and never creating a second TOML key for a caller. "security-issue-invalidate" = ["rollup-append", "rollup-amend-latest"] "security-issue-triage" = ["issue-view", "issue-comments", "osv-get-vuln", "osv-query-package"] From 5ae6ddeea5b3b510f7bedee528a12b7e303e36bd Mon Sep 17 00:00:00 2001 From: Kavya Katal Date: Mon, 2 Nov 2026 16:45:30 +0530 Subject: [PATCH 3/4] fix(setup): address security caller reconciliation review --- plugins/magpie-setup/skills/setup/config.md | 4 +- .../magpie-setup/skills/setup/reconcile.md | 13 +++++-- .../tools/vetted-ops/README.md | 38 ++++++++++++++----- tools/skill-evals/README.md | 2 +- tools/skill-evals/evals/setup/README.md | 16 +++++++- tools/skill-evals/evals/setup/runs.jsonl | 3 ++ .../case-1-declined-grant/expected.json | 6 +++ .../fixtures/case-1-declined-grant/report.md | 19 ++++++++++ .../case-2-confirmed-unsaved/expected.json | 6 +++ .../case-2-confirmed-unsaved/report.md | 19 ++++++++++ .../case-3-saved-and-verified/expected.json | 6 +++ .../case-3-saved-and-verified/report.md | 19 ++++++++++ .../fixtures/output-spec.md | 14 +++++++ .../fixtures/step-config.json | 4 ++ .../fixtures/user-prompt-template.md | 8 ++++ .../case-4-import-policy-grants/expected.json | 2 +- .../case-4-import-policy-grants/report.md | 2 +- tools/vetted-ops/README.md | 38 ++++++++++++++----- 18 files changed, 191 insertions(+), 28 deletions(-) create mode 100644 tools/skill-evals/evals/setup/runs.jsonl create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/expected.json create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/report.md create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/expected.json create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/report.md create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/expected.json create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/report.md create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/output-spec.md create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/step-config.json create mode 100644 tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/user-prompt-template.md diff --git a/plugins/magpie-setup/skills/setup/config.md b/plugins/magpie-setup/skills/setup/config.md index 4a2049a34..9fe18cc83 100644 --- a/plugins/magpie-setup/skills/setup/config.md +++ b/plugins/magpie-setup/skills/setup/config.md @@ -325,7 +325,7 @@ When a vetted-ops policy exists, show the `[tracker]` table it needs — `platform`, and `root` or the `jira_*` target (the backend's code comes from the tool installed beside vetted-ops, never from the policy) ([vetted-ops → Tracker backends](../../../../tools/vetted-ops/README.md#tracker-backends)) — and write it only on the user's confirmation; the policy is a security control, not configuration this step may change unasked. -For caller permissions, use the canonical [vetted-ops `[callers]` example](../../../../tools/vetted-ops/README.md#configuration), including only the operations applicable to the selected backend. Do not grant all tracker operations to every security caller. +For **every configured security caller** (not only the three import callers), inspect the tracker operations its workflow actually uses through the [security-tracker command mapping](../../../../tools/security-tracker/contract.md#from-skill-commands-to-vetted-operations). Use the canonical [vetted-ops `[callers]` example](../../../../tools/vetted-ops/README.md#configuration) for its existing base grants, then propose the missing backend-specific operations for that caller only. Include applicable `tracker-doctor`, `issue-view`, `issue-comments`, `issue-create`, `issue-search`, `issue-list-label`, `issue-reopen`, `issue-body`, `issue-attach`, and, for local-files writes, `tracker-pending` and `tracker-publish`. This is an operation checklist, not a blanket permission grant. Show the exact per-caller diff and require confirmation; preserve existing operations and unrelated callers. ### Personal tool configs, for a project that has not adopted Magpie @@ -344,7 +344,7 @@ and the sandbox profile denies the agent's writes to it (`Edit(//**/.git/**/apac So the user saves it themselves, from the draft; never route around that deny to write it. The CVE JSON config is ordinary configuration: write it on the user's yes. -### Import caller grants — independent of tracker selection +## Import caller grants — independent of tracker selection When any security issue-import workflow is configured, check its caller grants even when `tracker.platform` is already configured. Do not make this check diff --git a/plugins/magpie-setup/skills/setup/reconcile.md b/plugins/magpie-setup/skills/setup/reconcile.md index a390576c9..b3f393242 100644 --- a/plugins/magpie-setup/skills/setup/reconcile.md +++ b/plugins/magpie-setup/skills/setup/reconcile.md @@ -251,9 +251,16 @@ operator abandons mid-flow deliberately leaves nothing recorded, so the proposal correctly returns on the next run instead of being silently suppressed by a write that never happened. -- **Confirmed and applied** — the skill's configuration now resolves - cleanly. Its entry in the stamp's `skills:` map is written (or - refreshed) with its **current** `surface_hash`. +- **Confirmed and applied** — verify the resulting configuration + before writing the skill's clean stamp. For import caller policy + findings, re-read and parse the saved vetted-ops policy and confirm + that every required operation for the selected backend is present. + User confirmation of a draft alone is not proof of application. + If the policy is unchanged, missing a grant, or cannot be verified, + leave the finding unresolved and do not stamp that skill clean. + Only after all applicable checks pass may its entry in the stamp's + `skills:` map be written (or refreshed) with its **current** + `surface_hash`. - **Declined** — nothing about the project changes. Write `acknowledged.skills[""]: ` to the local file so the per-skill pre-flight does not re-propose the exact diff --git a/plugins/magpie-vetted-ops/tools/vetted-ops/README.md b/plugins/magpie-vetted-ops/tools/vetted-ops/README.md index 71f006058..fb4256241 100644 --- a/plugins/magpie-vetted-ops/tools/vetted-ops/README.md +++ b/plugins/magpie-vetted-ops/tools/vetted-ops/README.md @@ -220,15 +220,35 @@ board_status_field_id = "PVTSSF_…" # its Status field id "security-issue-import-from-md" = ["rollup-append"] "security-issue-import-from-pr" = ["pr-view-with-body", "rollup-append"] -# Backend-specific additions for EACH of the three security-issue-import -# callers above (keep all operations already listed for that caller): -# github: no backend-specific additions -# jira: tracker-doctor, issue-body, issue-attach -# local-files: tracker-doctor, issue-body, issue-attach, -# tracker-pending, tracker-publish -# These are conditional additions, not permissions for every backend. -# Derive setup/reconcile proposals from this single example, preserving -# existing grants and never creating a second TOML key for a caller. +# Non-GitHub tracker additions, per import caller. +# Add these to the corresponding existing caller array; preserve base grants. +# +# security-issue-import: +# jira: tracker-doctor, issue-search, issue-list, issue-list-label, +# issue-view, issue-comments, issue-comment, issue-create, +# issue-body, issue-attach +# local-files: same as jira, plus tracker-pending, tracker-publish +# +# security-issue-import-from-md: +# jira: tracker-doctor, issue-search, issue-create, +# issue-body, issue-attach +# local-files: same as jira, plus tracker-pending, tracker-publish +# +# security-issue-import-from-pr: +# jira: tracker-doctor, issue-search, issue-create, +# issue-set-milestone, issue-body, issue-attach +# local-files: same as jira, plus tracker-pending, tracker-publish +# +# These are conditional additions, not universal grants. +# issue-list-with-bodies works only with GitHub. The email importer must +# stop on Jira/local-files when this deduplication step is unsupported; +# never bypass the refusal or assume that unmatched reports are new. +# +# Other security callers (sync, fix, CVE allocation, deduplication, +# triage and invalidation) also require their own backend grants. +# Setup derives those from each workflow and the security-tracker contract, +# preserving existing grants and requesting explicit confirmation. +# Do not duplicate TOML keys or grant every operation to every caller. "security-issue-invalidate" = ["rollup-append", "rollup-amend-latest"] "security-issue-triage" = ["issue-view", "issue-comments", "osv-get-vuln", "osv-query-package"] diff --git a/tools/skill-evals/README.md b/tools/skill-evals/README.md index 75e5d8c87..3ce4f9ff8 100644 --- a/tools/skill-evals/README.md +++ b/tools/skill-evals/README.md @@ -11,7 +11,7 @@ Behavioral eval harness for Apache Magpie skills. Each eval suite tests a skill Suites are currently implemented for: -- **setup** — 154 cases across 33 steps (step-verify-drift, step-overrides-surface, step-override-bypass, step-m3-baseline-pick, step-m4-install-gates, step-m5-no-repo-offer, step-m5-companion-offer, step-upgrade-companion-offer, step-adopt-settings-merge, verify-default-set, uninstall-default-set, lock-marketplace-parse, adopt-write-floor, setup-prefill-from-floor, preflight-floor, upgrade-adoption-split, verify-floor, adopt-review-process, adopt-security-list, step-reconcile, step-verify, step-config-stamp, step-config-adversarial, step-config-mail, step-adopt-stamp, step-upgrade-stamp, step-delegate-propose, config-vcs-backend, config-local-custom-parser, adopt-isolation-warning, step-vetted-ops-no-policy, step-unknown-subaction) +- **setup** — 157 cases across 34 steps (step-verify-drift, step-overrides-surface, step-override-bypass, step-m3-baseline-pick, step-m4-install-gates, step-m5-no-repo-offer, step-m5-companion-offer, step-upgrade-companion-offer, step-adopt-settings-merge, verify-default-set, uninstall-default-set, lock-marketplace-parse, adopt-write-floor, setup-prefill-from-floor, preflight-floor, upgrade-adoption-split, verify-floor, adopt-review-process, adopt-security-list, step-reconcile, step-reconcile-confirmation, step-verify, step-config-stamp, step-config-adversarial, step-config-mail, step-adopt-stamp, step-upgrade-stamp, step-delegate-propose, config-vcs-backend, config-local-custom-parser, adopt-isolation-warning, step-vetted-ops-no-policy, step-unknown-subaction) - **setup-isolated-setup-install** — 28 cases across 6 steps (runtime-routing, step-snapshot-drift, step-scope-confirm, step-hardware-key, step-roborev-exclusion, step-hook-manager-shim) - **setup-privacy-llm** — 6 cases across 2 steps (step-1-resolve, step-4-gate) - **setup-shared-config-sync** — 12 cases across 2 steps (step-3-decide-action, step-5-draft-commit) diff --git a/tools/skill-evals/evals/setup/README.md b/tools/skill-evals/evals/setup/README.md index afa656f8e..ba724700e 100644 --- a/tools/skill-evals/evals/setup/README.md +++ b/tools/skill-evals/evals/setup/README.md @@ -5,7 +5,7 @@ Behavioral evals for the `setup` skill. -## Suites (154 cases total) +## Suites (157 cases total) | Suite | Step | Cases | What it covers | |---|---|---|---| @@ -29,7 +29,8 @@ Behavioral evals for the `setup` skill. | welcome-first-run | SKILL.md § First — the welcome guide | 3 | the `setup` skill's own hard-coded welcome check (the setup family runs no shared pre-flight): first Magpie run (show the general guide), general already seen (show the setup guide), both hidden (silent, and no setup finding sneaks in because only the welcome is checked) | | upgrade-adoption-split | upgrade.md § Step 0b | 4 | not adopted (nothing staged), adopted (floor raised and staged), already ahead (floor unchanged), snapshot method (falls through) | | verify-floor | verify.md § Adoption floor | 4 | no lock (not a fault), ahead of floor with extra plugins (not a fault), a shortfall (a fault), a floor plugin the marketplace no longer ships (a fault, not installed around) | -| step-reconcile | reconcile.md § The sweep | 5 | a clean sweep on a pinned-snapshot install (anchor present, config resolved — stamp written, nothing proposed), a renamed step heading stranding an override's anchor (one re-anchor proposal named), a marketplace install whose plugin cache is sandbox-denied (anchor resolution left `unchecked`, config resolution still completes), a configured security import policy with missing callers and operations (propose minimum grants, do not stamp clean) |, and a declined import-grant proposal that must not be stamped clean | +| step-reconcile | reconcile.md § The sweep | 5 | a clean sweep on a pinned-snapshot install (anchor present, config resolved — stamp written, nothing proposed), a renamed step heading stranding an override's anchor (one re-anchor proposal named), a marketplace install whose plugin cache is sandbox-denied (anchor resolution left `unchecked`, config resolution still completes), a configured security import policy with missing callers and operations (propose minimum grants, do not stamp clean), and a declined import-grant proposal that must not be stamped clean | +| step-reconcile-confirmation | reconcile.md § Step 2 — Confirm, apply, and write the stamp | 3 | declined grant, confirmed but unsaved policy, and saved policy with verified grants | | step-verify | verify.md § 12. Latest available plugin version | 2 | a dev-to-dev delta where the marketplace clone is one dev build ahead of an installed plugin (`update_available` carries the newer dev version — pins decision 7: nothing strips `.devN`), and a sandbox-denied marketplace clone (`update_available: null` **and** `unchecked: ["latest-version"]`, distinguishing *nothing newer* from *could not look*) | | step-config-stamp | config.md § Step 3b | 6 | `config` on an already-adopted project where Step 3 wrote the skill's last missing file this run, which records `acknowledged.skills` locally and never touches the committed lock; `config` on an unadopted one, whose entries land in the git-directory home's (`/apache-magpie/reconciled.json`) `skills` map with `version`/`at` regardless of whether this run touched a file; the R2 skip on a repo where nothing has ever been configured or adopted (`write_stamp: false`); and an already-adopted project where the one skill in scope was already fully configured *before* this run, so nothing is recorded even though the lock exists (`write_stamp: false` for a different reason — the narrowed acknowledged-write trigger); a linked worktree of an adopted project with no `.apache-magpie-local/` of its own, which records into the main checkout's (`write_location: main-checkout`); and a linked worktree of an unadopted clone, which records into the shared git-directory home (`write_location: git-dir`) | | config-vcs-backend | config.md § Step 3g | 5 | an SVN working copy as the `` clone beside a Git tracker repo (propose `vcs_backend: svn`, the URLs and `trunk`, written only on confirmation); a plain Git project (write `git`, ask nothing); a git-svn mirror on GitHub (propose svn with the repository root left `TODO`, say an `svn checkout` is needed, never run it); a checkout outside `trunk`/`branches`/`tags` (no default branch proposed); and an SVN checkout whose URLs could not be read (propose `svn`, leave both URLs `TODO` rather than guess) | @@ -143,3 +144,14 @@ uv run --directory tools/skill-evals skill-eval --cli "claude -p" \ `update_available: null` with `unchecked: ["latest-version"]`, never an empty list that a reader could mistake for "checked, nothing found." + +## Run history + +Live model runs over this whole eval directory, newest first. +Generated from [`runs.jsonl`](runs.jsonl) by `skill-eval-journal render`; +do not edit the table by hand. +Columns and rules: [Recording runs](../../README.md#recording-runs). + +| Date | Ref | Model | Runs | Result | Notes | +|---|---|---|---|---|---| +| 2026-11-02 | `5eb60e27` (fix/pr-1749-review-round2) | (unrecorded, `claude -p`) | 3 | `step-reconcile/case-2-stale-anchor` failed 1 of 2; `step-reconcile/case-4-import-policy-grants` failed 1 of 2 | | diff --git a/tools/skill-evals/evals/setup/runs.jsonl b/tools/skill-evals/evals/setup/runs.jsonl new file mode 100644 index 000000000..1f98c56a1 --- /dev/null +++ b/tools/skill-evals/evals/setup/runs.jsonl @@ -0,0 +1,3 @@ +{"branch": "fix/pr-1749-review-round2", "cases": 5, "cli": "claude -p", "cost": {"cli_calls": 5, "grader_calls": 2, "wall_seconds": 102.3}, "date": "2026-11-02", "dirty": true, "errored": 0, "errored_cases": [], "failed": 2, "failed_cases": ["step-reconcile/case-2-stale-anchor", "step-reconcile/case-4-import-policy-grants"], "graded_cases": ["step-reconcile/case-1-clean-sweep", "step-reconcile/case-2-stale-anchor", "step-reconcile/case-3-sandboxed-run", "step-reconcile/case-4-import-policy-grants", "step-reconcile/case-5-declined-import-grant"], "grader_cli": "claude -p --model haiku", "manual": 0, "model": null, "model_source": null, "notes": "", "passed": 3, "path": "tools/skill-evals/evals/setup/step-reconcile/fixtures", "ref": "5eb60e27", "schema": 1, "skill": "setup", "tags": [], "timestamp": "2026-11-02T06:21:33Z"} +{"branch": "fix/pr-1749-review-round2", "cases": 5, "cli": "claude -p", "cost": {"cli_calls": 5, "grader_calls": 3, "wall_seconds": 166.8}, "date": "2026-11-02", "dirty": true, "errored": 0, "errored_cases": [], "failed": 0, "failed_cases": [], "graded_cases": ["step-reconcile/case-1-clean-sweep", "step-reconcile/case-2-stale-anchor", "step-reconcile/case-3-sandboxed-run", "step-reconcile/case-4-import-policy-grants", "step-reconcile/case-5-declined-import-grant"], "grader_cli": "claude -p --model haiku", "manual": 0, "model": null, "model_source": null, "notes": "", "passed": 5, "path": "tools/skill-evals/evals/setup/step-reconcile/fixtures", "ref": "5eb60e27", "schema": 1, "skill": "setup", "tags": [], "timestamp": "2026-11-02T06:27:10Z"} +{"branch": "fix/pr-1749-review-round2", "cases": 3, "cli": "claude -p", "cost": {"cli_calls": 3, "grader_calls": 0, "wall_seconds": 26.0}, "date": "2026-11-02", "dirty": true, "errored": 0, "errored_cases": [], "failed": 0, "failed_cases": [], "graded_cases": ["step-reconcile-confirmation/case-1-declined-grant", "step-reconcile-confirmation/case-2-confirmed-unsaved", "step-reconcile-confirmation/case-3-saved-and-verified"], "grader_cli": "claude -p --model haiku", "manual": 0, "model": null, "model_source": null, "notes": "", "passed": 3, "path": "tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures", "ref": "5eb60e27", "schema": 1, "skill": "setup", "tags": [], "timestamp": "2026-11-02T06:28:09Z"} diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/expected.json b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/expected.json new file mode 100644 index 000000000..284b14d59 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/expected.json @@ -0,0 +1,6 @@ +{ + "decision": "declined", + "policy_verified": false, + "policy_changed": false, + "stamp_written": false +} diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/report.md b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/report.md new file mode 100644 index 000000000..4f0b46fc8 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-1-declined-grant/report.md @@ -0,0 +1,19 @@ + + +The configured skill is `security-issue-import-from-md`. +All override anchors and required configuration files resolve. +The tracker backend is `github`. + +Existing policy: `.apache-magpie-overrides/tools/vetted-ops/config.toml`. + +The original saved caller entry was: + + "security-issue-import-from-md" = ["issue-view"] + +The applicable canonical requirement is `rollup-append`. +The proposed diff adds only that operation. + +The operator declined the proposed rollup-append grant. The saved policy remains unchanged. + +The current stamp has no entry for this skill. diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/expected.json b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/expected.json new file mode 100644 index 000000000..64efed35b --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/expected.json @@ -0,0 +1,6 @@ +{ + "decision": "confirmed", + "policy_verified": false, + "policy_changed": false, + "stamp_written": false +} diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/report.md b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/report.md new file mode 100644 index 000000000..5b040f0be --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-2-confirmed-unsaved/report.md @@ -0,0 +1,19 @@ + + +The configured skill is `security-issue-import-from-md`. +All override anchors and required configuration files resolve. +The tracker backend is `github`. + +Existing policy: `.apache-magpie-overrides/tools/vetted-ops/config.toml`. + +The original saved caller entry was: + + "security-issue-import-from-md" = ["issue-view"] + +The applicable canonical requirement is `rollup-append`. +The proposed diff adds only that operation. + +The operator confirmed the proposed grant, but has not saved the policy. Re-reading the saved policy still shows only issue-view. + +The current stamp has no entry for this skill. diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/expected.json b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/expected.json new file mode 100644 index 000000000..9278a1165 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/expected.json @@ -0,0 +1,6 @@ +{ + "decision": "confirmed", + "policy_verified": true, + "policy_changed": true, + "stamp_written": true +} diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/report.md b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/report.md new file mode 100644 index 000000000..03fb129a5 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/case-3-saved-and-verified/report.md @@ -0,0 +1,19 @@ + + +The configured skill is `security-issue-import-from-md`. +All override anchors and required configuration files resolve. +The tracker backend is `github`. + +Existing policy: `.apache-magpie-overrides/tools/vetted-ops/config.toml`. + +The original saved caller entry was: + + "security-issue-import-from-md" = ["issue-view"] + +The applicable canonical requirement is `rollup-append`. +The proposed diff adds only that operation. + +The operator confirmed the change and saved the policy. A fresh read of the saved policy shows both issue-view and rollup-append. All other applicable checks passed. + +The current stamp has no entry for this skill. diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/output-spec.md b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/output-spec.md new file mode 100644 index 000000000..ed8818bf5 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/output-spec.md @@ -0,0 +1,14 @@ + + +## Output format + +Return ONLY valid JSON with these fields: + +- `decision`: `"declined"` or `"confirmed"` +- `policy_verified`: boolean; true only when the saved policy has been + re-read and all required grants are present. +- `policy_changed`: boolean; whether the saved policy actually changed. +- `stamp_written`: boolean; whether this skill was stamped clean. + +Return no additional text. diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/step-config.json b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/step-config.json new file mode 100644 index 000000000..9562e8943 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/step-config.json @@ -0,0 +1,4 @@ +{ + "skill_md": "skills/setup/reconcile.md", + "step_heading": "## Step 2 \u2014 Confirm, apply, and write the stamp" +} diff --git a/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/user-prompt-template.md b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/user-prompt-template.md new file mode 100644 index 000000000..edca4fed2 --- /dev/null +++ b/tools/skill-evals/evals/setup/step-reconcile-confirmation/fixtures/user-prompt-template.md @@ -0,0 +1,8 @@ + + +## Reconciliation confirmation state + +{report} + +Apply Step 2's confirmation and stamping rules. Return JSON only. diff --git a/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json index 49f0aff9b..9e6886291 100644 --- a/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json +++ b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/expected.json @@ -4,7 +4,7 @@ "kind": "policy", "skill": "security-issue-import", "override_file": null, - "detail": "Missing caller security-issue-import in .apache-magpie-overrides/tools/vetted-ops/config.toml; propose rollup-append only." + "detail": "Missing caller security-issue-import in .apache-magpie-overrides/tools/vetted-ops/config.toml; propose issue-list-with-bodies and rollup-append." }, { "kind": "policy", diff --git a/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md index 888184016..419c62fa3 100644 --- a/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md +++ b/tools/skill-evals/evals/setup/step-reconcile/fixtures/case-4-import-policy-grants/report.md @@ -30,7 +30,7 @@ Tracker backend: `github`. The framework's vetted-ops README provides this example: [callers] -"security-issue-import" = ["rollup-append"] +"security-issue-import" = ["issue-list-with-bodies", "rollup-append"] "security-issue-import-from-md" = ["rollup-append"] "security-issue-import-from-pr" = ["pr-view-with-body", "rollup-append"] diff --git a/tools/vetted-ops/README.md b/tools/vetted-ops/README.md index 00c49fadb..1081d913c 100644 --- a/tools/vetted-ops/README.md +++ b/tools/vetted-ops/README.md @@ -220,15 +220,35 @@ board_status_field_id = "PVTSSF_…" # its Status field id "security-issue-import-from-md" = ["rollup-append"] "security-issue-import-from-pr" = ["pr-view-with-body", "rollup-append"] -# Backend-specific additions for EACH of the three security-issue-import -# callers above (keep all operations already listed for that caller): -# github: no backend-specific additions -# jira: tracker-doctor, issue-body, issue-attach -# local-files: tracker-doctor, issue-body, issue-attach, -# tracker-pending, tracker-publish -# These are conditional additions, not permissions for every backend. -# Derive setup/reconcile proposals from this single example, preserving -# existing grants and never creating a second TOML key for a caller. +# Non-GitHub tracker additions, per import caller. +# Add these to the corresponding existing caller array; preserve base grants. +# +# security-issue-import: +# jira: tracker-doctor, issue-search, issue-list, issue-list-label, +# issue-view, issue-comments, issue-comment, issue-create, +# issue-body, issue-attach +# local-files: same as jira, plus tracker-pending, tracker-publish +# +# security-issue-import-from-md: +# jira: tracker-doctor, issue-search, issue-create, +# issue-body, issue-attach +# local-files: same as jira, plus tracker-pending, tracker-publish +# +# security-issue-import-from-pr: +# jira: tracker-doctor, issue-search, issue-create, +# issue-set-milestone, issue-body, issue-attach +# local-files: same as jira, plus tracker-pending, tracker-publish +# +# These are conditional additions, not universal grants. +# issue-list-with-bodies works only with GitHub. The email importer must +# stop on Jira/local-files when this deduplication step is unsupported; +# never bypass the refusal or assume that unmatched reports are new. +# +# Other security callers (sync, fix, CVE allocation, deduplication, +# triage and invalidation) also require their own backend grants. +# Setup derives those from each workflow and the security-tracker contract, +# preserving existing grants and requesting explicit confirmation. +# Do not duplicate TOML keys or grant every operation to every caller. "security-issue-invalidate" = ["rollup-append", "rollup-amend-latest"] "security-issue-triage" = ["issue-view", "issue-comments", "osv-get-vuln", "osv-query-package"] From 8dd02160292ddee61de7f12cb3ac70d9695a13ad Mon Sep 17 00:00:00 2001 From: Jarek Potiuk Date: Mon, 2 Nov 2026 15:27:39 +0100 Subject: [PATCH 4/4] docs(vetted-ops): grant issue-view to the md and PR import callers on Jira security-issue-import-from-md and security-issue-import-from-pr read the issue's labels with issue-view before regenerating the CVE JSON on a non-GitHub tracker, so a policy reconciled from the README example stopped at that step with "operation not permitted". Add issue-view to both callers' Jira lists (local-files inherits it), in both README copies. Generated-by: Claude Opus 5 --- plugins/magpie-vetted-ops/tools/vetted-ops/README.md | 4 ++-- tools/vetted-ops/README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugins/magpie-vetted-ops/tools/vetted-ops/README.md b/plugins/magpie-vetted-ops/tools/vetted-ops/README.md index 27a8afba8..6854c6d1b 100644 --- a/plugins/magpie-vetted-ops/tools/vetted-ops/README.md +++ b/plugins/magpie-vetted-ops/tools/vetted-ops/README.md @@ -231,12 +231,12 @@ board_status_field_id = "PVTSSF_…" # its Status field id # local-files: same as jira, plus tracker-pending, tracker-publish # # security-issue-import-from-md: -# jira: tracker-doctor, issue-search, issue-create, +# jira: tracker-doctor, issue-search, issue-view, issue-create, # issue-body, issue-attach # local-files: same as jira, plus tracker-pending, tracker-publish # # security-issue-import-from-pr: -# jira: tracker-doctor, issue-search, issue-create, +# jira: tracker-doctor, issue-search, issue-view, issue-create, # issue-set-milestone, issue-body, issue-attach # local-files: same as jira, plus tracker-pending, tracker-publish # diff --git a/tools/vetted-ops/README.md b/tools/vetted-ops/README.md index 60e35322f..1697d53b5 100644 --- a/tools/vetted-ops/README.md +++ b/tools/vetted-ops/README.md @@ -231,12 +231,12 @@ board_status_field_id = "PVTSSF_…" # its Status field id # local-files: same as jira, plus tracker-pending, tracker-publish # # security-issue-import-from-md: -# jira: tracker-doctor, issue-search, issue-create, +# jira: tracker-doctor, issue-search, issue-view, issue-create, # issue-body, issue-attach # local-files: same as jira, plus tracker-pending, tracker-publish # # security-issue-import-from-pr: -# jira: tracker-doctor, issue-search, issue-create, +# jira: tracker-doctor, issue-search, issue-view, issue-create, # issue-set-milestone, issue-body, issue-attach # local-files: same as jira, plus tracker-pending, tracker-publish #