@hypequery/deployment 0.7.5 → 0.9.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 (70) hide show
  1. package/README.md +5 -31
  2. package/dist/activation.d.ts.map +1 -1
  3. package/dist/activation.js +2 -1
  4. package/dist/authorized-contract.d.ts +72 -0
  5. package/dist/authorized-contract.d.ts.map +1 -0
  6. package/dist/authorized-contract.js +132 -0
  7. package/dist/bundle.d.ts.map +1 -1
  8. package/dist/bundle.js +10 -36
  9. package/dist/control-plane-limits.js +1 -1
  10. package/dist/filesystem-store.d.ts.map +1 -1
  11. package/dist/filesystem-store.js +7 -22
  12. package/dist/index.d.ts +6 -18
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +5 -9
  15. package/dist/intake.d.ts.map +1 -1
  16. package/dist/intake.js +8 -5
  17. package/dist/limits.d.ts.map +1 -1
  18. package/dist/limits.js +5 -2
  19. package/dist/principal.d.ts +11 -0
  20. package/dist/principal.d.ts.map +1 -0
  21. package/dist/principal.js +1 -0
  22. package/dist/semantic-data-plane.d.ts +70 -0
  23. package/dist/semantic-data-plane.d.ts.map +1 -0
  24. package/dist/semantic-data-plane.js +234 -0
  25. package/dist/semantic-invocation-errors.d.ts +30 -0
  26. package/dist/semantic-invocation-errors.d.ts.map +1 -0
  27. package/dist/semantic-invocation-errors.js +45 -0
  28. package/dist/semantic-operation-validation.d.ts +29 -0
  29. package/dist/semantic-operation-validation.d.ts.map +1 -0
  30. package/dist/semantic-operation-validation.js +157 -0
  31. package/dist/utils/read-bounded-file.d.ts +4 -0
  32. package/dist/utils/read-bounded-file.d.ts.map +1 -0
  33. package/dist/utils/read-bounded-file.js +18 -0
  34. package/dist/utils/required-access.d.ts +2 -0
  35. package/dist/utils/required-access.d.ts.map +1 -0
  36. package/dist/utils/required-access.js +4 -0
  37. package/dist/utils/semantic-budget-limits.d.ts +7 -0
  38. package/dist/utils/semantic-budget-limits.d.ts.map +1 -0
  39. package/dist/utils/semantic-budget-limits.js +15 -0
  40. package/dist/utils/semantic-executor-failure.d.ts +21 -0
  41. package/dist/utils/semantic-executor-failure.d.ts.map +1 -0
  42. package/dist/utils/semantic-executor-failure.js +52 -0
  43. package/package.json +5 -4
  44. package/dist/data-plane-adapters.d.ts +0 -18
  45. package/dist/data-plane-adapters.d.ts.map +0 -1
  46. package/dist/data-plane-adapters.js +0 -304
  47. package/dist/data-plane-limits.d.ts +0 -5
  48. package/dist/data-plane-limits.d.ts.map +0 -1
  49. package/dist/data-plane-limits.js +0 -5
  50. package/dist/data-plane-runtime.d.ts +0 -13
  51. package/dist/data-plane-runtime.d.ts.map +0 -1
  52. package/dist/data-plane-runtime.js +0 -12
  53. package/dist/data-plane.d.ts +0 -84
  54. package/dist/data-plane.d.ts.map +0 -1
  55. package/dist/data-plane.js +0 -209
  56. package/dist/filesystem-host.d.ts +0 -51
  57. package/dist/filesystem-host.d.ts.map +0 -1
  58. package/dist/filesystem-host.js +0 -73
  59. package/dist/host.d.ts +0 -40
  60. package/dist/host.d.ts.map +0 -1
  61. package/dist/host.js +0 -183
  62. package/dist/node-runtime-factory.d.ts +0 -27
  63. package/dist/node-runtime-factory.d.ts.map +0 -1
  64. package/dist/node-runtime-factory.js +0 -336
  65. package/dist/runtime-materialization.d.ts +0 -58
  66. package/dist/runtime-materialization.d.ts.map +0 -1
  67. package/dist/runtime-materialization.js +0 -187
  68. package/dist/runtime-supervisor.d.ts +0 -77
  69. package/dist/runtime-supervisor.d.ts.map +0 -1
  70. package/dist/runtime-supervisor.js +0 -265
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @hypequery/deployment
2
2
 
3
- Provider-neutral building blocks for receiving, verifying, activating, and hosting Hypequery deployment bundles.
3
+ Provider-neutral building blocks for receiving, verifying, activating, and invoking Hypequery deployment bundles.
4
4
 
5
5
  This package is for Cloud providers and self-hosted control planes. Application teams normally use `hypequery deploy` through `@hypequery/cli` instead.
6
6
 
@@ -11,7 +11,7 @@ Every deployment is treated as immutable content. Before storage or execution, t
11
11
  - the target-bound release envelope;
12
12
  - the closed bundle manifest;
13
13
  - declared paths and byte limits;
14
- - every file hash and artifact reference;
14
+ - every declared file hash and the canonical deployment JSON;
15
15
  - deployment, bundle, and release identities;
16
16
  - activation revision consistency.
17
17
 
@@ -24,10 +24,8 @@ Symbolic links, undeclared files, path traversal, missing content, and identity
24
24
  - a durable reference filesystem store;
25
25
  - compare-and-swap activation and rollback;
26
26
  - Node and Fetch control-plane adapters;
27
- - immutable runtime materialization;
28
- - readiness-gated runtime supervision;
29
- - named-query data-plane execution;
30
- - a reference single-host composition.
27
+ - contract-driven semantic invocation with an injected dataset executor;
28
+ - authorization-aware contract projection for discovery.
31
29
 
32
30
  ## Minimal intake
33
31
 
@@ -50,33 +48,9 @@ const intake = createDeploymentIntake({
50
48
 
51
49
  Authentication happens before upload bytes are consumed. The store receives a fully verified temporary bundle and must persist required bytes before returning.
52
50
 
53
- ## Single-host reference
54
-
55
- ```ts
56
- import { createFileSystemDeploymentHost } from '@hypequery/deployment';
57
-
58
- const service = createFileSystemDeploymentHost({
59
- directory: '/var/lib/hypequery/deployments',
60
- targets: [{ project: 'analytics', environment: 'production' }],
61
- intake: {
62
- authenticator: deploymentAuthenticator,
63
- authorizer: deploymentAuthorizer,
64
- },
65
- controlPlane: {
66
- authenticator: operatorAuthenticator,
67
- authorizer: operatorAuthorizer,
68
- },
69
- configureDataPlane,
70
- });
71
-
72
- await service.start();
73
- ```
74
-
75
- Distributed providers can keep the same interfaces while replacing persistence, runtime isolation, secret resolution, routing, and observability.
76
-
77
51
  ## Trust boundary
78
52
 
79
- The reference Node worker manages lifecycle and immutable generations for trusted deployment code; it is not a hostile-code sandbox. The filesystem store assumes its configured directory is controlled by the operator.
53
+ This package validates the deployment contract and gates semantic calls, but does not execute datasets or supervise application code. Providers supply the executor, credentials, tenant resolution, routing, and runtime isolation. The filesystem store assumes its configured directory is controlled by the operator.
80
54
 
81
55
  ## Specifications
82
56
 
@@ -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":"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"}
@@ -3,6 +3,7 @@ import { constants } from 'node:fs';
3
3
  import { lstat, mkdir, mkdtemp, open, readdir, rename, rm, } from 'node:fs/promises';
4
4
  import path from 'node:path';
5
5
  import { prepareProtocolDeploymentReleaseEnvelope, validateProtocolDeploymentReleaseTarget, } from '@hypequery/protocol';
6
+ import { readBoundedFile } from './utils/read-bounded-file.js';
6
7
  const ACTIVATION_FILE = 'activation.json';
7
8
  const CLAIMS_DIRECTORY = 'claims';
8
9
  // Each predecessor has one filesystem slot for its successor. Renaming a
@@ -242,7 +243,7 @@ async function readRegularFile(filePath, maximumBytes) {
242
243
  if (!stat.isFile() || stat.size < 1 || stat.size > maximumBytes) {
243
244
  throw new Error(`Stored entry is not a bounded regular file: ${filePath}`);
244
245
  }
245
- return await handle.readFile();
246
+ return await readBoundedFile(handle, maximumBytes, 1, `Stored entry is not a bounded regular file: ${filePath}`);
246
247
  }
247
248
  finally {
248
249
  await handle.close();
@@ -0,0 +1,72 @@
1
+ /**
2
+ * What one principal is allowed to see of a deployment contract.
3
+ *
4
+ * Discovery and execution must agree about who may reach what. The data plane
5
+ * already decides that per call, from the endpoint policy on the target; a
6
+ * gateway listing tools has to make the same decision over the whole contract,
7
+ * before any call exists. Restating the rule there would put an authorization
8
+ * predicate in two packages, and the copy that drifts is the one that leaks.
9
+ *
10
+ * The projection narrows, never widens: it can remove a target a principal may
11
+ * not reach, and can never add one or loosen a policy. Feeding the result to
12
+ * catalog projection or schema compilation therefore cannot advertise something
13
+ * execution would refuse.
14
+ */
15
+ import type { ProtocolAccessPolicy, ProtocolDeploymentContract, ProtocolEndpointPolicy } from '@hypequery/protocol';
16
+ import type { DeploymentDataPlanePrincipal } from './principal.js';
17
+ /**
18
+ * Whether a principal satisfies an access policy.
19
+ *
20
+ * Shares `missing` with the semantic data plane rather than restating it, which
21
+ * is the whole point of this module existing in Core: one predicate, so
22
+ * discovery cannot come to answer differently than execution.
23
+ */
24
+ export declare function satisfiesDeploymentAccess(access: ProtocolAccessPolicy, principal: DeploymentDataPlanePrincipal | null): boolean;
25
+ /** Whether a principal may reach a target published under this endpoint policy. */
26
+ export declare function isDeploymentEndpointAuthorized(endpoint: ProtocolEndpointPolicy | undefined, principal: DeploymentDataPlanePrincipal | null): boolean;
27
+ export interface AuthorizedDeploymentProjection {
28
+ /**
29
+ * A valid contract narrowed to what the principal may see, including any
30
+ * dataset retained only to support a join.
31
+ */
32
+ readonly contract: ProtocolDeploymentContract;
33
+ /**
34
+ * Datasets addressable as a `query_dataset` target, in contract order.
35
+ *
36
+ * Narrower than `contract.datasets`, which also holds datasets retained only
37
+ * to support a join. Always read this before advertising anything: catalog
38
+ * projection and rehydration enumerate every dataset they are given and
39
+ * neither consults an endpoint, so handing them the whole contract would
40
+ * advertise a supporting dataset and disclose its shape to a principal with
41
+ * no access to it.
42
+ */
43
+ readonly queryable: readonly string[];
44
+ }
45
+ /**
46
+ * Projects the contract down to what `principal` may see.
47
+ *
48
+ * A dataset is *published* when the principal may address it directly, and
49
+ * *supporting* when something published still needs it to stay coherent — the
50
+ * target of a relationship. A supporting dataset loses its endpoint and keeps
51
+ * only what a join reaches, so a relationship can still be traversed exactly as
52
+ * execution would traverse it while the dataset itself is not offered as a
53
+ * target.
54
+ *
55
+ * Dropping a relationship target instead would be the tempting alternative and
56
+ * is wrong twice: it would invalidate the relationship that names it, and it
57
+ * would advertise less than the data plane permits, since a one-hop join is
58
+ * governed by the endpoint of the dataset being queried, not by the target's.
59
+ *
60
+ * The contract and the target list are returned separately rather than as one
61
+ * contract because nothing downstream reads an endpoint.
62
+ * `projectAgentSafeCatalog` and `rehydrateProtocolDatasets` enumerate whatever
63
+ * they are handed, so an unpublished dataset left in the contract they see is
64
+ * an advertised one.
65
+ *
66
+ * The contract is revalidated. Callers hand it to catalog projection, schema
67
+ * compilation, and rehydration, all of which assume a valid contract; a
68
+ * projection that could emit an invalid one would move that failure to whatever
69
+ * read it next.
70
+ */
71
+ export declare function projectAuthorizedDeploymentContract(contract: ProtocolDeploymentContract, principal: DeploymentDataPlanePrincipal | null): AuthorizedDeploymentProjection;
72
+ //# sourceMappingURL=authorized-contract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authorized-contract.d.ts","sourceRoot":"","sources":["../src/authorized-contract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,oBAAoB,EACpB,0BAA0B,EAE1B,sBAAsB,EACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAGnE;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,oBAAoB,EAC5B,SAAS,EAAE,4BAA4B,GAAG,IAAI,GAC7C,OAAO,CAIT;AAED,mFAAmF;AACnF,wBAAgB,8BAA8B,CAC5C,QAAQ,EAAE,sBAAsB,GAAG,SAAS,EAC5C,SAAS,EAAE,4BAA4B,GAAG,IAAI,GAC7C,OAAO,CAKT;AAkCD,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;IAC9C;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;CACvC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mCAAmC,CACjD,QAAQ,EAAE,0BAA0B,EACpC,SAAS,EAAE,4BAA4B,GAAG,IAAI,GAC7C,8BAA8B,CA2ChC"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * What one principal is allowed to see of a deployment contract.
3
+ *
4
+ * Discovery and execution must agree about who may reach what. The data plane
5
+ * already decides that per call, from the endpoint policy on the target; a
6
+ * gateway listing tools has to make the same decision over the whole contract,
7
+ * before any call exists. Restating the rule there would put an authorization
8
+ * predicate in two packages, and the copy that drifts is the one that leaks.
9
+ *
10
+ * The projection narrows, never widens: it can remove a target a principal may
11
+ * not reach, and can never add one or loosen a policy. Feeding the result to
12
+ * catalog projection or schema compilation therefore cannot advertise something
13
+ * execution would refuse.
14
+ */
15
+ import { validateProtocolDeploymentContract } from '@hypequery/protocol';
16
+ import { missing } from './utils/required-access.js';
17
+ /**
18
+ * Whether a principal satisfies an access policy.
19
+ *
20
+ * Shares `missing` with the semantic data plane rather than restating it, which
21
+ * is the whole point of this module existing in Core: one predicate, so
22
+ * discovery cannot come to answer differently than execution.
23
+ */
24
+ export function satisfiesDeploymentAccess(access, principal) {
25
+ if (access.kind === 'public')
26
+ return true;
27
+ if (!principal)
28
+ return false;
29
+ return !missing(access.roles, principal.roles) && !missing(access.scopes, principal.scopes);
30
+ }
31
+ /** Whether a principal may reach a target published under this endpoint policy. */
32
+ export function isDeploymentEndpointAuthorized(endpoint, principal) {
33
+ // An absent endpoint is not a permissive one. A contract may describe a
34
+ // dataset it never published, and an unpublished target is unreachable for
35
+ // everyone — which is how the data plane's own target resolution reads it.
36
+ return endpoint !== undefined && satisfiesDeploymentAccess(endpoint.access, principal);
37
+ }
38
+ /**
39
+ * Narrows a dataset retained only to support a join.
40
+ *
41
+ * The principal cannot address this dataset, so advertising it whole would
42
+ * publish the name and type of every dimension, filter, and measure on it.
43
+ * What a join actually reaches is the target's dimensions — `resolveDataset`
44
+ * offers each groupable one as `<relationship>.<name>` and each filterable one
45
+ * under the full operator set — so those stay and everything else goes.
46
+ *
47
+ * A dataset no queryable relationship reaches keeps nothing but its time field,
48
+ * which the planner reads for every grained query. It is retained at all only
49
+ * because a relationship names it and the contract would not validate without
50
+ * it.
51
+ */
52
+ function narrowToJoin(dataset, reachable) {
53
+ // `defaults` describes how to query the dataset directly, which is exactly
54
+ // what this principal may not do.
55
+ const { defaults: _defaults, endpoint: _endpoint, ...rest } = dataset;
56
+ const timeField = dataset.timeField === undefined ? undefined : String(dataset.timeField);
57
+ return {
58
+ ...rest,
59
+ dimensions: reachable
60
+ ? dataset.dimensions
61
+ : dataset.dimensions.filter(dimension => String(dimension.name) === timeField),
62
+ measures: [],
63
+ filters: [],
64
+ };
65
+ }
66
+ /**
67
+ * Projects the contract down to what `principal` may see.
68
+ *
69
+ * A dataset is *published* when the principal may address it directly, and
70
+ * *supporting* when something published still needs it to stay coherent — the
71
+ * target of a relationship. A supporting dataset loses its endpoint and keeps
72
+ * only what a join reaches, so a relationship can still be traversed exactly as
73
+ * execution would traverse it while the dataset itself is not offered as a
74
+ * target.
75
+ *
76
+ * Dropping a relationship target instead would be the tempting alternative and
77
+ * is wrong twice: it would invalidate the relationship that names it, and it
78
+ * would advertise less than the data plane permits, since a one-hop join is
79
+ * governed by the endpoint of the dataset being queried, not by the target's.
80
+ *
81
+ * The contract and the target list are returned separately rather than as one
82
+ * contract because nothing downstream reads an endpoint.
83
+ * `projectAgentSafeCatalog` and `rehydrateProtocolDatasets` enumerate whatever
84
+ * they are handed, so an unpublished dataset left in the contract they see is
85
+ * an advertised one.
86
+ *
87
+ * The contract is revalidated. Callers hand it to catalog projection, schema
88
+ * compilation, and rehydration, all of which assume a valid contract; a
89
+ * projection that could emit an invalid one would move that failure to whatever
90
+ * read it next.
91
+ */
92
+ export function projectAuthorizedDeploymentContract(contract, principal) {
93
+ const byName = new Map(contract.datasets.map(dataset => [String(dataset.name), dataset]));
94
+ const published = new Set(contract.datasets
95
+ .filter(dataset => isDeploymentEndpointAuthorized(dataset.endpoint, principal))
96
+ .map(dataset => String(dataset.name)));
97
+ const required = new Set();
98
+ const require = (name) => {
99
+ if (required.has(name) || !byName.has(name))
100
+ return;
101
+ required.add(name);
102
+ // Transitive: a retained target has relationships of its own, and every
103
+ // target named in the contract has to still be there for it to validate.
104
+ for (const relationship of byName.get(name).relationships) {
105
+ require(String(relationship.target));
106
+ }
107
+ };
108
+ for (const name of published)
109
+ require(name);
110
+ // What each dataset is reachable *as a join target* for. Reach extends one
111
+ // queryable hop — `resolveDataset` does not recurse — and only from a dataset
112
+ // the principal can address, so a dataset retained purely so the contract
113
+ // validates passes none of it on.
114
+ const reachable = new Set();
115
+ for (const name of published) {
116
+ for (const relationship of byName.get(name).relationships) {
117
+ if (relationship.queryable)
118
+ reachable.add(String(relationship.target));
119
+ }
120
+ }
121
+ const datasets = contract.datasets
122
+ .filter(dataset => required.has(String(dataset.name)))
123
+ .map(dataset => (published.has(String(dataset.name))
124
+ ? dataset
125
+ : narrowToJoin(dataset, reachable.has(String(dataset.name)))));
126
+ return Object.freeze({
127
+ contract: validateProtocolDeploymentContract({ ...contract, datasets }),
128
+ queryable: Object.freeze(datasets
129
+ .filter(dataset => published.has(String(dataset.name)))
130
+ .map(dataset => String(dataset.name))),
131
+ });
132
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAQA,OAAO,EAKL,KAAK,gCAAgC,EACrC,KAAK,0BAA0B,EAChC,MAAM,qBAAqB,CAAC;AAE7B,eAAO,MAAM,0BAA0B,gBAAgB,CAAC;AACxD,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAE5D,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,gCAAgC,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;CAC/C;AAsKD,wBAAsB,sBAAsB,CAC1C,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,wBAAwB,CAAC,CAwEnC"}
1
+ {"version":3,"file":"bundle.d.ts","sourceRoot":"","sources":["../src/bundle.ts"],"names":[],"mappings":"AAQA,OAAO,EAIL,KAAK,gCAAgC,EACrC,KAAK,0BAA0B,EAChC,MAAM,qBAAqB,CAAC;AAG7B,eAAO,MAAM,0BAA0B,gBAAgB,CAAC;AACxD,eAAO,MAAM,0BAA0B,oBAAoB,CAAC;AAE5D,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,gCAAgC,CAAC;IACpD,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,0BAA0B,CAAC;CAC/C;AAkID,wBAAsB,sBAAsB,CAC1C,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,wBAAwB,CAAC,CAqEnC"}
package/dist/bundle.js CHANGED
@@ -2,6 +2,7 @@ import { createHash } from 'node:crypto';
2
2
  import { constants, lstat, open, readdir, } from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS, prepareProtocolDeploymentBundleManifest, prepareProtocolDeploymentContract, } from '@hypequery/protocol';
5
+ import { readBoundedFile } from './utils/read-bounded-file.js';
5
6
  export const DEPLOYMENT_BUNDLE_MANIFEST = 'bundle.json';
6
7
  export const DEPLOYMENT_BUNDLE_CONTRACT = 'deployment.json';
7
8
  const utf8Decoder = new TextDecoder('utf-8', { fatal: true });
@@ -35,7 +36,7 @@ async function readBoundedRegularFile(root, relativePath, maximum, allowEmpty =
35
36
  if (stat.size < (allowEmpty ? 0 : 1) || stat.size > maximum) {
36
37
  throw new Error(`Bundle entry exceeds its byte limit: ${relativePath}`);
37
38
  }
38
- return await handle.readFile();
39
+ return await readBoundedFile(handle, maximum, allowEmpty ? 0 : 1, `Bundle entry exceeds its byte limit: ${relativePath}`);
39
40
  }
40
41
  catch (error) {
41
42
  if (errorCode(error) === 'ELOOP') {
@@ -58,11 +59,11 @@ function expectedDirectories(files) {
58
59
  return result;
59
60
  }
60
61
  async function verifyExactEntries(root, manifest) {
62
+ const source = manifest.source;
61
63
  const expectedFiles = new Set([
62
64
  DEPLOYMENT_BUNDLE_MANIFEST,
63
65
  manifest.deployment.path,
64
- ...manifest.artifacts.map(artifact => artifact.path),
65
- ...(manifest.source?.files.map(file => `${manifest.source.root}/${file.path}`) ?? []),
66
+ ...(source?.files.map(file => `${source.root}/${file.path}`) ?? []),
66
67
  ]);
67
68
  const expectedDirectoryPaths = expectedDirectories([...expectedFiles]);
68
69
  const seenFiles = new Set();
@@ -116,34 +117,6 @@ function verifyFile(bytes, file) {
116
117
  throw new Error(`Bundle entry SHA-256 does not match the manifest: ${file.path}`);
117
118
  }
118
119
  }
119
- function requireClosedContractArtifactSet(contract) {
120
- const referenced = new Map();
121
- for (const query of contract.queries) {
122
- if (query.implementation.kind === 'runtime-reference') {
123
- referenced.set(query.implementation.artifactSha256, query.implementation.runtime);
124
- }
125
- }
126
- if (referenced.size !== contract.artifacts.length) {
127
- throw new Error('Deployment contract contains missing or unreferenced runtime artifacts.');
128
- }
129
- for (const artifact of contract.artifacts) {
130
- if (referenced.get(artifact.artifactSha256) !== artifact.runtime) {
131
- throw new Error(`Deployment runtime artifact ${artifact.artifactSha256} is not referenced by a named query.`);
132
- }
133
- }
134
- }
135
- function verifyRuntimeReferences(contract, artifacts) {
136
- requireClosedContractArtifactSet(contract);
137
- const declared = new Map(contract.artifacts.map(artifact => [artifact.artifactSha256, artifact.runtime]));
138
- if (declared.size !== artifacts.length) {
139
- throw new Error('Bundle runtime artifacts do not match the deployment contract.');
140
- }
141
- for (const artifact of artifacts) {
142
- if (declared.get(artifact.sha256) !== artifact.runtime) {
143
- throw new Error(`Bundle artifact ${artifact.sha256} does not match a deployment runtime reference.`);
144
- }
145
- }
146
- }
147
120
  export async function verifyDeploymentBundle(bundleDirectory) {
148
121
  const root = path.resolve(bundleDirectory);
149
122
  const rootStat = await lstat(root);
@@ -160,6 +133,9 @@ export async function verifyDeploymentBundle(bundleDirectory) {
160
133
  + (error instanceof Error ? error.message : String(error)));
161
134
  }
162
135
  const preparedManifest = prepareProtocolDeploymentBundleManifest(input);
136
+ if (preparedManifest.manifest.artifacts.length > 0) {
137
+ throw new Error('A deployment bundle cannot contain runtime artifacts.');
138
+ }
163
139
  const expectedManifestBytes = utf8Encoder.encode(`${preparedManifest.canonical}\n`);
164
140
  if (!Buffer.from(manifestBytes).equals(Buffer.from(expectedManifestBytes))) {
165
141
  throw new Error('Deployment bundle manifest must contain canonical JSON followed by one newline.');
@@ -177,13 +153,12 @@ export async function verifyDeploymentBundle(bundleDirectory) {
177
153
  + (error instanceof Error ? error.message : String(error)));
178
154
  }
179
155
  const preparedContract = prepareProtocolDeploymentContract(contractInput);
156
+ if (!Buffer.from(deploymentBytes).equals(Buffer.from(`${preparedContract.canonical}\n`))) {
157
+ throw new Error('Deployment JSON must contain canonical JSON followed by one newline.');
158
+ }
180
159
  if (preparedContract.identity !== deployment.identity) {
181
160
  throw new Error('Deployment identity does not match the bundle manifest.');
182
161
  }
183
- for (const artifact of preparedManifest.manifest.artifacts) {
184
- const bytes = await readBoundedRegularFile(root, artifact.path, DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS.maxArtifactBytes);
185
- verifyFile(bytes, artifact);
186
- }
187
162
  const source = preparedManifest.manifest.source;
188
163
  if (source) {
189
164
  for (const file of source.files) {
@@ -192,7 +167,6 @@ export async function verifyDeploymentBundle(bundleDirectory) {
192
167
  verifyFile(bytes, { ...file, path: bundlePath });
193
168
  }
194
169
  }
195
- verifyRuntimeReferences(preparedContract.contract, preparedManifest.manifest.artifacts);
196
170
  return Object.freeze({
197
171
  directory: root,
198
172
  manifest: preparedManifest.manifest,
@@ -10,7 +10,7 @@ export function resolveDeploymentControlPlaneLimits(input = {}) {
10
10
  continue;
11
11
  if (!Number.isSafeInteger(value) || value < 1
12
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`);
13
+ throw new RangeError(`${key} must be a positive safe integer no greater than the control-plane safety ceiling`);
14
14
  }
15
15
  limits[key] = value;
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"filesystem-store.d.ts","sourceRoot":"","sources":["../src/filesystem-store.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,YAAY,CAAC;AASpB,MAAM,MAAM,kCAAkC,GAC1C,mCAAmC,GACnC,wCAAwC,GACxC,mCAAmC,GACnC,wBAAwB,CAAC;AAE7B,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,EAAE,kCAAkC,CAAC;gBAGhD,IAAI,EAAE,kCAAkC,EACxC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAM7C;AAED,MAAM,WAAW,0CAA0C;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAC;IACpD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;CAC3C;AAED,MAAM,WAAW,mCAAmC,CAAC,SAAS,CAC5D,SAAQ,yBAAyB,CAAC,SAAS,CAAC;IAC5C,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC;CAChF;AAobD,wBAAgB,yCAAyC,CAAC,SAAS,GAAG,OAAO,EAC3E,OAAO,EAAE,0CAA0C,GAClD,mCAAmC,CAAC,SAAS,CAAC,CAkHhD"}
1
+ {"version":3,"file":"filesystem-store.d.ts","sourceRoot":"","sources":["../src/filesystem-store.ts"],"names":[],"mappings":"AAWA,OAAO,EAEL,KAAK,iCAAiC,EACvC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAGL,KAAK,wBAAwB,EAC9B,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,yBAAyB,EAE1B,MAAM,YAAY,CAAC;AAUpB,MAAM,MAAM,kCAAkC,GAC1C,mCAAmC,GACnC,wCAAwC,GACxC,mCAAmC,GACnC,wBAAwB,CAAC;AAE7B,qBAAa,8BAA+B,SAAQ,KAAK;IACvD,QAAQ,CAAC,IAAI,EAAE,kCAAkC,CAAC;gBAGhD,IAAI,EAAE,kCAAkC,EACxC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;QAAE,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAO;CAM7C;AAED,MAAM,WAAW,0CAA0C;IACzD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,iCAAiC,CAAC;IACpD,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,wBAAwB,CAAC;CAC3C;AAED,MAAM,WAAW,mCAAmC,CAAC,SAAS,CAC5D,SAAQ,yBAAyB,CAAC,SAAS,CAAC;IAC5C,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC;CAChF;AAkaD,wBAAgB,yCAAyC,CAAC,SAAS,GAAG,OAAO,EAC3E,OAAO,EAAE,0CAA0C,GAClD,mCAAmC,CAAC,SAAS,CAAC,CAkHhD"}
@@ -3,6 +3,7 @@ import { lstat, mkdir, mkdtemp, open, readdir, rename, rm, } from 'node:fs/promi
3
3
  import path from 'node:path';
4
4
  import { prepareProtocolDeploymentReleaseEnvelope, } from '@hypequery/protocol';
5
5
  import { DEPLOYMENT_BUNDLE_MANIFEST, verifyDeploymentBundle, } from './bundle.js';
6
+ import { readBoundedFile } from './utils/read-bounded-file.js';
6
7
  const RELEASE_FILE = 'release.json';
7
8
  const MAX_MANIFEST_BYTES = 1024 * 1024;
8
9
  const MAX_RELEASE_BYTES = 16 * 1024;
@@ -148,16 +149,17 @@ async function copyRegularFile(sourcePath, destinationPath, maximumBytes, expect
148
149
  }
149
150
  }
150
151
  function bundleFilePaths(bundle) {
152
+ const source = bundle.manifest.source;
151
153
  return Object.freeze([
152
154
  { path: DEPLOYMENT_BUNDLE_MANIFEST },
153
155
  {
154
156
  path: bundle.manifest.deployment.path,
155
157
  byteLength: bundle.manifest.deployment.byteLength,
156
158
  },
157
- ...bundle.manifest.artifacts.map(artifact => ({
158
- path: artifact.path,
159
- byteLength: artifact.byteLength,
160
- })),
159
+ ...(source?.files.map(file => ({
160
+ path: `${source.root}/${file.path}`,
161
+ byteLength: file.byteLength,
162
+ })) ?? []),
161
163
  ]);
162
164
  }
163
165
  async function syncBundleDirectories(bundleRoot, files) {
@@ -205,24 +207,7 @@ async function readRegularFile(filePath, maximumBytes) {
205
207
  if (!stat.isFile() || stat.size < 1 || stat.size > maximumBytes) {
206
208
  throw new Error(`Stored entry is not a bounded regular file: ${filePath}`);
207
209
  }
208
- const buffer = Buffer.allocUnsafe(Math.min(COPY_BUFFER_BYTES, maximumBytes + 1));
209
- const chunks = [];
210
- let total = 0;
211
- while (total <= maximumBytes) {
212
- const remaining = maximumBytes + 1 - total;
213
- const { bytesRead } = await handle.read(buffer, 0, Math.min(buffer.byteLength, remaining), null);
214
- if (bytesRead === 0)
215
- break;
216
- total += bytesRead;
217
- if (total > maximumBytes) {
218
- throw new Error(`Stored entry is not a bounded regular file: ${filePath}`);
219
- }
220
- chunks.push(Buffer.from(buffer.subarray(0, bytesRead)));
221
- }
222
- if (total < 1) {
223
- throw new Error(`Stored entry is not a bounded regular file: ${filePath}`);
224
- }
225
- return Buffer.concat(chunks, total);
210
+ return await readBoundedFile(handle, maximumBytes, 1, `Stored entry is not a bounded regular file: ${filePath}`);
226
211
  }
227
212
  finally {
228
213
  await handle.close();
package/dist/index.d.ts CHANGED
@@ -15,23 +15,11 @@ export { DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS, resolveDeploymentControlPlaneL
15
15
  export type { DeploymentControlPlaneLimits } from './control-plane-limits.js';
16
16
  export { DEFAULT_DEPLOYMENT_INTAKE_LIMITS, resolveDeploymentIntakeLimits, } from './limits.js';
17
17
  export type { DeploymentIntakeLimits } from './limits.js';
18
- export { createNodeWorkerDeploymentRuntimeFactory, NodeDeploymentRuntimeError, } from './node-runtime-factory.js';
19
- export type { NodeDeploymentRuntimeEnvironment, NodeDeploymentRuntimeEnvironmentResolver, 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, DeploymentRuntimeGeneration, DeploymentRuntimeInstance, DeploymentRuntimeInstanceInvocation, DeploymentRuntimeInvocation, DeploymentRuntimeReconcileResult, DeploymentRuntimeStatus, DeploymentRuntimeSupervisor, DeploymentRuntimeSupervisorErrorCode, DeploymentRuntimeSupervisorOptions, } from './runtime-supervisor.js';
24
18
  export type { DeploymentAuthenticationInput, DeploymentAuthenticator, DeploymentAuthorizationInput, DeploymentAuthorizer, DeploymentIntake, DeploymentIntakeOptions, DeploymentIntakeRequest, DeploymentIntakeResponse, DeploymentSubmissionResponse, DeploymentSubmissionStore, VerifiedDeploymentSubmission, } from './types.js';
25
- export { createDeploymentDataPlane, DeploymentDataPlaneError, } from './data-plane.js';
26
- export type { DeploymentCompiledSqlExecutionInput, DeploymentDataPlane, DeploymentDataPlaneAuthenticationInput, DeploymentDataPlaneErrorCode, DeploymentDataPlaneExecutionInput, DeploymentDataPlaneJsonRequest, DeploymentDataPlaneOptions, DeploymentDataPlanePrincipal, DeploymentDataPlaneRequest, DeploymentDataPlaneResult, DeploymentDataPlaneTenantInput, DeploymentRuntimeReferenceExecutionInput, DeploymentSemanticPlanExecutionInput, } from './data-plane.js';
27
- export { DEFAULT_DEPLOYMENT_DATA_PLANE_LIMITS, resolveDeploymentDataPlaneLimits, } from './data-plane-limits.js';
28
- export type { DeploymentDataPlaneLimits } from './data-plane-limits.js';
29
- export { createDeploymentRuntimeSupervisorExecutor } from './data-plane-runtime.js';
30
- export type { DeploymentRuntimeSupervisorExecutorOptions } from './data-plane-runtime.js';
31
- export { createDeploymentDataPlaneFetchHandler, createDeploymentDataPlaneNodeHandler, } from './data-plane-adapters.js';
32
- export type { DeploymentDataPlaneAdapterOptions, DeploymentDataPlaneAdapterRequest, DeploymentDataPlaneFetchHandler, DeploymentDataPlaneNodeHandler, } from './data-plane-adapters.js';
33
- export { createDeploymentHost, DeploymentHostError, } from './host.js';
34
- export { createFileSystemDeploymentHost } from './filesystem-host.js';
35
- export type { FileSystemDeploymentHost, FileSystemDeploymentHostOptions, } from './filesystem-host.js';
36
- export type { DeploymentHost, DeploymentHostDataPlaneConfiguration, DeploymentHostDataPlaneInput, DeploymentHostErrorCode, DeploymentHostOptions, } from './host.js';
19
+ export type { DeploymentDataPlanePrincipal } from './principal.js';
20
+ export { createDeploymentSemanticDataPlane, DeploymentSemanticInvocationError, toProtocolSemanticInvocationFailure, } from './semantic-data-plane.js';
21
+ export type { DeploymentSemanticAuthenticationInput, DeploymentSemanticBudget, DeploymentSemanticDataPlane, DeploymentSemanticDataPlaneOptions, DeploymentSemanticExecutionInput, DeploymentSemanticInvocationRequest, DeploymentSemanticTenantInput, } from './semantic-data-plane.js';
22
+ export { validateSemanticOperation } from './semantic-operation-validation.js';
23
+ export type { SemanticOperationLimits, SemanticOperationViolation, } from './semantic-operation-validation.js';
24
+ export { isDeploymentEndpointAuthorized, projectAuthorizedDeploymentContract, satisfiesDeploymentAccess, } from './authorized-contract.js';
37
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
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,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;AACpB,YAAY,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AAEnE,OAAO,EACL,iCAAiC,EACjC,iCAAiC,EACjC,mCAAmC,GACpC,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACV,qCAAqC,EACrC,wBAAwB,EACxB,2BAA2B,EAC3B,kCAAkC,EAClC,gCAAgC,EAChC,mCAAmC,EACnC,6BAA6B,GAC9B,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,yBAAyB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,YAAY,EACV,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,oCAAoC,CAAC;AAI5C,OAAO,EACL,8BAA8B,EAC9B,mCAAmC,EACnC,yBAAyB,GAC1B,MAAM,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -7,12 +7,8 @@ export { createDeploymentControlPlaneFetchHandler, createDeploymentControlPlaneN
7
7
  export { createDeploymentControlPlane, } from './control-plane.js';
8
8
  export { DEFAULT_DEPLOYMENT_CONTROL_PLANE_LIMITS, resolveDeploymentControlPlaneLimits, } from './control-plane-limits.js';
9
9
  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';
13
- export { createDeploymentDataPlane, DeploymentDataPlaneError, } from './data-plane.js';
14
- export { DEFAULT_DEPLOYMENT_DATA_PLANE_LIMITS, resolveDeploymentDataPlaneLimits, } from './data-plane-limits.js';
15
- export { createDeploymentRuntimeSupervisorExecutor } from './data-plane-runtime.js';
16
- export { createDeploymentDataPlaneFetchHandler, createDeploymentDataPlaneNodeHandler, } from './data-plane-adapters.js';
17
- export { createDeploymentHost, DeploymentHostError, } from './host.js';
18
- export { createFileSystemDeploymentHost } from './filesystem-host.js';
10
+ export { createDeploymentSemanticDataPlane, DeploymentSemanticInvocationError, toProtocolSemanticInvocationFailure, } from './semantic-data-plane.js';
11
+ export { validateSemanticOperation } from './semantic-operation-validation.js';
12
+ // What one principal may see of a contract, for a gateway listing targets
13
+ // before any call exists (decision 0002, CLOUD-03).
14
+ export { isDeploymentEndpointAuthorized, projectAuthorizedDeploymentContract, satisfiesDeploymentAccess, } from './authorized-contract.js';
@@ -1 +1 @@
1
- {"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../src/intake.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EAIxB,MAAM,YAAY,CAAC;AAuSpB,wBAAgB,sBAAsB,CAAC,SAAS,EAC9C,OAAO,EAAE,uBAAuB,CAAC,SAAS,CAAC,GAC1C,gBAAgB,CAiIlB"}
1
+ {"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../src/intake.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EACV,gBAAgB,EAChB,uBAAuB,EAIxB,MAAM,YAAY,CAAC;AAwSpB,wBAAgB,sBAAsB,CAAC,SAAS,EAC9C,OAAO,EAAE,uBAAuB,CAAC,SAAS,CAAC,GAC1C,gBAAgB,CAiIlB"}
package/dist/intake.js CHANGED
@@ -85,10 +85,10 @@ function decodeJson(bytes, description) {
85
85
  }
86
86
  }
87
87
  function requireReconstructablePaths(manifest) {
88
+ const source = manifest.manifest.source;
88
89
  const files = [
89
90
  manifest.manifest.deployment.path,
90
- ...manifest.manifest.artifacts.map(artifact => artifact.path),
91
- ...(manifest.manifest.source?.files.map(file => `${manifest.manifest.source.root}/${file.path}`) ?? []),
91
+ ...(source?.files.map(file => `${source.root}/${file.path}`) ?? []),
92
92
  ];
93
93
  const fileSet = new Set(files);
94
94
  if (fileSet.has(DEPLOYMENT_BUNDLE_MANIFEST)) {
@@ -149,6 +149,9 @@ async function readManifest(reader, maximum) {
149
149
  throw error;
150
150
  throw badRequest('The deployment bundle manifest is invalid.', error);
151
151
  }
152
+ if (prepared.manifest.artifacts.length > 0) {
153
+ throw badRequest('A deployment bundle cannot contain runtime artifacts.');
154
+ }
152
155
  const canonical = Buffer.from(`${prepared.canonical}\n`);
153
156
  if (!part.bytes.equals(canonical)) {
154
157
  throw badRequest('The deployment bundle manifest must use canonical JSON followed by one newline.');
@@ -282,12 +285,12 @@ export function createDeploymentIntake(options) {
282
285
  const bundleRoot = path.join(temporaryRoot, 'bundle');
283
286
  await mkdir(bundleRoot);
284
287
  await writeFile(path.join(bundleRoot, DEPLOYMENT_BUNDLE_MANIFEST), manifest.bytes, { flag: 'wx' });
288
+ const source = manifest.prepared.manifest.source;
285
289
  const files = [
286
290
  manifest.prepared.manifest.deployment,
287
- ...manifest.prepared.manifest.artifacts,
288
- ...(manifest.prepared.manifest.source?.files.map(file => ({
291
+ ...(source?.files.map(file => ({
289
292
  ...file,
290
- path: `${manifest.prepared.manifest.source.root}/${file.path}`,
293
+ path: `${source.root}/${file.path}`,
291
294
  })) ?? []),
292
295
  ];
293
296
  for (let index = 0; index < files.length; index += 1) {
@@ -1 +1 @@
1
- {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,eAAO,MAAM,gCAAgC,EAAE,QAAQ,CAAC,sBAAsB,CAK5E,CAAC;AAEH,wBAAgB,6BAA6B,CAC3C,KAAK,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC1C,QAAQ,CAAC,sBAAsB,CAAC,CAelC"}
1
+ {"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;CACrC;AAED,eAAO,MAAM,gCAAgC,EAAE,QAAQ,CAAC,sBAAsB,CAQ5E,CAAC;AAEH,wBAAgB,6BAA6B,CAC3C,KAAK,GAAE,OAAO,CAAC,sBAAsB,CAAM,GAC1C,QAAQ,CAAC,sBAAsB,CAAC,CAelC"}
package/dist/limits.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import { DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS } from '@hypequery/protocol';
2
2
  export const DEFAULT_DEPLOYMENT_INTAKE_LIMITS = Object.freeze({
3
- maxRequestBytes: DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS.maxTotalBytes + (2 * 1024 * 1024),
3
+ // Source and deployment bytes, plus the manifest and headers for up to 1,000 files.
4
+ maxRequestBytes: DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS.maxDeploymentBytes
5
+ + DEFAULT_PROTOCOL_DEPLOYMENT_BUNDLE_LIMITS.maxSourceBytes
6
+ + (10 * 1024 * 1024),
4
7
  maxReleaseBytes: 16 * 1024,
5
8
  maxManifestBytes: 1024 * 1024,
6
9
  maxPartHeaderBytes: 8 * 1024,
@@ -14,7 +17,7 @@ export function resolveDeploymentIntakeLimits(input = {}) {
14
17
  if (!Number.isSafeInteger(value) || value < 1
15
18
  || value > DEFAULT_DEPLOYMENT_INTAKE_LIMITS[key]) {
16
19
  throw new RangeError(`${key} must be a positive safe integer no greater than `
17
- + `${DEFAULT_DEPLOYMENT_INTAKE_LIMITS[key]} (the deployment intake v1 maximum)`);
20
+ + `${DEFAULT_DEPLOYMENT_INTAKE_LIMITS[key]} (the deployment intake safety ceiling)`);
18
21
  }
19
22
  result[key] = value;
20
23
  }