@volter/world-core 3.0.9 → 3.0.10

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.
@@ -113,11 +113,41 @@ export type DerivedFetch = ((request: Request) => Promise<Response>) & {
113
113
  upgrade?: WebSocketUpgrade;
114
114
  /** The workspace screens it draws, its lanes' too (`GET /twin`'s `screens`). */
115
115
  workspaces?(): Workspace[];
116
+ /** Whether it lays out frames of the World's board (`semantics/board.ts`). */
117
+ boards?: boolean;
118
+ /** Whether a built screen of it takes a URL: a board frame it draws. */
119
+ draws?(url: string): boolean;
116
120
  };
117
121
  /** A workspace screen a pack draws, as `GET /twin` lists it: its id and path (Viewing a World). */
118
122
  export type Workspace = {
119
123
  id: string;
120
124
  path: string;
121
125
  };
126
+ /** A frame of the World's board (architecture, "The board"): one thing of the vendor's where a person sees it, as the
127
+ * vendor's pack lays out its default board (`semantics/board.ts`), the editorial choice of which views of the vendor a
128
+ * person keeps open (a Worker's site, a repository's page, a Jira board). `GET /twin/board` lists them. */
129
+ export type BoardFrame = {
130
+ /** stable within the vendor, whatever the World's ids: what a saved board names the frame by */
131
+ id: string;
132
+ /** what it is, in the vendor's own word (a site, a repository, a board) */
133
+ kind: string;
134
+ title: string;
135
+ /** the vendor's container it is grouped under (an account, an organization, a project); `aka`, the ids it was known
136
+ * by before (an account a deploy adopted), so a board that included it under one still holds it */
137
+ section: {
138
+ id: string;
139
+ title: string;
140
+ aka?: string[];
141
+ };
142
+ /** where the vendor shows it: an absolute URL on the vendor's host, or on a hostname the vendor serves for its customer */
143
+ url: string;
144
+ /** the records whose changes are this frame's changes */
145
+ covers: Array<{
146
+ type: string;
147
+ id: string;
148
+ }>;
149
+ /** set by the kernel, never the pack: whether a built screen of the vendor's (any of its lanes') draws the url */
150
+ drawn?: boolean;
151
+ };
122
152
  export declare function createDerivedFetch(options: DerivedFetchOptions): DerivedFetch;
123
153
  export {};
@@ -28,7 +28,7 @@ export type { MultipartPart } from './multipart.js';
28
28
  export declare const bindSemantics: (m: Parameters<typeof bindAny>[0], handlers: Record<string, Handler>, scope?: CoreScope) => Record<string, DerivedHandler>;
29
29
  export { createPackFetch, createVendorFetch, type LanePart, type PackFetchOptions, type PackParts, type PackScenario } from './pack-fetch.js';
30
30
  export { createDerivedFetch } from './derived.js';
31
- export type { DerivedCall, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedSurface } from './derived.js';
31
+ export type { DerivedCall, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedSurface, BoardFrame } from './derived.js';
32
32
  export { coreFor, crossCutting, derivedRequestScopes, vendorError } from './derived-core.js';
33
33
  export { answerVendorErrors, RefusedWriteError } from './head.js';
34
34
  export { GraphqlError, type GraphqlPart, type GraphqlResolver } from './graphql-wire.js';
@@ -1,5 +1,5 @@
1
1
  import { type DerivedManifest, type Handler, type HandlerContext, type VendorManifest } from './derived-core.js';
2
- import { type DerivedFetch, type DerivedOwner, type DerivedSurface, type Workspace } from './derived.js';
2
+ import { type DerivedFetch, type DerivedOwner, type DerivedSurface, type Workspace, type BoardFrame } from './derived.js';
3
3
  import { type PackScenarioAdapter } from './scenario.js';
4
4
  import { type SocketEngine } from './sockets.js';
5
5
  import { type GraphqlPart } from './graphql-wire.js';
@@ -39,6 +39,8 @@ export type PackParts = {
39
39
  };
40
40
  /** `semantics/sockets.ts`: each socket's engine, by the id the manifest's `sockets` gives it (sockets.ts). */
41
41
  sockets?: Record<string, SocketEngine<HandlerContext>>;
42
+ /** `semantics/board.ts`: the vendor's frames on the World's board, read from its state (`GET /twin/board`). */
43
+ board?: (ctx: HandlerContext) => BoardFrame[] | Promise<BoardFrame[]>;
42
44
  };
43
45
  /** A pack's scenario (`semantics/scenario.ts` exports `scenario`): the adapter the kernel's engine reads the World's
44
46
  * scenario document with, the operations it decides a turn of, and the request an operation is to it (undefined when
@@ -52,6 +54,8 @@ export type PackScenario<Req = any> = {
52
54
  export type LanePart = {
53
55
  fetch: ((request: Request) => Promise<Response>) & {
54
56
  serves?: (method: string, path: string) => boolean;
57
+ boards?: boolean;
58
+ draws?: (url: string) => boolean;
55
59
  };
56
60
  manifest: {
57
61
  doors?: ReadonlyArray<{
@@ -211,7 +211,17 @@ export function createPackFetch(parts, options = {}) {
211
211
  // the workspaces a person can be shown (Viewing a World): each built workspace screen's id and path, the pack's own
212
212
  // and its lanes'
213
213
  const workspaces = () => [...(m.screens ?? []).filter((s) => s.kind === 'workspace' && s.status === 'done' && parts.screens?.[s.id]).map((s) => ({ id: s.id, path: s.path })), ...lanesWorkspaces(parts.lanes ?? {})];
214
- // a context the kernel opens for what no surface operation names: a door, a screen, the clock
214
+ /** Whether a built screen of this pack takes a url: its host one the screen names, its path under the screen's. */
215
+ const drawsUrl = (at) => {
216
+ try {
217
+ const u = new URL(at);
218
+ return screens.some((s) => Boolean(s.host(u.hostname.toLowerCase())) && Boolean(s.path(u.pathname.replace(/\/+$/, '') || '/')));
219
+ }
220
+ catch {
221
+ return false;
222
+ }
223
+ };
224
+ // a context the kernel opens for what no surface operation names: a door, a screen, the clock, the board
215
225
  const open = (request, id, method, path, params) => contextFor(m, { request, operation: { id, method, path, class: method === 'GET' ? 'retrieve' : 'action' }, params }, scope);
216
226
  const refusedReadOnly = () => vendorError(m, m.readOnly);
217
227
  const prefix = m.pathPrefix ? new RegExp(`^(?:${m.pathPrefix})(?=/)`) : undefined;
@@ -246,6 +256,15 @@ export function createPackFetch(parts, options = {}) {
246
256
  // the discovery door is the pack's own, whichever lane would take its path
247
257
  const asked = new URL(arrived.url).pathname.replace(/\/+$/, '') || '/';
248
258
  const discovery = arrived.method === 'GET' && m.discovery !== undefined && (asked === '/twin' || asked === '/twin/scenario');
259
+ // the board is read from the state as it stands, before anything else runs (the clock, a lane, the API): a read,
260
+ // whoever asks, each frame drawn when a built screen takes its url; a pack that lays out none has an empty board
261
+ if (arrived.method === 'GET' && asked === '/twin/board') {
262
+ if (!parts.board)
263
+ return Response.json({ frames: [] });
264
+ const request = withHeaders(arrived, new Headers([...arrived.headers, [READ_ONLY_REQUEST_HEADER, '1']]));
265
+ const frames = await parts.board(await open(request, 'board', 'GET', '/twin/board', {}));
266
+ return Response.json({ frames: frames.map((f) => ({ ...f, drawn: drawsUrl(f.url) })) });
267
+ }
249
268
  const toLane = discovery ? undefined : lane?.(arrived);
250
269
  if (toLane)
251
270
  return toLane(arrived);
@@ -400,7 +419,7 @@ export function createPackFetch(parts, options = {}) {
400
419
  async (asked) => engineOf()?.serve(asked)) : undefined;
401
420
  // what serves each operation: the pack's own, and each lane's
402
421
  const owners = () => ({ ...api.owners(), ...lanesOwners(parts.lanes ?? {}) });
403
- return derivedRequestScopes(m, Object.assign(served, { owners, serves, workspaces, ...(upgrade ? { upgrade } : {}) }));
422
+ return derivedRequestScopes(m, Object.assign(served, { owners, serves, workspaces, boards: Boolean(parts.board), draws: drawsUrl, ...(upgrade ? { upgrade } : {}) }));
404
423
  }
405
424
  /** The vendor's gateway over its lanes: the lane a request goes to (a door to the lane that declares it, then the first
406
425
  * route whose conditions all hold, then the default), behind the gateway's CORS; undefined when none takes it. */
@@ -456,6 +475,22 @@ export function createVendorFetch(manifest, lanes) {
456
475
  const lane = laneRouter(manifest.vendor, manifest.lanes, lanes);
457
476
  return Object.assign(async (request) => {
458
477
  const path = new URL(request.url).pathname.replace(/\/+$/, '') || '/';
478
+ // the vendor's board is the frames of the lanes that lay one out, each drawn when any lane's screen takes its url
479
+ if (request.method === 'GET' && path === '/twin/board') {
480
+ const frames = [];
481
+ for (const l of Object.values(lanes)) {
482
+ if (!l.fetch.boards)
483
+ continue;
484
+ try {
485
+ const answer = await l.fetch(new Request(request.url, { headers: request.headers }));
486
+ if (answer.ok)
487
+ frames.push(...((await answer.json()).frames ?? []));
488
+ }
489
+ catch { /* a lane whose board does not answer lays out nothing */ }
490
+ }
491
+ const draws = (url) => Object.values(lanes).some((l) => l.fetch.draws?.(url) ?? false);
492
+ return Response.json({ frames: frames.map((f) => ({ ...f, drawn: draws(f.url) })) });
493
+ }
459
494
  if (request.method === 'GET' && path === '/twin' && manifest.discovery) {
460
495
  // the vendor's screens are its lanes' (a dashboard drawn by one lane is the vendor's)
461
496
  const screens = lanesWorkspaces(lanes);
@@ -8,7 +8,7 @@ export { isReadOnlyRequest, READ_ONLY_REQUEST_HEADER, ReadOnlyRequestError, runA
8
8
  export { compileSurface, createDerivedFetch, matchOperation } from './derived.js';
9
9
  export { currentTraceparent, deliveryTraceHeaders, newTraceparent, parseTraceparent, runWithRequestTrace, runWithTraceparent, TRACEPARENT_HEADER, traceparentForDelivery, validTraceparent } from './trace-context.js';
10
10
  export type { Traceparent } from './trace-context.js';
11
- export type { DerivedCall, DerivedCoreOutcome, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedOwner, DerivedSurface } from './derived.js';
11
+ export type { DerivedCall, DerivedCoreOutcome, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedOwner, DerivedSurface, BoardFrame } from './derived.js';
12
12
  export { authRefusal, bindSemantics, coreFor, crossCutting, flagOf, derivedRequestScopes, observeTransitions, resourcesOfType as twinResourcesOfType, semanticsContext, stateOf, transitionFor, parseBracketForm, readParams, render as renderDerived, serveCore, sse, vendorError } from './derived-core.js';
13
13
  export { deliverEvents, fillEnvelope, signEvent, signEventAll, verifyEvent } from './events.js';
14
14
  export { equalSecrets, hmac, jwks, jwtDecode, jwtSign, jwtVerify, keyId, lettersFrom, md5, sha256, SIGNING_ALGORITHMS, uuidFrom } from './signing.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volter/world-core",
3
- "version": "3.0.9",
3
+ "version": "3.0.10",
4
4
  "description": "The kernel of Volter World: one log per twin, branches as pointers, checkpoints, the fold that keeps a twin current, the head that performs a write against the vendor, references, and the git plane. A twin package builds on it; the runtime serves it.",
5
5
  "keywords": [
6
6
  "twin",
package/src/derived.ts CHANGED
@@ -198,11 +198,35 @@ export type DerivedFetch = ((request: Request) => Promise<Response>) & {
198
198
  upgrade?: WebSocketUpgrade;
199
199
  /** The workspace screens it draws, its lanes' too (`GET /twin`'s `screens`). */
200
200
  workspaces?(): Workspace[];
201
+ /** Whether it lays out frames of the World's board (`semantics/board.ts`). */
202
+ boards?: boolean;
203
+ /** Whether a built screen of it takes a URL: a board frame it draws. */
204
+ draws?(url: string): boolean;
201
205
  };
202
206
 
203
207
  /** A workspace screen a pack draws, as `GET /twin` lists it: its id and path (Viewing a World). */
204
208
  export type Workspace = { id: string; path: string };
205
209
 
210
+ /** A frame of the World's board (architecture, "The board"): one thing of the vendor's where a person sees it, as the
211
+ * vendor's pack lays out its default board (`semantics/board.ts`), the editorial choice of which views of the vendor a
212
+ * person keeps open (a Worker's site, a repository's page, a Jira board). `GET /twin/board` lists them. */
213
+ export type BoardFrame = {
214
+ /** stable within the vendor, whatever the World's ids: what a saved board names the frame by */
215
+ id: string;
216
+ /** what it is, in the vendor's own word (a site, a repository, a board) */
217
+ kind: string;
218
+ title: string;
219
+ /** the vendor's container it is grouped under (an account, an organization, a project); `aka`, the ids it was known
220
+ * by before (an account a deploy adopted), so a board that included it under one still holds it */
221
+ section: { id: string; title: string; aka?: string[] };
222
+ /** where the vendor shows it: an absolute URL on the vendor's host, or on a hostname the vendor serves for its customer */
223
+ url: string;
224
+ /** the records whose changes are this frame's changes */
225
+ covers: Array<{ type: string; id: string }>;
226
+ /** set by the kernel, never the pack: whether a built screen of the vendor's (any of its lanes') draws the url */
227
+ drawn?: boolean;
228
+ };
229
+
206
230
  export function createDerivedFetch(options: DerivedFetchOptions): DerivedFetch {
207
231
  const handlers = options.handlers ?? {};
208
232
  const known = new Set(options.surface.operations.map((o) => o.id));
package/src/index.ts CHANGED
@@ -39,7 +39,7 @@ export const bindSemantics = (m: Parameters<typeof bindAny>[0], handlers: Record
39
39
  // ── the derived fetch ──────────────────────────────────────────────────────────────────────────
40
40
  export { createPackFetch, createVendorFetch, type LanePart, type PackFetchOptions, type PackParts, type PackScenario } from './pack-fetch.ts';
41
41
  export { createDerivedFetch } from './derived.ts';
42
- export type { DerivedCall, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedSurface } from './derived.ts';
42
+ export type { DerivedCall, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedSurface, BoardFrame } from './derived.ts';
43
43
  export { coreFor, crossCutting, derivedRequestScopes, vendorError } from './derived-core.ts';
44
44
  export { answerVendorErrors, RefusedWriteError } from './head.ts';
45
45
  // a GraphQL API's resolvers (`semantics/graphql.ts`), and the error one answers with the vendor's type
package/src/pack-fetch.ts CHANGED
@@ -10,7 +10,7 @@ import { TWIN_PREFIX_HEADER } from './twin-fetch.ts';
10
10
  import { PREFIX_PARAMS_HEADER } from './derived.ts';
11
11
  import { withHeaders } from './with-headers.ts';
12
12
  import { authRefusal, bindSemantics, contextFor, LANE_HEADER, SCENARIO_DECISION_HEADER, coreFor, crossCutting, derivedRequestScopes, vendorError, type CoreScope, type DerivedManifest, type ErrorSpec, type Handler, type HandlerContext, type LanesDecl, type VendorManifest } from './derived-core.ts';
13
- import { compileSurface, createDerivedFetch, matchOperation, type DerivedFetch, type DerivedOperation, type DerivedOwner, type DerivedSurface, type Workspace } from './derived.ts';
13
+ import { compileSurface, createDerivedFetch, matchOperation, type DerivedFetch, type DerivedOperation, type DerivedOwner, type DerivedSurface, type Workspace, type BoardFrame } from './derived.ts';
14
14
  import { isReadOnlyRequest, READ_ONLY_REQUEST_HEADER, runAsVendorMove } from './request-scope.ts';
15
15
  import { parseScenarioDocument, ScenarioEngine, ScenarioError, statefulTwinManifest, twinManifest, type PackScenarioAdapter } from './scenario.ts';
16
16
  import { getActiveWorldStore } from './world-store.ts';
@@ -57,6 +57,8 @@ export type PackParts = {
57
57
  graphql?: GraphqlPart<HandlerContext> & { sdl: string };
58
58
  /** `semantics/sockets.ts`: each socket's engine, by the id the manifest's `sockets` gives it (sockets.ts). */
59
59
  sockets?: Record<string, SocketEngine<HandlerContext>>;
60
+ /** `semantics/board.ts`: the vendor's frames on the World's board, read from its state (`GET /twin/board`). */
61
+ board?: (ctx: HandlerContext) => BoardFrame[] | Promise<BoardFrame[]>;
60
62
  };
61
63
 
62
64
  /** A pack's scenario (`semantics/scenario.ts` exports `scenario`): the adapter the kernel's engine reads the World's
@@ -66,7 +68,7 @@ export type PackParts = {
66
68
  export type PackScenario<Req = any> = { adapter: PackScenarioAdapter<Req>; operations: ReadonlyArray<string>; request: (ctx: HandlerContext) => Req | undefined };
67
69
 
68
70
  /** A lane as its vendor's fetch is given it: its own pack fetch, and its manifest (the doors it declares). */
69
- export type LanePart = { fetch: ((request: Request) => Promise<Response>) & { serves?: (method: string, path: string) => boolean }; manifest: { doors?: ReadonlyArray<{ method: string; path: string }> } };
71
+ export type LanePart = { fetch: ((request: Request) => Promise<Response>) & { serves?: (method: string, path: string) => boolean; boards?: boolean; draws?: (url: string) => boolean }; manifest: { doors?: ReadonlyArray<{ method: string; path: string }> } };
70
72
 
71
73
  /** Where a pack serves: its World's root, whether it was started read-only, the World instant when a caller pins it, the
72
74
  * World's managed Postgres the runtime binds a pack declaring `managedDatabase` to (a handler's `ctx.engine`), and the
@@ -245,7 +247,11 @@ export function createPackFetch(parts: PackParts, options: PackFetchOptions = {}
245
247
  // the workspaces a person can be shown (Viewing a World): each built workspace screen's id and path, the pack's own
246
248
  // and its lanes'
247
249
  const workspaces = (): Workspace[] => [...(m.screens ?? []).filter((s) => s.kind === 'workspace' && s.status === 'done' && parts.screens?.[s.id]).map((s) => ({ id: s.id, path: s.path })), ...lanesWorkspaces(parts.lanes ?? {})];
248
- // a context the kernel opens for what no surface operation names: a door, a screen, the clock
250
+ /** Whether a built screen of this pack takes a url: its host one the screen names, its path under the screen's. */
251
+ const drawsUrl = (at: string): boolean => {
252
+ try { const u = new URL(at); return screens.some((s) => Boolean(s.host(u.hostname.toLowerCase())) && Boolean(s.path(u.pathname.replace(/\/+$/, '') || '/'))); } catch { return false; }
253
+ };
254
+ // a context the kernel opens for what no surface operation names: a door, a screen, the clock, the board
249
255
  const open = (request: Request, id: string, method: string, path: string, params: Record<string, string>): Promise<HandlerContext> =>
250
256
  contextFor(m, { request, operation: { id, method, path, class: method === 'GET' ? 'retrieve' : 'action' } as DerivedOperation, params }, scope);
251
257
  const refusedReadOnly = (): Response => vendorError(m, m.readOnly);
@@ -278,6 +284,14 @@ export function createPackFetch(parts: PackParts, options: PackFetchOptions = {}
278
284
  // the discovery door is the pack's own, whichever lane would take its path
279
285
  const asked = new URL(arrived.url).pathname.replace(/\/+$/, '') || '/';
280
286
  const discovery = arrived.method === 'GET' && m.discovery !== undefined && (asked === '/twin' || asked === '/twin/scenario');
287
+ // the board is read from the state as it stands, before anything else runs (the clock, a lane, the API): a read,
288
+ // whoever asks, each frame drawn when a built screen takes its url; a pack that lays out none has an empty board
289
+ if (arrived.method === 'GET' && asked === '/twin/board') {
290
+ if (!parts.board) return Response.json({ frames: [] });
291
+ const request = withHeaders(arrived, new Headers([...arrived.headers, [READ_ONLY_REQUEST_HEADER, '1']]));
292
+ const frames = await parts.board(await open(request, 'board', 'GET', '/twin/board', {}));
293
+ return Response.json({ frames: frames.map((f) => ({ ...f, drawn: drawsUrl(f.url) })) });
294
+ }
281
295
  const toLane = discovery ? undefined : lane?.(arrived);
282
296
  if (toLane) return toLane(arrived);
283
297
  // only the kernel names a scenario's decision, or a path prefix's parameters
@@ -407,7 +421,7 @@ export function createPackFetch(parts: PackParts, options: PackFetchOptions = {}
407
421
  async (asked) => engineOf()?.serve(asked)) : undefined;
408
422
  // what serves each operation: the pack's own, and each lane's
409
423
  const owners = (): Record<string, DerivedOwner> => ({ ...api.owners(), ...lanesOwners(parts.lanes ?? {}) });
410
- return derivedRequestScopes(m, Object.assign(served, { owners, serves, workspaces, ...(upgrade ? { upgrade } : {}) }));
424
+ return derivedRequestScopes(m, Object.assign(served, { owners, serves, workspaces, boards: Boolean(parts.board), draws: drawsUrl, ...(upgrade ? { upgrade } : {}) }));
411
425
  }
412
426
 
413
427
  /** The vendor's gateway over its lanes: the lane a request goes to (a door to the lane that declares it, then the first
@@ -468,6 +482,19 @@ export function createVendorFetch(manifest: VendorManifest, lanes: Record<string
468
482
  const lane = laneRouter(manifest.vendor, manifest.lanes, lanes);
469
483
  return Object.assign(async (request: Request): Promise<Response> => {
470
484
  const path = new URL(request.url).pathname.replace(/\/+$/, '') || '/';
485
+ // the vendor's board is the frames of the lanes that lay one out, each drawn when any lane's screen takes its url
486
+ if (request.method === 'GET' && path === '/twin/board') {
487
+ const frames: BoardFrame[] = [];
488
+ for (const l of Object.values(lanes)) {
489
+ if (!l.fetch.boards) continue;
490
+ try {
491
+ const answer = await l.fetch(new Request(request.url, { headers: request.headers }));
492
+ if (answer.ok) frames.push(...(((await answer.json()) as { frames?: BoardFrame[] }).frames ?? []));
493
+ } catch { /* a lane whose board does not answer lays out nothing */ }
494
+ }
495
+ const draws = (url: string): boolean => Object.values(lanes).some((l) => l.fetch.draws?.(url) ?? false);
496
+ return Response.json({ frames: frames.map((f) => ({ ...f, drawn: draws(f.url) })) });
497
+ }
471
498
  if (request.method === 'GET' && path === '/twin' && manifest.discovery) {
472
499
  // the vendor's screens are its lanes' (a dashboard drawn by one lane is the vendor's)
473
500
  const screens = lanesWorkspaces(lanes);
package/src/runtime.ts CHANGED
@@ -17,7 +17,7 @@ export { isReadOnlyRequest, READ_ONLY_REQUEST_HEADER, ReadOnlyRequestError, runA
17
17
  export { compileSurface, createDerivedFetch, matchOperation } from './derived.ts';
18
18
  export { currentTraceparent, deliveryTraceHeaders, newTraceparent, parseTraceparent, runWithRequestTrace, runWithTraceparent, TRACEPARENT_HEADER, traceparentForDelivery, validTraceparent } from './trace-context.ts';
19
19
  export type { Traceparent } from './trace-context.ts';
20
- export type { DerivedCall, DerivedCoreOutcome, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedOwner, DerivedSurface } from './derived.ts';
20
+ export type { DerivedCall, DerivedCoreOutcome, DerivedFetch, DerivedFetchOptions, DerivedHandler, DerivedOperation, DerivedOwner, DerivedSurface, BoardFrame } from './derived.ts';
21
21
  export { authRefusal, bindSemantics, coreFor, crossCutting, flagOf, derivedRequestScopes, observeTransitions, resourcesOfType as twinResourcesOfType, semanticsContext, stateOf, transitionFor, parseBracketForm, readParams, render as renderDerived, serveCore, sse, vendorError } from './derived-core.ts';
22
22
  export { deliverEvents, fillEnvelope, signEvent, signEventAll, verifyEvent } from './events.ts';
23
23
  export { equalSecrets, hmac, jwks, jwtDecode, jwtSign, jwtVerify, keyId, lettersFrom, md5, sha256, SIGNING_ALGORITHMS, uuidFrom } from './signing.ts';