@almadar/shell-runtime 0.0.0-stage → 0.1.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.
- package/dist/chunk-2JU7Y4KU.js +21 -0
- package/dist/chunk-46RWK2B5.js +28 -0
- package/dist/chunk-4J2QEIUV.js +78 -0
- package/dist/chunk-4SEK5ER2.js +8 -0
- package/dist/chunk-4ZICQ5PM.js +192 -0
- package/dist/chunk-53IPZXDP.js +76 -0
- package/dist/chunk-5D63EMO5.js +16 -0
- package/dist/chunk-64IH2SMY.js +22 -0
- package/dist/chunk-7SDV3QWR.js +67 -0
- package/dist/chunk-CPSQXEJ6.js +55 -0
- package/dist/chunk-CQP5XAX6.js +173 -0
- package/dist/chunk-CROS2GEX.js +49 -0
- package/dist/chunk-D4XJTBLB.js +217 -0
- package/dist/chunk-D5USD2EX.js +232 -0
- package/dist/chunk-DYOJGLIX.js +25 -0
- package/dist/chunk-ELBLT2HZ.js +1 -0
- package/dist/chunk-EV56K4GB.js +63 -0
- package/dist/chunk-EZZYLTWY.js +1 -0
- package/dist/chunk-FQ6IZMIU.js +10 -0
- package/dist/chunk-FWA5K7Q2.js +48 -0
- package/dist/chunk-HC6ERSAH.js +55 -0
- package/dist/chunk-HLOUDLPI.js +48 -0
- package/dist/chunk-HMK6YMQS.js +135 -0
- package/dist/chunk-HNOAZWFH.js +19 -0
- package/dist/chunk-IHQLE5M7.js +62 -0
- package/dist/chunk-IOPUS6Q5.js +15 -0
- package/dist/chunk-JFWFDUTR.js +35 -0
- package/dist/chunk-LZIOTBFX.js +1 -0
- package/dist/chunk-MHYSHSRG.js +54 -0
- package/dist/chunk-MLKGABMK.js +7 -0
- package/dist/chunk-MZKIL5IN.js +74 -0
- package/dist/chunk-NAECVIAR.js +322 -0
- package/dist/chunk-NATGCIVM.js +583 -0
- package/dist/chunk-O57GKTYU.js +30 -0
- package/dist/chunk-ODJCZ27I.js +50 -0
- package/dist/chunk-P53CKOME.js +1 -0
- package/dist/chunk-Q2H75UYT.js +92 -0
- package/dist/chunk-Q7JK4KY7.js +9 -0
- package/dist/chunk-QELZ6TEJ.js +208 -0
- package/dist/chunk-QQRDUMB2.js +40 -0
- package/dist/chunk-RBUMDYFS.js +681 -0
- package/dist/chunk-REPX5QPI.js +57 -0
- package/dist/chunk-SAS5KKCR.js +43 -0
- package/dist/chunk-SKLMWHQD.js +109 -0
- package/dist/chunk-SOQDEPME.js +131 -0
- package/dist/chunk-SWPDU752.js +28 -0
- package/dist/chunk-T775TUCD.js +18 -0
- package/dist/chunk-UBN5JJKZ.js +26 -0
- package/dist/chunk-UJHOUZAL.js +36 -0
- package/dist/chunk-UP6GGGAN.js +34 -0
- package/dist/chunk-VMOBW7RK.js +21 -0
- package/dist/chunk-VNMG7NKY.js +69 -0
- package/dist/chunk-WNPNNYXY.js +22 -0
- package/dist/chunk-XB5GYODW.js +28 -0
- package/dist/chunk-XXWNMJI6.js +15 -0
- package/dist/chunk-YL2SO5TP.js +334 -0
- package/dist/chunk-YO4LWS3I.js +606 -0
- package/dist/chunk-ZAQSS47X.js +157 -0
- package/dist/chunk-ZCQUUJIF.js +129 -0
- package/dist/client/EventTransport.d.ts +131 -0
- package/dist/client/EventTransport.js +2 -0
- package/dist/client/ServerBridge.d.ts +126 -0
- package/dist/client/ServerBridge.js +3 -0
- package/dist/client/awaiting.d.ts +28 -0
- package/dist/client/awaiting.js +2 -0
- package/dist/client/channel-transport.d.ts +69 -0
- package/dist/client/channel-transport.js +2 -0
- package/dist/client/circuit-store.d.ts +76 -0
- package/dist/client/circuit-store.js +4 -0
- package/dist/client/client-kernel.d.ts +113 -0
- package/dist/client/client-kernel.js +1 -0
- package/dist/client/declared-input-dispatch.d.ts +5 -0
- package/dist/client/declared-input-dispatch.js +2 -0
- package/dist/client/inbound-dispatch.d.ts +5 -0
- package/dist/client/inbound-dispatch.js +2 -0
- package/dist/client/local-fold.d.ts +26 -0
- package/dist/client/local-fold.js +2 -0
- package/dist/client/render-sigils.d.ts +24 -0
- package/dist/client/render-sigils.js +2 -0
- package/dist/client/state-book.d.ts +37 -0
- package/dist/client/state-book.js +2 -0
- package/dist/client/trait-mount-error.d.ts +9 -0
- package/dist/client/trait-mount-error.js +2 -0
- package/dist/client/trait-types.d.ts +67 -0
- package/dist/client/trait-types.js +1 -0
- package/dist/credentials/env-vars.d.ts +14 -0
- package/dist/credentials/env-vars.js +3 -0
- package/dist/credentials/scope.d.ts +50 -0
- package/dist/credentials/scope.js +2 -0
- package/dist/credentials/seed.d.ts +21 -0
- package/dist/credentials/seed.js +2 -0
- package/dist/credentials/store.d.ts +110 -0
- package/dist/credentials/store.js +2 -0
- package/dist/effects/in-flight-calls.d.ts +36 -0
- package/dist/effects/in-flight-calls.js +2 -0
- package/dist/effects/on-device-model.d.ts +22 -0
- package/dist/effects/on-device-model.js +2 -0
- package/dist/events/EventBus.d.ts +90 -0
- package/dist/events/EventBus.js +2 -0
- package/dist/events/emit-stamp.d.ts +47 -0
- package/dist/events/emit-stamp.js +2 -0
- package/dist/index-hT1xCdTq.d.ts +46 -0
- package/dist/index.d.ts +60 -0
- package/dist/index.js +59 -0
- package/dist/kernel/beacon.d.ts +32 -0
- package/dist/kernel/beacon.js +2 -0
- package/dist/kernel/decode.d.ts +15 -0
- package/dist/kernel/decode.js +2 -0
- package/dist/kernel/engine.d.ts +94 -0
- package/dist/kernel/engine.js +11 -0
- package/dist/kernel/frame-applier.d.ts +43 -0
- package/dist/kernel/frame-applier.js +2 -0
- package/dist/kernel/host.d.ts +95 -0
- package/dist/kernel/host.js +9 -0
- package/dist/kernel/http.d.ts +302 -0
- package/dist/kernel/http.js +6 -0
- package/dist/kernel/lane.d.ts +28 -0
- package/dist/kernel/lane.js +2 -0
- package/dist/kernel/oauth-effects.d.ts +25 -0
- package/dist/kernel/oauth-effects.js +7 -0
- package/dist/kernel/oauth-port.d.ts +31 -0
- package/dist/kernel/oauth-port.js +2 -0
- package/dist/kernel/os-port.d.ts +133 -0
- package/dist/kernel/os-port.js +2 -0
- package/dist/kernel/program-effects.d.ts +65 -0
- package/dist/kernel/program-effects.js +2 -0
- package/dist/kernel/wire.d.ts +66 -0
- package/dist/kernel/wire.js +1 -0
- package/dist/loader/http-loader.d.ts +111 -0
- package/dist/loader/http-loader.js +2 -0
- package/dist/loader/lazy-page.d.ts +12 -0
- package/dist/loader/lazy-page.js +2 -0
- package/dist/loader/schema-loader.d.ts +160 -0
- package/dist/loader/schema-loader.js +1 -0
- package/dist/persistence/native-memory.d.ts +28 -0
- package/dist/persistence/native-memory.js +2 -0
- package/dist/runtime/effects/composition/compose-behaviors.d.ts +58 -0
- package/dist/runtime/effects/composition/compose-behaviors.js +4 -0
- package/dist/runtime/effects/composition/event-wiring.d.ts +38 -0
- package/dist/runtime/effects/composition/event-wiring.js +2 -0
- package/dist/runtime/effects/composition/index.d.ts +5 -0
- package/dist/runtime/effects/composition/index.js +6 -0
- package/dist/runtime/effects/composition/layout-strategy.d.ts +35 -0
- package/dist/runtime/effects/composition/layout-strategy.js +2 -0
- package/dist/runtime/effects/composition/pipe.d.ts +25 -0
- package/dist/runtime/effects/composition/pipe.js +2 -0
- package/dist/runtime/entities/mockStoreSeed.d.ts +56 -0
- package/dist/runtime/entities/mockStoreSeed.js +3 -0
- package/dist/runtime/entities/seedBrowserStore.d.ts +28 -0
- package/dist/runtime/entities/seedBrowserStore.js +2 -0
- package/dist/runtime/entities/std-mock-seed.d.ts +87 -0
- package/dist/runtime/entities/std-mock-seed.js +2 -0
- package/dist/runtime/evaluation/local-store-transport.d.ts +68 -0
- package/dist/runtime/evaluation/local-store-transport.js +18 -0
- package/dist/runtime/evaluation/residence-transport.d.ts +15 -0
- package/dist/runtime/evaluation/residence-transport.js +2 -0
- package/dist/runtime/evaluation/routed-persistence.d.ts +9 -0
- package/dist/runtime/evaluation/routed-persistence.js +2 -0
- package/dist/runtime/events/identity/routing.d.ts +84 -0
- package/dist/runtime/events/identity/routing.js +2 -0
- package/dist/runtime/time/TickScheduler.d.ts +77 -0
- package/dist/runtime/time/TickScheduler.js +3 -0
- package/dist/runtime/time/cron.d.ts +25 -0
- package/dist/runtime/time/cron.js +2 -0
- package/dist/runtime/time/duration.d.ts +20 -0
- package/dist/runtime/time/duration.js +2 -0
- package/dist/runtime/traits/OrbitalTraitParsing.d.ts +34 -0
- package/dist/runtime/traits/OrbitalTraitParsing.js +2 -0
- package/dist/runtime/traits/listen-targets.d.ts +16 -0
- package/dist/runtime/traits/listen-targets.js +3 -0
- package/dist/runtime/traits/trait-index.d.ts +35 -0
- package/dist/runtime/traits/trait-index.js +3 -0
- package/dist/runtime/types.d.ts +574 -0
- package/dist/runtime/types.js +2 -0
- package/dist/service/default-call-service.d.ts +23 -0
- package/dist/service/default-call-service.js +3 -0
- package/dist/service/service-provider.d.ts +37 -0
- package/dist/service/service-provider.js +2 -0
- package/package.json +46 -3
- package/README.md +0 -3
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { PageFactField, BrowserPageFacts, PersistenceAdapter, ServiceParams, EventPayload, JsonValue, UserContext, ServiceHostPorts, OnDeviceModelPorts, BrowserTabPort, EventStreamItem } from '@almadar/core';
|
|
2
|
+
import { InFlightCalls } from '../effects/in-flight-calls.js';
|
|
3
|
+
import { ServiceCallContext } from '../service/service-provider.js';
|
|
4
|
+
import { ProgramEffectName, ProgramEffectOutcome } from './program-effects.js';
|
|
5
|
+
import { HttpPorts } from './http.js';
|
|
6
|
+
import { CallSiteWire, Settled, SubstrateFailureWire, IoRequestWire, IoAnswerWire } from '@almadar/core/kernel-wire';
|
|
7
|
+
import { OsHostPort, OsCompletionPort, OsCompletionEvent } from './os-port.js';
|
|
8
|
+
import './beacon.js';
|
|
9
|
+
import '../credentials/store.js';
|
|
10
|
+
import './decode.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The host half of the kernel path: the I/O the kernel asks for, answered with the runtime's own
|
|
14
|
+
* adapters. Persistence goes through the `PersistenceAdapter` (`@almadar/db`), `call-service` through the
|
|
15
|
+
* injected provider (or the mock / integrations default the JS stage uses), substrate operators through
|
|
16
|
+
* the program host. Nothing here decides an execution step.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** `call-service`, as the host answers it: the host's handler, mock mode, or the integrations default. */
|
|
20
|
+
type KernelCallService = (service: string, action: string, params: ServiceParams | undefined, context: ServiceCallContext | undefined) => Promise<EventPayload | null>;
|
|
21
|
+
/** A follow-on step's `call-service` outcome, run later as a dispatch of its own on `traitName`. */
|
|
22
|
+
interface DeferredCallOutcome {
|
|
23
|
+
orbital: string;
|
|
24
|
+
traitName: string;
|
|
25
|
+
event: string;
|
|
26
|
+
payload: EventPayload | undefined;
|
|
27
|
+
entityId: string | undefined;
|
|
28
|
+
originClientId: string | undefined;
|
|
29
|
+
user: UserContext | undefined;
|
|
30
|
+
locale: string | undefined;
|
|
31
|
+
}
|
|
32
|
+
interface SubstrateStreamSource {
|
|
33
|
+
subscribe(message: (value: JsonValue) => void, ended: () => void): () => void;
|
|
34
|
+
}
|
|
35
|
+
interface KernelHostPorts {
|
|
36
|
+
pageFacts?: (fields: readonly PageFactField[]) => BrowserPageFacts;
|
|
37
|
+
persistence: PersistenceAdapter;
|
|
38
|
+
callService: KernelCallService;
|
|
39
|
+
/** The program host, read per call: a host wires it lazily. */
|
|
40
|
+
programEffect: () => ((op: ProgramEffectName, args: readonly JsonValue[], context?: Pick<ServiceCallContext, 'principal' | 'role'>) => Promise<ProgramEffectOutcome>) | undefined;
|
|
41
|
+
inFlightCalls: InFlightCalls;
|
|
42
|
+
/** The running app lent to one `call-service` provider as the caller. */
|
|
43
|
+
servicePorts: (caller: {
|
|
44
|
+
orbital: string;
|
|
45
|
+
trait: string;
|
|
46
|
+
}, user: UserContext | undefined, message: (payload: EventPayload) => void, assertReentry?: () => void) => ServiceHostPorts;
|
|
47
|
+
/** Deliver one live message of a running call (`emit.onMessage`) to the requesting tab only, never in-band. */
|
|
48
|
+
deliverLive: (site: {
|
|
49
|
+
orbital: string;
|
|
50
|
+
trait: string;
|
|
51
|
+
event: string;
|
|
52
|
+
}, payload: EventPayload, originClientId: string | undefined) => void;
|
|
53
|
+
/** Read per call: the sink a follow-on call's outcome runs through, absent when the host cannot deliver it to the tab. */
|
|
54
|
+
deferCallOutcome: () => ((call: DeferredCallOutcome) => void) | undefined;
|
|
55
|
+
/** The `http` effect's ports (kernel builder, secrets, egress); absent, an `http` ask fails as unavailable. */
|
|
56
|
+
http?: HttpPorts;
|
|
57
|
+
/** The on-device model and embedder; absent, a `browser/prompt` or `browser/embed` ask fails `unconfigured`. */
|
|
58
|
+
onDevice?: OnDeviceModelPorts;
|
|
59
|
+
/** The browser's tabs for the `browser/tab-*` effects; absent, a tab ask fails `unavailable`. */
|
|
60
|
+
tabs?: BrowserTabPort;
|
|
61
|
+
/** The `os` effect's host (Node: `createNodeOsHost` from `@almadar/shell-node`); absent, every `os` ask is denied, as the native host does with none. */
|
|
62
|
+
os?: OsHostPort;
|
|
63
|
+
/** What the kernel decides about a deferred `os` call (which ops defer, the event an outcome fires); absent, every `os` ask is answered in place. */
|
|
64
|
+
osCompletions?: OsCompletionPort;
|
|
65
|
+
substrateStream?: (op: string, args: readonly JsonValue[], scope: KernelAnswerScope) => SubstrateStreamSource | undefined;
|
|
66
|
+
substrateMessage?: (site: CallSiteWire, key: string, value: JsonValue) => OsCompletionEvent | null;
|
|
67
|
+
substrateCompletion?: (site: CallSiteWire, key: string, op: string, args: readonly JsonValue[], outcome: Settled<JsonValue, SubstrateFailureWire>) => OsCompletionEvent | null;
|
|
68
|
+
/** The host clock in epoch milliseconds, answering the kernel's `clock` ask; absent, the system clock. */
|
|
69
|
+
now?: () => number;
|
|
70
|
+
}
|
|
71
|
+
/** What one dispatch brings to its answers. */
|
|
72
|
+
interface KernelAnswerScope {
|
|
73
|
+
/** The orbital the request is addressed to. */
|
|
74
|
+
orbital: string;
|
|
75
|
+
/** The viewer the dispatch runs as; a substrate operator is called as them. */
|
|
76
|
+
user?: UserContext;
|
|
77
|
+
/** The requesting tab. */
|
|
78
|
+
originClientId?: string;
|
|
79
|
+
locale?: string;
|
|
80
|
+
entityId?: string;
|
|
81
|
+
/** Runs `work` with the host's event queue released (a service call must not hold the next event). */
|
|
82
|
+
outsideEventQueue?: <T>(work: () => Promise<T>) => Promise<T>;
|
|
83
|
+
onStream?: (item: EventStreamItem) => void;
|
|
84
|
+
assertReentry?: () => void;
|
|
85
|
+
}
|
|
86
|
+
declare function writeRows(persistence: PersistenceAdapter, request: Extract<IoRequestWire, {
|
|
87
|
+
kind: 'writeRows';
|
|
88
|
+
}>): Promise<IoAnswerWire>;
|
|
89
|
+
/** Tell the kernel what the adapter pushes down for each entity type, once, before the first dispatch. */
|
|
90
|
+
declare function declareCapabilities(persistence: PersistenceAdapter, declare: (entityType: string, queryJson: string, writeJson: string) => void, entityTypes: readonly string[]): void;
|
|
91
|
+
/** Answer one request of the kernel; a thrown adapter error becomes the request's declared failure. */
|
|
92
|
+
declare function answerRequest(ports: KernelHostPorts, request: IoRequestWire, scope: KernelAnswerScope): Promise<IoAnswerWire>;
|
|
93
|
+
|
|
94
|
+
export { answerRequest, declareCapabilities, writeRows };
|
|
95
|
+
export type { DeferredCallOutcome, KernelAnswerScope, KernelCallService, KernelHostPorts, SubstrateStreamSource };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { answerRequest, declareCapabilities, writeRows } from '../chunk-NATGCIVM.js';
|
|
2
|
+
import '../chunk-HNOAZWFH.js';
|
|
3
|
+
import '../chunk-YO4LWS3I.js';
|
|
4
|
+
import '../chunk-MZKIL5IN.js';
|
|
5
|
+
import '../chunk-FWA5K7Q2.js';
|
|
6
|
+
import '../chunk-VMOBW7RK.js';
|
|
7
|
+
import '../chunk-RBUMDYFS.js';
|
|
8
|
+
import '../chunk-HLOUDLPI.js';
|
|
9
|
+
import '../chunk-MLKGABMK.js';
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
import { HttpFailurePayload, JsonValue, HttpStreamEvent, RuntimeValue, CredentialPayload, HttpOAuthFailureCode, HttpOAuthFailureReason, HttpCall } from '@almadar/core';
|
|
2
|
+
export { HttpCall } from '@almadar/core';
|
|
3
|
+
import { BeaconDeliveryPorts } from './beacon.js';
|
|
4
|
+
import { CredentialStore } from '../credentials/store.js';
|
|
5
|
+
export { decodeOAuthAsk } from './decode.js';
|
|
6
|
+
import { IoRequestWire, OAuthAsk, OAuthReply, HttpResponseWire, HttpFailureWire, HttpRequestWire } from '@almadar/core/kernel-wire';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The one TypeScript half of the `http` effect: the host side that moves the bytes the Rust request builder
|
|
10
|
+
* (`@almadar/kernel`, wasm) produced. Both the kernel host (`host.ts`) and the interpreter (`EffectExecutor`)
|
|
11
|
+
* call it; nothing here builds a request, frames a stream or shapes a payload — the wasm exports do.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The pure half of `oauth-authorize` (`@almadar/kernel` `oauthAuthorizePlan` / `oauthAuthorizeBuild` / `oauthFailure`);
|
|
16
|
+
* a kernel build without them cannot run the effect.
|
|
17
|
+
*/
|
|
18
|
+
interface OAuthAuthorizeKernel {
|
|
19
|
+
/** Parses the client and options: `{ plan, clientId: { name, scope }, issuer, metadata }`; throws the effect's failure message. */
|
|
20
|
+
oauthAuthorizePlan(clientJson: string, optionsJson: string): string;
|
|
21
|
+
/** `{ ok: { authUrl, state, grant } }`, `{ failure: OAuthEffectFailurePayload }` or `{ refused: string }`. */
|
|
22
|
+
oauthAuthorizeBuild(planJson: string, clientId: string, metadataJson: string, stateBase64: string, verifierBase64: string): string;
|
|
23
|
+
/** The mock backend's `{ authUrl, state, grant }` from a plan and the drawn state bytes. */
|
|
24
|
+
oauthAuthorizeMockBuild(planJson: string, stateBase64: string): string;
|
|
25
|
+
/** The failure payload `{ error, code, reason }` of a closed reason. */
|
|
26
|
+
oauthFailure(reason: string): string;
|
|
27
|
+
}
|
|
28
|
+
/** The `@almadar/kernel` module-level exports the `http` effect uses; each takes and returns JSON text. */
|
|
29
|
+
interface HttpKernel extends Partial<OAuthAuthorizeKernel> {
|
|
30
|
+
httpDriverStart(callJson: string, egressJson: string): string;
|
|
31
|
+
httpDriverResume(driverJson: string, answerJson: string): string;
|
|
32
|
+
isPublicAddress(ip: string): boolean;
|
|
33
|
+
/** Frames a chunk of a stream (`{ events, carry }`); each event carries `key`. The call's driver is not needed. */
|
|
34
|
+
frameStream(framing: StreamFramingWire, key: string | null, chunk: string, carry: string): string;
|
|
35
|
+
/** The events the unterminated tail in `carry` makes at end of body. */
|
|
36
|
+
frameStreamFinish(framing: StreamFramingWire, key: string | null, carry: string): string;
|
|
37
|
+
/** Releases what the kernel holds for a call that ends before its final step (cancelled, aborted, thrown). */
|
|
38
|
+
httpDriverDrop(driverJson: string): void;
|
|
39
|
+
}
|
|
40
|
+
type StreamFramingWire = Extract<IoRequestWire, {
|
|
41
|
+
kind: 'httpStream';
|
|
42
|
+
}>['framing'];
|
|
43
|
+
/** How a stream's body is framed, and the key each framed event echoes. */
|
|
44
|
+
interface StreamFrame {
|
|
45
|
+
framing: StreamFramingWire;
|
|
46
|
+
key: string | null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The host's secret store: a credential NAME in, its value out; `set` keeps a minted value (an OAuth2 token) for `ttlMs`.
|
|
50
|
+
* `principal` is the signed-in user's id for a user-scoped credential (the kernel sets it from the dispatch's `@user`,
|
|
51
|
+
* never the program); absent, the credential is app-wide.
|
|
52
|
+
*/
|
|
53
|
+
interface HttpSecrets {
|
|
54
|
+
get(name: string, principal?: string): Promise<string | undefined>;
|
|
55
|
+
/** `ttlMs` of 0 forgets the value. */
|
|
56
|
+
set(name: string, value: string, ttlMs: number, principal?: string): Promise<void>;
|
|
57
|
+
/** Replace the stored credential with `value`, durably (a rotated refresh token). A host without one cannot rotate. */
|
|
58
|
+
rotate?(name: string, value: string, principal?: string): Promise<void>;
|
|
59
|
+
/** Drop the credential, the minted value and the stored one. */
|
|
60
|
+
forget(name: string, principal?: string): Promise<void>;
|
|
61
|
+
/** Keep `value` as the credential until it is forgotten, creating it when absent (an OAuth connection's tokens): unlike `rotate` it needs no existing entry. `label` is a non-secret account name stored beside it, never the value. */
|
|
62
|
+
persist?(name: string, value: string, principal?: string, label?: string): Promise<void>;
|
|
63
|
+
/** The non-secret account label stored beside the credential; absent when its row carries none. */
|
|
64
|
+
label?(name: string, principal?: string): Promise<string | undefined>;
|
|
65
|
+
/** Keep a one-use value (a pending OAuth grant) where every instance of the deployment can take it: the credential store's adapter when it shares one-use values, else the minted tier. */
|
|
66
|
+
hold?(name: string, value: string, ttlMs: number, principal?: string): Promise<void>;
|
|
67
|
+
/** Remove and return a held or minted value in one step, the single read of a one-use value. */
|
|
68
|
+
take?(name: string, principal?: string): Promise<string | undefined>;
|
|
69
|
+
/** Whether `persist` keeps a value on this host. */
|
|
70
|
+
durable?(): Promise<boolean>;
|
|
71
|
+
}
|
|
72
|
+
/** The credential-store key of one user's credential. */
|
|
73
|
+
declare function userCredentialKey(principal: string, name: string): string;
|
|
74
|
+
/** Where a host name points: its addresses, and whether the name already is one. */
|
|
75
|
+
interface ResolvedHost {
|
|
76
|
+
literal: boolean;
|
|
77
|
+
addresses: readonly string[];
|
|
78
|
+
}
|
|
79
|
+
interface PinnedInit {
|
|
80
|
+
method: string;
|
|
81
|
+
headers: Array<[string, string]>;
|
|
82
|
+
body?: Uint8Array<ArrayBuffer>;
|
|
83
|
+
redirect: 'manual';
|
|
84
|
+
signal?: AbortSignal;
|
|
85
|
+
}
|
|
86
|
+
/** The part of a fetch response the exchange reads. */
|
|
87
|
+
interface PinnedResponse {
|
|
88
|
+
status: number;
|
|
89
|
+
headers: {
|
|
90
|
+
entries(): IterableIterator<[string, string]>;
|
|
91
|
+
};
|
|
92
|
+
body: {
|
|
93
|
+
getReader(): {
|
|
94
|
+
read(): Promise<{
|
|
95
|
+
done: boolean;
|
|
96
|
+
value?: Uint8Array;
|
|
97
|
+
}>;
|
|
98
|
+
cancel?(): Promise<void>;
|
|
99
|
+
releaseLock?(): void;
|
|
100
|
+
};
|
|
101
|
+
} | null;
|
|
102
|
+
arrayBuffer(): Promise<ArrayBuffer>;
|
|
103
|
+
}
|
|
104
|
+
/** Fetch with the connection pinned to `address`, the one that was checked (no resolve-then-connect race). */
|
|
105
|
+
type PinnedFetch = (url: URL, init: PinnedInit, address: string) => Promise<PinnedResponse>;
|
|
106
|
+
/** CSPRNG output: `bytes` random bytes. */
|
|
107
|
+
type RandomSource = (bytes: number) => Uint8Array;
|
|
108
|
+
/**
|
|
109
|
+
* The host's raw credential store and mode flag, answered to the kernel's `credentialStore*` and `credentialMode*`
|
|
110
|
+
* asks. It decides nothing: the role gate, the declared-name check, the masking and the mode check are the kernel's.
|
|
111
|
+
*/
|
|
112
|
+
interface CredentialAdminPort {
|
|
113
|
+
/** Whether the store can encrypt and the service and name of every stored row; `null` when the host holds no store. */
|
|
114
|
+
list(): Promise<{
|
|
115
|
+
enabled: boolean;
|
|
116
|
+
entries: Array<{
|
|
117
|
+
service: string;
|
|
118
|
+
name: string;
|
|
119
|
+
}>;
|
|
120
|
+
} | null>;
|
|
121
|
+
/** The stored value of credential `name`, from the store only. */
|
|
122
|
+
read(name: string): Promise<string | null>;
|
|
123
|
+
write(service: string, name: string, value: string): Promise<void>;
|
|
124
|
+
/** Whether a stored row existed. */
|
|
125
|
+
remove(name: string): Promise<boolean>;
|
|
126
|
+
rotate(): Promise<{
|
|
127
|
+
rotated: number;
|
|
128
|
+
alreadyCurrent: number;
|
|
129
|
+
unreadable: number;
|
|
130
|
+
}>;
|
|
131
|
+
/** The mode flag; `null` when the host keeps none. */
|
|
132
|
+
mode(): Promise<string | null>;
|
|
133
|
+
/** Switch the flag; the host may refuse. The mode in force afterwards. */
|
|
134
|
+
setMode(mode: string): Promise<string>;
|
|
135
|
+
}
|
|
136
|
+
interface HttpPorts {
|
|
137
|
+
kernel: () => Promise<HttpKernel>;
|
|
138
|
+
/** The host CSPRNG `random-bytes` and the driver's `Random` ask draw from. */
|
|
139
|
+
random: RandomSource;
|
|
140
|
+
/** The program's declared `egress` origins. */
|
|
141
|
+
egress: readonly string[];
|
|
142
|
+
secrets: HttpSecrets;
|
|
143
|
+
/** The credential store and mode flag the credential administration effects ask; absent, those asks fail unavailable. */
|
|
144
|
+
credentials?: CredentialAdminPort;
|
|
145
|
+
fetch: PinnedFetch;
|
|
146
|
+
/** Looks a host up for the public-address check; `null` where the host cannot resolve a name (a browser). */
|
|
147
|
+
resolve: ((host: string) => Promise<ResolvedHost>) | null;
|
|
148
|
+
/** The host's beacon queue and keepalive fetch; absent, a `browser/beacon` call fails `unavailable`. */
|
|
149
|
+
beacon?: BeaconDeliveryPorts;
|
|
150
|
+
/** What an `oauth-client` call and the OAuth effects persist; absent, they fail `store-unavailable`. */
|
|
151
|
+
oauth?: OAuthPort;
|
|
152
|
+
}
|
|
153
|
+
interface HttpPortsOptions {
|
|
154
|
+
kernel: () => Promise<HttpKernel>;
|
|
155
|
+
random?: RandomSource;
|
|
156
|
+
egress: readonly string[];
|
|
157
|
+
secrets?: HttpSecrets;
|
|
158
|
+
/** Defaults to the installed credential store and mode flag. */
|
|
159
|
+
credentials?: CredentialAdminPort;
|
|
160
|
+
fetch?: PinnedFetch;
|
|
161
|
+
resolve?: (host: string) => Promise<ResolvedHost>;
|
|
162
|
+
/** What `oauth-client` calls and the OAuth effects persist; absent, they fail `store-unavailable`. */
|
|
163
|
+
oauth?: OAuthPort;
|
|
164
|
+
}
|
|
165
|
+
interface BrowserHttpPortsOptions {
|
|
166
|
+
kernel: () => Promise<HttpKernel>;
|
|
167
|
+
/** The program's declared `egress` origins. */
|
|
168
|
+
egress: readonly string[];
|
|
169
|
+
/** Defaults to the global `fetch`. */
|
|
170
|
+
fetch?: (url: string, init: RequestInit) => Promise<PinnedResponse & Response>;
|
|
171
|
+
/** Defaults to `navigator.sendBeacon` (text/plain Blob) when the page has one, and the global `fetch`. */
|
|
172
|
+
beacon?: BeaconDeliveryPorts;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* What an OAuth flow asks its host to keep (pending grants, connections, the subject index, discovered metadata,
|
|
176
|
+
* the clock). `principal` is the dispatch's signed-in user, set by the kernel and never by the program.
|
|
177
|
+
*/
|
|
178
|
+
interface OAuthPort {
|
|
179
|
+
answer(ask: OAuthAsk, principal: string | undefined): Promise<OAuthReply>;
|
|
180
|
+
}
|
|
181
|
+
/** The loud, coded error for a host that gave the `http` effect no ports. */
|
|
182
|
+
declare class HttpUnavailableError extends Error {
|
|
183
|
+
readonly code = "HTTP_KERNEL_UNAVAILABLE";
|
|
184
|
+
constructor(detail: string);
|
|
185
|
+
}
|
|
186
|
+
/** A failed `http` effect: its payload is what the `emit.failure` route carries. */
|
|
187
|
+
declare class HttpEffectFailure extends Error {
|
|
188
|
+
readonly payload: HttpFailurePayload;
|
|
189
|
+
constructor(payload: HttpFailurePayload);
|
|
190
|
+
}
|
|
191
|
+
/** Where the secrets' durable credentials live: the store a host installed, and how a name resolves through it. */
|
|
192
|
+
interface HttpSecretsHost {
|
|
193
|
+
store(): Promise<CredentialStore | null>;
|
|
194
|
+
resolve(name: string, principal: string | undefined): Promise<string | undefined>;
|
|
195
|
+
}
|
|
196
|
+
/** In-process secrets: minted values with an expiry, then the credential store the host holds (by default the one the host installed). */
|
|
197
|
+
declare function createHttpSecrets(now?: () => number, host?: HttpSecretsHost): HttpSecrets;
|
|
198
|
+
/** The credential store and mode flag the host installed, as the kernel's raw asks. */
|
|
199
|
+
declare function createCredentialAdminPort(): CredentialAdminPort;
|
|
200
|
+
/** Bytes from the platform CSPRNG. */
|
|
201
|
+
declare const systemRandom: RandomSource;
|
|
202
|
+
/** The most bytes one `random-bytes` may ask for (the kernel's `RANDOM_BYTES_MAX`). */
|
|
203
|
+
declare const RANDOM_BYTES_MAX = 1024;
|
|
204
|
+
/** Standard padded base64 (the wire form of a `Random` answer). */
|
|
205
|
+
declare function base64Standard(bytes: Uint8Array): string;
|
|
206
|
+
/** URL-safe base64 without padding (the `random-bytes` value; the kernel's `codec::base64url_encode`). */
|
|
207
|
+
declare function base64Url(bytes: Uint8Array): string;
|
|
208
|
+
/**
|
|
209
|
+
* `random-bytes`: the success payload for `bytes` drawn from the host CSPRNG; a bad count or key is the effect's
|
|
210
|
+
* failure. A keyed call echoes its `key` beside the `value`.
|
|
211
|
+
*/
|
|
212
|
+
declare function randomBytesPayload(ports: Pick<HttpPorts, 'random'>, bytes: RuntimeValue | undefined, key?: RuntimeValue): {
|
|
213
|
+
value: string;
|
|
214
|
+
key?: string;
|
|
215
|
+
};
|
|
216
|
+
/** `credential-status`: a bare name selects the viewer; an explicit slot selects its declared scope. */
|
|
217
|
+
declare function credentialStatusPayload(ports: Pick<HttpPorts, 'secrets'>, credential: RuntimeValue | undefined, principal: string | undefined): Promise<CredentialPayload>;
|
|
218
|
+
/** `credential-forget`: drops the signed-in viewer's credential; `{ connected: false }`. */
|
|
219
|
+
declare function credentialForgetPayload(ports: Pick<HttpPorts, 'secrets'>, credential: RuntimeValue | undefined, principal: string | undefined): Promise<{
|
|
220
|
+
connected: false;
|
|
221
|
+
label: string;
|
|
222
|
+
}>;
|
|
223
|
+
/** The Node half of the server `http` ports: name resolution and the address-pinned fetch (`@almadar/shell-node` installs it). */
|
|
224
|
+
interface NetPort {
|
|
225
|
+
resolve: (host: string) => Promise<ResolvedHost>;
|
|
226
|
+
fetch: PinnedFetch;
|
|
227
|
+
}
|
|
228
|
+
declare function installNetPort(port: NetPort): void;
|
|
229
|
+
declare function createHttpPorts(options: HttpPortsOptions): HttpPorts;
|
|
230
|
+
/**
|
|
231
|
+
* Ports for a client-site `http` (a call with no `auth`): the same kernel driver and exchange as the server,
|
|
232
|
+
* over the browser's `fetch`. A browser cannot resolve a name or pin a connection, so there is no
|
|
233
|
+
* public-address check; the program's `egress` (the driver refuses any other origin) and the browser's own
|
|
234
|
+
* CORS rules bound what the call reaches.
|
|
235
|
+
*/
|
|
236
|
+
declare function createBrowserHttpPorts(options: BrowserHttpPortsOptions): HttpPorts;
|
|
237
|
+
/** What one exchange came to; a cancelled exchange is the caller's abort signal, never an outcome. */
|
|
238
|
+
type Exchange = {
|
|
239
|
+
kind: 'reply';
|
|
240
|
+
response: HttpResponseWire;
|
|
241
|
+
} | {
|
|
242
|
+
kind: 'failure';
|
|
243
|
+
failure: HttpFailureWire;
|
|
244
|
+
};
|
|
245
|
+
/** Send one built request after its requested retry delay and read the whole reply. */
|
|
246
|
+
declare function sendHttp(ports: HttpPorts, request: HttpRequestWire, signal?: AbortSignal, delayMs?: number): Promise<Exchange>;
|
|
247
|
+
/**
|
|
248
|
+
* Send one built request and hand each framed event of the body to `onEvent` as it arrives; the reply that
|
|
249
|
+
* ends the exchange carries an empty body. Framing, and the `key` each event echoes, are the kernel's
|
|
250
|
+
* (`frameStream`, `frameStreamFinish`) over the ask's `framing` and `key`.
|
|
251
|
+
*/
|
|
252
|
+
declare function streamHttp(ports: HttpPorts, request: HttpRequestWire, stream: StreamFrame, onEvent: (event: HttpStreamEvent) => void, signal?: AbortSignal): Promise<Exchange>;
|
|
253
|
+
/** How a host took one beacon, as the driver's `beacon` answer carries it; a fetch that threw is a failure. */
|
|
254
|
+
type BeaconSettled = {
|
|
255
|
+
ok: {
|
|
256
|
+
via: 'queue';
|
|
257
|
+
} | {
|
|
258
|
+
via: 'fetch';
|
|
259
|
+
status: number;
|
|
260
|
+
} | {
|
|
261
|
+
via: 'unavailable';
|
|
262
|
+
message: string;
|
|
263
|
+
};
|
|
264
|
+
} | {
|
|
265
|
+
error: {
|
|
266
|
+
kind: 'failed';
|
|
267
|
+
message: string;
|
|
268
|
+
};
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* Hand one built beacon request to the host's beacon port. Cancelling stops the wait only: the queue and the
|
|
272
|
+
* fetch the browser already has are never aborted, and a late completion is dropped.
|
|
273
|
+
*/
|
|
274
|
+
declare function sendBeaconRequest(ports: HttpPorts, request: HttpRequestWire, signal?: AbortSignal): Promise<BeaconSettled>;
|
|
275
|
+
|
|
276
|
+
type HttpOutcome = {
|
|
277
|
+
ok: JsonValue;
|
|
278
|
+
} | {
|
|
279
|
+
error: HttpFailurePayload;
|
|
280
|
+
};
|
|
281
|
+
interface HttpRunOptions {
|
|
282
|
+
signal?: AbortSignal;
|
|
283
|
+
/** The dispatch's signed-in user id: whose credential a `scope: "user"` ask names (never set by the program). */
|
|
284
|
+
principal?: string | undefined;
|
|
285
|
+
/** Receives each framed event of a `stream` call. */
|
|
286
|
+
onMessage?: (event: HttpStreamEvent) => void;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
declare function isOAuthCode(value: JsonValue | undefined): value is HttpOAuthFailureCode;
|
|
290
|
+
declare function isOAuthReason(value: JsonValue | undefined): value is HttpOAuthFailureReason;
|
|
291
|
+
/** The failure of a call whose host has no port for what it needs. */
|
|
292
|
+
declare function unavailableFailure(error: string, key: string | null): HttpFailurePayload;
|
|
293
|
+
/** The reply the port answered, checked to be one of the closed reply variants. */
|
|
294
|
+
declare function checkOAuthReply(reply: OAuthReply): OAuthReply;
|
|
295
|
+
/**
|
|
296
|
+
* One `http` effect, driven by the kernel's step machine (`httpDriverStart`/`httpDriverResume`): every ask
|
|
297
|
+
* (credential, token store, request, stream) is answered here and nothing else is decided in TypeScript.
|
|
298
|
+
*/
|
|
299
|
+
declare function runHttpCall(ports: HttpPorts, call: HttpCall, options?: HttpRunOptions): Promise<HttpOutcome>;
|
|
300
|
+
|
|
301
|
+
export { HttpEffectFailure, HttpUnavailableError, RANDOM_BYTES_MAX, base64Standard, base64Url, checkOAuthReply, createBrowserHttpPorts, createCredentialAdminPort, createHttpPorts, createHttpSecrets, credentialForgetPayload, credentialStatusPayload, installNetPort, isOAuthCode, isOAuthReason, randomBytesPayload, runHttpCall, sendBeaconRequest, sendHttp, streamHttp, systemRandom, unavailableFailure, userCredentialKey };
|
|
302
|
+
export type { BeaconSettled, BrowserHttpPortsOptions, CredentialAdminPort, Exchange, HttpKernel, HttpOutcome, HttpPorts, HttpPortsOptions, HttpRunOptions, HttpSecrets, HttpSecretsHost, NetPort, OAuthAuthorizeKernel, OAuthPort, PinnedFetch, PinnedInit, PinnedResponse, RandomSource, ResolvedHost, StreamFrame, StreamFramingWire };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { HttpEffectFailure, HttpUnavailableError, RANDOM_BYTES_MAX, base64Standard, base64Url, checkOAuthReply, createBrowserHttpPorts, createCredentialAdminPort, createHttpPorts, createHttpSecrets, credentialForgetPayload, credentialStatusPayload, installNetPort, isOAuthCode, isOAuthReason, randomBytesPayload, runHttpCall, sendBeaconRequest, sendHttp, streamHttp, systemRandom, unavailableFailure, userCredentialKey } from '../chunk-YO4LWS3I.js';
|
|
2
|
+
import '../chunk-MZKIL5IN.js';
|
|
3
|
+
import '../chunk-VMOBW7RK.js';
|
|
4
|
+
export { decodeOAuthAsk } from '../chunk-RBUMDYFS.js';
|
|
5
|
+
import '../chunk-HLOUDLPI.js';
|
|
6
|
+
import '../chunk-MLKGABMK.js';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
interface LaneTurn {
|
|
2
|
+
readonly ticket: number;
|
|
3
|
+
}
|
|
4
|
+
declare class LaneHeldByParkedDispatch extends Error {
|
|
5
|
+
readonly ticket: number;
|
|
6
|
+
readonly event: string;
|
|
7
|
+
constructor(ticket: number, event: string);
|
|
8
|
+
}
|
|
9
|
+
interface LaneGuard {
|
|
10
|
+
readonly turn: LaneTurn;
|
|
11
|
+
park(event: string): void;
|
|
12
|
+
resume(): void;
|
|
13
|
+
release(): void;
|
|
14
|
+
}
|
|
15
|
+
declare class DispatchLane {
|
|
16
|
+
private nextTicket;
|
|
17
|
+
private holder;
|
|
18
|
+
private depth;
|
|
19
|
+
private parkedEvent;
|
|
20
|
+
private readonly waiters;
|
|
21
|
+
assertCanReenter(turn: LaneTurn): void;
|
|
22
|
+
enter(turn?: LaneTurn): Promise<LaneGuard>;
|
|
23
|
+
private take;
|
|
24
|
+
private guard;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { DispatchLane, LaneHeldByParkedDispatch };
|
|
28
|
+
export type { LaneGuard, LaneTurn };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { OAuthEffectFailurePayload, RuntimeValue, OAuthAuthorizePayload, OAuthConnectionPayload } from '@almadar/core';
|
|
2
|
+
import { HttpPorts } from './http.js';
|
|
3
|
+
import './beacon.js';
|
|
4
|
+
import '../credentials/store.js';
|
|
5
|
+
import './decode.js';
|
|
6
|
+
import '@almadar/core/kernel-wire';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The interpreter and kernel-host half of the OAuth effects (`oauth-authorize`, `oauth-connection-status`,
|
|
10
|
+
* `oauth-connection-forget`): the asks that orbital-core's `run_oauth_authorize` / `run_oauth_connection` make,
|
|
11
|
+
* in the same order, answered here. Every rule (client and option parsing, the authorization URL, the failure
|
|
12
|
+
* messages) is the kernel's, reached through `@almadar/kernel`; only the sequencing of host asks lives here.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** A failed OAuth effect: its payload is what the `emit.failure` route carries. */
|
|
16
|
+
declare class OAuthEffectFailure extends Error {
|
|
17
|
+
readonly payload: OAuthEffectFailurePayload;
|
|
18
|
+
constructor(payload: OAuthEffectFailurePayload);
|
|
19
|
+
}
|
|
20
|
+
/** `oauth-authorize`: the kernel's steps, in order — secret, metadata, two draws, pending grant. */
|
|
21
|
+
declare function oauthAuthorizePayload(ports: HttpPorts, client: RuntimeValue | undefined, options: RuntimeValue | undefined, principal: string | undefined, key?: RuntimeValue): Promise<OAuthAuthorizePayload>;
|
|
22
|
+
/** `oauth-connection-status` / `oauth-connection-forget`: store first, then caller (the legacy order). */
|
|
23
|
+
declare function oauthConnectionPayload(ports: HttpPorts, head: 'oauth-connection-status' | 'oauth-connection-forget', provider: RuntimeValue | undefined, principal: string | undefined): Promise<OAuthConnectionPayload>;
|
|
24
|
+
|
|
25
|
+
export { OAuthEffectFailure, oauthAuthorizePayload, oauthConnectionPayload };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { OAuthEffectFailure, oauthAuthorizePayload, oauthConnectionPayload } from '../chunk-ZAQSS47X.js';
|
|
2
|
+
import '../chunk-YO4LWS3I.js';
|
|
3
|
+
import '../chunk-MZKIL5IN.js';
|
|
4
|
+
import '../chunk-VMOBW7RK.js';
|
|
5
|
+
import '../chunk-RBUMDYFS.js';
|
|
6
|
+
import '../chunk-HLOUDLPI.js';
|
|
7
|
+
import '../chunk-MLKGABMK.js';
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { HttpSecrets, OAuthPort } from './http.js';
|
|
2
|
+
import '@almadar/core';
|
|
3
|
+
import './beacon.js';
|
|
4
|
+
import '../credentials/store.js';
|
|
5
|
+
import './decode.js';
|
|
6
|
+
import '@almadar/core/kernel-wire';
|
|
7
|
+
|
|
8
|
+
/** What the person's consent page is opened with. */
|
|
9
|
+
interface OAuthConsentRequest {
|
|
10
|
+
authUrl: string;
|
|
11
|
+
state: string;
|
|
12
|
+
redirectUri: string;
|
|
13
|
+
}
|
|
14
|
+
interface OAuthPortOptions {
|
|
15
|
+
/** The host's credentials (read per ask when a function: a host installs them at boot). */
|
|
16
|
+
secrets: HttpSecrets | (() => HttpSecrets);
|
|
17
|
+
/** The host clock in epoch milliseconds. */
|
|
18
|
+
now?: () => number;
|
|
19
|
+
/** Opens the consent page for the person and answers the authorization code it returned, `null` when they declined; absent, the host asks no one. */
|
|
20
|
+
consent?: (request: OAuthConsentRequest) => Promise<string | null>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The port's clock decides expiry (`expiresAt >= now` is live, the inclusive boundary of the native store); the
|
|
24
|
+
* credential only garbage-collects, so it is given a grace beyond the TTL and an expired state answers `expired`,
|
|
25
|
+
* not `missing`.
|
|
26
|
+
*/
|
|
27
|
+
declare const PENDING_GRACE_MS: number;
|
|
28
|
+
declare function createOAuthPort(options: OAuthPortOptions): OAuthPort;
|
|
29
|
+
|
|
30
|
+
export { PENDING_GRACE_MS, createOAuthPort };
|
|
31
|
+
export type { OAuthConsentRequest, OAuthPortOptions };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { JsonValue } from '@almadar/core';
|
|
2
|
+
import { OsOp, Settled, OsError, CallSiteWire } from '@almadar/core/kernel-wire';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `os` ports of a kernel host, with no Node builtin in sight so the browser bundle can import them.
|
|
6
|
+
* The Node answerer is `os-node.ts`; the grant check is the Rust `OsGrants` (`allows` below), never TypeScript.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
type OsFsMode = 'read' | 'write' | 'create' | 'remove' | 'meta';
|
|
10
|
+
type OsNetKind = 'tcp' | 'udp' | 'listen';
|
|
11
|
+
type OsStdioKind = 'in' | 'out' | 'err';
|
|
12
|
+
type OsSysKind = 'cpu' | 'memory' | 'disk' | 'network' | 'power-state' | 'identity';
|
|
13
|
+
type OsDesktopKind = 'notify' | 'speak' | 'brightness' | 'volume' | 'power';
|
|
14
|
+
/** One thing an `os/` call needs from the program's grants: the JSON of Rust `OsRequirement`. */
|
|
15
|
+
type OsRequirement = {
|
|
16
|
+
need: 'fs';
|
|
17
|
+
path: string;
|
|
18
|
+
mode: OsFsMode;
|
|
19
|
+
} | {
|
|
20
|
+
need: 'exec';
|
|
21
|
+
command: string;
|
|
22
|
+
} | {
|
|
23
|
+
need: 'net';
|
|
24
|
+
host: string;
|
|
25
|
+
port: number;
|
|
26
|
+
kinds: OsNetKind[];
|
|
27
|
+
} | {
|
|
28
|
+
need: 'env';
|
|
29
|
+
name: string;
|
|
30
|
+
} | {
|
|
31
|
+
need: 'stdio';
|
|
32
|
+
kind: OsStdioKind;
|
|
33
|
+
} | {
|
|
34
|
+
need: 'sys';
|
|
35
|
+
kind: OsSysKind;
|
|
36
|
+
} | {
|
|
37
|
+
need: 'desktop';
|
|
38
|
+
kind: OsDesktopKind;
|
|
39
|
+
};
|
|
40
|
+
/** The grant decisions the wasm kernel owns (`OsGrants::allows`, the one-grant glob matcher, `is_public_address`). */
|
|
41
|
+
interface OsGrantPort {
|
|
42
|
+
/** `OsGrants::allows` over the grants every registered program declares. */
|
|
43
|
+
allows(need: OsRequirement): boolean;
|
|
44
|
+
/** Whether the absolute `glob` (`**`, `*`, `?`) matches `path`, as a one-grant `fs_allows` for read. */
|
|
45
|
+
globMatches(glob: string, path: string): boolean;
|
|
46
|
+
/** `is_public_address`: the rule an outbound host name must pass. */
|
|
47
|
+
isPublicAddress(ip: string): boolean;
|
|
48
|
+
/** Place the program's anchored grants and arguments under the host's anchors (`set_os_anchors_json`); answers what grants nothing. */
|
|
49
|
+
anchor(anchors: OsAnchors): OsAnchorProblem[];
|
|
50
|
+
/** An `os/` call's arguments with every anchored part replaced by what it names under the host's anchors (`resolve_anchored_args`). */
|
|
51
|
+
resolveArgs(op: OsOp, args: JsonValue[]): Settled<JsonValue[], OsError>;
|
|
52
|
+
}
|
|
53
|
+
/** An anchored grant entry that grants nothing under the host's anchors. */
|
|
54
|
+
interface OsAnchorProblem {
|
|
55
|
+
path: string;
|
|
56
|
+
message: string;
|
|
57
|
+
}
|
|
58
|
+
/** What a host answers an `os` ask with; `close` drops every handle it holds, as the native `OsHandles::close_all`. */
|
|
59
|
+
interface OsHostPort {
|
|
60
|
+
answer(op: OsOp, args: JsonValue[]): Promise<Settled<JsonValue, OsError>>;
|
|
61
|
+
/**
|
|
62
|
+
* `Completions::run_later`: a keyed ask of a completion-deferring op. A failed check (or a key already pending) is the
|
|
63
|
+
* in-place `error`; `ok` means the work runs in the background and its outcome reaches `deliver` once, unless
|
|
64
|
+
* the key is cancelled first. A host with no `defer` answers every ask in place.
|
|
65
|
+
*/
|
|
66
|
+
defer?(op: OsOp, args: JsonValue[], key: string, deliver: (outcome: Settled<JsonValue, OsError>) => void): Settled<null, OsError>;
|
|
67
|
+
/**
|
|
68
|
+
* A keyed stream (`OsOp::is_stream`, EXEC-QUEUE-12): the host binds and answers once in place, then hands each message
|
|
69
|
+
* to `message` until it ends; `message` answers `false` when no one takes it any more. A failure after the answer
|
|
70
|
+
* reaches `fail` once. A host with no `stream` answers every stream ask in place, as unsupported.
|
|
71
|
+
*/
|
|
72
|
+
stream?(op: OsOp, args: JsonValue[], key: string, message: (value: JsonValue) => boolean, fail: (error: OsError) => void): Promise<Settled<JsonValue, OsError>>;
|
|
73
|
+
/** `OsHandles::cancel_completion`: drop the pending completion of `key`, or stop its stream; `false` when none is open. */
|
|
74
|
+
cancel?(key: string): boolean;
|
|
75
|
+
close(): void;
|
|
76
|
+
}
|
|
77
|
+
/** The event a deferred `os` call's outcome fires on its call site, as the kernel shapes it. */
|
|
78
|
+
interface OsCompletionEvent {
|
|
79
|
+
event: string;
|
|
80
|
+
payload: JsonValue;
|
|
81
|
+
}
|
|
82
|
+
/** What the wasm kernel decides about a deferred `os` call: which ops defer, and the event an outcome fires. */
|
|
83
|
+
interface OsCompletionPort {
|
|
84
|
+
defers(op: OsOp): boolean;
|
|
85
|
+
streams(op: OsOp): boolean;
|
|
86
|
+
event(site: CallSiteWire, key: string, outcome: Settled<JsonValue, OsError>): OsCompletionEvent | null;
|
|
87
|
+
}
|
|
88
|
+
/** The kernel exports the completion port is built from. */
|
|
89
|
+
interface OsCompletionMatchers {
|
|
90
|
+
osDeferringOps(): string;
|
|
91
|
+
osStreamOps(): string;
|
|
92
|
+
osCompletionEvent(siteJson: string, key: string, outcomeJson: string): string;
|
|
93
|
+
}
|
|
94
|
+
/** The completion port over the wasm kernel: `OsOp::defers_completion`, `OsOp::is_stream` and `completion_event`, not copied. */
|
|
95
|
+
declare function kernelOsCompletions(kernel: OsCompletionMatchers): OsCompletionPort;
|
|
96
|
+
/** The kernel pieces a grant port is built from: the `Server` handle holding the program's grants and the module-level matchers. */
|
|
97
|
+
interface OsGrantKernel {
|
|
98
|
+
osAllows(requirementJson: string): boolean;
|
|
99
|
+
setOsAnchors(anchorsJson: string): string;
|
|
100
|
+
osResolveArgs(op: string, argsJson: string): string;
|
|
101
|
+
}
|
|
102
|
+
interface OsGrantMatchers {
|
|
103
|
+
osGlobMatches(glob: string, path: string): boolean;
|
|
104
|
+
isPublicAddress(ip: string): boolean;
|
|
105
|
+
}
|
|
106
|
+
/** The grant port over the wasm kernel: every decision is `OsGrants::allows` and the exports beside it. */
|
|
107
|
+
declare function kernelOsGrants(matchers: OsGrantMatchers, server: () => OsGrantKernel): OsGrantPort;
|
|
108
|
+
/**
|
|
109
|
+
* Where a host anchors `~/` and `./` paths and grants (the user's home and the directory it started the program in), and
|
|
110
|
+
* what a grant's declared anchors resolve to: its executable's directory and its boot environment (`orbital-core` `OsAnchors`).
|
|
111
|
+
*/
|
|
112
|
+
interface OsAnchors {
|
|
113
|
+
readonly home?: string;
|
|
114
|
+
readonly start?: string;
|
|
115
|
+
readonly exeDir?: string;
|
|
116
|
+
readonly env?: Readonly<Record<string, string>>;
|
|
117
|
+
}
|
|
118
|
+
/** What a written path names under the host's anchors (`OsAnchors::expand`). */
|
|
119
|
+
type AnchoredPath = {
|
|
120
|
+
kind: 'plain';
|
|
121
|
+
} | {
|
|
122
|
+
kind: 'anchored';
|
|
123
|
+
path: string;
|
|
124
|
+
} | {
|
|
125
|
+
kind: 'unknown';
|
|
126
|
+
message: string;
|
|
127
|
+
};
|
|
128
|
+
declare function expandAnchor(anchors: OsAnchors, text: string): AnchoredPath;
|
|
129
|
+
/** The grant port a host checks absolute paths through: an fs need also matches the program's `~/` and `./` grants (`OsGrants::fs_allows_at`). */
|
|
130
|
+
declare function anchoredGrants(grants: OsGrantPort, anchors: OsAnchors): OsGrantPort;
|
|
131
|
+
|
|
132
|
+
export { anchoredGrants, expandAnchor, kernelOsCompletions, kernelOsGrants };
|
|
133
|
+
export type { AnchoredPath, OsAnchorProblem, OsAnchors, OsCompletionEvent, OsCompletionMatchers, OsCompletionPort, OsDesktopKind, OsFsMode, OsGrantKernel, OsGrantMatchers, OsGrantPort, OsHostPort, OsNetKind, OsRequirement, OsStdioKind, OsSysKind };
|