22
33## Single provider
44
5- When there is only one section per invocation point, no lift is needed — the
6- dispatch short-circuits before the lift is ever called. Provide a no-op lift
7- as a placeholder:
5+ When there is only one provider per invocation point, no policy is needed —
6+ the dispatch short-circuits before the policy is ever called. Provide a no-op
7+ policy as a placeholder:
88
99``` ts
1010import { M } from ' @endo/patterns' ;
11- import { sheafify , makeSection , noopLift } from ' @metamask/kernel-utils ' ;
11+ import { sheafify , makeHandler , noopPolicy } from ' @metamask/sheaves ' ;
1212
1313const priceGuard = M .interface (' PriceService' , {
1414 getPrice: M .callWhen (M .await (M .string ())).returns (M .await (M .number ())),
1515});
1616
17- const priceExo = makeSection (' PriceService' , priceGuard , {
17+ const priceHandler = makeHandler (' PriceService' , priceGuard , {
1818 async getPrice(token ) {
1919 return fetchPrice (token );
2020 },
2121});
2222
2323const sheaf = sheafify ({
2424 name: ' PriceService' ,
25- sections : [{ exo: priceExo }],
25+ providers : [{ handler: priceHandler }],
2626});
2727
28- const section = sheaf .getSection ({ guard: priceGuard , lift: noopLift });
29- // section is a dispatch exo ; call it like any capability
28+ const section = sheaf .getSection ({ guard: priceGuard , lift: noopPolicy });
29+ // section is a dispatch handler ; call it like any capability
3030const price = await E (section ).getPrice (' ETH' );
3131```
3232
33- ## Multiple providers with a lift
33+ ## Multiple providers with a policy
3434
35- When the stalk at a given invocation point contains more than one germ, the
36- sheaf calls the lift to choose. The lift is an ` async function* ` coroutine that
37- yields candidates in preference order; it receives accumulated errors as the
38- argument to each subsequent ` .next() ` so it can adapt its ranking.
35+ When more than one candidate matches an invocation, the sheaf calls the policy
36+ to choose. The policy is an ` async function* ` coroutine that yields candidates
37+ in preference order; it receives accumulated errors as the argument to each
38+ subsequent ` .next() ` so it can adapt its ranking.
3939
4040The idiomatic pattern is a generator that ` yield* ` s candidates filtered by
4141metadata, expressing priority tiers in source order:
4242
4343``` ts
44- import { sheafify , constant } from ' @metamask/kernel-utils ' ;
45- import type { Lift } from ' @metamask/kernel-utils ' ;
44+ import { sheafify , constant } from ' @metamask/sheaves ' ;
45+ import type { Policy } from ' @metamask/sheaves ' ;
4646
4747type WalletMeta = { mode: ' fast' | ' reliable' };
4848
49- const preferFast: Lift <WalletMeta > = async function * (germs ) {
50- yield * germs .filter ((g ) => g .metadata ?.mode === ' fast' );
51- yield * germs .filter ((g ) => g .metadata ?.mode === ' reliable' );
49+ const preferFast: Policy <WalletMeta > = async function * (candidates ) {
50+ yield * candidates .filter ((c ) => c .metadata ?.mode === ' fast' );
51+ yield * candidates .filter ((c ) => c .metadata ?.mode === ' reliable' );
5252};
5353
5454const sheaf = sheafify <WalletMeta >({
5555 name: ' Wallet' ,
56- sections : [
57- { exo: fastExo , metadata: constant ({ mode: ' fast' }) },
58- { exo: reliableExo , metadata: constant ({ mode: ' reliable' }) },
56+ providers : [
57+ { handler: fastHandler , metadata: constant ({ mode: ' fast' }) },
58+ { handler: reliableHandler , metadata: constant ({ mode: ' reliable' }) },
5959 ],
6060});
6161
@@ -65,12 +65,12 @@ const section = sheaf.getSection({ guard: clientGuard, lift: preferFast });
6565
6666The sheaf drives the generator: it primes it with ` gen.next([]) ` , calls the
6767chosen candidate, then passes any thrown errors back as ` gen.next(errors) ` so
68- the lift can adapt before yielding the next candidate.
68+ the policy can adapt before yielding the next candidate.
6969
7070Use the ` constant ` , ` source ` , or ` callable ` helpers to build metadata specs:
7171
7272``` ts
73- import { constant , source , callable } from ' @metamask/kernel-utils ' ;
73+ import { constant , source , callable } from ' @metamask/sheaves ' ;
7474
7575// static value known at construction time
7676constant ({ mode: ' fast' });
@@ -86,10 +86,11 @@ callable((args) => ({ cost: Number(args[0]) > 9000 ? 'high' : 'low' }));
8686
8787## Discoverable sections
8888
89- ` getDiscoverableSection ` works like ` getSection ` but the returned exo exposes
90- its guard — it can be introspected by the caller to discover what methods and
91- argument shapes it accepts. Use this when the recipient needs to advertise
92- capability to a third party. It requires a ` schema ` map describing each method:
89+ ` getDiscoverableSection ` works like ` getSection ` but the returned handler
90+ exposes its guard — it can be introspected by the caller to discover what
91+ methods and argument shapes it accepts. Use this when the recipient needs to
92+ advertise capability to a third party. It requires a ` schema ` map describing
93+ each method:
9394
9495``` ts
9596import type { MethodSchema } from ' @metamask/kernel-utils' ;
@@ -108,60 +109,56 @@ const section = sheaf.getDiscoverableSection({
108109` getSection ` is the non-discoverable variant (no ` schema ` required).
109110
110111` getGlobalSection ` and ` getDiscoverableGlobalSection ` derive the guard
111- automatically from the union of all presheaf sections . They are ` @deprecated `
112- as a nudge toward explicit guards once the caller knows the section set —
113- explicit guards make the capability's scope visible at the call site. When
114- sections are assembled dynamically (e.g., rebuilt at runtime from a set of
115- grants that changes) and the union guard isn't known until after ` sheafify `
116- runs, the global variants are the right choice.
112+ automatically from the union of all providers . They are ` @deprecated ` as a
113+ nudge toward explicit guards once the caller knows the provider set — explicit
114+ guards make the capability's scope visible at the call site. When providers are
115+ assembled dynamically (e.g., rebuilt at runtime from a set of grants that
116+ changes) and the union guard isn't known until after ` sheafify ` runs, the
117+ global variants are the right choice.
117118
118- ## Remote sections
119+ ## Remote providers
119120
120- ` makeRemoteSection ` wraps a CapTP remote reference as a ` PresheafSection ` ,
121- fetching the remote's guard once at construction and forwarding all calls via
122- ` E() ` . This lets you mix local exos and remote capabilities in the same sheaf:
121+ ` makeRemoteSection ` wraps a CapTP remote reference as a ` Provider ` , fetching
122+ the remote's guard once at construction and forwarding all calls via ` E() ` .
123+ This lets you mix local handlers and remote capabilities in the same sheaf:
123124
124125``` ts
125- import {
126- makeSection ,
127- makeRemoteSection ,
128- constant ,
129- } from ' @metamask/kernel-utils' ;
126+ import { makeHandler , makeRemoteSection , constant } from ' @metamask/sheaves' ;
130127
131- const remoteSection = await makeRemoteSection (
132- ' RemoteWallet' , // name for the wrapper exo
128+ const remoteProvider = await makeRemoteSection (
129+ ' RemoteWallet' , // name for the wrapper handler
133130 remoteCapRef , // CapTP reference
134131 constant ({ mode: ' remote' }), // optional metadata
135132);
136133
137134const sheaf = sheafify ({
138135 name: ' Mixed' ,
139- sections : [localSection , remoteSection ],
136+ providers : [localProvider , remoteProvider ],
140137});
141138```
142139
143- ## Lift composition
140+ ## Policy composition
144141
145- ` @metamask/kernel-utils ` exports helpers for building lifts from composable
146- parts, useful when lift logic would otherwise be duplicated across callers:
142+ ` @metamask/sheaves ` exports helpers for building policies from composable
143+ parts, useful when policy logic would otherwise be duplicated across callers:
147144
148145``` ts
149146import {
150- proxyLift ,
147+ proxyPolicy ,
151148 withFilter ,
152149 withRanking ,
153150 fallthrough ,
154- } from ' @metamask/kernel-utils ' ;
151+ } from ' @metamask/sheaves ' ;
155152```
156153
157- - ** ` withRanking(comparator)(inner) ` ** — sort germs by comparator before
154+ - ** ` withRanking(comparator)(inner) ` ** — sort candidates by comparator before
158155 passing to ` inner `
159- - ** ` withFilter(predicate)(inner) ` ** — remove germs that fail ` predicate `
156+ - ** ` withFilter(predicate)(inner) ` ** — remove candidates that fail ` predicate `
160157 before passing to ` inner `
161- - ** ` fallthrough(liftA, liftB ) ` ** — try all candidates from ` liftA ` first;
162- if all fail, try ` liftB `
163- - ** ` proxyLift (gen)` ** — forward yielded candidates up and error arrays down
158+ - ** ` fallthrough(policyA, policyB ) ` ** — try all candidates from ` policyA `
159+ first; if all fail, try ` policyB `
160+ - ** ` proxyPolicy (gen)` ** — forward yielded candidates up and error arrays down
164161 to an already-started generator; useful when you need to add logic between
165162 yields (logging, counting, conditional abort). For simple sequential
166- composition (` fallthrough ` , ` withFilter ` ) you do not need ` proxyLift ` —
163+ composition (` fallthrough ` , ` withFilter ` ) you do not need ` proxyPolicy ` —
167164 ` yield* ` forwards ` .next(value) ` to the delegated iterator automatically.
0 commit comments