BRC-325 Wallet

User-Initiated Browser Permission Requests for Wallet Discovery

This document specifies what an application MUST do in the seconds before a browser asks the user whether a site may reach the wallet running on their own computer. BRC-185 requires applications to discover wallets by probing loopback addresses. Since Chrome 142 that probe is gated by a permission, and the first probe makes the browser interrupt the user wit

Crumbs

How it connects

Relationships

Found in the source

Implementation links

These links are extracted from the upstream implementation section. Inclusion is not an OpenStandards endorsement.

Authoritative content mirror

Full upstream text

View source ↗
Rendered from wallet/0325.md at the indexed upstream commit

Abstract

This document specifies what an application MUST do in the seconds before a browser asks the user whether a site may reach the wallet running on their own computer.

BRC-185 requires applications to discover wallets by probing loopback addresses. Since Chrome 142 that probe is gated by a permission, and the first probe makes the browser interrupt the user with a dialog the application did not write, cannot style, cannot reword, and gets exactly one of per origin. A user who declines it has not declined a wallet. They have declined a sentence about apps and services that never mentioned wallets, arriving at a moment they did not choose, from a site that said nothing first.

Five things are specified. The read: determine the permission state with navigator.permissions.query before probing anything, because that query distinguishes four situations demanding four different behaviours and costs nothing. The order: exhaust the adapters that cannot raise the prompt first, because a wallet found through an extension makes the question unnecessary. The primer: in the prompt state only, show the application's own explanation first, on a deliberate user action, naming the wallet, naming what the browser is about to ask, and offering a refusal that is a real control rather than a dismissal. The eliciting request: the probe that raises the dialog is one request with no deadline, because BRC-185 section 4.1 sets a 1000 ms deadline per discovery request and a person reading a dialog takes longer. The recovery: in the denied state, do not probe, report the condition in BRC-185's existing blocked coverage vocabulary rather than as an absent wallet, and offer both a repair path and the substrates that need no permission at all.

The design rests on one asymmetry. Declining a primer costs nothing and declining a browser dialog costs the origin permanently. A primer dismissed can be offered again next week in a better moment. A prompt denied removes loopback discovery from that origin until the user goes into site settings and reverses it, which almost nobody does. The primer is therefore not decoration in front of the dialog. It is the only place where a refusal is recoverable, and a standard that leaves it optional spends the irreversible budget first.

Motivation

BRC-185 section 4.1 tells an application to look for wallets at http://localhost:3301, http://localhost:3321 and https://localhost:2121, and to walk offsets 0 to 63 from each base with up to 16 simultaneous requests. That is between one and 192 requests to loopback addresses, issued before the user has done anything except arrive.

Chrome 142 shipped Local Network Access, which gates exactly those requests behind a permission. Chrome later split that permission into two, local-network for other machines and loopback-network for this one, and wallet discovery is entirely the second. The first request of a discovery round now suspends and the browser shows the user a dialog. The Chromium strings are unambiguous about what it says:

IDS_LOOPBACK_NETWORK_PERMISSION_FRAGMENT
  "Access other apps and services on this device."

IDS_LOOPBACK_NETWORK_INFOBAR_TEXT
  "<URL> wants to access other apps and services on this device."

IDS_PERMISSION_DENY
  "Block"

What the user is actually looking at

The infobar string is the one-line form. On desktop the user gets the permission bubble, composed from the fragment, and it is worth reproducing exactly, because five properties of it determine everything this document requires. The following is a real prompt raised by a real deployment, with the host replaced by a reserved example name:

+--------------------------------------------------------------+
|                                                              |
|   example.com wants to                                   [x] |
|                                                              |
|   [#]   Access other apps and services on this               |
|         device                                               |
|                                                              |
|                                 [  Block  ]   [  Allow  ]    |
|                                                              |
+--------------------------------------------------------------+

The word wallet does not appear, and cannot be made to appear. Neither does Bitcoin, nor keys, nor the name of the software actually listening. The glyph is a generic display icon. Nothing connects the surface to the thing the user asked for ten seconds earlier, which is why section 5.3 requires the application to make that connection in advance.

The only identification is the serialized host. No application name, no favicon, no description. Where that host is a platform deployment or preview name, which is common, the user has never seen it before and does not associate it with the product they believe they are using. That is why section 5.2 requires the primer to display the same string first.

Block and Allow are peers, equal in size and contrast. The browser does not weight the choice, and an application that weights its own is being less respectful than the security dialog it stands in front of. Section 5.4 is written to that standard.

The refusal is called Block and it means it. IDS_PERMISSION_DENY is a persistent denial for the origin, and the control says so. A user who presses it has not deferred anything.

There is a third outcome. The close control is neither. Dismissing leaves the state at prompt and fails the request, and browsers suppress the prompt after repeated dismissals, so an application that retries walks the user toward a state where the dialog stops appearing at all. Section 6.2 handles it separately; branching only on grant and denial is incomplete.

The dialog follows the browser and operating system theme. It is dark here because that user's browser is. A page cannot know this and cannot match it, which is one more reason section 5.7 prohibits imitating browser chrome rather than discouraging it.

What we propose the user sees first

This document is about a surface, so here is the surface. The dialog above arrives with no warning. The proposal is that it arrives second, and this arrives first, on a control the user operated:

+--------------------------------------------------------------+
|                                                              |
|   Your browser's question is broader than this site needs    |
|                                                              |
|   It asks whether this site may reach apps and services on   |
|   this device. That covers everything running here.          |
|                                                              |
|   This site looks for one thing, your wallet, and your keys  |
|   stay inside it. The question appears near the top of your  |
|   browser window.                                            |
|                                                              |
|   [  Connect my wallet  ]   [  Other ways to connect  ]      |
|                                                              |
+--------------------------------------------------------------+

Forty-two words, two controls of equal weight, no technical vocabulary, and the only claim it makes about the grant is one that section 12 binds the implementation to keep. While the browser's question is open the user keeps a non-blocking line telling them where to look, and if they refuse, a panel offers the routes that need no permission at all. Those three surfaces, before, during and after, are what this document specifies. Appendix A carries the rest of the copy and the copy that fails.

The two figures above are the same moment, sixty seconds apart in a user's experience and one ordering decision apart in an implementation. This is that ordering, looping:

Wireframe animation in two phases. In the first, labelled Today, a browser permission bubble reading "example.com wants to access other apps and services on this device" appears beneath the address bar with no warning, offering Block and Allow. In the second, labelled This Document, the user operates a Buy control low in the page, a dashed line traces the distance from that control up to the top of the window, a primer appears there reading "Your browser's question is broader than this site needs" with Connect wallet and Other ways, and only then does the browser's own question appear, alongside a non-blocking note reading "Look near the top of your browser window. No time limit."

The dashed arc in the second phase is not decoration. The control the user operated is at the bottom of the page and the browser's question is drawn at the top, in chrome the page does not own, and that distance is the one thing the mobile patterns this document adapts never had to solve. Section 9 is about it.

What the existing standards already say, and who said it

Ty Everett and Deggen anticipated this in BRC-185. Three of their statements set the boundary this document works inside. Section 1, on what a controller may treat as a runtime fact:

"Runtime support" means facts such as DOM availability, permitted loopback access, native bridge presence, or an interactive terminal.

Section 3, on discovery:

Discovery MUST be noninteractive at the wallet-permission layer. [...] Browser or OS permission to access a substrate is a separate state that the controller MUST explain and respect.

Section 4.1, on the loopback scan itself:

Discovery SHOULD begin only on an application wallet-use or connect action. A controller MUST NOT repeatedly rescan in the background, work around browser local-network permissions, disable certificate validation, or follow discovery redirects. A policy-blocked scan is blocked, not evidence of absence. A browser UI can ask for local-network access through normal browser controls or offer another substrate.

That last paragraph contains almost all of the correct policy. It forbids circumvention, names the reporting state, ties discovery to a user action, and says a browser may ask. What it leaves open is the only variable that determines the outcome: when. An explanation offered after the dialog has been denied is a post mortem, and MUST explain and respect does not say otherwise because it was not written to.

Ty Everett's BRC-219 supplies the principle from the other side:

If a request is a wallet status, readiness, network, version, or authentication probe, the wallet must not use that request to trigger a permission prompt.

A probe is not a consent moment. BRC-219 enforces that against the wallet. Nothing enforced it against the browser, and the browser is now the party being provoked by the same probe.

Two conflicts that the browser permission creates in the existing standards

Reading BRC-185 and BRC-219 against the shipped Local Network Access behaviour produces two defects that are not matters of taste.

A blocked probe is indistinguishable from an absent wallet, using the probe alone. The Local Network Access specification states that a denied permission makes the fetch fail, and the failure is an ordinary network error. A fetch to http://localhost:3321 that the browser refused on permission grounds and a fetch to a port where nothing is listening produce the same rejection in the same shape. BRC-185 section 4.1 requires that a policy-blocked scan be reported as blocked and section 5.1 requires that it be distinguished from wallet absence, and from the probe result that requirement is unmeetable. navigator.permissions.query is the only thing that makes it meetable, which is why section 3.1 of this document makes the query mandatory rather than advisory.

A pending browser prompt breaks BRC-219's central assumption. BRC-219 states the contract plainly:

The intended binary is explicit: if a connected wallet request appears to "hang" at the application boundary, the application developer should be able to assume that the wallet is asking the user. If that assumption is false, the wallet is non-compliant.

The Local Network Access check runs after the connection is obtained and suspends the fetch while the dialog is displayed. So a loopback probe can now hang for a third reason that BRC-219 does not enumerate: the browser is asking the user whether the request may be made at all, and nothing has reached the wallet. An application that follows BRC-219's binary will attribute that hang to a wallet that has not been contacted, and a wallet that is behaving correctly will be recorded as non-compliant. Section 3.1 resolves this too: an application that read the state before probing knows which of the two is happening, and section 10.3 requires the two to be presented differently.

There is a third, narrower collision, and it is the one most likely to break a correct implementation in practice. BRC-185 section 4.1 sets a 1000 ms deadline per discovery request. The browser holds the request open until the user answers the dialog. A user who reads four lines of unfamiliar text and clicks Allow takes several seconds, by which time a conforming controller has already abandoned the request. Priming the user perfectly and then timing out their grant is a worse outcome than not priming at all. Section 6 of this document fixes it.

The evidence, and the one finding that shapes a rule

Five studies bear on this, and the table is the whole of what they contribute.

Source Scale Finding
Bilogrevic et al., 2021 300M+ Chrome users, 800M+ prompts, then an A/B across 40M users and 70k sites Redesigning the prompt UI moved grant rates by under 5 percent. Baseline grant rates are 10 percent on desktop and 21 percent on Android
Felt et al., 2012 308 surveyed, 25 observed 17 percent paid attention to permissions. 3 percent answered all three comprehension questions. 42 percent of lab participants did not know permissions existed
Akhawe and Felt, 2013 25M+ warning impressions Chrome's SSL warning bypassed 70.2 percent of the time. Text arriving without context is treated as an obstacle, not a question
Wijesekera et al., 2015 36 instrumented phones At least 80 percent would have blocked a request they had granted. A 2017 follow-up across 131 participants put the figure at 60 percent
Tan et al., 2014 772 participants, iOS dialogs Approval rose from 65.8 to 73.6 percent when a purpose string was present (Z = -3.569, p < 0.0005)

The first row is the one that answers the obvious objection, which is that prompt wording is the browser's problem. Chrome ran that experiment at a scale nobody else can and published the result: redesigning the box does almost nothing to the decision, because the decision was made before the box appeared. On an unprimed page it was made out of no context at all.

The last row is the one that shapes a rule here, and the usual reading of it is wrong. Tan et al. also randomised 14 purpose strings for one fictitious application, from a contentless control to careful explanations of what would be stored and where. Approval ran from 38.8 to 70.2 percent, which is the source of the widely quoted claim that better wording improves grants by 81 percent. But Fisher's exact test found no significant difference between the control string and the others (p < 0.495). Participants approved more when an explanation was present regardless of what it said. Satisfaction moved with quality; behaviour moved with presence.

So the presence of an explanation is normative in this document and the quality of its wording is not, because mandating an effect the source paper failed to find would be unfalsifiable and easy to check. Quality still earns its rules, for the reason Tan et al. did measure: it is what leaves a user satisfied with a decision rather than merely willing to make it, and a user who feels tricked revokes the grant later.

Mobile solved a weaker version of this, and the web has a better signal than mobile

The mobile platforms converged on two mechanisms and the loopback prompt has neither. iOS puts a slot inside the dialog, a purpose string rendered in the system sheet, which Tan et al. found only 19 percent of 4,400 applications used. Android puts a signal outside it: no purpose string, so Google's guidance is an educational interface first, with shouldShowRequestPermissionRationale indicating when one is warranted.

The loopback prompt has no slot and will not get one, because letting an arbitrary site write text into browser security chrome is a phishing primitive rather than a feature. So the web is in Android's position, and the explanation must be a surface of the site's own.

What the web has that Android does not is a better signal. shouldShowRequestPermissionRationale is a boolean largely meaning "they denied you once". navigator.permissions.query({name: "loopback-network"}) returns granted, prompt or denied before a single byte goes to loopback. That is a three-state read of the exact thing about to happen, free, and available inside a click handler. Mobile best practice is a workaround for a missing signal; here the signal exists, so this document is stricter than the pattern it adapts. Not "explain when you suspect you should" but "read the state, and let the state choose among four behaviours".

The timing rule is not new, and is already a published accessibility criterion

Everything above argues the ordering from conversion evidence and from the structure of an irreversible grant. There is a shorter argument, normative in another standards body since 2008. WCAG success criterion 3.2.5, Change on Request, reads in full:

Changes of context are initiated only by user request or a mechanism is available to turn off such changes.

A change of context is defined there as a major change that, made without the user's awareness, disorients a user who cannot see the whole page at once, and the enumerated kinds include a change of user agent, of viewport, and of focus. A permission bubble drawn in browser chrome, raised by a probe the page issued on its own initiative, is all three and none of them was requested. Section 5.1 point 1 is the criterion's first limb and section 5.1 point 6 is its second, the mechanism to turn such changes off, which here means letting a user disable wallet discovery outright.

The criterion is Level AAA and honesty requires saying so: most products target AA and are not obliged to meet it. Two things make it the right bar anyway. This change of context is irreversible, unlike the new windows and auto-submitting forms the criterion was written for, where a disoriented user can close the tab. And it is satisfiable here for one API call and an ordering rule, which is rare for AAA.

Its account of who is harmed reaches three requirements the conversion literature does not. Blind and low-vision users may not notice a context change occurred at all, and the bubble is outside the document where the page cannot announce it, which is why section 5.7 point 3 requires the primer to speak before it hands off. Readers with motor impairments find unexpected changes hard to recover from, and recovery here is a settings surface the page cannot link to, which is section 8.2's problem. Readers with reading or intellectual disabilities benefit from advance cues, which the understanding text notes are not required by the criterion but do reduce confusion, and which section 5.2 point 1 makes mandatory.

Prior Art

The Motivation quotes the three BRC-185 statements and the BRC-219 statement this document builds on. This section records what each source supplies and which rule it reaches.

Where this sits

Several documents describe one arc, from a user who has no wallet to a user whose request has just failed. None of them states the arc, so it is stated here, and this document's own place in it is marked. Each is independently implementable and none depends on another having been read.

Moment Document What it owns
Arriving with no wallet BRC-110 Zero friction, deferred onboarding, and a benefit explained in context at the point of use
Being offered one BRC-137 Device detection, catalog-resolved install paths, fallback login, and the connect decision flow
Choosing among them BRC-300, pull request #224 The connect control and its vocabulary, chooser neutrality, and the sponsorship behind placement
The browser's permission This document What precedes the loopback dialog, and the honest reporting of a refusal
Reaching the wallet BRC-185 Substrate discovery and selection, coverage states, and connection states
When something fails BRC-326, pull request #332 What a failure says, and what an application may do with it

Documents named without a link are submitted and not yet merged. They are named rather than linked so that this document resolves correctly whatever order the set lands in.

The arc continues past a failure, into what an application may claim about a request that did succeed and into reviewing and withdrawing the grants a user has already given. This document specifies neither and forecloses neither. Its own subject ends where the browser's permission is resolved and BRC-185 discovery can begin.

The seam this document occupies did not exist when the onboarding documents were written. It opened when Chrome 142 placed a permission between the connect action and the substrate.

What this document changes in BRC-137

BRC-137 section 4 specifies the connect decision flow as a two-way branch: attempt a substrate connection, and on failure detect the operating system and show install cards. Section 5 point 1 then requires that view to state plainly that no wallet was detected.

Both predate the permission and neither survives it unchanged.

  1. The attempt is now the probe that raises the browser's dialog, so BRC-137's flow begins by spending an irreversible grant with no explanation. Sections 3 to 6 of this document go between the tap and the attempt.
  2. "No substrate reachable" is now four conditions wearing one label: granted and nothing listening, blocked by policy, denied by the user, and dismissed without an answer. Section 10.1 separates them.
  3. Section 5 point 1's requirement becomes a requirement to say something false whenever the cause was the permission rather than an absent wallet. A user whose wallet is running and whose browser refused is told their wallet was not detected. Section 7.3 of this document forbids that sentence, as does BRC-185 section 4.1's rule that a policy-blocked scan is blocked and not evidence of absence.

Where the cause is a permission condition under section 10.1, this document supersedes BRC-137 section 5 point 1 and inserts sections 3 through 6 into its section 4 flow. Everything else in BRC-137 stands, including the whole of the no-wallet view once absence is actually established.

Source What it supplies Where it lands
BRC-185, Ty Everett and Deggen The discovery round that triggers the prompt, and the whole reporting vocabulary reused here: coverage states complete, partial, blocked, unsupported; the ConnectionError shape with code, delivery and cause, including DISCOVERY_BLOCKED and CONFIGURATION_ERROR; selection modes automatic, ask, explicit; the section 5.1 connection-state table Sections 4, 10 and 13. Nothing here adds a wire field, method, endpoint or error code
BRC-219, Ty Everett A probe must not trigger a permission prompt. A prompt must identify the requesting origin and the capability. There is no elapsed-time limit on a live permission decision Sections 3.1, 5.2 and 6.1, each applied one layer outward to the browser. Section 5.6 keeps the two dialogs apart
BRC-73, Ty Everett That consecutive one-off permission requests are answered worse than one coherent request: "permission prompts can become fragmented and repetitive" Section 5.1 point 4. The browser's dialog cannot be grouped with anything, so it is isolated instead
BRC-184, Ty Everett The failure mode of an opaque request, a prompt reading only [2, "auth message signature"], and the rule against delaying a prompt for a slow lookup Section 5.5
BRC-151, BitcoinSvGuide The threat Local Network Access exists to mitigate, naming DNS rebinding and malicious localhost requests, and the copy principle: "Permission prompts should describe consequences rather than internal terminology" Section 5.5 point 1, section 12, Security Considerations
BRC-137 That a wallet-less visitor must meet install paths rather than an error Sections 4.3 and 8.2. This document covers the case BRC-137 does not reach, where a wallet is running and the browser is in the way
BRC-110 That a benefit must be explained in context, at the point of use, in at most two lines Section 5.2's connect disclosure
BRC-6 and BRC-185's extension, injected-global, React Native and mobile adapters The substrates that never raise this prompt Section 4.1, which requires them exhausted first
WCAG 3.2.5, Change on Request That changes of context be user-initiated, or that a mechanism exist to turn them off, plus the account of who is harmed when they are not Section 5.1 points 1 and 6, section 5.7 point 3, section 8.2
Nielsen Norman Group, Rosala 2019 Copy, timing and decision reversal, and the dark-pattern catalogue Sections 5.1, 5.4, 5.5 and 9.2
Nielsen, Response Times: The 3 Important Limits, 1993 The 0.1, 1 and 10 second limits, from Miller 1968 and Card et al. 1991, and what each one obliges Section 6.1, which explains where BRC-185's 1000 ms deadline comes from and why it does not reach a human decision, and section 9.5, which is written to the ten-second case
Android educational interfaces, Apple purpose strings The two mobile mechanisms the primer adapts, neither of which the loopback prompt provides Section 5, for the reasons in the Motivation

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, and MAY in this document are to be interpreted as described in RFC 2119.

1. Terminology

Terms defined in BRC-185 section 1, in particular provider, substrate, adapter, candidate, controller, chooser, wrapper, application origin and coverage, are used as defined there.

  • Loopback request: a request from the document's origin to a loopback address, meaning localhost, an address in 127.0.0.0/8, or [::1], matching BRC-185 section 1's definition of loopback for this profile. The discovery addresses of BRC-185 section 4.1 are loopback addresses.
  • Loopback access prompt: the browser's own permission dialog, shown on the first loopback request from an origin whose permission state is prompt. Its text, styling, button labels, button order and settings label belong to the browser. In current desktop Chrome it is the permission bubble reproduced in the Motivation, composed from IDS_LOOPBACK_NETWORK_PERMISSION_FRAGMENT with the controls Allow and IDS_PERMISSION_DENY, plus a close control.
  • Dismissal: closure of the loopback access prompt without choosing either control, through its close affordance, the Escape key, or loss of the anchoring surface. A dismissal is neither a grant nor a denial and leaves the permission state at prompt.
  • Permission state: the value of PermissionStatus.state for the loopback-network descriptor, one of granted, prompt or denied, or one of the two distinct conditions unsupported and exempt defined in sections 3.3 and 3.4.
  • Primer: a surface belonging to the application, shown before the loopback access prompt, which explains what the browser is about to ask and obtains the user's decision to proceed. The term is taken from the mobile literature, where it is also called a pre-permission prompt or an educational interface.
  • Probe: a single loopback request issued as part of a BRC-185 section 4.1 discovery round.
  • Eliciting request: the single loopback request issued for the purpose of raising the loopback access prompt, defined in section 6. It is not a probe and is not part of a discovery round.
  • Connect surface: the control through which a user asks the application to connect a wallet, together with the surface carrying it. This document does not define that control. BRC-137 section 1 governs its place in a single login surface, the Sponsored Onboarding and Wallet Choice proposal governs its label and what it must say once, and BRC-185 sections 5 and 7 govern the chooser and any application-supplied replacement. Where this document says connect surface it means whichever of those the application has built, and under section 5.1 point 1 a value control that needs a wallet counts as one.
  • Recovery surface: a surface belonging to the application, shown when the permission state is denied, which explains the state and offers both repair and alternatives.
  • Affirmative response: a user action on the primer that unambiguously selects proceeding. Closing, dismissing, pressing Escape, clicking away, navigating, or allowing a timer to expire are not affirmative responses.

2. Scope

2.1 This document applies to any document that will issue a loopback request in order to discover or connect a wallet, whether through BRC-185 section 4.1 discovery, a legacy BRC-5 substrate address, a getVersion readiness probe against a legacy default endpoint, or an application-configured loopback endpoint.

2.2 It does not apply to the local-network permission, to the extension, injected-global, BRC-6 cross-document-messaging, React Native or encrypted mobile substrates, or to any wallet-layer permission governed by BRC-116, BRC-181 or BRC-219.

2.3 It adds no wire format, no payload, no endpoint, no protocol identifier, no BRC-185 error code and no cryptographic value. It constrains the order and content of user-facing surfaces, one call to a browser API, and the reporting of one condition into vocabulary BRC-185 already defines. Conformance is therefore defined by the state table in section 9 rather than by test vectors.

3. Reading the permission state before probing

3.1 The query is mandatory and comes first

  1. Before issuing its first probe or eliciting request, a conforming controller MUST determine the permission state by calling navigator.permissions.query with the descriptor name loopback-network.
  2. If that call rejects, the controller MUST retry once with the legacy combined descriptor name local-network-access, which browsers that predate the split expose as an alias of local-network and loopback-network.
  3. The controller MUST NOT issue a loopback request in order to discover the permission state. A probe issued to find out whether probes are allowed will itself raise the prompt, at a moment the application chose and the user did not, spending the single irreversible grant to learn something the Permissions API answers for free. This is BRC-219's rule that a readiness probe must not trigger a permission prompt, applied to the browser rather than the wallet.
  4. The controller MUST NOT infer the state from the result of a loopback request. A denied permission makes the fetch fail with an ordinary network error, which is the same result as an unoccupied port, so the inference cannot be made and BRC-185 section 4.1's requirement to report a blocked scan as blocked cannot be met without this query.
  5. The controller MUST NOT substitute a stored flag, a heuristic, a user-agent test or a prior session's outcome for the live query.
  6. A granted state does not imply that a wallet exists, and a denied state does not imply that one does not.

3.2 Four states, four behaviours

State Primer Loopback requests Surface shown
unsupported MUST NOT show MAY probe immediately ordinary discovery
exempt MUST NOT show MAY probe immediately ordinary discovery
granted MUST NOT show MUST probe without interruption ordinary discovery
prompt MUST show, under section 5 eliciting request only after an affirmative response, under section 6 primer, then ordinary discovery
denied MUST NOT show MUST NOT issue any recovery surface, under section 8

3.3 Unsupported browsers

  1. Where both descriptor names in section 3.1 reject with a TypeError, the browser does not implement this permission, the loopback access prompt will not appear, and the state is unsupported.
  2. In the unsupported state a controller MUST NOT show a primer. A primer in front of a dialog that will never appear is a self-inflicted interruption, and it teaches the user that this application interrupts them for nothing. This mirrors BRC-185 section 4.3's treatment of an absent parent window or native bridge, which reports unsupported without sending a message rather than waiting on a nonexistent channel.
  3. A controller in the unsupported state MUST still handle a failed probe, because a browser may block loopback requests by a mechanism other than this permission. It MUST surface such a failure as blocked coverage under section 10.1, not as an absent wallet.

3.4 Documents served from a loopback origin

  1. A document whose own origin is a loopback origin is not making a local network request when it reaches another loopback address, and no prompt will appear. The state is exempt and a controller MUST NOT show a primer.
  2. Implementers are warned that this is the condition under which wallet integrations are normally developed. A local development server at http://localhost:3000 will never see the dialog this document is about, and an implementation tested only there is untested. Conformance testing MUST exercise the prompt and denied states from a non-loopback origin.
  3. BRC-185 section 8.2 permits a canonical HTTP loopback origin as a pairing origin for explicit local development. That allowance is unaffected and does not extend to production.

3.5 Watching for change

  1. A controller that holds a PermissionStatus SHOULD subscribe to its change event and re-evaluate section 3.2 when the state changes.
  2. A controller showing a recovery surface MUST re-evaluate the state when the document becomes visible again, so that a user who repairs the permission in browser settings and returns is not left looking at an instruction they have already followed. Requiring a reload after a successful repair is a conformance failure.
  3. On a transition from denied or prompt to granted, the controller MUST run a fresh discovery round and update the candidate snapshot required by BRC-185 section 2.

4. Ordering against the other substrates

4.1 Adapters that cannot raise the prompt go first

  1. A controller MUST attempt every configured adapter that cannot raise the loopback access prompt before issuing an eliciting request. At minimum these are the extension announcement channel and legacy window.CWI of BRC-185 section 4.2, the BRC-6 and XDM adapter of section 4.3, React Native, an application-supplied embedded object, and any established mobile session.
  2. Where those adapters yield a candidate that satisfies the controller's selection policy under BRC-185 section 5, the controller MUST NOT show a primer and MUST NOT issue an eliciting request. The permission is a single irreversible resource and MUST NOT be spent to complete an inventory that has already answered the user's question.
  3. The loopback adapter's coverage MUST then be reported as blocked under section 10.1 with the cause defined there, so that BRC-185 section 4.1's requirement never to claim that all ports or all installed wallets were searched is satisfied honestly.
  4. Where the user explicitly opens the chooser, requests a refresh, or asks to change wallet, the controller MAY offer the primer so that the loopback adapter can be included. That is a user-initiated action on the connect surface and satisfies section 5.1.

4.2 Automatic mode and the missing user activation

BRC-185 section 2 requires an upgraded WalletClient in automatic mode to delegate to the connection provider on its first connection attempt. That attempt can occur with no user gesture at all, which is precisely when a primer cannot be shown and the browser dialog would therefore be raised unprimed.

  1. In the prompt state, where no transient user activation is available, a controller MUST NOT issue an eliciting request and MUST NOT probe loopback.
  2. It MUST complete the adapters of section 4.1, report the loopback adapter's coverage as blocked with cause permission-required under section 10.1, and resolve under BRC-185 section 5 on the candidates it has.
  3. Where section 5 of that document then requires a chooser, or where no candidate was found, the resulting surface is a connect surface and the user's action on it supplies the activation the primer needs.
  4. Where no user interface adapter exists, BRC-185 section 5's existing SELECTION_REQUIRED applies unchanged, carrying the coverage state. This document introduces no new error code for the condition.

4.3 Readers who may not have a wallet at all

The worst sequence this document can produce is a user with no wallet who is shown a browser security dialog, allows it, and is then told to go and install something. They have paid a trust cost for nothing, and the origin's single irreversible grant has been spent to establish an absence.

  1. Where the controller has positive evidence that the user is unlikely to have a loopback wallet, it SHOULD present the install and pairing routes before or alongside the primer, rather than after a discovery round that finds nothing. Evidence includes no prior connection remembered for this origin, no extension or injected provider announced under BRC-185 section 4.2, and no established mobile session.
  2. The controller MUST NOT treat that evidence as proof. It cannot know what is listening without looking, and section 7.3's prohibition on reporting absence still applies.
  3. This document does not name, rank, recommend or describe any wallet, and a conforming implementation of it does not acquire a wallet recommendation. BRC-137 owns operating system detection and catalog-resolved install paths. BRC-185 section 5 owns neutral presentation and forbids ordering candidates by vendor or commercial relationship. Wallet choice and its commercial arrangements are a separate subject with a separate document. The division is that this document governs when the permission may be spent on a user who may not have a wallet, and those documents govern what that user is shown instead.

4.4 One component owns the interaction

BRC-185 section 7 requires that one component own a given connection or onboarding interaction, and forbids a controller and a wrapper from each opening a competing missing-wallet modal. The same rule applies here: a controller and a wrapper MUST NOT each show a primer or a recovery surface for the same resolution, and integration documentation MUST state which component owns them.

5. The primer

This section applies only in the prompt state.

5.1 Timing

  1. A primer MUST be shown only in response to a deliberate user action that needs a wallet. Two shapes qualify: operating a connect control, whose evident purpose is connecting a wallet, or operating a value control whose completion needs one, such as buying, posting, unlocking or signing. This is the stricter form of BRC-185 section 4.1's "Discovery SHOULD begin only on an application wallet-use or connect action." It is also WCAG success criterion 3.2.5 applied to this change of context: the browser's dialog is a change of user agent, viewport and focus, and it must be initiated by the user's request rather than by the page's initiative.
  2. Where both shapes are available, an application SHOULD use the value control. A user who has just pressed Buy is holding the reason for the question, and a user who has just pressed Connect wallet is holding only a mechanism. This is Nielsen Norman Group's distinction between a context-related request, which arrives attached to something the user wanted, and a system-initiated one, which arrives attached to nothing, and the finding is that the first is the easier of the two to answer. A standard that recognised only a dedicated connect step would push implementers toward the shape that performs worse, and most products have no dedicated connect step in the path anyway. Section 9.3 gives the matching presentation.
  3. A primer MUST NOT be shown on page load, on first scroll, on a timer, on exit intent, on hover, or as part of a sequence of unrelated onboarding dialogs.
  4. A primer MUST NOT be shown alongside, immediately before, or immediately after any other permission request, consent dialog or cookie banner. BRC-73 records that fragmented and repetitive permission requests are answered worse than one coherent request; the browser's dialog cannot be grouped with anything, so it must be isolated instead.
  5. An application that can deliver any of its value without a wallet SHOULD deliver some of it before offering the connect surface at all.
  6. An application SHOULD offer the user a way to disable wallet discovery for the application entirely, reachable from its ordinary settings. This satisfies the second limb of WCAG 3.2.5, a mechanism to turn such changes off, and it gives a user who wants this application without this capability something better than refusing a security dialog they did not understand. Disabling discovery MUST NOT be presented as disabling the application.

5.2 Required content

A primer MUST communicate five things, and SHOULD communicate a sixth. Beyond these and the two disclosures below, it SHOULD communicate nothing at all.

  1. That the browser is about to ask. The user is about to see a dialog that is not the application's. Saying so converts an ambush into an expected step. It is the one element with no equivalent in the mobile patterns this section adapts, because on mobile the system sheet is familiar and this one is not, and it is mandatory here rather than advisory because the change it precedes cannot be undone by the person it disorients.
  2. What is actually being reached. A wallet running on this computer. The primer MUST name the wallet where the controller holds a verified descriptor name from BRC-185 section 3, rendered as inert text as that section requires, and MUST otherwise say that it is a wallet.
  3. Why it has to be reached locally. Keys stay in the wallet and the site never receives them. This is the benefit that justifies the access, and the one the browser's wording obscures.
  4. What the user gets. The specific thing they were trying to do, in the words they used to try to do it.
  5. That the browser's question is broader than what this site will do. Access other apps and services on this device describes a capability over the whole machine. What the application wants is one wallet on one of a handful of known addresses, and section 12 binds it to that. A user not told this reads the dialog as a website asking to get into their computer, which is a fair reading of the sentence in front of them and a wrong description of what is being asked for. The primer is the only place the mismatch can be named, because the application has no voice once the dialog appears.
  6. Where the question will appear. The prompt is drawn at an anchor the page does not choose, and on desktop that anchor is nowhere near the control the user just operated. A user told to expect a question and not told where to find it has been prepared for the wrong half of the problem. This is a SHOULD only because the position cannot always be determined: section 9.4 point 3 forbids claiming one more precise than the application can establish, and silence beats a false statement.

BRC-219 requires a wallet prompt to identify the requesting origin and the capability. A primer SHOULD likewise show its own serialized origin, as BRC-185 section 1 requires when asking for approval, warning that a friendly name does not replace it. Where the host is not the name the user associates with the application, which includes platform subdomains and preview deployments, the primer MUST display it. The browser is about to identify the requester by that string and nothing else, and a user meeting an unfamiliar host for the first time inside a security dialog has been handed a reason to refuse that one line would have removed.

A primer MUST NOT state or imply that the dialog is a formality, that allowing is required to use the site when it is not, that the application has vetted or vouched for the grant, or that the application can undo it. Only the user can, in browser settings.

Why a wallet rather than an email address, and where that argument belongs. A user meeting this dialog for the first time is often also meeting the idea of connecting a wallet for the first time, and the question underneath their hesitation is usually not about permissions at all. It is why they are doing this instead of the sign-in they already know.

That argument is owned elsewhere and MUST NOT be rebuilt here. BRC-110 section 6 requires applications to communicate the benefit in context, at the point of use, in at most two lines, on the finding that users retain such explanations only at the moment of relevance. The Sponsored Onboarding and Wallet Choice proposal requires the connect surface to carry a plain statement that the account is the user's and the application does not hold it, visible without navigation, and forbids self-custody, non-custodial, sovereign and decentralized as substitutes for saying what they mean.

Two consequences for this document:

  1. Where a connect surface carried that statement, the primer MUST NOT repeat it. The user has read it, and a primer that re-argues the case has become a pitch attached to a security question.
  2. Where the ask was bound to a value control under section 5.1 point 2, there may have been no connect surface and no statement. The primer MUST then carry it, within the two-line bound BRC-110 section 6 sets, in the same plain terms and under the same prohibited vocabulary. This case exists because section 5.1 point 2 prefers the value control, and preferring it must not quietly remove the one explanation a newcomer was owed.

A primer MUST NOT state or imply that the grant extends beyond this origin, or that the user will not meet the same question again. It will not and they will. The permission is granted to one origin, so a user who uses three applications in this ecosystem answers this question three times. An application that says "you will only be asked once" has told the truth about itself and a falsehood about the user's week, and the second application to raise the dialog inherits the disbelief.

5.3 Translating the browser's words

  1. A primer MUST relate the browser's own phrasing to the wallet, so that the user recognises the dialog rather than meeting it cold.
  2. An application MUST NOT hard-code the browser's exact sentence as though it were stable. Chrome has already renamed this permission once, from a local-network phrasing to the loopback phrasing, and renamed the settings entry to Apps on device. An application SHOULD paraphrase the category the browser will name, and MUST ensure the paraphrase remains true if the browser rewords the dialog.
  3. The paraphrase MUST NOT contradict the dialog. Telling the user they will be asked about a wallet, when they will be asked about apps and services on this device, produces a mismatch that reads as deception at exactly the moment trust is being established.
  4. A primer MUST distinguish the breadth of the question from the narrowness of the use, and MUST NOT collapse the two. It MAY state what the application will do with the grant, which section 12 confines to wallet discovery and wallet communication. It MUST NOT state or imply that the grant itself is narrow, that the browser is overstating the case, that the question is wider than it needs to be, or that the browser has erred in asking it. The grant genuinely does reach every service listening on the machine. A primer that says otherwise has told the user a falsehood about a security control in order to get past it, which is the conduct section 12 exists to make nameable and the Security Considerations describe as using an honest explanation to obtain a dishonest capability.
  5. The narrowness claim is checkable, and a primer MUST NOT make it unless the implementation keeps it. Section 12 is what makes "this site looks only for your wallet" a conformance statement rather than a reassurance. An implementation that makes the claim in its primer and scans unrelated ports is non-conforming twice, once for the scan and once for the sentence.
  6. A primer MUST NOT quote the browser's control labels. The dialog is drawn in the browser's user interface language, which is frequently not the document's. A page that tells its user to look for a particular word sends everyone with a differently localised browser hunting for text that is not on screen, and does it at the one moment the user is deciding whether this site can be trusted. A primer MAY instead describe the controls by role, for example that the question offers one control to allow and one to refuse, which stays true in every locale. It MUST NOT instruct the user to choose either one, MUST NOT describe choosing refusal as an error, and MUST NOT characterise the browser's question as unnecessary, routine or already answered.

5.4 Two controls, equally weighted

  1. A primer MUST offer exactly two controls: one that proceeds, one that declines.
  2. Both MUST be real controls, reachable by pointer, keyboard and assistive technology.
  3. Both MUST carry visible labels, and accessible names, that name the outcome. Continue, OK, Next, Submit and a bare Cancel name no outcome, and a user who scans only the controls, which is most users, learns nothing from them. Two labels that name two different outcomes can be chosen between without reading the body at all, which is the only form of this surface that survives a user who does not read.
  4. The declining control MUST NOT be weaker than the proceeding control in size, contrast, placement or labelling. A filled button beside a low-contrast text link is a weighting, and Nielsen Norman Group identifies it among the dark patterns that raise short-term acceptance and cost long-term trust. The standard to meet is the browser's own: Block and Allow are adjacent peers of equal size and contrast, and a primer that weights its choice is less respectful than the security dialog it precedes.
  5. Neither control may carry a recommendation badge, a default-selected indicator, a count of other users who chose it, or a pre-checked box.
  6. The declining control MUST describe declining the primer, not blocking in the browser, and MUST NOT borrow the browser's refusal wording. Declining a primer is reversible and Block is not, so a primer labelled Block or Deny misrepresents a recoverable refusal as a permanent one and discards the only advantage the primer has.
  7. The declining control MUST produce the behaviour in section 7. It MUST NOT merely close the primer and leave the user on the surface they started from with no explanation and no alternative.
  8. Escape, the backdrop, and any close affordance MUST be treated as declining, never as proceeding.

5.5 Language

  1. A primer MUST NOT use the words loopback, localhost, port, substrate, origin, CORS, permission policy, or the name or number of any BRC, in text shown to the user. It MUST NOT use self-custody, non-custodial, sovereign or decentralized without saying what they mean alongside, and SHOULD avoid them entirely. That second list is the Sponsored Onboarding and Wallet Choice proposal's, adopted here unchanged so that a user who meets the connect surface and the primer does not meet two vocabularies. BRC-151 states the principle for this corpus: permission prompts should describe consequences rather than internal terminology. BRC-184 states the failure mode: a prompt carrying only [2, "auth message signature"] is hard to understand.
  2. A primer SHOULD state at most two reasons. Evidence that long rationales outperform short ones does not exist; evidence that users stop reading does.
  3. A primer SHOULD use active voice and name the benefit rather than the mechanism, following the pattern [the wallet] so that you can [the thing you were doing].
  4. A primer SHOULD NOT claim a better experience, a smoother journey, or any benefit the user cannot check. Vague benefit claims are distrusted, and they occupy the space a checkable one would fill.
  5. Applications SHOULD test primer copy with users who do not work in this industry. The evidence in the Motivation is that presence drives the decision and quality drives satisfaction, so copy testing is a satisfaction and comprehension exercise, not a conversion exercise.
  6. One name for each thing, and sentences short enough to survive an interruption. A primer MUST use one consistent term for the application throughout, one for the wallet, and one for the browser. Alternating between the site, this page, the app and we forces the user to re-resolve the subject of every sentence, and the user is already being asked to resolve an unfamiliar security question. A primer MUST NOT refer to the application in the first person in one sentence and the third in another. Sentences SHOULD be at most 20 words, and the body SHOULD be at most 50. Semicolons, parenthetical asides, and subordinate clauses stacked more than one deep SHOULD be rewritten as separate sentences. These numbers are a testable proxy and no study supports the specific figures; what is supported, and is set out in the Motivation, is that a user about to be interrupted reads less than a user who is not.
  7. Say what declining costs. A primer MUST state, either in its body or in the declining control's own label, what happens if the user declines. Under section 7 the answer is that nothing of consequence happens and other routes remain open, and the user has no way to know that unless they are told. A surface that offers a choice while disclosing the outcome of only one branch is asking for agreement to something undisclosed, whatever its tone, and it wastes the one genuine advantage this document has over the dialog it precedes.

5.6 Not at the same time as the wallet's own prompt

A primer MUST NOT be shown while a BRC-219 wallet permission prompt is pending for the same interaction. The two dialogs ask different questions of the user, one on behalf of the browser and one on behalf of the wallet, and presenting them together produces a user who grants or denies both without distinguishing them. Loopback access is resolved first, because the wallet cannot be reached to ask its question until it is. BRC-185 section 8.5 states the same separation for pairing confirmation.

5.7 Presentation and accessibility

  1. A primer MUST NOT imitate browser chrome, a browser dialog, an operating system dialog, or the loopback access prompt itself. Beyond being the disguised-dialog dark pattern, a site that successfully impersonates browser security UI is training its own users to trust an impersonation of browser security UI.
  2. A primer MUST meet the accessibility requirements BRC-185 section 5 sets for the chooser: keyboard access, visible focus, accessible names, screen-reader status updates, and a reachable cancel or back action. It MUST carry the role appropriate to the form it takes under section 9, MUST place focus within itself on open, and MUST return focus to the control that summoned it when it closes without handing off. This document does not require that form to be a modal dialog, and section 9 explains why a modal is rarely the best of the available choices.
  3. A primer MUST say what is about to happen before it hands off, and MUST then get out of the way. The prompt is drawn in browser chrome, outside the document. The application cannot announce it, cannot describe it, cannot label its controls and cannot move focus to it. WCAG 3.2.5's understanding text records that people who are blind or have low vision may not notice that a change of context has occurred; here the application is the only party that can give notice, and it can only do so beforehand. The announcement MUST be made by the primer, as the last thing it does.
  4. On an affirmative response the primer MUST release any focus trap it holds and MUST NOT retain a modal barrier over the document while the browser's decision is outstanding. The decision has left the page, and a page-level focus trap running against browser chrome fights the user agent for control of a dialog the page does not own. A waiting state under section 6.1 point 5 MAY remain, and MUST be reachable rather than trapping.
  5. A primer MUST NOT auto-dismiss, MUST NOT carry a countdown, and MUST NOT be re-presented because the user has not yet answered.

6. The eliciting request

6.1 One request, with no deadline

  1. The eliciting request MUST be issued as a direct consequence of an affirmative response to the primer, within the same user activation, with no intervening navigation and no further interstitial. There MUST be nothing between the affirmative response and the browser's dialog. A loading state, a secondary confirmation or a marketing step breaks the link the primer just established and leaves the dialog looking unprompted again. This is the first of Nielsen's limits: under a tenth of a second the user feels they acted on the thing directly and no feedback is owed beyond the result, and the result owed here is the browser's question.

  2. The controller MUST issue exactly one loopback request for the purpose of raising the prompt. It MUST NOT begin a BRC-185 section 4.1 discovery round, and MUST NOT issue the 16 simultaneous requests that section permits, because every request beyond the first is wasted while the dialog is open and a fan-out can leave a trail of failures attributable to nothing.

  3. The eliciting request SHOULD address the first candidate of one configured base, and MUST be an ordinary discovery request to GET /.well-known/brc-wallet or, for a legacy default endpoint, the unchanged getVersion({}) probe that BRC-185 section 4.1 permits. It introduces no new endpoint.

  4. A controller MUST NOT issue an eliciting request in order to find out whether the user would have wanted the prompt, MUST NOT issue one speculatively during idle time or prefetch, and MUST NOT issue one from a code path the user did not initiate. A declined primer is a decision the controller may revisit. A denied prompt is one it cannot revisit at all.

  5. The 1000 ms per-request discovery deadline of BRC-185 section 4.1 MUST NOT be applied to the eliciting request. That deadline bounds a machine's response. The eliciting request is bounded by a person reading an unfamiliar dialog, and 1000 ms is shorter than that by an order of magnitude. A controller that applies it will abandon the request while the user is still deciding, and will then receive a grant it has already stopped waiting for.

  6. This is BRC-219's rule applied one layer out. That document states there is no elapsed-time limit on a live permission decision and requires wallets and substrates not to abort a permission-required request because wall-clock time elapsed. The same holds when the party deciding is answering the browser instead of the wallet.

  7. The 1000 ms figure is a response-time limit, and response-time limits bound machines. Nielsen's three limits, from Miller and from Card et al., are 0.1 seconds for a reaction that feels instantaneous, 1 second for the user's flow of thought to survive, and 10 seconds for their attention to stay on the task. BRC-185 section 4.1's per-request deadline sits exactly on the second of these and is correct there: a discovery round is a machine answering, and a round that overruns a second has cost the user their train of thought for nothing.

    A request the browser is holding open while a person reads four lines of unfamiliar security text is not a machine answering. It is a human decision, and it belongs past the third limit rather than at the second. Applying a flow-of-thought bound to it is a category error, and the cost of the error is that the user allows and the controller has already stopped listening. The same three limits say what to do instead, and section 9.5 does it: past one second, show that something is happening; past ten, expect the user to look away, give them a way to interrupt, and expect them to need reorienting when they come back.

  8. A controller MAY bound the eliciting request by a user-cancellable waiting state, and MUST NOT bound it by a fixed timer. Section 9.5 governs that surface, which is the one the user is looking at while the browser holds the decision.

6.2 Three outcomes, not two

The prompt has three exits, and an implementation that branches only on grant and denial mishandles the third. A controller MUST re-read the permission state after the eliciting request settles rather than inferring the outcome from the request result, because two of the three outcomes fail the request identically.

Granted. The state is granted. The controller MUST run the full BRC-185 section 4.1 discovery round with that section's ordinary deadlines and concurrency. The result of the eliciting request MAY be retained as the first probe result if it completed; it MUST NOT be treated as a complete round, and coverage MUST NOT be reported as complete on the strength of an eliciting request alone.

Blocked. The state is denied and section 8 applies. The controller MUST NOT retry the eliciting request, MUST NOT issue any probe, and MUST NOT present the denial as a transport failure.

Dismissed. The state remains prompt and the request has failed. The user has answered neither question, usually because the prompt arrived while their attention was elsewhere.

  1. A controller MUST NOT issue another eliciting request in response to a dismissal.
  2. It MUST treat the interaction as declined, applying section 7 in full, and MUST NOT describe the outcome as a refusal of the wallet.
  3. It MAY offer the primer again only under section 7.3, which requires a fresh user action on the connect surface.
  4. Coverage is reported as blocked with cause permission-declined under section 10.1.

The prohibition on retrying is not politeness. Browsers place an origin under embargo after repeated dismissals, suppressing the prompt without notifying the page and without changing the permission state away from prompt. Chromium's PermissionDecisionAutoBlocker carries the thresholds: three dismissals, or four occasions on which the user simply ignores the prompt, put the origin under a seven-day embargo, and under the quiet user interface those fall to one dismissal and two ignores. Both counts and the embargo duration are field-trial parameters rather than constants of the platform.

A controller that retries therefore spends the user's tolerance and arrives at a condition in which the dialog no longer appears, the state still reads prompt, and every branch in section 3.2 is wrong. Because the thresholds are configurable and differ between the standard and quiet interfaces, a controller MUST NOT depend on any particular count, MUST NOT attempt to determine the threshold in force, and MUST NOT issue eliciting requests in order to discover it. One dismissal is enough to be the last one.

Note also that ignoring the prompt counts, not only dismissing it. A primer that hands off and then leaves the user with nothing to look at, contrary to section 9.5, is manufacturing exactly the ignores that drive an origin toward embargo.

6.3 Returning the user to what they were doing

By the time a grant resolves, the user has crossed up to five surfaces: the control they operated, the primer, the browser's dialog, possibly the chooser of BRC-185 section 5, and possibly a BRC-219 wallet prompt. The action that started it was none of these.

  1. On a grant, the controller MUST return the user to the action that caused the primer to be shown, in the state it was in. A user who pressed Buy and then answered three questions MUST arrive back at Buy, not at a connected-wallet confirmation with no onward path.
  2. Where the action cannot be resumed automatically, the application MUST say what the user was doing and offer to resume it. It MUST NOT leave the user on a success screen whose only content is that a wallet is connected.
  3. Connection is not an accomplishment from the user's point of view. BRC-185 section 5.1 makes the related point in its own terms, that connection MUST NOT be presented as account authentication or as approval of a wallet operation; it is equally not the completion of the user's task. BRC-137 section 9 states the same principle one layer up, requiring every successful login to resolve to one application session of the same shape so that application code never branches on how the user arrived. This section is that rule applied to the user rather than to the code: the session should not branch, and neither should the person.
  4. This applies to a refusal too. Section 7.1 already requires the connect surface to survive a decline, and the same obligation to preserve the task applies: a user who declines MUST NOT lose the thing they were part-way through.

6.4 Cancellation

  1. Where the application aborts the connection request through the AbortSignal of BRC-185 section 2 while the prompt is displayed, the controller MUST NOT report the abort as a user denial. The browser dialog cannot be withdrawn by the page, and the user may still answer it.
  2. A grant that arrives after an abort MUST be honoured as a permission state change under section 3.5. A denial that arrives after an abort MUST be recorded as denied.
  3. An aborted resolution rejects waiting calls with USER_CANCELLED and delivery: 'not-sent' as BRC-185 section 6 already requires. No wallet method was dispatched, because no wallet was reached.

7. Declining is not a dead end

This section applies to a declined primer and to a dismissed prompt alike.

7.1 Return the user to what they were doing

The controller MUST return the user to the surface they came from, with the connect surface still present and still usable.

7.2 Offer the substrates that need no permission

The controller MUST offer the substrates of section 4.1 that remain available, and the encrypted mobile pairing path of BRC-185 section 8, which reaches a wallet on the user's phone and never touches this permission. Where no candidate exists at all, the device-aware install paths of BRC-137 and the application-supplied onboarding of BRC-185 section 7 apply. BRC-185 section 5 requires that pairing and installation remain distinguishable from discovered-provider rows; they are actions, not fictitious wallets.

7.3 Name the state honestly

A controller MUST NOT describe a declined primer, a dismissed prompt, a denied permission or a blocked probe as the absence of a wallet, in its interface, in its coverage snapshot, or in a typed error handed to an application. This is BRC-185 section 4.1's rule that a policy-blocked scan is blocked and not evidence of absence, and section 5.1's rule that an empty pending snapshot must not be described as a completed search.

7.4 Re-asking

  1. After a decline, a controller MUST NOT re-present the primer in the same session except in response to a fresh user action on the connect surface.
  2. A controller MAY present the primer again in a later session, in response to such an action. It MUST NOT present it on an escalating schedule, and MUST NOT present it more often because the user declined.
  3. A controller MUST NOT record a decline in a way that makes the connect surface unavailable later. The user declined a browser dialog, not a wallet.
  4. A decline MUST NOT be stored in the selection memory of BRC-185 section 5. It is not a provider choice.

7.5 Do not penalise the refusal

A controller MUST NOT degrade, delay or withhold functionality that does not depend on a wallet because the user declined. Nielsen Norman Group's third consideration is that a permission decision must be reversible without penalty; penalising it converts a reversible refusal into a permanent one.

7.6 A dismissal is not a decline, and the copy differs

A declined primer and a dismissed prompt reach the same place by different routes, and the surface cannot be the same for both. After a decline the user has not seen the browser's dialog. After a dismissal they have.

  1. A dismissal surface MUST NOT say that the browser will ask, or is about to ask. It already did, and a surface that says otherwise has told the user something they can see is untrue.
  2. It MUST NOT describe the browser's question again in full. The user either read it or chose not to, and restating it implies they failed to understand rather than declined to answer.
  3. It MUST NOT assert why the prompt went unanswered. A dismissal is indistinguishable at the page from a user who closed the dialog deliberately, a user whose attention was taken by something else, and a user who never noticed it. The honest surface names the state, not the act, and "you dismissed" and "you declined" are both guesses.
  4. It SHOULD state that nothing was shared and nothing changed. A user who closed a security dialog without answering it generally wants to know whether closing it was sufficient, and it was.
  5. It MUST offer the alternatives of section 7.2, and MAY offer one further attempt, which section 7.4 point 1 already restricts to a fresh user action on the connect surface.
  6. It MUST NOT count down, retry by itself, or reappear unprompted. Section 6.2 gives the reason: the browser's embargo counter does not distinguish a dismissal the user intended from one the application provoked, and the application cannot see the counter.

8. The denied state and recovery

8.1 Detection

  1. In the denied state a controller MUST NOT probe and MUST NOT issue an eliciting request. Neither can succeed, neither produces a dialog, and both yield only a failure the controller already knew about.
  2. A controller MUST also reach this section when a loopback request fails in a manner consistent with a blocked request while the state is unsupported, per section 3.3 point 3.

8.2 What recovery must offer

  1. The recovery surface MUST state what is blocked and what the consequence is, in the user's vocabulary, under the constraints of section 5.5.

  2. It MUST name the browser's own control path as the browser currently labels it, and MUST NOT invent a label. In current Chrome the relevant settings entry is Apps on device, which is IDS_SITE_SETTINGS_TYPE_LOOPBACK_NETWORK in Chromium's site settings strings, reachable from the control at the left of the address bar and from site settings. Where the application cannot determine the current label with confidence, it MUST describe the location rather than guess the wording.

  3. It MUST, in the same surface, offer the alternatives of section 7.2, and those alternatives SHOULD be the primary action. The settings path SHOULD be secondary.

    This inverts the usual advice deliberately. Nielsen Norman Group's decision-reversal guidance is to link the user directly to the exact settings location, and it is good advice for the native applications it was written for, which can deep-link into operating system settings. A web page cannot link to its own browser's settings. It can only describe where they are and hope. So the one mechanism that makes reversal work is unavailable here, and a recovery surface that leads with an unlinkable procedure leads with the branch most likely to fail. The user who wants to repair the permission will find the instructions wherever they sit. The user who does not want to edit browser settings, which is most users, needs the other route in front of them.

  4. It MUST detect repair without a reload, per section 3.5. A recovery surface MUST NOT require the user to tell it that they changed the setting, and MUST NOT offer a control whose only function is to say so.

  5. A recovery surface MAY print a settings address as text for the user to copy, and MUST NOT render one as a link. A page cannot navigate to a chrome:// address, so the link would do nothing when pressed, and a control that silently does nothing is worse than printed text that at least looks like something to copy.

  6. It MUST satisfy BRC-185 section 5.1's requirements for the "Discovery blocked or partial" state: explain the access or coverage limitation, distinguish it from wallet absence, and offer retry, phone pairing and application-supplied onboarding or install paths.

8.3 What recovery must not do

  1. It MUST NOT instruct the user to enable a browser flag, to disable Local Network Access checks, or to change any setting that applies to sites other than this one. That advice trades a single site's inconvenience for every site's protection. It is also the plain reading of BRC-185 section 4.1's prohibition on working around browser local-network permissions: telling the user to disable the check is the controller working around it by proxy.
  2. It MUST NOT present an unexplained error, a retry control that cannot succeed, or an indefinite spinner.
  3. It MUST NOT imply that the user made a mistake. They answered a question the application failed to prepare them for.

8.4 Where the permission lives, and where it does not

A recovery surface that sends the user to the wrong settings screen is worse than one that sends them nowhere. The user arrives somewhere plausible, finds no such setting, and concludes the application is broken rather than that the instruction was. The common wrong turn is the operating system, and for wallet discovery it is always the wrong turn.

Loopback is not the local network, and the operating systems agree. BRC-185's loopback substrates are ports on the machine the browser is running on. Apple's stated position is that 127.0.0.1 and ::1 are exempt from the Local Network privacy restriction, because traffic to them never leaves the device; the restriction covers multicast, broadcast, and unicast to the local subnet. So macOS and iOS hold no second gate over a wallet on localhost. Windows and desktop Linux have never gated loopback for an ordinary desktop browser. On the desktop the browser's permission is the only one in the way, and every recovery path below is a browser path.

Platform and browser Where the user re-grants Second gate in the operating system
Chrome or Edge, desktop The control at the left of the address bar, then the Apps on device entry. The same control is at chrome://settings/content/loopbackNetwork, and per site under chrome://settings/content/siteDetails None for loopback
Chrome, Android The control at the left of the address bar, then Permissions Unsettled, see below and section 11.5 point 2
Safari or Firefox Neither shipped this permission at the time of writing, so the state is unsupported and section 3.3 governs rather than this section. A controller reads the state and never this table None
Any browser under enterprise policy An administrator may have fixed the state, in which case the user cannot change it at all and the surface MUST NOT tell them they can. Section 8.2 point 1's statement of the consequence is the whole of what can honestly be offered Not applicable

The Apps on device wording is IDS_SITE_SETTINGS_TYPE_LOOPBACK_NETWORK in Chromium's site settings strings, distinct from Local network, which is the other half of the split permission and not the one wallet discovery needs. Section 8.2 point 2 governs: name it as the browser currently labels it, or describe the location and do not guess.

Android is the one platform where this document cannot give an answer. Section 11.5 point 2 sets out why: Chrome for Android is itself an application holding operating system permissions, it declares android.permission.ACCESS_LOCAL_NETWORK, and Chromium carries a distinct prompt for the case where it lacks one, reading Connect to nearby devices?. Android's own documentation defines the restriction over local network addresses and does not state whether loopback is among them, so whether a loopback-network grant on Android can be defeated by a missing operating system permission is not established here. An implementation MUST NOT assume either answer.

Section 8.2 point 4 is what covers the gap. A controller that watches the permission state and re-evaluates on change behaves correctly whichever way the Android question resolves, because it never reasons about the platform in the first place. A controller that branches on a guess about Android will be wrong on half the devices under one answer and all of them under the other.

9. Presentation forms

BRC-185 section 5 declines to prescribe a form for the chooser, in those words: "Modal styling is not prescribed." Its section 5.1 permits "a modal, panel, page, or native surface" and requires only that equivalent presentations preserve that document's equal treatment, accessibility, cancellation and selection policy. This document prescribes no form either. It ranks them, because one variable dominates and it is not aesthetic.

The browser draws its question in its own chrome, at an anchor the page does not control and cannot move. In current desktop Chrome that anchor is beneath the address bar. The application's surface is in the viewport, below it and usually centred. Every candidate form is better or worse according to two things: how far the user's attention must travel from the application's surface to that anchor, and how many layers the application interposed on the way. A centre-screen modal maximises both.

That is also where the mobile priming literature this document adapts stops transferring. On iOS and Android the system sheet and the primer occupy the same region of the same screen, so the question of where the user looks next never arises. On desktop it is the main question, and a standard that imports the mobile pattern without noticing produces applications that explain themselves well and then point the user at the wrong half of the window.

9.1 Three surfaces, three problems

Surface When Defined in What the form must protect
Primer Before the prompt Section 5 Attention, and a handoff the user can follow
Waiting state While the prompt is open Section 6.1 point 5 Orientation, with the page no longer in control
Recovery surface After a refusal Section 8 Dignity, and a route that is not browser settings

These are three different problems and an application MUST NOT adopt one form for all three without reference to this section. They differ in whether the page owns the user's attention at all: before the handoff it does, during the handoff it does not, and after a refusal it has been told it should not.

9.2 Forms for the primer

Form Verdict When it is right
Anchored popover, placed toward the browser's prompt anchor SHOULD, default on pointer and desktop The ordinary case. It shortens the attention distance to near zero by placing the explanation where the question will appear
Inline panel inside the connect surface or chooser SHOULD, whenever one is already open Adds no layer at all. A chooser under BRC-185 section 5 is already the surface the user is attending to
Inline disclosure at the value control the user just operated SHOULD, when the ask follows Buy, Post, Unlock or similar Keeps the explanation attached to the reason for it, which is the strongest timing the evidence supports
Bottom sheet SHOULD, on mobile browsers Mobile browsers commonly draw permission UI low. Co-locate with it rather than with the desktop convention
Modal dialog MAY Acceptable where connecting is the user's whole task and nothing else is on screen. It costs the maximum attention distance and one full layer
Full-page view or dedicated route SHOULD NOT A navigation is itself a change of context under WCAG 3.2.5, and it discards the task the user was in the middle of. Acceptable only where the user deliberately navigated to a connect route
Toast, snackbar, banner, or any auto-dismissing surface MUST NOT It auto-dismisses, against section 5.7 point 5. It cannot carry two equally weighted controls, against section 5.4. And nothing establishes that it was read before the browser's question arrived

9.3 Choosing among them

Apply in order. The first matching row governs.

  1. A connect surface or chooser is already open: inline panel within it.
  2. The ask follows the user's operation of a value control: inline disclosure at that control.
  3. Pointer or desktop presentation: anchored popover.
  4. Mobile browser presentation: bottom sheet.
  5. None of the above: modal dialog.

A full-page view is permitted only where the user navigated to a connect route of their own accord. An auto-dismissing surface is permitted in no case.

9.4 The anchored popover, and the rule it pulls against

Recommending proximity to browser chrome and prohibiting imitation of browser chrome pull in opposite directions, and the recommended form is the one most exposed to the prohibition. Proximity is for attention. It is not for borrowed authority.

  1. An anchored popover MUST read as content of the page: the page's typography, the page's surface treatment, the page's colours.
  2. It MUST NOT carry a frame, pointer, arrow or border that implies continuity with the browser's own interface, and MUST NOT be positioned so as to appear contiguous with it.
  3. It MUST NOT assert a position for the browser's question more precise than the application can determine. Browsers differ, and the same browser differs between desktop and mobile. Describe the region, or say nothing about position.
  4. Section 5.7 point 1 bears more heavily the closer the form sits to chrome, not less. An implementation that cannot keep an anchored popover visibly distinct from browser UI MUST use an inline panel or a modal instead.

9.5 The waiting state

The user is now past Nielsen's ten-second limit, which is where attention leaves the task, other work begins, and a returning user has to reorient. Each rule below follows from that.

  1. The waiting state MUST be non-modal and MUST NOT block interaction with the rest of the document. The decision has left the page under section 5.7 point 4, and a page that blocks itself while browser chrome is deciding has locked a door it is not standing behind. Past ten seconds a user will want to do something else, and a blocking overlay punishes them for a delay the page did not cause and cannot end.
  2. It MUST persist until the permission state resolves or the user stops it, and MUST NOT auto-dismiss. It MUST NOT be a toast, for the reasons in section 13.2.
  3. It SHOULD be positioned toward the browser's prompt anchor, subject to section 9.4 point 3.
  4. It MUST carry a control that stops waiting, labelled under section 5.4 point 3, and that control MUST NOT be presented as refusing the browser's question. The page cannot answer on the user's behalf. An interruptible path out is the standing requirement for any operation that runs past ten seconds.
  5. It MUST remain legible to a user who has looked away and come back, which is the ordinary case at this duration. Stating where the question is, as section 5.2 point 6 requires of the primer, is what that means in practice.
  6. It MUST NOT display a countdown, a progress bar implying completion, or any other representation of a deadline. There is none, under section 6.1. A percent-done indicator is the right answer for a long machine operation and the wrong one here, because nothing is progressing: a person is deciding.

9.6 The recovery surface

  1. The recovery surface SHOULD be an inline panel, in place of or beside the connect surface.
  2. It MUST NOT be modal. A modal shown to somebody who has just refused re-opens a decision they have made, in the one form they cannot ignore, moments after being told their refusal would be respected. Nothing in its copy will repair what its form has said.
  3. It MUST remain dismissible, and dismissal MUST NOT put the alternatives of section 7.2 out of reach.
  4. It MUST NOT be re-presented automatically during the same visit after it has been dismissed.

9.7 What the form does not change

Sections 5.2 through 5.7 apply whatever form is chosen: the four content elements, two controls of equal weight, labels that name outcomes, the language rules, the handoff announcement, and the accessibility requirements BRC-185 section 5 sets for the chooser. That document's rule holds here in its own words: equivalent presentations MUST preserve equal treatment, accessibility and cancellation. A form is a container, and no container relaxes a requirement. An application that moves the primer from a modal into an inline disclosure to make it less conspicuous has not chosen a better form, it has chosen a quieter way to fail section 5.4.

10. Reporting

This document introduces no new error code, coverage state or connection state. It specifies how the browser permission maps onto the ones BRC-185 already defines.

10.1 Coverage

The loopback adapter's per-adapter coverage, required by BRC-185 section 2, MUST be reported as follows. The cause strings below are ConnectionError.cause values, which BRC-185 section 6 explicitly permits libraries to add without replacing its required fields.

Condition Coverage cause
granted, round completed over the configured scope complete none
granted, round partially completed or probes timed out partial as BRC-185 section 4.1 requires
prompt, no user activation available blocked permission-required
prompt, candidate already found by another adapter blocked permission-not-requested
prompt, primer declined blocked permission-declined
denied blocked permission-denied
Non-secure context unsupported insecure-context
Cross-origin frame without delegation unsupported permission-policy
unsupported, requests not blocked as the round determines none
exempt as the round determines none

In every blocked row the snapshot MUST disclose that the loopback address space was not searched, as BRC-185 section 4.1 requires, and MUST NOT claim to have searched all ports or all installed wallets.

10.2 Errors

  1. Where a resolution fails and the loopback adapter's coverage is blocked for any permission cause, the controller MUST use the existing DISCOVERY_BLOCKED code with delivery: 'not-sent' and the cause from section 10.1. Delivery is always not-sent for these conditions, because no request reached a wallet.
  2. A non-secure context and an undelegated cross-origin frame are configuration faults and MUST use the existing CONFIGURATION_ERROR code, reported to the embedding application or operator rather than rendered to the user as a wallet problem.
  3. A permission condition MUST NOT be reported as PROVIDER_CHANGED, DISCONNECTED, CONNECTION_CLOSED or PROTOCOL_ERROR. No provider changed, no connection existed, and no protocol was violated.

10.3 Connection state

BRC-185 section 6 requires an application to be able to distinguish discovering, choosing, pairing, connected, locked or authentication required, waiting for wallet approval, suspended, disconnected and closed.

  1. A controller MUST additionally distinguish waiting for browser permission from waiting for wallet approval, and MUST NOT present one as the other. They differ in who is being asked, in what has been reached, and in what a refusal costs.
  2. This distinction is what repairs BRC-219's binary. That document allows an application to assume that a hanging request means the wallet is asking the user. While an eliciting request is outstanding, that assumption is false and the controller is the only component that knows it. A controller MUST NOT surface a pending eliciting request to the application in a form that invites the BRC-219 inference.
  3. A pending eliciting request MUST NOT be presented as a locked wallet, an unresponsive wallet, or a slow network.

10.4 Remembered selections

  1. A remembered loopback provider that cannot be reached because the permission state is denied MUST NOT be treated as missing, changed, rotated or unverifiable under BRC-185 section 5. The provider has not changed; the route to it is closed.
  2. The controller MUST preserve the remembered preference, as that section requires preferences be preserved until replaced or forgotten, and MUST NOT fall through to a different candidate on the strength of a permission failure. BRC-185 section 5 already states that lock state is not absence and forbids silently moving to another wallet because the selected one is unavailable; the same reasoning applies.

11. Embedding, delegation, workers and secure context

11.1 Cross-origin frames

  1. Where the connect surface is in a cross-origin frame, the embedder MUST delegate the permission to that frame's origin through Permissions Policy, using the loopback-network feature, or the combined local-network-access feature on browsers that predate the split. The default allowlist is self, so an undelegated frame cannot obtain the permission and the prompt will never appear.
  2. The embedder MUST delegate to named origins. It MUST NOT use a wildcard allowlist for this feature.
  3. A frame that detects it has not been delegated to MUST NOT show a primer, because the primer would precede a dialog that cannot appear. It MUST report the condition under section 10.1 and section 10.2 point 2.

11.2 Workers

Service workers and shared workers cannot raise this prompt on an origin that has not already been granted the permission. A controller that performs discovery from a worker MUST obtain the grant from a document first, under sections 3 to 7, before delegating any loopback request to a worker.

11.3 Secure context

The permission is available only in a secure context. An application served over a non-secure, non-loopback context MUST NOT show a primer, because no grant is obtainable and the primer would promise a dialog that will not come. This is a deployment fault and MUST be surfaced under section 10.2 point 2, not to the user as a wallet problem.

11.4 Non-browser hosts

BRC-185 section 1 requires non-web hosts to supply an explicit application context and states that a headless caller cannot acquire browser-origin authenticity by supplying a string. Node, terminal and headless controllers have no loopback access prompt and no Permissions API. They are in the unsupported state of section 3.3 and MUST NOT show a primer. The reasoning of BRC-219's non-interactive wallet section applies: where there is no user to ask, behaviour must be deterministic policy rather than a hanging wait.

11.5 Mobile browsers

This document is shaped by the desktop case, because that is where loopback wallets run. Three things differ on a mobile browser and an implementation that ignores them will be wrong there.

  1. The prompt is drawn elsewhere. Mobile browsers commonly place permission UI low on the screen rather than beneath the address bar, and some place the address bar itself at the bottom. Section 5.2 point 6 and section 9.4 point 3 apply: state the position for the platform actually in use, or state nothing.

  2. There is a second permission, and the page cannot see it. On Android the browser is itself an application holding operating system permissions. Chromium's Android manifest declares android.permission.ACCESS_LOCAL_NETWORK, and the browser may not hold it, in which case it cannot honour a grant the user has already given the site. Chromium carries a distinct string for that case, IDS_MESSAGE_MISSING_LOCAL_NETWORK_PERMISSION_TITLE, reading Connect to nearby devices?.

    The page has no access to operating system permission state, so it cannot query this, cannot request it, and cannot distinguish it from any other failure: the Permissions API reports the site's own grant and nothing about the browser's. A controller MUST NOT present a failure arising from the browser's own missing operating system permission as the user's refusal or as an absent wallet. Where the site's own state reads granted and loopback requests still fail, a controller SHOULD say that the browser may need permission of its own, which is the only honest account available to it.

  3. Loopback is usually the wrong substrate here anyway. A mobile browser reaching a wallet on the same handset is possible and uncommon; the ordinary mobile path is the encrypted pairing of BRC-185 section 8, which needs none of this. A controller on a mobile browser SHOULD order pairing ahead of loopback under section 4.1, and SHOULD NOT spend a permission on a substrate it does not expect to find.

12. The grant is for wallet discovery

12.1 An origin granted loopback access can reach every service listening on the user's own machine, which is precisely the capability Local Network Access exists to restrict and precisely the fingerprinting surface it exists to close. BRC-151 already names malicious localhost requests and DNS rebinding among the threats implementations must defend against. The grant obtained under this document is obtained by telling a user it is for their wallet.

12.2 A conforming controller MUST confine its loopback requests to wallet discovery and wallet communication: the address space of BRC-185 section 4.1, any endpoint the user or application explicitly configured, and the connection established from them. It MUST honour that section's requirement to deduplicate identical scheme, host and port probes, which now also bounds what the grant is used for.

12.3 A conforming controller MUST NOT use the grant to enumerate unrelated local services, to profile installed software, to detect other applications, or to derive any identifier from the result of such a scan, whether or not the result is transmitted. BRC-185 section 3 already requires the discovery record and candidate inventory to remain local to the application unless the user explicitly requests sharing them.

12.4 An application that needs loopback access for any other purpose MUST obtain it through its own surface, with its own explanation, and MUST NOT present that purpose as part of connecting a wallet.

13. Conformance

13.1 State table

An implementation conforms if, for every entry, it exhibits the behaviour given.

Condition Required behaviour
Before first loopback request navigator.permissions.query({name: "loopback-network"}), falling back to local-network-access
Query rejects both names State unsupported; no primer; probing permitted; a blocked request surfaced as blocked coverage
Document origin is loopback State exempt; no primer; probing permitted
State granted No primer; round proceeds with BRC-185 deadlines; no interruption
State prompt, non-loopback adapter already yielded a selectable candidate No primer; no eliciting request; coverage blocked, cause permission-not-requested
State prompt, no user activation No primer; no eliciting request; coverage blocked, cause permission-required; resolve on other adapters
State prompt, user unlikely to hold a wallet Install and pairing routes offered before or alongside the primer
State prompt, user operates a connect or value control Primer, per section 5; value control preferred where both exist
Primer content Names the gap between the browser's wording and the use; claims no narrowness in the grant
Value-control path, user has never connected Primer carries the two-line connect explanation the connect surface would have
Primer form chosen Per section 9.3's ordered rule; never an auto-dismissing surface
Primer, before handing off States that the browser is about to ask; announcement is the last thing the primer does
Prompt outstanding Waiting state non-blocking, persistent, cancellable, no deadline shown
Recovery surface form Inline panel, never modal, dismissible without losing the alternatives
Primer, affirmative response One eliciting request, same user activation, no 1000 ms deadline, no fan-out; focus trap released, no modal barrier retained
Eliciting request settled State re-read, not inferred from the request result
Prompt granted Run full BRC-185 round; do not report complete from the eliciting request alone
Grant resolved User returned to the action that caused the primer, in the state it was in
Prompt blocked State denied; no retry; not presented as a transport failure
Prompt dismissed State still prompt; no second eliciting request; treated as declined; coverage blocked, cause permission-declined
Dismissal surface Does not say the browser will ask, does not restate the question, does not assert why it went unanswered
Recovery surface, settings path Named as the browser labels it or described by location; printed as text, never as a link
Recovery surface, repair Noticed without a reload and without the user asserting it; no control whose only function is to say the setting changed
Recovery surface, policy-fixed state Does not tell the user they can change what an administrator has fixed
Primer declined No eliciting request; connect surface retained; alternatives offered; coverage blocked, cause permission-declined
Abort while prompt displayed Not reported as denial; later grant honoured; USER_CANCELLED, delivery: 'not-sent'
State denied No requests; no primer; recovery surface with repair path and alternatives; coverage blocked, cause permission-denied
State denied, remembered loopback provider Preference preserved; not treated as missing, changed or unverifiable
Mobile browser, grant held but requests still fail Not reported as refusal or absence; browser may lack its own OS permission
Repair detected while page open State re-evaluated and round re-run without reload
Eliciting request outstanding Presented as waiting for browser permission, never as waiting for wallet approval
Cross-origin frame, not delegated No primer; coverage unsupported, cause permission-policy; CONFIGURATION_ERROR
Non-secure, non-loopback context No primer; coverage unsupported, cause insecure-context; CONFIGURATION_ERROR
Any state No loopback request outside the wallet discovery address space

13.2 Surfaces that fail conformance

Each of the following is a conformance failure on its own. The list is not exhaustive of section 13.1, which is normative; these are the ones that are non-obvious, or that are already deployed somewhere.

  1. A discovery round on page load, raising the prompt before the user has acted.
  2. An eliciting request subject to the 1000 ms discovery deadline, abandoning the user's grant while they are still reading.
  3. A dismissed prompt answered with a second eliciting request, walking the origin toward silent suppression.
  4. An outcome inferred from the failed request rather than re-read from the permission state, which cannot distinguish a block from a dismissal.
  5. A primer shown when the state is granted, when the query is unsupported, or from a loopback-origin development server, interrupting a user for a dialog that will not appear.
  6. A primer that leaves the browser's wording unaddressed, so the user decides on other apps and services on this device with nothing to compare it against.
  7. A primer claiming the grant is narrow, that the browser is overstating the case, or that its question may be disregarded.
  8. A primer claiming the application looks only for a wallet, in an implementation that scans anything else.
  9. A primer that quotes the browser's control labels, which are absent in any browser localised differently from the page.
  10. A primer whose controls are labelled Continue and Cancel, or any pair that names no outcome.
  11. A dismissal surface telling the user their browser is about to ask, when it already did and they closed it.
  12. A dismissal surface asserting that the user declined, when the page cannot tell a deliberate close from a user who never saw the dialog.
  13. A recovery surface sending the user to operating system settings for a loopback permission the operating system does not hold.
  14. A chrome:// settings address rendered as a link, which does nothing when pressed because a page may not navigate there.
  15. A recovery surface with an I have changed the setting control, in place of the detection section 8.2 point 4 requires.
  16. A primer whose decline control is a text link beside a filled proceed button, or is labelled Block or Deny, presenting a reversible refusal as a permanent one.
  17. A primer that reproduces the browser's dialog styling, or is framed or positioned to appear contiguous with browser chrome. The recommended anchored form makes this easy.
  18. A primer that hands off without having said that the browser is about to ask, leaving a screen-reader user with a dialog that closes and nothing else.
  19. A primer that holds a focus trap or a modal barrier over the document while the browser's dialog is outstanding.
  20. A toast, snackbar, banner or any other auto-dismissing surface used as a primer.
  21. A value-control primer shown to a user who has never connected a wallet and was never told what connecting is, because no connect surface appeared on that path.
  22. A newcomer with no wallet taken through the browser's dialog and then told to install one.
  23. A grant that lands the user on a connected-wallet confirmation instead of the action they started.
  24. A denied state rendered as No wallet available over any communication substrate, as complete coverage, or as PROVIDER_CHANGED or DISCONNECTED.
  25. A pending eliciting request presented as a wallet awaiting approval.
  26. A recovery surface that tells the user to open chrome://flags, or that leads with browser settings instructions the page cannot link to ahead of a route the user can take.
  27. A mobile failure caused by the browser's own missing operating system permission, reported as the user's refusal or as an absent wallet.
  28. A grant obtained for a wallet and reused to scan other local ports.

What Is Checkable, and What Is Taken on Trust

This document defines no cryptographic value, so nothing in it is checkable in the sense the rest of this corpus usually means. What it defines is an order of events and the content of three surfaces, and both are checkable by observing an implementation rather than by verifying a number. That is a weaker guarantee and it is worth saying which claims it does and does not reach.

Fact Who can check it How
No loopback request preceded the permission query Anybody with developer tools The network panel, against section 3.1
The prompt followed a user action rather than page load Anybody Load the page and wait. Nothing should happen
A primer preceded the prompt Anybody The order of the two surfaces
The eliciting request was one request, not a fan-out Anybody with developer tools One entry, not sixteen, against section 6.1 point 1
The discovery deadline was not applied to it Anybody Hold the dialog open past 1000 ms. The grant must still produce a round
The grant is used only for wallet discovery Anybody with developer tools Every loopback request addresses the BRC-185 section 4.1 space, against section 12
A blocked scan was reported as blocked, not as absence The embedding application The coverage snapshot, against section 10.1
A denial produced DISCOVERY_BLOCKED with delivery: 'not-sent' The embedding application The typed error, against section 10.2
The decline control is a peer of the proceed control Anybody Rendered size, contrast and placement, against section 5.4 point 4
No browser control label was quoted Anybody, in any locale The primer's text, against section 5.3 point 6
Claim Why it cannot be checked What stands in for a check
The user understood the question No mechanism reaches a mind The content rules of section 5.2 and the comprehension testing of section 5.5 point 5
The user was not persuaded past their own judgement Tan et al. found that the presence of an explanation raises approval regardless of what it says, so a grant cannot be read as comprehension Sections 5.3 and 5.4, which constrain the means rather than the outcome
The stated position of the browser's question is true here The page cannot read browser chrome, and browsers differ Section 9.4 point 3, which permits saying nothing instead
The grant will not be abused after it is obtained A conforming discovery scan and an abusive one are the same API call made twice Section 12, which makes the abuse nameable, and the devtools check above
The browser holds its own operating system permission on Android The page cannot query it and the Permissions API keeps reporting the site's state Section 11.5 point 2's reporting rule
The prompt was dismissed rather than blocked Both fail the request identically and neither is visible to the page Re-reading the permission state, section 6.2
A wallet exists that discovery did not find Coverage is completion of a configured scope, not proof of absence BRC-185's coverage vocabulary, used unchanged in section 10.1
The primer's copy is comprehensible to this user Readability is a property of a user, not of a text Section 5.5's constraints, which are a proxy and are labelled as one

The first table is what a reviewer can establish about a deployed implementation in an afternoon. The second is what no reviewer can establish about any implementation, and the honest position is that this document converts several of those into obligations that can be audited rather than into facts that can be proved.

What It Buys, and What It Costs

Party What they get What it costs them
User A question asked at a moment they chose, in words that name what is actually wanted, and a refusal that costs them nothing One more surface before the browser's, and a grant that is genuinely broader than the use it was explained by
Application A grant obtained rather than spent, discovery failures it can describe truthfully, and users who do not leave at an unexplained dialog A Permissions API dependency, three surfaces to build and maintain, discovery that may not begin on load, and some users who decline the primer and would have allowed the dialog
Wallet vendor Reachability that survives a browser release which would otherwise have ended loopback discovery quietly Nothing. No wallet changes
Browser Its permission answered by a prepared user rather than an ambushed one Nothing
Ecosystem Fewer reflexive refusals, and one less source of the habituation every site draws on Nothing this document adds

Two of these deserve saying plainly.

The user pays a surface to avoid an ambush, and that is a real cost. This document adds a step to a flow that had none, in a corpus whose onboarding documents exist to remove steps. BRC-110 is about zero friction and BRC-137 is about not meeting a visitor with an obstacle. The defence is that the step being added is small and recoverable and the step being avoided is neither, and that a user who refuses an unexplained dialog has not been spared friction but handed a permanent one. A user who thinks a site should simply probe and take its chances is disagreeing with a decision made on purpose.

The application pays most, and some of what it pays is grants it would have had. A primer gives a user a free way to say no, and some who would have pressed the browser's allow will press the primer's decline instead. That is the mechanism working rather than failing, because those users remain askable next week and a browser-level refusal would not have been. But it is a cost, it falls on the party doing the work, and a document that claimed priming is free in both directions would be arguing from only half of its own evidence.

Security Considerations

A primer raises grant rates, and that is the hazard as well as the purpose. Tan et al. measured a significant increase in approvals from the mere presence of an explanation, including explanations that conveyed nothing. A standard that mandates explanation therefore mandates a technique that works on users who have not understood. The mitigations here are structural rather than exhortative: section 5.2 fixes what may be said and forbids claims the application cannot support, section 5.4 forbids weighting the choice, section 4.1 forbids spending the permission at all when another adapter has already answered, and section 12 confines what the resulting grant may be used for. None of them prevents a determined bad actor from writing a persuasive primer. The permission itself remains the security control; the primer is a comprehension control, and this document does not claim otherwise.

Imitating browser chrome is the serious attack this pattern invites. A primer that looks like a browser dialog is more effective, and an ecosystem whose standard permits it trains users to accept browser-looking dialogs drawn by web pages. That is a transferable harm: the user so trained is more vulnerable on every other site. Section 5.7 point 1 is a prohibition rather than a recommendation for that reason.

The grant is broader than the ask. Loopback access reaches every listening service on the machine, not only a wallet. BRC-151 names malicious localhost requests and DNS rebinding as threats wallet implementations must defend against, and Local Network Access is the browser-side counterpart of that defence. The user is told the grant is for their wallet because that is the truthful reason the application wants it, and section 12 binds the application to that reason. An application that honours sections 1 through 11 and ignores section 12 has used an honest explanation to obtain a dishonest capability, and is non-conforming.

Denial must stay cheap for the user and expensive for nobody. Section 7.4 forbids penalising a refusal. The reason is security-relevant, not merely courteous: a user who learns that refusing a permission breaks unrelated functionality learns to grant permissions reflexively, which is the habituation that Akhawe and Felt measured at 70.2 percent clickthrough on Chrome's SSL warning. Every application that penalises refusal spends down a resource shared by every other application.

Retrying a dismissed prompt is an availability attack an application runs against itself. Dismissal leaves the permission state at prompt, so a naive controller reads a state that says "you may ask" and asks again. Browsers suppress the prompt after repeated dismissals without notifying the page and without changing that state, so the end condition is an origin that can never raise the dialog, reports prompt, and takes every prompt branch in section 3.2 incorrectly. The application has made itself permanently unable to reach a wallet that is running, and has no signal telling it so. Section 6.2 forbids the retry, and section 7.3 requires a fresh user action before the primer returns.

The eliciting request has no deadline, and that is a deliberate denial-of-service tradeoff. Section 6.1 removes the only timer bounding a request that the browser holds open. A page that issues an eliciting request and never resolves it holds a connection and a waiting state indefinitely. The mitigation is that the waiting state MUST be user-cancellable, that only one eliciting request may be outstanding, and that the alternative, a fixed timer, discards real user grants. BRC-219 made the same tradeoff for wallet prompts and for the same reason.

Privacy Considerations

Priming does not make loopback discovery safe for the user's privacy. BRC-185 section 4.1 discovery enumerates up to 192 addresses and the result is a fingerprinting signal about which wallet software is installed. That property is unchanged by this document. What changes is that the user agreed to it having been told what it was for, which is the difference between a disclosed surface and an undisclosed one.

The permission state is a stable signal about the user. A denied state persists across sessions and is readable by any site. This document does not create that signal; the Permissions API does. Controllers SHOULD NOT transmit or persist the state beyond what the session requires, MUST NOT combine it with other signals for identification, and MUST NOT place it in the selection memory of BRC-185 section 5, which that section restricts to provider identity material.

Implementations

This document is implementable today against shipped APIs, with no new dependency and no change to any wallet.

The read. navigator.permissions.query({name: "loopback-network"}) returns a PermissionStatus whose state is granted, prompt or denied, and whose change event satisfies section 3.5. An unrecognised descriptor name rejects with a TypeError, which is the feature detection section 3.3 requires. Browsers that shipped Local Network Access before the permission was split into local-network and loopback-network expose the combined local-network-access name, which reports denied if either granular permission is denied; the two-step query in section 3.1 covers both generations.

Checked against Google Chrome 155.0.8059.80: the query resolves rather than rejecting and reports prompt; loopback-network, local-network and the legacy local-network-access are all accepted as descriptor names while an invented name is rejected as an invalid descriptor; and the change event fires on every transition, including the denied to prompt transition that section 3.5 point 2 depends on, through both the onchange property and addEventListener.

The request. Ordinary BRC-185 section 4.1 discovery over fetch. Where a configured endpoint is a public hostname that resolves to a loopback address, the request must set targetAddressSpace: "loopback", without which an HTTPS document's request to an HTTP loopback endpoint fails mixed content checks before the permission is ever consulted. Private IP literals and .local names do not need it.

No preflight header is required, and stale guidance says otherwise. Local Network Access replaced Private Network Access specifically by gating on a permission rather than on a preflight. A wallet listener does not need to emit Access-Control-Allow-Private-Network, and BRC-185 section 4.1's existing CORS rules, including that preflight is noninteractive and that the exact permitted origin is returned, are unchanged. Implementers who find documentation requiring that header are reading Private Network Access material.

Delegation. Permissions-Policy: loopback-network=("https://wallet-connect.example") as a response header, or allow="loopback-network" on an iframe, satisfies section 11.1. The default allowlist is self.

Where this belongs in a stack. The natural home is the external connection controller of BRC-185 section 2, which already owns adapter coverage, the candidate snapshot, typed connection errors and the no-wallet surfaces, and is already required by section 5.1 to distinguish blocked discovery from wallet absence. Sections 3, 4, 6 and 10 of this document are controller logic. Sections 5, 8 and 9 are two presentation components, a primer dialog and a recovery panel, which belong beside the chooser as replaceable adapters under BRC-185 section 7. A wrapper that supplies its own connect experience, including the commercial onboarding wrappers that section anticipates and the chooser described in the Sponsored Onboarding and Wallet Choice proposal, inherits these requirements for the surfaces it replaces, and section 4.4 applies: controller and wrapper must not each show a primer.

Verification. There are no cryptographic values and no wire format here, so there is nothing to publish as test vectors. An implementation is checked against the state table in section 13.1, which is directly automatable. A headless browser with the permission pre-set to each of granted, prompt and denied covers three rows; a build with the descriptor name removed covers unsupported; serving the page from a loopback origin covers exempt; and an undelegated cross-origin frame and a plain HTTP origin cover the two configuration faults. The deadline row of section 13.1 is tested by holding the dialog open for longer than 1000 ms and asserting that the subsequent grant still produces a discovery round.

Failure Modes

The claim running through this document is that every bad outcome here is attributable to a named party, and that most of them are attributable to the controller. This is that claim written out. The last column carries the argument: in only one row is the user implicated, and in that row nothing went wrong.

What went wrong How it shows Detected by Attributable to
The prompt was raised on page load A security dialog with no preceding action The user, and anybody with developer tools The controller
The permission state was never read A blocked scan is reported as an absent wallet The embedding application The controller
The discovery deadline was applied to the eliciting request The user allows, and nothing connects The user, who has no idea why The controller
A dismissal was retried The dialog stops appearing while the state still reads prompt Nobody, until discovery fails silently forever The controller
A block and a dismissal were not distinguished A recovery surface shown to somebody who dismissed, or none shown to somebody who blocked Nobody from the page The controller, for inferring from the request
The browser's prompt was attributed to the wallet A conforming wallet is reported as hanging, against BRC-219 The application, and the wallet vendor accused The controller
A cross-origin connect frame was not delegated to No prompt ever appears and discovery simply fails The embedder, eventually The embedding application
The document was served over a non-secure context The same, with no grant obtainable The operator Deployment
The browser lacks its own Android permission A grant is held and requests still fail Nobody from the page The browser. Not the user, and not the wallet
The primer imitated browser chrome A user trusts a page-drawn security dialog somewhere else, later Nobody, ever The application, and the whole ecosystem pays
The grant was reused to scan unrelated ports Nothing the user can see Anybody with developer tools The application
The user refused Nothing went wrong Everybody Nobody. This is the system working

Appendix A: Worked Copy

These examples illustrate sections 5.2 to 5.5. They are not a required wording, and section 5.5 point 5 applies: test with real users rather than adopting these as given.

Three conventions run through all of them, and each is a rule rather than a preference. This site is the only term used for the application, never this page, the app, we or us, per section 5.5 point 6. No browser control is quoted by label, only described by role, per section 5.3 point 6, because the dialog is rendered in the browser's language and not the document's. And every control names an outcome, per section 5.4 point 3.

A primer in the prompt state, where no wallet is yet known.

Your browser's question is broader than this site needs

It asks whether this site may reach apps and services on this device. That covers everything running here.

This site looks for one thing, your wallet, and your keys stay inside it. The question appears near the top of your browser window.

[ Connect my wallet ] [ Other ways to connect ]

That is section 5.2 point 5 carrying the weight. The heading names the mismatch, the second paragraph states what the browser's sentence covers, and the third states what this site does with it. Nothing claims the grant is narrow, which it is not, and nothing suggests the browser is overstating the case, which section 5.3 point 4 forbids. The claim in the third paragraph is only available because section 12 binds the implementation to it.

A primer where the document is served from a platform or preview host, per section 5.2. The address is shown because the browser is about to show it and nothing else.

Next, your browser will ask about apps on this device

Your wallet runs on this computer. This site never sees your keys.

Your browser will ask whether checkout-9f2c.preview.example, which is this site, may reach apps running here. The question appears near the top of your browser window.

Refusing there lasts until you change your browser settings. Declining costs nothing.

[ Connect my wallet ] [ Other ways to connect ]

That last line is section 5.5 point 7 doing its work, in nine words. The two refusals available to the user have different consequences, one lasting and one not, and nobody can infer which is which from the surface alone. The whole body is 49 words against section 5.5 point 6's ceiling of 50, which is the budget this surface actually has.

A primer where the wallet is known from a verified descriptor.

Reconnect Metanet Explorer?

Metanet Explorer is running on this computer, and your keys stay inside it.

Your browser will ask whether this site may reach apps and services here. The only one this site wants is Metanet Explorer. The question appears near the top of your browser window.

[ Reconnect Metanet Explorer ] [ Use my phone instead ]

A primer on the value-control path, where no connect surface carried the explanation. Section 5.2's second disclosure applies: the user pressed Buy, has never connected a wallet, and was never told what connecting is. The two lines are BRC-110 section 6's bound.

Your browser's question is broader than this site needs

Paying here uses a wallet you hold. The account is yours and this site does not keep it.

Your browser will ask whether this site may reach apps and services on this device. The only one this site wants is your wallet.

[ Pay with my wallet ] [ Other ways to pay ]

The second paragraph is the whole of the argument for a wallet rather than an email address, and it is two lines because that is all the evidence supports carrying here. The controls name the user's task, not the plumbing, which is section 5.1 point 2 and section 5.4 point 3 agreeing.

A waiting state while the eliciting request is outstanding. The heading is the one thing the user has to do, so it is the heading.

Look near the top of your browser window

Your browser is asking whether this site may reach apps on this device. The question sits just under the address bar.

Take as long as you need. There is no time limit.

[ Stop waiting ]

A recovery surface in the denied state. This is a section 8 surface and not a primer, so section 5.5 point 6's 50-word ceiling does not bind it. It is longer because it has to teach a procedure, and the sentence discipline still applies.

Your browser is blocking this site from reaching your wallet

A wallet may be running on this computer, but this site cannot see it. Your browser blocks that until you allow it.

You can change this in your browser settings for this site. Look for Apps on device. The control is at the left of the address bar.

You do not have to. A wallet on your phone works instead, and nothing else on this site is affected.

[ Connect with my phone ] [ How to change this setting ]

Two cautions on the examples above. The stated position of the browser's question is accurate for current desktop Chrome and is close enough for desktop Firefox and Safari, and it is wrong on several mobile browsers, which draw the question low rather than high. An application MUST say where the question will actually appear on the platform it is running on, or say nothing about position. Apps on device is likewise the label current Chrome uses, and section 8.2 point 2 forbids guessing it where it cannot be determined.

A surface after the prompt was dismissed. Section 7.6 applies. The user has already seen the browser's question, so it is not described again, and nothing claims to know why it went unanswered.

Your browser's question is still unanswered

Nothing was shared and nothing changed. You can answer it, or connect another way.

[ Ask me again ] [ Use my phone instead ]

Still unanswered is the state rather than the act, per section 7.6 point 3. The second line is section 7.6 point 4: a user who closed a security dialog wants to know whether closing it was enough, and it was. Neither control is weighted, because the application has no view on which the user should pick.

A recovery surface in the denied state. Section 8.2 point 3 puts the alternative first and the settings path second, which reverses the usual advice for the reason given there.

This site cannot reach a wallet on this computer

Your browser is set to block it. Connecting from your phone works instead, and needs nothing changed here.

To undo the block, open the control at the left of the address bar and turn on apps on device.

[ Use my phone instead ] [ Not now ]

No control claims to open settings, because no control can. The instruction is a sentence rather than a link, per section 8.2 point 5. There is no control saying the setting has been changed, because section 8.2 point 4 requires the surface to notice by itself. And the phone route is first because it is the one that works without the user leaving the page, which is section 8.2 point 3's whole argument.

Copy that fails this document.

Allow localhost access to enable BRC-100 substrate discovery on ports 3301-3364.

Fails section 5.5 point 1 four times over, and tells the user nothing about what they get.

We need this permission for a better experience. [Allow (Recommended)] Not now

Fails section 5.2 by promising an uncheckable benefit, section 5.4 point 5 by badging a recommendation, and section 5.5 point 4.

No wallet available over any communication substrate.

Fails section 7.3. The controller knows the permission was denied, and says something else.

Connect your wallet [...] [ Continue ] [ Cancel ]

Fails section 5.4 point 3. Neither control names an outcome, so a user who scans the buttons, which is most users, learns nothing from the surface at all and has to read the body to discover what the two branches are. Cancel is the worse of the two, because it does not distinguish cancelling the browser's question from cancelling the connection from cancelling whatever the user was doing before any of this started.

Your browser will warn you about accessing other apps. Ignore it, we only need your wallet.

Fails section 5.3 point 4 twice and section 5.2's forbidden claims once. It tells the user the browser is overstating the case and invites them to disregard a security control, and "we only need your wallet" is true of the use and false of the grant, which is the collapse that point forbids. The honest form of the same sentence names both: the question covers everything running here, and this site looks only for your wallet.

Click Allow to continue. Blocking is permanent.

Fails three ways. It quotes a control label that will not be present in a browser localised differently from the page, against section 5.3 point 6. It instructs the user which branch to take, against the same point. And it is false: a blocked permission is reversible in browser settings, so a primer that calls it permanent has frightened the user out of a choice that was theirs to make and will not be believed on anything else it said.

Connect your wallet [...] [ Allow ] [ Block ]

Fails section 5.4 point 6 and section 5.7 point 1 together. It borrows both of the browser's control labels and so reads as the browser's dialog, while the refusal it offers is reversible and the one it imitates is not. The user who presses this Block believes they have done something they have not, and the user who presses the real one a moment later believes they are repeating themselves.

References