From 1f532b179a58b498bc134295a2d7aeeaeb2651c1 Mon Sep 17 00:00:00 2001 From: LubuSeb <187313664+LubuSeb@users.noreply.github.com> Date: Mon, 22 Jun 2026 16:32:22 +0200 Subject: [PATCH 1/3] Add least privilege plan skill --- skills/least-privilege-plan/SKILL.md | 63 + skills/least-privilege-plan/X.yaml | 171 +++ .../evidence/clean-install.json | 43 + .../evidence/dogfood-output.json | 1341 ++++++++++++++++ .../evidence/dogfood-receipts-linux.tgz | Bin 0 -> 1510 bytes .../evidence/hosted-dogfood-output.json | 1352 +++++++++++++++++ .../hosted-dogfood-receipts-linux.tgz | Bin 0 -> 1511 bytes .../hosted-harness-receipts-linux.tgz | Bin 0 -> 2447 bytes .../evidence/hosted-harness-verification.json | 29 + .../evidence/hosted-harness.json | 17 + .../evidence/hosted-verification.json | 15 + .../evidence/local-harness-receipts-linux.tgz | Bin 0 -> 2435 bytes .../evidence/local-harness-verification.json | 29 + .../evidence/local-harness.json | 17 + .../evidence/registry-publish.json | 20 + .../evidence/registry-read.json | 50 + .../evidence/runx-version.txt | 1 + .../evidence/verification.json | 15 + .../fixtures/over-broad-run-history.json | 64 + .../least-privilege-plan/fixtures/policy.json | 8 + skills/least-privilege-plan/run.mjs | 334 ++++ 21 files changed, 3569 insertions(+) create mode 100644 skills/least-privilege-plan/SKILL.md create mode 100644 skills/least-privilege-plan/X.yaml create mode 100644 skills/least-privilege-plan/evidence/clean-install.json create mode 100644 skills/least-privilege-plan/evidence/dogfood-output.json create mode 100644 skills/least-privilege-plan/evidence/dogfood-receipts-linux.tgz create mode 100644 skills/least-privilege-plan/evidence/hosted-dogfood-output.json create mode 100644 skills/least-privilege-plan/evidence/hosted-dogfood-receipts-linux.tgz create mode 100644 skills/least-privilege-plan/evidence/hosted-harness-receipts-linux.tgz create mode 100644 skills/least-privilege-plan/evidence/hosted-harness-verification.json create mode 100644 skills/least-privilege-plan/evidence/hosted-harness.json create mode 100644 skills/least-privilege-plan/evidence/hosted-verification.json create mode 100644 skills/least-privilege-plan/evidence/local-harness-receipts-linux.tgz create mode 100644 skills/least-privilege-plan/evidence/local-harness-verification.json create mode 100644 skills/least-privilege-plan/evidence/local-harness.json create mode 100644 skills/least-privilege-plan/evidence/registry-publish.json create mode 100644 skills/least-privilege-plan/evidence/registry-read.json create mode 100644 skills/least-privilege-plan/evidence/runx-version.txt create mode 100644 skills/least-privilege-plan/evidence/verification.json create mode 100644 skills/least-privilege-plan/fixtures/over-broad-run-history.json create mode 100644 skills/least-privilege-plan/fixtures/policy.json create mode 100644 skills/least-privilege-plan/run.mjs diff --git a/skills/least-privilege-plan/SKILL.md b/skills/least-privilege-plan/SKILL.md new file mode 100644 index 00000000..8691e4f0 --- /dev/null +++ b/skills/least-privilege-plan/SKILL.md @@ -0,0 +1,63 @@ +--- +name: least-privilege-plan +description: Produce a read-only least-privilege grant plan from bounded run history and a declared policy. +source: + type: cli-tool + command: node + args: + - run.mjs + input_mode: stdin + cwd: . + timeout_seconds: 30 +inputs: + run_history_packet: + type: json + required: true + description: Bounded run history containing grants, observed effects, receipt refs, and missing-evidence notes. + policy: + type: json + required: true + description: Declared least-privilege policy with grant metadata, reserved scopes, and review rules. + objective: + type: string + required: false + description: Optional operator intent for the plan. +runx: + category: security + input_resolution: + required: + - run_history_packet + - policy +--- + +# least-privilege-plan + +Use this skill when an operator needs a read-only plan for narrowing granted +authority after one or more runs. The skill compares a bounded run history +packet against a declared policy and emits keep, reduce, revoke, and +needs_human_review recommendations with cited evidence. + +The skill does not mutate grants, write credentials, call provider APIs, or infer +authority from broad task success. Every recommendation cites exact observed +effects, policy inputs, unused scopes, or missing evidence so a reviewer can +apply the plan separately. + +## Inputs + +- `run_history_packet`: bounded JSON with `subject`, `policy_id`, `grants`, + `observed_effects`, `receipt_refs`, and optional `missing_evidence`. +- `policy`: declared JSON policy with grant metadata, reserved scopes, wildcard + rules, and review thresholds. +- `objective`: optional operator intent. + +## Output + +The runner returns JSON with: + +- `plan`: the typed least-privilege plan. +- `recommendations`: one recommendation per grant. +- `evidence_json`: a compact evidence object suitable for external review. +- `report`: a human-readable summary. + +Recommendation actions are exactly `keep`, `reduce`, `revoke`, and +`needs_human_review`. diff --git a/skills/least-privilege-plan/X.yaml b/skills/least-privilege-plan/X.yaml new file mode 100644 index 00000000..d03f44e0 --- /dev/null +++ b/skills/least-privilege-plan/X.yaml @@ -0,0 +1,171 @@ +skill: least-privilege-plan +version: "0.1.0" + +catalog: + kind: skill + audience: public + visibility: public + role: canonical + +policy: + side_effects: none + grant_mutation: denied + network_during_run: denied + secrets_required: false + filesystem: + read: [] + write: [] + +harness: + cases: + - name: over-broad-grant-plan + runner: default + inputs: + objective: "Prepare a hosted skill for grant reduction before renewal." + policy: + policy_id: runx-policy-demo-v1 + review_rules: + wildcard_reduction_allowed: true + require_human_review_for_denied_secret: true + reserved_grants: + - grant-breakglass + run_history_packet: + subject: skills/sourcey-docs + policy_id: runx-policy-demo-v1 + receipt_refs: + - runx:receipt:sha256:111 + - runx:receipt:sha256:222 + grants: + - grant_id: grant-read-all + scope: repo.read:github/LubuSeb/sourcey-demo/* + declared_policy_ref: policy:repo-read + - grant_id: grant-write-issues + scope: repo.write:github/LubuSeb/sourcey-demo/issues/* + declared_policy_ref: policy:issue-write + - grant_id: grant-delete + scope: repo.delete:github/LubuSeb/sourcey-demo/* + declared_policy_ref: policy:delete + - grant_id: grant-secret-prod + scope: secret.read:prod/* + declared_policy_ref: policy:secret-breakglass + - grant_id: grant-breakglass + scope: incident.breakglass:runx/* + declared_policy_ref: policy:reserved + observed_effects: + - effect_id: e-read-issue + grant_id: grant-read-all + verb: repo.read + resource: github/LubuSeb/sourcey-demo/issues/81 + status: success + receipt_ref: runx:receipt:sha256:111#read_issue + - effect_id: e-write-comment + grant_id: grant-write-issues + verb: repo.write + resource: github/LubuSeb/sourcey-demo/issues/81/comments + status: success + receipt_ref: runx:receipt:sha256:222#comment + - effect_id: e-secret-denied + grant_id: grant-secret-prod + verb: secret.read + resource: prod/frantic-agent-token + status: denied + receipt_ref: runx:receipt:sha256:222#secret_denied + missing_evidence: + - grant_id: grant-secret-prod + reason: "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + expect: + status: sealed + receipt: + schema: runx.receipt.v1 + state: sealed + disposition: closed + reason_code: process_closed + + - name: justified-grant-plan + runner: default + inputs: + objective: "Check that observed usage justifies the current production grant." + policy: + policy_id: runx-policy-justified-v1 + review_rules: + wildcard_reduction_allowed: true + reserved_grants: [] + run_history_packet: + subject: skills/receipt-verifier + policy_id: runx-policy-justified-v1 + receipt_refs: + - runx:receipt:sha256:333 + grants: + - grant_id: grant-receipt-read + scope: receipt.read:runx/receipts/sha256:333 + declared_policy_ref: policy:receipt-read + - grant_id: grant-output-read + scope: artifact.read:runx/outputs/plan.json + declared_policy_ref: policy:artifact-read + observed_effects: + - effect_id: e-receipt-read + grant_id: grant-receipt-read + verb: receipt.read + resource: runx/receipts/sha256:333 + status: success + receipt_ref: runx:receipt:sha256:333#receipt_read + - effect_id: e-output-read + grant_id: grant-output-read + verb: artifact.read + resource: runx/outputs/plan.json + status: success + receipt_ref: runx:receipt:sha256:333#artifact_read + expect: + status: sealed + receipt: + schema: runx.receipt.v1 + state: sealed + disposition: closed + reason_code: process_closed + + - name: missing-grants-fails-closed + runner: default + inputs: + objective: "Reject incomplete run history packets instead of guessing authority." + policy: + policy_id: runx-policy-invalid-v1 + review_rules: + wildcard_reduction_allowed: true + reserved_grants: [] + run_history_packet: + subject: skills/incomplete + policy_id: runx-policy-invalid-v1 + receipt_refs: [] + observed_effects: [] + expect: + status: failure + +runners: + default: + default: true + type: cli-tool + command: node + input_mode: stdin + args: + - run.mjs + outputs: + plan: object + recommendations: array + evidence_json: object + report: string + artifacts: + wrap_as: least_privilege_plan_packet + packet: runx.security.least_privilege_plan.v1 + inputs: + run_history_packet: + type: json + required: true + description: Bounded run history containing grant ids, scopes, effects, receipt refs, and missing evidence. + policy: + type: json + required: true + description: Declared least-privilege policy. + objective: + type: string + required: false + description: Operator intent for the review. diff --git a/skills/least-privilege-plan/evidence/clean-install.json b/skills/least-privilege-plan/evidence/clean-install.json new file mode 100644 index 00000000..bea956a4 --- /dev/null +++ b/skills/least-privilege-plan/evidence/clean-install.json @@ -0,0 +1,43 @@ +{ + "status": "success", + "registry": { + "action": "install", + "source": "remote", + "ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "install": { + "status": "installed", + "destination": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745/SKILL.md", + "skill_name": "least-privilege-plan", + "source": "runx-registry", + "source_label": "runx registry", + "skill_id": "lubuseb/least-privilege-plan", + "version": "sha-e2d0eec62745", + "digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", + "profile_digest": "sha256:f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "profile_state_path": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745/.runx/profile.json", + "runner_names": [ + "default" + ], + "trust_tier": "community" + }, + "receipt_metadata": { + "destination": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745/SKILL.md", + "digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", + "install_count": 1, + "package_digest": "56702fe284f54bf0a115550c773b53328e803a0f452d1b93106d8002493c6534", + "profile_digest": "sha256:f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "publisher": { + "display_name": "LubuSeb", + "handle": "lubuseb", + "id": "user_53f00ae7ec2363e37ac6ff68", + "kind": "user" + }, + "ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "skill_id": "lubuseb/least-privilege-plan", + "source_label": "runx registry", + "status": "installed", + "trust_tier": "community", + "version": "sha-e2d0eec62745" + } + } +} diff --git a/skills/least-privilege-plan/evidence/dogfood-output.json b/skills/least-privilege-plan/evidence/dogfood-output.json new file mode 100644 index 00000000..750a70a0 --- /dev/null +++ b/skills/least-privilege-plan/evidence/dogfood-output.json @@ -0,0 +1,1341 @@ +{ + "closure": { + "closed_at": "2026-06-22T14:29:51.345Z", + "disposition": "closed", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "execution": { + "exit_code": 0, + "skill_claim": { + "evidence_json": { + "artifact": "least-privilege-plan", + "observations": { + "grant_ids": [ + "grant-read-all", + "grant-write-issues", + "grant-delete", + "grant-secret-prod", + "grant-breakglass" + ], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "grant_id": "grant-read-all", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + }, + { + "effect_id": "e-write-comment", + "grant_id": "grant-write-issues", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + }, + { + "effect_id": "e-secret-denied", + "grant_id": "grant-secret-prod", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_digest": "sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9", + "policy_id": "runx-policy-demo-v1", + "receipt_refs": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "recommendations": [ + { + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "recommendation": "reduce" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "recommendation": "reduce" + }, + { + "evidence_refs": [], + "grant_id": "grant-delete", + "proposed_scope": null, + "recommendation": "revoke" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "proposed_scope": null, + "recommendation": "needs_human_review" + }, + { + "evidence_refs": [], + "grant_id": "grant-breakglass", + "proposed_scope": null, + "recommendation": "keep" + } + ], + "run_history_digest": "sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965", + "subject": "skills/sourcey-docs", + "unused_scopes": [ + { + "grant_id": "grant-delete", + "scope": "repo.delete:github/LubuSeb/sourcey-demo/*" + } + ] + }, + "schema": "frantic.delivery.evidence.v1" + }, + "plan": { + "objective": "Dogfood least privilege plan for Frantic bounty 37.", + "policy_id": "runx-policy-demo-v1", + "proposed_grants": [ + { + "grant_id": "grant-read-all", + "scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "source": "reduce" + }, + { + "grant_id": "grant-write-issues", + "scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "source": "reduce" + }, + { + "grant_id": "grant-breakglass", + "scope": "incident.breakglass:runx/*", + "source": "keep" + } + ], + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "safeguards": { + "mutates_grants": false, + "network_required": false, + "read_only": true, + "secrets_required": false + }, + "schema": "runx.security.least_privilege_plan.v1", + "source_receipts": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "status": "needs_human_review", + "subject": "skills/sourcey-docs", + "summary": { + "grant_count": 5, + "observed_effect_count": 3, + "recommendation_counts": { + "keep": 1, + "needs_human_review": 1, + "reduce": 2, + "revoke": 1 + } + } + }, + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "report": "# least-privilege-plan report\n\nSubject: skills/sourcey-docs\nPolicy: runx-policy-demo-v1\nStatus: needs_human_review\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\n\n## Recommendations\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\n\nRead-only: true; mutates grants: false." + }, + "stderr": "", + "stdout": "{\n \"plan\": {\n \"schema\": \"runx.security.least_privilege_plan.v1\",\n \"status\": \"needs_human_review\",\n \"subject\": \"skills/sourcey-docs\",\n \"objective\": \"Dogfood least privilege plan for Frantic bounty 37.\",\n \"policy_id\": \"runx-policy-demo-v1\",\n \"source_receipts\": [\n \"runx:receipt:sha256:111\",\n \"runx:receipt:sha256:222\"\n ],\n \"recommendations\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"current_scope\": \"repo.read:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-read-issue\",\n \"verb\": \"repo.read\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:111#read_issue\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:repo-read\"\n ],\n \"unused_scopes\": [\n \"repo.read:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:111#read_issue\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"current_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-write-comment\",\n \"verb\": \"repo.write\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:222#comment\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:issue-write\"\n ],\n \"unused_scopes\": [\n \"repo.write:github/LubuSeb/sourcey-demo/issues/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#comment\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-delete\",\n \"current_scope\": \"repo.delete:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"revoke\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:delete\"\n ],\n \"unused_scopes\": [\n \"repo.delete:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"No successful observed effect exercised this grant in the supplied run history.\",\n \"risk_notes\": [\n \"Revocation is safe only for the supplied evidence window; future workloads may require new authority.\"\n ]\n },\n {\n \"grant_id\": \"grant-secret-prod\",\n \"current_scope\": \"secret.read:prod/*\",\n \"recommendation\": \"needs_human_review\",\n \"proposed_scope\": null,\n \"observed_effects\": [\n {\n \"effect_id\": \"e-secret-denied\",\n \"verb\": \"secret.read\",\n \"resource\": \"prod/frantic-agent-token\",\n \"status\": \"denied\",\n \"receipt_ref\": \"runx:receipt:sha256:222#secret_denied\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:secret-breakglass\"\n ],\n \"unused_scopes\": [\n \"secret.read:prod/*\"\n ],\n \"missing_evidence\": [\n \"Only a denied check exists; policy owner must decide whether this reserved secret scope is still required.\"\n ],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#secret_denied\"\n ],\n \"rationale\": \"The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.\",\n \"risk_notes\": [\n \"Do not revoke or reduce this grant automatically until the missing evidence is resolved.\"\n ]\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"current_scope\": \"incident.breakglass:runx/*\",\n \"recommendation\": \"keep\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:reserved\"\n ],\n \"unused_scopes\": [\n \"incident.breakglass:runx/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"The declared policy marks this grant as reserved or break-glass authority.\",\n \"risk_notes\": [\n \"Reserved grants remain broad by policy; schedule a separate human review if that posture changes.\"\n ]\n }\n ],\n \"proposed_grants\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"source\": \"reduce\"\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"source\": \"reduce\"\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"scope\": \"incident.breakglass:runx/*\",\n \"source\": \"keep\"\n }\n ],\n \"summary\": {\n \"grant_count\": 5,\n \"observed_effect_count\": 3,\n \"recommendation_counts\": {\n \"keep\": 1,\n \"reduce\": 2,\n \"revoke\": 1,\n \"needs_human_review\": 1\n }\n },\n \"safeguards\": {\n \"read_only\": true,\n \"mutates_grants\": false,\n \"network_required\": false,\n \"secrets_required\": false\n }\n },\n \"recommendations\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"current_scope\": \"repo.read:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-read-issue\",\n \"verb\": \"repo.read\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:111#read_issue\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:repo-read\"\n ],\n \"unused_scopes\": [\n \"repo.read:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:111#read_issue\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"current_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-write-comment\",\n \"verb\": \"repo.write\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:222#comment\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:issue-write\"\n ],\n \"unused_scopes\": [\n \"repo.write:github/LubuSeb/sourcey-demo/issues/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#comment\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-delete\",\n \"current_scope\": \"repo.delete:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"revoke\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:delete\"\n ],\n \"unused_scopes\": [\n \"repo.delete:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"No successful observed effect exercised this grant in the supplied run history.\",\n \"risk_notes\": [\n \"Revocation is safe only for the supplied evidence window; future workloads may require new authority.\"\n ]\n },\n {\n \"grant_id\": \"grant-secret-prod\",\n \"current_scope\": \"secret.read:prod/*\",\n \"recommendation\": \"needs_human_review\",\n \"proposed_scope\": null,\n \"observed_effects\": [\n {\n \"effect_id\": \"e-secret-denied\",\n \"verb\": \"secret.read\",\n \"resource\": \"prod/frantic-agent-token\",\n \"status\": \"denied\",\n \"receipt_ref\": \"runx:receipt:sha256:222#secret_denied\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:secret-breakglass\"\n ],\n \"unused_scopes\": [\n \"secret.read:prod/*\"\n ],\n \"missing_evidence\": [\n \"Only a denied check exists; policy owner must decide whether this reserved secret scope is still required.\"\n ],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#secret_denied\"\n ],\n \"rationale\": \"The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.\",\n \"risk_notes\": [\n \"Do not revoke or reduce this grant automatically until the missing evidence is resolved.\"\n ]\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"current_scope\": \"incident.breakglass:runx/*\",\n \"recommendation\": \"keep\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:reserved\"\n ],\n \"unused_scopes\": [\n \"incident.breakglass:runx/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"The declared policy marks this grant as reserved or break-glass authority.\",\n \"risk_notes\": [\n \"Reserved grants remain broad by policy; schedule a separate human review if that posture changes.\"\n ]\n }\n ],\n \"evidence_json\": {\n \"schema\": \"frantic.delivery.evidence.v1\",\n \"artifact\": \"least-privilege-plan\",\n \"observations\": {\n \"policy_id\": \"runx-policy-demo-v1\",\n \"policy_digest\": \"sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9\",\n \"run_history_digest\": \"sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965\",\n \"subject\": \"skills/sourcey-docs\",\n \"grant_ids\": [\n \"grant-read-all\",\n \"grant-write-issues\",\n \"grant-delete\",\n \"grant-secret-prod\",\n \"grant-breakglass\"\n ],\n \"observed_effects\": [\n {\n \"effect_id\": \"e-read-issue\",\n \"grant_id\": \"grant-read-all\",\n \"verb\": \"repo.read\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:111#read_issue\"\n },\n {\n \"effect_id\": \"e-write-comment\",\n \"grant_id\": \"grant-write-issues\",\n \"verb\": \"repo.write\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:222#comment\"\n },\n {\n \"effect_id\": \"e-secret-denied\",\n \"grant_id\": \"grant-secret-prod\",\n \"verb\": \"secret.read\",\n \"resource\": \"prod/frantic-agent-token\",\n \"status\": \"denied\",\n \"receipt_ref\": \"runx:receipt:sha256:222#secret_denied\"\n }\n ],\n \"unused_scopes\": [\n {\n \"grant_id\": \"grant-delete\",\n \"scope\": \"repo.delete:github/LubuSeb/sourcey-demo/*\"\n }\n ],\n \"recommendations\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"evidence_refs\": [\n \"runx:receipt:sha256:111#read_issue\"\n ]\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#comment\"\n ]\n },\n {\n \"grant_id\": \"grant-delete\",\n \"recommendation\": \"revoke\",\n \"proposed_scope\": null,\n \"evidence_refs\": []\n },\n {\n \"grant_id\": \"grant-secret-prod\",\n \"recommendation\": \"needs_human_review\",\n \"proposed_scope\": null,\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#secret_denied\"\n ]\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"recommendation\": \"keep\",\n \"proposed_scope\": null,\n \"evidence_refs\": []\n }\n ],\n \"receipt_refs\": [\n \"runx:receipt:sha256:111\",\n \"runx:receipt:sha256:222\"\n ]\n }\n },\n \"report\": \"# least-privilege-plan report\\n\\nSubject: skills/sourcey-docs\\nPolicy: runx-policy-demo-v1\\nStatus: needs_human_review\\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\\n\\n## Recommendations\\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\\n\\nRead-only: true; mutates grants: false.\"\n}\n", + "structured_output": { + "evidence_json": { + "artifact": "least-privilege-plan", + "observations": { + "grant_ids": [ + "grant-read-all", + "grant-write-issues", + "grant-delete", + "grant-secret-prod", + "grant-breakglass" + ], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "grant_id": "grant-read-all", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + }, + { + "effect_id": "e-write-comment", + "grant_id": "grant-write-issues", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + }, + { + "effect_id": "e-secret-denied", + "grant_id": "grant-secret-prod", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_digest": "sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9", + "policy_id": "runx-policy-demo-v1", + "receipt_refs": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "recommendations": [ + { + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "recommendation": "reduce" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "recommendation": "reduce" + }, + { + "evidence_refs": [], + "grant_id": "grant-delete", + "proposed_scope": null, + "recommendation": "revoke" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "proposed_scope": null, + "recommendation": "needs_human_review" + }, + { + "evidence_refs": [], + "grant_id": "grant-breakglass", + "proposed_scope": null, + "recommendation": "keep" + } + ], + "run_history_digest": "sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965", + "subject": "skills/sourcey-docs", + "unused_scopes": [ + { + "grant_id": "grant-delete", + "scope": "repo.delete:github/LubuSeb/sourcey-demo/*" + } + ] + }, + "schema": "frantic.delivery.evidence.v1" + }, + "plan": { + "objective": "Dogfood least privilege plan for Frantic bounty 37.", + "policy_id": "runx-policy-demo-v1", + "proposed_grants": [ + { + "grant_id": "grant-read-all", + "scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "source": "reduce" + }, + { + "grant_id": "grant-write-issues", + "scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "source": "reduce" + }, + { + "grant_id": "grant-breakglass", + "scope": "incident.breakglass:runx/*", + "source": "keep" + } + ], + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "safeguards": { + "mutates_grants": false, + "network_required": false, + "read_only": true, + "secrets_required": false + }, + "schema": "runx.security.least_privilege_plan.v1", + "source_receipts": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "status": "needs_human_review", + "subject": "skills/sourcey-docs", + "summary": { + "grant_count": 5, + "observed_effect_count": 3, + "recommendation_counts": { + "keep": 1, + "needs_human_review": 1, + "reduce": 2, + "revoke": 1 + } + } + }, + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "report": "# least-privilege-plan report\n\nSubject: skills/sourcey-docs\nPolicy: runx-policy-demo-v1\nStatus: needs_human_review\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\n\n## Recommendations\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\n\nRead-only: true; mutates grants: false." + } + }, + "payload": { + "evidence_json": { + "artifact": "least-privilege-plan", + "observations": { + "grant_ids": [ + "grant-read-all", + "grant-write-issues", + "grant-delete", + "grant-secret-prod", + "grant-breakglass" + ], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "grant_id": "grant-read-all", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + }, + { + "effect_id": "e-write-comment", + "grant_id": "grant-write-issues", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + }, + { + "effect_id": "e-secret-denied", + "grant_id": "grant-secret-prod", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_digest": "sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9", + "policy_id": "runx-policy-demo-v1", + "receipt_refs": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "recommendations": [ + { + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "recommendation": "reduce" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "recommendation": "reduce" + }, + { + "evidence_refs": [], + "grant_id": "grant-delete", + "proposed_scope": null, + "recommendation": "revoke" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "proposed_scope": null, + "recommendation": "needs_human_review" + }, + { + "evidence_refs": [], + "grant_id": "grant-breakglass", + "proposed_scope": null, + "recommendation": "keep" + } + ], + "run_history_digest": "sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965", + "subject": "skills/sourcey-docs", + "unused_scopes": [ + { + "grant_id": "grant-delete", + "scope": "repo.delete:github/LubuSeb/sourcey-demo/*" + } + ] + }, + "schema": "frantic.delivery.evidence.v1" + }, + "plan": { + "objective": "Dogfood least privilege plan for Frantic bounty 37.", + "policy_id": "runx-policy-demo-v1", + "proposed_grants": [ + { + "grant_id": "grant-read-all", + "scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "source": "reduce" + }, + { + "grant_id": "grant-write-issues", + "scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "source": "reduce" + }, + { + "grant_id": "grant-breakglass", + "scope": "incident.breakglass:runx/*", + "source": "keep" + } + ], + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "safeguards": { + "mutates_grants": false, + "network_required": false, + "read_only": true, + "secrets_required": false + }, + "schema": "runx.security.least_privilege_plan.v1", + "source_receipts": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "status": "needs_human_review", + "subject": "skills/sourcey-docs", + "summary": { + "grant_count": 5, + "observed_effect_count": 3, + "recommendation_counts": { + "keep": 1, + "needs_human_review": 1, + "reduce": 2, + "revoke": 1 + } + } + }, + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "report": "# least-privilege-plan report\n\nSubject: skills/sourcey-docs\nPolicy: runx-policy-demo-v1\nStatus: needs_human_review\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\n\n## Recommendations\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\n\nRead-only: true; mutates grants: false." + }, + "receipt": { + "acts": [ + { + "artifact_refs": [], + "closure": { + "closed_at": "2026-06-22T14:29:51.345Z", + "disposition": "closed", + "reason_code": "process_exit", + "summary": "cli-tool exited successfully" + }, + "criterion_bindings": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "form": "observation", + "id": "act_default", + "intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Runtime graph execution was admitted by the local harness", + "purpose": "Run graph step default", + "success_criteria": [ + { + "criterion_id": "process_exit", + "required": true, + "statement": "cli-tool exits successfully" + } + ] + }, + "source_refs": [], + "summary": "Executed graph step default", + "target_refs": [] + } + ], + "authority": { + "actor_ref": { + "type": "principal", + "uri": "runx:principal:local_runtime" + }, + "attenuation": { + "parent_authority_ref": null, + "subset_proof": null + }, + "authority_proof_refs": [], + "enforcement": { + "profile_hash": "sha256:runtime-skeleton-enforcement", + "redaction_refs": [], + "setup_refs": [], + "teardown_refs": [] + }, + "grant_refs": [], + "scope_refs": [], + "terms": [] + }, + "canonicalization": "runx.receipt.c14n.v1", + "created_at": "2026-06-22T14:29:51.345Z", + "decisions": [ + { + "artifact_refs": [], + "choice": "open", + "closure": null, + "decision_id": "dec_default", + "inputs": { + "opportunity_refs": [], + "selection_ref": null, + "signal_refs": [], + "target_ref": null + }, + "justification": { + "evidence_refs": [], + "summary": "runtime graph planner selected this node" + }, + "proposed_intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Local graph execution requested this node", + "purpose": "Open runtime node default", + "success_criteria": [] + }, + "selected_act_id": "act_default", + "selected_harness_ref": null + } + ], + "digest": "sha256:68417a4d8d2591b921f9d12f6479fb162c8c75ac7cd652994c2ca42030ecf9a9", + "id": "sha256:9cf478c16863cb9c70c72713830af33805764ed229e321cac3a7b256a009d854", + "idempotency": { + "content_hash": "sha256:run_default_54e783e6e467-default-content", + "intent_key": "sha256:run_default_54e783e6e467-default-intent", + "trigger_fingerprint": "sha256:run_default_54e783e6e467-default-trigger" + }, + "issuer": { + "kid": "local:bountybar-frantic-runx-22-20260618192655", + "public_key_sha256": "sha256:afae74faf1b1b104b27d788bee2dd0982052af89a1ae30b3282f1a14b0707871", + "type": "hosted" + }, + "lineage": { + "children": [], + "sync": [] + }, + "schema": "runx.receipt.v1", + "seal": { + "closed_at": "2026-06-22T14:29:51.345Z", + "criteria": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "disposition": "closed", + "last_observed_at": "2026-06-22T14:29:51.345Z", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "signals": [], + "signature": { + "alg": "Ed25519", + "value": "base64:4nb3X4dHlZrEewDsh5WZOihXKYKpmPjBQn87ov3oM-lwEzDCzDAMlUooc4-32-gos8AVDbBVlQP-s-0QDKgbCw" + }, + "subject": { + "commitments": [], + "kind": "skill", + "ref": { + "type": "harness", + "uri": "hrn_run_default_54e783e6e467_default" + } + } + }, + "receipt_id": "sha256:9cf478c16863cb9c70c72713830af33805764ed229e321cac3a7b256a009d854", + "run_id": "run_default_54e783e6e467", + "schema": "runx.skill_run.v1", + "skill_name": "least-privilege-plan", + "status": "sealed" +} diff --git a/skills/least-privilege-plan/evidence/dogfood-receipts-linux.tgz b/skills/least-privilege-plan/evidence/dogfood-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..20a953126a596dfa2b39798da03f9a85dbdfcf24 GIT binary patch literal 1510 zcmV z>bm>pe^EJjcJS=CV<~3GT%7(O8#cj76s_`o^NH#9cevmOLE;B{&hZbzvm>kgD=E#_ z*4;P%i;8-9{p&d;aWctS6{Q&qk}L^Xk+aliDM^Dc3w>IJVdlqa5q+_7UU#}WBjaXi<-0PDJ-YG-!J`>cm3M^z=&rthON#Z!j(e@dwTkAtXH6+m_5=Hni zDu1s(sUtW))bseSPjC4AR$Sl%+mbMkP&0gOc_e!nbE@Z$P%wPf<*O}DfEnx3DHmNe zobtLx-3qF0+EFDyYaDMCx9>_!@3ONRwECG`EVx;qHSJFR`4>lMYvxjM(}j^TBh_@* zlnn>t4XxM4ESV?k;Yr7NYu)e#SR*q_daI?gfle{mz}EZP&RlY4V~+6>mgJ&o zZKAFQh1+JSnt|C4h-@0EOe=;st>M4RqfY#^=Yhnm=q$q8<@yu!}DVw7$d3#yhqi8}{- z`1SxIKshUAJJ{h2yNzHQ3fn@erS95lZ-^?iV{xsQST-}$=lmAbNVA1aG?G}I_3-xH z+p_V#6$3_$X>(U9-tTy`Nya(V4lS|dtxv@g-2$hpS7*~fZb{9RJG`uTiiGLbzyDS& zdb~GG`=WWsx$bd{egaY;w`(qd&bkD%Ij>9H;szy4!TJs4XP?o3q&(vOhb0Xc-*S7u z=l repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\n\nRead-only: true; mutates grants: false." + }, + "stderr": "", + "stdout": "{\n \"plan\": {\n \"schema\": \"runx.security.least_privilege_plan.v1\",\n \"status\": \"needs_human_review\",\n \"subject\": \"skills/sourcey-docs\",\n \"objective\": \"Hosted dogfood least privilege plan for Frantic bounty 37.\",\n \"policy_id\": \"runx-policy-demo-v1\",\n \"source_receipts\": [\n \"runx:receipt:sha256:111\",\n \"runx:receipt:sha256:222\"\n ],\n \"recommendations\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"current_scope\": \"repo.read:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-read-issue\",\n \"verb\": \"repo.read\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:111#read_issue\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:repo-read\"\n ],\n \"unused_scopes\": [\n \"repo.read:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:111#read_issue\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"current_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-write-comment\",\n \"verb\": \"repo.write\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:222#comment\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:issue-write\"\n ],\n \"unused_scopes\": [\n \"repo.write:github/LubuSeb/sourcey-demo/issues/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#comment\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-delete\",\n \"current_scope\": \"repo.delete:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"revoke\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:delete\"\n ],\n \"unused_scopes\": [\n \"repo.delete:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"No successful observed effect exercised this grant in the supplied run history.\",\n \"risk_notes\": [\n \"Revocation is safe only for the supplied evidence window; future workloads may require new authority.\"\n ]\n },\n {\n \"grant_id\": \"grant-secret-prod\",\n \"current_scope\": \"secret.read:prod/*\",\n \"recommendation\": \"needs_human_review\",\n \"proposed_scope\": null,\n \"observed_effects\": [\n {\n \"effect_id\": \"e-secret-denied\",\n \"verb\": \"secret.read\",\n \"resource\": \"prod/frantic-agent-token\",\n \"status\": \"denied\",\n \"receipt_ref\": \"runx:receipt:sha256:222#secret_denied\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:secret-breakglass\"\n ],\n \"unused_scopes\": [\n \"secret.read:prod/*\"\n ],\n \"missing_evidence\": [\n \"Only a denied check exists; policy owner must decide whether this reserved secret scope is still required.\"\n ],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#secret_denied\"\n ],\n \"rationale\": \"The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.\",\n \"risk_notes\": [\n \"Do not revoke or reduce this grant automatically until the missing evidence is resolved.\"\n ]\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"current_scope\": \"incident.breakglass:runx/*\",\n \"recommendation\": \"keep\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:reserved\"\n ],\n \"unused_scopes\": [\n \"incident.breakglass:runx/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"The declared policy marks this grant as reserved or break-glass authority.\",\n \"risk_notes\": [\n \"Reserved grants remain broad by policy; schedule a separate human review if that posture changes.\"\n ]\n }\n ],\n \"proposed_grants\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"source\": \"reduce\"\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"source\": \"reduce\"\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"scope\": \"incident.breakglass:runx/*\",\n \"source\": \"keep\"\n }\n ],\n \"summary\": {\n \"grant_count\": 5,\n \"observed_effect_count\": 3,\n \"recommendation_counts\": {\n \"keep\": 1,\n \"reduce\": 2,\n \"revoke\": 1,\n \"needs_human_review\": 1\n }\n },\n \"safeguards\": {\n \"read_only\": true,\n \"mutates_grants\": false,\n \"network_required\": false,\n \"secrets_required\": false\n }\n },\n \"recommendations\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"current_scope\": \"repo.read:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-read-issue\",\n \"verb\": \"repo.read\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:111#read_issue\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:repo-read\"\n ],\n \"unused_scopes\": [\n \"repo.read:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:111#read_issue\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"current_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/*\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"observed_effects\": [\n {\n \"effect_id\": \"e-write-comment\",\n \"verb\": \"repo.write\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:222#comment\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:issue-write\"\n ],\n \"unused_scopes\": [\n \"repo.write:github/LubuSeb/sourcey-demo/issues/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#comment\"\n ],\n \"rationale\": \"Successful observed effects fit a narrower resource path than the current wildcard grant.\",\n \"risk_notes\": [\n \"The reduced scope preserves only the cited resources from this evidence packet.\"\n ]\n },\n {\n \"grant_id\": \"grant-delete\",\n \"current_scope\": \"repo.delete:github/LubuSeb/sourcey-demo/*\",\n \"recommendation\": \"revoke\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:delete\"\n ],\n \"unused_scopes\": [\n \"repo.delete:github/LubuSeb/sourcey-demo/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"No successful observed effect exercised this grant in the supplied run history.\",\n \"risk_notes\": [\n \"Revocation is safe only for the supplied evidence window; future workloads may require new authority.\"\n ]\n },\n {\n \"grant_id\": \"grant-secret-prod\",\n \"current_scope\": \"secret.read:prod/*\",\n \"recommendation\": \"needs_human_review\",\n \"proposed_scope\": null,\n \"observed_effects\": [\n {\n \"effect_id\": \"e-secret-denied\",\n \"verb\": \"secret.read\",\n \"resource\": \"prod/frantic-agent-token\",\n \"status\": \"denied\",\n \"receipt_ref\": \"runx:receipt:sha256:222#secret_denied\"\n }\n ],\n \"policy_input_refs\": [\n \"policy:secret-breakglass\"\n ],\n \"unused_scopes\": [\n \"secret.read:prod/*\"\n ],\n \"missing_evidence\": [\n \"Only a denied check exists; policy owner must decide whether this reserved secret scope is still required.\"\n ],\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#secret_denied\"\n ],\n \"rationale\": \"The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.\",\n \"risk_notes\": [\n \"Do not revoke or reduce this grant automatically until the missing evidence is resolved.\"\n ]\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"current_scope\": \"incident.breakglass:runx/*\",\n \"recommendation\": \"keep\",\n \"proposed_scope\": null,\n \"observed_effects\": [],\n \"policy_input_refs\": [\n \"policy:reserved\"\n ],\n \"unused_scopes\": [\n \"incident.breakglass:runx/*\"\n ],\n \"missing_evidence\": [],\n \"evidence_refs\": [],\n \"rationale\": \"The declared policy marks this grant as reserved or break-glass authority.\",\n \"risk_notes\": [\n \"Reserved grants remain broad by policy; schedule a separate human review if that posture changes.\"\n ]\n }\n ],\n \"evidence_json\": {\n \"schema\": \"frantic.delivery.evidence.v1\",\n \"artifact\": \"least-privilege-plan\",\n \"observations\": {\n \"policy_id\": \"runx-policy-demo-v1\",\n \"policy_digest\": \"sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9\",\n \"run_history_digest\": \"sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965\",\n \"subject\": \"skills/sourcey-docs\",\n \"grant_ids\": [\n \"grant-read-all\",\n \"grant-write-issues\",\n \"grant-delete\",\n \"grant-secret-prod\",\n \"grant-breakglass\"\n ],\n \"observed_effects\": [\n {\n \"effect_id\": \"e-read-issue\",\n \"grant_id\": \"grant-read-all\",\n \"verb\": \"repo.read\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:111#read_issue\"\n },\n {\n \"effect_id\": \"e-write-comment\",\n \"grant_id\": \"grant-write-issues\",\n \"verb\": \"repo.write\",\n \"resource\": \"github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"status\": \"success\",\n \"receipt_ref\": \"runx:receipt:sha256:222#comment\"\n },\n {\n \"effect_id\": \"e-secret-denied\",\n \"grant_id\": \"grant-secret-prod\",\n \"verb\": \"secret.read\",\n \"resource\": \"prod/frantic-agent-token\",\n \"status\": \"denied\",\n \"receipt_ref\": \"runx:receipt:sha256:222#secret_denied\"\n }\n ],\n \"unused_scopes\": [\n {\n \"grant_id\": \"grant-delete\",\n \"scope\": \"repo.delete:github/LubuSeb/sourcey-demo/*\"\n }\n ],\n \"recommendations\": [\n {\n \"grant_id\": \"grant-read-all\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.read:github/LubuSeb/sourcey-demo/issues/81\",\n \"evidence_refs\": [\n \"runx:receipt:sha256:111#read_issue\"\n ]\n },\n {\n \"grant_id\": \"grant-write-issues\",\n \"recommendation\": \"reduce\",\n \"proposed_scope\": \"repo.write:github/LubuSeb/sourcey-demo/issues/81/comments\",\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#comment\"\n ]\n },\n {\n \"grant_id\": \"grant-delete\",\n \"recommendation\": \"revoke\",\n \"proposed_scope\": null,\n \"evidence_refs\": []\n },\n {\n \"grant_id\": \"grant-secret-prod\",\n \"recommendation\": \"needs_human_review\",\n \"proposed_scope\": null,\n \"evidence_refs\": [\n \"runx:receipt:sha256:222#secret_denied\"\n ]\n },\n {\n \"grant_id\": \"grant-breakglass\",\n \"recommendation\": \"keep\",\n \"proposed_scope\": null,\n \"evidence_refs\": []\n }\n ],\n \"receipt_refs\": [\n \"runx:receipt:sha256:111\",\n \"runx:receipt:sha256:222\"\n ]\n }\n },\n \"report\": \"# least-privilege-plan report\\n\\nSubject: skills/sourcey-docs\\nPolicy: runx-policy-demo-v1\\nStatus: needs_human_review\\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\\n\\n## Recommendations\\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\\n\\nRead-only: true; mutates grants: false.\"\n}\n", + "structured_output": { + "evidence_json": { + "artifact": "least-privilege-plan", + "observations": { + "grant_ids": [ + "grant-read-all", + "grant-write-issues", + "grant-delete", + "grant-secret-prod", + "grant-breakglass" + ], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "grant_id": "grant-read-all", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + }, + { + "effect_id": "e-write-comment", + "grant_id": "grant-write-issues", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + }, + { + "effect_id": "e-secret-denied", + "grant_id": "grant-secret-prod", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_digest": "sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9", + "policy_id": "runx-policy-demo-v1", + "receipt_refs": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "recommendations": [ + { + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "recommendation": "reduce" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "recommendation": "reduce" + }, + { + "evidence_refs": [], + "grant_id": "grant-delete", + "proposed_scope": null, + "recommendation": "revoke" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "proposed_scope": null, + "recommendation": "needs_human_review" + }, + { + "evidence_refs": [], + "grant_id": "grant-breakglass", + "proposed_scope": null, + "recommendation": "keep" + } + ], + "run_history_digest": "sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965", + "subject": "skills/sourcey-docs", + "unused_scopes": [ + { + "grant_id": "grant-delete", + "scope": "repo.delete:github/LubuSeb/sourcey-demo/*" + } + ] + }, + "schema": "frantic.delivery.evidence.v1" + }, + "plan": { + "objective": "Hosted dogfood least privilege plan for Frantic bounty 37.", + "policy_id": "runx-policy-demo-v1", + "proposed_grants": [ + { + "grant_id": "grant-read-all", + "scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "source": "reduce" + }, + { + "grant_id": "grant-write-issues", + "scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "source": "reduce" + }, + { + "grant_id": "grant-breakglass", + "scope": "incident.breakglass:runx/*", + "source": "keep" + } + ], + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "safeguards": { + "mutates_grants": false, + "network_required": false, + "read_only": true, + "secrets_required": false + }, + "schema": "runx.security.least_privilege_plan.v1", + "source_receipts": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "status": "needs_human_review", + "subject": "skills/sourcey-docs", + "summary": { + "grant_count": 5, + "observed_effect_count": 3, + "recommendation_counts": { + "keep": 1, + "needs_human_review": 1, + "reduce": 2, + "revoke": 1 + } + } + }, + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "report": "# least-privilege-plan report\n\nSubject: skills/sourcey-docs\nPolicy: runx-policy-demo-v1\nStatus: needs_human_review\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\n\n## Recommendations\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\n\nRead-only: true; mutates grants: false." + } + }, + "payload": { + "evidence_json": { + "artifact": "least-privilege-plan", + "observations": { + "grant_ids": [ + "grant-read-all", + "grant-write-issues", + "grant-delete", + "grant-secret-prod", + "grant-breakglass" + ], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "grant_id": "grant-read-all", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + }, + { + "effect_id": "e-write-comment", + "grant_id": "grant-write-issues", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + }, + { + "effect_id": "e-secret-denied", + "grant_id": "grant-secret-prod", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_digest": "sha256:f9de1472ae8508bc4c5d5989263eaee7b7a5b749fb769089eedd6436f0f5adf9", + "policy_id": "runx-policy-demo-v1", + "receipt_refs": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "recommendations": [ + { + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "recommendation": "reduce" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "recommendation": "reduce" + }, + { + "evidence_refs": [], + "grant_id": "grant-delete", + "proposed_scope": null, + "recommendation": "revoke" + }, + { + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "proposed_scope": null, + "recommendation": "needs_human_review" + }, + { + "evidence_refs": [], + "grant_id": "grant-breakglass", + "proposed_scope": null, + "recommendation": "keep" + } + ], + "run_history_digest": "sha256:7aa9061a8fcb3de014fc3d813dffaae8ccf7eada3faa207932124e173f62a965", + "subject": "skills/sourcey-docs", + "unused_scopes": [ + { + "grant_id": "grant-delete", + "scope": "repo.delete:github/LubuSeb/sourcey-demo/*" + } + ] + }, + "schema": "frantic.delivery.evidence.v1" + }, + "plan": { + "objective": "Hosted dogfood least privilege plan for Frantic bounty 37.", + "policy_id": "runx-policy-demo-v1", + "proposed_grants": [ + { + "grant_id": "grant-read-all", + "scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "source": "reduce" + }, + { + "grant_id": "grant-write-issues", + "scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "source": "reduce" + }, + { + "grant_id": "grant-breakglass", + "scope": "incident.breakglass:runx/*", + "source": "keep" + } + ], + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "safeguards": { + "mutates_grants": false, + "network_required": false, + "read_only": true, + "secrets_required": false + }, + "schema": "runx.security.least_privilege_plan.v1", + "source_receipts": [ + "runx:receipt:sha256:111", + "runx:receipt:sha256:222" + ], + "status": "needs_human_review", + "subject": "skills/sourcey-docs", + "summary": { + "grant_count": 5, + "observed_effect_count": 3, + "recommendation_counts": { + "keep": 1, + "needs_human_review": 1, + "reduce": 2, + "revoke": 1 + } + } + }, + "recommendations": [ + { + "current_scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [ + "runx:receipt:sha256:111#read_issue" + ], + "grant_id": "grant-read-all", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "receipt_ref": "runx:receipt:sha256:111#read_issue", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "verb": "repo.read" + } + ], + "policy_input_refs": [ + "policy:repo-read" + ], + "proposed_scope": "repo.read:github/LubuSeb/sourcey-demo/issues/81", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.read:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "evidence_refs": [ + "runx:receipt:sha256:222#comment" + ], + "grant_id": "grant-write-issues", + "missing_evidence": [], + "observed_effects": [ + { + "effect_id": "e-write-comment", + "receipt_ref": "runx:receipt:sha256:222#comment", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "verb": "repo.write" + } + ], + "policy_input_refs": [ + "policy:issue-write" + ], + "proposed_scope": "repo.write:github/LubuSeb/sourcey-demo/issues/81/comments", + "rationale": "Successful observed effects fit a narrower resource path than the current wildcard grant.", + "recommendation": "reduce", + "risk_notes": [ + "The reduced scope preserves only the cited resources from this evidence packet." + ], + "unused_scopes": [ + "repo.write:github/LubuSeb/sourcey-demo/issues/*" + ] + }, + { + "current_scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "evidence_refs": [], + "grant_id": "grant-delete", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:delete" + ], + "proposed_scope": null, + "rationale": "No successful observed effect exercised this grant in the supplied run history.", + "recommendation": "revoke", + "risk_notes": [ + "Revocation is safe only for the supplied evidence window; future workloads may require new authority." + ], + "unused_scopes": [ + "repo.delete:github/LubuSeb/sourcey-demo/*" + ] + }, + { + "current_scope": "secret.read:prod/*", + "evidence_refs": [ + "runx:receipt:sha256:222#secret_denied" + ], + "grant_id": "grant-secret-prod", + "missing_evidence": [ + "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + ], + "observed_effects": [ + { + "effect_id": "e-secret-denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied", + "resource": "prod/frantic-agent-token", + "status": "denied", + "verb": "secret.read" + } + ], + "policy_input_refs": [ + "policy:secret-breakglass" + ], + "proposed_scope": null, + "rationale": "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + "recommendation": "needs_human_review", + "risk_notes": [ + "Do not revoke or reduce this grant automatically until the missing evidence is resolved." + ], + "unused_scopes": [ + "secret.read:prod/*" + ] + }, + { + "current_scope": "incident.breakglass:runx/*", + "evidence_refs": [], + "grant_id": "grant-breakglass", + "missing_evidence": [], + "observed_effects": [], + "policy_input_refs": [ + "policy:reserved" + ], + "proposed_scope": null, + "rationale": "The declared policy marks this grant as reserved or break-glass authority.", + "recommendation": "keep", + "risk_notes": [ + "Reserved grants remain broad by policy; schedule a separate human review if that posture changes." + ], + "unused_scopes": [ + "incident.breakglass:runx/*" + ] + } + ], + "report": "# least-privilege-plan report\n\nSubject: skills/sourcey-docs\nPolicy: runx-policy-demo-v1\nStatus: needs_human_review\nReceipts: runx:receipt:sha256:111, runx:receipt:sha256:222\n\n## Recommendations\n- reduce: grant-read-all repo.read:github/LubuSeb/sourcey-demo/* -> repo.read:github/LubuSeb/sourcey-demo/issues/81 (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- reduce: grant-write-issues repo.write:github/LubuSeb/sourcey-demo/issues/* -> repo.write:github/LubuSeb/sourcey-demo/issues/81/comments (Successful observed effects fit a narrower resource path than the current wildcard grant.)\n- revoke: grant-delete repo.delete:github/LubuSeb/sourcey-demo/* (No successful observed effect exercised this grant in the supplied run history.)\n- needs_human_review: grant-secret-prod secret.read:prod/* (The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.)\n- keep: grant-breakglass incident.breakglass:runx/* (The declared policy marks this grant as reserved or break-glass authority.)\n\nRead-only: true; mutates grants: false." + }, + "receipt": { + "acts": [ + { + "artifact_refs": [], + "closure": { + "closed_at": "2026-06-22T14:31:33.747Z", + "disposition": "closed", + "reason_code": "process_exit", + "summary": "cli-tool exited successfully" + }, + "criterion_bindings": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "form": "observation", + "id": "act_default", + "intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Runtime graph execution was admitted by the local harness", + "purpose": "Run graph step default", + "success_criteria": [ + { + "criterion_id": "process_exit", + "required": true, + "statement": "cli-tool exits successfully" + } + ] + }, + "source_refs": [], + "summary": "Executed graph step default", + "target_refs": [] + } + ], + "authority": { + "actor_ref": { + "type": "principal", + "uri": "runx:principal:local_runtime" + }, + "attenuation": { + "parent_authority_ref": null, + "subset_proof": null + }, + "authority_proof_refs": [], + "enforcement": { + "profile_hash": "sha256:runtime-skeleton-enforcement", + "redaction_refs": [], + "setup_refs": [], + "teardown_refs": [] + }, + "grant_refs": [], + "scope_refs": [], + "terms": [] + }, + "canonicalization": "runx.receipt.c14n.v1", + "created_at": "2026-06-22T14:31:33.747Z", + "decisions": [ + { + "artifact_refs": [], + "choice": "open", + "closure": null, + "decision_id": "dec_default", + "inputs": { + "opportunity_refs": [], + "selection_ref": null, + "signal_refs": [], + "target_ref": null + }, + "justification": { + "evidence_refs": [], + "summary": "runtime graph planner selected this node" + }, + "proposed_intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Local graph execution requested this node", + "purpose": "Open runtime node default", + "success_criteria": [] + }, + "selected_act_id": "act_default", + "selected_harness_ref": null + } + ], + "digest": "sha256:a63037f85cb3d49f57a81b2c83cbd2b4407c1f7e9652b19077b365147d0664a1", + "id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "idempotency": { + "content_hash": "sha256:run_default_799e8544dbfd-default-content", + "intent_key": "sha256:run_default_799e8544dbfd-default-intent", + "trigger_fingerprint": "sha256:run_default_799e8544dbfd-default-trigger" + }, + "issuer": { + "kid": "local:bountybar-frantic-runx-22-20260618192655", + "public_key_sha256": "sha256:afae74faf1b1b104b27d788bee2dd0982052af89a1ae30b3282f1a14b0707871", + "type": "hosted" + }, + "lineage": { + "children": [], + "sync": [] + }, + "schema": "runx.receipt.v1", + "seal": { + "closed_at": "2026-06-22T14:31:33.747Z", + "criteria": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "disposition": "closed", + "last_observed_at": "2026-06-22T14:31:33.747Z", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "signals": [], + "signature": { + "alg": "Ed25519", + "value": "base64:l50JZnqIVzm865x_KGQ2iBSY7RfIyUI5YsiK1p4onLdzTcaDzL5q7Ig8nR5W1KUiaPNLE2YrHq2QtpOeiNQtDw" + }, + "subject": { + "commitments": [], + "kind": "skill", + "ref": { + "type": "harness", + "uri": "hrn_run_default_799e8544dbfd_default" + } + } + }, + "receipt_id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "registry_provenance": { + "digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", + "profile_digest": "sha256:f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "registry_key_id": "runx-registry-ed25519-v1", + "registry_source": "remote https://api.runx.ai", + "registry_source_fingerprint": "ba1ac16b631195fd", + "skill_id": "lubuseb/least-privilege-plan", + "trust_state": "trusted", + "trust_tier": "community", + "version": "sha-e2d0eec62745" + }, + "run_id": "run_default_799e8544dbfd", + "schema": "runx.skill_run.v1", + "skill_name": "least-privilege-plan", + "status": "sealed" +} diff --git a/skills/least-privilege-plan/evidence/hosted-dogfood-receipts-linux.tgz b/skills/least-privilege-plan/evidence/hosted-dogfood-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..f288a3901beeeb82a8f0c00436c613c225af6518 GIT binary patch literal 1511 zcmVoLz&ZI&cy?r! zeK#@{8HK>;OB=P*jBjjBWO~YUshDT|XezfbT zkb*N>^DAn&6t}UlAQA&Wty@s;^x8Gc25?VgNLr>@Rsecg`jd?KF`-p9 zp#g=^FG7-$Dxg7B_^F>}Y2e-*x|+`fHLU^*nbtGZ{-Pvt98A#m1+81_LqRnp(X@{J zKR$}{Q#jFU+Xi~)~&4PlkEM!GV ziYW3^7E~!rk{FXY@zb;jlQ@Xd(od3z_Dq3ABMk_)w61Z1e~k^}#tOzfFQKAsZSr(7 zfeh=uEGq0U{h-%>gvyNKvl*zo;sPJomW0_u&G5D5k?dj2sh;nlVEC-dS6h4nW~@tR zTy)iN#_Jk&E2y?t3eu%ZOUH7c>M*Xy^u>lgU8P7h{hE;+L?$9M@# za?!LlQP+dQZL?I(z-$LZHjPxK6+@iXaBEn*u#OW(qmddr<4^)NK&`SvX#6!AcZSF~ zLYClc5aMplah%$!b5CsI9n5w!ci<9OYwb7+&Reie(J^zbI|Z&y7h_1+oM9e8aoVFp z=4+!UALwXfg=Yf9RVld`2-JPsaT?0;B@usY&ystskwHCmlaQuFx?us z9D*yWO%! z!9mjFy&><5<}v5G{TTfOq(E-hTmYSQ31)L%m$=0ZN|u848_177qkm7?|Ne)S4VQb} z-XFOC`B4(zy8n@skn#Ta6mrk~FV}eTguKsnch#B!ZpfSKTaacX2(x4org4%GKg{eE z2Dc!^q3`-DP2czu*&Q1NUBI`~+L8Iu_fzZ|KRRinj55k7ql_}jD5H!r$|$3ZGRi1> N$bTs05ZC}H002|=`jh|w literal 0 HcmV?d00001 diff --git a/skills/least-privilege-plan/evidence/hosted-harness-receipts-linux.tgz b/skills/least-privilege-plan/evidence/hosted-harness-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..394c1a9ed04639b4d23b49e4abe3378b357177db GIT binary patch literal 2447 zcmV;A32^owiwFP!000001MM4YQ`@+fpW?}hBhk%cmUhQk zp+wLfGntB_=t{vwl&hk@u{Iz8YTNn~QyVp(xEgO@1KR{U#4>GUZXklFWo{Vu`lQx} zvQSJK#zrChJJ;Pe|2KtRzt{iwPL_^#qV)6!(a;8VENg1-o1fqe^qMaqj2(-pbA*l{)t^b`vChv)yR zPQk|_VVyxoyF#xqbMG8?UUZ@Wh94>30UeiuflCdU0<;7Xr;D5}A%9?NU}E^`QQJGx z>sXql5odAqm8mF8Z}P^ml{O3(MJZ%waMe+hT)?{8X<_EH;yum)%fQddR84#)yP;&M zig>s3dP2II3FKfGdjy1o*YeVjBR)J8lVL6QTmdX(f?6R9u@C={YE;-LR`~v5%oi4 zVd{B|I)s5SJqsQ=1SqA#B$n^lU}@KJs0eB0DI&=;B~m`oqD3kEsbzc9i|HO^$D zDm5~$GC90XN~?oMIg4k+v@;K8!-LA_HFXswLK7Kjr`K328Xy$UaV(_YyGpW@%Ute*SmT_EZst~HiP>%s+C1lc|5^0!8F0`l>Dw&0_*ZkEqn(1zF zDq^9sw7dA0)_DLL0cIA35vt4=o|RxS$S&qfzD>g}ZdL?>M+G3!k5{v&VU;i7X=Wa< z&Nz#>);Z`a)lQz~r8d-6gK&{7lOv%P6_Vw7CRLd>dYZ8ti4s1S6t zxi|-h9dfXvkP)l71J5s%WKrXeT31jL0AHcZlEy)633L|cs#co*WzN!UzKMxNot(gC z8-q(T}~WY>5X=a6kuK6haqNO4wFX|*QAB+$`(&6a3y z=Bl>&60X6`5^ZR3VtHP(_oB1R8hd5h@CZ81Z!^W-HEHI?xL}3B0tk66lRp8mgi*z- zG0z}NOmo#~9;SW@4pXfWmr}Be}gHb z;>5_(%5ze6+lP3s=`-*I}JR>TIz!)aA?U_6CT(507nQ@{7@NmV;At>-gVo{loc z1MJM`?q)$5i?^BIgL&hb&N~C03?wA|eo{>qeNiOM@57VKADF}*5PQx$D<&y#FzsXv zqN*1qdP}$qUtBF5KutOz)=ga1|BzX>QY9xJGeB?{sqxnSZjJsnyxJoYusO&`2b#g- z^gS$u^S5zMP!E34aoW+TpvX#jE$ZgG+O#0JnO7GwFYKjJ0a-F?O7>YeL)8yQ{UO)c z`>)a8MsOR!Z3I6;1lOT>@A3Lu73l)b59>zkY_WrNE z|9jB=4-F_bZRP}4Xmjq{j_28a7`Pq|2Mt=+djZ=cJa=Ic{uV> z_kf&;{Oh~TcZnoX^y<^e{$+l?_5Pw5hv$>-Ys<#Fdnih2e<^}YWqKJ|K~yHe>Y&l3pwV@HBBN=NCkEsDr~_Jwo!om(6LM`kk4pHebZqmAaGb> z!logdj@tguF9AD*?+_dD@96(5MYB%-XDNao(EnMa)AoPb{!iQgY5PBI|EKN$tls~r zN~2$=|I<`zEB1e;bzR&4`Q>2!^B+XExLoV>e$V+2o3?%9{-00_x97j7fLqRgL;Xch zF|2J}9koURHsty74O5q3({(&d9qM75nn;Ie3e~r$v;Gv*BmWU`RW_z95s!zpa^{u) zKKa{=<+44(7bKR*_9$PoTKT&dx5@ShhyNwAJxU94<-P)B`=1?bEws==3oW$JLJPkD N{2$j}d87bP0061J)K&lh literal 0 HcmV?d00001 diff --git a/skills/least-privilege-plan/evidence/hosted-harness-verification.json b/skills/least-privilege-plan/evidence/hosted-harness-verification.json new file mode 100644 index 00000000..ad5c5201 --- /dev/null +++ b/skills/least-privilege-plan/evidence/hosted-harness-verification.json @@ -0,0 +1,29 @@ +{ + "receipt_dir": "/tmp/runx-least-privilege-plan-hosted-harness-receipts", + "signature_mode": "production", + "trees": [ + { + "root_receipt_id": "sha256:3746554df2b970f6db6aab3babe7c9a9f438f26c5cefedb6dc8f0cabc9380e23", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:7d7135a6d4f5ccb56995bfd8971770a104cada2fb978c3f9ca99d49db9d810f5", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:8dae9fc1ca8332e0f7e1867e5ea0150d0bf6431e0ba7f7b36a0d2beeae57fb32", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + } + ], + "unreadable_files": [], + "valid": true +} diff --git a/skills/least-privilege-plan/evidence/hosted-harness.json b/skills/least-privilege-plan/evidence/hosted-harness.json new file mode 100644 index 00000000..5ee459e6 --- /dev/null +++ b/skills/least-privilege-plan/evidence/hosted-harness.json @@ -0,0 +1,17 @@ +{ + "status": "passed", + "case_count": 3, + "assertion_error_count": 0, + "assertion_errors": [], + "case_names": [ + "over-broad-grant-plan", + "justified-grant-plan", + "missing-grants-fails-closed" + ], + "receipt_ids": [ + "sha256:8dae9fc1ca8332e0f7e1867e5ea0150d0bf6431e0ba7f7b36a0d2beeae57fb32", + "sha256:7d7135a6d4f5ccb56995bfd8971770a104cada2fb978c3f9ca99d49db9d810f5", + "sha256:3746554df2b970f6db6aab3babe7c9a9f438f26c5cefedb6dc8f0cabc9380e23" + ], + "graph_case_count": 0 +} diff --git a/skills/least-privilege-plan/evidence/hosted-verification.json b/skills/least-privilege-plan/evidence/hosted-verification.json new file mode 100644 index 00000000..b0358190 --- /dev/null +++ b/skills/least-privilege-plan/evidence/hosted-verification.json @@ -0,0 +1,15 @@ +{ + "receipt_dir": "/tmp/runx-least-privilege-plan-hosted-dogfood-receipts", + "signature_mode": "production", + "trees": [ + { + "root_receipt_id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + } + ], + "unreadable_files": [], + "valid": true +} diff --git a/skills/least-privilege-plan/evidence/local-harness-receipts-linux.tgz b/skills/least-privilege-plan/evidence/local-harness-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..ca87da40fb8225c93f4a8144cb482f5a21dccb84 GIT binary patch literal 2435 zcmV-}34Hb+iwFP!000001MOS+Q`|MEp0hU+HQ|!HzUh( zV(<}cnWIeq_kFUR0~$)8K>Pi!UpoX#^1I)&^ohxes6)O;P=c%ki34FeR7~%QQ_`hi!|I6@%Ve;vJ~S70(P~ zC70e$*WEV%7o|?O)BWd8nhbZs6PZE}7Na zefLtW?URpzUuKGo$ElKuxX`AB3H++G8)s6$=L25`yol6* z`pCAVfE=-$c0JgxZUSa13x`9Q4T3O%4`@q?x&xc~ZkizpaFv1HpO0!Uv zZsbCx+2E=u?G6!+c{CNKlesq??v**OrK>QOTF6i*z2;KN0HZ`YmUGurk%KX8a)S98 z1&%1{8oX?cd8XYtTVHCH6j4-qDwnF_P>q3PC9}9@C6ge{gw&>%tgm$%d??W^A1VJ<1|x6Qu}GDZX~BBO#KAj7^gXO#<~Qw zgNjTKf$)70Zq%MJlGK;ROhb5DhcM1{)wOnX;0=iOcx1?PDGDve$mB^ObyGCdD9lR+ zEgdc)AYlgr;wZC_SK2}5=PKi2osQa9uqOb$f-H^e1g$L4U0kTjY5JF$O4IqeCgy!| z1P|LVfX+V2sJw_{o?TQ)TpC!ZuQwox%!~=ME4s^5=r)O%rLZofD9y{ZS_$GA$kBRD zm*{L3s*3pnts%`~9cW16?6gvEwY4Z3{UWJ#1fPy?3Pt~lHM3xx@!a4(l)Sddy8yGK zQP!(5>mUn4bJ?mdCV2`8Q?8NcVd--P&(*55z!PCxrDly8vV=~G5bCJa zQ&}OuFB|h|n6^q&K>39}m}%)jw}kGUFR6S13tOkKCJ4)?_YWant!Jy$nJ=iRYF7*g z4X;?PEzQ#+yTWo-w3B{!J#FR^3tB~(LlT7bjzmwCy27Rg4m1Oylk-R8mQ!!FW_Qch z=zD2~gx-Hwb*9q`6sqHAz{6+^ZMR&ulsb^~aBdh>MYGJl?rs_V1W5t89fgVH!!p2P z6h=Ng;%X)riKreRzk84VnAG4u4gPbt^S{S@N=*k&IdEL?5uDVy-wAi+sr(n^PGt65C%%h5k4}>F z@y5p^9FmXQgZ^f5_V(TJH|uLZUSB)i+3JjMgxqJcxX&qQ!{{Ku!l<(zoF5a<{1 zpM`Ahg8wXJ@Cf+NyqpIAY4D#0|7q}_2LHKs)DJjxg!>-!bvNmCyWKcZ-JrW(KJnLi z*3BdYuB%&Qw`|>cchP27FX+Tad5@U(VPY6zU_2|^X5NWpGE^hu#fujPdJX~0(laBG zXU0~RrP;GXowx%?PH5E7Ke;%Ts#D!*#E|WVewcuB4X%t*u#qNZS|sYQ_52@N)-Ckk z!{jh2h4qa4%PQr-cmjE@_f_&$b>Fjx^IOlfo=@dG5L=9Um`$1PrhXC0H>uZwdE=RG z2R&V*8T8_ATu$a)naB0-gQL{z!FHxc=u9!LVV#=OPRb$KJ7KIl_0RZ4<-#6p6???G z&a39s@2MghJY@8C*f&b_*c?8^Y zT4hV(mQ7(bh4nWqtR-G?)Q8cZAnvym(scTv-ngvJ#>>8OS)Ziufw(u1;ig+O-QxOV z`0x5n(H-z#*wV}M`=Ix?y#I$yO0VI+*kY)`f1iSGz<&q2yU9Tn@)BwtN;r_u;9G1v z1e*?ZTtILk<0A`X53cpb`L3004lP B=hpxL literal 0 HcmV?d00001 diff --git a/skills/least-privilege-plan/evidence/local-harness-verification.json b/skills/least-privilege-plan/evidence/local-harness-verification.json new file mode 100644 index 00000000..ddf82401 --- /dev/null +++ b/skills/least-privilege-plan/evidence/local-harness-verification.json @@ -0,0 +1,29 @@ +{ + "receipt_dir": "/tmp/runx-least-privilege-plan-harness-receipts", + "signature_mode": "production", + "trees": [ + { + "root_receipt_id": "sha256:4e018f04cfc115662e499a0cb7c8e47777648f0d06be40aa7d093dee63d7923d", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:b6d55381ae059d0325aeadfb0f5721c6bbecf29b82adc889ee46058a5abbcf4a", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:c6a7506ece63c90fb2a4b66e90de687a51e2000c719a53951e5da0331f44f48a", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + } + ], + "unreadable_files": [], + "valid": true +} diff --git a/skills/least-privilege-plan/evidence/local-harness.json b/skills/least-privilege-plan/evidence/local-harness.json new file mode 100644 index 00000000..5790b04d --- /dev/null +++ b/skills/least-privilege-plan/evidence/local-harness.json @@ -0,0 +1,17 @@ +{ + "status": "passed", + "case_count": 3, + "assertion_error_count": 0, + "assertion_errors": [], + "case_names": [ + "over-broad-grant-plan", + "justified-grant-plan", + "missing-grants-fails-closed" + ], + "receipt_ids": [ + "sha256:b6d55381ae059d0325aeadfb0f5721c6bbecf29b82adc889ee46058a5abbcf4a", + "sha256:4e018f04cfc115662e499a0cb7c8e47777648f0d06be40aa7d093dee63d7923d", + "sha256:c6a7506ece63c90fb2a4b66e90de687a51e2000c719a53951e5da0331f44f48a" + ], + "graph_case_count": 0 +} diff --git a/skills/least-privilege-plan/evidence/registry-publish.json b/skills/least-privilege-plan/evidence/registry-publish.json new file mode 100644 index 00000000..4fdb3d51 --- /dev/null +++ b/skills/least-privilege-plan/evidence/registry-publish.json @@ -0,0 +1,20 @@ +{ + "status": "success", + "registry": { + "action": "publish", + "publish": { + "target": "hosted", + "status": "published", + "skill_id": "lubuseb/least-privilege-plan", + "owner": "lubuseb", + "name": "least-privilege-plan", + "version": "sha-e2d0eec62745", + "digest": "09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", + "profile_digest": "f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "trust_tier": "community", + "install_command": "runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai", + "run_command": "runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai", + "public_url": "https://runx.ai/x/lubuseb/least-privilege-plan" + } + } +} diff --git a/skills/least-privilege-plan/evidence/registry-read.json b/skills/least-privilege-plan/evidence/registry-read.json new file mode 100644 index 00000000..a09f3125 --- /dev/null +++ b/skills/least-privilege-plan/evidence/registry-read.json @@ -0,0 +1,50 @@ +{ + "status": "success", + "registry": { + "action": "read", + "source": "remote", + "ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "skill": { + "skill_id": "lubuseb/least-privilege-plan", + "owner": "lubuseb", + "name": "least-privilege-plan", + "description": "Produce a read-only least-privilege grant plan from bounded run history and a declared policy.", + "category": "security", + "version": "sha-e2d0eec62745", + "digest": "09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", + "markdown": "---\nname: least-privilege-plan\ndescription: Produce a read-only least-privilege grant plan from bounded run history and a declared policy.\nsource:\n type: cli-tool\n command: node\n args:\n - run.mjs\n input_mode: stdin\n cwd: .\n timeout_seconds: 30\ninputs:\n run_history_packet:\n type: json\n required: true\n description: Bounded run history containing grants, observed effects, receipt refs, and missing-evidence notes.\n policy:\n type: json\n required: true\n description: Declared least-privilege policy with grant metadata, reserved scopes, and review rules.\n objective:\n type: string\n required: false\n description: Optional operator intent for the plan.\nrunx:\n category: security\n input_resolution:\n required:\n - run_history_packet\n - policy\n---\n\n# least-privilege-plan\n\nUse this skill when an operator needs a read-only plan for narrowing granted\nauthority after one or more runs. The skill compares a bounded run history\npacket against a declared policy and emits keep, reduce, revoke, and\nneeds_human_review recommendations with cited evidence.\n\nThe skill does not mutate grants, write credentials, call provider APIs, or infer\nauthority from broad task success. Every recommendation cites exact observed\neffects, policy inputs, unused scopes, or missing evidence so a reviewer can\napply the plan separately.\n\n## Inputs\n\n- `run_history_packet`: bounded JSON with `subject`, `policy_id`, `grants`,\n `observed_effects`, `receipt_refs`, and optional `missing_evidence`.\n- `policy`: declared JSON policy with grant metadata, reserved scopes, wildcard\n rules, and review thresholds.\n- `objective`: optional operator intent.\n\n## Output\n\nThe runner returns JSON with:\n\n- `plan`: the typed least-privilege plan.\n- `recommendations`: one recommendation per grant.\n- `evidence_json`: a compact evidence object suitable for external review.\n- `report`: a human-readable summary.\n\nRecommendation actions are exactly `keep`, `reduce`, `revoke`, and\n`needs_human_review`.", + "profile_digest": "f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "runner_names": [ + "default" + ], + "source_type": "cli-tool", + "trust_tier": "community", + "required_scopes": [], + "tags": [], + "publisher": { + "kind": "user", + "id": "user_53f00ae7ec2363e37ac6ff68", + "handle": "lubuseb", + "display_name": "LubuSeb" + }, + "attestations": [ + { + "kind": "publisher", + "id": "publisher:user_53f00ae7ec2363e37ac6ff68", + "status": "declared", + "summary": "LubuSeb", + "issued_at": "2026-06-22T14:30:00.811Z", + "metadata": { + "publisher_display_name": "LubuSeb", + "publisher_handle": "lubuseb", + "publisher_id": "user_53f00ae7ec2363e37ac6ff68", + "publisher_kind": "user", + "trust_tier": "community" + } + } + ], + "install_command": "runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai", + "run_command": "runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai" + } + } +} diff --git a/skills/least-privilege-plan/evidence/runx-version.txt b/skills/least-privilege-plan/evidence/runx-version.txt new file mode 100644 index 00000000..6ff8172c --- /dev/null +++ b/skills/least-privilege-plan/evidence/runx-version.txt @@ -0,0 +1 @@ +runx-cli 0.6.13 diff --git a/skills/least-privilege-plan/evidence/verification.json b/skills/least-privilege-plan/evidence/verification.json new file mode 100644 index 00000000..6904cd36 --- /dev/null +++ b/skills/least-privilege-plan/evidence/verification.json @@ -0,0 +1,15 @@ +{ + "receipt_dir": "/tmp/runx-least-privilege-plan-dogfood-receipts", + "signature_mode": "production", + "trees": [ + { + "root_receipt_id": "sha256:9cf478c16863cb9c70c72713830af33805764ed229e321cac3a7b256a009d854", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + } + ], + "unreadable_files": [], + "valid": true +} diff --git a/skills/least-privilege-plan/fixtures/over-broad-run-history.json b/skills/least-privilege-plan/fixtures/over-broad-run-history.json new file mode 100644 index 00000000..02075352 --- /dev/null +++ b/skills/least-privilege-plan/fixtures/over-broad-run-history.json @@ -0,0 +1,64 @@ +{ + "subject": "skills/sourcey-docs", + "policy_id": "runx-policy-demo-v1", + "receipt_refs": ["runx:receipt:sha256:111", "runx:receipt:sha256:222"], + "grants": [ + { + "grant_id": "grant-read-all", + "scope": "repo.read:github/LubuSeb/sourcey-demo/*", + "declared_policy_ref": "policy:repo-read" + }, + { + "grant_id": "grant-write-issues", + "scope": "repo.write:github/LubuSeb/sourcey-demo/issues/*", + "declared_policy_ref": "policy:issue-write" + }, + { + "grant_id": "grant-delete", + "scope": "repo.delete:github/LubuSeb/sourcey-demo/*", + "declared_policy_ref": "policy:delete" + }, + { + "grant_id": "grant-secret-prod", + "scope": "secret.read:prod/*", + "declared_policy_ref": "policy:secret-breakglass" + }, + { + "grant_id": "grant-breakglass", + "scope": "incident.breakglass:runx/*", + "declared_policy_ref": "policy:reserved" + } + ], + "observed_effects": [ + { + "effect_id": "e-read-issue", + "grant_id": "grant-read-all", + "verb": "repo.read", + "resource": "github/LubuSeb/sourcey-demo/issues/81", + "status": "success", + "receipt_ref": "runx:receipt:sha256:111#read_issue" + }, + { + "effect_id": "e-write-comment", + "grant_id": "grant-write-issues", + "verb": "repo.write", + "resource": "github/LubuSeb/sourcey-demo/issues/81/comments", + "status": "success", + "receipt_ref": "runx:receipt:sha256:222#comment" + }, + { + "effect_id": "e-secret-denied", + "grant_id": "grant-secret-prod", + "verb": "secret.read", + "resource": "prod/frantic-agent-token", + "status": "denied", + "receipt_ref": "runx:receipt:sha256:222#secret_denied" + } + ], + "missing_evidence": [ + { + "grant_id": "grant-secret-prod", + "reason": "Only a denied check exists; policy owner must decide whether this reserved secret scope is still required." + } + ] +} diff --git a/skills/least-privilege-plan/fixtures/policy.json b/skills/least-privilege-plan/fixtures/policy.json new file mode 100644 index 00000000..4df7bd2d --- /dev/null +++ b/skills/least-privilege-plan/fixtures/policy.json @@ -0,0 +1,8 @@ +{ + "policy_id": "runx-policy-demo-v1", + "review_rules": { + "wildcard_reduction_allowed": true, + "require_human_review_for_denied_secret": true + }, + "reserved_grants": ["grant-breakglass"] +} diff --git a/skills/least-privilege-plan/run.mjs b/skills/least-privilege-plan/run.mjs new file mode 100644 index 00000000..46f7d5bc --- /dev/null +++ b/skills/least-privilege-plan/run.mjs @@ -0,0 +1,334 @@ +import fs from "node:fs"; +import crypto from "node:crypto"; + +const inputs = readInputs(); +const history = requireObject(inputs.run_history_packet, "run_history_packet"); +const policy = requireObject(inputs.policy, "policy"); +const objective = stringValue(inputs.objective) || "Produce a least-privilege grant plan."; + +const subject = stringValue(history.subject) || "unknown-subject"; +const policyId = stringValue(history.policy_id) || stringValue(policy.policy_id) || "unknown-policy"; +const grants = normalizeGrants(history.grants); +const effects = normalizeEffects(history.observed_effects); +const missingEvidence = normalizeMissingEvidence(history.missing_evidence); +const reservedGrantIds = new Set(arrayValue(policy.reserved_grants).map(String)); +const reviewRules = isObject(policy.review_rules) ? policy.review_rules : {}; + +const recommendations = grants.map((grant) => + recommendGrant(grant, effects, missingEvidence, reservedGrantIds, reviewRules), +); + +const counts = recommendations.reduce( + (acc, rec) => { + acc[rec.recommendation] = (acc[rec.recommendation] || 0) + 1; + return acc; + }, + { keep: 0, reduce: 0, revoke: 0, needs_human_review: 0 }, +); + +const status = + counts.needs_human_review > 0 + ? "needs_human_review" + : counts.reduce > 0 || counts.revoke > 0 + ? "attenuation_proposed" + : "no_change"; + +const plan = { + schema: "runx.security.least_privilege_plan.v1", + status, + subject, + objective, + policy_id: policyId, + source_receipts: arrayValue(history.receipt_refs).map(String), + recommendations, + proposed_grants: recommendations + .filter((rec) => rec.recommendation === "keep" || rec.recommendation === "reduce") + .map((rec) => ({ + grant_id: rec.grant_id, + scope: rec.proposed_scope || rec.current_scope, + source: rec.recommendation, + })), + summary: { + grant_count: grants.length, + observed_effect_count: effects.length, + recommendation_counts: counts, + }, + safeguards: { + read_only: true, + mutates_grants: false, + network_required: false, + secrets_required: false, + }, +}; + +const evidenceJson = { + schema: "frantic.delivery.evidence.v1", + artifact: "least-privilege-plan", + observations: { + policy_id: policyId, + policy_digest: sha256Json(policy), + run_history_digest: sha256Json(history), + subject, + grant_ids: grants.map((grant) => grant.grant_id), + observed_effects: effects.map((effect) => ({ + effect_id: effect.effect_id, + grant_id: effect.grant_id, + verb: effect.verb, + resource: effect.resource, + status: effect.status, + receipt_ref: effect.receipt_ref, + })), + unused_scopes: recommendations + .filter((rec) => rec.recommendation === "revoke") + .map((rec) => ({ grant_id: rec.grant_id, scope: rec.current_scope })), + recommendations: recommendations.map((rec) => ({ + grant_id: rec.grant_id, + recommendation: rec.recommendation, + proposed_scope: rec.proposed_scope, + evidence_refs: rec.evidence_refs, + })), + receipt_refs: plan.source_receipts, + }, +}; + +const report = renderReport(plan); + +process.stdout.write(`${JSON.stringify({ plan, recommendations, evidence_json: evidenceJson, report }, null, 2)}\n`); + +function recommendGrant(grant, effects, missingEvidence, reservedGrantIds, reviewRules) { + const grantEffects = effects.filter((effect) => effect.grant_id === grant.grant_id); + const successEffects = grantEffects.filter((effect) => effect.status === "success"); + const deniedEffects = grantEffects.filter((effect) => effect.status === "denied"); + const missing = missingEvidence.filter((entry) => entry.grant_id === grant.grant_id); + const policyRefs = [grant.declared_policy_ref].filter(Boolean); + const evidenceRefs = grantEffects.map((effect) => effect.receipt_ref).filter(Boolean); + + if (missing.length > 0 || (deniedEffects.length > 0 && reviewRules.require_human_review_for_denied_secret)) { + return buildRecommendation({ + grant, + recommendation: "needs_human_review", + proposedScope: null, + observedEffects: grantEffects, + evidenceRefs, + policyRefs, + unusedScopes: successEffects.length === 0 ? [grant.scope] : [], + missingEvidence: missing.map((entry) => entry.reason), + rationale: + "The grant has missing or denied evidence that could change the attenuation decision; a policy owner must review it.", + riskNotes: ["Do not revoke or reduce this grant automatically until the missing evidence is resolved."], + }); + } + + if (reservedGrantIds.has(grant.grant_id)) { + return buildRecommendation({ + grant, + recommendation: "keep", + proposedScope: null, + observedEffects: grantEffects, + evidenceRefs, + policyRefs, + unusedScopes: successEffects.length === 0 ? [grant.scope] : [], + missingEvidence: [], + rationale: "The declared policy marks this grant as reserved or break-glass authority.", + riskNotes: ["Reserved grants remain broad by policy; schedule a separate human review if that posture changes."], + }); + } + + if (successEffects.length === 0) { + return buildRecommendation({ + grant, + recommendation: "revoke", + proposedScope: null, + observedEffects: grantEffects, + evidenceRefs, + policyRefs, + unusedScopes: [grant.scope], + missingEvidence: [], + rationale: "No successful observed effect exercised this grant in the supplied run history.", + riskNotes: ["Revocation is safe only for the supplied evidence window; future workloads may require new authority."], + }); + } + + const proposedScope = narrowerScope(grant.scope, successEffects); + if (proposedScope && proposedScope !== grant.scope && reviewRules.wildcard_reduction_allowed !== false) { + return buildRecommendation({ + grant, + recommendation: "reduce", + proposedScope, + observedEffects: successEffects, + evidenceRefs, + policyRefs, + unusedScopes: [grant.scope], + missingEvidence: [], + rationale: "Successful observed effects fit a narrower resource path than the current wildcard grant.", + riskNotes: ["The reduced scope preserves only the cited resources from this evidence packet."], + }); + } + + return buildRecommendation({ + grant, + recommendation: "keep", + proposedScope: null, + observedEffects: successEffects, + evidenceRefs, + policyRefs, + unusedScopes: [], + missingEvidence: [], + rationale: "Successful observed effects require the current grant as declared.", + riskNotes: [], + }); +} + +function buildRecommendation({ + grant, + recommendation, + proposedScope, + observedEffects, + evidenceRefs, + policyRefs, + unusedScopes, + missingEvidence, + rationale, + riskNotes, +}) { + return { + grant_id: grant.grant_id, + current_scope: grant.scope, + recommendation, + proposed_scope: proposedScope, + observed_effects: observedEffects.map((effect) => ({ + effect_id: effect.effect_id, + verb: effect.verb, + resource: effect.resource, + status: effect.status, + receipt_ref: effect.receipt_ref, + })), + policy_input_refs: policyRefs, + unused_scopes: unusedScopes, + missing_evidence: missingEvidence, + evidence_refs: evidenceRefs, + rationale, + risk_notes: riskNotes, + }; +} + +function narrowerScope(scope, successEffects) { + if (!scope.endsWith("*") || successEffects.length === 0) return null; + const [verbPrefix, resourcePrefix = ""] = scope.slice(0, -1).split(/:(.*)/s); + const resources = [...new Set(successEffects.map((effect) => effect.resource).filter(Boolean))]; + if (resources.length !== 1) return null; + const observedResource = resources[0]; + if (!observedResource.startsWith(resourcePrefix)) return null; + return `${verbPrefix}:${observedResource}`; +} + +function normalizeGrants(value) { + const grants = arrayValue(value).map((grant, index) => { + if (!isObject(grant)) throw new Error(`grants[${index}] must be an object`); + const grantId = stringValue(grant.grant_id) || `grant-${index + 1}`; + const scope = stringValue(grant.scope); + if (!scope) throw new Error(`grants[${index}].scope is required`); + return { + grant_id: grantId, + scope, + declared_policy_ref: stringValue(grant.declared_policy_ref), + }; + }); + if (grants.length === 0) throw new Error("run_history_packet.grants must contain at least one grant"); + return grants; +} + +function normalizeEffects(value) { + return arrayValue(value).map((effect, index) => { + if (!isObject(effect)) throw new Error(`observed_effects[${index}] must be an object`); + return { + effect_id: stringValue(effect.effect_id) || `effect-${index + 1}`, + grant_id: stringValue(effect.grant_id) || "", + verb: stringValue(effect.verb) || "", + resource: stringValue(effect.resource) || "", + status: normalizeStatus(effect.status), + receipt_ref: stringValue(effect.receipt_ref) || "", + }; + }); +} + +function normalizeMissingEvidence(value) { + return arrayValue(value).map((entry, index) => { + if (!isObject(entry)) throw new Error(`missing_evidence[${index}] must be an object`); + return { + grant_id: stringValue(entry.grant_id) || "", + reason: stringValue(entry.reason) || "missing evidence", + }; + }); +} + +function normalizeStatus(value) { + const normalized = stringValue(value) || "success"; + if (["success", "denied", "dry_run"].includes(normalized)) return normalized; + return "success"; +} + +function renderReport(plan) { + const lines = [ + `# least-privilege-plan report`, + ``, + `Subject: ${plan.subject}`, + `Policy: ${plan.policy_id}`, + `Status: ${plan.status}`, + `Receipts: ${plan.source_receipts.join(", ") || "none supplied"}`, + ``, + `## Recommendations`, + ...plan.recommendations.map( + (rec) => + `- ${rec.recommendation}: ${rec.grant_id} ${rec.current_scope}` + + (rec.proposed_scope ? ` -> ${rec.proposed_scope}` : "") + + ` (${rec.rationale})`, + ), + ``, + `Read-only: ${plan.safeguards.read_only}; mutates grants: ${plan.safeguards.mutates_grants}.`, + ]; + return lines.join("\n"); +} + +function readInputs() { + if (process.env.RUNX_INPUTS_PATH) { + return JSON.parse(fs.readFileSync(process.env.RUNX_INPUTS_PATH, "utf8")); + } + if (process.env.RUNX_INPUTS_JSON) { + return JSON.parse(process.env.RUNX_INPUTS_JSON); + } + if (!process.stdin.isTTY) { + const raw = fs.readFileSync(0, "utf8").trim(); + if (raw) return JSON.parse(raw); + } + return {}; +} + +function requireObject(value, field) { + if (!isObject(value)) throw new Error(`${field} must be an object`); + return value; +} + +function isObject(value) { + return Boolean(value) && typeof value === "object" && !Array.isArray(value); +} + +function arrayValue(value) { + return Array.isArray(value) ? value : []; +} + +function stringValue(value) { + return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; +} + +function sha256Json(value) { + return `sha256:${crypto.createHash("sha256").update(JSON.stringify(sortJson(value))).digest("hex")}`; +} + +function sortJson(value) { + if (Array.isArray(value)) return value.map(sortJson); + if (isObject(value)) { + return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortJson(value[key])])); + } + return value; +} From 5e0f954cced3feaae5cd43987adad347e38557fb Mon Sep 17 00:00:00 2001 From: LubuSeb <187313664+LubuSeb@users.noreply.github.com> Date: Mon, 22 Jun 2026 16:33:55 +0200 Subject: [PATCH 2/3] Add least privilege plan delivery evidence --- .../evidence/evidence.json | 93 +++++++++++++++++++ .../least-privilege-plan/evidence/report.md | 23 +++++ 2 files changed, 116 insertions(+) create mode 100644 skills/least-privilege-plan/evidence/evidence.json create mode 100644 skills/least-privilege-plan/evidence/report.md diff --git a/skills/least-privilege-plan/evidence/evidence.json b/skills/least-privilege-plan/evidence/evidence.json new file mode 100644 index 00000000..70fca9e2 --- /dev/null +++ b/skills/least-privilege-plan/evidence/evidence.json @@ -0,0 +1,93 @@ +{ + "schema": "frantic.delivery.evidence.v1", + "summary": "least-privilege-plan was published as a hosted runx skill, installed from the registry into a clean directory, harnessed from the installed package, dogfooded on a bounded over-broad grant packet, and verified with a sealed production-mode runx receipt.", + "artifact": "least-privilege-plan", + "package": { + "owner": "lubuseb", + "name": "least-privilege-plan", + "version": "sha-e2d0eec62745", + "registry_ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "public_url": "https://runx.ai/x/lubuseb/least-privilege-plan@sha-e2d0eec62745", + "digest": "09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", + "profile_digest": "f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea" + }, + "source": { + "pr_url": "https://github.com/runxhq/runx/pull/118", + "source_url": "https://github.com/LubuSeb/runx/tree/lubu/least-privilege-plan-37", + "x_yaml": "https://raw.githubusercontent.com/LubuSeb/runx/lubu/least-privilege-plan-37/skills/least-privilege-plan/X.yaml", + "skill_md": "https://raw.githubusercontent.com/LubuSeb/runx/lubu/least-privilege-plan-37/skills/least-privilege-plan/SKILL.md" + }, + "runtime": { + "runx_version": "runx-cli 0.6.13", + "receipt_ref": "runx:receipt:sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "receipt_id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "verify_verdict": "valid", + "signature_mode": "production" + }, + "observations": [ + { + "name": "published_registry_package", + "status": "passed", + "detail": "runx registry publish completed successfully for lubuseb/least-privilege-plan@sha-e2d0eec62745 on https://api.runx.ai.", + "evidence_ref": "registry-publish.json" + }, + { + "name": "registry_read", + "status": "passed", + "detail": "runx registry read resolved the same owner, name, version, digest, profile digest, publisher handle, install command, and run command.", + "evidence_ref": "registry-read.json" + }, + { + "name": "clean_install", + "status": "passed", + "detail": "runx add installed the published package into /tmp/runx-least-privilege-plan-clean-install with digest sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471.", + "evidence_ref": "clean-install.json" + }, + { + "name": "hosted_harness", + "status": "passed", + "detail": "The installed registry package passed over-broad-grant-plan, justified-grant-plan, and missing-grants-fails-closed harness cases.", + "evidence_ref": "hosted-harness.json" + }, + { + "name": "hosted_harness_receipts_verified", + "status": "passed", + "detail": "All hosted harness receipts verified with production-mode signatures and no findings.", + "evidence_ref": "hosted-harness-verification.json" + }, + { + "name": "dogfood_run", + "status": "sealed", + "detail": "runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 produced keep, reduce, revoke, and needs_human_review recommendations for the over-broad fixture.", + "evidence_ref": "hosted-dogfood-output.json" + }, + { + "name": "dogfood_receipt_verified", + "status": "passed", + "detail": "runx verify accepted receipt sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f with valid=true and no findings.", + "evidence_ref": "hosted-verification.json" + }, + { + "name": "recommendation_contract", + "status": "passed", + "detail": "Typed output includes keep, reduce, revoke, and needs_human_review; every recommendation cites observed effects, policy refs, unused scopes, or missing evidence.", + "evidence_ref": "hosted-dogfood-output.json" + }, + { + "name": "read_only_behavior", + "status": "passed", + "detail": "The runner reads JSON inputs, computes in memory, performs no provider calls, requires no secrets, and emits structured stdout only.", + "evidence_ref": "run.mjs" + } + ], + "commands": [ + "npx --yes @runxhq/cli@latest --version", + "npx --yes @runxhq/cli@latest harness /mnt/f/BountyBar/repos/runx/skills/least-privilege-plan --json", + "npx --yes @runxhq/cli@latest registry publish /mnt/f/BountyBar/repos/runx/skills/least-privilege-plan/SKILL.md --registry https://api.runx.ai --json", + "npx --yes @runxhq/cli@latest registry read lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --json", + "npx --yes @runxhq/cli@latest add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --to /tmp/runx-least-privilege-plan-clean-install --json", + "npx --yes @runxhq/cli@latest harness /tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745 --json", + "npx --yes @runxhq/cli@latest skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --input-json run_history_packet= --input-json policy= --json", + "npx --yes @runxhq/cli@latest verify --receipt-dir /tmp/runx-least-privilege-plan-hosted-dogfood-receipts --json" + ] +} diff --git a/skills/least-privilege-plan/evidence/report.md b/skills/least-privilege-plan/evidence/report.md new file mode 100644 index 00000000..fdf4d0b0 --- /dev/null +++ b/skills/least-privilege-plan/evidence/report.md @@ -0,0 +1,23 @@ +# least-privilege-plan delivery report + +- Package: `lubuseb/least-privilege-plan@sha-e2d0eec62745`. +- Public registry URL: `https://runx.ai/x/lubuseb/least-privilege-plan@sha-e2d0eec62745`. +- Source PR: `https://github.com/runxhq/runx/pull/118`. +- `runx-cli 0.6.13` was used for publish, registry read, clean install, harness, dogfood, and receipt verification. +- Local harness passed three cases: `over-broad-grant-plan`, `justified-grant-plan`, and `missing-grants-fails-closed`. +- Hosted clean install succeeded with `runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai`. +- Harness from the clean installed package passed the same three cases and all harness receipts verified. +- Hosted dogfood produced sealed receipt `runx:receipt:sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f`. +- `runx verify` returned `valid=true` and no findings for the dogfood receipt. +- The runner emits `keep`, `reduce`, `revoke`, and `needs_human_review` recommendations with exact observed effects, policy refs, unused scopes, or missing evidence. +- The implementation is read-only: it reads the provided JSON packet and policy, computes recommendations in memory, requires no credentials, performs no network/provider calls, and emits structured stdout. + +Reproduce: + +```bash +runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai +runx registry read lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --json +runx harness ./least-privilege-plan --json +runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --input-json run_history_packet='' --input-json policy='' --json +runx verify --receipt-dir /tmp/runx-least-privilege-plan-hosted-dogfood-receipts --json +``` From 9ad08b11afe2be2f70f38bd5dcf92f9ed2041c57 Mon Sep 17 00:00:00 2001 From: LubuSeb <187313664+LubuSeb@users.noreply.github.com> Date: Mon, 22 Jun 2026 16:40:09 +0200 Subject: [PATCH 3/3] Harden least privilege plan validation --- skills/least-privilege-plan/X.yaml | 56 ++++++++++++++++++ .../evidence/clean-install.json | 20 +++---- .../evidence/dogfood-output.json | 18 +++--- .../evidence/dogfood-receipts-linux.tgz | Bin 1510 -> 1507 bytes .../evidence/evidence.json | 28 ++++----- .../evidence/hosted-dogfood-output.json | 22 +++---- .../hosted-dogfood-receipts-linux.tgz | Bin 1511 -> 1514 bytes .../hosted-harness-receipts-linux.tgz | Bin 2447 -> 3300 bytes .../evidence/hosted-harness-verification.json | 20 ++++++- .../evidence/hosted-harness.json | 14 +++-- .../evidence/hosted-verification.json | 2 +- .../evidence/local-harness-receipts-linux.tgz | Bin 2435 -> 3276 bytes .../evidence/local-harness-verification.json | 20 ++++++- .../evidence/local-harness.json | 14 +++-- .../evidence/registry-publish.json | 8 +-- .../evidence/registry-read.json | 12 ++-- .../least-privilege-plan/evidence/report.md | 18 +++--- .../evidence/verification.json | 2 +- skills/least-privilege-plan/run.mjs | 18 ++++-- 19 files changed, 186 insertions(+), 86 deletions(-) diff --git a/skills/least-privilege-plan/X.yaml b/skills/least-privilege-plan/X.yaml index d03f44e0..e5d0cc70 100644 --- a/skills/least-privilege-plan/X.yaml +++ b/skills/least-privilege-plan/X.yaml @@ -140,6 +140,62 @@ harness: expect: status: failure + - name: invalid-effect-status-fails-closed + runner: default + inputs: + objective: "Reject malformed observed effect status instead of treating it as success." + policy: + policy_id: runx-policy-invalid-status-v1 + review_rules: + wildcard_reduction_allowed: true + reserved_grants: [] + run_history_packet: + subject: skills/status-check + policy_id: runx-policy-invalid-status-v1 + receipt_refs: + - runx:receipt:sha256:badstatus + grants: + - grant_id: grant-read + scope: repo.read:github/LubuSeb/sourcey-demo/* + declared_policy_ref: policy:repo-read + observed_effects: + - effect_id: e-failed + grant_id: grant-read + verb: repo.read + resource: github/LubuSeb/sourcey-demo/issues/81 + status: failed + receipt_ref: runx:receipt:sha256:badstatus#read + expect: + status: failure + + - name: policy-mismatch-fails-closed + runner: default + inputs: + objective: "Reject history packets bound to a different policy id." + policy: + policy_id: runx-policy-declared-v1 + review_rules: + wildcard_reduction_allowed: true + reserved_grants: [] + run_history_packet: + subject: skills/policy-mismatch + policy_id: runx-policy-history-v1 + receipt_refs: + - runx:receipt:sha256:mismatch + grants: + - grant_id: grant-read + scope: repo.read:github/LubuSeb/sourcey-demo/issues/81 + declared_policy_ref: policy:repo-read + observed_effects: + - effect_id: e-read + grant_id: grant-read + verb: repo.read + resource: github/LubuSeb/sourcey-demo/issues/81 + status: success + receipt_ref: runx:receipt:sha256:mismatch#read + expect: + status: failure + runners: default: default: true diff --git a/skills/least-privilege-plan/evidence/clean-install.json b/skills/least-privilege-plan/evidence/clean-install.json index bea956a4..2b5c05bd 100644 --- a/skills/least-privilege-plan/evidence/clean-install.json +++ b/skills/least-privilege-plan/evidence/clean-install.json @@ -3,41 +3,41 @@ "registry": { "action": "install", "source": "remote", - "ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "ref": "lubuseb/least-privilege-plan@sha-2ed0e113ff52", "install": { "status": "installed", - "destination": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745/SKILL.md", + "destination": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-2ed0e113ff52/SKILL.md", "skill_name": "least-privilege-plan", "source": "runx-registry", "source_label": "runx registry", "skill_id": "lubuseb/least-privilege-plan", - "version": "sha-e2d0eec62745", + "version": "sha-2ed0e113ff52", "digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", - "profile_digest": "sha256:f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", - "profile_state_path": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745/.runx/profile.json", + "profile_digest": "sha256:259c08c1e5725838b9cd593e7a595c883ad10a4ed8d8b2107bfb3cd712977d4e", + "profile_state_path": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-2ed0e113ff52/.runx/profile.json", "runner_names": [ "default" ], "trust_tier": "community" }, "receipt_metadata": { - "destination": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-e2d0eec62745/SKILL.md", + "destination": "/tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-2ed0e113ff52/SKILL.md", "digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", "install_count": 1, - "package_digest": "56702fe284f54bf0a115550c773b53328e803a0f452d1b93106d8002493c6534", - "profile_digest": "sha256:f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "package_digest": "a25cc87d7f6078709b7f7af1e7485d67257b428d3d26a895e2395ab7bcb4867e", + "profile_digest": "sha256:259c08c1e5725838b9cd593e7a595c883ad10a4ed8d8b2107bfb3cd712977d4e", "publisher": { "display_name": "LubuSeb", "handle": "lubuseb", "id": "user_53f00ae7ec2363e37ac6ff68", "kind": "user" }, - "ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "ref": "lubuseb/least-privilege-plan@sha-2ed0e113ff52", "skill_id": "lubuseb/least-privilege-plan", "source_label": "runx registry", "status": "installed", "trust_tier": "community", - "version": "sha-e2d0eec62745" + "version": "sha-2ed0e113ff52" } } } diff --git a/skills/least-privilege-plan/evidence/dogfood-output.json b/skills/least-privilege-plan/evidence/dogfood-output.json index 750a70a0..0137db7b 100644 --- a/skills/least-privilege-plan/evidence/dogfood-output.json +++ b/skills/least-privilege-plan/evidence/dogfood-output.json @@ -1,6 +1,6 @@ { "closure": { - "closed_at": "2026-06-22T14:29:51.345Z", + "closed_at": "2026-06-22T14:38:16.608Z", "disposition": "closed", "reason_code": "process_closed", "summary": "cli-tool default completed" @@ -1203,7 +1203,7 @@ { "artifact_refs": [], "closure": { - "closed_at": "2026-06-22T14:29:51.345Z", + "closed_at": "2026-06-22T14:38:16.608Z", "disposition": "closed", "reason_code": "process_exit", "summary": "cli-tool exited successfully" @@ -1258,7 +1258,7 @@ "terms": [] }, "canonicalization": "runx.receipt.c14n.v1", - "created_at": "2026-06-22T14:29:51.345Z", + "created_at": "2026-06-22T14:38:16.608Z", "decisions": [ { "artifact_refs": [], @@ -1286,8 +1286,8 @@ "selected_harness_ref": null } ], - "digest": "sha256:68417a4d8d2591b921f9d12f6479fb162c8c75ac7cd652994c2ca42030ecf9a9", - "id": "sha256:9cf478c16863cb9c70c72713830af33805764ed229e321cac3a7b256a009d854", + "digest": "sha256:53135f35bf5f06deb443db6c5cbc2c7028d801a45e914de76d290b534a637da3", + "id": "sha256:cfceaadb4aee0c212b40c4eb2a554f5df3a6e5fbf0ea0df7538efc627e839a15", "idempotency": { "content_hash": "sha256:run_default_54e783e6e467-default-content", "intent_key": "sha256:run_default_54e783e6e467-default-intent", @@ -1304,7 +1304,7 @@ }, "schema": "runx.receipt.v1", "seal": { - "closed_at": "2026-06-22T14:29:51.345Z", + "closed_at": "2026-06-22T14:38:16.608Z", "criteria": [ { "criterion_id": "process_exit", @@ -1315,14 +1315,14 @@ } ], "disposition": "closed", - "last_observed_at": "2026-06-22T14:29:51.345Z", + "last_observed_at": "2026-06-22T14:38:16.608Z", "reason_code": "process_closed", "summary": "cli-tool default completed" }, "signals": [], "signature": { "alg": "Ed25519", - "value": "base64:4nb3X4dHlZrEewDsh5WZOihXKYKpmPjBQn87ov3oM-lwEzDCzDAMlUooc4-32-gos8AVDbBVlQP-s-0QDKgbCw" + "value": "base64:zMqSnStJB5sXWbNMpqXwZwRd3sjXvbgmBzqaessSZXONA62tyUgaqa5t2g3gmitDUbCki9jc-92XhMBy7pvsBQ" }, "subject": { "commitments": [], @@ -1333,7 +1333,7 @@ } } }, - "receipt_id": "sha256:9cf478c16863cb9c70c72713830af33805764ed229e321cac3a7b256a009d854", + "receipt_id": "sha256:cfceaadb4aee0c212b40c4eb2a554f5df3a6e5fbf0ea0df7538efc627e839a15", "run_id": "run_default_54e783e6e467", "schema": "runx.skill_run.v1", "skill_name": "least-privilege-plan", diff --git a/skills/least-privilege-plan/evidence/dogfood-receipts-linux.tgz b/skills/least-privilege-plan/evidence/dogfood-receipts-linux.tgz index 20a953126a596dfa2b39798da03f9a85dbdfcf24..f9023ecf910cbe09ab243a6fd20bbc7b64d66a1b 100644 GIT binary patch literal 1507 zcmV<91swVxiwFP!000001MOFBZ`(Ey&QB5aIZE|LN%p5LTfYoxi?u5jbQlbZI>}6A zQXwfPZjk@Jqa?qzNfQ@siefr{kVR5=&)q$DBvmVJyc(!BUZePu*HD4i)KqwdtV$^h zPXPno82#etYsE)N39-*0CI0XXy757d0ulyE7{^hB^FbO%@sUHm+TsDyYD1Od9BIhE zxbCs}pHxm>oV@tuOp5A^i_7n1!zMV1<8{72ePX)(Judh`koduobM~F^?8!R+N=oyk zb&t*eq@tc)|9VbCl1y32fYKt5DS*$yAk1T*#gK=Tkhmm88PNntnU_9LzbI1@Wl*vt zOd*RVG$1DzT8ba-_9%lqNB+C|_x*?ZKZ&t7?DhZ14@q?7_|Fl5|9Stvbv2vAg1S@J zQsHFC_Q^7Ek6m8i@HZ-ZRL2xh1I3IQR2%wX;`xaehJOX|G|Hwya+3Jj2fL06DLA7w z|40p&;!|uah{XU<>lTzdy>-p10bDni8ZF?=Wrw|%sAZbVR+v>zl~*b%3};@)`Y`k? z2tNt3U=k+8LTuW+=4^Het6A^&HUPAwkj5n~gB*W;oQG+VW?2pp7KJ~_LZ5`R%+OZ~ zk)KCl7M1}G;@nUDG)n{b?%37564bN`EM!_&sQqOT5)w?%_LA1E^&zJkl6d;@)zv%k z&irvo^!eZU>sQUy`SpkEw?(8c&X;+$IQ@7nGC>eD|hih@_5&DJv#1raGDl9#0PlLB%q!y-=@VL1y~>W5j8 z`2mdyOoF(8G%3P~pOYx2Nt6~e>X-tHMj8-oWnJR}{~8;{trd*FR0w36xggHRX@U`WU>|xBQo*$rK_^iuUn_mDk)}>1>x@x%O zb&a|el)JQ}N?&U(=5XL5n5TA(%UPXGBAM`&y2QgPFTkuoFIY~Pd( z2jdN`H^wZPr<>tv$9Zer@C8^Sl_kB^(%C?#m~3F@ePeRg;322noiP}QcBsKyx1q|0 zbGyDnCfd60BBjCf8u~G`Y(OmrRUk^K7+6<3RZ5n)*L>aAx;~(HEdki#0jI(NR6FwC;=OwR@osm{sxUZLu4Ew3vjjw zaku6;PHok>XEyN;X1kd?a09Hhb{qv)E!d{$m^s&-0@tRCF(mAaVIDzo+M`3}YojP1 z=xAewX9C1kD!CX4+IwKTI5U0F?4K>9&HPXkyD_=I&6bzg+1HHH?P5XIswZ*hU=QCO zKm;gft!xiFEV0`NwxzHwq+05(t@ehfLOT}MW{G7pGkwnQL5(z9*hC|V)v||o?B17+ zx2+g3VoaNdQt@`rn{6_#sdi|AC2xJoSLhZvUA;Qn4suUwZr$N!%~K>yw+3!_7juLA zYF}Cy3GNvwYsb!MXV6w+SXNyLU9}wR$ekM1!rfDIzDd)|&J_fIZw$65bL^Jbz4a5p zx46(<;+m3oyZ2`)J|1R!>g*QO2HKwEh;Ywy>#3Hl+EckL+I7GClr}rW!dAgGl7J5< z5SKyKGu0Ij+NvpKH|+~Ni$E5Z5=Y?${{k0=}Krj?+)RpJLbe(McO+lugV003v3@pJ$H literal 1510 zcmV z>bm>pe^EJjcJS=CV<~3GT%7(O8#cj76s_`o^NH#9cevmOLE;B{&hZbzvm>kgD=E#_ z*4;P%i;8-9{p&d;aWctS6{Q&qk}L^Xk+aliDM^Dc3w>IJVdlqa5q+_7UU#}WBjaXi<-0PDJ-YG-!J`>cm3M^z=&rthON#Z!j(e@dwTkAtXH6+m_5=Hni zDu1s(sUtW))bseSPjC4AR$Sl%+mbMkP&0gOc_e!nbE@Z$P%wPf<*O}DfEnx3DHmNe zobtLx-3qF0+EFDyYaDMCx9>_!@3ONRwECG`EVx;qHSJFR`4>lMYvxjM(}j^TBh_@* zlnn>t4XxM4ESV?k;Yr7NYu)e#SR*q_daI?gfle{mz}EZP&RlY4V~+6>mgJ&o zZKAFQh1+JSnt|C4h-@0EOe=;st>M4RqfY#^=Yhnm=q$q8<@yu!}DVw7$d3#yhqi8}{- z`1SxIKshUAJJ{h2yNzHQ3fn@erS95lZ-^?iV{xsQST-}$=lmAbNVA1aG?G}I_3-xH z+p_V#6$3_$X>(U9-tTy`Nya(V4lS|dtxv@g-2$hpS7*~fZb{9RJG`uTiiGLbzyDS& zdb~GG`=WWsx$bd{egaY;w`(qd&bkD%Ij>9H;szy4!TJs4XP?o3q&(vOhb0Xc-*S7u z=l --input-json policy= --json", + "npx --yes @runxhq/cli@latest registry read lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai --json", + "npx --yes @runxhq/cli@latest add lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai --to /tmp/runx-least-privilege-plan-clean-install --json", + "npx --yes @runxhq/cli@latest harness /tmp/runx-least-privilege-plan-clean-install/lubuseb/least-privilege-plan/sha-2ed0e113ff52 --json", + "npx --yes @runxhq/cli@latest skill lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai --input-json run_history_packet= --input-json policy= --json", "npx --yes @runxhq/cli@latest verify --receipt-dir /tmp/runx-least-privilege-plan-hosted-dogfood-receipts --json" ] } diff --git a/skills/least-privilege-plan/evidence/hosted-dogfood-output.json b/skills/least-privilege-plan/evidence/hosted-dogfood-output.json index 903a6e76..9ecb3e6d 100644 --- a/skills/least-privilege-plan/evidence/hosted-dogfood-output.json +++ b/skills/least-privilege-plan/evidence/hosted-dogfood-output.json @@ -1,6 +1,6 @@ { "closure": { - "closed_at": "2026-06-22T14:31:33.747Z", + "closed_at": "2026-06-22T14:38:42.900Z", "disposition": "closed", "reason_code": "process_closed", "summary": "cli-tool default completed" @@ -1203,7 +1203,7 @@ { "artifact_refs": [], "closure": { - "closed_at": "2026-06-22T14:31:33.747Z", + "closed_at": "2026-06-22T14:38:42.900Z", "disposition": "closed", "reason_code": "process_exit", "summary": "cli-tool exited successfully" @@ -1258,7 +1258,7 @@ "terms": [] }, "canonicalization": "runx.receipt.c14n.v1", - "created_at": "2026-06-22T14:31:33.747Z", + "created_at": "2026-06-22T14:38:42.900Z", "decisions": [ { "artifact_refs": [], @@ -1286,8 +1286,8 @@ "selected_harness_ref": null } ], - "digest": "sha256:a63037f85cb3d49f57a81b2c83cbd2b4407c1f7e9652b19077b365147d0664a1", - "id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "digest": "sha256:50484eb4284019f8a3050efedd4ff8d07c9b09f82c503e67a404bd8758a1b541", + "id": "sha256:434a5446b2f7d85b35a2ff9ec70ba48d25c8bf06b8cb64f0f79ff4a576f33d77", "idempotency": { "content_hash": "sha256:run_default_799e8544dbfd-default-content", "intent_key": "sha256:run_default_799e8544dbfd-default-intent", @@ -1304,7 +1304,7 @@ }, "schema": "runx.receipt.v1", "seal": { - "closed_at": "2026-06-22T14:31:33.747Z", + "closed_at": "2026-06-22T14:38:42.900Z", "criteria": [ { "criterion_id": "process_exit", @@ -1315,14 +1315,14 @@ } ], "disposition": "closed", - "last_observed_at": "2026-06-22T14:31:33.747Z", + "last_observed_at": "2026-06-22T14:38:42.900Z", "reason_code": "process_closed", "summary": "cli-tool default completed" }, "signals": [], "signature": { "alg": "Ed25519", - "value": "base64:l50JZnqIVzm865x_KGQ2iBSY7RfIyUI5YsiK1p4onLdzTcaDzL5q7Ig8nR5W1KUiaPNLE2YrHq2QtpOeiNQtDw" + "value": "base64:beTqJciXTFi0qnMl6g8rPCLpImEpTSUJTcNoqNBYH7e8klQF1i1MmBdSSNkfxBdd6KEZjXb3IbR3bG3N-YQwDQ" }, "subject": { "commitments": [], @@ -1333,17 +1333,17 @@ } } }, - "receipt_id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "receipt_id": "sha256:434a5446b2f7d85b35a2ff9ec70ba48d25c8bf06b8cb64f0f79ff4a576f33d77", "registry_provenance": { "digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", - "profile_digest": "sha256:f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "profile_digest": "sha256:259c08c1e5725838b9cd593e7a595c883ad10a4ed8d8b2107bfb3cd712977d4e", "registry_key_id": "runx-registry-ed25519-v1", "registry_source": "remote https://api.runx.ai", "registry_source_fingerprint": "ba1ac16b631195fd", "skill_id": "lubuseb/least-privilege-plan", "trust_state": "trusted", "trust_tier": "community", - "version": "sha-e2d0eec62745" + "version": "sha-2ed0e113ff52" }, "run_id": "run_default_799e8544dbfd", "schema": "runx.skill_run.v1", diff --git a/skills/least-privilege-plan/evidence/hosted-dogfood-receipts-linux.tgz b/skills/least-privilege-plan/evidence/hosted-dogfood-receipts-linux.tgz index f288a3901beeeb82a8f0c00436c613c225af6518..3d3f29a3b104b8ef78e4fb98eb4b66de0f5873c7 100644 GIT binary patch literal 1514 zcmVDDgI);0s$4ue5aN1L%s zDioE*3-aH0l;pQGX=0#FQB0Q)vPkOgxx43%WOO61yb@?_yh@8pQNk3ws-)7JsoFr{ z6>7?rDm)DgL}lt{2YU-aN#oc){WK>1({IOnIq>7aPl6~4li+{^Bn{#NC*I%G{?gQj zYR5UKA^+mKhvt7!IeK>V?57hYrzb+rzmW}_;3SGx`M&)`GNe0PAikgYiFW&chzr64hdf09{^$Mw+O63P z7StWPmI_CGnvX7h_s|su4u7S3M|DgCMM_PmLA3!15|1Qa5S;nZILyXTa5N(1qg_X( zl7i7v{7a2c@-{Z+N3sW4*9~ZQeC?WL1-PywEzZna?4?32<6Je;EOV+ouBkMFc`fUM zz_TDo;%ELSNa7ejtD3wNY%+)Cr1N_d0Lm$(5vSbG@sC7#kQQl{UmKlzaM`*f1igh^S5FCYk2B?c=PF(Hx@-9rcj%WXEBMg2=XY%BI1vDMne)4;7}A1 z=UG8gHp&T(2P`HbBq@#1`yxx@jQV*TbxeUpr3^^6w5|z>KaCCJ#tO!KQUIq-X(s7t z1R1ia$T@bHZqVyKLS;sa=@j&Y3yBYGOVaG2rvKXVNOdq~w4Uvup#QARSCgLuGuEZK zkZm>0MOmV54Sbt+R75022r%#;?U4I^bn z>B+7s8xAHaTCR;*GLP58t1&zoGypYE)uhuh(yrwqM}eIz5=3nG(##9OES| z$z|2pL|yj^x6M*L1+yIxRaHuxM)q-9!!2R$!a7bEjY`$n8T%5j0cx}zLgRm+ai@=r zBUJ&;1|ja&0>`PXI`_mT-ob2FGY77KHP()!;i3WC6df}Yb*sR&>0%5CJ7Jhd(1Ld8 zkomRIRP=PTvBEO};^JB@dV+Qy*e=dY7c~2018F_q*Ti;A&T+F996S4pQFXIeP`&I( z+&b97w+9dj+F2>v!48+$Z6w=J*cMW$>b9+RhNwn67T0=-WivBf&hJ2tG+Wq2BZ>88 z2k+3mD;sYc*<-|*R`;di?T$B_WPGBvLklc<>r=i&x4>!Z)!B5AJ5qD)_Ae`*B4OG! za3$K98{AjB(!xjx&nQ(ocCL1MZ5+e0Y)j~(5m-m=*ysjs9-H%ZnvPpn5d57n*r3d@ zTVnUF9|^v}h3+M;;iBEWKTGjpKig4fyP($4b{t29JDyulYt`r-m7Ahn^}E}&*&-IU z3Q;2oM1LZ&6D?Le)Zk5K!YnyIckXfU4tsSE9F1;THvoJ8zHrvlcL3`1=ip{kVcTt& zJqiwz9`6m4u4o=}uG^2%Pe2Ofb}1y#X`5g+6J>#0T(4v)S+{|F?=$+hl>P62SlMv3 z*X{j*`yYvt_}2gbf;5PR``=T@J@>y!jVDi-bh&P?T2sIcd2@a9(=71Aksk!3Ao8<} zgrO}_iKlPqy8cSjSH48H$3{sP@b$E|WPbGh6uZXvPTC-Y3^K?dgA6jrAcG7t$RL9Z QGRPkCA8N6k#{eh*0N+IN)c^nh literal 1511 zcmVoLz&ZI&cy?r! zeK#@{8HK>;OB=P*jBjjBWO~YUshDT|XezfbT zkb*N>^DAn&6t}UlAQA&Wty@s;^x8Gc25?VgNLr>@Rsecg`jd?KF`-p9 zp#g=^FG7-$Dxg7B_^F>}Y2e-*x|+`fHLU^*nbtGZ{-Pvt98A#m1+81_LqRnp(X@{J zKR$}{Q#jFU+Xi~)~&4PlkEM!GV ziYW3^7E~!rk{FXY@zb;jlQ@Xd(od3z_Dq3ABMk_)w61Z1e~k^}#tOzfFQKAsZSr(7 zfeh=uEGq0U{h-%>gvyNKvl*zo;sPJomW0_u&G5D5k?dj2sh;nlVEC-dS6h4nW~@tR zTy)iN#_Jk&E2y?t3eu%ZOUH7c>M*Xy^u>lgU8P7h{hE;+L?$9M@# za?!LlQP+dQZL?I(z-$LZHjPxK6+@iXaBEn*u#OW(qmddr<4^)NK&`SvX#6!AcZSF~ zLYClc5aMplah%$!b5CsI9n5w!ci<9OYwb7+&Reie(J^zbI|Z&y7h_1+oM9e8aoVFp z=4+!UALwXfg=Yf9RVld`2-JPsaT?0;B@usY&ystskwHCmlaQuFx?us z9D*yWO%! z!9mjFy&><5<}v5G{TTfOq(E-hTmYSQ31)L%m$=0ZN|u848_177qkm7?|Ne)S4VQb} z-XFOC`B4(zy8n@skn#Ta6mrk~FV}eTguKsnch#B!ZpfSKTaacX2(x4org4%GKg{eE z2Dc!^q3`-DP2czu*&Q1NUBI`~+L8Iu_fzZ|KRRinj55k7ql_}jD5H!r$|$3ZGRi1> N$bTs05ZC}H002|=`jh|w diff --git a/skills/least-privilege-plan/evidence/hosted-harness-receipts-linux.tgz b/skills/least-privilege-plan/evidence/hosted-harness-receipts-linux.tgz index 394c1a9ed04639b4d23b49e4abe3378b357177db..b196988cf6ebca1ce02dd7f4eb91849135f90ca2 100644 GIT binary patch literal 3300 zcmV)(wiwFP!000001MOXTQyV!J&qwKU?H@^143b*v!@IM!Kp2t?FbU)!nap}6 zwPZKg-KGz~N#(omQ@1aO2{sTy61_iaUSGKeD%7k&i|mavbwVRpY1g1Y{$vbHyXn@*rRmp?~6Yn82odwfH3wj zdf;q-BYDoz*#B9Y7GJyWs`Ec6WlQIO-sOaOtx$$Ea1kSc_7Du z@%sO%k;|^?^G2&-LSbd(=9LrNc-)91IDAX_4(w#6ID}N27r>Sv;x&=iB;*yQEjMVn z;R*}A_vSjDq)9A!FaF4jI883fCNWJ$0_J(CvPSDuqZkepTvrDzoH?pw@1?+{CDJk} zhJt5Jo$;iIWwVNULYhVh>n$Pawn`24t$$DM>1Wu}bCyw?Hln-O6QhcNaD z@0CUe!E@!&R=LrCQvA{G@9*riaaXm&=SRcLTaTYovhI~<2QSa~vyYnt>K;7}cj(S` z_v6OLBnaQ`zhT>M^!)8R+1<<9r1Rq7_W{p4TAp@K*E>dvDDJ4dm}=%>;s-JQRFC30v~ixc>@FlL;N z0yb|)O7pT;v?C@%&WVVmM9tB`W_=SdE3&xLQCVBZ3H*SvloU&_8QpE-D6Pfl^1QnQ zgVAl3ze;haWMNb~ijyiEj^bVqcxOt_hFx7G;dq(F=5v;`FB@lk(D0XOzaJNU7%gwK z{`wn^@UrNpSzJ_Rtt#ft=tbODW{{2vdc&m}1C)~K zK+Sxf4A~yQBuCGlDZmirCv7 z&Xg?8I8LUHOJ$0pQ*`6JV$d+|k`e;8Ey0f}i+L>_M1EdmJRXIku@%e-KrWr7{ZW9{ z8kj0Bi`r=Bm#IjT^P`-YwaFnoY-0_TeH>AF+3)jgSO;;XU@g9xfFvq&#>~#iu1=uZ zByt+UCXsq+UX|5)AfCZEMy|;vCYohY`+Sbn5N3VjXb9r$q!#aSW1ctm%48%X*mQ82 zEB4N5Gj+x(&mA5?${U@;5Y$pmm9NgUg3NKvr^e{RI8Gs8s%z9)T-m&U=W3l=V2QX{ zq-oDF=W=JnO@mp6RSF%KG2~IBRb-|5yr|D7ZrZF=0paJ`U@E16Y6;alUr_iGE^KHH z6(O4EV0bpd{o}xyO{a-qrkb=?S67SvVD<7jt%RcqJZNCdUT?KmiV~)EtMe{3)7&Oe z5mFetS~Fs}uJjM{7EDqu=|TpcVLsJ|qoO3i7nf z&Sl;7sWzSvT&$}zl^33+aSl~79!=RN=?t@eSn9W>soq~^zs+Eq!8U_$A%p8wymEQ{ zxyp0}>xX4Cc5-@}vy;ijXbu3;*&o2vy}E26abV&EUT)VDuSI$T%gu`H#KM*(Tb91> z!~zx&y*N?4Q%w?NH||9ltf%WdgOTf1`uA>x{-R{@Ka2le3;)5skXZ6SQ!QK~1otD) zRf2heE2MB~7-E5F6of`+qr6iby$m;YpXtuo(Mgi*C4qPNWNWbL9UM@;bL?e@XQbDU zo^-lh{^amgnr%FZU%xn8r*DdlvmjnOZ6}=e`a3S#&HODvqOG;HdHA0qDj*?}B=UKL zrRyO`M2h`Tcp^ZqWT6O=7X;vW5egTpFcdmuKIX!YsOK(^|FH=9R7pQVG`Io&H-KaaKI7oO-^V^3v>h9*^@WxlgySiCg zO^v?NyS+l3$?03_-Hv8z3-)fu^SW#FZoh3%*w&Qo|JeS|wbuWF>&V3z9IFG5QG%2} zN`;=wR6s*m$9vLK5sO^uOXcH`d&-McC>f7@A~CW3pL;=f;r}c4f4d&07x#a|ueSel z7qoEy=cf6-NdL!2uI>Mf`#<}ggFN!e?DdvBUXNp*?RNio_i`BTcAo2v4O#3z505vg z$PZ8U;=@;i@a3+5I-q1N`~7tIYMt)J>uq(qvmf_2)E+-x-y6IpAD_(K{~bjfNfbt0 z$bd>Ju?xBqr5R&^FFhu}<=h8_CDS?p&7}sNcmxIzE~Drg`@cDpA@w=%AUE0nJ&(;& z`@iQg_!j%WXU4JpAKU-2{U6)^vHhPPbeoo6?dQ3;8|#0QHi*(1f;Ru_AD_So>g@C1 zE47OCMk%4jK6wn5OJWs0cGAp=vZ1Nj|C`;HHM{-l3+`wcwqNeS+OO}u%RN}W*9yPK z7OV=rWRro{vWyQ``h4I#{Fj+%4*O}D|NGIGCfckmeYgA6!WId>%RaTRh5cW9pV}|9 z0p6A{Tf%G!``Jp^)v!&~V7Wiv02uXq7DSQ8-JzfO8vwR0+q!J)^3PV6?=#M9@n4Jo zUJw6M$d$?s;K88XP?LaD76b${j$F+ZRRa0GLOApZj~K&L$WXg3_cX#Z^038!?*-k3 z|F6J*4XAh#|MjWGfA54A$A52_?~CBS0cIBe9pk@zr`JZv=lm&u^>&!zUFL4K-@IwQ zd-0kczx3AR=8@NZMmA4&Zqc>VkMH#F ztg|r}{{=A#MG^%navAZwC?YO#nT%XtOQ|)-D1d)%#5@@?7pAU~xZ3rk7a~mrTOR+_ z2)HsXeeQ)fz<=kmSqA@|%itT}zq8|5{MX{Y7XP*Quf>0V%qCsk?^)<&9D@`l6GPCt zZlv{jAtAP_gVS^8-^FpoD>oM7_#JvYtQG#+EuLQoJ+uj66W|)yQ?X7XP_c|33&Y7j78w!1O>h8dUQ^X_F zQG~1gkV@u-5(~t+uie1a!s0*og6_iqOTYh#_;9<$f9`@7#(!>_?~C9+ZfL*%H^G0N z#p+=FkJqoa|9r6@tsTGbXZ>vJ?LnMouikE?Ip03-6M^k#5iohJ*H#x$l3H!V`X=sK*HxRO1k=LOB(l4^BiB34$oo zA@a1)k>_LXMWOZsCIlgYMA!KK9|VmLY3~t+aYZ zEdFEhAN&5N#ozx_O^xo)`=3TLwFSGU<9VHZ|I@vr<=21JHxHItypx;H zv+KV*pi9<&ZPT7t?b_GXQmdojfjnKlVLu?)4KWS_>LXYj24?vLkDx48b=4npy5*M$ zSJTFX_toujt%7-x^=bVQzQ^-*yM+bv9NliE&9?B``!d~b;g7%0(d}0Lg!Cf1)qnWr z65Vd$#YS^XrrmkE-Nx4ch4%x)Q~G-sNlTV2S+Zowk|j%)ELpN- i$&w{YmMmGaWXX~xOO`BIvSjI=)BgdoiB#YKpa1}4@W~bc literal 2447 zcmV;A32^owiwFP!000001MM4YQ`@+fpW?}hBhk%cmUhQk zp+wLfGntB_=t{vwl&hk@u{Iz8YTNn~QyVp(xEgO@1KR{U#4>GUZXklFWo{Vu`lQx} zvQSJK#zrChJJ;Pe|2KtRzt{iwPL_^#qV)6!(a;8VENg1-o1fqe^qMaqj2(-pbA*l{)t^b`vChv)yR zPQk|_VVyxoyF#xqbMG8?UUZ@Wh94>30UeiuflCdU0<;7Xr;D5}A%9?NU}E^`QQJGx z>sXql5odAqm8mF8Z}P^ml{O3(MJZ%waMe+hT)?{8X<_EH;yum)%fQddR84#)yP;&M zig>s3dP2II3FKfGdjy1o*YeVjBR)J8lVL6QTmdX(f?6R9u@C={YE;-LR`~v5%oi4 zVd{B|I)s5SJqsQ=1SqA#B$n^lU}@KJs0eB0DI&=;B~m`oqD3kEsbzc9i|HO^$D zDm5~$GC90XN~?oMIg4k+v@;K8!-LA_HFXswLK7Kjr`K328Xy$UaV(_YyGpW@%Ute*SmT_EZst~HiP>%s+C1lc|5^0!8F0`l>Dw&0_*ZkEqn(1zF zDq^9sw7dA0)_DLL0cIA35vt4=o|RxS$S&qfzD>g}ZdL?>M+G3!k5{v&VU;i7X=Wa< z&Nz#>);Z`a)lQz~r8d-6gK&{7lOv%P6_Vw7CRLd>dYZ8ti4s1S6t zxi|-h9dfXvkP)l71J5s%WKrXeT31jL0AHcZlEy)633L|cs#co*WzN!UzKMxNot(gC z8-q(T}~WY>5X=a6kuK6haqNO4wFX|*QAB+$`(&6a3y z=Bl>&60X6`5^ZR3VtHP(_oB1R8hd5h@CZ81Z!^W-HEHI?xL}3B0tk66lRp8mgi*z- zG0z}NOmo#~9;SW@4pXfWmr}Be}gHb z;>5_(%5ze6+lP3s=`-*I}JR>TIz!)aA?U_6CT(507nQ@{7@NmV;At>-gVo{loc z1MJM`?q)$5i?^BIgL&hb&N~C03?wA|eo{>qeNiOM@57VKADF}*5PQx$D<&y#FzsXv zqN*1qdP}$qUtBF5KutOz)=ga1|BzX>QY9xJGeB?{sqxnSZjJsnyxJoYusO&`2b#g- z^gS$u^S5zMP!E34aoW+TpvX#jE$ZgG+O#0JnO7GwFYKjJ0a-F?O7>YeL)8yQ{UO)c z`>)a8MsOR!Z3I6;1lOT>@A3Lu73l)b59>zkY_WrNE z|9jB=4-F_bZRP}4Xmjq{j_28a7`Pq|2Mt=+djZ=cJa=Ic{uV> z_kf&;{Oh~TcZnoX^y<^e{$+l?_5Pw5hv$>-Ys<#Fdnih2e<^}YWqKJ|K~yHe>Y&l3pwV@HBBN=NCkEsDr~_Jwo!om(6LM`kk4pHebZqmAaGb> z!logdj@tguF9AD*?+_dD@96(5MYB%-XDNao(EnMa)AoPb{!iQgY5PBI|EKN$tls~r zN~2$=|I<`zEB1e;bzR&4`Q>2!^B+XExLoV>e$V+2o3?%9{-00_x97j7fLqRgL;Xch zF|2J}9koURHsty74O5q3({(&d9qM75nn;Ie3e~r$v;Gv*BmWU`RW_z95s!zpa^{u) zKKa{=<+44(7bKR*_9$PoTKT&dx5@ShhyNwAJxU94<-P)B`=1?bEws==3oW$JLJPkD N{2$j}d87bP0061J)K&lh diff --git a/skills/least-privilege-plan/evidence/hosted-harness-verification.json b/skills/least-privilege-plan/evidence/hosted-harness-verification.json index ad5c5201..f3c2cc1d 100644 --- a/skills/least-privilege-plan/evidence/hosted-harness-verification.json +++ b/skills/least-privilege-plan/evidence/hosted-harness-verification.json @@ -3,21 +3,35 @@ "signature_mode": "production", "trees": [ { - "root_receipt_id": "sha256:3746554df2b970f6db6aab3babe7c9a9f438f26c5cefedb6dc8f0cabc9380e23", + "root_receipt_id": "sha256:17bc1ca8f4fb32bba7d63eb5683bcb34991b04d892fbb8a8514191b3a5444ae5", "receipt_count": 1, "parent_missing": null, "valid": true, "findings": [] }, { - "root_receipt_id": "sha256:7d7135a6d4f5ccb56995bfd8971770a104cada2fb978c3f9ca99d49db9d810f5", + "root_receipt_id": "sha256:881ab39da888bef5a16f4e2623026d16740ad8ed3a25794c569c1b0aa7f383fb", "receipt_count": 1, "parent_missing": null, "valid": true, "findings": [] }, { - "root_receipt_id": "sha256:8dae9fc1ca8332e0f7e1867e5ea0150d0bf6431e0ba7f7b36a0d2beeae57fb32", + "root_receipt_id": "sha256:9c94830528f600bcc5055cc34d76bb55af2821be56a9f6bacdfd2e6aa97ef75d", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:bafd311064f865420eb0ee9635e8494356c6ed5d3c7ce719a6e6de9c5ad72c12", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:be03ce38ccef39f28a4588215a03fae4eb077e01972ad5514bc9f33a6f014d61", "receipt_count": 1, "parent_missing": null, "valid": true, diff --git a/skills/least-privilege-plan/evidence/hosted-harness.json b/skills/least-privilege-plan/evidence/hosted-harness.json index 5ee459e6..e48afeda 100644 --- a/skills/least-privilege-plan/evidence/hosted-harness.json +++ b/skills/least-privilege-plan/evidence/hosted-harness.json @@ -1,17 +1,21 @@ { "status": "passed", - "case_count": 3, + "case_count": 5, "assertion_error_count": 0, "assertion_errors": [], "case_names": [ "over-broad-grant-plan", "justified-grant-plan", - "missing-grants-fails-closed" + "missing-grants-fails-closed", + "invalid-effect-status-fails-closed", + "policy-mismatch-fails-closed" ], "receipt_ids": [ - "sha256:8dae9fc1ca8332e0f7e1867e5ea0150d0bf6431e0ba7f7b36a0d2beeae57fb32", - "sha256:7d7135a6d4f5ccb56995bfd8971770a104cada2fb978c3f9ca99d49db9d810f5", - "sha256:3746554df2b970f6db6aab3babe7c9a9f438f26c5cefedb6dc8f0cabc9380e23" + "sha256:881ab39da888bef5a16f4e2623026d16740ad8ed3a25794c569c1b0aa7f383fb", + "sha256:17bc1ca8f4fb32bba7d63eb5683bcb34991b04d892fbb8a8514191b3a5444ae5", + "sha256:9c94830528f600bcc5055cc34d76bb55af2821be56a9f6bacdfd2e6aa97ef75d", + "sha256:bafd311064f865420eb0ee9635e8494356c6ed5d3c7ce719a6e6de9c5ad72c12", + "sha256:be03ce38ccef39f28a4588215a03fae4eb077e01972ad5514bc9f33a6f014d61" ], "graph_case_count": 0 } diff --git a/skills/least-privilege-plan/evidence/hosted-verification.json b/skills/least-privilege-plan/evidence/hosted-verification.json index b0358190..890bb5bd 100644 --- a/skills/least-privilege-plan/evidence/hosted-verification.json +++ b/skills/least-privilege-plan/evidence/hosted-verification.json @@ -3,7 +3,7 @@ "signature_mode": "production", "trees": [ { - "root_receipt_id": "sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f", + "root_receipt_id": "sha256:434a5446b2f7d85b35a2ff9ec70ba48d25c8bf06b8cb64f0f79ff4a576f33d77", "receipt_count": 1, "parent_missing": null, "valid": true, diff --git a/skills/least-privilege-plan/evidence/local-harness-receipts-linux.tgz b/skills/least-privilege-plan/evidence/local-harness-receipts-linux.tgz index ca87da40fb8225c93f4a8144cb482f5a21dccb84..3dcfbef231f4d376e68eda9a03ac2e604bf31fef 100644 GIT binary patch literal 3276 zcmV;-3^Vf|iwFP!000001MOXTQ`<-u&qq*j1Is_<-6}|SvE&Zu!CX9q~A=%SZcj~x4M7blJhD(Z^x1qWqXiEr%^0>vOS1d z+U~PFl||9cC702lELNU;FCie0QvHcNikeScA8+UhrUbjhaclzZu;;ksiABG=$2q7f zN|syJlR}2yYnWeqWC_TQXKD2{f#~J(k`X{&>U5N#Rv5W8%YxADu zxk6+A=UG;MtKDtqe^AP2&;O#&2z5J@_<|$q`QSDw0_i&f5gItIkA)rDL@7#2>;jlkI+r^pE^(*uGD|xQcRy%=phX7lh^;x zt%CPu!djh{4u$2$+smi8wbY6P99~e`13R8eR!Y%jC9oyn4aI8mcx+c zZI!dMjCi|_dP3S-2;^cP2M}@;E*n%~9P#e49Ck-~Ul@QXCOt}^d54XN7wTh^hva-sh7MaC8;JzUUr8t1TPgz`P z9YR(}*Xg_rL(xlp=crUiy}e|w=bf*u9^z>4-5b9Mlhc>g#xB~=&JR~N)&u8s=lx;# z{d+V#N7zufoVRRe!F+*(Vw!zwf@9^np#q>(CNU?1rju5XSMJ9u+lqnx-)uI&sEVUUgdI6hv zg;cDH%Pz5DKiqr( z9AQ=2&+@3O&B%C}<=v}YX>;&sz~V_~I+#0?!<{Eq46?ke(#B2`abr1A zVPYq+#vm)8GBzoo4OHd&5Olr`om-7%tTYqSx{wg=))5?MI_p}S+VK{6d(gM!x#X4Z z$I9hNC3R7>%6?ST3|iV-{G2x>{I&R6TAf=qGE=T`G&9H$U4bsKpe)iy8TzB)=Rutd}@vn;ms zxx#9=DKN{hPN9=3f;?(<%Dj?aX7%~RO&hf;ApBGtTu2#0wS?+j%qV;X4O^$sMn(1A z`zseOHD^bmb2*_VqFqrOB)p=z*0ji~{0hs9q#f70>tS;#u%J{#1q4CVj7ao}T2>g; zz=WpDb#Q*I+-%}4HSBH~8hxqNkWl;Q6=!mKia?G3EVvmBpzPMoW)cU29_9_*QPRvZ zuA48SA0Q|ow&N(3tXDgj_oGr@>h@1?~@GvWALB(=KnC;^8=XnC>ML& z#i3wGGx*O#(9HPHUDJLR{KqEP;6G#hXMOYN?1a2aH{S`--4(W5hT`nNe<9l4v-Q4@ zi?w%auiv8c1KXCT-D>M~cKALeJbU>nEd2KKgo0Wh_iTG8R;xVQUXKrQyw;nB{|LmG zC%HflC&Ff+6XMwSi4>f1-^RpNK9;^@TsQ)f6f22*DMN0DGN7EzkN*hD1I9=wI7fHD zf2OjT2mhJM;2!Xw%l#Pq$KXE(|1tQF!GEqz^%aAP@Vyg#T}?VGD=SG_uBer@`i{TG z@|9eI<5qNuT&YWUu`+G2s~apQABzr*KtH6G6)Ed!T{es5Sf;(QZ~gMiFBWu3Q#q;H@h%#N*7f|lWb z^dY?m+;Wm-Gvbyeu}ot94HN5jh`XMQegkp8C6Okl7lgPsbK@Bi_wh{nI}mqs8#dL# zREz7k;lJxjky-yS>p%11|2QNrQvqe6bZzEPg&dm-5je`BF6Sb^TzElfdxS`z$Pg(^ zLf2O~5H@v{Yu0}r6Fr3g=imRUH_MszpNF8C*MIJs_Oq=25agQmpUM8;_gm5MFcS7U zmdRo6ZtN?WdGFfiua4J_UY0KDcGYTyf7>|8&X1B{^Bv2?ZWX`X&b@W}`MSqX$!dJ| z{&2fw=^N+dfc=_nuTEY6A&l5A3SEa_6iO9v;Yg{tUfv58XVS-RNQKQjOceJi3!H#C z$YGGnE=RUI|N0LV$a5t31aka4tp7}9Gtc_ZR0j93{&Tq>v;Je&f6V%iS^qKXKW6{$ z?E8P~q0!^n|J#hzW<(>$<2tkd_tBBTe+>RJ-~2xae3;HL!EN8;NOB=;=_A*61s5vB zp0F`Y5*!<*RLEvXc>xJ^TjVoN6*c(JqoRlK|1JA}5p}=9e;h&#{__wtGyZeew4Vk4 zp*Au2&lvyNcO)9TI>>}utg^#Hw)=V~Kj8FQ<2zfy>e_$Xdr?eISMiG%#cKP_i8okXoreE-#1b*y|C!2W9{gu2gL}Y# zF85>bAA|oG{Kw!w2LE}48;>y6+e&8IUNp#Hq%Z`PM!S9zR&og3`ryU6tGkPC*+euO z$3^e$p`GC8-rDmw*;+hN*zLiKp|ur~9%8Byc$Z14x&!)o&JXUoSQaXrD{ z{|5h`5C2sG=fcOt2?87-N!VOP9`mV(G4ZJ@gsZ5F1ak<*+@;dy zHkRM<{trfZ0F0RcC*0xvAJf>(_5P1(4DRFoAD8+u_`kvb4gPQNe}n%&LePeI?ljcq z&k0&3m4b*Ye*ed3&`_R#`D1w`{|ILZ<=Eg$V3stJV#&&KOXNdckpH|1!1;PXQqP= z@fZKhbkM=x&y9xtO%_&6O)xdV)Px6Gv8o|}$FpM9AQCgKSdH|L^ME1hPAFc@4GqWGeFu_#S({e&sg` zZ0gvK?fQYEZ(fi~ksQtX$D9`Y5{Vi%Oj#lq$F+{>ncq+GWof!@3;2P&DY`A>*EVO- zZS(^(H|Vy2hd-w1wvZ>uW`3^ZCfyeBV*4q&E#y}+X3=f*n!+1&Tfm~-6x|lG17PO$ zK)99u)kV^fAwz}?88T$ZkRd~c3>h+H$dDmJh71`pWXO;qLxv0)GGxe*Awz~9A^jgT K%5+Eopa1}4T#+~c literal 2435 zcmV-}34Hb+iwFP!000001MOS+Q`|MEp0hU+HQ|!HzUh( zV(<}cnWIeq_kFUR0~$)8K>Pi!UpoX#^1I)&^ohxes6)O;P=c%ki34FeR7~%QQ_`hi!|I6@%Ve;vJ~S70(P~ zC70e$*WEV%7o|?O)BWd8nhbZs6PZE}7Na zefLtW?URpzUuKGo$ElKuxX`AB3H++G8)s6$=L25`yol6* z`pCAVfE=-$c0JgxZUSa13x`9Q4T3O%4`@q?x&xc~ZkizpaFv1HpO0!Uv zZsbCx+2E=u?G6!+c{CNKlesq??v**OrK>QOTF6i*z2;KN0HZ`YmUGurk%KX8a)S98 z1&%1{8oX?cd8XYtTVHCH6j4-qDwnF_P>q3PC9}9@C6ge{gw&>%tgm$%d??W^A1VJ<1|x6Qu}GDZX~BBO#KAj7^gXO#<~Qw zgNjTKf$)70Zq%MJlGK;ROhb5DhcM1{)wOnX;0=iOcx1?PDGDve$mB^ObyGCdD9lR+ zEgdc)AYlgr;wZC_SK2}5=PKi2osQa9uqOb$f-H^e1g$L4U0kTjY5JF$O4IqeCgy!| z1P|LVfX+V2sJw_{o?TQ)TpC!ZuQwox%!~=ME4s^5=r)O%rLZofD9y{ZS_$GA$kBRD zm*{L3s*3pnts%`~9cW16?6gvEwY4Z3{UWJ#1fPy?3Pt~lHM3xx@!a4(l)Sddy8yGK zQP!(5>mUn4bJ?mdCV2`8Q?8NcVd--P&(*55z!PCxrDly8vV=~G5bCJa zQ&}OuFB|h|n6^q&K>39}m}%)jw}kGUFR6S13tOkKCJ4)?_YWant!Jy$nJ=iRYF7*g z4X;?PEzQ#+yTWo-w3B{!J#FR^3tB~(LlT7bjzmwCy27Rg4m1Oylk-R8mQ!!FW_Qch z=zD2~gx-Hwb*9q`6sqHAz{6+^ZMR&ulsb^~aBdh>MYGJl?rs_V1W5t89fgVH!!p2P z6h=Ng;%X)riKreRzk84VnAG4u4gPbt^S{S@N=*k&IdEL?5uDVy-wAi+sr(n^PGt65C%%h5k4}>F z@y5p^9FmXQgZ^f5_V(TJH|uLZUSB)i+3JjMgxqJcxX&qQ!{{Ku!l<(zoF5a<{1 zpM`Ahg8wXJ@Cf+NyqpIAY4D#0|7q}_2LHKs)DJjxg!>-!bvNmCyWKcZ-JrW(KJnLi z*3BdYuB%&Qw`|>cchP27FX+Tad5@U(VPY6zU_2|^X5NWpGE^hu#fujPdJX~0(laBG zXU0~RrP;GXowx%?PH5E7Ke;%Ts#D!*#E|WVewcuB4X%t*u#qNZS|sYQ_52@N)-Ckk z!{jh2h4qa4%PQr-cmjE@_f_&$b>Fjx^IOlfo=@dG5L=9Um`$1PrhXC0H>uZwdE=RG z2R&V*8T8_ATu$a)naB0-gQL{z!FHxc=u9!LVV#=OPRb$KJ7KIl_0RZ4<-#6p6???G z&a39s@2MghJY@8C*f&b_*c?8^Y zT4hV(mQ7(bh4nWqtR-G?)Q8cZAnvym(scTv-ngvJ#>>8OS)Ziufw(u1;ig+O-QxOV z`0x5n(H-z#*wV}M`=Ix?y#I$yO0VI+*kY)`f1iSGz<&q2yU9Tn@)BwtN;r_u;9G1v z1e*?ZTtILk<0A`X53cpb`L3004lP B=hpxL diff --git a/skills/least-privilege-plan/evidence/local-harness-verification.json b/skills/least-privilege-plan/evidence/local-harness-verification.json index ddf82401..ad7b47f4 100644 --- a/skills/least-privilege-plan/evidence/local-harness-verification.json +++ b/skills/least-privilege-plan/evidence/local-harness-verification.json @@ -3,21 +3,35 @@ "signature_mode": "production", "trees": [ { - "root_receipt_id": "sha256:4e018f04cfc115662e499a0cb7c8e47777648f0d06be40aa7d093dee63d7923d", + "root_receipt_id": "sha256:1b26af95abe63a45f0435dd94f456ccd91cd79b3722e82eb0f12b68f19d356f6", "receipt_count": 1, "parent_missing": null, "valid": true, "findings": [] }, { - "root_receipt_id": "sha256:b6d55381ae059d0325aeadfb0f5721c6bbecf29b82adc889ee46058a5abbcf4a", + "root_receipt_id": "sha256:528dc0578170ed9e84d02594681d3b32ff5507126251724002ccb00895f91fdc", "receipt_count": 1, "parent_missing": null, "valid": true, "findings": [] }, { - "root_receipt_id": "sha256:c6a7506ece63c90fb2a4b66e90de687a51e2000c719a53951e5da0331f44f48a", + "root_receipt_id": "sha256:9986f6adc387c0ecdd3e80636dcdfb17d31c854392603a0f792bc38708ac5f56", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:d3b898bef617c61bda97f989dd774a6213958974f55e3ffaec14708906d2d25b", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:f9ccd81249919052b7289653fdd890577f580a63d2bc9fc7bb6d07ec70bd30b6", "receipt_count": 1, "parent_missing": null, "valid": true, diff --git a/skills/least-privilege-plan/evidence/local-harness.json b/skills/least-privilege-plan/evidence/local-harness.json index 5790b04d..0485f0ee 100644 --- a/skills/least-privilege-plan/evidence/local-harness.json +++ b/skills/least-privilege-plan/evidence/local-harness.json @@ -1,17 +1,21 @@ { "status": "passed", - "case_count": 3, + "case_count": 5, "assertion_error_count": 0, "assertion_errors": [], "case_names": [ "over-broad-grant-plan", "justified-grant-plan", - "missing-grants-fails-closed" + "missing-grants-fails-closed", + "invalid-effect-status-fails-closed", + "policy-mismatch-fails-closed" ], "receipt_ids": [ - "sha256:b6d55381ae059d0325aeadfb0f5721c6bbecf29b82adc889ee46058a5abbcf4a", - "sha256:4e018f04cfc115662e499a0cb7c8e47777648f0d06be40aa7d093dee63d7923d", - "sha256:c6a7506ece63c90fb2a4b66e90de687a51e2000c719a53951e5da0331f44f48a" + "sha256:528dc0578170ed9e84d02594681d3b32ff5507126251724002ccb00895f91fdc", + "sha256:1b26af95abe63a45f0435dd94f456ccd91cd79b3722e82eb0f12b68f19d356f6", + "sha256:d3b898bef617c61bda97f989dd774a6213958974f55e3ffaec14708906d2d25b", + "sha256:f9ccd81249919052b7289653fdd890577f580a63d2bc9fc7bb6d07ec70bd30b6", + "sha256:9986f6adc387c0ecdd3e80636dcdfb17d31c854392603a0f792bc38708ac5f56" ], "graph_case_count": 0 } diff --git a/skills/least-privilege-plan/evidence/registry-publish.json b/skills/least-privilege-plan/evidence/registry-publish.json index 4fdb3d51..cdb73598 100644 --- a/skills/least-privilege-plan/evidence/registry-publish.json +++ b/skills/least-privilege-plan/evidence/registry-publish.json @@ -8,12 +8,12 @@ "skill_id": "lubuseb/least-privilege-plan", "owner": "lubuseb", "name": "least-privilege-plan", - "version": "sha-e2d0eec62745", + "version": "sha-2ed0e113ff52", "digest": "09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", - "profile_digest": "f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "profile_digest": "259c08c1e5725838b9cd593e7a595c883ad10a4ed8d8b2107bfb3cd712977d4e", "trust_tier": "community", - "install_command": "runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai", - "run_command": "runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai", + "install_command": "runx add lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai", + "run_command": "runx skill lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai", "public_url": "https://runx.ai/x/lubuseb/least-privilege-plan" } } diff --git a/skills/least-privilege-plan/evidence/registry-read.json b/skills/least-privilege-plan/evidence/registry-read.json index a09f3125..7b6fa565 100644 --- a/skills/least-privilege-plan/evidence/registry-read.json +++ b/skills/least-privilege-plan/evidence/registry-read.json @@ -3,17 +3,17 @@ "registry": { "action": "read", "source": "remote", - "ref": "lubuseb/least-privilege-plan@sha-e2d0eec62745", + "ref": "lubuseb/least-privilege-plan@sha-2ed0e113ff52", "skill": { "skill_id": "lubuseb/least-privilege-plan", "owner": "lubuseb", "name": "least-privilege-plan", "description": "Produce a read-only least-privilege grant plan from bounded run history and a declared policy.", "category": "security", - "version": "sha-e2d0eec62745", + "version": "sha-2ed0e113ff52", "digest": "09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471", "markdown": "---\nname: least-privilege-plan\ndescription: Produce a read-only least-privilege grant plan from bounded run history and a declared policy.\nsource:\n type: cli-tool\n command: node\n args:\n - run.mjs\n input_mode: stdin\n cwd: .\n timeout_seconds: 30\ninputs:\n run_history_packet:\n type: json\n required: true\n description: Bounded run history containing grants, observed effects, receipt refs, and missing-evidence notes.\n policy:\n type: json\n required: true\n description: Declared least-privilege policy with grant metadata, reserved scopes, and review rules.\n objective:\n type: string\n required: false\n description: Optional operator intent for the plan.\nrunx:\n category: security\n input_resolution:\n required:\n - run_history_packet\n - policy\n---\n\n# least-privilege-plan\n\nUse this skill when an operator needs a read-only plan for narrowing granted\nauthority after one or more runs. The skill compares a bounded run history\npacket against a declared policy and emits keep, reduce, revoke, and\nneeds_human_review recommendations with cited evidence.\n\nThe skill does not mutate grants, write credentials, call provider APIs, or infer\nauthority from broad task success. Every recommendation cites exact observed\neffects, policy inputs, unused scopes, or missing evidence so a reviewer can\napply the plan separately.\n\n## Inputs\n\n- `run_history_packet`: bounded JSON with `subject`, `policy_id`, `grants`,\n `observed_effects`, `receipt_refs`, and optional `missing_evidence`.\n- `policy`: declared JSON policy with grant metadata, reserved scopes, wildcard\n rules, and review thresholds.\n- `objective`: optional operator intent.\n\n## Output\n\nThe runner returns JSON with:\n\n- `plan`: the typed least-privilege plan.\n- `recommendations`: one recommendation per grant.\n- `evidence_json`: a compact evidence object suitable for external review.\n- `report`: a human-readable summary.\n\nRecommendation actions are exactly `keep`, `reduce`, `revoke`, and\n`needs_human_review`.", - "profile_digest": "f71005f3f3f5a85109980dc5fde8f427ceee0ec34ae315410954292574516dea", + "profile_digest": "259c08c1e5725838b9cd593e7a595c883ad10a4ed8d8b2107bfb3cd712977d4e", "runner_names": [ "default" ], @@ -33,7 +33,7 @@ "id": "publisher:user_53f00ae7ec2363e37ac6ff68", "status": "declared", "summary": "LubuSeb", - "issued_at": "2026-06-22T14:30:00.811Z", + "issued_at": "2026-06-22T14:38:27.637Z", "metadata": { "publisher_display_name": "LubuSeb", "publisher_handle": "lubuseb", @@ -43,8 +43,8 @@ } } ], - "install_command": "runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai", - "run_command": "runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai" + "install_command": "runx add lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai", + "run_command": "runx skill lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai" } } } diff --git a/skills/least-privilege-plan/evidence/report.md b/skills/least-privilege-plan/evidence/report.md index fdf4d0b0..c1773ca7 100644 --- a/skills/least-privilege-plan/evidence/report.md +++ b/skills/least-privilege-plan/evidence/report.md @@ -1,13 +1,13 @@ # least-privilege-plan delivery report -- Package: `lubuseb/least-privilege-plan@sha-e2d0eec62745`. -- Public registry URL: `https://runx.ai/x/lubuseb/least-privilege-plan@sha-e2d0eec62745`. +- Package: `lubuseb/least-privilege-plan@sha-2ed0e113ff52`. +- Public registry URL: `https://runx.ai/x/lubuseb/least-privilege-plan@sha-2ed0e113ff52`. - Source PR: `https://github.com/runxhq/runx/pull/118`. - `runx-cli 0.6.13` was used for publish, registry read, clean install, harness, dogfood, and receipt verification. -- Local harness passed three cases: `over-broad-grant-plan`, `justified-grant-plan`, and `missing-grants-fails-closed`. -- Hosted clean install succeeded with `runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai`. -- Harness from the clean installed package passed the same three cases and all harness receipts verified. -- Hosted dogfood produced sealed receipt `runx:receipt:sha256:fd396e6bf878658a9d3c745a5c4d228c95bc6c45008a298cb2bbe2d2f2b13d5f`. +- Local harness passed five cases: `over-broad-grant-plan`, `justified-grant-plan`, `missing-grants-fails-closed`, `invalid-effect-status-fails-closed`, and `policy-mismatch-fails-closed`. +- Hosted clean install succeeded with `runx add lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai`. +- Harness from the clean installed package passed the same five cases and all harness receipts verified. +- Hosted dogfood produced sealed receipt `runx:receipt:sha256:434a5446b2f7d85b35a2ff9ec70ba48d25c8bf06b8cb64f0f79ff4a576f33d77`. - `runx verify` returned `valid=true` and no findings for the dogfood receipt. - The runner emits `keep`, `reduce`, `revoke`, and `needs_human_review` recommendations with exact observed effects, policy refs, unused scopes, or missing evidence. - The implementation is read-only: it reads the provided JSON packet and policy, computes recommendations in memory, requires no credentials, performs no network/provider calls, and emits structured stdout. @@ -15,9 +15,9 @@ Reproduce: ```bash -runx add lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai -runx registry read lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --json +runx add lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai +runx registry read lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai --json runx harness ./least-privilege-plan --json -runx skill lubuseb/least-privilege-plan@sha-e2d0eec62745 --registry https://api.runx.ai --input-json run_history_packet='' --input-json policy='' --json +runx skill lubuseb/least-privilege-plan@sha-2ed0e113ff52 --registry https://api.runx.ai --input-json run_history_packet='' --input-json policy='' --json runx verify --receipt-dir /tmp/runx-least-privilege-plan-hosted-dogfood-receipts --json ``` diff --git a/skills/least-privilege-plan/evidence/verification.json b/skills/least-privilege-plan/evidence/verification.json index 6904cd36..3ec6dd90 100644 --- a/skills/least-privilege-plan/evidence/verification.json +++ b/skills/least-privilege-plan/evidence/verification.json @@ -3,7 +3,7 @@ "signature_mode": "production", "trees": [ { - "root_receipt_id": "sha256:9cf478c16863cb9c70c72713830af33805764ed229e321cac3a7b256a009d854", + "root_receipt_id": "sha256:cfceaadb4aee0c212b40c4eb2a554f5df3a6e5fbf0ea0df7538efc627e839a15", "receipt_count": 1, "parent_missing": null, "valid": true, diff --git a/skills/least-privilege-plan/run.mjs b/skills/least-privilege-plan/run.mjs index 46f7d5bc..11cb87d0 100644 --- a/skills/least-privilege-plan/run.mjs +++ b/skills/least-privilege-plan/run.mjs @@ -7,7 +7,14 @@ const policy = requireObject(inputs.policy, "policy"); const objective = stringValue(inputs.objective) || "Produce a least-privilege grant plan."; const subject = stringValue(history.subject) || "unknown-subject"; -const policyId = stringValue(history.policy_id) || stringValue(policy.policy_id) || "unknown-policy"; +const historyPolicyId = stringValue(history.policy_id); +const declaredPolicyId = stringValue(policy.policy_id); +if (!historyPolicyId) throw new Error("run_history_packet.policy_id is required"); +if (!declaredPolicyId) throw new Error("policy.policy_id is required"); +if (historyPolicyId !== declaredPolicyId) { + throw new Error("run_history_packet.policy_id must match policy.policy_id"); +} +const policyId = declaredPolicyId; const grants = normalizeGrants(history.grants); const effects = normalizeEffects(history.observed_effects); const missingEvidence = normalizeMissingEvidence(history.missing_evidence); @@ -246,7 +253,7 @@ function normalizeEffects(value) { grant_id: stringValue(effect.grant_id) || "", verb: stringValue(effect.verb) || "", resource: stringValue(effect.resource) || "", - status: normalizeStatus(effect.status), + status: normalizeStatus(effect.status, index), receipt_ref: stringValue(effect.receipt_ref) || "", }; }); @@ -262,10 +269,11 @@ function normalizeMissingEvidence(value) { }); } -function normalizeStatus(value) { - const normalized = stringValue(value) || "success"; +function normalizeStatus(value, index) { + const normalized = stringValue(value); + if (!normalized) throw new Error(`observed_effects[${index}].status is required`); if (["success", "denied", "dry_run"].includes(normalized)) return normalized; - return "success"; + throw new Error(`observed_effects[${index}].status must be success, denied, or dry_run`); } function renderReport(plan) {