@lumenflow/control-plane-sdk 4.24.0 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/agent-host-registry.d.ts +61 -0
  2. package/dist/agent-host-registry.d.ts.map +1 -0
  3. package/dist/agent-host-registry.js +196 -0
  4. package/dist/agent-host-registry.js.map +1 -0
  5. package/dist/authenticate.d.ts +59 -0
  6. package/dist/authenticate.d.ts.map +1 -0
  7. package/dist/authenticate.js +113 -0
  8. package/dist/authenticate.js.map +1 -0
  9. package/dist/delegation-registry.d.ts +107 -0
  10. package/dist/delegation-registry.d.ts.map +1 -0
  11. package/dist/delegation-registry.js +160 -0
  12. package/dist/delegation-registry.js.map +1 -0
  13. package/dist/index.d.ts +5 -0
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +5 -0
  16. package/dist/index.js.map +1 -1
  17. package/dist/mock/mock-control-plane-sync-port.d.ts +2 -2
  18. package/dist/mock/mock-control-plane-sync-port.d.ts.map +1 -1
  19. package/dist/mock/mock-control-plane-sync-port.js.map +1 -1
  20. package/dist/pack-outcome-descriptor.d.ts +42 -0
  21. package/dist/pack-outcome-descriptor.d.ts.map +1 -0
  22. package/dist/pack-outcome-descriptor.js +4 -0
  23. package/dist/pack-outcome-descriptor.js.map +1 -0
  24. package/dist/policy-mode.d.ts +2 -2
  25. package/dist/policy-mode.d.ts.map +1 -1
  26. package/dist/policy-mode.js +12 -4
  27. package/dist/policy-mode.js.map +1 -1
  28. package/dist/replay-artifact.d.ts +48 -0
  29. package/dist/replay-artifact.d.ts.map +1 -0
  30. package/dist/replay-artifact.js +4 -0
  31. package/dist/replay-artifact.js.map +1 -0
  32. package/dist/scope-grammar.d.ts +12 -0
  33. package/dist/scope-grammar.d.ts.map +1 -0
  34. package/dist/scope-grammar.js +109 -0
  35. package/dist/scope-grammar.js.map +1 -0
  36. package/dist/sync-port.d.ts +261 -24
  37. package/dist/sync-port.d.ts.map +1 -1
  38. package/dist/sync-port.js +92 -0
  39. package/dist/sync-port.js.map +1 -1
  40. package/dist/wu-events.d.ts +197 -0
  41. package/dist/wu-events.d.ts.map +1 -0
  42. package/dist/wu-events.js +109 -0
  43. package/dist/wu-events.js.map +1 -0
  44. package/package.json +4 -1
@@ -0,0 +1,61 @@
1
+ export declare const AGENT_HOST_REACHABILITY_CLASSES: {
2
+ readonly REVERSE_TUNNEL: "reverse-tunnel";
3
+ readonly PUBLIC: "public";
4
+ readonly LAN: "lan";
5
+ readonly UNREACHABLE: "unreachable";
6
+ };
7
+ export declare const AGENT_HOST_REACHABILITY_CLASS_VALUES: readonly ["reverse-tunnel", "public", "lan", "unreachable"];
8
+ export type AgentHostReachabilityClass = (typeof AGENT_HOST_REACHABILITY_CLASS_VALUES)[number];
9
+ export interface AgentHostEnrollmentInput {
10
+ workspace_id: string;
11
+ session_id: string;
12
+ agent_id: string;
13
+ host_id?: string;
14
+ client_type?: string;
15
+ agent_version?: string;
16
+ lane?: string;
17
+ wu_id?: string;
18
+ enrolled_at?: string;
19
+ last_seen_at?: string;
20
+ reachable_http_url: string | null;
21
+ reachability_class: AgentHostReachabilityClass;
22
+ health_endpoint: string | null;
23
+ tls_fingerprint: string | null;
24
+ }
25
+ export interface AgentHostRecord extends AgentHostEnrollmentInput {
26
+ last_seen_at: string;
27
+ }
28
+ export interface ListAgentHostsInput {
29
+ workspace_id: string;
30
+ }
31
+ export interface ListAgentHostsResult {
32
+ hosts: AgentHostRecord[];
33
+ }
34
+ export interface QueuedAgentToolCommand {
35
+ command_id: string;
36
+ tool_name: string;
37
+ input?: unknown;
38
+ context: Record<string, unknown>;
39
+ enqueued_at?: string;
40
+ }
41
+ export interface AgentHostHeartbeatEnvelope {
42
+ queued_commands?: QueuedAgentToolCommand[];
43
+ }
44
+ export interface HttpAgentHostRegistryClientOptions {
45
+ fetchFn?: typeof fetch;
46
+ }
47
+ export declare function normalizeReachabilityClass(value: unknown): AgentHostReachabilityClass | null;
48
+ export declare function inferAgentHostReachabilityClass(reachableHttpUrl: string | null | undefined, explicitReachabilityClass?: AgentHostReachabilityClass | null): AgentHostReachabilityClass;
49
+ export declare function normalizeAgentHostEnrollment(input: AgentHostEnrollmentInput): AgentHostEnrollmentInput;
50
+ export declare function normalizeAgentHostRecord(input: AgentHostEnrollmentInput): AgentHostRecord;
51
+ export declare function buildAgentHostRegistryPath(workspaceId: string): string;
52
+ export declare function buildAgentHostRegistryUrl(endpoint: string, workspaceId: string): string;
53
+ export declare class HttpAgentHostRegistryClient {
54
+ private readonly endpoint;
55
+ private readonly token;
56
+ private readonly fetchFn;
57
+ constructor(endpoint: string, token: string, options?: HttpAgentHostRegistryClientOptions);
58
+ registerHost(input: AgentHostEnrollmentInput): Promise<AgentHostRecord>;
59
+ listHosts(input: ListAgentHostsInput): Promise<ListAgentHostsResult>;
60
+ }
61
+ //# sourceMappingURL=agent-host-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-host-registry.d.ts","sourceRoot":"","sources":["../src/agent-host-registry.ts"],"names":[],"mappings":"AAmCA,eAAO,MAAM,+BAA+B;;;;;CAKlC,CAAC;AAEX,eAAO,MAAM,oCAAoC,6DAKvC,CAAC;AAEX,MAAM,MAAM,0BAA0B,GAAG,CAAC,OAAO,oCAAoC,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/F,MAAM,WAAW,wBAAwB;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,eAAgB,SAAQ,wBAAwB;IAC/D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,eAAe,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,0BAA0B;IACzC,eAAe,CAAC,EAAE,sBAAsB,EAAE,CAAC;CAC5C;AAED,MAAM,WAAW,kCAAkC;IACjD,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB;AAwED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,GAAG,IAAI,CAO5F;AAED,wBAAgB,+BAA+B,CAC7C,gBAAgB,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC3C,yBAAyB,CAAC,EAAE,0BAA0B,GAAG,IAAI,GAC5D,0BAA0B,CAmB5B;AAED,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,wBAAwB,GAC9B,wBAAwB,CAoB1B;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,wBAAwB,GAAG,eAAe,CAMzF;AAED,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAItE;AAED,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEvF;AAaD,qBAAa,2BAA2B;IAIpC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,KAAK;IAJxB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;gBAGpB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EAC9B,OAAO,GAAE,kCAAuC;IAKrC,YAAY,CAAC,KAAK,EAAE,wBAAwB,GAAG,OAAO,CAAC,eAAe,CAAC;IAsBvE,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAsBlF"}
@@ -0,0 +1,196 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { isIP } from 'node:net';
4
+ const HTTP_METHOD = {
5
+ GET: 'GET',
6
+ POST: 'POST',
7
+ };
8
+ const HTTP_HEADER = {
9
+ AUTHORIZATION: 'authorization',
10
+ CONTENT_TYPE: 'content-type',
11
+ };
12
+ const CONTENT_TYPE_JSON = 'application/json';
13
+ const AGENT_HOST_REGISTRY_ROUTE_PREFIX = '/api/v1/workspaces';
14
+ const AGENT_HOST_REGISTRY_ROUTE_SUFFIX = 'agent-hosts';
15
+ const PRIVATE_HOSTNAME_SUFFIXES = ['.local', '.internal', '.lan'];
16
+ const PRIVATE_IPV4_PREFIXES = ['10.', '127.', '169.254.', '192.168.'];
17
+ const PRIVATE_IPV4_SECOND_OCTET_172_MIN = 16;
18
+ const PRIVATE_IPV4_SECOND_OCTET_172_MAX = 31;
19
+ const PRIVATE_IPV6_PREFIXES = ['::1', 'fc', 'fd', 'fe80'];
20
+ const REVERSE_TUNNEL_HOST_SUFFIXES = [
21
+ '.gradio.live',
22
+ '.loca.lt',
23
+ '.ngrok-free.app',
24
+ '.ngrok.app',
25
+ '.ngrok.io',
26
+ '.trycloudflare.com',
27
+ '.tunnelmole.net',
28
+ ];
29
+ export const AGENT_HOST_REACHABILITY_CLASSES = {
30
+ REVERSE_TUNNEL: 'reverse-tunnel',
31
+ PUBLIC: 'public',
32
+ LAN: 'lan',
33
+ UNREACHABLE: 'unreachable',
34
+ };
35
+ export const AGENT_HOST_REACHABILITY_CLASS_VALUES = [
36
+ AGENT_HOST_REACHABILITY_CLASSES.REVERSE_TUNNEL,
37
+ AGENT_HOST_REACHABILITY_CLASSES.PUBLIC,
38
+ AGENT_HOST_REACHABILITY_CLASSES.LAN,
39
+ AGENT_HOST_REACHABILITY_CLASSES.UNREACHABLE,
40
+ ];
41
+ function asNonEmptyString(value) {
42
+ return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
43
+ }
44
+ function normalizeEndpoint(endpoint) {
45
+ return endpoint.endsWith('/') ? endpoint.slice(0, endpoint.length - 1) : endpoint;
46
+ }
47
+ function normalizeOptionalUrl(value) {
48
+ const normalizedValue = asNonEmptyString(value);
49
+ if (!normalizedValue) {
50
+ return null;
51
+ }
52
+ try {
53
+ return new URL(normalizedValue).toString().replace(/\/$/, '');
54
+ }
55
+ catch {
56
+ return null;
57
+ }
58
+ }
59
+ function isPrivateIpv4Address(hostname) {
60
+ if (PRIVATE_IPV4_PREFIXES.some((prefix) => hostname.startsWith(prefix))) {
61
+ return true;
62
+ }
63
+ const octets = hostname.split('.');
64
+ if (octets.length !== 4 || octets[0] !== '172') {
65
+ return false;
66
+ }
67
+ const secondOctet = Number.parseInt(octets[1] ?? '', 10);
68
+ return (Number.isFinite(secondOctet) &&
69
+ secondOctet >= PRIVATE_IPV4_SECOND_OCTET_172_MIN &&
70
+ secondOctet <= PRIVATE_IPV4_SECOND_OCTET_172_MAX);
71
+ }
72
+ function isPrivateIpv6Address(hostname) {
73
+ const lowerHostname = hostname.toLowerCase();
74
+ return PRIVATE_IPV6_PREFIXES.some((prefix) => lowerHostname.startsWith(prefix));
75
+ }
76
+ function isLanHostname(hostname) {
77
+ const normalizedHostname = hostname.trim().toLowerCase();
78
+ if (normalizedHostname.length === 0 || normalizedHostname === 'localhost') {
79
+ return true;
80
+ }
81
+ if (PRIVATE_HOSTNAME_SUFFIXES.some((suffix) => normalizedHostname.endsWith(suffix))) {
82
+ return true;
83
+ }
84
+ const ipKind = isIP(normalizedHostname);
85
+ if (ipKind === 4) {
86
+ return isPrivateIpv4Address(normalizedHostname);
87
+ }
88
+ if (ipKind === 6) {
89
+ return isPrivateIpv6Address(normalizedHostname);
90
+ }
91
+ return false;
92
+ }
93
+ function isReverseTunnelHostname(hostname) {
94
+ const normalizedHostname = hostname.trim().toLowerCase();
95
+ return REVERSE_TUNNEL_HOST_SUFFIXES.some((suffix) => normalizedHostname.endsWith(suffix));
96
+ }
97
+ export function normalizeReachabilityClass(value) {
98
+ if (typeof value !== 'string') {
99
+ return null;
100
+ }
101
+ const normalized = value.trim().toLowerCase();
102
+ return AGENT_HOST_REACHABILITY_CLASS_VALUES.find((entry) => entry === normalized) ?? null;
103
+ }
104
+ export function inferAgentHostReachabilityClass(reachableHttpUrl, explicitReachabilityClass) {
105
+ if (explicitReachabilityClass) {
106
+ return explicitReachabilityClass;
107
+ }
108
+ const normalizedUrl = normalizeOptionalUrl(reachableHttpUrl);
109
+ if (!normalizedUrl) {
110
+ return AGENT_HOST_REACHABILITY_CLASSES.UNREACHABLE;
111
+ }
112
+ const hostname = new URL(normalizedUrl).hostname;
113
+ if (isReverseTunnelHostname(hostname)) {
114
+ return AGENT_HOST_REACHABILITY_CLASSES.REVERSE_TUNNEL;
115
+ }
116
+ if (isLanHostname(hostname)) {
117
+ return AGENT_HOST_REACHABILITY_CLASSES.LAN;
118
+ }
119
+ return AGENT_HOST_REACHABILITY_CLASSES.PUBLIC;
120
+ }
121
+ export function normalizeAgentHostEnrollment(input) {
122
+ const reachableHttpUrl = normalizeOptionalUrl(input.reachable_http_url);
123
+ const healthEndpoint = normalizeOptionalUrl(input.health_endpoint);
124
+ const explicitReachabilityClass = normalizeReachabilityClass(input.reachability_class);
125
+ const reachabilityClass = inferAgentHostReachabilityClass(reachableHttpUrl, explicitReachabilityClass);
126
+ const now = new Date().toISOString();
127
+ return {
128
+ ...input,
129
+ reachable_http_url: reachableHttpUrl,
130
+ reachability_class: reachabilityClass,
131
+ health_endpoint: reachabilityClass === AGENT_HOST_REACHABILITY_CLASSES.UNREACHABLE ? null : healthEndpoint,
132
+ tls_fingerprint: asNonEmptyString(input.tls_fingerprint),
133
+ enrolled_at: asNonEmptyString(input.enrolled_at) ?? now,
134
+ last_seen_at: asNonEmptyString(input.last_seen_at) ?? now,
135
+ };
136
+ }
137
+ export function normalizeAgentHostRecord(input) {
138
+ const normalized = normalizeAgentHostEnrollment(input);
139
+ return {
140
+ ...normalized,
141
+ last_seen_at: normalized.last_seen_at ?? normalized.enrolled_at ?? new Date().toISOString(),
142
+ };
143
+ }
144
+ export function buildAgentHostRegistryPath(workspaceId) {
145
+ return `${AGENT_HOST_REGISTRY_ROUTE_PREFIX}/${encodeURIComponent(workspaceId)}/${AGENT_HOST_REGISTRY_ROUTE_SUFFIX}`;
146
+ }
147
+ export function buildAgentHostRegistryUrl(endpoint, workspaceId) {
148
+ return `${normalizeEndpoint(endpoint)}${buildAgentHostRegistryPath(workspaceId)}`;
149
+ }
150
+ function buildRequestHeaders(token) {
151
+ return {
152
+ [HTTP_HEADER.AUTHORIZATION]: `Bearer ${token}`,
153
+ [HTTP_HEADER.CONTENT_TYPE]: CONTENT_TYPE_JSON,
154
+ };
155
+ }
156
+ async function readJsonResponse(response) {
157
+ return (await response.json().catch(() => ({})));
158
+ }
159
+ export class HttpAgentHostRegistryClient {
160
+ endpoint;
161
+ token;
162
+ fetchFn;
163
+ constructor(endpoint, token, options = {}) {
164
+ this.endpoint = endpoint;
165
+ this.token = token;
166
+ this.fetchFn = options.fetchFn ?? fetch;
167
+ }
168
+ async registerHost(input) {
169
+ const normalizedInput = normalizeAgentHostEnrollment(input);
170
+ const response = await this.fetchFn(buildAgentHostRegistryUrl(this.endpoint, normalizedInput.workspace_id), {
171
+ method: HTTP_METHOD.POST,
172
+ headers: buildRequestHeaders(this.token),
173
+ body: JSON.stringify(normalizedInput),
174
+ });
175
+ if (!response.ok) {
176
+ throw new Error(`Failed to register agent host for workspace ${normalizedInput.workspace_id}: HTTP ${response.status}.`);
177
+ }
178
+ return normalizeAgentHostRecord((await readJsonResponse(response)) ?? normalizedInput);
179
+ }
180
+ async listHosts(input) {
181
+ const response = await this.fetchFn(buildAgentHostRegistryUrl(this.endpoint, input.workspace_id), {
182
+ method: HTTP_METHOD.GET,
183
+ headers: buildRequestHeaders(this.token),
184
+ });
185
+ if (!response.ok) {
186
+ throw new Error(`Failed to list agent hosts for workspace ${input.workspace_id}: HTTP ${response.status}.`);
187
+ }
188
+ const payload = await readJsonResponse(response);
189
+ return {
190
+ hosts: Array.isArray(payload.hosts)
191
+ ? payload.hosts.map((entry) => normalizeAgentHostRecord(entry))
192
+ : [],
193
+ };
194
+ }
195
+ }
196
+ //# sourceMappingURL=agent-host-registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-host-registry.js","sourceRoot":"","sources":["../src/agent-host-registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import type { AuthenticateInput, ControlPlaneIdentity } from './sync-port.js';
2
+ export interface ControlPlaneAuthProfileConfig {
3
+ scopes: string[];
4
+ ttl_seconds?: number;
5
+ }
6
+ export interface ScopedControlPlaneIdentity extends ControlPlaneIdentity {
7
+ scopes: string[];
8
+ expires_at: string;
9
+ profile?: string;
10
+ /**
11
+ * Authoritative identity claim embedded in the enrollment token.
12
+ *
13
+ * Workspace enrollment tokens (WU-2641) may omit this field, in which case
14
+ * the workspace_id is the authoritative subject. Phone-device enrollment
15
+ * tokens (WU-2731, ADR-013 §5) set this to `{workspace_id}:phone:{device_id}`
16
+ * so inbound POSTs can resolve per-device attribution without trusting the
17
+ * request body.
18
+ */
19
+ subject?: string;
20
+ }
21
+ export interface ScopedControlPlaneTokenPayload {
22
+ version: 1;
23
+ workspace_id: string;
24
+ org_id: string;
25
+ agent_id: string;
26
+ scopes: string[];
27
+ expires_at: string;
28
+ profile?: string;
29
+ /** See ScopedControlPlaneIdentity.subject. */
30
+ subject?: string;
31
+ }
32
+ export interface IssueControlPlaneIdentityOptions {
33
+ scopes?: string[];
34
+ profile?: string;
35
+ profiles?: Record<string, ControlPlaneAuthProfileConfig>;
36
+ ttl_seconds?: number;
37
+ now?: Date | string;
38
+ /**
39
+ * Authoritative identity string written into the token payload. When
40
+ * omitted the token has no subject claim (workspace identity is derived
41
+ * from workspace_id).
42
+ */
43
+ subject?: string;
44
+ }
45
+ declare module './sync-port.js' {
46
+ interface AuthenticateInput {
47
+ profile?: string;
48
+ requested_scopes?: string[];
49
+ ttl_seconds?: number;
50
+ }
51
+ interface ControlPlaneIdentity {
52
+ scopes?: string[];
53
+ expires_at?: string;
54
+ profile?: string;
55
+ }
56
+ }
57
+ export declare function issueControlPlaneIdentity(input: AuthenticateInput, options?: IssueControlPlaneIdentityOptions): ScopedControlPlaneIdentity;
58
+ export declare function parseControlPlaneToken(token: string): ScopedControlPlaneTokenPayload | null;
59
+ //# sourceMappingURL=authenticate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticate.d.ts","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAM9E,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,0BAA2B,SAAQ,oBAAoB;IACtE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,8BAA8B;IAC7C,OAAO,EAAE,CAAC,CAAC;IACX,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gCAAgC;IAC/C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IACzD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,OAAO,QAAQ,gBAAgB,CAAC;IAC9B,UAAU,iBAAiB;QACzB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC5B,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB;IAED,UAAU,oBAAoB;QAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB;CACF;AAuGD,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,gCAAqC,GAC7C,0BAA0B,CA8B5B;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,8BAA8B,GAAG,IAAI,CAY3F"}
@@ -0,0 +1,113 @@
1
+ // Copyright (c) 2026 Hellmai Ltd
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { normalizeToolScopes } from './scope-grammar.js';
4
+ const DEFAULT_TTL_SECONDS = 60 * 60;
5
+ const TOKEN_PREFIX = 'lfcp1.';
6
+ function resolveNow(input) {
7
+ if (input instanceof Date) {
8
+ return new Date(input.getTime());
9
+ }
10
+ if (typeof input === 'string') {
11
+ return new Date(input);
12
+ }
13
+ return new Date();
14
+ }
15
+ function asPositiveInteger(value) {
16
+ return typeof value === 'number' && Number.isInteger(value) && value > 0 ? value : undefined;
17
+ }
18
+ function resolveProfileConfig(profile, profiles) {
19
+ if (!profile || !profiles) {
20
+ return undefined;
21
+ }
22
+ return profiles[profile];
23
+ }
24
+ function resolveScopes(input, options) {
25
+ const configuredProfile = resolveProfileConfig(options.profile ?? input.profile, options.profiles);
26
+ const explicitScopes = options.scopes ?? input.requested_scopes;
27
+ if (explicitScopes && explicitScopes.length > 0) {
28
+ return normalizeToolScopes(explicitScopes);
29
+ }
30
+ if (configuredProfile?.scopes?.length) {
31
+ return normalizeToolScopes(configuredProfile.scopes);
32
+ }
33
+ return [];
34
+ }
35
+ function resolveTtlSeconds(input, options) {
36
+ const configuredProfile = resolveProfileConfig(options.profile ?? input.profile, options.profiles);
37
+ return (asPositiveInteger(options.ttl_seconds) ??
38
+ asPositiveInteger(input.ttl_seconds) ??
39
+ asPositiveInteger(configuredProfile?.ttl_seconds) ??
40
+ DEFAULT_TTL_SECONDS);
41
+ }
42
+ function encodeTokenPayload(payload) {
43
+ return `${TOKEN_PREFIX}${Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url')}`;
44
+ }
45
+ function parseScopedTokenPayload(value) {
46
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
47
+ return null;
48
+ }
49
+ const record = value;
50
+ if (record.version !== 1 ||
51
+ typeof record.workspace_id !== 'string' ||
52
+ typeof record.org_id !== 'string' ||
53
+ typeof record.agent_id !== 'string' ||
54
+ typeof record.expires_at !== 'string' ||
55
+ !Array.isArray(record.scopes)) {
56
+ return null;
57
+ }
58
+ const scopes = record.scopes.filter((scope) => typeof scope === 'string');
59
+ if (scopes.length !== record.scopes.length) {
60
+ return null;
61
+ }
62
+ return {
63
+ version: 1,
64
+ workspace_id: record.workspace_id,
65
+ org_id: record.org_id,
66
+ agent_id: record.agent_id,
67
+ expires_at: record.expires_at,
68
+ scopes: normalizeToolScopes(scopes),
69
+ ...(typeof record.profile === 'string' ? { profile: record.profile } : {}),
70
+ ...(typeof record.subject === 'string' ? { subject: record.subject } : {}),
71
+ };
72
+ }
73
+ export function issueControlPlaneIdentity(input, options = {}) {
74
+ const scopes = resolveScopes(input, options);
75
+ const now = resolveNow(options.now);
76
+ const expiresAt = new Date(now.getTime() + resolveTtlSeconds(input, options) * 1000).toISOString();
77
+ const profile = options.profile ?? input.profile;
78
+ const subject = options.subject;
79
+ const tokenPayload = {
80
+ version: 1,
81
+ workspace_id: input.workspace_id,
82
+ org_id: input.org_id,
83
+ agent_id: input.agent_id,
84
+ scopes,
85
+ expires_at: expiresAt,
86
+ ...(profile ? { profile } : {}),
87
+ ...(subject ? { subject } : {}),
88
+ };
89
+ return {
90
+ workspace_id: input.workspace_id,
91
+ org_id: input.org_id,
92
+ agent_id: input.agent_id,
93
+ token: encodeTokenPayload(tokenPayload),
94
+ scopes,
95
+ expires_at: expiresAt,
96
+ ...(profile ? { profile } : {}),
97
+ ...(subject ? { subject } : {}),
98
+ };
99
+ }
100
+ export function parseControlPlaneToken(token) {
101
+ if (!token.startsWith(TOKEN_PREFIX)) {
102
+ return null;
103
+ }
104
+ try {
105
+ const encodedPayload = token.slice(TOKEN_PREFIX.length);
106
+ const decoded = Buffer.from(encodedPayload, 'base64url').toString('utf8');
107
+ return parseScopedTokenPayload(JSON.parse(decoded));
108
+ }
109
+ catch {
110
+ return null;
111
+ }
112
+ }
113
+ //# sourceMappingURL=authenticate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authenticate.js","sourceRoot":"","sources":["../src/authenticate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Apache-2.0 delegation registry schema for lumenflow-cloud (WU-2637, ADR-011 §1).
3
+ *
4
+ * Mirrors the delegation lifecycle shape that @lumenflow/core tracks for local
5
+ * LumenFlow agents, but lives on the Apache-2.0 boundary so that cloud can
6
+ * validate delegation records without linking the AGPL-3.0-only core package.
7
+ *
8
+ * The wrapper document carries an explicit `schema_version`. The parser accepts
9
+ * the current version as-is and migrates one prior snake_case shape to the
10
+ * current camelCase shape (the shape used by agents before the schema was
11
+ * promoted to the public SDK contract).
12
+ */
13
+ import { z } from 'zod';
14
+ /**
15
+ * Current (camelCase) registry schema version. Increment when the record shape
16
+ * changes; add a migration branch to `parseDelegationRegistry` when bumping.
17
+ */
18
+ export declare const DELEGATION_REGISTRY_SCHEMA_VERSION: 2;
19
+ /**
20
+ * Legacy snake_case registry schema version. `parseDelegationRegistry` accepts
21
+ * this version and migrates records forward to the current shape.
22
+ */
23
+ export declare const DELEGATION_REGISTRY_LEGACY_SCHEMA_VERSION: 1;
24
+ export declare const DELEGATION_STATUSES: readonly ["pending", "completed", "timeout", "crashed", "escalated"];
25
+ export type DelegationStatus = (typeof DELEGATION_STATUSES)[number];
26
+ export declare const DELEGATION_INTENTS: readonly ["delegation", "legacy-spawn"];
27
+ export type DelegationIntent = (typeof DELEGATION_INTENTS)[number];
28
+ export declare const DelegationAttestationSchema: z.ZodObject<{
29
+ algorithm: z.ZodLiteral<"sha256">;
30
+ promptHash: z.ZodString;
31
+ promptLength: z.ZodNumber;
32
+ generatedAt: z.ZodString;
33
+ clientName: z.ZodString;
34
+ }, z.core.$strip>;
35
+ export type DelegationAttestation = z.infer<typeof DelegationAttestationSchema>;
36
+ export declare const DelegationRecordSchema: z.ZodObject<{
37
+ id: z.ZodString;
38
+ parentWuId: z.ZodString;
39
+ targetWuId: z.ZodString;
40
+ lane: z.ZodString;
41
+ intent: z.ZodOptional<z.ZodEnum<{
42
+ delegation: "delegation";
43
+ "legacy-spawn": "legacy-spawn";
44
+ }>>;
45
+ delegatedAt: z.ZodString;
46
+ status: z.ZodEnum<{
47
+ pending: "pending";
48
+ completed: "completed";
49
+ timeout: "timeout";
50
+ crashed: "crashed";
51
+ escalated: "escalated";
52
+ }>;
53
+ completedAt: z.ZodNullable<z.ZodString>;
54
+ pickedUpAt: z.ZodOptional<z.ZodString>;
55
+ pickedUpBy: z.ZodOptional<z.ZodString>;
56
+ briefAttestation: z.ZodOptional<z.ZodObject<{
57
+ algorithm: z.ZodLiteral<"sha256">;
58
+ promptHash: z.ZodString;
59
+ promptLength: z.ZodNumber;
60
+ generatedAt: z.ZodString;
61
+ clientName: z.ZodString;
62
+ }, z.core.$strip>>;
63
+ }, z.core.$strip>;
64
+ export type DelegationRecord = z.infer<typeof DelegationRecordSchema>;
65
+ declare const DelegationRegistryDocumentSchema: z.ZodObject<{
66
+ schema_version: z.ZodLiteral<2>;
67
+ records: z.ZodArray<z.ZodObject<{
68
+ id: z.ZodString;
69
+ parentWuId: z.ZodString;
70
+ targetWuId: z.ZodString;
71
+ lane: z.ZodString;
72
+ intent: z.ZodOptional<z.ZodEnum<{
73
+ delegation: "delegation";
74
+ "legacy-spawn": "legacy-spawn";
75
+ }>>;
76
+ delegatedAt: z.ZodString;
77
+ status: z.ZodEnum<{
78
+ pending: "pending";
79
+ completed: "completed";
80
+ timeout: "timeout";
81
+ crashed: "crashed";
82
+ escalated: "escalated";
83
+ }>;
84
+ completedAt: z.ZodNullable<z.ZodString>;
85
+ pickedUpAt: z.ZodOptional<z.ZodString>;
86
+ pickedUpBy: z.ZodOptional<z.ZodString>;
87
+ briefAttestation: z.ZodOptional<z.ZodObject<{
88
+ algorithm: z.ZodLiteral<"sha256">;
89
+ promptHash: z.ZodString;
90
+ promptLength: z.ZodNumber;
91
+ generatedAt: z.ZodString;
92
+ clientName: z.ZodString;
93
+ }, z.core.$strip>>;
94
+ }, z.core.$strip>>;
95
+ }, z.core.$strip>;
96
+ export type DelegationRegistryDocument = z.infer<typeof DelegationRegistryDocumentSchema>;
97
+ /**
98
+ * Parses a delegation registry document. Accepts the current schema version
99
+ * verbatim and migrates the legacy snake_case version forward.
100
+ *
101
+ * @throws Error with a `schema_version`-prefixed message when the input carries
102
+ * an unknown schema version, and a zod ZodError when records fail
103
+ * validation.
104
+ */
105
+ export declare function parseDelegationRegistry(input: unknown): DelegationRegistryDocument;
106
+ export {};
107
+ //# sourceMappingURL=delegation-registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegation-registry.d.ts","sourceRoot":"","sources":["../src/delegation-registry.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,kCAAkC,EAAG,CAAU,CAAC;AAE7D;;;GAGG;AACH,eAAO,MAAM,yCAAyC,EAAG,CAAU,CAAC;AAMpE,eAAO,MAAM,mBAAmB,sEAMtB,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEpE,eAAO,MAAM,kBAAkB,yCAA0C,CAAC;AAE1E,MAAM,MAAM,gBAAgB,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAC;AAEnE,eAAO,MAAM,2BAA2B;;;;;;iBAQtC,CAAC;AAEH,MAAM,MAAM,qBAAqB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAEhF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkBjC,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAEtE,QAAA,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAGpC,CAAC;AAEH,MAAM,MAAM,0BAA0B,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gCAAgC,CAAC,CAAC;AAiE1F;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,0BAA0B,CAqClF"}