Skip to content

PersistedApprovalGrants

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:955

The persisted (always) grant store, backed by a JSON file whose path is injected (the runner resolves it via fileUtils → .gsloth/.gsloth-settings/shell-allowlist.json for approvals and …/shell-denylist.json for refusals) so tests can point it at a temp dir.

One class, two files. Which list a store’s entries belong to is the caller’s question, not this class’s: it holds ApprovalGrant records and writes them back. The only thing either side configures is PersistedApprovalGrantsOptions.legacyPrefixMigration, which the deny store turns off.

The v1 migration, and the direction it goes

Section titled “The v1 migration, and the direction it goes”

The shipped v1 file held prefixes: string[] — classified command PREFIXES, so a stored npm test also auto-approved npm test --watch. Each prefix migrates to an exact entry for the same string, with one notice naming the file.

That narrows what the file grants, on purpose: a v1 prefix was broader than what the human was actually shown when they answered the prompt, so narrowing it costs at worst a re-prompt and never an execution — the direction every ambiguity in this design resolves. The migrated file is rewritten as v2 immediately, so the notice is a one-time event rather than a per-session one; a write that fails (read-only checkout) is not fatal — the grants are in force for this session and the notice simply appears again next time.

new PersistedApprovalGrants(filePath, options?): PersistedApprovalGrants

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:988

string

PersistedApprovalGrantsOptions

PersistedApprovalGrants

add(grant): boolean

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1238

Add a grant and persist the whole store. A duplicate entry rewrites nothing.

Returns whether the grant is now recorded in the file ([[EXT-144]]), which is not the same question as whether it is in force — it is in force either way, held here and in the runner’s session store. false says only that a restart will not find it.

ApprovalGrant

boolean


canPersist(): boolean

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1227

[[EXT-144]] — may this store write its file at all? False when the load failed, in which case every write is refused.

Public because the caller has to know before it builds the record it is about to hand over: a grant is stamped with the scope it actually got, the runner’s in-memory stores can hold the very object they are passed, and a scope corrected after the fact would be corrected inside somebody else’s store. Asking first is what lets an answer that cannot be written down be recorded as the session-only thing it is.

It answers about the FILE being readable, never about a write succeeding. A store whose path cannot be written — a read-only checkout — still answers true here, because nothing was lost by reading it and the next write may well land.

boolean


entries(): ApprovalEntry[]

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1204

Just the entries, for handing to the matcher as one of its rule lists.

ApprovalEntry[]


find(entry): ApprovalGrant | undefined

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1263

The grant held under this entry’s identity, or undefined.

ApprovalEntry

ApprovalGrant | undefined


list(): ApprovalGrant[]

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1199

Every grant.

ApprovalGrant[]


remove(entry): boolean

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1290

Drop the grant held under this entry’s identity and rewrite the file.

Returns whether the deletion reached the FILE ([[EXT-149]]) — the mirror of what add answers, and not the same question as whether the entry is still in force here. The in-memory removal happens either way and is what lifts the entry for this session; false says only that a restart will find it again. It used to return true after a write that threw, which is how the /approvals lift came to report a deletion that had not happened.

false is also the answer when there was no such grant. The two are distinguishable with find beforehand, and the caller that reports to a user has already established the entry was there — it is offering to lift something it just listed.

The write is what makes §4.7.4’s invalidation a one-time event: a removal held only in memory would be undone by the next session reloading the same stale snapshot, so the user would be told their grant had been withdrawn once per session, forever.

The [[EXT-144]] refusal cannot strand a removal half-done, and by construction rather than by a check here: a store that could not read its file is empty — the load recovered nothing, and add takes back what it could not write — so there is never a grant to remove, and this returns before reaching the write. If that invariant is ever broken, restore it rather than teaching this method to unwind.

ApprovalEntry

boolean


size(): number

Defined in: _worktrees/docs-release/gaunt-sloth/packages/core/src/core/approvals/grants.ts:1209

How many grants are persisted.

number