Least Privilege Auditor
Turn granted authority plus attributable observed usage into a bounded
attenuation proposal.
This skill resolves every supporting receipt id through the native ledger
runner before comparing exercised scopes from Runx's redacted receipt detail
with the current grant. Native detail is authoritative for scope use. A supplied
usage summary exists only for deterministic replay of older evidence that lacks
that projection. Missing receipt proof defers every scope. The output is a
reviewable attenuation proposal, not an automatic change.
Composes
What this skill does
- Diff granted authority against receipt-backed usage.
- Classify each granted scope as
keep, narrow, remove, or defer.
- Propose the narrowest grant that still covers observed usage.
- State residual risk after attenuation.
- Emit a receipt-quality report a reviewer can apply or reject.
When to use this skill
- Periodic least-privilege review of a skill, grant, or principal before
publish, renewal, or maturity promotion.
- After an incident, to identify authority that can be safely removed without
breaking observed behavior.
- Before expanding distribution of a public skill, to prove its grant is
minimal against real receipts.
- When a reviewer asks for a scope-by-scope evidence trail, not just a summary.
When not to use this skill
- To grant new authority. This skill only narrows; widening is a human
decision.
- When no usable receipt evidence exists. Return
needs_more_evidence rather
than guessing a grant down to nothing.
- For secret material handling or credential exposure. Use the appropriate
secret-leak triage flow instead of scope review.
- When the user asks for automatic permission changes. Produce a proposal and
stop unless a separate approved delivery lane exists.
- When grant semantics are unknown and cannot be normalized. Return
needs_input with the exact syntax or policy question.
Procedure
Scope the audit target.
- Identify
subject, grant source, receipt ids or receipt window, and
whether receipts are from the same principal or skill version.
- Gate: if the subject, grant list, or usage source is ambiguous, stop with
needs_input.
- Evidence expected: subject id or label, granted scope list, receipt ids or
an explicit statement that no receipts were available.
Normalize granted scopes.
- Parse each scope into verb, resource, path or namespace, conditions, and
wildcard breadth.
- Preserve original scope strings. Do not rewrite policy syntax casually.
- Gate: if a scope cannot be parsed, keep it as
defer and request the
missing policy semantics instead of treating it as unused.
Build the usage model from attributable evidence.
- Resolve each supporting receipt id through
ledger read.
- Read exercised scopes and receipt references from native redacted receipt
detail. Use the supplied usage summary only when replaying older evidence.
- Count successful use separately from denied or dry-run checks.
- Do not infer scope usage from a successful high-level task alone; cite the
receipt step or policy check that exercised the authority.
Classify every granted scope.
keep: at least one observed successful use requires the granted scope as
written, or a reserved/break-glass policy explicitly requires it.
narrow: all observed uses fit a strictly smaller verb, resource,
namespace, condition, or path.
remove: no observed use, denied check, or documented reserved purpose
supports the scope.
defer: evidence is conflicting, receipt attribution is weak, or policy
semantics are unknown.
Propose attenuation.
- Remove scopes classified as
remove.
- Downgrade scopes classified as
narrow only when every observed use fits
the narrower grant.
- Leave
keep and defer scopes unchanged in the proposed grant.
- Gate: never produce a proposal narrower than the evidence supports. A
scope used once is used.
State residual risk and reviewer action.
- Name what the proposed grant can still do.
- Name any broad scope kept despite thin evidence and why.
- Separate
applyable now from needs human policy decision.
Emit receipt expectations.
- A valid receipt for this skill should record input grant count, receipt
sources, classification counts, proposed removals or narrowings, stop
status, and unresolved questions.
Edge cases and stop conditions
- Empty or unattributable usage evidence: return
needs_more_evidence; do not
remove all scopes by default.
- Missing granted scopes: return
needs_input; there is no baseline to diff.
- Receipt subject mismatch: return
needs_input with the mismatched subject or
version.
- Conflicting receipts: classify affected scopes as
defer and return
needs_human if the conflict changes the proposal.
- Wildcard grants: narrow only to observed resource prefixes when receipt
coverage is representative; otherwise keep and flag residual risk.
- Reserved, compliance, or break-glass scopes: keep unless the operator
provides explicit policy authority to remove them.
- Dry-run-only use: do not count as successful exercised authority unless the
grant exists solely for validation.
- Grant already matches usage: return
no_change with the evidence summary.
- User asks to hide or omit unused authority: refuse that part and report the
complete scope diff.
Output schema
Return a structured report with these fields:
status: attenuation_proposed | no_change | needs_more_evidence
subject: string
evidence:
receipt_ids: [string]
receipt_window: string | null
grant_source: string | null
limitations: [string]
scope_diff:
- granted_scope: string
normalized:
verb: string | null
resource: string | null
conditions: object | null
observed_use:
count: number
verbs: [string]
resources: [string]
receipt_refs: [string]
classification: keep | narrow | remove | defer
proposal: string | null
rationale: string
attenuated_grant: [string]
removed_scopes: [string]
narrowed_scopes:
- from: string
to: string
kept_scopes: [string]
deferred_scopes: [string]
residual_risk: [string]
reviewer_action: applyable_now | gather_more_receipts | none
receipt_expectations:
classification_counts: object
stop_status: string
unresolved_questions: [string]
Worked example
Input:
subject: skills/report-exporter
granted_scopes:
- drive.files.read:/reports/*
- drive.files.write:/reports/*
- drive.files.delete:/reports/*
receipt_ids: [rx_101, rx_102]
usage_summary:
observed:
- scope: drive.files.read:/reports/*
count: 8
refs: [rx_101:step_3, rx_102:step_2]
- scope: drive.files.write:/reports/*
count: 2
refs: [rx_101:step_6, rx_102:step_5]
Output:
status: attenuation_proposed
subject: skills/report-exporter
removed_scopes:
- drive.files.delete:/reports/*
narrowed_scopes: []
kept_scopes:
- drive.files.read:/reports/*
- drive.files.write:/reports/*
attenuated_grant:
- drive.files.read:/reports/*
- drive.files.write:/reports/*
residual_risk:
- The skill can still read and write any file under /reports/*.
reviewer_action: applyable_now
The delete scope is removable because no cited receipt exercised delete
authority. The read and write scopes stay because each was used at least once.
Inputs
subject (optional): skill id, grant id, principal, or other label for what
is being audited.
granted_scopes (required): the current scopes granted to the subject,
preferably in canonical policy syntax.
receipt_ids (required): exact receipt ids supporting the audit.
usage_summary (optional): legacy replay supplement with an observed array
of scope, count, and receipt refs; live runs use native receipt detail.
receipt_rows (optional): native-projection rows for deterministic replay;
live runs resolve receipt_ids from the configured receipt store.
receipt_details (optional): native redacted detail projections for
deterministic replay; live runs resolve them from receipt_ids.
objective (optional): operator intent that focuses the review, such as
"prepare for public publish" or "post-incident attenuation".
policy_notes (optional): reserved scopes, compliance constraints, or
human-approved exceptions that affect removal decisions.
1---2name: least-privilege3description: Verify the receipt ids behind a normalized authority-usage summary, compare that evidence with granted scopes, and propose the narrowest grant the evidence supports.4---56# Least Privilege Auditor78Turn granted authority plus attributable observed usage into a bounded9attenuation proposal.1011This skill resolves every supporting receipt id through the native `ledger`12runner before comparing exercised scopes from Runx's redacted receipt detail13with the current grant. Native detail is authoritative for scope use. A supplied14usage summary exists only for deterministic replay of older evidence that lacks15that projection. Missing receipt proof defers every scope. The output is a16reviewable attenuation proposal, not an automatic change.1718## Composes1920<!-- Generated from the native execution closure; run pnpm core-skills:composes:generate. -->2122- `ledger#read`2324## What this skill does25261. Diff granted authority against receipt-backed usage.272. Classify each granted scope as `keep`, `narrow`, `remove`, or `defer`.283. Propose the narrowest grant that still covers observed usage.294. State residual risk after attenuation.305. Emit a receipt-quality report a reviewer can apply or reject.3132## When to use this skill3334- Periodic least-privilege review of a skill, grant, or principal before35 publish, renewal, or maturity promotion.36- After an incident, to identify authority that can be safely removed without37 breaking observed behavior.38- Before expanding distribution of a public skill, to prove its grant is39 minimal against real receipts.40- When a reviewer asks for a scope-by-scope evidence trail, not just a summary.4142## When not to use this skill4344- To grant new authority. This skill only narrows; widening is a human45 decision.46- When no usable receipt evidence exists. Return `needs_more_evidence` rather47 than guessing a grant down to nothing.48- For secret material handling or credential exposure. Use the appropriate49 secret-leak triage flow instead of scope review.50- When the user asks for automatic permission changes. Produce a proposal and51 stop unless a separate approved delivery lane exists.52- When grant semantics are unknown and cannot be normalized. Return53 `needs_input` with the exact syntax or policy question.5455## Procedure56571. Scope the audit target.58 - Identify `subject`, grant source, receipt ids or receipt window, and59 whether receipts are from the same principal or skill version.60 - Gate: if the subject, grant list, or usage source is ambiguous, stop with61 `needs_input`.62 - Evidence expected: subject id or label, granted scope list, receipt ids or63 an explicit statement that no receipts were available.64652. Normalize granted scopes.66 - Parse each scope into verb, resource, path or namespace, conditions, and67 wildcard breadth.68 - Preserve original scope strings. Do not rewrite policy syntax casually.69 - Gate: if a scope cannot be parsed, keep it as `defer` and request the70 missing policy semantics instead of treating it as unused.71723. Build the usage model from attributable evidence.73 - Resolve each supporting receipt id through `ledger read`.74 - Read exercised scopes and receipt references from native redacted receipt75 detail. Use the supplied usage summary only when replaying older evidence.76 - Count successful use separately from denied or dry-run checks.77 - Do not infer scope usage from a successful high-level task alone; cite the78 receipt step or policy check that exercised the authority.79804. Classify every granted scope.81 - `keep`: at least one observed successful use requires the granted scope as82 written, or a reserved/break-glass policy explicitly requires it.83 - `narrow`: all observed uses fit a strictly smaller verb, resource,84 namespace, condition, or path.85 - `remove`: no observed use, denied check, or documented reserved purpose86 supports the scope.87 - `defer`: evidence is conflicting, receipt attribution is weak, or policy88 semantics are unknown.89905. Propose attenuation.91 - Remove scopes classified as `remove`.92 - Downgrade scopes classified as `narrow` only when every observed use fits93 the narrower grant.94 - Leave `keep` and `defer` scopes unchanged in the proposed grant.95 - Gate: never produce a proposal narrower than the evidence supports. A96 scope used once is used.97986. State residual risk and reviewer action.99 - Name what the proposed grant can still do.100 - Name any broad scope kept despite thin evidence and why.101 - Separate `applyable now` from `needs human policy decision`.1021037. Emit receipt expectations.104 - A valid receipt for this skill should record input grant count, receipt105 sources, classification counts, proposed removals or narrowings, stop106 status, and unresolved questions.107108## Edge cases and stop conditions109110- Empty or unattributable usage evidence: return `needs_more_evidence`; do not111 remove all scopes by default.112- Missing granted scopes: return `needs_input`; there is no baseline to diff.113- Receipt subject mismatch: return `needs_input` with the mismatched subject or114 version.115- Conflicting receipts: classify affected scopes as `defer` and return116 `needs_human` if the conflict changes the proposal.117- Wildcard grants: narrow only to observed resource prefixes when receipt118 coverage is representative; otherwise keep and flag residual risk.119- Reserved, compliance, or break-glass scopes: keep unless the operator120 provides explicit policy authority to remove them.121- Dry-run-only use: do not count as successful exercised authority unless the122 grant exists solely for validation.123- Grant already matches usage: return `no_change` with the evidence summary.124- User asks to hide or omit unused authority: refuse that part and report the125 complete scope diff.126127## Output schema128129Return a structured report with these fields:130131```yaml132status: attenuation_proposed | no_change | needs_more_evidence133subject: string134evidence:135 receipt_ids: [string]136 receipt_window: string | null137 grant_source: string | null138 limitations: [string]139scope_diff:140 - granted_scope: string141 normalized:142 verb: string | null143 resource: string | null144 conditions: object | null145 observed_use:146 count: number147 verbs: [string]148 resources: [string]149 receipt_refs: [string]150 classification: keep | narrow | remove | defer151 proposal: string | null152 rationale: string153attenuated_grant: [string]154removed_scopes: [string]155narrowed_scopes:156 - from: string157 to: string158kept_scopes: [string]159deferred_scopes: [string]160residual_risk: [string]161reviewer_action: applyable_now | gather_more_receipts | none162receipt_expectations:163 classification_counts: object164 stop_status: string165 unresolved_questions: [string]166```167168## Worked example169170Input:171172```yaml173subject: skills/report-exporter174granted_scopes:175 - drive.files.read:/reports/*176 - drive.files.write:/reports/*177 - drive.files.delete:/reports/*178receipt_ids: [rx_101, rx_102]179usage_summary:180 observed:181 - scope: drive.files.read:/reports/*182 count: 8183 refs: [rx_101:step_3, rx_102:step_2]184 - scope: drive.files.write:/reports/*185 count: 2186 refs: [rx_101:step_6, rx_102:step_5]187```188189Output:190191```yaml192status: attenuation_proposed193subject: skills/report-exporter194removed_scopes:195 - drive.files.delete:/reports/*196narrowed_scopes: []197kept_scopes:198 - drive.files.read:/reports/*199 - drive.files.write:/reports/*200attenuated_grant:201 - drive.files.read:/reports/*202 - drive.files.write:/reports/*203residual_risk:204 - The skill can still read and write any file under /reports/*.205reviewer_action: applyable_now206```207208The delete scope is removable because no cited receipt exercised delete209authority. The read and write scopes stay because each was used at least once.210211## Inputs212213- `subject` (optional): skill id, grant id, principal, or other label for what214 is being audited.215- `granted_scopes` (required): the current scopes granted to the subject,216 preferably in canonical policy syntax.217- `receipt_ids` (required): exact receipt ids supporting the audit.218- `usage_summary` (optional): legacy replay supplement with an `observed` array219 of scope, count, and receipt refs; live runs use native receipt detail.220- `receipt_rows` (optional): native-projection rows for deterministic replay;221 live runs resolve `receipt_ids` from the configured receipt store.222- `receipt_details` (optional): native redacted detail projections for223 deterministic replay; live runs resolve them from `receipt_ids`.224- `objective` (optional): operator intent that focuses the review, such as225 "prepare for public publish" or "post-incident attenuation".226- `policy_notes` (optional): reserved scopes, compliance constraints, or227 human-approved exceptions that affect removal decisions.