Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions skills/least-privilege-plan/SKILL.md
Original file line number Diff line number Diff line change
@@ -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`.
227 changes: 227 additions & 0 deletions skills/least-privilege-plan/X.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
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

- 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
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.
43 changes: 43 additions & 0 deletions skills/least-privilege-plan/evidence/clean-install.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"status": "success",
"registry": {
"action": "install",
"source": "remote",
"ref": "lubuseb/least-privilege-plan@sha-2ed0e113ff52",
"install": {
"status": "installed",
"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-2ed0e113ff52",
"digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471",
"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-2ed0e113ff52/SKILL.md",
"digest": "sha256:09c761cf110265d8e5ddc4453fb4cff90cd5b775920557cd4eda384ae20af471",
"install_count": 1,
"package_digest": "a25cc87d7f6078709b7f7af1e7485d67257b428d3d26a895e2395ab7bcb4867e",
"profile_digest": "sha256:259c08c1e5725838b9cd593e7a595c883ad10a4ed8d8b2107bfb3cd712977d4e",
"publisher": {
"display_name": "LubuSeb",
"handle": "lubuseb",
"id": "user_53f00ae7ec2363e37ac6ff68",
"kind": "user"
},
"ref": "lubuseb/least-privilege-plan@sha-2ed0e113ff52",
"skill_id": "lubuseb/least-privilege-plan",
"source_label": "runx registry",
"status": "installed",
"trust_tier": "community",
"version": "sha-2ed0e113ff52"
}
}
}
Loading