Contracts and capabilities
Every app hands the shell a contract on connect. It is a single declaration of how your app participates in the platform. It has four parts.
The four fields
Section titled “The four fields”provides— the intents and surfaces your app offers to others. Intent declarations carry a version and JSON schemas for their payload and result; surface declarations carry a name and the contexts they can be hosted in.consumes— the intents your app intends to invoke on others, with a minimum version. This is how the platform knows your app depends on a capability before it ever calls it.subscribes— the event topics you listen to, such assession.changedandtheme.changed.permissions— the platform capabilities you intend to use, such asnotify.toastorsurface.embed.
It is advisory, not enforcement
Section titled “It is advisory, not enforcement”This is the load-bearing idea. The contract is delivered to the shell, and the shell sources app capabilities from it — discovery, wiring, the dashboard’s list of available surfaces, which app provides which intent. But the contract is not a security boundary:
- A
requiredPermissionon a provided intent or surface is inert. It does not gate anything. - The contract describes intent; the provider’s backend authorizes every actual call.
So declare your contract honestly because the platform reasons about it, not because it protects you. The protection lives one layer down, at each app’s backend. For the authorization story an app author actually touches, see Advisory auth vs the backend gate.
Why declare what you consume
Section titled “Why declare what you consume”Declaring consumes and subscribes looks redundant — you could just call invoke and subscribe
at runtime. Declaring them up front lets the platform see the dependency graph between apps: who needs
whom, and at which versions. That is what makes a capability removal or a version bump a reviewable
change rather than a runtime surprise.