@alpacakit/agents 0.1.0-beta.20 → 0.1.0-beta.21
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/README.md +60 -0
- package/dist/agents/claude.d.ts.map +1 -1
- package/dist/agents/claude.js +3 -0
- package/dist/agents/codex.d.ts.map +1 -1
- package/dist/agents/codex.js +4 -0
- package/dist/agents/openai-compatible/config.d.ts.map +1 -1
- package/dist/agents/openai-compatible/config.js +5 -0
- package/dist/agents/openai-compatible/fetch-engine.d.ts.map +1 -1
- package/dist/agents/openai-compatible/fetch-engine.js +6 -0
- package/dist/agents/openai-compatible/pi/module.d.ts.map +1 -1
- package/dist/agents/openai-compatible/pi/module.js +1 -0
- package/dist/agents/openai-compatible/pi/sandbox.js +2 -0
- package/dist/agents/openai-compatible/response.js +1 -0
- package/dist/auth/profile-store.d.ts.map +1 -1
- package/dist/auth/profile-store.js +1 -0
- package/dist/auth/secrets.d.ts.map +1 -1
- package/dist/auth/secrets.js +2 -0
- package/dist/codex/app-server.js +6 -0
- package/dist/core/controlled-process.d.ts +98 -0
- package/dist/core/controlled-process.d.ts.map +1 -0
- package/dist/core/controlled-process.js +29 -0
- package/dist/core/error.d.ts +25 -0
- package/dist/core/error.d.ts.map +1 -1
- package/dist/core/error.js +32 -0
- package/dist/core/node-controlled-exec.d.ts +3 -0
- package/dist/core/node-controlled-exec.d.ts.map +1 -0
- package/dist/core/node-controlled-exec.js +32 -0
- package/dist/core/node-ports.d.ts +1 -0
- package/dist/core/node-ports.d.ts.map +1 -1
- package/dist/core/node-ports.js +9 -1
- package/dist/core/ports.d.ts +5 -0
- package/dist/core/ports.d.ts.map +1 -1
- package/dist/fleet/fleet.d.ts.map +1 -1
- package/dist/fleet/fleet.js +5 -2
- package/dist/fleet/store.d.ts.map +1 -1
- package/dist/fleet/store.js +3 -0
- package/dist/host/github-dir.d.ts.map +1 -1
- package/dist/host/github-dir.js +5 -0
- package/dist/host/mcp-list.d.ts.map +1 -1
- package/dist/host/mcp-list.js +1 -0
- package/dist/host/run-command.d.ts.map +1 -1
- package/dist/host/run-command.js +2 -0
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/internal/controlled-process/authentication.d.ts +13 -0
- package/dist/internal/controlled-process/authentication.d.ts.map +1 -0
- package/dist/internal/controlled-process/authentication.js +112 -0
- package/dist/internal/controlled-process/child-fd.d.ts +5 -0
- package/dist/internal/controlled-process/child-fd.d.ts.map +1 -0
- package/dist/internal/controlled-process/child-fd.js +47 -0
- package/dist/internal/controlled-process/framed-transport.d.ts +6 -0
- package/dist/internal/controlled-process/framed-transport.d.ts.map +1 -0
- package/dist/internal/controlled-process/framed-transport.js +117 -0
- package/dist/internal/controlled-process/host-controller.d.ts +23 -0
- package/dist/internal/controlled-process/host-controller.d.ts.map +1 -0
- package/dist/internal/controlled-process/host-controller.js +908 -0
- package/dist/internal/controlled-process/lifecycle.d.ts +5 -0
- package/dist/internal/controlled-process/lifecycle.d.ts.map +1 -0
- package/dist/internal/controlled-process/lifecycle.js +22 -0
- package/dist/internal/controlled-process/model.d.ts +99 -0
- package/dist/internal/controlled-process/model.d.ts.map +1 -0
- package/dist/internal/controlled-process/model.js +1 -0
- package/dist/internal/controlled-process/record-store.d.ts +17 -0
- package/dist/internal/controlled-process/record-store.d.ts.map +1 -0
- package/dist/internal/controlled-process/record-store.js +170 -0
- package/dist/internal/controlled-process/record.d.ts +12 -0
- package/dist/internal/controlled-process/record.d.ts.map +1 -0
- package/dist/internal/controlled-process/record.js +87 -0
- package/dist/internal/controlled-process/schema.d.ts +133 -0
- package/dist/internal/controlled-process/schema.d.ts.map +1 -0
- package/dist/internal/controlled-process/schema.js +99 -0
- package/dist/internal/controlled-process/shim-entry.d.ts +2 -0
- package/dist/internal/controlled-process/shim-entry.d.ts.map +1 -0
- package/dist/internal/controlled-process/shim-entry.js +2 -0
- package/dist/internal/controlled-process/shim-runtime.d.ts +2 -0
- package/dist/internal/controlled-process/shim-runtime.d.ts.map +1 -0
- package/dist/internal/controlled-process/shim-runtime.js +57 -0
- package/dist/internal/controlled-process/supervisor-coordinator.d.ts +67 -0
- package/dist/internal/controlled-process/supervisor-coordinator.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-coordinator.js +325 -0
- package/dist/internal/controlled-process/supervisor-entry.d.ts +2 -0
- package/dist/internal/controlled-process/supervisor-entry.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-entry.js +2 -0
- package/dist/internal/controlled-process/supervisor-model.d.ts +92 -0
- package/dist/internal/controlled-process/supervisor-model.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-model.js +1 -0
- package/dist/internal/controlled-process/supervisor-platform.d.ts +16 -0
- package/dist/internal/controlled-process/supervisor-platform.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-platform.js +104 -0
- package/dist/internal/controlled-process/supervisor-runtime.d.ts +11 -0
- package/dist/internal/controlled-process/supervisor-runtime.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-runtime.js +773 -0
- package/dist/internal/controlled-process/supervisor-schema.d.ts +100 -0
- package/dist/internal/controlled-process/supervisor-schema.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-schema.js +73 -0
- package/dist/internal/controlled-process/supervisor-transport.d.ts +46 -0
- package/dist/internal/controlled-process/supervisor-transport.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-transport.js +368 -0
- package/dist/internal/controlled-process/supervisor-values.d.ts +39 -0
- package/dist/internal/controlled-process/supervisor-values.d.ts.map +1 -0
- package/dist/internal/controlled-process/supervisor-values.js +38 -0
- package/dist/internal/controlled-process/token.d.ts +4 -0
- package/dist/internal/controlled-process/token.d.ts.map +1 -0
- package/dist/internal/controlled-process/token.js +38 -0
- package/dist/internal/controlled-process/values.d.ts +39 -0
- package/dist/internal/controlled-process/values.d.ts.map +1 -0
- package/dist/internal/controlled-process/values.js +38 -0
- package/dist/kernel/cli-agent.d.ts.map +1 -1
- package/dist/kernel/cli-agent.js +330 -34
- package/dist/kernel/cli-login.d.ts.map +1 -1
- package/dist/kernel/cli-login.js +5 -0
- package/dist/kernel/env-template.js +1 -0
- package/dist/kernel/facets.d.ts.map +1 -1
- package/dist/kernel/facets.js +1 -0
- package/dist/kernel/keyed.d.ts.map +1 -1
- package/dist/kernel/keyed.js +1 -0
- package/dist/kernel/login.js +2 -0
- package/dist/kernel/options.d.ts +14 -0
- package/dist/kernel/options.d.ts.map +1 -1
- package/dist/kernel/options.js +3 -0
- package/dist/kernel/process-lifecycle-failure.d.ts +5 -0
- package/dist/kernel/process-lifecycle-failure.d.ts.map +1 -0
- package/dist/kernel/process-lifecycle-failure.js +5 -0
- package/dist/kernel/run.d.ts.map +1 -1
- package/dist/kernel/run.js +11 -0
- package/dist/kernel/runtime.d.ts.map +1 -1
- package/dist/kernel/runtime.js +2 -0
- package/dist/keyring/resolver.d.ts.map +1 -1
- package/dist/keyring/resolver.js +2 -0
- package/dist/structured/run-structured.js +1 -0
- package/dist/testing/fake-controlled-exec.d.ts +21 -0
- package/dist/testing/fake-controlled-exec.d.ts.map +1 -0
- package/dist/testing/fake-controlled-exec.js +172 -0
- package/dist/testing/fake-exec.d.ts.map +1 -1
- package/dist/testing/fake-exec.js +64 -54
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ControlledProcessState } from "./model.js";
|
|
2
|
+
export declare const CONTROLLED_PROCESS_TRANSITIONS: readonly [readonly ["reserved", "acked"], readonly ["reserved", "absent"], readonly ["acked", "running"], readonly ["acked", "absent"], readonly ["running", "term"], readonly ["running", "absent"], readonly ["term", "kill_sent"], readonly ["term", "absent"], readonly ["kill_sent", "absent"], readonly ["absent", "released"]];
|
|
3
|
+
export declare function isControlledProcessTransitionAllowed(from: ControlledProcessState, to: ControlledProcessState): boolean;
|
|
4
|
+
export declare function transitionControlledProcess(from: ControlledProcessState, to: ControlledProcessState): ControlledProcessState;
|
|
5
|
+
//# sourceMappingURL=lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/internal/controlled-process/lifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAQzD,eAAO,MAAM,8BAA8B,uUAWgB,CAAC;AAE5D,wBAAgB,oCAAoC,CAClD,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,sBAAsB,GACzB,OAAO,CAIT;AAED,wBAAgB,2BAA2B,CACzC,IAAI,EAAE,sBAAsB,EAC5B,EAAE,EAAE,sBAAsB,GACzB,sBAAsB,CAKxB"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { CONTROLLED_PROCESS_STATE } from "./values.js";
|
|
2
|
+
export const CONTROLLED_PROCESS_TRANSITIONS = [
|
|
3
|
+
[CONTROLLED_PROCESS_STATE.reserved, CONTROLLED_PROCESS_STATE.acked],
|
|
4
|
+
[CONTROLLED_PROCESS_STATE.reserved, CONTROLLED_PROCESS_STATE.absent],
|
|
5
|
+
[CONTROLLED_PROCESS_STATE.acked, CONTROLLED_PROCESS_STATE.running],
|
|
6
|
+
[CONTROLLED_PROCESS_STATE.acked, CONTROLLED_PROCESS_STATE.absent],
|
|
7
|
+
[CONTROLLED_PROCESS_STATE.running, CONTROLLED_PROCESS_STATE.term],
|
|
8
|
+
[CONTROLLED_PROCESS_STATE.running, CONTROLLED_PROCESS_STATE.absent],
|
|
9
|
+
[CONTROLLED_PROCESS_STATE.term, CONTROLLED_PROCESS_STATE.killSent],
|
|
10
|
+
[CONTROLLED_PROCESS_STATE.term, CONTROLLED_PROCESS_STATE.absent],
|
|
11
|
+
[CONTROLLED_PROCESS_STATE.killSent, CONTROLLED_PROCESS_STATE.absent],
|
|
12
|
+
[CONTROLLED_PROCESS_STATE.absent, CONTROLLED_PROCESS_STATE.released],
|
|
13
|
+
];
|
|
14
|
+
export function isControlledProcessTransitionAllowed(from, to) {
|
|
15
|
+
return CONTROLLED_PROCESS_TRANSITIONS.some((transition) => transition[0] === from && transition[1] === to);
|
|
16
|
+
}
|
|
17
|
+
export function transitionControlledProcess(from, to) {
|
|
18
|
+
if (!isControlledProcessTransitionAllowed(from, to)) {
|
|
19
|
+
throw new Error(`Invalid controlled process transition: ${from} -> ${to}`);
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { Brand, ValueOf } from "@alpacakit/core";
|
|
2
|
+
import type { ChildProcessAbsenceProof } from "../../core/controlled-process.js";
|
|
3
|
+
import type { CHILD_PROCESS_ABSENCE_PROOF } from "../../core/controlled-process.js";
|
|
4
|
+
import type { CONTROLLED_PROCESS_PLATFORM, CONTROLLED_PROCESS_PROTOCOL_VERSION, CONTROLLED_PROCESS_STATE, SUPERVISOR_AUTHENTICATION_FRAME_KIND, SUPERVISOR_AUTHENTICATION_REJECTION_REASON, SUPERVISOR_AUTHENTICATION_RESULT_KIND, SUPERVISOR_CHALLENGE_STATE_KIND } from "./values.js";
|
|
5
|
+
export type ControlledProcessPlatform = ValueOf<typeof CONTROLLED_PROCESS_PLATFORM>;
|
|
6
|
+
export type ControlledProcessState = ValueOf<typeof CONTROLLED_PROCESS_STATE>;
|
|
7
|
+
export type PersistedChildProcessAbsenceProof = Exclude<ChildProcessAbsenceProof, typeof CHILD_PROCESS_ABSENCE_PROOF.releasedReceipt>;
|
|
8
|
+
export type SupervisorBootId = Brand<string, "SupervisorBootId">;
|
|
9
|
+
export type SupervisorInstanceId = Brand<string, "SupervisorInstanceId">;
|
|
10
|
+
export type ControlledProcessRecordId = Brand<string, "ControlledProcessRecordId">;
|
|
11
|
+
export type SupervisorSocketLocator = Brand<string, "SupervisorSocketLocator">;
|
|
12
|
+
export type SupervisorCapability = Brand<string, "SupervisorCapability">;
|
|
13
|
+
export type ProcessStartToken = Brand<string, "ProcessStartToken">;
|
|
14
|
+
export type ControlledProcessRecordMac = Brand<string, "ControlledProcessRecordMac">;
|
|
15
|
+
export type SupervisorAuthenticationMac = Brand<string, "SupervisorAuthenticationMac">;
|
|
16
|
+
export type SupervisorClientNonce = Brand<string, "SupervisorClientNonce">;
|
|
17
|
+
export type SupervisorServerNonce = Brand<string, "SupervisorServerNonce">;
|
|
18
|
+
export type ShimProcessId = Brand<number, "ShimProcessId">;
|
|
19
|
+
export type ProcessStartTokenFields = {
|
|
20
|
+
readonly protocolVersion: typeof CONTROLLED_PROCESS_PROTOCOL_VERSION;
|
|
21
|
+
readonly platform: ControlledProcessPlatform;
|
|
22
|
+
readonly bootId: SupervisorBootId;
|
|
23
|
+
readonly supervisorInstanceId: SupervisorInstanceId;
|
|
24
|
+
readonly recordId: ControlledProcessRecordId;
|
|
25
|
+
readonly socketLocator: SupervisorSocketLocator;
|
|
26
|
+
readonly capability: SupervisorCapability;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Durable supervisor record. `pid` identifies the shim and the supervisor
|
|
30
|
+
* enforces the private spawn invariant `PGID === shim pid`. Consumers must not
|
|
31
|
+
* derive a raw process-group signaling authority from this record: only the
|
|
32
|
+
* authenticated supervisor protocol may terminate or prove group absence.
|
|
33
|
+
* That proof covers only absence of the shim leader's same POSIX process
|
|
34
|
+
* group. A descendant that escapes with `setsid` or `setpgid` is outside this
|
|
35
|
+
* guarantee; `absent` must not be interpreted as an OS-wide descendant census.
|
|
36
|
+
*/
|
|
37
|
+
export type ControlledProcessRecord = {
|
|
38
|
+
readonly protocolVersion: typeof CONTROLLED_PROCESS_PROTOCOL_VERSION;
|
|
39
|
+
readonly platform: ControlledProcessPlatform;
|
|
40
|
+
readonly bootId: SupervisorBootId;
|
|
41
|
+
readonly supervisorInstanceId: SupervisorInstanceId;
|
|
42
|
+
readonly recordId: ControlledProcessRecordId;
|
|
43
|
+
readonly socketLocator: SupervisorSocketLocator;
|
|
44
|
+
readonly pid: ShimProcessId;
|
|
45
|
+
readonly state: ControlledProcessState;
|
|
46
|
+
readonly absenceProof: PersistedChildProcessAbsenceProof | null;
|
|
47
|
+
};
|
|
48
|
+
export type SignedControlledProcessRecord = {
|
|
49
|
+
readonly record: ControlledProcessRecord;
|
|
50
|
+
readonly recordMac: ControlledProcessRecordMac;
|
|
51
|
+
};
|
|
52
|
+
export type SupervisorClientChallenge = {
|
|
53
|
+
readonly kind: typeof SUPERVISOR_AUTHENTICATION_FRAME_KIND.clientChallenge;
|
|
54
|
+
readonly recordId: ControlledProcessRecordId;
|
|
55
|
+
readonly clientNonce: SupervisorClientNonce;
|
|
56
|
+
};
|
|
57
|
+
export type SupervisorChallengeTranscript = {
|
|
58
|
+
readonly protocolVersion: typeof CONTROLLED_PROCESS_PROTOCOL_VERSION;
|
|
59
|
+
readonly recordId: ControlledProcessRecordId;
|
|
60
|
+
readonly clientNonce: SupervisorClientNonce;
|
|
61
|
+
readonly serverNonce: SupervisorServerNonce;
|
|
62
|
+
};
|
|
63
|
+
export type SupervisorChallenge = {
|
|
64
|
+
readonly kind: typeof SUPERVISOR_AUTHENTICATION_FRAME_KIND.supervisorChallenge;
|
|
65
|
+
readonly recordId: ControlledProcessRecordId;
|
|
66
|
+
readonly clientNonce: SupervisorClientNonce;
|
|
67
|
+
readonly serverNonce: SupervisorServerNonce;
|
|
68
|
+
readonly supervisorMac: SupervisorAuthenticationMac;
|
|
69
|
+
};
|
|
70
|
+
export type SupervisorClientProof = {
|
|
71
|
+
readonly kind: typeof SUPERVISOR_AUTHENTICATION_FRAME_KIND.clientProof;
|
|
72
|
+
readonly recordId: ControlledProcessRecordId;
|
|
73
|
+
readonly clientNonce: SupervisorClientNonce;
|
|
74
|
+
readonly serverNonce: SupervisorServerNonce;
|
|
75
|
+
readonly supervisorMac: SupervisorAuthenticationMac;
|
|
76
|
+
readonly clientMac: SupervisorAuthenticationMac;
|
|
77
|
+
};
|
|
78
|
+
export type SupervisorChallengeState = {
|
|
79
|
+
readonly kind: typeof SUPERVISOR_CHALLENGE_STATE_KIND.awaitingClient;
|
|
80
|
+
readonly transcript: SupervisorChallengeTranscript;
|
|
81
|
+
readonly supervisorMac: SupervisorAuthenticationMac;
|
|
82
|
+
} | {
|
|
83
|
+
readonly kind: typeof SUPERVISOR_CHALLENGE_STATE_KIND.consumed;
|
|
84
|
+
readonly transcript: SupervisorChallengeTranscript;
|
|
85
|
+
readonly supervisorMac: SupervisorAuthenticationMac;
|
|
86
|
+
};
|
|
87
|
+
export type SupervisorAuthenticationResult = {
|
|
88
|
+
readonly kind: typeof SUPERVISOR_AUTHENTICATION_RESULT_KIND.accepted;
|
|
89
|
+
readonly state: Extract<SupervisorChallengeState, {
|
|
90
|
+
readonly kind: typeof SUPERVISOR_CHALLENGE_STATE_KIND.consumed;
|
|
91
|
+
}>;
|
|
92
|
+
} | {
|
|
93
|
+
readonly kind: typeof SUPERVISOR_AUTHENTICATION_RESULT_KIND.rejected;
|
|
94
|
+
readonly reason: ValueOf<typeof SUPERVISOR_AUTHENTICATION_REJECTION_REASON>;
|
|
95
|
+
readonly state: Extract<SupervisorChallengeState, {
|
|
96
|
+
readonly kind: typeof SUPERVISOR_CHALLENGE_STATE_KIND.consumed;
|
|
97
|
+
}>;
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../../src/internal/controlled-process/model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ControlledProcessPlatform, ControlledProcessRecordId, SignedControlledProcessRecord, SupervisorSocketLocator } from "./model.js";
|
|
2
|
+
export declare function assertSecureRuntimeDirectory(runtimeDirectory: string, uid: number): Promise<string>;
|
|
3
|
+
export declare function resolveSupervisorSocketNamespace(platform: ControlledProcessPlatform, uid: number): Promise<string>;
|
|
4
|
+
export declare function supervisorSocketPath(input: {
|
|
5
|
+
readonly socketDirectory: string;
|
|
6
|
+
readonly socketLocator: SupervisorSocketLocator;
|
|
7
|
+
readonly platform: ControlledProcessPlatform;
|
|
8
|
+
}): string;
|
|
9
|
+
export declare class SignedRecordStore {
|
|
10
|
+
private readonly uid;
|
|
11
|
+
readonly filePath: string;
|
|
12
|
+
constructor(runtimeDirectory: string, recordId: ControlledProcessRecordId, uid: number);
|
|
13
|
+
read(): Promise<SignedControlledProcessRecord>;
|
|
14
|
+
write(record: SignedControlledProcessRecord): Promise<void>;
|
|
15
|
+
removeUnpublished(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=record-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-store.d.ts","sourceRoot":"","sources":["../../../src/internal/controlled-process/record-store.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EACzB,6BAA6B,EAC7B,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAkBpB,wBAAsB,4BAA4B,CAChD,gBAAgB,EAAE,MAAM,EACxB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAkBjB;AAED,wBAAsB,gCAAgC,CACpD,QAAQ,EAAE,yBAAyB,EACnC,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,MAAM,CAAC,CAiBjB;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,uBAAuB,CAAC;IAChD,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;CAC9C,GAAG,MAAM,CAWT;AAkDD,qBAAa,iBAAiB;IAM1B,OAAO,CAAC,QAAQ,CAAC,GAAG;IALtB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBAGxB,gBAAgB,EAAE,MAAM,EACxB,QAAQ,EAAE,yBAAyB,EAClB,GAAG,EAAE,MAAM;IAQxB,IAAI,IAAI,OAAO,CAAC,6BAA6B,CAAC;IAO9C,KAAK,CAAC,MAAM,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC;IAyB3D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAWzC"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { lstat, mkdir, open, readFile, realpath, rename, unlink, } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { decodeSignedControlledProcessRecord, encodeSignedControlledProcessRecord, } from "./record.js";
|
|
4
|
+
const RUNTIME_DIRECTORY_MODE = 0o700;
|
|
5
|
+
const RECORD_FILE_MODE = 0o600;
|
|
6
|
+
const PERMISSION_BITS = 0o777;
|
|
7
|
+
const RECORD_FILE_SUFFIX = ".record.json";
|
|
8
|
+
const SOCKET_FILE_SUFFIX = ".sock";
|
|
9
|
+
const SOCKET_PATH_LIMIT = { darwin: 103, linux: 107 };
|
|
10
|
+
const SOCKET_NAMESPACE_PARENT = {
|
|
11
|
+
darwin: "/private/tmp",
|
|
12
|
+
linux: "/tmp",
|
|
13
|
+
};
|
|
14
|
+
const SOCKET_NAMESPACE_PREFIX = "alpacakit-agents-";
|
|
15
|
+
export async function assertSecureRuntimeDirectory(runtimeDirectory, uid) {
|
|
16
|
+
const resolved = path.resolve(runtimeDirectory);
|
|
17
|
+
const stat = await lstat(resolved);
|
|
18
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
19
|
+
throw new Error("Supervisor runtime path must be a real directory.");
|
|
20
|
+
}
|
|
21
|
+
if (stat.uid !== uid) {
|
|
22
|
+
throw new Error("Supervisor runtime directory owner does not match uid.");
|
|
23
|
+
}
|
|
24
|
+
if ((stat.mode & PERMISSION_BITS) !== RUNTIME_DIRECTORY_MODE) {
|
|
25
|
+
throw new Error("Supervisor runtime directory mode must be 0700.");
|
|
26
|
+
}
|
|
27
|
+
if ((await realpath(resolved)) !== resolved) {
|
|
28
|
+
throw new Error("Supervisor runtime directory path must contain no symlink.");
|
|
29
|
+
}
|
|
30
|
+
return resolved;
|
|
31
|
+
}
|
|
32
|
+
export async function resolveSupervisorSocketNamespace(platform, uid) {
|
|
33
|
+
if (!Number.isSafeInteger(uid) || uid < 0) {
|
|
34
|
+
throw new Error("Supervisor socket namespace requires a real POSIX uid.");
|
|
35
|
+
}
|
|
36
|
+
const socketDirectory = path.join(SOCKET_NAMESPACE_PARENT[platform], `${SOCKET_NAMESPACE_PREFIX}${uid}`);
|
|
37
|
+
await assertRealDirectoryAncestors(path.dirname(socketDirectory));
|
|
38
|
+
try {
|
|
39
|
+
await mkdir(socketDirectory, { mode: RUNTIME_DIRECTORY_MODE });
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (!isErrno(error, "EEXIST")) {
|
|
43
|
+
throw error;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return assertSecureSocketDirectory(socketDirectory, uid);
|
|
47
|
+
}
|
|
48
|
+
export function supervisorSocketPath(input) {
|
|
49
|
+
const socketPath = path.join(input.socketDirectory, `${input.socketLocator}${SOCKET_FILE_SUFFIX}`);
|
|
50
|
+
if (Buffer.byteLength(socketPath, "utf8") > SOCKET_PATH_LIMIT[input.platform]) {
|
|
51
|
+
throw new Error("Supervisor Unix socket path exceeds the platform limit.");
|
|
52
|
+
}
|
|
53
|
+
return socketPath;
|
|
54
|
+
}
|
|
55
|
+
async function assertSecureSocketDirectory(socketDirectory, uid) {
|
|
56
|
+
const resolved = path.resolve(socketDirectory);
|
|
57
|
+
const stat = await lstat(resolved);
|
|
58
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
59
|
+
throw new Error("Supervisor socket namespace must be a real directory.");
|
|
60
|
+
}
|
|
61
|
+
if (stat.uid !== uid) {
|
|
62
|
+
throw new Error("Supervisor socket namespace owner does not match uid.");
|
|
63
|
+
}
|
|
64
|
+
if ((stat.mode & PERMISSION_BITS) !== RUNTIME_DIRECTORY_MODE) {
|
|
65
|
+
throw new Error("Supervisor socket namespace mode must be 0700.");
|
|
66
|
+
}
|
|
67
|
+
if ((await realpath(resolved)) !== resolved) {
|
|
68
|
+
throw new Error("Supervisor socket namespace path must contain no symlink.");
|
|
69
|
+
}
|
|
70
|
+
return resolved;
|
|
71
|
+
}
|
|
72
|
+
async function assertRealDirectoryAncestors(directory) {
|
|
73
|
+
const resolved = path.resolve(directory);
|
|
74
|
+
const { root } = path.parse(resolved);
|
|
75
|
+
let componentPath = root;
|
|
76
|
+
await assertRealDirectoryComponent(componentPath);
|
|
77
|
+
for (const component of path.relative(root, resolved).split(path.sep)) {
|
|
78
|
+
if (component.length === 0) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
componentPath = path.join(componentPath, component);
|
|
82
|
+
await assertRealDirectoryComponent(componentPath);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
async function assertRealDirectoryComponent(componentPath) {
|
|
86
|
+
const stat = await lstat(componentPath);
|
|
87
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
88
|
+
throw new Error("Supervisor socket namespace ancestors must be real directories.");
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export class SignedRecordStore {
|
|
92
|
+
uid;
|
|
93
|
+
filePath;
|
|
94
|
+
constructor(runtimeDirectory, recordId, uid) {
|
|
95
|
+
this.uid = uid;
|
|
96
|
+
this.filePath = path.join(runtimeDirectory, `${recordId}${RECORD_FILE_SUFFIX}`);
|
|
97
|
+
}
|
|
98
|
+
async read() {
|
|
99
|
+
await assertSecureOwnedFile(this.filePath, this.uid);
|
|
100
|
+
return decodeSignedControlledProcessRecord(await readFile(this.filePath, "utf8"));
|
|
101
|
+
}
|
|
102
|
+
async write(record) {
|
|
103
|
+
await assertReplaceableTarget(this.filePath, this.uid);
|
|
104
|
+
const temporaryPath = `${this.filePath}.tmp-${process.pid}-${Date.now()}`;
|
|
105
|
+
const handle = await open(temporaryPath, "wx", RECORD_FILE_MODE);
|
|
106
|
+
let renamed = false;
|
|
107
|
+
try {
|
|
108
|
+
await handle.chmod(RECORD_FILE_MODE);
|
|
109
|
+
await handle.writeFile(encodeSignedControlledProcessRecord(record), "utf8");
|
|
110
|
+
await handle.sync();
|
|
111
|
+
await handle.close();
|
|
112
|
+
await rename(temporaryPath, this.filePath);
|
|
113
|
+
renamed = true;
|
|
114
|
+
await syncDirectory(path.dirname(this.filePath));
|
|
115
|
+
await assertSecureOwnedFile(this.filePath, this.uid);
|
|
116
|
+
}
|
|
117
|
+
finally {
|
|
118
|
+
await handle.close().catch(() => undefined);
|
|
119
|
+
if (!renamed) {
|
|
120
|
+
await unlink(temporaryPath).catch(() => undefined);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async removeUnpublished() {
|
|
125
|
+
try {
|
|
126
|
+
await unlink(this.filePath);
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
if (!isErrno(error, "ENOENT")) {
|
|
130
|
+
throw error;
|
|
131
|
+
}
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
await syncDirectory(path.dirname(this.filePath));
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
async function assertReplaceableTarget(filePath, uid) {
|
|
138
|
+
try {
|
|
139
|
+
await assertSecureOwnedFile(filePath, uid);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
if (!isErrno(error, "ENOENT")) {
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async function assertSecureOwnedFile(filePath, uid) {
|
|
148
|
+
const stat = await lstat(filePath);
|
|
149
|
+
if (stat.isSymbolicLink() || !stat.isFile()) {
|
|
150
|
+
throw new Error("Supervisor record must be a real regular file.");
|
|
151
|
+
}
|
|
152
|
+
if (stat.uid !== uid) {
|
|
153
|
+
throw new Error("Supervisor record owner does not match uid.");
|
|
154
|
+
}
|
|
155
|
+
if ((stat.mode & PERMISSION_BITS) !== RECORD_FILE_MODE) {
|
|
156
|
+
throw new Error("Supervisor record mode must be 0600.");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function syncDirectory(directory) {
|
|
160
|
+
const handle = await open(directory, "r");
|
|
161
|
+
try {
|
|
162
|
+
await handle.sync();
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
await handle.close();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function isErrno(error, code) {
|
|
169
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
170
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ValueOf } from "@alpacakit/core";
|
|
2
|
+
import type { ControlledProcessRecord, ProcessStartTokenFields, SignedControlledProcessRecord, SupervisorCapability } from "./model.js";
|
|
3
|
+
import { SUPERVISOR_MAC_DOMAIN } from "./values.js";
|
|
4
|
+
export declare function encodeCanonicalControlledProcessRecord(record: ControlledProcessRecord): string;
|
|
5
|
+
export declare function signControlledProcessRecord(record: ControlledProcessRecord, capability: SupervisorCapability): SignedControlledProcessRecord;
|
|
6
|
+
export declare function encodeSignedControlledProcessRecord(signedRecord: SignedControlledProcessRecord): string;
|
|
7
|
+
export declare function decodeSignedControlledProcessRecord(value: string): SignedControlledProcessRecord;
|
|
8
|
+
export declare function controlledProcessRecordMatchesToken(record: ControlledProcessRecord, token: ProcessStartTokenFields): boolean;
|
|
9
|
+
export declare function verifySignedControlledProcessRecord(signedRecordInput: unknown, identityInput: unknown): signedRecordInput is SignedControlledProcessRecord;
|
|
10
|
+
export declare function createDomainSeparatedMac(domain: ValueOf<typeof SUPERVISOR_MAC_DOMAIN>, transcript: string, capability: SupervisorCapability): string;
|
|
11
|
+
export declare function constantTimeMacEqual(left: string, right: string): boolean;
|
|
12
|
+
//# sourceMappingURL=record.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../../../src/internal/controlled-process/record.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,KAAK,EACV,uBAAuB,EAEvB,uBAAuB,EACvB,6BAA6B,EAC7B,oBAAoB,EACrB,MAAM,YAAY,CAAC;AASpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAMpD,wBAAgB,sCAAsC,CACpD,MAAM,EAAE,uBAAuB,GAC9B,MAAM,CAYR;AAED,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,uBAAuB,EAC/B,UAAU,EAAE,oBAAoB,GAC/B,6BAA6B,CAM/B;AAED,wBAAgB,mCAAmC,CACjD,YAAY,EAAE,6BAA6B,GAC1C,MAAM,CAMR;AAED,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,MAAM,GACZ,6BAA6B,CAQ/B;AAED,wBAAgB,mCAAmC,CACjD,MAAM,EAAE,uBAAuB,EAC/B,KAAK,EAAE,uBAAuB,GAC7B,OAAO,CAST;AAED,wBAAgB,mCAAmC,CACjD,iBAAiB,EAAE,OAAO,EAC1B,aAAa,EAAE,OAAO,GACrB,iBAAiB,IAAI,6BAA6B,CA0BpD;AA0BD,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,OAAO,CAAC,OAAO,qBAAqB,CAAC,EAC7C,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,oBAAoB,GAC/B,MAAM,CAMR;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAQzE"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { readJsonRecord } from "../../core/json.js";
|
|
3
|
+
import { controlledProcessIdentitySchema, controlledProcessRecordSchema, controlledProcessRecordMacSchema, lowerHex32ByteSchema, signedControlledProcessRecordSchema, } from "./schema.js";
|
|
4
|
+
import { decodeProcessStartToken } from "./token.js";
|
|
5
|
+
import { SUPERVISOR_MAC_DOMAIN } from "./values.js";
|
|
6
|
+
const MAC_ENCODING = "hex";
|
|
7
|
+
const MAC_ALGORITHM = "sha256";
|
|
8
|
+
const MAC_TRANSCRIPT_SEPARATOR = "\0";
|
|
9
|
+
export function encodeCanonicalControlledProcessRecord(record) {
|
|
10
|
+
return JSON.stringify({
|
|
11
|
+
protocolVersion: record.protocolVersion,
|
|
12
|
+
platform: record.platform,
|
|
13
|
+
bootId: record.bootId,
|
|
14
|
+
supervisorInstanceId: record.supervisorInstanceId,
|
|
15
|
+
recordId: record.recordId,
|
|
16
|
+
socketLocator: record.socketLocator,
|
|
17
|
+
pid: record.pid,
|
|
18
|
+
state: record.state,
|
|
19
|
+
absenceProof: record.absenceProof,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
export function signControlledProcessRecord(record, capability) {
|
|
23
|
+
const validatedRecord = controlledProcessRecordSchema.parse(record);
|
|
24
|
+
return {
|
|
25
|
+
record: validatedRecord,
|
|
26
|
+
recordMac: createRecordMac(validatedRecord, capability),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export function encodeSignedControlledProcessRecord(signedRecord) {
|
|
30
|
+
const validatedRecord = signedControlledProcessRecordSchema.parse(signedRecord);
|
|
31
|
+
return `{"record":${encodeCanonicalControlledProcessRecord(validatedRecord.record)},"recordMac":"${validatedRecord.recordMac}"}`;
|
|
32
|
+
}
|
|
33
|
+
export function decodeSignedControlledProcessRecord(value) {
|
|
34
|
+
const parsed = signedControlledProcessRecordSchema.parse(readJsonRecord(value));
|
|
35
|
+
if (encodeSignedControlledProcessRecord(parsed) !== value) {
|
|
36
|
+
throw new Error("Controlled process record is not canonically encoded.");
|
|
37
|
+
}
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
export function controlledProcessRecordMatchesToken(record, token) {
|
|
41
|
+
return (record.protocolVersion === token.protocolVersion &&
|
|
42
|
+
record.platform === token.platform &&
|
|
43
|
+
record.bootId === token.bootId &&
|
|
44
|
+
record.supervisorInstanceId === token.supervisorInstanceId &&
|
|
45
|
+
record.recordId === token.recordId &&
|
|
46
|
+
record.socketLocator === token.socketLocator);
|
|
47
|
+
}
|
|
48
|
+
export function verifySignedControlledProcessRecord(signedRecordInput, identityInput) {
|
|
49
|
+
const signedRecord = signedControlledProcessRecordSchema.safeParse(signedRecordInput);
|
|
50
|
+
if (!signedRecord.success) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const identity = controlledProcessIdentitySchema.safeParse(identityInput);
|
|
54
|
+
if (!identity.success) {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const token = decodeProcessStartToken(identity.data.processStartToken);
|
|
58
|
+
if (!controlledProcessRecordMatchesIdentity(signedRecord.data.record, token, identity.data)) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return constantTimeMacEqual(signedRecord.data.recordMac, createRecordMac(signedRecord.data.record, token.capability));
|
|
62
|
+
}
|
|
63
|
+
function controlledProcessRecordMatchesIdentity(record, token, identity) {
|
|
64
|
+
return (controlledProcessRecordMatchesToken(record, token) &&
|
|
65
|
+
record.pid === identity.pid);
|
|
66
|
+
}
|
|
67
|
+
function createRecordMac(record, capability) {
|
|
68
|
+
return controlledProcessRecordMacSchema.parse(createDomainSeparatedMac(SUPERVISOR_MAC_DOMAIN.record, encodeCanonicalControlledProcessRecord(record), capability));
|
|
69
|
+
}
|
|
70
|
+
export function createDomainSeparatedMac(domain, transcript, capability) {
|
|
71
|
+
return createHmac(MAC_ALGORITHM, Buffer.from(capability, MAC_ENCODING))
|
|
72
|
+
.update(domain)
|
|
73
|
+
.update(MAC_TRANSCRIPT_SEPARATOR)
|
|
74
|
+
.update(transcript)
|
|
75
|
+
.digest(MAC_ENCODING);
|
|
76
|
+
}
|
|
77
|
+
export function constantTimeMacEqual(left, right) {
|
|
78
|
+
const leftBytes = decodeMac(left);
|
|
79
|
+
const rightBytes = decodeMac(right);
|
|
80
|
+
return (leftBytes !== null &&
|
|
81
|
+
rightBytes !== null &&
|
|
82
|
+
timingSafeEqual(leftBytes, rightBytes));
|
|
83
|
+
}
|
|
84
|
+
function decodeMac(value) {
|
|
85
|
+
const parsed = lowerHex32ByteSchema.safeParse(value);
|
|
86
|
+
return parsed.success ? Buffer.from(parsed.data, MAC_ENCODING) : null;
|
|
87
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import type { ControlledProcessRecordId, ControlledProcessRecordMac, ProcessStartToken, ShimProcessId, SupervisorAuthenticationMac, SupervisorBootId, SupervisorCapability, SupervisorClientNonce, SupervisorInstanceId, SupervisorServerNonce, SupervisorSocketLocator } from "./model.js";
|
|
3
|
+
export declare const lowerHex32ByteSchema: z.ZodString;
|
|
4
|
+
export declare const controlledProcessPlatformSchema: z.ZodEnum<{
|
|
5
|
+
darwin: "darwin";
|
|
6
|
+
linux: "linux";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const controlledProcessStateSchema: z.ZodEnum<{
|
|
9
|
+
absent: "absent";
|
|
10
|
+
reserved: "reserved";
|
|
11
|
+
acked: "acked";
|
|
12
|
+
running: "running";
|
|
13
|
+
term: "term";
|
|
14
|
+
kill_sent: "kill_sent";
|
|
15
|
+
released: "released";
|
|
16
|
+
}>;
|
|
17
|
+
export declare const supervisorBootIdSchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorBootId, string>>;
|
|
18
|
+
export declare const supervisorInstanceIdSchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorInstanceId, string>>;
|
|
19
|
+
export declare const controlledProcessRecordIdSchema: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordId, string>>;
|
|
20
|
+
export declare const supervisorSocketLocatorSchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorSocketLocator, string>>;
|
|
21
|
+
export declare const supervisorCapabilitySchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorCapability, string>>;
|
|
22
|
+
export declare const controlledProcessRecordMacSchema: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordMac, string>>;
|
|
23
|
+
export declare const supervisorAuthenticationMacSchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorAuthenticationMac, string>>;
|
|
24
|
+
export declare const supervisorClientNonceSchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorClientNonce, string>>;
|
|
25
|
+
export declare const supervisorServerNonceSchema: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorServerNonce, string>>;
|
|
26
|
+
export declare const shimProcessIdSchema: z.ZodPipe<z.ZodNumber, z.ZodTransform<ShimProcessId, number>>;
|
|
27
|
+
export declare const processStartTokenSchema: z.ZodPipe<z.ZodString, z.ZodTransform<ProcessStartToken, string>>;
|
|
28
|
+
export declare const controlledProcessIdentitySchema: z.ZodReadonly<z.ZodObject<{
|
|
29
|
+
pid: z.ZodPipe<z.ZodNumber, z.ZodTransform<ShimProcessId, number>>;
|
|
30
|
+
processStartToken: z.ZodPipe<z.ZodString, z.ZodTransform<ProcessStartToken, string>>;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
export declare const controlledProcessRecordSchema: z.ZodReadonly<z.ZodObject<{
|
|
33
|
+
protocolVersion: z.ZodLiteral<"alpacakit-supervisor-v1">;
|
|
34
|
+
platform: z.ZodEnum<{
|
|
35
|
+
darwin: "darwin";
|
|
36
|
+
linux: "linux";
|
|
37
|
+
}>;
|
|
38
|
+
bootId: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorBootId, string>>;
|
|
39
|
+
supervisorInstanceId: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorInstanceId, string>>;
|
|
40
|
+
recordId: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordId, string>>;
|
|
41
|
+
socketLocator: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorSocketLocator, string>>;
|
|
42
|
+
pid: z.ZodPipe<z.ZodNumber, z.ZodTransform<ShimProcessId, number>>;
|
|
43
|
+
state: z.ZodEnum<{
|
|
44
|
+
absent: "absent";
|
|
45
|
+
reserved: "reserved";
|
|
46
|
+
acked: "acked";
|
|
47
|
+
running: "running";
|
|
48
|
+
term: "term";
|
|
49
|
+
kill_sent: "kill_sent";
|
|
50
|
+
released: "released";
|
|
51
|
+
}>;
|
|
52
|
+
absenceProof: z.ZodNullable<z.ZodEnum<{
|
|
53
|
+
supervisor_probe: "supervisor_probe";
|
|
54
|
+
boot_changed: "boot_changed";
|
|
55
|
+
}>>;
|
|
56
|
+
}, z.core.$strip>>;
|
|
57
|
+
export declare const signedControlledProcessRecordSchema: z.ZodReadonly<z.ZodObject<{
|
|
58
|
+
record: z.ZodReadonly<z.ZodObject<{
|
|
59
|
+
protocolVersion: z.ZodLiteral<"alpacakit-supervisor-v1">;
|
|
60
|
+
platform: z.ZodEnum<{
|
|
61
|
+
darwin: "darwin";
|
|
62
|
+
linux: "linux";
|
|
63
|
+
}>;
|
|
64
|
+
bootId: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorBootId, string>>;
|
|
65
|
+
supervisorInstanceId: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorInstanceId, string>>;
|
|
66
|
+
recordId: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordId, string>>;
|
|
67
|
+
socketLocator: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorSocketLocator, string>>;
|
|
68
|
+
pid: z.ZodPipe<z.ZodNumber, z.ZodTransform<ShimProcessId, number>>;
|
|
69
|
+
state: z.ZodEnum<{
|
|
70
|
+
absent: "absent";
|
|
71
|
+
reserved: "reserved";
|
|
72
|
+
acked: "acked";
|
|
73
|
+
running: "running";
|
|
74
|
+
term: "term";
|
|
75
|
+
kill_sent: "kill_sent";
|
|
76
|
+
released: "released";
|
|
77
|
+
}>;
|
|
78
|
+
absenceProof: z.ZodNullable<z.ZodEnum<{
|
|
79
|
+
supervisor_probe: "supervisor_probe";
|
|
80
|
+
boot_changed: "boot_changed";
|
|
81
|
+
}>>;
|
|
82
|
+
}, z.core.$strip>>;
|
|
83
|
+
recordMac: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordMac, string>>;
|
|
84
|
+
}, z.core.$strip>>;
|
|
85
|
+
export declare const supervisorClientChallengeSchema: z.ZodReadonly<z.ZodObject<{
|
|
86
|
+
kind: z.ZodLiteral<"client_challenge">;
|
|
87
|
+
recordId: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordId, string>>;
|
|
88
|
+
clientNonce: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorClientNonce, string>>;
|
|
89
|
+
}, z.core.$strip>>;
|
|
90
|
+
export declare const supervisorChallengeSchema: z.ZodReadonly<z.ZodObject<{
|
|
91
|
+
kind: z.ZodLiteral<"supervisor_challenge">;
|
|
92
|
+
recordId: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordId, string>>;
|
|
93
|
+
clientNonce: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorClientNonce, string>>;
|
|
94
|
+
serverNonce: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorServerNonce, string>>;
|
|
95
|
+
supervisorMac: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorAuthenticationMac, string>>;
|
|
96
|
+
}, z.core.$strip>>;
|
|
97
|
+
export declare const supervisorClientProofSchema: z.ZodReadonly<z.ZodObject<{
|
|
98
|
+
kind: z.ZodLiteral<"client_proof">;
|
|
99
|
+
recordId: z.ZodPipe<z.ZodString, z.ZodTransform<ControlledProcessRecordId, string>>;
|
|
100
|
+
clientNonce: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorClientNonce, string>>;
|
|
101
|
+
serverNonce: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorServerNonce, string>>;
|
|
102
|
+
supervisorMac: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorAuthenticationMac, string>>;
|
|
103
|
+
clientMac: z.ZodPipe<z.ZodString, z.ZodTransform<SupervisorAuthenticationMac, string>>;
|
|
104
|
+
}, z.core.$strip>>;
|
|
105
|
+
export declare const childProcessTerminationResultSchema: z.ZodDiscriminatedUnion<[z.ZodReadonly<z.ZodObject<{
|
|
106
|
+
kind: z.ZodLiteral<"absent">;
|
|
107
|
+
proof: z.ZodEnum<{
|
|
108
|
+
supervisor_probe: "supervisor_probe";
|
|
109
|
+
boot_changed: "boot_changed";
|
|
110
|
+
released_receipt: "released_receipt";
|
|
111
|
+
}>;
|
|
112
|
+
}, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
|
|
113
|
+
kind: z.ZodLiteral<"pending">;
|
|
114
|
+
phase: z.ZodEnum<{
|
|
115
|
+
term_grace: "term_grace";
|
|
116
|
+
kill_probe: "kill_probe";
|
|
117
|
+
}>;
|
|
118
|
+
retryAfterMs: z.ZodNumber;
|
|
119
|
+
}, z.core.$strip>>, z.ZodReadonly<z.ZodObject<{
|
|
120
|
+
kind: z.ZodLiteral<"unkillable">;
|
|
121
|
+
reason: z.ZodEnum<{
|
|
122
|
+
invalid_identity: "invalid_identity";
|
|
123
|
+
boot_identity_unavailable: "boot_identity_unavailable";
|
|
124
|
+
supervisor_unreachable: "supervisor_unreachable";
|
|
125
|
+
record_authentication_failed: "record_authentication_failed";
|
|
126
|
+
record_identity_mismatch: "record_identity_mismatch";
|
|
127
|
+
protocol_failure: "protocol_failure";
|
|
128
|
+
probe_permission_denied: "probe_permission_denied";
|
|
129
|
+
shim_lost_with_live_group: "shim_lost_with_live_group";
|
|
130
|
+
group_survived_sigkill: "group_survived_sigkill";
|
|
131
|
+
}>;
|
|
132
|
+
}, z.core.$strip>>], "kind">;
|
|
133
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/internal/controlled-process/schema.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAWxB,OAAO,KAAK,EAEV,yBAAyB,EACzB,0BAA0B,EAC1B,iBAAiB,EACjB,aAAa,EAEb,2BAA2B,EAC3B,gBAAgB,EAChB,oBAAoB,EAGpB,qBAAqB,EAErB,oBAAoB,EACpB,qBAAqB,EACrB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAcpB,eAAO,MAAM,oBAAoB,aAA8C,CAAC;AAEhF,eAAO,MAAM,+BAA+B;;;EAE3C,CAAC;AACF,eAAO,MAAM,4BAA4B;;;;;;;;EAExC,CAAC;AAEF,eAAO,MAAM,sBAAsB,kEAElC,CAAC;AACF,eAAO,MAAM,0BAA0B,sEAEtC,CAAC;AACF,eAAO,MAAM,+BAA+B,2EAE3C,CAAC;AACF,eAAO,MAAM,6BAA6B,yEAEzC,CAAC;AACF,eAAO,MAAM,0BAA0B,sEAEtC,CAAC;AACF,eAAO,MAAM,gCAAgC,4EAE5C,CAAC;AACF,eAAO,MAAM,iCAAiC,6EAE7C,CAAC;AACF,eAAO,MAAM,2BAA2B,uEAEvC,CAAC;AACF,eAAO,MAAM,2BAA2B,uEAEvC,CAAC;AACF,eAAO,MAAM,mBAAmB,+DAKe,CAAC;AAEhD,eAAO,MAAM,uBAAuB,mEAGe,CAAC;AAEpD,eAAO,MAAM,+BAA+B;;;kBAGA,CAAC;AAkB7C,eAAO,MAAM,6BAA6B;;;;;;;;;;;;;;;;;;;;;;;;kBAWO,CAAC;AAElD,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAGK,CAAC;AAEtD,eAAO,MAAM,+BAA+B;;;;kBAIK,CAAC;AAElD,eAAO,MAAM,yBAAyB;;;;;;kBAMK,CAAC;AAE5C,eAAO,MAAM,2BAA2B;;;;;;;kBAOK,CAAC;AAE9C,eAAO,MAAM,mCAAmC;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAiBI,CAAC"}
|