@juspay/neurolink 11.29.2 → 11.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/dist/auth/anthropicOAuth.d.ts +50 -0
  3. package/dist/auth/anthropicOAuth.js +78 -0
  4. package/dist/browser/neurolink.min.js +393 -393
  5. package/dist/cli/commands/proxy.d.ts +2 -0
  6. package/dist/cli/commands/proxy.js +284 -4
  7. package/dist/cli/commands/proxyExpose.d.ts +35 -0
  8. package/dist/cli/commands/proxyExpose.js +252 -0
  9. package/dist/cli/commands/proxyPeer.d.ts +29 -0
  10. package/dist/cli/commands/proxyPeer.js +738 -0
  11. package/dist/cli/commands/proxyShare.d.ts +37 -0
  12. package/dist/cli/commands/proxyShare.js +1080 -0
  13. package/dist/cli/parser.js +7 -1
  14. package/dist/proxy/peerStore.d.ts +52 -0
  15. package/dist/proxy/peerStore.js +324 -0
  16. package/dist/proxy/peerTransport.d.ts +38 -0
  17. package/dist/proxy/peerTransport.js +242 -0
  18. package/dist/proxy/proxyPaths.d.ts +8 -0
  19. package/dist/proxy/proxyPaths.js +55 -17
  20. package/dist/proxy/requestLogger.js +8 -0
  21. package/dist/proxy/residentGrants.d.ts +57 -0
  22. package/dist/proxy/residentGrants.js +393 -0
  23. package/dist/proxy/shareAudit.d.ts +81 -0
  24. package/dist/proxy/shareAudit.js +280 -0
  25. package/dist/proxy/shareContext.d.ts +38 -0
  26. package/dist/proxy/shareContext.js +92 -0
  27. package/dist/proxy/shareGate.d.ts +64 -0
  28. package/dist/proxy/shareGate.js +216 -0
  29. package/dist/proxy/shareGrants.d.ts +115 -0
  30. package/dist/proxy/shareGrants.js +590 -0
  31. package/dist/proxy/shareLease.d.ts +101 -0
  32. package/dist/proxy/shareLease.js +192 -0
  33. package/dist/proxy/shareLedger.d.ts +105 -0
  34. package/dist/proxy/shareLedger.js +406 -0
  35. package/dist/proxy/shareListener.d.ts +60 -0
  36. package/dist/proxy/shareListener.js +143 -0
  37. package/dist/proxy/shareNotes.d.ts +97 -0
  38. package/dist/proxy/shareNotes.js +234 -0
  39. package/dist/proxy/sharePolicy.d.ts +110 -0
  40. package/dist/proxy/sharePolicy.js +366 -0
  41. package/dist/proxy/shareProvisioning.d.ts +110 -0
  42. package/dist/proxy/shareProvisioning.js +237 -0
  43. package/dist/proxy/shareReceipts.d.ts +99 -0
  44. package/dist/proxy/shareReceipts.js +303 -0
  45. package/dist/proxy/shareSigning.d.ts +40 -0
  46. package/dist/proxy/shareSigning.js +78 -0
  47. package/dist/server/routes/claudeProxyRoutes.js +1066 -3
  48. package/dist/types/cli.d.ts +61 -0
  49. package/dist/types/proxy.d.ts +781 -0
  50. package/package.json +2 -1
@@ -0,0 +1,366 @@
1
+ /**
2
+ * Peer-sharing admission policy.
3
+ *
4
+ * Pure evaluation, no I/O — every input is passed in, so this module is cheap on
5
+ * the hot path and directly exercisable from a test.
6
+ *
7
+ * The gate set is deliberately **orthogonal and AND-ed**: a grant may carry a
8
+ * headroom floor *and* a window-slice ceiling *and* a model allowlist, and each
9
+ * is checked independently. The effective allowance is therefore the minimum
10
+ * across whatever is configured, which is what lets "share only what I am not
11
+ * using, and never more than a fifth of it" be one grant rather than two
12
+ * competing modes.
13
+ *
14
+ * Evaluation splits in two, because the two halves answer different questions:
15
+ *
16
+ * - `evaluateShareAdmission` — request-level. Is this borrower allowed to ask at
17
+ * all, right now, for this model?
18
+ * - `filterAccountsForGrant` — account-level. Of the lender's accounts, which
19
+ * may serve this borrower? Headroom and slice ceilings live here because they
20
+ * are properties of an individual account's windows, not of the request.
21
+ *
22
+ * @module proxy/sharePolicy
23
+ */
24
+ const HOUR_MS = 3_600_000;
25
+ /** Human-facing text for a refusal. Kept terse — it reaches the borrower. */
26
+ const REFUSAL_MESSAGES = {
27
+ missing_token: "No share token was presented.",
28
+ unknown_token: "Share token is not recognized.",
29
+ malformed_token: "Share token is malformed.",
30
+ paused: "The lender has paused this share.",
31
+ revoked: "This share has been revoked.",
32
+ expired: "This share has expired.",
33
+ out_of_window: "This share is outside its allowed hours.",
34
+ model_not_allowed: "This share does not cover the requested model.",
35
+ exhausted: "This share has no credit remaining.",
36
+ rate_limited: "This share's request rate limit was exceeded.",
37
+ concurrency_limited: "This share's concurrent request limit was reached.",
38
+ reserve_floor: "The lender's reserved headroom is in force.",
39
+ spillover_inactive: "This share serves only the lender's spare capacity, and none is spare yet.",
40
+ slice_exhausted: "This share has used its allotted portion of the window.",
41
+ no_capacity: "No lender account can currently serve this share.",
42
+ };
43
+ /**
44
+ * Narrow an admission to its refusing half.
45
+ *
46
+ * A plain `!admission.admitted` check would do this under `strict`, but one of
47
+ * the package's build steps compiles without `strictNullChecks`, where TypeScript
48
+ * declines to narrow a boolean discriminant at all. An explicit predicate holds
49
+ * in both modes.
50
+ */
51
+ export function isShareRefusal(admission) {
52
+ return !admission.admitted;
53
+ }
54
+ export function shareRefusalMessage(reason) {
55
+ return REFUSAL_MESSAGES[reason];
56
+ }
57
+ /** HTTP status for a refusal. 401 is "who are you", 403 is "not you, not ever
58
+ * under this grant", 429 is "not now" — the borrower retries only the last. */
59
+ export function shareRefusalStatus(reason) {
60
+ switch (reason) {
61
+ case "missing_token":
62
+ case "unknown_token":
63
+ case "malformed_token":
64
+ return 401;
65
+ case "paused":
66
+ case "revoked":
67
+ case "expired":
68
+ case "out_of_window":
69
+ case "model_not_allowed":
70
+ return 403;
71
+ default:
72
+ return 429;
73
+ }
74
+ }
75
+ function refuse(reason, options = {}) {
76
+ return {
77
+ admitted: false,
78
+ status: shareRefusalStatus(reason),
79
+ reason,
80
+ message: REFUSAL_MESSAGES[reason],
81
+ ...(options.retryAfterSeconds !== undefined
82
+ ? { retryAfterSeconds: options.retryAfterSeconds }
83
+ : {}),
84
+ ...(options.grant ? { grant: options.grant } : {}),
85
+ };
86
+ }
87
+ /**
88
+ * Is `now` inside the grant's allowed hours?
89
+ *
90
+ * A window whose start hour is greater than its end hour wraps midnight
91
+ * (`21 → 9` means the night shift), which is the common case for lending
92
+ * capacity you are asleep through.
93
+ */
94
+ export function isWithinSchedule(schedule, now) {
95
+ const hour = new Date(now).getHours();
96
+ const { fromHour, toHour } = schedule;
97
+ if (fromHour === toHour) {
98
+ return true;
99
+ }
100
+ return fromHour < toHour
101
+ ? hour >= fromHour && hour < toHour
102
+ : hour >= fromHour || hour < toHour;
103
+ }
104
+ /** Seconds until the schedule next opens, for an honest `Retry-After`. */
105
+ function secondsUntilScheduleOpens(schedule, now) {
106
+ const next = new Date(now);
107
+ next.setMinutes(0, 0, 0);
108
+ for (let ahead = 1; ahead <= 24; ahead += 1) {
109
+ next.setHours(next.getHours() + 1);
110
+ if (isWithinSchedule(schedule, next.getTime())) {
111
+ return Math.max(1, Math.round((next.getTime() - now) / 1000));
112
+ }
113
+ }
114
+ return 3600;
115
+ }
116
+ /**
117
+ * Does the requested model fall inside the allowlist?
118
+ *
119
+ * Entries are matched as case-insensitive substrings so a grant can name a tier
120
+ * (`sonnet`) rather than having to track every dated model id.
121
+ */
122
+ export function isModelAllowed(models, model) {
123
+ if (!models || models.length === 0) {
124
+ return true;
125
+ }
126
+ if (!model) {
127
+ return false;
128
+ }
129
+ const normalized = model.toLowerCase();
130
+ return models.some((entry) => normalized.includes(entry.toLowerCase()));
131
+ }
132
+ /**
133
+ * Request-level admission.
134
+ *
135
+ * Order matters: identity and lifecycle first (they are permanent refusals),
136
+ * then scope, then the transient limits that carry a `Retry-After`. A borrower
137
+ * that is told "paused" must not also be told "slow down".
138
+ */
139
+ export function evaluateShareAdmission(input) {
140
+ const { grant, now, model, counters, coinBalance } = input;
141
+ if (grant.state !== "active") {
142
+ const reason = grant.state === "paused"
143
+ ? "paused"
144
+ : grant.state === "revoked"
145
+ ? "revoked"
146
+ : "expired";
147
+ return refuse(reason, { grant });
148
+ }
149
+ if (grant.gates.notAfter !== undefined && grant.gates.notAfter <= now) {
150
+ return refuse("expired", { grant });
151
+ }
152
+ if (grant.gates.schedule && !isWithinSchedule(grant.gates.schedule, now)) {
153
+ return refuse("out_of_window", {
154
+ grant,
155
+ retryAfterSeconds: secondsUntilScheduleOpens(grant.gates.schedule, now),
156
+ });
157
+ }
158
+ if (!isModelAllowed(grant.gates.models, model)) {
159
+ return refuse("model_not_allowed", { grant });
160
+ }
161
+ const rate = grant.gates.rate;
162
+ if (rate?.concurrency !== undefined &&
163
+ counters.inFlight >= rate.concurrency) {
164
+ return refuse("concurrency_limited", { grant, retryAfterSeconds: 1 });
165
+ }
166
+ if (rate?.perMinute !== undefined &&
167
+ counters.requestsInLastMinute >= rate.perMinute) {
168
+ return refuse("rate_limited", { grant, retryAfterSeconds: 60 });
169
+ }
170
+ if (grant.entitlement.ledger === "coins" &&
171
+ (coinBalance ?? grant.entitlement.coins ?? 0) <= 0) {
172
+ return refuse("exhausted", { grant });
173
+ }
174
+ return { admitted: true, grant };
175
+ }
176
+ /** The slice ceiling in force, taking spillover's own ceiling into account. */
177
+ function effectiveSlicePct(base, spilloverCap) {
178
+ const tighten = (configured) => {
179
+ if (configured === undefined) {
180
+ return spilloverCap;
181
+ }
182
+ if (spilloverCap === undefined) {
183
+ return configured;
184
+ }
185
+ return Math.min(configured, spilloverCap);
186
+ };
187
+ return {
188
+ session: tighten(base?.session5hPct),
189
+ weekly: tighten(base?.weekly7dPct),
190
+ };
191
+ }
192
+ /**
193
+ * Is the account inside its spillover window — close enough to a reset, with
194
+ * little enough consumed, that the remaining capacity would otherwise expire?
195
+ *
196
+ * Unknown reset times fail closed. A spillover grant is a promise about capacity
197
+ * that is *about to be lost*; without a reset time there is no such promise to
198
+ * keep, and guessing would hand out capacity the lender still intends to use.
199
+ */
200
+ export function isSpilloverActive(gates, account, now) {
201
+ const spillover = gates.spillover;
202
+ if (!spillover) {
203
+ return false;
204
+ }
205
+ const windowMs = spillover.beforeResetHours * HOUR_MS;
206
+ const threshold = spillover.whenUtilizationBelowPct / 100;
207
+ const nearWeekly = account.weeklyResetAt !== null &&
208
+ account.weeklyResetAt - now <= windowMs &&
209
+ account.weeklyResetAt > now &&
210
+ account.weeklyUsed !== null &&
211
+ account.weeklyUsed < threshold;
212
+ const nearSession = account.sessionResetAt !== null &&
213
+ account.sessionResetAt - now <= windowMs &&
214
+ account.sessionResetAt > now &&
215
+ account.sessionUsed !== null &&
216
+ account.sessionUsed < threshold;
217
+ return nearWeekly || nearSession;
218
+ }
219
+ /**
220
+ * Split the pool into the accounts this grant may draw on and the rest.
221
+ *
222
+ * An entry in `gates.accounts` matches either the full store key
223
+ * (`anthropic:alice`) or the bare label (`alice`), because operators think in
224
+ * labels and the routing path thinks in keys.
225
+ *
226
+ * Exported because the scope decides more than admission: it is also the
227
+ * denominator of the pool-wide slice, and computing that over accounts the grant
228
+ * can never touch would loosen the ceiling in proportion to how many there are.
229
+ */
230
+ export function accountsInGrantScope(gates, accounts) {
231
+ if (!gates.accounts || gates.accounts.length === 0) {
232
+ return { inScope: [...accounts], outOfScope: [] };
233
+ }
234
+ const allowedKeys = new Set(gates.accounts.map((entry) => entry.trim().toLowerCase()));
235
+ const inScope = [];
236
+ const outOfScope = [];
237
+ for (const account of accounts) {
238
+ const key = account.accountKey.toLowerCase();
239
+ const label = key.includes(":") ? key.slice(key.indexOf(":") + 1) : key;
240
+ if (allowedKeys.has(key) || allowedKeys.has(label)) {
241
+ inScope.push(account);
242
+ }
243
+ else {
244
+ outOfScope.push(account);
245
+ }
246
+ }
247
+ return { inScope, outOfScope };
248
+ }
249
+ /**
250
+ * Decide which of the lender's accounts this grant may draw on.
251
+ *
252
+ * Returning exclusions alongside the survivors is deliberate: when nothing
253
+ * survives, the caller needs to say *why* — "your slice is spent" and "I am
254
+ * holding back my reserve" are different answers, and only one of them will
255
+ * change on its own.
256
+ */
257
+ export function filterAccountsForGrant(grant, accounts, now,
258
+ /**
259
+ * Required, not optional. `gates.maxSlice` is a ceiling on what this grant
260
+ * has already drawn from the pool, and with nothing to compare against the
261
+ * only available answer is "not yet" — so an omitted argument would not relax
262
+ * the ceiling, it would remove it. `readSharePoolWindowUsage` returns zeroed
263
+ * fractions for a grant with no history, which is the honest empty value.
264
+ */
265
+ poolUsage) {
266
+ const gates = grant.gates;
267
+ // Scope first. "The pool" a slice ceiling divides is the set of accounts this
268
+ // grant may draw on at all — not every credential the node happens to hold.
269
+ // Counting the others would inflate the denominator and loosen the ceiling by
270
+ // exactly the ratio between the two sets.
271
+ const { inScope, outOfScope } = accountsInGrantScope(gates, accounts);
272
+ // The pool ceiling is one decision about the whole pool, so it is settled
273
+ // before any account is considered. Spillover's tighter cap applies as soon
274
+ // as any in-scope account is spilling — the borrower is drawing on pooled
275
+ // capacity, not on one credential's clock.
276
+ const anySpillover = inScope.some((account) => isSpilloverActive(gates, account, now));
277
+ const poolSlice = effectiveSlicePct(gates.maxSlice, anySpillover ? gates.spillover?.maxSlicePct : undefined);
278
+ const poolSpent = (poolSlice.session !== undefined &&
279
+ poolUsage.sessionFraction * 100 >= poolSlice.session) ||
280
+ (poolSlice.weekly !== undefined &&
281
+ poolUsage.weeklyFraction * 100 >= poolSlice.weekly);
282
+ if (poolSpent) {
283
+ // Refused everywhere, including on idle accounts. That is what a pool
284
+ // ceiling means: the borrower has had its share of the whole.
285
+ return {
286
+ allowed: [],
287
+ excluded: [
288
+ ...inScope.map((account) => ({
289
+ accountKey: account.accountKey,
290
+ reason: "slice_exhausted",
291
+ })),
292
+ ...outOfScope.map((account) => ({
293
+ accountKey: account.accountKey,
294
+ reason: "no_capacity",
295
+ })),
296
+ ],
297
+ };
298
+ }
299
+ const allowed = [];
300
+ const excluded = outOfScope.map((account) => ({
301
+ accountKey: account.accountKey,
302
+ reason: "no_capacity",
303
+ }));
304
+ for (const account of inScope) {
305
+ const spilloverActive = isSpilloverActive(gates, account, now);
306
+ if (gates.spillover && !spilloverActive) {
307
+ // Not `reserve_floor`: no headroom is being held back, the lender simply
308
+ // has not used enough of this account for its spare capacity to exist
309
+ // yet. Both are transient, but they clear on opposite movements and the
310
+ // borrower is told which one it is waiting on.
311
+ excluded.push({
312
+ accountKey: account.accountKey,
313
+ reason: "spillover_inactive",
314
+ });
315
+ continue;
316
+ }
317
+ const floor = gates.reserveFloor;
318
+ if (floor) {
319
+ const sessionBlocked = floor.session5hPct !== undefined &&
320
+ account.sessionUsed !== null &&
321
+ account.sessionUsed * 100 > 100 - floor.session5hPct;
322
+ const weeklyBlocked = floor.weekly7dPct !== undefined &&
323
+ account.weeklyUsed !== null &&
324
+ account.weeklyUsed * 100 > 100 - floor.weekly7dPct;
325
+ if (sessionBlocked || weeklyBlocked) {
326
+ excluded.push({
327
+ accountKey: account.accountKey,
328
+ reason: "reserve_floor",
329
+ });
330
+ continue;
331
+ }
332
+ }
333
+ // Per-account ceiling, opt-in and independent of the pool one above.
334
+ const slice = effectiveSlicePct(gates.maxSlicePerAccount, spilloverActive ? gates.spillover?.maxSlicePct : undefined);
335
+ const sessionSliceSpent = slice.session !== undefined &&
336
+ account.borrowedSessionFraction * 100 >= slice.session;
337
+ const weeklySliceSpent = slice.weekly !== undefined &&
338
+ account.borrowedWeeklyFraction * 100 >= slice.weekly;
339
+ if (sessionSliceSpent || weeklySliceSpent) {
340
+ excluded.push({
341
+ accountKey: account.accountKey,
342
+ reason: "slice_exhausted",
343
+ });
344
+ continue;
345
+ }
346
+ allowed.push(account.accountKey);
347
+ }
348
+ return { allowed, excluded };
349
+ }
350
+ /**
351
+ * Collapse per-account exclusions into the single reason the borrower is told
352
+ * when nothing survived. A transient cause outranks a structural one so the
353
+ * borrower learns whether waiting is worth anything.
354
+ */
355
+ export function summarizeAccountExclusions(excluded) {
356
+ if (excluded.some((entry) => entry.reason === "reserve_floor")) {
357
+ return "reserve_floor";
358
+ }
359
+ if (excluded.some((entry) => entry.reason === "spillover_inactive")) {
360
+ return "spillover_inactive";
361
+ }
362
+ if (excluded.some((entry) => entry.reason === "slice_exhausted")) {
363
+ return "slice_exhausted";
364
+ }
365
+ return "no_capacity";
366
+ }
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Split-PKCE provisioning — minting a resident credential without ever holding
3
+ * one.
4
+ *
5
+ * The earlier design had the lender complete an authorization and hand the
6
+ * borrower a file containing a live access token and a refresh token. That file
7
+ * is copyable, re-sharable, and exists on disk in plaintext at both ends for as
8
+ * long as anyone forgets to delete it. Nothing about the lease constrains a
9
+ * credential someone else already copied.
10
+ *
11
+ * This splits the flow along the seam PKCE was designed for:
12
+ *
13
+ * 1. The **borrower** generates a verifier and sends only its SHA-256
14
+ * challenge, over its authenticated grant.
15
+ * 2. The **lender** authorizes in their own browser, against their own account,
16
+ * with the borrower's challenge in the URL.
17
+ * 3. The **authorization code** comes back to the lender and is relayed to the
18
+ * borrower.
19
+ * 4. The **borrower** exchanges code + verifier for tokens, on its own machine.
20
+ *
21
+ * The code is worthless to anyone who intercepts it: the token endpoint will not
22
+ * exchange it without the verifier, which never left the borrower. The lender
23
+ * never possesses a token for the credential it just authorized, so there is
24
+ * nothing for it to leak, re-send, or forget to delete.
25
+ *
26
+ * **What this module owns** is the lender's side of that conversation: the
27
+ * pending request, its binding to one grant, its expiry, and the rule that a
28
+ * code is handed over exactly once.
29
+ *
30
+ * @module proxy/shareProvisioning
31
+ */
32
+ import type { ProxyShareProvisionOutcome, ProxyShareProvisionRequest } from "../types/index.js";
33
+ /**
34
+ * How long a challenge stays claimable.
35
+ *
36
+ * Long enough for a lender to notice a request and finish a browser login,
37
+ * short enough that a challenge left lying around is not a standing invitation.
38
+ */
39
+ export declare const PROVISION_REQUEST_TTL_MS = 900000;
40
+ export declare function initShareProvisioning(filePath: string): void;
41
+ /**
42
+ * Narrow an open/authorize outcome to its failing half.
43
+ *
44
+ * One of the package's build steps compiles without `strictNullChecks`, where a
45
+ * boolean discriminant does not narrow. Callers reading `.reason` need this.
46
+ */
47
+ export declare function isProvisionFailure(outcome: ProxyShareProvisionOutcome): outcome is {
48
+ ok: false;
49
+ reason: string;
50
+ };
51
+ /** Is this request still live? Expiry and consumption both retire it. */
52
+ export declare function isProvisionRequestOpen(request: ProxyShareProvisionRequest, now?: number): boolean;
53
+ /**
54
+ * Record a borrower's challenge.
55
+ *
56
+ * One open request per grant: a second one replaces the first rather than
57
+ * queueing, because the borrower that just asked is the one waiting, and an
58
+ * abandoned challenge should not be claimable later by whoever finds it.
59
+ *
60
+ * Rejects anything that is not a well-formed S256 challenge. The lender is about
61
+ * to put this string into an authorization URL against its own account, so it
62
+ * is not the place to be relaxed about input.
63
+ */
64
+ export declare function openProvisionRequest(args: {
65
+ grantId: string;
66
+ codeChallenge: string;
67
+ state: string;
68
+ now?: number;
69
+ }): Promise<ProxyShareProvisionOutcome>;
70
+ /** The open request for a grant, if there is one. */
71
+ export declare function getProvisionRequest(grantId: string, now?: number): Promise<ProxyShareProvisionRequest | undefined>;
72
+ /** Every open request, for a lender deciding which to authorize. */
73
+ export declare function listProvisionRequests(now?: number): Promise<ProxyShareProvisionRequest[]>;
74
+ /**
75
+ * Attach the authorization code the lender's browser produced.
76
+ *
77
+ * The code is bound to the grant that asked for it and to the account the lender
78
+ * authorized against — the same account the drift audit will later reconcile —
79
+ * so a code cannot be redirected to a different grant after the fact.
80
+ */
81
+ export declare function authorizeProvisionRequest(args: {
82
+ grantId: string;
83
+ code: string;
84
+ accountLabel?: string;
85
+ now?: number;
86
+ }): Promise<ProxyShareProvisionOutcome>;
87
+ /**
88
+ * Hand the code to the borrower — once.
89
+ *
90
+ * Single-use is the whole binding: an authorization code that could be claimed
91
+ * twice would let anyone who replayed the call mint a second credential on the
92
+ * lender's account. Consumption is recorded before the value is returned.
93
+ */
94
+ export declare function claimProvisionRequest(grantId: string, now?: number): Promise<{
95
+ status: "ready";
96
+ code: string;
97
+ state: string;
98
+ } | {
99
+ status: "pending";
100
+ } | {
101
+ status: "none";
102
+ }>;
103
+ /** Drop a grant's request — used when the grant itself goes away. */
104
+ export declare function clearProvisionRequest(grantId: string): Promise<void>;
105
+ /**
106
+ * A state value for a borrower to send alongside its challenge.
107
+ *
108
+ * Kept here so both ends agree on the shape `STATE_PATTERN` will accept.
109
+ */
110
+ export declare function generateProvisionState(): string;