moderator-toolbox-nxg-for-reddit / modules/shared/proposals/gateway

modules/shared/proposals/gateway

Functions

isTrainingCaptureActive()

isTrainingCaptureActive(subreddit): Promise<boolean>

Defined in: extension/data/modules/shared/proposals/gateway.ts:338

Whether training/second-opinion capture is active for the current user in subreddit. Bulk-action surfaces (which v1 does not capture) call this to refuse gracefully in training mode instead of letting the per-item guard fail-close mid-batch.

Parameters

subreddit

string

The subreddit to check.

Returns

Promise<boolean>


maybePropose()

maybePropose(action, ctx): Promise<boolean>

Defined in: extension/data/modules/shared/proposals/gateway.ts:130

Decides whether to capture action as a proposal instead of performing it.

Parameters

action

ProposedAction

The fully-frozen action to capture.

ctx

ProposalContext

Where/what the action targets and whether review is forced.

Returns

Promise<boolean>

true if captured (caller MUST abort its real pipeline), else false.


performProposal()

performProposal(subreddit, proposal, reviewer, pruneRetentionDays?, overrides?): Promise<PerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:506

Accepts a proposal: replays its frozen action and, only on full success, marks it accepted. A replay failure records needs_attention with step detail instead. Enforces our workflow rules (Reddit’s API is the real permission gate): a proposer cannot self-accept their own second-opinion request, and terminal proposals cannot be replayed. (The trainees-cannot-accept rule is applied at the UI in Block 3, which knows the reviewer’s trainee status.)

The accept first claims the proposal in one atomic write - the compare-and-set that makes two reviewers accepting the same proposal serialize rather than both replaying the (irreversible) side effect. The claim also re-checks the accept preconditions (terminal / irreversible-retry) against the fresh page, so a stale caller snapshot can’t slip a double-apply past them; a refused claim is surfaced as already-resolved/irreversible-retry/in-progress. The replay then uses the freshly-claimed state, not the caller’s snapshot.

Parameters

subreddit

string

The subreddit the proposal belongs to.

proposal

Proposal

The proposal to accept (its current known state).

reviewer

string

Username of the accepting moderator.

pruneRetentionDays?

number

Retention window (days) to prune resolved proposals by in the same write that marks this one accepted, or omit to skip pruning.

overrides?

AcceptOverrides

Reviewer edits to merge into the action before replay (accept-with- edit); omit to replay the proposal exactly as captured.

Returns

Promise<PerformResult>


performRemoval()

performRemoval(ctx, spam): Promise<void>

Defined in: extension/data/modules/shared/proposals/gateway.ts:199

Performs a real removal for an accept surface (the Edit-&-Accept overlay’s “Silently remove”), bypassing capture entirely. Runs in the authorized replay window so it still performs even if the accepting reviewer happens to be a trainee in this subreddit - an accept surface must always perform, never re-capture. UI calls this instead of importing removeThing.

Parameters

ctx

ProposalContext

Where/what the removal targets.

spam

boolean

Whether to remove as spam.

Returns

Promise<void>


proposeOrApprove()

proposeOrApprove(ctx): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:208

Captures an approve as a proposal when sandboxed/forced, otherwise performs the real approval. UI calls this instead of importing approveThing.

Parameters

ctx

ProposalContext

Where/what the approval targets and whether review is forced.

Returns

Promise<ProposeOrPerformResult>


proposeOrBan()

proposeOrBan(ctx, params): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:284

Captures or performs a ban. ctx.itemId is the target username and ctx.itemKind is 'user'.

Parameters

ctx

ProposalContext

params

BanParams

Returns

Promise<ProposeOrPerformResult>


proposeOrDistinguish()

proposeOrDistinguish(ctx, sticky): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:229

Captures or performs a distinguish on the target thing.

Parameters

ctx

ProposalContext

sticky

boolean

Returns

Promise<ProposeOrPerformResult>


proposeOrLock()

proposeOrLock(ctx): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:215

Captures or performs a lock on the target thing.

Parameters

ctx

ProposalContext

Returns

Promise<ProposeOrPerformResult>


proposeOrMarkNsfw()

proposeOrMarkNsfw(ctx, nsfw): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:236

Captures or performs marking the target post NSFW (nsfw: false unmarks it).

Parameters

ctx

ProposalContext

nsfw

boolean

Returns

Promise<ProposeOrPerformResult>


proposeOrMute()

proposeOrMute(ctx, params?): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:308

Captures or performs a mute of ctx.itemId (username).

Parameters

ctx

ProposalContext

params?
duration?

number

note?

string

Returns

Promise<ProposeOrPerformResult>


proposeOrRemove()

proposeOrRemove(ctx, spam): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:182

Captures a plain remove as a proposal when sandboxed/forced, otherwise performs the real removal. UI calls this instead of importing removeThing, so the static reachability guard can keep moderation primitives out of UI code.

Parameters

ctx

ProposalContext

Where/what the removal targets and whether review is forced.

spam

boolean

Whether to remove as spam.

Returns

Promise<ProposeOrPerformResult>


proposeOrSticky()

proposeOrSticky(ctx, num): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:243

Captures or performs stickying the target submission into num’s slot (1 or 2).

Parameters

ctx

ProposalContext

num

number | undefined

Returns

Promise<ProposeOrPerformResult>


proposeOrUnban()

proposeOrUnban(ctx): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:301

Captures or performs an unban of ctx.itemId (username).

Parameters

ctx

ProposalContext

Returns

Promise<ProposeOrPerformResult>


proposeOrUnlock()

proposeOrUnlock(ctx): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:222

Captures or performs an unlock on the target thing.

Parameters

ctx

ProposalContext

Returns

Promise<ProposeOrPerformResult>


proposeOrUnmute()

proposeOrUnmute(ctx): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:325

Captures or performs an unmute of ctx.itemId (username).

Parameters

ctx

ProposalContext

Returns

Promise<ProposeOrPerformResult>


proposeOrUnsticky()

proposeOrUnsticky(ctx): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:255

Captures or performs unstickying the target submission.

Parameters

ctx

ProposalContext

Returns

Promise<ProposeOrPerformResult>


proposeOrUserFlair()

proposeOrUserFlair(ctx, flair): Promise<ProposeOrPerformResult>

Defined in: extension/data/modules/shared/proposals/gateway.ts:262

Captures or performs setting the target user’s flair. ctx.itemId is the username.

Parameters

ctx

ProposalContext

flair
cssClass?

string

templateID?

string

text?

string

Returns

Promise<ProposeOrPerformResult>


registerReplayHandler()

registerReplayHandler(type, handler): void

Defined in: extension/data/modules/shared/proposals/gateway.ts:366

Registers the replay handler for a composite action type (e.g. removal-reason), called from the owning module so this substrate stays feature-agnostic.

Parameters

type

"approve" | "remove" | "ban" | "mute" | "unmute" | "lock" | "removal-reason" | "unlock" | "distinguish" | "marknsfw" | "sticky" | "unban" | "userflair"

The action discriminant to handle.

handler

ReplayHandler

Replays the action; must throw on failure.

Returns

void


setActionGuardDecider()

setActionGuardDecider(decider): void

Defined in: extension/data/modules/shared/proposals/gateway.ts:120

Installs the per-action guard decision used by maybePropose. Injectable for tests; wired to the warm guarded-action config by the proposals module.

Parameters

decider

ActionGuardDecider

Per-subreddit, per-action-type guard check (sync or async).

Returns

void


setCaptureDecider()

setCaptureDecider(decider): void

Defined in: extension/data/modules/shared/proposals/gateway.ts:100

Installs the capture decision used by maybePropose. Injectable for tests; wired to the warm trainee state by the proposals module.

Parameters

decider

CaptureDecider

Per-subreddit capture-active check (sync or async).

Returns

void


setCurrentUserProvider()

setCurrentUserProvider(provider): void

Defined in: extension/data/modules/shared/proposals/gateway.ts:81

Installs the provider that returns the current logged-in username (wired by the proposals module from cached session state; injectable for tests).

Parameters

provider

CurrentUserProvider

Returns the current username.

Returns

void

Interfaces

AcceptOverrides

Defined in: extension/data/modules/shared/proposals/gateway.ts:347

Reviewer edits applied to a proposal at accept time (accept-with-edit). Only the fields a reviewer can tweak before replay; composite handlers merge these onto the thawed intent. Currently the removal-reason message text only.

Properties

reasonText?

optional reasonText?: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:349

Replacement composed reason text for a removal-reason proposal.


BanParams

Defined in: extension/data/modules/shared/proposals/gateway.ts:272

Parameters for a ban (the resolved values, ready to perform or freeze).

Properties

context?

optional context?: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:277

days

days: number

Defined in: extension/data/modules/shared/proposals/gateway.ts:274

message

message: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:276

note

note: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:275

permanent

permanent: boolean

Defined in: extension/data/modules/shared/proposals/gateway.ts:273


ProposalContext

Defined in: extension/data/modules/shared/proposals/gateway.ts:54

Context for a capture decision at an action chokepoint.

Properties

force?

optional force?: boolean

Defined in: extension/data/modules/shared/proposals/gateway.ts:66

When true, force capture as an explicit second-opinion request.

itemId

itemId: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:58

Fullname of the targeted thing.

itemKind

itemKind: ProposalItemKind

Defined in: extension/data/modules/shared/proposals/gateway.ts:60

Whether the target is a post or comment.

note?

optional note?: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:64

Optional rationale from the proposer.

subreddit

subreddit: string

Defined in: extension/data/modules/shared/proposals/gateway.ts:56

Subreddit the action targets.

Type Aliases

PerformResult

PerformResult = { ok: true; proposal: Proposal; } | { current?: Proposal; error?: string; ok: false; reason: "not-found" | "already-resolved" | "invalid-transition" | "self-accept" | "replay-failed" | "irreversible-retry" | "in-progress"; }

Defined in: extension/data/modules/shared/proposals/gateway.ts:467

The outcome of an accept attempt.


ProposeOrPerformResult

ProposeOrPerformResult = "captured" | "performed"

Defined in: extension/data/modules/shared/proposals/gateway.ts:173

Outcome of a propose-or-perform helper: captured for review, or performed for real.