@hypequery/deployment 0.0.0-canary-20260719200737 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # @hypequery/deployment
2
2
 
3
- Provider-neutral verification, intake, activation, and HTTP control-plane
4
- building blocks for Hypequery deployment bundles.
3
+ Provider-neutral verification and receiving-side intake for Hypequery deployment
4
+ bundles.
5
5
 
6
6
  The package accepts the authenticated multipart transport emitted by
7
7
  `hypequery deploy`, reconstructs only manifest-declared files in temporary
@@ -152,97 +152,4 @@ append-only chain. It has no mutable pointer file or persistent lock to become
152
152
  stale after a crash. Activation does not load runtime code, route traffic,
153
153
  perform health checks, or authorize callers; those remain provider concerns.
154
154
 
155
- ## HTTP control plane
156
-
157
- `createDeploymentControlPlane` combines intake and activation behind closed v1
158
- routes. Activation reads and writes use a separate target-scoped authorizer;
159
- write authorization completes before the small JSON request body is consumed.
160
- The Fetch and Node adapters preserve streaming multipart submission bodies.
161
-
162
- ```ts
163
- import {
164
- createDeploymentControlPlane,
165
- createDeploymentControlPlaneNodeHandler,
166
- } from '@hypequery/deployment';
167
-
168
- const controlPlane = createDeploymentControlPlane({
169
- intake,
170
- activations,
171
- authenticator,
172
- authorizer: {
173
- async authorize({ principal, action, target }) {
174
- return canControlDeployment(principal, action, target);
175
- },
176
- },
177
- });
178
-
179
- const nodeHandler = createDeploymentControlPlaneNodeHandler(controlPlane);
180
- ```
181
-
182
- The control plane exposes release submission, compare-and-swap activation,
183
- current state, and bounded cursor history. It returns stable, bounded JSON error
184
- codes and suppresses internal provider and filesystem details. The HTTP
185
- contract is specified in `specs/deployment/0003-control-plane-http.md`.
186
-
187
- ## Runtime materialization
188
-
189
- `createDeploymentRuntimeMaterializer` converts the current target activation
190
- into a private runtime snapshot. It revalidates the accepted release and closed
191
- bundle, copies and hashes each runtime artifact without following symbolic
192
- links, and confirms the activation revision again before returning.
193
-
194
- ```ts
195
- import { createDeploymentRuntimeMaterializer } from '@hypequery/deployment';
196
-
197
- const materializer = createDeploymentRuntimeMaterializer({
198
- activations,
199
- releases: store,
200
- });
201
-
202
- const snapshot = await materializer.current({
203
- project: 'analytics',
204
- environment: 'production',
205
- });
206
- ```
207
-
208
- Artifact `read()` methods return fresh byte copies, so neither callers nor later
209
- changes to durable storage can alter a materialized snapshot. Runtime imports,
210
- process lifecycle, readiness, and traffic switching remain separate concerns.
211
-
212
- ## Runtime supervision
213
-
214
- `createDeploymentRuntimeSupervisor` starts materialized snapshots through a
215
- runtime factory, checks candidate readiness, confirms activation again, and
216
- atomically changes the generation used for new named-query invocations. Failed
217
- or superseded candidates never displace a healthy generation.
218
-
219
- ```ts
220
- import {
221
- createDeploymentRuntimeSupervisor,
222
- createNodeWorkerDeploymentRuntimeFactory,
223
- } from '@hypequery/deployment';
224
-
225
- const supervisor = createDeploymentRuntimeSupervisor({
226
- materializer,
227
- factory: createNodeWorkerDeploymentRuntimeFactory(),
228
- });
229
-
230
- await supervisor.reconcile({ project: 'analytics', environment: 'production' });
231
- const result = await supervisor.invoke({
232
- target: { project: 'analytics', environment: 'production' },
233
- query: 'orders',
234
- argument: { input, ctx: { tenantId } },
235
- });
236
- ```
237
-
238
- Calls already assigned to an old generation may finish after cutover. That
239
- generation receives no new calls and closes when its in-flight work reaches
240
- zero or the drain deadline expires. The reference Node factory loads exact
241
- materialized bytes in worker threads and removes their temporary files on
242
- shutdown. Provider factories can implement Python, process, container, or
243
- remote-sandbox isolation behind the same lifecycle interface.
244
-
245
- The reference worker is a lifecycle boundary, not a hostile-code security
246
- sandbox. Only trusted deployment code should use it directly.
247
-
248
155
  The package is ESM-only and requires Node.js 20 or newer.
@@ -29,14 +29,6 @@ export type DeploymentActivationResult = {
29
29
  readonly status: 'conflict';
30
30
  readonly current: DeploymentActivationRecord | null;
31
31
  };
32
- export interface DeploymentActivationHistoryQuery {
33
- readonly limit: number;
34
- readonly before?: string;
35
- }
36
- export interface DeploymentActivationHistoryPage {
37
- readonly activations: readonly DeploymentActivationRecord[];
38
- readonly nextBefore: string | null;
39
- }
40
32
  export interface DeploymentActivationRelease {
41
33
  readonly release: ProtocolDeploymentReleaseEnvelope;
42
34
  readonly releaseIdentity: string;
@@ -54,9 +46,6 @@ export interface DeploymentActivationRegistry {
54
46
  activate(request: DeploymentActivationRequest): Promise<DeploymentActivationResult>;
55
47
  current(target: ProtocolDeploymentReleaseTarget): Promise<DeploymentActivationRecord | undefined>;
56
48
  history(target: ProtocolDeploymentReleaseTarget): Promise<readonly DeploymentActivationRecord[]>;
57
- historyPage(target: ProtocolDeploymentReleaseTarget, query: DeploymentActivationHistoryQuery): Promise<DeploymentActivationHistoryPage>;
58
49
  }
59
- /** Validate and recompute an immutable deployment activation record. */
60
- export declare function validateDeploymentActivationRecord(input: unknown): DeploymentActivationRecord;
61
50
  export declare function createFileSystemDeploymentActivationRegistry(options: FileSystemDeploymentActivationRegistryOptions): DeploymentActivationRegistry;
62
51
  //# sourceMappingURL=activation.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../src/activation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"activation.d.ts","sourceRoot":"","sources":["../src/activation.ts"],"names":[],"mappings":"AAYA,OAAO,EAGL,KAAK,iCAAiC,EACtC,KAAK,+BAA+B,EACrC,MAAM,qBAAqB,CAAC;AAe7B,MAAM,MAAM,6BAA6B,GACrC,wCAAwC,GACxC,0CAA0C,GAC1C,4CAA4C,GAC5C,8CAA8C,GAC9C,0CAA0C,GAC1C,wCAAwC,GACxC,6BAA6B,CAAC;AAElC,qBAAa,yBAA0B,SAAQ,KAAK;IAClD,QAAQ,CAAC,IAAI,EAAE,6BAA6B,CAAC;gBAG3C,IAAI,EAAE,6BAA6B,EACnC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAM7C;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,IAAI,EAAE,iCAAiC,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,QAAQ,CAAC,uBAAuB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,MAAM,EAAE,+BAA+B,CAAC;IACjD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,6EAA6E;IAC7E,QAAQ,CAAC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAED,MAAM,MAAM,0BAA0B,GAClC;IACA,QAAQ,CAAC,MAAM,EAAE,WAAW,GAAG,gBAAgB,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,0BAA0B,CAAC;CACjD,GACC;IACA,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,0BAA0B,GAAG,IAAI,CAAC;CACrD,CAAC;AAEJ,MAAM,WAAW,2BAA2B;IAC1C,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAC;IACpD,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;CAClC;AAED,MAAM,WAAW,uBAAuB;IACtC,6FAA6F;IAC7F,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAAC;CACjF;AAED,MAAM,WAAW,6CAA6C;IAC5D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,uBAAuB,CAAC;IAC3C,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,OAAO,EAAE,2BAA2B,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACpF,OAAO,CACL,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC;IACnD,OAAO,CACL,MAAM,EAAE,+BAA+B,GACtC,OAAO,CAAC,SAAS,0BAA0B,EAAE,CAAC,CAAC;CACnD;AAqdD,wBAAgB,4CAA4C,CAC1D,OAAO,EAAE,6CAA6C,GACrD,4BAA4B,CAqM9B"}
@@ -128,16 +128,21 @@ function requireRecord(input) {
128
128
  }
129
129
  return value;
130
130
  }
131
- function prepareValidatedActivation(input) {
131
+ function validateStoredActivation(input, expectedTarget, expectedPreviousRevision, expectedPreviousReleaseIdentity) {
132
132
  const value = requireRecord(input);
133
133
  if (value.kind !== 'hypequery-deployment-activation' || value.version !== 1) {
134
134
  throw new Error('Activation record kind or version is invalid.');
135
135
  }
136
136
  const target = validateTarget(value.target, 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
137
+ if (!targetsEqual(target, expectedTarget)) {
138
+ throw new Error('Activation record target is inconsistent.');
139
+ }
137
140
  const releaseIdentity = requireIdentity(value.releaseIdentity, 'Stored release identity', 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
138
141
  const previousRevision = requireNullableIdentity(value.previousRevision, 'Stored previous revision', 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
139
142
  const previousReleaseIdentity = requireNullableIdentity(value.previousReleaseIdentity, 'Stored previous release identity', 'HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE');
140
- if ((previousRevision === null) !== (previousReleaseIdentity === null)) {
143
+ if (previousRevision !== expectedPreviousRevision
144
+ || previousReleaseIdentity !== expectedPreviousReleaseIdentity
145
+ || (previousRevision === null) !== (previousReleaseIdentity === null)) {
141
146
  throw new Error('Activation record predecessor is inconsistent.');
142
147
  }
143
148
  if (typeof value.activatedAt !== 'string') {
@@ -159,21 +164,6 @@ function prepareValidatedActivation(input) {
159
164
  }
160
165
  return prepared;
161
166
  }
162
- /** Validate and recompute an immutable deployment activation record. */
163
- export function validateDeploymentActivationRecord(input) {
164
- return prepareValidatedActivation(input).record;
165
- }
166
- function validateStoredActivation(input, expectedTarget, expectedPreviousRevision, expectedPreviousReleaseIdentity) {
167
- const prepared = prepareValidatedActivation(input);
168
- if (!targetsEqual(prepared.record.target, expectedTarget)) {
169
- throw new Error('Activation record target is inconsistent.');
170
- }
171
- if (prepared.record.previousRevision !== expectedPreviousRevision
172
- || prepared.record.previousReleaseIdentity !== expectedPreviousReleaseIdentity) {
173
- throw new Error('Activation record predecessor is inconsistent.');
174
- }
175
- return prepared;
176
- }
177
167
  async function pathExists(filePath) {
178
168
  try {
179
169
  await lstat(filePath);
@@ -345,7 +335,7 @@ async function readStoredActivation(claimDirectory, target, previousRevision, pr
345
335
  }
346
336
  return prepared;
347
337
  }
348
- async function visitHistory(targetDirectory, target, visitor) {
338
+ async function resolveHistory(targetDirectory, target) {
349
339
  try {
350
340
  await readCanonicalTarget(targetDirectory, target);
351
341
  const claimsDirectory = path.join(targetDirectory, CLAIMS_DIRECTORY);
@@ -357,6 +347,7 @@ async function visitHistory(targetDirectory, target, visitor) {
357
347
  }
358
348
  const remaining = new Set(claimNames);
359
349
  const revisions = new Set();
350
+ const history = [];
360
351
  let previousRevision = null;
361
352
  let previousReleaseIdentity = null;
362
353
  // Following predecessor-named claims derives the head without trusting a
@@ -370,13 +361,14 @@ async function visitHistory(targetDirectory, target, visitor) {
370
361
  throw new Error('Deployment activation history contains a cycle.');
371
362
  }
372
363
  revisions.add(prepared.record.revision);
373
- visitor(prepared.record);
364
+ history.push(prepared.record);
374
365
  previousRevision = prepared.record.revision;
375
366
  previousReleaseIdentity = prepared.record.releaseIdentity;
376
367
  }
377
368
  if (remaining.size > 0) {
378
369
  throw new Error('Deployment activation history contains unreachable claims.');
379
370
  }
371
+ return Object.freeze(history);
380
372
  }
381
373
  catch (error) {
382
374
  if (error instanceof DeploymentActivationError)
@@ -386,53 +378,8 @@ async function visitHistory(targetDirectory, target, visitor) {
386
378
  throw activationError('HQ_DEPLOYMENT_ACTIVATION_CORRUPT_STATE', 'Stored deployment activation history is invalid.', error);
387
379
  }
388
380
  }
389
- async function resolveHistory(targetDirectory, target) {
390
- const history = [];
391
- await visitHistory(targetDirectory, target, record => { history.push(record); });
392
- return Object.freeze(history);
393
- }
394
- async function resolveCurrent(targetDirectory, target) {
395
- let current;
396
- await visitHistory(targetDirectory, target, record => { current = record; });
397
- return current;
398
- }
399
- function validateHistoryQuery(input) {
400
- if (!Number.isSafeInteger(input?.limit) || input.limit < 1
401
- || (input.before !== undefined && !IDENTITY_PATTERN.test(input.before))) {
402
- throw activationError('HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST', 'Deployment activation history query is invalid.');
403
- }
404
- return Object.freeze({
405
- limit: input.limit,
406
- ...(input.before === undefined ? {} : { before: input.before }),
407
- });
408
- }
409
- async function resolveHistoryPage(targetDirectory, target, query) {
410
- const retained = [];
411
- let beforeFound = query.before === undefined;
412
- let beforeReached = false;
413
- await visitHistory(targetDirectory, target, record => {
414
- if (record.revision === query.before) {
415
- beforeFound = true;
416
- beforeReached = true;
417
- return;
418
- }
419
- if (beforeReached)
420
- return;
421
- retained.push(record);
422
- if (retained.length > query.limit + 1)
423
- retained.shift();
424
- });
425
- if (!beforeFound) {
426
- throw activationError('HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST', 'Deployment activation history cursor was not found.');
427
- }
428
- const hasOlder = retained.length > query.limit;
429
- if (hasOlder)
430
- retained.shift();
431
- const activations = Object.freeze(retained);
432
- return Object.freeze({
433
- activations,
434
- nextBefore: hasOlder ? activations[0].revision : null,
435
- });
381
+ function currentActivation(history) {
382
+ return history[history.length - 1];
436
383
  }
437
384
  export function createFileSystemDeploymentActivationRegistry(options) {
438
385
  if (typeof options.directory !== 'string' || options.directory.length < 1) {
@@ -486,37 +433,8 @@ export function createFileSystemDeploymentActivationRegistry(options) {
486
433
  throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not read deployment activation history.', error);
487
434
  }
488
435
  }
489
- async function current(targetInput) {
490
- const target = validateTarget(targetInput, 'HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST');
491
- try {
492
- const key = sha256(TARGET_IDENTITY_DOMAIN, targetCanonical(target));
493
- const targetDirectory = path.join(await activationRoot(), key);
494
- if (!await pathExists(targetDirectory))
495
- return undefined;
496
- return await resolveCurrent(targetDirectory, target);
497
- }
498
- catch (error) {
499
- if (error instanceof DeploymentActivationError)
500
- throw error;
501
- throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not read the current deployment activation.', error);
502
- }
503
- }
504
- async function historyPage(targetInput, queryInput) {
505
- const target = validateTarget(targetInput, 'HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST');
506
- const query = validateHistoryQuery(queryInput);
507
- try {
508
- const key = sha256(TARGET_IDENTITY_DOMAIN, targetCanonical(target));
509
- const targetDirectory = path.join(await activationRoot(), key);
510
- if (!await pathExists(targetDirectory)) {
511
- return Object.freeze({ activations: Object.freeze([]), nextBefore: null });
512
- }
513
- return await resolveHistoryPage(targetDirectory, target, query);
514
- }
515
- catch (error) {
516
- if (error instanceof DeploymentActivationError)
517
- throw error;
518
- throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not read deployment activation history.', error);
519
- }
436
+ async function current(target) {
437
+ return currentActivation(await history(target));
520
438
  }
521
439
  async function activate(request) {
522
440
  const target = validateTarget(request.target, 'HQ_DEPLOYMENT_ACTIVATION_INVALID_REQUEST');
@@ -549,7 +467,8 @@ export function createFileSystemDeploymentActivationRegistry(options) {
549
467
  try {
550
468
  const activations = await activationRoot();
551
469
  const targetDirectory = await ensureTargetDirectory(activations, target);
552
- const existing = await resolveCurrent(targetDirectory, target);
470
+ const existingHistory = await resolveHistory(targetDirectory, target);
471
+ const existing = currentActivation(existingHistory);
553
472
  if (existing?.releaseIdentity === releaseIdentity) {
554
473
  return Object.freeze({ status: 'already-active', activation: existing });
555
474
  }
@@ -595,7 +514,7 @@ export function createFileSystemDeploymentActivationRegistry(options) {
595
514
  if (published) {
596
515
  return Object.freeze({ status: 'activated', activation: prepared.record });
597
516
  }
598
- const resolved = await resolveCurrent(targetDirectory, target);
517
+ const resolved = currentActivation(await resolveHistory(targetDirectory, target));
599
518
  if (resolved?.releaseIdentity === releaseIdentity) {
600
519
  return Object.freeze({ status: 'already-active', activation: resolved });
601
520
  }
@@ -607,5 +526,5 @@ export function createFileSystemDeploymentActivationRegistry(options) {
607
526
  throw activationError('HQ_DEPLOYMENT_ACTIVATION_IO', 'Could not update deployment activation state.', error);
608
527
  }
609
528
  }
610
- return Object.freeze({ activate, current, history, historyPage });
529
+ return Object.freeze({ activate, current, history });
611
530
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError, validateDeploymentActivationRecord, } from './activation.js';
2
- export type { DeploymentActivationErrorCode, DeploymentActivationHistoryPage, DeploymentActivationHistoryQuery, DeploymentActivationRegistry, DeploymentActivationRelease, DeploymentActivationRecord, DeploymentActivationRequest, DeploymentActivationResult, DeploymentReleaseReader, FileSystemDeploymentActivationRegistryOptions, } from './activation.js';
1
+ export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError, } from './activation.js';
2
+ export type { DeploymentActivationErrorCode, DeploymentActivationRegistry, DeploymentActivationRelease, DeploymentActivationRecord, DeploymentActivationRequest, DeploymentActivationResult, DeploymentReleaseReader, FileSystemDeploymentActivationRegistryOptions, } from './activation.js';
3
3
  export { DEPLOYMENT_BUNDLE_CONTRACT, DEPLOYMENT_BUNDLE_MANIFEST, verifyDeploymentBundle, } from './bundle.js';
4
4
  export type { VerifiedDeploymentBundle } from './bundle.js';
5
5
  export { DeploymentIntakeError, } from './errors.js';
@@ -7,19 +7,7 @@ export type { DeploymentIntakeErrorCode } from './errors.js';
7
7
  export { createFileSystemDeploymentSubmissionStore, FileSystemDeploymentStoreError, } from './filesystem-store.js';
8
8
  export type { FileSystemDeploymentStoreErrorCode, FileSystemDeploymentSubmissionStore, FileSystemDeploymentSubmissionStoreOptions, StoredDeploymentSubmission, } from './filesystem-store.js';
9
9
  export { createDeploymentIntake, } from './intake.js';
10
- export { createDeploymentControlPlaneFetchHandler, createDeploymentControlPlaneNodeHandler, } from './control-plane-adapters.js';
11
- export type { DeploymentControlPlaneFetchHandler, DeploymentControlPlaneNodeHandler, } from './control-plane-adapters.js';
12
- export { createDeploymentControlPlane, } from './control-plane.js';
13
- export type { DeploymentControlPlane, DeploymentControlPlaneAction, DeploymentControlPlaneAuthorizationInput, DeploymentControlPlaneAuthorizer, DeploymentControlPlaneErrorCode, DeploymentControlPlaneOptions, DeploymentControlPlaneRequest, DeploymentControlPlaneResponse, } from './control-plane.js';
14
- export { DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS, resolveDeploymentControlPlaneLimits, } from './control-plane-limits.js';
15
- export type { DeploymentControlPlaneLimits } from './control-plane-limits.js';
16
10
  export { DEFAULT_DEPLOYMENT_INTAKE_LIMITS, resolveDeploymentIntakeLimits, } from './limits.js';
17
11
  export type { DeploymentIntakeLimits } from './limits.js';
18
- export { createNodeWorkerDeploymentRuntimeFactory, NodeDeploymentRuntimeError, } from './node-runtime-factory.js';
19
- export type { NodeDeploymentRuntimeErrorCode, NodeDeploymentRuntimeFactoryOptions, } from './node-runtime-factory.js';
20
- export { createDeploymentRuntimeMaterializer, DeploymentRuntimeMaterializationError, } from './runtime-materialization.js';
21
- export type { DeploymentRuntimeArtifactSnapshot, DeploymentRuntimeMaterializationErrorCode, DeploymentRuntimeMaterializer, DeploymentRuntimeMaterializerOptions, DeploymentRuntimeQueryBinding, DeploymentRuntimeRelease, DeploymentRuntimeReleaseReader, DeploymentRuntimeSnapshot, } from './runtime-materialization.js';
22
- export { createDeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorError, } from './runtime-supervisor.js';
23
- export type { DeploymentRuntimeFactory, DeploymentRuntimeInstance, DeploymentRuntimeInstanceInvocation, DeploymentRuntimeInvocation, DeploymentRuntimeReconcileResult, DeploymentRuntimeStatus, DeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorErrorCode, DeploymentRuntimeSupervisorOptions, } from './runtime-supervisor.js';
24
12
  export type { DeploymentAuthenticationInput, DeploymentAuthenticator, DeploymentAuthorizationInput, DeploymentAuthorizer, DeploymentIntake, DeploymentIntakeOptions, DeploymentIntakeRequest, DeploymentIntakeResponse, DeploymentSubmissionResponse, DeploymentSubmissionStore, VerifiedDeploymentSubmission, } from './types.js';
25
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4CAA4C,EAC5C,yBAAyB,EACzB,kCAAkC,GACnC,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,6BAA6B,EAC7B,+BAA+B,EAC/B,gCAAgC,EAChC,4BAA4B,EAC5B,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,EACvB,6CAA6C,GAC9C,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,yCAAyC,EACzC,8BAA8B,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,kCAAkC,EAClC,mCAAmC,EACnC,0CAA0C,EAC1C,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,wCAAwC,EACxC,uCAAuC,GACxC,MAAM,6BAA6B,CAAC;AACrC,YAAY,EACV,kCAAkC,EAClC,iCAAiC,GAClC,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,4BAA4B,GAC7B,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,sBAAsB,EACtB,4BAA4B,EAC5B,wCAAwC,EACxC,gCAAgC,EAChC,+BAA+B,EAC/B,6BAA6B,EAC7B,6BAA6B,EAC7B,8BAA8B,GAC/B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,uCAAuC,EACvC,mCAAmC,GACpC,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAC9E,OAAO,EACL,gCAAgC,EAChC,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EACL,wCAAwC,EACxC,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,8BAA8B,EAC9B,mCAAmC,GACpC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,mCAAmC,EACnC,qCAAqC,GACtC,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,iCAAiC,EACjC,yCAAyC,EACzC,6BAA6B,EAC7B,oCAAoC,EACpC,6BAA6B,EAC7B,wBAAwB,EACxB,8BAA8B,EAC9B,yBAAyB,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,iCAAiC,EACjC,gCAAgC,GACjC,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,wBAAwB,EACxB,yBAAyB,EACzB,mCAAmC,EACnC,2BAA2B,EAC3B,gCAAgC,EAChC,uBAAuB,EACvB,2BAA2B,EAC3B,oCAAoC,EACpC,kCAAkC,GACnC,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACV,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4CAA4C,EAC5C,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,6BAA6B,EAC7B,4BAA4B,EAC5B,2BAA2B,EAC3B,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC1B,uBAAuB,EACvB,6CAA6C,GAC9C,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,0BAA0B,EAC1B,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,EACL,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EACL,yCAAyC,EACzC,8BAA8B,GAC/B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EACV,kCAAkC,EAClC,mCAAmC,EACnC,0CAA0C,EAC1C,0BAA0B,GAC3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,gCAAgC,EAChC,6BAA6B,GAC9B,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EACV,6BAA6B,EAC7B,uBAAuB,EACvB,4BAA4B,EAC5B,oBAAoB,EACpB,gBAAgB,EAChB,uBAAuB,EACvB,uBAAuB,EACvB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,4BAA4B,GAC7B,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,12 +1,6 @@
1
- export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError, validateDeploymentActivationRecord, } from './activation.js';
1
+ export { createFileSystemDeploymentActivationRegistry, DeploymentActivationError, } from './activation.js';
2
2
  export { DEPLOYMENT_BUNDLE_CONTRACT, DEPLOYMENT_BUNDLE_MANIFEST, verifyDeploymentBundle, } from './bundle.js';
3
3
  export { DeploymentIntakeError, } from './errors.js';
4
4
  export { createFileSystemDeploymentSubmissionStore, FileSystemDeploymentStoreError, } from './filesystem-store.js';
5
5
  export { createDeploymentIntake, } from './intake.js';
6
- export { createDeploymentControlPlaneFetchHandler, createDeploymentControlPlaneNodeHandler, } from './control-plane-adapters.js';
7
- export { createDeploymentControlPlane, } from './control-plane.js';
8
- export { DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS, resolveDeploymentControlPlaneLimits, } from './control-plane-limits.js';
9
6
  export { DEFAULT_DEPLOYMENT_INTAKE_LIMITS, resolveDeploymentIntakeLimits, } from './limits.js';
10
- export { createNodeWorkerDeploymentRuntimeFactory, NodeDeploymentRuntimeError, } from './node-runtime-factory.js';
11
- export { createDeploymentRuntimeMaterializer, DeploymentRuntimeMaterializationError, } from './runtime-materialization.js';
12
- export { createDeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorError, } from './runtime-supervisor.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/deployment",
3
- "version": "0.0.0-canary-20260719200737",
3
+ "version": "0.2.0",
4
4
  "description": "Provider-neutral deployment verification and intake for Hypequery",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -18,7 +18,7 @@
18
18
  "README.md"
19
19
  ],
20
20
  "dependencies": {
21
- "@hypequery/protocol": "0.0.0-canary-20260719200737"
21
+ "@hypequery/protocol": "0.6.0"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@types/node": "^22.5.0",
@@ -41,6 +41,6 @@
41
41
  "dev": "tsc --project tsconfig.json --watch",
42
42
  "lint": "eslint --ext .ts \"src/**/*.ts\"",
43
43
  "test": "vitest run",
44
- "types": "tsc --project tsconfig.json --noEmit && tsc --project tsconfig.test.json"
44
+ "types": "tsc --project tsconfig.json --noEmit"
45
45
  }
46
46
  }
@@ -1,7 +0,0 @@
1
- import type { IncomingMessage, ServerResponse } from 'node:http';
2
- import type { DeploymentControlPlane } from './control-plane.js';
3
- export type DeploymentControlPlaneFetchHandler = (request: Request) => Promise<Response>;
4
- export type DeploymentControlPlaneNodeHandler = (request: IncomingMessage, response: ServerResponse) => Promise<void>;
5
- export declare function createDeploymentControlPlaneFetchHandler(controlPlane: DeploymentControlPlane): DeploymentControlPlaneFetchHandler;
6
- export declare function createDeploymentControlPlaneNodeHandler(controlPlane: DeploymentControlPlane): DeploymentControlPlaneNodeHandler;
7
- //# sourceMappingURL=control-plane-adapters.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"control-plane-adapters.d.ts","sourceRoot":"","sources":["../src/control-plane-adapters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,KAAK,EACV,sBAAsB,EAGvB,MAAM,oBAAoB,CAAC;AAE5B,MAAM,MAAM,kCAAkC,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AACzF,MAAM,MAAM,iCAAiC,GAAG,CAC9C,OAAO,EAAE,eAAe,EACxB,QAAQ,EAAE,cAAc,KACrB,OAAO,CAAC,IAAI,CAAC,CAAC;AAkHnB,wBAAgB,wCAAwC,CACtD,YAAY,EAAE,sBAAsB,GACnC,kCAAkC,CAkBpC;AAED,wBAAgB,uCAAuC,CACrD,YAAY,EAAE,sBAAsB,GACnC,iCAAiC,CAgCnC"}
@@ -1,163 +0,0 @@
1
- const INTERNAL_BODY = '{"error":{"code":"HQ_CONTROL_INTERNAL","message":"The deployment control-plane request could not be processed."}}\n';
2
- const INTERNAL_RESPONSE = Object.freeze({
3
- status: 500,
4
- headers: Object.freeze({
5
- 'content-type': 'application/json; charset=utf-8',
6
- 'content-length': String(Buffer.byteLength(INTERNAL_BODY)),
7
- 'cache-control': 'no-store',
8
- }),
9
- body: INTERNAL_BODY,
10
- });
11
- const FETCH_SINGLETON_HEADERS = new Set([
12
- 'authorization',
13
- 'content-length',
14
- 'content-type',
15
- 'idempotency-key',
16
- 'x-hypequery-bundle-identity',
17
- 'x-hypequery-release-identity',
18
- ]);
19
- function queryParameters(search) {
20
- const query = Object.create(null);
21
- for (const [name, value] of search) {
22
- const current = query[name];
23
- if (current === undefined) {
24
- query[name] = value;
25
- }
26
- else if (typeof current === 'string') {
27
- query[name] = Object.freeze([current, value]);
28
- }
29
- else {
30
- query[name] = Object.freeze([...current, value]);
31
- }
32
- }
33
- return Object.freeze(query);
34
- }
35
- function fetchHeaders(input) {
36
- const headers = Object.create(null);
37
- for (const [name, value] of input.entries()) {
38
- headers[name] = value;
39
- if (FETCH_SINGLETON_HEADERS.has(name) && value.includes(',')) {
40
- // Fetch combines duplicate header lines before exposing Headers. Reify a
41
- // second case-insensitive entry so the core singleton guard rejects it.
42
- headers[name.toUpperCase()] = value;
43
- }
44
- }
45
- return Object.freeze(headers);
46
- }
47
- async function* fetchBody(input) {
48
- if (input === null)
49
- return;
50
- const reader = input.getReader();
51
- try {
52
- while (true) {
53
- const result = await reader.read();
54
- if (result.done)
55
- return;
56
- yield result.value;
57
- }
58
- }
59
- finally {
60
- reader.releaseLock();
61
- }
62
- }
63
- function nodeHeaders(request) {
64
- const headers = Object.create(null);
65
- for (let index = 0; index < request.rawHeaders.length; index += 2) {
66
- const name = request.rawHeaders[index].toLowerCase();
67
- const value = request.rawHeaders[index + 1];
68
- if (headers[name] === undefined) {
69
- headers[name] = value;
70
- }
71
- else {
72
- // Keep a second case-insensitive entry so the core duplicate-header guard
73
- // observes duplicates instead of accepting Node's comma-joined value.
74
- headers[name.toUpperCase()] = value;
75
- }
76
- }
77
- return Object.freeze(headers);
78
- }
79
- async function* nodeBody(request) {
80
- for await (const chunk of request) {
81
- yield chunk instanceof Uint8Array ? chunk : Buffer.from(chunk);
82
- }
83
- }
84
- function nodeHasBody(headers) {
85
- return Object.entries(headers).some(([name, value]) => {
86
- const normalized = name.toLowerCase();
87
- return normalized === 'transfer-encoding'
88
- || (normalized === 'content-length' && value !== '0');
89
- });
90
- }
91
- function internalFetchResponse() {
92
- return new Response(INTERNAL_RESPONSE.body, {
93
- status: INTERNAL_RESPONSE.status,
94
- headers: INTERNAL_RESPONSE.headers,
95
- });
96
- }
97
- function sendNodeResponse(response, controlResponse) {
98
- if (response.writableEnded || response.headersSent)
99
- return;
100
- response.statusCode = controlResponse.status;
101
- for (const [name, value] of Object.entries(controlResponse.headers)) {
102
- response.setHeader(name, value);
103
- }
104
- response.end(controlResponse.body);
105
- }
106
- export function createDeploymentControlPlaneFetchHandler(controlPlane) {
107
- return async (request) => {
108
- try {
109
- const url = new URL(request.url);
110
- const response = await controlPlane.handle({
111
- method: request.method,
112
- path: url.pathname,
113
- query: queryParameters(url.searchParams),
114
- headers: fetchHeaders(request.headers),
115
- body: fetchBody(request.body),
116
- hasBody: request.body !== null,
117
- signal: request.signal,
118
- });
119
- return new Response(response.body, { status: response.status, headers: response.headers });
120
- }
121
- catch {
122
- return internalFetchResponse();
123
- }
124
- };
125
- }
126
- export function createDeploymentControlPlaneNodeHandler(controlPlane) {
127
- return async (request, response) => {
128
- const abort = new AbortController();
129
- const abortRequest = () => {
130
- if (!request.complete)
131
- abort.abort(new Error('The request connection was closed.'));
132
- };
133
- const abortResponse = () => {
134
- if (!response.writableEnded)
135
- abort.abort(new Error('The response connection was closed.'));
136
- };
137
- request.socket.once('close', abortRequest);
138
- response.once('close', abortResponse);
139
- if (request.destroyed && !request.complete)
140
- abortRequest();
141
- try {
142
- const url = new URL(request.url ?? '/', 'http://deployment-control-plane.invalid');
143
- const headers = nodeHeaders(request);
144
- const controlResponse = await controlPlane.handle({
145
- method: request.method ?? 'GET',
146
- path: url.pathname,
147
- query: queryParameters(url.searchParams),
148
- headers,
149
- body: nodeBody(request),
150
- hasBody: nodeHasBody(headers),
151
- signal: abort.signal,
152
- });
153
- sendNodeResponse(response, controlResponse);
154
- }
155
- catch {
156
- sendNodeResponse(response, INTERNAL_RESPONSE);
157
- }
158
- finally {
159
- request.socket.off('close', abortRequest);
160
- response.off('close', abortResponse);
161
- }
162
- };
163
- }
@@ -1,7 +0,0 @@
1
- export interface DeploymentControlPlaneLimits {
2
- readonly maxActivationRequestBytes: number;
3
- readonly maxHistoryPageSize: number;
4
- }
5
- export declare const DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS: Readonly<DeploymentControlPlaneLimits>;
6
- export declare function resolveDeploymentControlPlaneLimits(input?: Partial<DeploymentControlPlaneLimits>): Readonly<DeploymentControlPlaneLimits>;
7
- //# sourceMappingURL=control-plane-limits.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"control-plane-limits.d.ts","sourceRoot":"","sources":["../src/control-plane-limits.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,eAAO,MAAM,uCAAuC,EACpD,QAAQ,CAAC,4BAA4B,CAGnC,CAAC;AAEH,wBAAgB,mCAAmC,CACjD,KAAK,GAAE,OAAO,CAAC,4BAA4B,CAAM,GAChD,QAAQ,CAAC,4BAA4B,CAAC,CAcxC"}
@@ -1,18 +0,0 @@
1
- export const DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS = Object.freeze({
2
- maxActivationRequestBytes: 16 * 1024,
3
- maxHistoryPageSize: 100,
4
- });
5
- export function resolveDeploymentControlPlaneLimits(input = {}) {
6
- const limits = { ...DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS };
7
- for (const key of Object.keys(limits)) {
8
- const value = input[key];
9
- if (value === undefined)
10
- continue;
11
- if (!Number.isSafeInteger(value) || value < 1
12
- || value > DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS[key]) {
13
- throw new RangeError(`${key} must be a positive safe integer no greater than the control-plane v1 maximum`);
14
- }
15
- limits[key] = value;
16
- }
17
- return Object.freeze(limits);
18
- }