@parall/daemon 1.34.0 → 1.36.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.
@@ -0,0 +1,294 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * `parall-browser-pod` — the V2 hosted-browser pod entrypoint.
4
+ *
5
+ * This is the production replacement for the Go echo-stub (server/cmd/browser-stub):
6
+ * a single-profile pod that runs the REAL browser stack (Chromium under Xvfb +
7
+ * bb-browser, started lazily by BrowserProfileManager) and registers to the Clip
8
+ * Service hub as the "browser" provider for exactly ONE profile.
9
+ *
10
+ * It is deliberately NOT the daemon supervisor. The daemon (`index.ts`) is a
11
+ * Machine: it authenticates with a 90-day `mck_`, polls `/machines/me/*`, and
12
+ * supervises per-agent subprocesses. A hosted browser pod has none of that — it
13
+ * is platform infrastructure with a short-lived, controller-minted platform
14
+ * assignment token (`pba_`) scoped to `(org_id, profile_id, pod_id)`, and serves
15
+ * a single profile until its lease is released. Per the V2 design (§3.3, §6) this
16
+ * is an **image/entrypoint-level** slim mode: it reuses the shared clip-runtime
17
+ * building blocks (ClipProvider / ClipProcessManager / BrowserProfileManager)
18
+ * without deleting anything from the shared package, so the BYOC daemon path and
19
+ * its `mck_` identity are untouched.
20
+ *
21
+ * Contract (mirrors server/cmd/browser-stub/main.go, the reference implementation):
22
+ *
23
+ * Env (injected by browser-profile-controller's pod spec):
24
+ * PRLL_ASSIGNMENT_TOKEN the pba_ platform assignment token (required)
25
+ * PRLL_CLIP_RPC in-cluster clip-service URL, e.g. http://clip-service:8095 (required)
26
+ * PRLL_PROFILE_ID the profile this pod serves (required)
27
+ * PRLL_POD_ID this pod's name → provider_name; must match the token's pod_id (required)
28
+ * PRLL_ORG_ID owning org (logging only; the hub derives org from the token)
29
+ * PRLL_HEALTH_PORT liveness/readiness listen port (default 8080)
30
+ * PRLL_BROWSER_STATE_DIR root for on-disk browser state (default $HOME/.parall-agent)
31
+ *
32
+ * Health (the contract the controller's K8s probes consume):
33
+ * GET /livez -> 200 always (process is alive; a liveness restart trigger).
34
+ * GET /readyz -> 200 only while registered to the hub AND not draining, else 503.
35
+ * Readiness is ROUTE-readiness, not mere liveness: a started-but-not-yet-
36
+ * registered (or disconnected, or token/lease-invalidated) pod reads
37
+ * NotReady, so the controller never treats pod existence as routable. The
38
+ * hub fences the ProviderStream on the pba_ token + live lease, so loss of
39
+ * either drops the registration → isConnected() → false → NotReady.
40
+ *
41
+ * Shutdown (SIGTERM, on pod deletion / lease release): fail readiness FIRST so
42
+ * K8s/controller stop routing, THEN tear down the ProviderStream (hub
43
+ * unregisters) and the bb-browser daemon — all within terminationGracePeriod.
44
+ * The authoritative lease state transition (lease -> released, quota freed) is
45
+ * still owned by the controller/api-server, never inferred from the pod exiting.
46
+ */
47
+ import * as http from 'node:http';
48
+ import { type GatewayLogger } from '@parall/agent-core';
49
+ import { BrowserStateStore, type HydrateResult } from './clip-runtime/browser-state-store.js';
50
+ export interface BrowserPodConfig {
51
+ /** Controller-minted pba_ platform assignment token (ProviderStream bearer). */
52
+ assignmentToken: string;
53
+ /** Clip Service hub URL (h2c in-cluster, e.g. http://clip-service:8095). */
54
+ clipRpcUrl: string;
55
+ /** The single profile this pod serves. */
56
+ profileId: string;
57
+ /** This pod's name; becomes the provider_name and must match the token's pod_id. */
58
+ podId: string;
59
+ /** Owning org — used for local logging only; the hub derives org from the token. */
60
+ orgId: string;
61
+ /** Liveness/readiness HTTP port. */
62
+ healthPort: number;
63
+ /** Root for on-disk browser state (parent of the bb-browser user-data dir). */
64
+ stateDir: string;
65
+ /** bb-browser user-data dir (BB_BROWSER_HOME); where S3 state hydrates in a later PR. */
66
+ homeDir: string;
67
+ }
68
+ /**
69
+ * Resolve and validate the pod's runtime config from the environment. Throws on
70
+ * any missing required var (fail-fast: a pod missing its token / clip-rpc /
71
+ * profile / pod id can never register, so we crash now instead of starting a
72
+ * doomed reconnect loop).
73
+ */
74
+ export declare function resolveBrowserPodConfig(env?: NodeJS.ProcessEnv): BrowserPodConfig;
75
+ /** Resolved warm-pool config — the identity-less env a warm pod boots with. */
76
+ export interface PoolPodConfig {
77
+ /** Controller-minted pba_ pool bootstrap token; the bearer required on POST /assign. */
78
+ poolToken: string;
79
+ /** This warm pod's name → provider_name after assignment; matches the controller pod spec. */
80
+ podId: string;
81
+ /** Clip Service hub URL (stable per cluster; injected at pool creation, reused post-assign). */
82
+ clipRpcUrl: string;
83
+ /** Liveness/readiness/control HTTP port. */
84
+ healthPort: number;
85
+ }
86
+ /**
87
+ * Resolve a warm pod's identity-less config. Unlike resolveBrowserPodConfig this
88
+ * requires PRLL_POOL_TOKEN (not PRLL_ASSIGNMENT_TOKEN) and NO profile/org — those
89
+ * arrive later via /assign. PRLL_CLIP_RPC is injected at pool creation (stable per
90
+ * cluster) so the assigned path needs no extra wiring.
91
+ */
92
+ export declare function resolvePoolPodConfig(env?: NodeJS.ProcessEnv): PoolPodConfig;
93
+ /** Profile-scoped S3 credentials delivered in an /assign payload (mirrors the
94
+ * controller's PodStateCredentials → cold-pod env injection). */
95
+ export interface AssignStateCreds {
96
+ bucket: string;
97
+ region: string;
98
+ endpoint?: string;
99
+ accessKeyId: string;
100
+ secretAccessKey: string;
101
+ sessionToken: string;
102
+ }
103
+ /** The POST /assign body the browser-profile-controller sends to bind a warm pod
104
+ * to a profile (design §9 PR10). Wire format is snake_case (Go JSON). */
105
+ export interface AssignRequest {
106
+ assignmentToken: string;
107
+ profileId: string;
108
+ orgId: string;
109
+ leaseId: string;
110
+ generation: number;
111
+ state?: AssignStateCreds;
112
+ }
113
+ type AssignParseResult = {
114
+ ok: true;
115
+ value: AssignRequest;
116
+ } | {
117
+ ok: false;
118
+ error: string;
119
+ };
120
+ /**
121
+ * Validate + normalize an /assign body (already JSON-parsed). Rejects a missing /
122
+ * non-pba_ assignment token, a missing profile/lease, and PARTIAL S3 creds (a
123
+ * half-set would build a misconfigured S3 client — worse than stateless). State is
124
+ * optional (stateless profile); when present it must be complete.
125
+ */
126
+ export declare function parseAssignRequest(body: unknown): AssignParseResult;
127
+ /**
128
+ * Apply an /assign payload to `env` (process.env in prod) so the assigned path
129
+ * reads identity + S3 creds EXACTLY as the controller injects them into a cold
130
+ * pod's spec. The AWS_* creds must land in process.env: the S3 client
131
+ * (browser-state-store buildS3Client) reads the default AWS provider chain.
132
+ */
133
+ export declare function applyAssignmentEnv(env: NodeJS.ProcessEnv, req: AssignRequest): void;
134
+ /** HTTP outcome of an /assign request. */
135
+ export type AssignOutcome = {
136
+ status: number;
137
+ message?: string;
138
+ };
139
+ /** /assign handler: bearer (already stripped of "Bearer ") + parsed-or-raw body. */
140
+ export type AssignHandler = (bearer: string | undefined, body: unknown) => Promise<AssignOutcome>;
141
+ /** Narrow runtime surface the pool path drives after an assignment lands. */
142
+ export interface AssignedRuntime {
143
+ isReady(): boolean;
144
+ drain(): Promise<void>;
145
+ }
146
+ /** A live warm-pool assignment controller — its /assign handler + readiness/drain. */
147
+ export interface PoolAssign {
148
+ handler: AssignHandler;
149
+ isReady(): boolean;
150
+ drain(): Promise<void>;
151
+ assignedLeaseId(): string | null;
152
+ }
153
+ /**
154
+ * Build the warm pod's /assign controller. The cardinal rules:
155
+ * - auth: bearer MUST equal the pool token (constant-time).
156
+ * - single-assignment: a warm pod serves ONE profile for life — a repeat for the
157
+ * same lease is idempotent (200), a different lease is a conflict (409). The
158
+ * lease is claimed SYNCHRONOUSLY so a duplicate/concurrent POST conflicts.
159
+ * - eventual readiness: identity is applied then the real runtime is started in
160
+ * the BACKGROUND (hydrate + connect take seconds); /readyz is the gate, exactly
161
+ * as a cold pod whose Create returns fast and becomes Ready later.
162
+ * `startRuntime` is injected so the assign flow is testable without a real hub.
163
+ */
164
+ export declare function createPoolAssign(opts: {
165
+ poolToken: string;
166
+ env: NodeJS.ProcessEnv;
167
+ log: Pick<GatewayLogger, 'info' | 'warn' | 'error'>;
168
+ startRuntime: (env: NodeJS.ProcessEnv) => Promise<AssignedRuntime>;
169
+ }): PoolAssign;
170
+ /** Minimal ProviderStream surface the runtime needs — kept narrow for testing. */
171
+ export interface PodProvider {
172
+ connect(): Promise<void>;
173
+ disconnect(): Promise<void>;
174
+ isConnected(): boolean;
175
+ }
176
+ /** Minimal browser-runtime surface the runtime needs — kept narrow for testing. */
177
+ export interface PodBrowser {
178
+ stop(): Promise<void>;
179
+ }
180
+ /**
181
+ * Narrow S3-checkpoint surface (kept testable, decoupled from BrowserStateStore).
182
+ * `checkpointPeriodic` runs on a timer while the pod serves; `checkpointFinal` runs
183
+ * once during drain AFTER bb-browser is stopped, for a consistent snapshot.
184
+ */
185
+ export interface PodStateCheckpointer {
186
+ checkpointPeriodic(): Promise<void>;
187
+ checkpointFinal(): Promise<void>;
188
+ }
189
+ /**
190
+ * BrowserPodRuntime owns the pod's readiness state and the ordered teardown. It
191
+ * is deliberately decoupled from the concrete ClipProvider / BrowserProfileManager
192
+ * (only the narrow PodProvider / PodBrowser surfaces) so the readiness gate and
193
+ * drain ORDER are unit-testable without a real browser or hub.
194
+ */
195
+ export declare class BrowserPodRuntime {
196
+ private readonly provider;
197
+ private readonly browser;
198
+ private readonly log;
199
+ private readonly checkpointer?;
200
+ private readonly checkpointIntervalMs;
201
+ private draining;
202
+ private drainPromise;
203
+ private checkpointTimer;
204
+ constructor(provider: PodProvider, browser: PodBrowser, log: Pick<GatewayLogger, 'info' | 'warn' | 'error'>, checkpointer?: PodStateCheckpointer | undefined, checkpointIntervalMs?: number);
205
+ /**
206
+ * Route-readiness: registered to the hub AND not draining. `draining` is checked
207
+ * first so the readiness gate flips false the instant a drain begins — before
208
+ * the (async) ProviderStream teardown completes. The hub fences the stream on
209
+ * the pba_ token + live lease, so isConnected() already encodes "token/lease
210
+ * still valid".
211
+ */
212
+ isReady(): boolean;
213
+ /** Open the ProviderStream, register as the "browser" provider, and start the
214
+ * periodic checkpoint loop (if a checkpointer was supplied). */
215
+ start(): Promise<void>;
216
+ /** Periodic S3 checkpoints while serving. Best-effort: a checkpoint error is
217
+ * logged but never throws (it must not kill the pod); the timer is unref'd so it
218
+ * never keeps the process alive on its own. */
219
+ private startCheckpointLoop;
220
+ /**
221
+ * Graceful drain (SIGTERM / lease release): fail readiness FIRST, stop the
222
+ * periodic checkpoint loop, then tear down the hub stream and the browser, and
223
+ * finally take ONE last checkpoint AFTER bb-browser is stopped (a consistent
224
+ * snapshot of the settled state — design §3.2). Idempotent — a second SIGTERM
225
+ * joins the first.
226
+ */
227
+ drain(): Promise<void>;
228
+ }
229
+ /**
230
+ * Create the liveness/readiness HTTP server. `/livez` is mere process liveness;
231
+ * `/readyz` is route-readiness driven by `isReady`. Mirrors the Go stub's health
232
+ * contract so the controller's probes are runtime-agnostic.
233
+ */
234
+ export declare function createHealthServer(opts: {
235
+ isLive: () => boolean;
236
+ isReady: () => boolean;
237
+ log: Pick<GatewayLogger, 'info' | 'warn' | 'error'>;
238
+ onAssign?: AssignHandler;
239
+ }): http.Server;
240
+ /**
241
+ * Build the S3 state store from env, or return null (stateless pod) ONLY when no
242
+ * bucket is configured (the feature is off). When a bucket IS set, state was
243
+ * REQUESTED, so the org id (part of the S3 key + the pod's STS prefix scope) and the
244
+ * activation generation (the single-writer fence) are required: a missing/invalid
245
+ * value is a controller-injection misconfiguration and FAILS CLOSED (throws) rather
246
+ * than silently registering a non-persisted profile — silent stateless serving when
247
+ * state was configured is data loss. The thrown error propagates to pod startup, so
248
+ * the pod never reaches readiness and the controller releases it on the deadline.
249
+ */
250
+ export declare function buildStateStore(config: BrowserPodConfig, env: NodeJS.ProcessEnv, log: GatewayLogger): BrowserStateStore | null;
251
+ /** Resolve the periodic checkpoint cadence (ms) from env, clamped to ≥1s. */
252
+ export declare function resolveCheckpointIntervalMs(env: NodeJS.ProcessEnv): number;
253
+ /**
254
+ * Whether it is SAFE to checkpoint after a hydrate. Checkpoint ONLY when the prior
255
+ * snapshot was loaded (hydrated) or there was genuinely none (a new profile —
256
+ * head returned null, so no flags set). If a snapshot EXISTED but could not be
257
+ * loaded (checksum mismatch, or a download/extract/HEAD error), checkpointing must
258
+ * be disabled: an empty homeDir would otherwise overwrite the good state, and the
259
+ * generation fence permits it (this pod's gen is legitimately higher than the
260
+ * snapshot's). Returns false in that case so the pod runs checkpoint-less, leaving
261
+ * the existing snapshot untouched rather than clobbering it (simplified durability:
262
+ * the prior state is preserved in place — there is no controller-side repair).
263
+ */
264
+ export declare function shouldCheckpointAfterHydrate(result: HydrateResult): boolean;
265
+ /**
266
+ * Wire the real clip-runtime stack for a hosted browser pod from a resolved config
267
+ * and return the {@link BrowserPodRuntime} — WITHOUT creating the health server,
268
+ * binding a port, or parking on a signal. Splitting this out lets the warm-pool
269
+ * path (runPoolPod) reuse the EXACT assigned-pod wiring after a `/assign` arrives,
270
+ * while keeping a single control/health server bound on healthPort (the pool path
271
+ * already owns it). hydrate() runs here — before the provider opens — because
272
+ * bb-browser launches lazily on first invoke, so the snapshot must be on disk first.
273
+ */
274
+ export declare function preparePodRuntime(config: BrowserPodConfig, env: NodeJS.ProcessEnv, log: GatewayLogger): Promise<BrowserPodRuntime>;
275
+ /**
276
+ * Wire the real clip-runtime stack for a hosted browser pod and run until the
277
+ * abort signal fires (SIGTERM). Returns after the ordered drain completes. This is
278
+ * the ASSIGNED path: PRLL_ASSIGNMENT_TOKEN + profile are already in env (the
279
+ * controller's cold-create pod spec). The warm-pool path (runPoolPod) reaches the
280
+ * same runtime via preparePodRuntime once a `/assign` delivers the identity.
281
+ */
282
+ export declare function runBrowserPod(env: NodeJS.ProcessEnv, signal: AbortSignal, log: GatewayLogger): Promise<void>;
283
+ /**
284
+ * Run a WARM pod: bind ONE control/health server (livez/readyz/assign) on
285
+ * healthPort and park — no Chromium, no profile, no hub registration — until a
286
+ * `POST /assign` delivers an identity, at which point the pod transitions into the
287
+ * exact assigned-pod runtime (preparePodRuntime, hydrating S3 like a cold pod). On
288
+ * SIGTERM, drain the started runtime (if any) then close the server. The single
289
+ * server is the reason runPoolPod reuses preparePodRuntime rather than runBrowserPod
290
+ * (which would bind its own health port).
291
+ */
292
+ export declare function runPoolPod(env: NodeJS.ProcessEnv, signal: AbortSignal, log: GatewayLogger): Promise<void>;
293
+ export {};
294
+ //# sourceMappingURL=browser-pod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser-pod.d.ts","sourceRoot":"","sources":["../src/browser-pod.ts"],"names":[],"mappings":"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"}