Perch
Building modsScopes & trust

Scopes & trust

The complete scope table, what each grant means, and the contract behind the Workshop page.

3 min readUpdated Jul 21, 2026

Scopes are Perch’s entire permission model. Your manifest declares them; the Workshop page and the settings mod card render them verbatim with per-scope revocation; the sandbox installs exactly the APIs they grant. An undeclared capability doesn’t error — it simply doesn’t exist inside your Lua state.

The scope table

ScopeGrantsNotes
(none)perch.time.*, perch.json.*, host.g, the host APIpure — always available
timerhost.timer / cancel_timerfloors enforce the idle budget
storageperch.storage.*mod-scoped KV, ≤64 KB
mediaperch.media.read + on_mediathe now-playing model
media.controlperch.media.controltransport verbs only
discordperch.discord.status + on_call on_dnote on_ring on_statusread side
discord.controlperch.discord.control / .reconnectthe five call verbs
weatherperch.weather.read / .set_config + on_weathernative met.no pipeline
system.statsperch.system.stats.readCPU/RAM/GPU/temps
system.transientson_volume on_brightness on_nightlight on_connect + timer eventsthe HUD stream
volume.controlperch.volume.controlup / down / set:<0-100>
system.poweron_powerbattery events
system.downloadson_downloaddownload progress
system.notificationsperch.mirror.set_config + on_noteopt-in mirror; loud wording
appsperch.apps.*recent/top + launch of recorded refs only, never arbitrary exec
openperch.open.url / .steamhttps:// URLs and numeric appids only; audit-logged
net.http:<host>perch.http.get pinned to <host>one scope per host; ≤30 req/h, ≤1 MB

Dotted names narrow: discord reads, discord.control acts. Declare both if you do both.

What the gates actually enforce

  • Verbs are whitelists. media.control accepts exactly the transport verb set; open.url accepts exactly https://; apps.launch launches only refs the tracker recorded. There is no string that reaches a shell, a browser, or an RPC socket unchecked.
  • HTTP is pinned. net.http:api.github.com reaches api.github.com — exact host match, https only, no wandering off into other hosts. Want two hosts? Declare two scopes; the user sees both.
  • The carve-outs are absolute. Perch’s own preference directory (secrets, config, caches) is denied at the API layer regardless of any scope. Trust surfaces — the mic-live indicator, the ownership gate, suppression — live in core where no scope reaches.

The social contract

Rules of thumb:

  • Narrow beats broad: net.http:api.open-meteo.com, never a generic proxy host you control.
  • Late beats early: don’t declare scopes for the feature you might build next month.
  • Explain in your Workshop description why each non-obvious scope exists — the users who read scope lists are exactly the users who write reviews.

Revocation

Users can revoke any scope per-mod from the settings card. Your mod is not told — the APIs simply stop existing (calls become no-ops, events stop). Write logic that degrades: a weather widget without weather should show its waiting state, not error.

esc
Type to search
navigate open