Browse API 1 documentation
Capabilities
Requested permissions and the API each permission unlocks.
Capabilities are native permissions requested in manifest.json and accepted by the user. A requested capability is not authority by itself: Mango stores the grant and checks it for every delivered event and accepted bridge call.
Channel and query capabilities remain bound to the instance’s scope. A server-scoped instance does not turn channel.send into permission to send anywhere. network.send accepts only a modeled, explicit target that Mango confirms is currently joined; no capability in API 1 grants arbitrary IRC lines.
An application-scoped Root is deliberately outside every IRC session. IRC message delivery, sends, notices, typing, presence, filters, slash commands, cards, and member actions remain unavailable even if its manifest requests those capabilities. Application Roots may use storage, settings, host-attributed status badges, and declared app-wide contributions such as upload providers.
Implemented capabilities
| Capability | API 1 access |
|---|---|
channel.read |
Receive message events for the bound channel, or live messages from all confirmed joined channels when the extension is server-scoped. A server-scoped reader also receives the retained channels roster event. |
channel.send |
Use grove.send(text) and channel-scoped grove.typing(...). |
channel.notice |
Use grove.notice(text) for the bound channel. |
query.read |
Receive direct-message-shaped message events in a granted query scope. |
query.send |
Use targeted grove.send in an existing query, direct-message grove.reply, and direct-message typing. A channel-message grove.reply instead requires channel.send in conversation scope or network.send in server scope. |
query.open |
Add { open: true } to an explicit { to } send so Mango creates and selects that private conversation. Requires query.send too. |
query.notice |
Use targeted grove.notice. |
presence.set |
Set or clear the connection-wide IRC away state with grove.away. |
storage |
Use a persistent per-extension WebKit data store. Without it web storage is ephemeral. |
storage.secure |
Use Keychain-backed grove.secrets namespaces and the legacy Blowfish interoperability helper. |
oauth.authorize |
Open a user-visible system authentication session through grove.oauth.authorize(...). Mango owns the callback, random state, and PKCE challenge; the extension exchanges the resulting one-time code. |
network.request |
Make bounded native HTTPS requests to accepted hostPermissions origins when an API does not support browser CORS. Redirects are returned but never followed automatically; cookies, unsafe headers, and undeclared destinations are rejected. |
commands.register |
Register slash commands and publish their native output cards. An exclusive composer utility may use this capability for manifest-declared commands that launch it on demand and return draft text. |
ui.member-actions |
Register bounded, host-attributed actions in channel member menus. |
ui.web-pane |
From a server-scoped headless Root, open or replace one isolated packaged HTML pane beside an explicit confirmed channel. Data requests use accepted hostPermissions; the page receives no Grove bridge or IRC context. Remote executable pages are rejected. |
ui.member-badges |
Publish bounded, host-attributed badges beside members from retained snapshots. |
ui.channel-actions |
Register bounded, host-attributed actions in joined-channel menus. |
ui.channel-badges |
Publish bounded, host-attributed badges beside joined channels. |
channel.members |
Receive the retained authoritative member roster for confirmed joined channels through channelSnapshots. |
channel.metadata |
Receive retained channel topic and boolean channel modes through channelSnapshots. Sensitive argument-bearing values such as channel keys are never exposed. |
statusbar |
Publish host-attributed native status-bar badges. |
uploads.provide |
Register manifest-declared upload handlers from a headless Root. |
uploads.use |
From a user-invoked composer utility, hand one bounded in-memory file to Mango’s configured native uploader. |
microphone.record |
Record a bounded voice clip through Mango’s native microphone bridge, only from a visible composer utility. Apple microphone permission is also required. See composer audio. |
messages.filter.inbound |
Inspect and allow, deny, or transform messages before Mango displays them. |
messages.filter.outbound |
Inspect and allow, deny, or transform messages before Mango sends them. |
messages.protect |
From a server-scoped Root or tab, return terminal protected message transforms with bounded ordered frames. Security protocols may also publish host-owned fail-closed policy through grove.protection.set(...): queries are protected in both directions, while channel policies fail closed on outbound sends and continue accepting mixed inbound plaintext. Requires the matching inbound/outbound filter grants. |
network.send |
From a server-scoped instance, use grove.send, channel-message grove.reply, or grove.typing with an explicit { channel }. The target must be one confirmed joined channel and cannot be combined with { to }. It does not grant server-wide NOTICE. This is modeled output, not raw IRC access. |
Request only the permissions needed by the current release. Additional capabilities change what the user is consenting to and should correspond to a visible feature.
Reserved capabilities
These names are recognized by API 1 manifests but do not currently expose a corresponding bridge getter, event, or command:
| Capability | Intended area |
|---|---|
identity |
The user’s identity on the network. |
notifications |
Native user notifications. |
server.events |
Whole-session registration, numeric, or raw-event delivery. |
Do not request a reserved capability in expectation that an undocumented JavaScript API exists. Unknown capability strings fail manifest decoding; reserved strings decode but grant no API beyond what is documented.
Host permissions are separate
hostPermissions controls browser network egress and is shown separately during consent. It does not grant IRC data or native bridge operations. Conversely, channel.read does not let an extension exfiltrate messages to an undeclared host.
An extension that processes data entirely locally should use an empty network allow-list:
"capabilities": ["messages.filter.inbound", "storage"],
"hostPermissions": []
An extension that fetches one API should declare only that origin:
"capabilities": ["commands.register"],
"hostPermissions": ["https://api.example.com"]
When a service intentionally assigns one direct subdomain per user, a complete leftmost-label wildcard is available:
"hostPermissions": ["https://*.example.com"]
It matches alice.example.com, but not the apex, a deeper subdomain, another
scheme, or an undeclared port. Prefer an exact origin whenever possible.
Consent and replacement
Mango attributes grants to the immutable package identifier. Installing replacement bytes or an update stops the old instance and clears its prior grant so new code cannot silently inherit consent. The user reviews capabilities again before starting the replacement.
Removing an extension removes its installed bytes and associated storage. Revoking or losing a grant stops new bridge access immediately; an extension must not assume a registration remains active after its authority changes.