@graftland/plugin-remote 0.3.0 → 0.3.2
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/Auth.d.ts +2 -2
- package/dist/Auth.d.ts.map +1 -1
- package/dist/Auth.js.map +1 -1
- package/dist/{Bootstrap-MCwivGN1.js → Bootstrap-H9gDsgsC.js} +2 -2
- package/dist/{Contract-CcpSIJm4.js → Contract-DsJtisvL.js} +8 -46
- package/dist/Contract.d.ts +50 -53
- package/dist/Contract.d.ts.map +1 -1
- package/dist/Contract.js +1 -1
- package/dist/Contract.js.map +1 -1
- package/dist/{Errors-oPsTLY7l.js → Errors-DYhsGZcZ.js} +14 -1
- package/dist/Errors.d.ts +19 -0
- package/dist/Errors.d.ts.map +1 -1
- package/dist/Errors.js +14 -1
- package/dist/Errors.js.map +1 -1
- package/dist/{FailureGroup-BcH0XOBi.js → FailureGroup-BgT73AaR.js} +14 -4
- package/dist/{Framing-zaYdOJnT.js → Framing-G9eSaeLb.js} +1 -1
- package/dist/{Graft-BsYq3F-J.js → Graft-B71CPA2Y.js} +46 -35
- package/dist/{Packages-B1TPk8pa.js → Packages-AgoCGotL.js} +23 -26
- package/dist/{Peer-IJgFK6mD.js → Peer-DXeVrGBh.js} +5 -5
- package/dist/{ProcessObservation-DEGrEMfP.js → ProcessObservation-gLgGirYv.js} +1 -1
- package/dist/{ServeLifecycle-CJM0gG5B.js → ServeLifecycle-Bd1FPJ6e.js} +1 -1
- package/dist/Testing.d.ts +4 -4
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js +10 -4
- package/dist/Testing.js.map +1 -1
- package/dist/Transport.d.ts +2 -2
- package/dist/Transport.d.ts.map +1 -1
- package/dist/Transport.js.map +1 -1
- package/dist/bin.js +48 -47
- package/dist/bin.js.map +1 -1
- package/dist/{childRuntime-DSqtFN9o.js → childRuntime-Bm3iSg_N.js} +30 -26
- package/dist/connectionEnded-BwcxQ7W8.js +54 -0
- package/dist/{entry-SYsx9VNb.js → entry-psOpX3Bj.js} +76 -48
- package/dist/host/auth/bearer.d.ts +1 -2
- package/dist/host/auth/bearer.d.ts.map +1 -1
- package/dist/host/auth/bearer.js +1 -1
- package/dist/host/auth/bearer.js.map +1 -1
- package/dist/host/auth/jwt.d.ts +1 -2
- package/dist/host/auth/jwt.d.ts.map +1 -1
- package/dist/host/auth/jwt.js +1 -1
- package/dist/host/auth/jwt.js.map +1 -1
- package/dist/host/auth/mtls.js +2 -2
- package/dist/host/auth/none.js +1 -1
- package/dist/host/command.d.ts +1 -1
- package/dist/host/command.d.ts.map +1 -1
- package/dist/host/command.js +4 -4
- package/dist/host/command.js.map +1 -1
- package/dist/host/local.d.ts +1 -2
- package/dist/host/local.d.ts.map +1 -1
- package/dist/host/local.js +3 -3
- package/dist/host/local.js.map +1 -1
- package/dist/host/unix.d.ts +1 -1
- package/dist/host/unix.d.ts.map +1 -1
- package/dist/host/unix.js +3 -3
- package/dist/host/unix.js.map +1 -1
- package/dist/host/websocket.d.ts +1 -1
- package/dist/host/websocket.d.ts.map +1 -1
- package/dist/host/websocket.js +3 -3
- package/dist/host/websocket.js.map +1 -1
- package/dist/host/worker.d.ts +1 -2
- package/dist/host/worker.d.ts.map +1 -1
- package/dist/host/worker.js +4 -5
- package/dist/host/worker.js.map +1 -1
- package/dist/{importer-D7zSgqxq.js → importer-Cvf88eAY.js} +5 -8
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -10
- package/dist/index.js.map +1 -1
- package/dist/internal/Certificates.js +4 -4
- package/dist/internal/Certificates.js.map +1 -1
- package/dist/internal/FailureGroup.js +3 -2
- package/dist/internal/FailureGroup.js.map +1 -1
- package/dist/internal/assembly.js +9 -2
- package/dist/internal/assembly.js.map +1 -1
- package/dist/internal/auth/mtls.js +1 -1
- package/dist/internal/auth/mtls.js.map +1 -1
- package/dist/internal/auth/tokenCredentials.d.ts +0 -1
- package/dist/internal/auth/tokenCredentials.d.ts.map +1 -1
- package/dist/internal/auth/tokenCredentials.js.map +1 -1
- package/dist/internal/child.js +20 -17
- package/dist/internal/child.js.map +1 -1
- package/dist/internal/childRuntime.js +6 -4
- package/dist/internal/childRuntime.js.map +1 -1
- package/dist/internal/contract.js +26 -0
- package/dist/internal/contract.js.map +1 -0
- package/dist/internal/credentials.d.ts +6 -6
- package/dist/internal/credentials.d.ts.map +1 -1
- package/dist/internal/credentials.js.map +1 -1
- package/dist/internal/directTransport.d.ts +1 -1
- package/dist/internal/entry.d.ts +1 -2
- package/dist/internal/entry.d.ts.map +1 -1
- package/dist/internal/entry.js +4 -14
- package/dist/internal/entry.js.map +1 -1
- package/dist/internal/execution.js +44 -7
- package/dist/internal/execution.js.map +1 -1
- package/dist/internal/host/runner.js +7 -6
- package/dist/internal/host/runner.js.map +1 -1
- package/dist/internal/host.js +5 -5
- package/dist/internal/host.js.map +1 -1
- package/dist/internal/port.d.ts +2 -10
- package/dist/internal/port.js +5 -5
- package/dist/internal/port.js.map +1 -1
- package/dist/internal/release.js +1 -1
- package/dist/internal/release.js.map +1 -1
- package/dist/internal/runner/Connection.d.ts +1 -1
- package/dist/internal/runner/Connection.js +4 -4
- package/dist/internal/runner/Connection.js.map +1 -1
- package/dist/internal/runner/Execution.js +3 -3
- package/dist/internal/runner/Execution.js.map +1 -1
- package/dist/internal/runner/Framing.d.ts +1 -11
- package/dist/internal/runner/Framing.js +1 -1
- package/dist/internal/runner/Framing.js.map +1 -1
- package/dist/internal/runner/Local.js +1 -1
- package/dist/internal/runner/Local.js.map +1 -1
- package/dist/internal/runner/Lock.js +1 -1
- package/dist/internal/runner/Lock.js.map +1 -1
- package/dist/internal/runner/Packages.d.ts +1 -1
- package/dist/internal/runner/Packages.js +22 -25
- package/dist/internal/runner/Packages.js.map +1 -1
- package/dist/internal/runner/Processes.js +7 -9
- package/dist/internal/runner/Processes.js.map +1 -1
- package/dist/internal/runner/Store.js +3 -3
- package/dist/internal/runner/Store.js.map +1 -1
- package/dist/internal/runner/Supervisor.js +46 -47
- package/dist/internal/runner/Supervisor.js.map +1 -1
- package/dist/internal/runner/accept.js +3 -3
- package/dist/internal/runner/accept.js.map +1 -1
- package/dist/internal/runner/model.js +1 -1
- package/dist/internal/runner/model.js.map +1 -1
- package/dist/internal/serve.js +1 -1
- package/dist/internal/serve.js.map +1 -1
- package/dist/internal/services.d.ts +2 -12
- package/dist/internal/services.d.ts.map +1 -1
- package/dist/internal/services.js.map +1 -1
- package/dist/internal/supervisorPlugin.js +1 -1
- package/dist/internal/watchdogMain.js +5 -5
- package/dist/internal/watchdogMain.js.map +1 -1
- package/dist/internal/websocketServer.js +3 -1
- package/dist/internal/websocketServer.js.map +1 -1
- package/dist/internal/workerMain.js +3 -3
- package/dist/{port-Blbh8tms.js → port--3x2zJ4D.js} +8 -8
- package/dist/{release-BY4Mlluy.js → release-DfZPuIcK.js} +1 -1
- package/dist/runner/auth/bearer.js +2 -2
- package/dist/runner/auth/jwt.js +4 -4
- package/dist/runner/auth/jwt.js.map +1 -1
- package/dist/runner/auth/mtls.js +3 -3
- package/dist/runner/auth/none.js +1 -1
- package/dist/runner/index.js +5 -5
- package/dist/runner/stdio.js +3 -3
- package/dist/runner/unix.js +3 -3
- package/dist/runner/websocket.js +4 -4
- package/dist/{socketChannel-KmtzF-9G.js → socketChannel-CJvL2DiB.js} +2 -2
- package/dist/{supervisorPlugin-Inb1S5IV.js → supervisorPlugin-t6Z6PrhD.js} +72 -76
- package/dist/{token-v5ne2I0-.js → token-CYBNNlhS.js} +1 -1
- package/dist/{tokenCredentials-WUJm2AKm.js → tokenCredentials-CbCuk-Rt.js} +3 -3
- package/dist/{websocketServer-MXcCJx0v.js → websocketServer-NQhODlEt.js} +5 -3
- package/dist/{workerChannel-P82YdNjh.js → workerChannel-C8hhBJzA.js} +1 -1
- package/package.json +3 -3
- package/src/Auth.ts +9 -2
- package/src/Contract.ts +67 -51
- package/src/Errors.ts +23 -0
- package/src/Testing.ts +16 -2
- package/src/Transport.ts +6 -2
- package/src/bin.ts +28 -30
- package/src/host/auth/bearer.ts +1 -6
- package/src/host/auth/jwt.ts +1 -6
- package/src/host/command.ts +2 -0
- package/src/host/local.ts +5 -9
- package/src/host/unix.ts +2 -0
- package/src/host/websocket.ts +2 -0
- package/src/host/worker.ts +4 -6
- package/src/index.ts +8 -4
- package/src/internal/Certificates.ts +10 -13
- package/src/internal/FailureGroup.ts +128 -121
- package/src/internal/assembly.ts +19 -10
- package/src/internal/auth/mtls.ts +19 -20
- package/src/internal/auth/tokenCredentials.ts +1 -7
- package/src/internal/child.ts +249 -240
- package/src/internal/childRuntime.ts +84 -81
- package/src/internal/contract.ts +47 -0
- package/src/internal/credentials.ts +12 -9
- package/src/internal/entry.ts +11 -25
- package/src/internal/execution.ts +73 -14
- package/src/internal/host/runner.ts +153 -153
- package/src/internal/host.ts +123 -130
- package/src/internal/port.ts +100 -103
- package/src/internal/release.ts +3 -2
- package/src/internal/runner/Connection.ts +52 -60
- package/src/internal/runner/Execution.ts +163 -164
- package/src/internal/runner/Framing.ts +9 -10
- package/src/internal/runner/Local.ts +26 -27
- package/src/internal/runner/Lock.ts +23 -25
- package/src/internal/runner/Packages.ts +67 -70
- package/src/internal/runner/Processes.ts +89 -92
- package/src/internal/runner/Store.ts +110 -114
- package/src/internal/runner/Supervisor.ts +392 -405
- package/src/internal/runner/accept.ts +76 -84
- package/src/internal/runner/model.ts +20 -21
- package/src/internal/serve.ts +15 -13
- package/src/internal/services.ts +1 -19
- package/src/internal/watchdogMain.ts +16 -11
- package/src/internal/websocketServer.ts +18 -3
- package/src/runner/auth/jwt.ts +10 -6
- package/dist/cleanup-BPWr-5U9.js +0 -13
- package/dist/connectionEnded-DUgcobEd.js +0 -9
- package/dist/internal/childErrors.d.ts +0 -33
- package/dist/internal/childErrors.d.ts.map +0 -1
- package/dist/internal/port.d.ts.map +0 -1
- package/dist/internal/runner/Framing.d.ts.map +0 -1
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as payloadLimit, s as protocol, t as fromSocket } from "./socketChannel-
|
|
1
|
+
import { u as TransportError } from "./Errors-DYhsGZcZ.js";
|
|
2
|
+
import { a as payloadLimit, s as protocol, t as fromSocket } from "./socketChannel-CJvL2DiB.js";
|
|
3
3
|
import { Array, Cause, Deferred, Effect, Option, Redacted, Scope, String } from "effect";
|
|
4
4
|
import { NodeHttpServer, NodeHttpServerRequest } from "@effect/platform-node";
|
|
5
5
|
import { HttpServerRequest, HttpServerResponse } from "effect/http";
|
|
6
6
|
import { TLSSocket } from "node:tls";
|
|
7
7
|
// packages/remote/src/internal/websocketServer.ts
|
|
8
|
-
const rejection = (error) =>
|
|
8
|
+
const rejection = (error) => error._tag === "AuthenticatorUnavailable" ? unavailable(error) : unauthorized(error);
|
|
9
|
+
const unavailable = (error) => Effect.logError("Remote host authenticator is unavailable", error.cause).pipe(Effect.as(HttpServerResponse.empty({ status: 503 })));
|
|
10
|
+
const unauthorized = (error) => Effect.logWarning("Remote host authentication failed", { reason: error.reason }, ...error.cause === void 0 ? [] : [error.cause]).pipe(Effect.as(HttpServerResponse.empty({
|
|
9
11
|
status: 401,
|
|
10
12
|
headers: error.challenge === void 0 ? {} : { "www-authenticate": error.challenge }
|
|
11
13
|
})));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { u as TransportError } from "./Errors-DYhsGZcZ.js";
|
|
2
2
|
import { Cause, Effect, FiberSet, Queue, Schema, Sink, Stream } from "effect";
|
|
3
3
|
// packages/remote/src/internal/workerBootstrap.ts
|
|
4
4
|
const Bootstrap = Schema.Struct({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@graftland/plugin-remote",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local and authenticated network execution for Graft plugins",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -49,9 +49,9 @@
|
|
|
49
49
|
"effect": "4.1.*"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@graftland/graft": "0.3.
|
|
52
|
+
"@graftland/graft": "0.3.2",
|
|
53
53
|
"@effect/platform-node": "4.1.2",
|
|
54
|
-
"@graftland/loader": "0.3.
|
|
54
|
+
"@graftland/loader": "0.3.2",
|
|
55
55
|
"pkijs": "4.0.1",
|
|
56
56
|
"asn1js": "4.0.0",
|
|
57
57
|
"ws": "8.22.1"
|
package/src/Auth.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/** Credentials and authenticated identities shared by transport plugins. */
|
|
2
2
|
import { Context } from "effect"
|
|
3
3
|
import type { Effect, Redacted, Option, Scope } from "effect"
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
AuthenticationFailed,
|
|
6
|
+
AuthenticatorUnavailable,
|
|
7
|
+
CredentialsError,
|
|
8
|
+
} from "./Errors"
|
|
5
9
|
|
|
6
10
|
export interface ClientCertificate {
|
|
7
11
|
readonly cert: string
|
|
@@ -42,7 +46,10 @@ export type AuthenticatorApi =
|
|
|
42
46
|
readonly issuer?: string
|
|
43
47
|
readonly authenticate: (
|
|
44
48
|
header: Option.Option<Redacted.Redacted<string>>,
|
|
45
|
-
) => Effect.Effect<
|
|
49
|
+
) => Effect.Effect<
|
|
50
|
+
string,
|
|
51
|
+
AuthenticationFailed | AuthenticatorUnavailable
|
|
52
|
+
>
|
|
46
53
|
}
|
|
47
54
|
| {
|
|
48
55
|
readonly _tag: "Mtls"
|
package/src/Contract.ts
CHANGED
|
@@ -1,38 +1,79 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import type { Service } from "./internal/services"
|
|
1
|
+
import { Array, Predicate, Schema } from "effect"
|
|
2
|
+
import type { Context, Effect, Scope } from "effect"
|
|
3
|
+
import type { Graft } from "@graftland/graft"
|
|
4
|
+
import type { Rpc, RpcClient, RpcGroup, RpcServer } from "effect/rpc"
|
|
6
5
|
import * as Control from "./internal/control"
|
|
7
6
|
export { service } from "./internal/services"
|
|
8
7
|
|
|
9
8
|
const TypeId = "~@graftland/plugin-remote/Contract"
|
|
10
9
|
|
|
11
|
-
/**
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
/** RPC types stay inside the descriptor; Graft supplies its dynamic activation context. */
|
|
11
|
+
export interface Service<R = never, ClientR = never> {
|
|
12
|
+
readonly key: Context.Key<unknown, unknown>
|
|
13
|
+
readonly group: Pick<RpcGroup.RpcGroup<Rpc.Any>, "requests">
|
|
14
|
+
readonly serve: (port: {
|
|
15
|
+
readonly serverProtocol: (endpoint: string) => RpcServer.Protocol["Service"]
|
|
16
|
+
}) => Effect.Effect<never, never, R>
|
|
17
|
+
readonly publish: (port: {
|
|
18
|
+
readonly clientProtocol: (endpoint: string) => RpcClient.Protocol["Service"]
|
|
19
|
+
}) => Effect.Effect<
|
|
20
|
+
void,
|
|
21
|
+
Graft.ServiceConflict,
|
|
22
|
+
Graft.Graft | Scope.Scope | ClientR
|
|
23
|
+
>
|
|
24
|
+
}
|
|
16
25
|
|
|
17
|
-
/**
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
/** A self-contained configuration schema that encodes as JSON. */
|
|
27
|
+
export type ConfigSchema = Schema.Top & {
|
|
28
|
+
readonly Encoded: Schema.Json
|
|
29
|
+
readonly DecodingServices: never
|
|
30
|
+
readonly EncodingServices: never
|
|
31
|
+
}
|
|
32
|
+
/** A self-contained schema for declared failures. */
|
|
33
|
+
export type ErrorSchema = Schema.Top & {
|
|
34
|
+
readonly DecodingServices: never
|
|
35
|
+
readonly EncodingServices: never
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** The shared configuration and service declarations for one remote plugin. */
|
|
39
|
+
export interface Contract<
|
|
40
|
+
S extends ConfigSchema,
|
|
41
|
+
E extends ErrorSchema = typeof Schema.Never,
|
|
42
|
+
> {
|
|
29
43
|
readonly name: string
|
|
30
44
|
readonly config: S
|
|
31
45
|
readonly error: E
|
|
32
46
|
readonly module: string
|
|
47
|
+
readonly inject: ReadonlyArray<Service>
|
|
48
|
+
readonly provides: ReadonlyArray<Service>
|
|
49
|
+
readonly [TypeId]: typeof TypeId
|
|
50
|
+
}
|
|
51
|
+
/** Configuration accepted by make; omitted errors default to Never. */
|
|
52
|
+
export interface Options<S extends ConfigSchema, E extends ErrorSchema> {
|
|
53
|
+
readonly name: string
|
|
54
|
+
readonly config: S
|
|
55
|
+
readonly error?: E
|
|
56
|
+
readonly module: string
|
|
33
57
|
readonly inject?: ReadonlyArray<Service>
|
|
34
58
|
readonly provides?: ReadonlyArray<Service>
|
|
35
|
-
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** An undeclared failure still crosses the boundary, with its diagnostic value. */
|
|
62
|
+
export class UndeclaredFailure extends Schema.TaggedError<
|
|
63
|
+
UndeclaredFailure,
|
|
64
|
+
{ readonly brand: unique symbol }
|
|
65
|
+
>()("UndeclaredFailure", { original: Schema.Defect({ includeStack: true }) }) {}
|
|
66
|
+
|
|
67
|
+
/** Pure metadata shared by the host and the executable runner bootstrap. */
|
|
68
|
+
export function make<S extends ConfigSchema, E extends ErrorSchema>(
|
|
69
|
+
options: Options<S, E> & { readonly error: E },
|
|
70
|
+
): Contract<S, E>
|
|
71
|
+
export function make<S extends ConfigSchema>(
|
|
72
|
+
options: Options<S, typeof Schema.Never>,
|
|
73
|
+
): Contract<S>
|
|
74
|
+
export function make<S extends ConfigSchema, E extends ErrorSchema>(
|
|
75
|
+
options: Options<S, E>,
|
|
76
|
+
): Contract<S, E | typeof Schema.Never> {
|
|
36
77
|
// Keys are runtime strings; tuple types cannot distinguish independently created keys.
|
|
37
78
|
const keys = Array.map(
|
|
38
79
|
[...(options.inject ?? []), ...(options.provides ?? [])],
|
|
@@ -45,42 +86,17 @@ export const make = <
|
|
|
45
86
|
throw new Error(
|
|
46
87
|
"Service keys must be unique within a remote contract and must not use the control endpoint",
|
|
47
88
|
)
|
|
48
|
-
|
|
49
|
-
const codec = Schema.toCodecJson(
|
|
50
|
-
Schema.Cause(failure, Schema.Defect({ includeStack: true })),
|
|
51
|
-
)
|
|
52
|
-
const declared = Schema.is(failure)
|
|
53
|
-
const normalizeCause = (cause: Cause.Cause<unknown>) =>
|
|
54
|
-
Cause.map(cause, (error) =>
|
|
55
|
-
declared(error) ? error : UndeclaredFailure.make({ original: error }),
|
|
56
|
-
)
|
|
89
|
+
|
|
57
90
|
return {
|
|
58
91
|
...options,
|
|
59
|
-
|
|
60
|
-
normalizeCause,
|
|
92
|
+
error: options.error ?? Schema.Never,
|
|
61
93
|
inject: options.inject ?? [],
|
|
62
94
|
provides: options.provides ?? [],
|
|
63
95
|
[TypeId]: TypeId,
|
|
64
|
-
encodeCause: (cause: Cause.Cause<unknown>) =>
|
|
65
|
-
normalizeCause(cause).pipe(Schema.encodeEffect(codec)),
|
|
66
|
-
decodeCause: Schema.decodeUnknownEffect(codec),
|
|
67
96
|
}
|
|
68
97
|
}
|
|
69
98
|
|
|
70
|
-
/**
|
|
71
|
-
export type Contract<
|
|
72
|
-
S extends Schema.Top & {
|
|
73
|
-
readonly Encoded: Schema.Json
|
|
74
|
-
readonly DecodingServices: never
|
|
75
|
-
readonly EncodingServices: never
|
|
76
|
-
},
|
|
77
|
-
E extends Schema.Top & {
|
|
78
|
-
readonly DecodingServices: never
|
|
79
|
-
readonly EncodingServices: never
|
|
80
|
-
},
|
|
81
|
-
> = ReturnType<typeof make<S, E>>
|
|
82
|
-
|
|
83
|
-
/** Dynamic imports retain the control server and cause normalization; hosts retain the declared error type. */
|
|
99
|
+
/** A contract whose schemas are discovered through a dynamic import. */
|
|
84
100
|
export type RunnerContract = Contract<
|
|
85
101
|
Schema.Codec<unknown, Schema.Json>,
|
|
86
102
|
Schema.Codec<unknown>
|
package/src/Errors.ts
CHANGED
|
@@ -80,3 +80,26 @@ export class AuthenticationFailed extends Schema.TaggedError<
|
|
|
80
80
|
challenge: Schema.optionalKey(Schema.String),
|
|
81
81
|
cause: Schema.optionalKey(Schema.Cause(Schema.Unknown, Schema.Unknown)),
|
|
82
82
|
}) {}
|
|
83
|
+
|
|
84
|
+
/** The authenticator could not reach what it needs to decide, such as its key set; the credential may still be valid. */
|
|
85
|
+
export class AuthenticatorUnavailable extends Schema.TaggedError<
|
|
86
|
+
AuthenticatorUnavailable,
|
|
87
|
+
{ readonly brand: unique symbol }
|
|
88
|
+
>()("AuthenticatorUnavailable", {
|
|
89
|
+
cause: Schema.Cause(Schema.Unknown, Schema.Unknown),
|
|
90
|
+
}) {}
|
|
91
|
+
|
|
92
|
+
/** A remote entry could not be resolved or configured at the indicated field. */
|
|
93
|
+
export class RemoteEntryError extends Schema.TaggedError<
|
|
94
|
+
RemoteEntryError,
|
|
95
|
+
{ readonly brand: unique symbol }
|
|
96
|
+
>()("RemoteEntryError", {
|
|
97
|
+
entry: Schema.Option(Schema.String),
|
|
98
|
+
directory: Schema.Option(Schema.String),
|
|
99
|
+
field: Schema.String,
|
|
100
|
+
cause: Schema.Cause(Schema.Unknown, Schema.Unknown),
|
|
101
|
+
}) {
|
|
102
|
+
override get message() {
|
|
103
|
+
return `Remote entry ${Option.getOrElse(this.entry, () => "<programmatic>")} failed at ${this.field}`
|
|
104
|
+
}
|
|
105
|
+
}
|
package/src/Testing.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Plugin } from "@graftland/graft"
|
|
2
2
|
import {
|
|
3
3
|
Array,
|
|
4
|
+
Cause,
|
|
4
5
|
Equivalence,
|
|
5
6
|
Deferred,
|
|
6
7
|
Effect,
|
|
@@ -9,13 +10,17 @@ import {
|
|
|
9
10
|
String,
|
|
10
11
|
Schema,
|
|
11
12
|
} from "effect"
|
|
13
|
+
import type { TransportError } from "./Errors"
|
|
12
14
|
import type { Channel } from "./Transport"
|
|
13
15
|
import * as Framing from "./internal/runner/Framing"
|
|
14
16
|
|
|
15
17
|
export class ConformanceError extends Schema.TaggedError<
|
|
16
18
|
ConformanceError,
|
|
17
19
|
{ readonly brand: unique symbol }
|
|
18
|
-
>()("ConformanceError", {
|
|
20
|
+
>()("ConformanceError", {
|
|
21
|
+
message: Schema.String,
|
|
22
|
+
cause: Schema.optionalKey(Schema.Cause(Schema.Unknown, Schema.Unknown)),
|
|
23
|
+
}) {}
|
|
19
24
|
const check = (condition: boolean, message: string) =>
|
|
20
25
|
condition ? Effect.void : Effect.fail(ConformanceError.make({ message }))
|
|
21
26
|
export interface Capabilities {
|
|
@@ -88,7 +93,16 @@ export const transport = <E, R>(
|
|
|
88
93
|
),
|
|
89
94
|
"The channel changed byte order across split or coalesced chunks",
|
|
90
95
|
)
|
|
91
|
-
})
|
|
96
|
+
}).pipe(
|
|
97
|
+
Effect.mapError((error): E | ConformanceError | TransportError =>
|
|
98
|
+
Schema.is(Framing.FrameError)(error)
|
|
99
|
+
? ConformanceError.make({
|
|
100
|
+
message: error.message,
|
|
101
|
+
cause: Cause.fail(error),
|
|
102
|
+
})
|
|
103
|
+
: error,
|
|
104
|
+
),
|
|
105
|
+
),
|
|
92
106
|
eof: Effect.gen(function* () {
|
|
93
107
|
const channel = yield* connect
|
|
94
108
|
yield* Stream.empty.pipe(Stream.run(channel.output))
|
package/src/Transport.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
/** Execution and byte-channel capabilities; implementations live in host plugins. */
|
|
2
2
|
import { Context } from "effect"
|
|
3
3
|
import type { Effect, Option, Scope, Stream, Sink, Redacted } from "effect"
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
AuthenticationFailed,
|
|
6
|
+
AuthenticatorUnavailable,
|
|
7
|
+
TransportError,
|
|
8
|
+
} from "./Errors"
|
|
5
9
|
import type { Prepared, VerifiedCertificate, TlsPolicy } from "./Auth"
|
|
6
10
|
/** Ordered reliable bytes. Chunk boundaries have no meaning; EOF is not exit confirmation. */
|
|
7
11
|
export interface Channel {
|
|
@@ -24,7 +28,7 @@ export type Session = (
|
|
|
24
28
|
) => Effect.Effect<void, TransportError, Scope.Scope>
|
|
25
29
|
export type Accept = (
|
|
26
30
|
handshake: Handshake,
|
|
27
|
-
) => Effect.Effect<Session, AuthenticationFailed>
|
|
31
|
+
) => Effect.Effect<Session, AuthenticationFailed | AuthenticatorUnavailable>
|
|
28
32
|
export interface Serving {
|
|
29
33
|
/** Completes after serve has registered its accept loop, not merely after bind. */
|
|
30
34
|
readonly ready: Effect.Effect<void>
|
package/src/bin.ts
CHANGED
|
@@ -68,24 +68,23 @@ const child = Command.make(
|
|
|
68
68
|
Argument.withSchema(Schema.fromJsonString(Bootstrap)),
|
|
69
69
|
),
|
|
70
70
|
},
|
|
71
|
-
({ contract, session, bootstrap })
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}),
|
|
71
|
+
Effect.fnUntraced(function* ({ contract, session, bootstrap }) {
|
|
72
|
+
const watchdog = yield* Watchdog.start
|
|
73
|
+
// The executable owns stdin; it must not retain the process after a supervisor stop.
|
|
74
|
+
yield* Effect.addFinalizer(() =>
|
|
75
|
+
Effect.sync(() => {
|
|
76
|
+
process.stdin.destroy()
|
|
77
|
+
}),
|
|
78
|
+
)
|
|
79
|
+
const begin = yield* Effect.raceFirst(
|
|
80
|
+
watchdog.begin.pipe(Effect.as(true)),
|
|
81
|
+
watchdog.stop.pipe(Effect.as(false)),
|
|
82
|
+
)
|
|
83
|
+
if (!begin) return
|
|
84
|
+
const definition = yield* load(pathToFileURL(contract).href)
|
|
85
|
+
const channel = yield* bytes
|
|
86
|
+
return yield* run(definition, channel, session, bootstrap, watchdog.stop)
|
|
87
|
+
}),
|
|
89
88
|
)
|
|
90
89
|
const cli = Command.make(
|
|
91
90
|
"graft-remote",
|
|
@@ -93,18 +92,17 @@ const cli = Command.make(
|
|
|
93
92
|
contract: Argument.String("contract").pipe(Argument.optional),
|
|
94
93
|
session: Argument.String("session").pipe(Argument.withDefault("local")),
|
|
95
94
|
},
|
|
96
|
-
({ contract, session })
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}),
|
|
95
|
+
Effect.fnUntraced(function* ({ contract, session }) {
|
|
96
|
+
if (Option.isNone(contract))
|
|
97
|
+
return yield* CliError.UserError.make({
|
|
98
|
+
cause: "Missing contract module",
|
|
99
|
+
userMessage:
|
|
100
|
+
"A contract module or the child/serve/certificates subcommand is required",
|
|
101
|
+
})
|
|
102
|
+
const definition = yield* load(contract.value)
|
|
103
|
+
const channel = yield* bytes
|
|
104
|
+
return yield* run(definition, channel, session)
|
|
105
|
+
}),
|
|
108
106
|
).pipe(Command.withSubcommands([child, serve, certificates]))
|
|
109
107
|
|
|
110
108
|
NodeRuntime.runMain(
|
package/src/host/auth/bearer.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import type { Graft, Plugin } from "@graftland/graft"
|
|
2
1
|
import { Config, plugin } from "../../internal/auth/tokenCredentials"
|
|
3
2
|
export { Config }
|
|
4
3
|
|
|
5
|
-
const capability
|
|
6
|
-
typeof Config.Type,
|
|
7
|
-
typeof Config.Encoded,
|
|
8
|
-
Graft.ServiceConflict
|
|
9
|
-
> = plugin("remote-bearer-credentials")
|
|
4
|
+
const capability = plugin("remote-bearer-credentials")
|
|
10
5
|
export default capability
|
package/src/host/auth/jwt.ts
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import type { Graft, Plugin } from "@graftland/graft"
|
|
2
1
|
import { Config, plugin } from "../../internal/auth/tokenCredentials"
|
|
3
2
|
export { Config }
|
|
4
3
|
|
|
5
|
-
const capability
|
|
6
|
-
typeof Config.Type,
|
|
7
|
-
typeof Config.Encoded,
|
|
8
|
-
Graft.ServiceConflict
|
|
9
|
-
> = plugin("remote-jwt-credentials")
|
|
4
|
+
const capability = plugin("remote-jwt-credentials")
|
|
10
5
|
export default capability
|
package/src/host/command.ts
CHANGED
package/src/host/local.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Plugin
|
|
1
|
+
import { Plugin } from "@graftland/graft"
|
|
2
2
|
import { Array, Effect, Scope } from "effect"
|
|
3
3
|
import { ChildProcess, ChildProcessSpawner } from "effect/process"
|
|
4
4
|
import { LocalTransport } from "../internal/directTransport"
|
|
@@ -29,13 +29,9 @@ const make = Effect.map(ChildProcessSpawner.ChildProcessSpawner, (spawner) =>
|
|
|
29
29
|
}),
|
|
30
30
|
}),
|
|
31
31
|
)
|
|
32
|
-
const plugin
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
name: "remote-local-transport",
|
|
37
|
-
inject: [ChildProcessSpawner.ChildProcessSpawner],
|
|
38
|
-
},
|
|
39
|
-
)
|
|
32
|
+
const plugin = Plugin.service(LocalTransport, make, {
|
|
33
|
+
name: "remote-local-transport",
|
|
34
|
+
inject: [ChildProcessSpawner.ChildProcessSpawner],
|
|
35
|
+
})
|
|
40
36
|
|
|
41
37
|
export default plugin
|
package/src/host/unix.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Options for the unix connector. */
|
|
2
|
+
export type { UnixOptions as Options } from "../internal/transportOptions"
|
|
1
3
|
import type { UnixOptions } from "../internal/transportOptions"
|
|
2
4
|
import { Plugin, Graft } from "@graftland/graft"
|
|
3
5
|
import { ConfigDirectory } from "@graftland/loader"
|
package/src/host/websocket.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
/** Options for the websocket connector. */
|
|
2
|
+
export type { WebsocketOptions as Options } from "../internal/transportOptions"
|
|
1
3
|
import type { WebsocketOptions } from "../internal/transportOptions"
|
|
2
4
|
import { Plugin, Graft } from "@graftland/graft"
|
|
3
5
|
import { Cause, Effect, FileSystem, Option, Path, Schema } from "effect"
|
package/src/host/worker.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Plugin
|
|
1
|
+
import { Plugin } from "@graftland/graft"
|
|
2
2
|
import { Cause, Deferred, Effect, FiberSet, Option, Schema } from "effect"
|
|
3
3
|
import { Worker } from "node:worker_threads"
|
|
4
4
|
import { WorkerTransport } from "../internal/directTransport"
|
|
@@ -82,9 +82,7 @@ const start: typeof WorkerTransport.Service.start = Effect.fnUntraced(
|
|
|
82
82
|
}
|
|
83
83
|
},
|
|
84
84
|
)
|
|
85
|
-
const plugin
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
{ name: "remote-thread-transport" },
|
|
89
|
-
)
|
|
85
|
+
const plugin = Plugin.service(WorkerTransport, Effect.succeed({ start }), {
|
|
86
|
+
name: "remote-thread-transport",
|
|
87
|
+
})
|
|
90
88
|
export default plugin
|
package/src/index.ts
CHANGED
|
@@ -16,9 +16,11 @@ export { Contract }
|
|
|
16
16
|
export { Instance } from "./Instance"
|
|
17
17
|
export { RemoteTerminationUnconfirmed } from "./internal/runner/model"
|
|
18
18
|
export { RemoteError, RemoteWithdrawn, MissingInstance } from "./Errors"
|
|
19
|
-
export { UndeclaredFailure
|
|
19
|
+
export { UndeclaredFailure } from "./Contract"
|
|
20
20
|
export type {
|
|
21
21
|
Connect,
|
|
22
|
+
Authentication,
|
|
23
|
+
Token as CredentialToken,
|
|
22
24
|
Source as CredentialSource,
|
|
23
25
|
} from "./internal/credentials"
|
|
24
26
|
|
|
@@ -90,8 +92,8 @@ export const plugin = <
|
|
|
90
92
|
ChildProcessSpawner.ChildProcessSpawner,
|
|
91
93
|
],
|
|
92
94
|
retry: options.retry,
|
|
93
|
-
apply: (
|
|
94
|
-
|
|
95
|
+
apply: Effect.fnUntraced(
|
|
96
|
+
function* () {
|
|
95
97
|
const input = yield* Schema.decodeUnknownEffect(Configuration.Host)({
|
|
96
98
|
contract: options.contractModule,
|
|
97
99
|
connect: options.connect,
|
|
@@ -110,6 +112,8 @@ export const plugin = <
|
|
|
110
112
|
yield* follow(child, (cause) =>
|
|
111
113
|
Effect.failCause(publicCause(contract.error, cause)),
|
|
112
114
|
)
|
|
113
|
-
}
|
|
115
|
+
},
|
|
116
|
+
Effect.mapError((error) => publicError(contract.error, error)),
|
|
117
|
+
),
|
|
114
118
|
})
|
|
115
119
|
export { host as default } from "./internal/entry"
|
|
@@ -241,20 +241,17 @@ export const write = Effect.fn("Certificates.write")(function* (
|
|
|
241
241
|
force: boolean = false,
|
|
242
242
|
) {
|
|
243
243
|
const fs = yield* FileSystem.FileSystem
|
|
244
|
-
yield* fs
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
})
|
|
249
|
-
.pipe(Effect.uninterruptible)
|
|
244
|
+
yield* fs.writeFileString(base + ".key", Redacted.value(pair.privateKey), {
|
|
245
|
+
flag: force ? "w" : "wx",
|
|
246
|
+
mode: 0o600,
|
|
247
|
+
})
|
|
250
248
|
// Opening an existing file does not change its permissions when renewing it.
|
|
251
|
-
yield* fs.chmod(base + ".key", 0o600)
|
|
252
|
-
yield* fs
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
})
|
|
249
|
+
yield* fs.chmod(base + ".key", 0o600)
|
|
250
|
+
yield* fs.writeFileString(base + ".crt", pair.certificate, {
|
|
251
|
+
flag: force ? "w" : "wx",
|
|
252
|
+
})
|
|
253
|
+
// One region for the pair: an interruption between the files would leave a key without its certificate.
|
|
254
|
+
}, Effect.uninterruptible)
|
|
258
255
|
|
|
259
256
|
export interface Options {
|
|
260
257
|
readonly out: string
|