The Passes Protocol
This is an early release of Passes.
We invite you to read the documentation and source code, experiment by adding Pass Requests in your apps, and contribute to discussions to help shape the future of Passes.
These docs are under active development, and we'll be continuously publishing updates. We welcome your feedback – please reach out.
The Request ABI Protocol
interface PassesABI {
request: (raw: Uint8Array) => Promise<Uint8Array>;
}
PassesABI
is the protocol used to send raw Pass Requests to the user. On the web (via the Polyfill) it's available at document.passes
.
Envelope Transport Format
// Request message structure
type RequestEnvelopeV0 = {
// Version is always 0 for this envelope version
version: 0;
// The request topic's identifier. This field is run-length encoded and can be up to 256 bytes long
topic: string;
// The raw request body, encoded via the request topic's request body codec
body: Uint8Array;
}
// Result message structure
type ResultEnvelopeV0 =
// The user accepted the request. Body contains the raw result body, encoded via the request topic's result body codec
| { status: 'accepted'; body: Uint8Array }
// The user rejected the request (no additional information is available)
| { status: 'rejected' }
// The Pass Provider doesn't support the requested topic
| { status: 'unsupported' }
// An exception occurred when presenting or accepting the request
| { status: 'exception'; message: string }
This is the standard format for Pass Requests and their results.
A "topic" is a string using reverse-dns notation to uniquely identify a request topic.
This format includes a 1-byte version specifier to provide future-compatibility for changes to the transport encoding.
Request Topic Specs
For apps and Pass Providers to implement support for common Pass Request topics, they need specifications to refer to.
Pass Request specifications will specify:
- Envelope Format (generally, v0 – see above)
- Request Topic ID
- Request Body Codec
- Result Body Codec
- Request Interpretation and Presentation Details
Discussing RFCs
To propose and participate in discussions around Pass Request Topic RFCs, please go to Passes Discussions.
@passes/reqs
RequestTopic
As Request Topic Specs become standard, @passes/reqs
and other community packages will implement RequestTopic
to provide high-level APIs for use in apps.
ABI Implementations
An implementation of the request ABI is needed to present Pass Requests to the user. The request ABI is responsible for routing pass requests to a Pass Provider for presentation to the user.
Some examples of how Pass Requests flow to Pass Providers given different ABI implementations include:
@passes/polyfill
ABI Implementation
Web Extension ABI Implementation
Native Browser ABI Implementation
Request Handlers
Request Handlers are responsible for presenting a rich interpretation of a Pass Request to the user so they can review and then approve or reject it.
Pass Providers
All Pass Requests are sent directly to the user's Pass Provider over the client.
A Pass Provider can be a web or native mobile app. It could even be built into a user's browser or operating system.
If a Pass Provider supports the topic of a Pass Request, it will present it to the user. If not, it can delegate it to a Topic Provider that does support it.
Web Request Handlers
Building a Request Handler on the web that works with the @passes/polyfill
script and the upcoming Passes web extension is simple.
You just need a page served over HTTPS at an arbitrary URI.
- Your page will be opened when a requesting app sends it a Pass Request.
- When your page loads, send a "connect" message to the requesting app in order to await the Pass Request.
- Once you receive the Pass Request, present it to the user for review.
- Finally, send the result back to the requesting app when the user approves or rejects the request.
Communication between the requesting app and your page will happen on the client side via window.postMessage
.
import * as Messaging from '@passes/reqs/messaging';
const { request, origin } = await Messaging.awaitRequest();
const result = await presentRequestToUserAndAwaitResult(request); // < your custom presentation logic
await Messaging.sendResult(result, origin);