@volter/world-core 3.0.38 → 3.0.40
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/app-route.cjs +26 -25
- package/app-route.d.cts +1 -0
- package/dist/app-route.cjs +26 -25
- package/dist/app-route.d.cts +1 -0
- package/dist/generated/pack-facts.json +409 -352
- package/dist/inject.cjs +474 -95
- package/dist/network-policy.cjs +110 -13
- package/dist/network-policy.d.cts +8 -3
- package/dist/src/actions.js +2 -1
- package/dist/src/anthropic-wire.d.ts +2 -0
- package/dist/src/anthropic-wire.js +5 -0
- package/dist/src/attestation.d.ts +6 -0
- package/dist/src/attestation.js +27 -0
- package/dist/src/bytes.d.ts +3 -0
- package/dist/src/bytes.js +17 -0
- package/dist/src/changeset.js +2 -1
- package/dist/src/clickhouse/sql.js +73 -14
- package/dist/src/derived-core.d.ts +210 -32
- package/dist/src/derived-core.js +510 -244
- package/dist/src/derived-real.d.ts +1 -1
- package/dist/src/derived-real.js +704 -93
- package/dist/src/derived.d.ts +18 -2
- package/dist/src/derived.js +21 -2
- package/dist/src/events.d.ts +28 -45
- package/dist/src/events.js +40 -58
- package/dist/src/exact-json.d.ts +10 -0
- package/dist/src/exact-json.js +98 -0
- package/dist/src/executor.d.ts +17 -0
- package/dist/src/executor.js +91 -30
- package/dist/src/file-response.js +1 -1
- package/dist/src/form.d.ts +8 -0
- package/dist/src/form.js +76 -0
- package/dist/src/git/format.d.ts +16 -0
- package/dist/src/git/format.js +110 -0
- package/dist/src/git/index.d.ts +1 -0
- package/dist/src/git/index.js +1 -0
- package/dist/src/git/lfs.d.ts +1 -1
- package/dist/src/git/lfs.js +4 -3
- package/dist/src/graphql-wire.d.ts +6 -0
- package/dist/src/graphql-wire.js +6 -3
- package/dist/src/grpc-wire.js +2 -1
- package/dist/src/head.d.ts +1 -0
- package/dist/src/head.js +15 -4
- package/dist/src/held-reads.d.ts +6 -0
- package/dist/src/held-reads.js +60 -0
- package/dist/src/history.js +5 -4
- package/dist/src/host-port.d.ts +5 -0
- package/dist/src/host-port.js +14 -0
- package/dist/src/index.d.ts +11 -3
- package/dist/src/index.js +9 -4
- package/dist/src/log.js +12 -7
- package/dist/src/machines.d.ts +81 -5
- package/dist/src/machines.js +125 -9
- package/dist/src/managed-database.d.ts +15 -11
- package/dist/src/managed-database.js +38 -37
- package/dist/src/multipart.d.ts +21 -3
- package/dist/src/multipart.js +112 -38
- package/dist/src/observe.d.ts +3 -0
- package/dist/src/observe.js +6 -2
- package/dist/src/openai-wire.d.ts +16 -0
- package/dist/src/openai-wire.js +43 -12
- package/dist/src/pack-fetch.d.ts +4 -6
- package/dist/src/pack-fetch.js +189 -57
- package/dist/src/packRegistry.d.ts +7 -1
- package/dist/src/packRegistry.js +20 -3
- package/dist/src/private-transport.d.ts +1 -0
- package/dist/src/private-transport.js +11 -0
- package/dist/src/protobuf.js +10 -4
- package/dist/src/rateBudget.d.ts +8 -1
- package/dist/src/rateBudget.js +1 -0
- package/dist/src/redis/engine.d.ts +14 -5
- package/dist/src/redis/engine.js +271 -72
- package/dist/src/redis/frames.d.ts +17 -0
- package/dist/src/redis/frames.js +123 -0
- package/dist/src/redis/index.d.ts +6 -0
- package/dist/src/redis/index.js +6 -0
- package/dist/src/redis/json.d.ts +2 -0
- package/dist/src/redis/json.js +14 -0
- package/dist/src/redis/lua-libs.d.ts +4 -0
- package/dist/src/redis/lua-libs.js +173 -0
- package/dist/src/redis/lua.d.ts +1 -0
- package/dist/src/redis/lua.js +36 -0
- package/dist/src/redis/member-storage.d.ts +5 -0
- package/dist/src/redis/member-storage.js +75 -0
- package/dist/src/redis/resp2.d.ts +4 -0
- package/dist/src/redis/resp2.js +29 -0
- package/dist/src/redis/stream.d.ts +14 -0
- package/dist/src/redis/stream.js +335 -0
- package/dist/src/remote-execute.d.ts +2 -2
- package/dist/src/request-body.d.ts +11 -0
- package/dist/src/request-body.js +11 -0
- package/dist/src/runtime.d.ts +6 -5
- package/dist/src/runtime.js +5 -5
- package/dist/src/s3/wire.d.ts +4 -4
- package/dist/src/s3/wire.js +5 -3
- package/dist/src/scenario.d.ts +22 -0
- package/dist/src/scenario.js +35 -31
- package/dist/src/serve-http.d.ts +2 -1
- package/dist/src/serve-http.js +10 -1
- package/dist/src/serve.js +7 -4
- package/dist/src/signing.d.ts +23 -5
- package/dist/src/signing.js +74 -11
- package/dist/src/sigv4.d.ts +3 -1
- package/dist/src/sigv4.js +4 -2
- package/dist/src/smtp.js +2 -1
- package/dist/src/sockets.js +8 -3
- package/dist/src/state-system.d.ts +3 -0
- package/dist/src/storage.js +5 -2
- package/dist/src/twin-fetch.d.ts +3 -1
- package/dist/src/twin-fetch.js +3 -2
- package/dist/src/vendor-call.d.ts +10 -3
- package/dist/src/vendor-call.js +58 -14
- package/dist/test-fixtures/attestation.SOURCE.md +1 -0
- package/dist/test-fixtures/attestation.json +50 -0
- package/generated/pack-facts.json +409 -352
- package/inject.cjs +474 -95
- package/network-policy.cjs +110 -13
- package/network-policy.d.cts +8 -3
- package/package.json +11 -4
- package/src/actions.ts +2 -1
- package/src/anthropic-wire.ts +6 -0
- package/src/attestation.ts +23 -0
- package/src/bytes.ts +21 -0
- package/src/changeset.ts +2 -1
- package/src/clickhouse/sql.ts +50 -16
- package/src/derived-core.ts +573 -249
- package/src/derived-real.ts +552 -42
- package/src/derived.ts +23 -4
- package/src/events.ts +54 -85
- package/src/exact-json.ts +71 -0
- package/src/executor.ts +86 -27
- package/src/file-response.ts +1 -1
- package/src/form.ts +66 -0
- package/src/git/format.ts +89 -0
- package/src/git/index.ts +1 -0
- package/src/git/lfs.ts +5 -4
- package/src/graphql-wire.ts +8 -3
- package/src/grpc-wire.ts +2 -1
- package/src/head.ts +15 -5
- package/src/held-reads.ts +54 -0
- package/src/history.ts +5 -4
- package/src/host-port.ts +9 -0
- package/src/index.ts +10 -4
- package/src/log.ts +11 -7
- package/src/machines.ts +135 -13
- package/src/managed-database.ts +48 -40
- package/src/multipart.ts +110 -35
- package/src/observe.ts +6 -3
- package/src/openai-wire.ts +45 -14
- package/src/pack-fetch.ts +173 -50
- package/src/packRegistry.ts +27 -4
- package/src/private-transport.ts +8 -0
- package/src/protobuf.ts +8 -4
- package/src/rateBudget.ts +6 -1
- package/src/redis/engine.ts +168 -63
- package/src/redis/frames.ts +53 -0
- package/src/redis/index.ts +6 -0
- package/src/redis/json.ts +13 -0
- package/src/redis/lua-libs.ts +62 -0
- package/src/redis/lua.ts +20 -0
- package/src/redis/member-storage.ts +58 -0
- package/src/redis/resp2.ts +25 -0
- package/src/redis/stream.ts +102 -0
- package/src/remote-execute.ts +2 -2
- package/src/request-body.ts +12 -0
- package/src/runtime.ts +6 -5
- package/src/s3/wire.ts +8 -5
- package/src/scenario.ts +34 -13
- package/src/serve-http.ts +11 -2
- package/src/serve.ts +4 -3
- package/src/signing.ts +71 -17
- package/src/sigv4.ts +5 -3
- package/src/smtp.ts +3 -2
- package/src/sockets.ts +8 -3
- package/src/state-system.ts +3 -0
- package/src/storage.ts +5 -2
- package/src/twin-fetch.ts +4 -3
- package/src/vendor-call.ts +59 -12
- package/test-fixtures/attestation.json +50 -0
package/dist/network-policy.cjs
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const WORLD_NETWORK_POLICY_ENV = 'VOLTER_WORLD_NETWORK_POLICY';
|
|
4
|
+
/** Reads only: an `egress` grant admits these; any other method needs `writes`. */
|
|
5
|
+
const READ_METHODS = Object.freeze(['GET', 'HEAD', 'OPTIONS']);
|
|
6
|
+
/** The public build-artifact origins a build-phase World reads without listing them (architecture, "Reads are granted generously"). */
|
|
7
|
+
const PUBLIC_BUILD_READS = Object.freeze([
|
|
8
|
+
'https://binaries.prisma.sh', 'https://fonts.googleapis.com', 'https://fonts.gstatic.com',
|
|
9
|
+
'https://index.crates.io', 'https://registry.npmjs.org', 'https://static.crates.io',
|
|
10
|
+
]);
|
|
4
11
|
|
|
5
12
|
function object(value, keys, label) {
|
|
6
13
|
if (!value || typeof value !== 'object' || Array.isArray(value)
|
|
@@ -10,17 +17,37 @@ function object(value, keys, label) {
|
|
|
10
17
|
return value;
|
|
11
18
|
}
|
|
12
19
|
|
|
20
|
+
// Decode once, then resolve dot segments. Separators must have been literal on the wire.
|
|
21
|
+
function normalizedPath(path) {
|
|
22
|
+
if (/\\|%2f|%5c/i.test(path)) return null;
|
|
23
|
+
let decoded;
|
|
24
|
+
try { decoded = decodeURIComponent(path); } catch { return null; }
|
|
25
|
+
if (/[\\\x00-\x1f\x7f]/.test(decoded) || /%[0-9a-f]{2}/i.test(decoded)) return null;
|
|
26
|
+
const parts = [];
|
|
27
|
+
for (const segment of decoded.split('/')) {
|
|
28
|
+
if (segment === '.') continue;
|
|
29
|
+
if (segment === '..') { if (parts.length > 1) parts.pop(); }
|
|
30
|
+
else parts.push(segment);
|
|
31
|
+
}
|
|
32
|
+
let result = parts.join('/');
|
|
33
|
+
if (!result.startsWith('/')) result = '/' + result;
|
|
34
|
+
if ((decoded.endsWith('/.') || decoded.endsWith('/..')) && !result.endsWith('/')) result += '/';
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
|
|
13
38
|
function origins(value) {
|
|
14
|
-
if (!Array.isArray(value) || value.length > 256) throw new Error('World network egress must be an array of at most 256 exact HTTPS origins');
|
|
39
|
+
if (!Array.isArray(value) || value.length > 256) throw new Error('World network egress must be an array of at most 256 exact HTTPS origins, exact paths or trailing-slash subtrees');
|
|
15
40
|
const normalized = value.map(origin => {
|
|
16
41
|
if (typeof origin !== 'string' || origin.length > 2048) throw new Error('World network egress origins must be strings');
|
|
17
42
|
let url;
|
|
18
43
|
try { url = new URL(origin); } catch { throw new Error(`Invalid World network origin: ${origin}`); }
|
|
19
|
-
|
|
44
|
+
const canonical = url.pathname === '/' ? url.origin : url.origin + url.pathname;
|
|
45
|
+
if (url.protocol !== 'https:' || url.port === '0' || canonical !== origin || url.username || url.password || url.search || url.hash
|
|
46
|
+
|| /[\\*]/.test(origin) || normalizedPath(url.pathname) === null
|
|
20
47
|
|| !/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/.test(url.hostname)
|
|
21
48
|
|| url.hostname.split('.').some(label => !label || label.length > 63 || label.startsWith('-') || label.endsWith('-'))
|
|
22
49
|
|| /^[\d.]+$/.test(url.hostname) || url.hostname === 'localhost' || url.hostname.endsWith('.localhost')) {
|
|
23
|
-
throw new Error(`World network requires an exact canonical HTTPS origin: ${origin}`);
|
|
50
|
+
throw new Error(`World network requires an exact canonical HTTPS origin, path or subtree: ${origin}`);
|
|
24
51
|
}
|
|
25
52
|
return origin;
|
|
26
53
|
});
|
|
@@ -28,19 +55,32 @@ function origins(value) {
|
|
|
28
55
|
}
|
|
29
56
|
|
|
30
57
|
function normalizeWorldNetwork(value) {
|
|
31
|
-
const network = object(value, ['egress'], 'World network');
|
|
32
|
-
|
|
58
|
+
const network = object(value, ['egress', 'writes', 'phase', 'passthrough', 'publicReads'], 'World network');
|
|
59
|
+
const egress = origins(network.egress);
|
|
60
|
+
const writes = origins(network.writes ?? []);
|
|
61
|
+
const phase = network.phase ?? 'runtime';
|
|
62
|
+
if (phase !== 'build' && phase !== 'runtime') throw new Error('World network phase must be build or runtime');
|
|
63
|
+
if (network.publicReads !== undefined && typeof network.publicReads !== 'boolean') throw new Error('World network publicReads must be a boolean');
|
|
64
|
+
const publicReads = phase === 'build' && network.publicReads !== false;
|
|
65
|
+
const passthrough = origins(network.passthrough ?? []);
|
|
66
|
+
if (passthrough.length && phase !== 'build') throw new Error('World TLS passthrough requires phase: build');
|
|
67
|
+
for (const origin of passthrough) {
|
|
68
|
+
if (origin !== new URL(origin).origin || !egress.includes(origin)) throw new Error(`TLS passthrough requires an exact-origin egress grant: ${origin}`);
|
|
69
|
+
// an opaque tunnel cannot show its method, so it cannot carry a write
|
|
70
|
+
if (writes.some(grant => new URL(grant).origin === origin)) throw new Error(`TLS passthrough cannot carry a write grant: ${origin}`);
|
|
71
|
+
}
|
|
72
|
+
return Object.freeze({ egress, writes, phase, passthrough, publicReads });
|
|
33
73
|
}
|
|
34
74
|
|
|
35
75
|
function createWorldNetworkPolicy(world, network) {
|
|
36
76
|
if (typeof world !== 'string' || !world || world.length > 256) throw new Error('World network policy requires its World identity');
|
|
37
|
-
return Object.freeze({ version: 1, world,
|
|
77
|
+
return Object.freeze({ version: 1, world, ...normalizeWorldNetwork(network) });
|
|
38
78
|
}
|
|
39
79
|
|
|
40
80
|
function parseWorldNetworkPolicy(value) {
|
|
41
|
-
const policy = object(value, ['version', 'world', 'egress'], 'World network policy');
|
|
81
|
+
const policy = object(value, ['version', 'world', 'egress', 'writes', 'phase', 'passthrough', 'publicReads'], 'World network policy');
|
|
42
82
|
if (policy.version !== 1) throw new Error('Unsupported World network policy version');
|
|
43
|
-
return createWorldNetworkPolicy(policy.world, { egress: policy.egress });
|
|
83
|
+
return createWorldNetworkPolicy(policy.world, { egress: policy.egress, writes: policy.writes, phase: policy.phase, passthrough: policy.passthrough, publicReads: policy.publicReads });
|
|
44
84
|
}
|
|
45
85
|
|
|
46
86
|
function worldNetworkPolicyFromEnv(env) {
|
|
@@ -52,10 +92,67 @@ function worldNetworkPolicyFromEnv(env) {
|
|
|
52
92
|
return policy;
|
|
53
93
|
}
|
|
54
94
|
|
|
55
|
-
function
|
|
95
|
+
function destination(value, originOnly = false) {
|
|
96
|
+
if (/\\/.test(String(value).split(/[?#]/, 1)[0])) return null;
|
|
97
|
+
let url;
|
|
98
|
+
try { url = new URL(String(value)); } catch { return null; }
|
|
99
|
+
const path = normalizedPath(url.pathname);
|
|
100
|
+
return url.protocol === 'https:' && url.port !== '0' && !url.username && !url.password && (path !== null || originOnly) ? { url, path } : null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function containsGrant(broad, narrow) {
|
|
104
|
+
const a = destination(broad); const b = destination(narrow);
|
|
105
|
+
if (!a || !b || a.url.origin !== b.url.origin) return false;
|
|
106
|
+
if (broad === a.url.origin) return true;
|
|
107
|
+
if (narrow === b.url.origin) return false;
|
|
108
|
+
return a.path.endsWith('/') ? b.path.startsWith(a.path) : !b.path.endsWith('/') && b.path === a.path;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function granted(grants, to) {
|
|
112
|
+
return grants.some(grant => {
|
|
113
|
+
const allowed = destination(grant);
|
|
114
|
+
return allowed && to.url.origin === allowed.url.origin && (grant === allowed.url.origin
|
|
115
|
+
|| (to.path !== null && (allowed.path.endsWith('/') ? to.path.startsWith(allowed.path) : to.path === allowed.path)));
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/** Whether `method` to `value` is allowed: reads by `egress`, `writes` or the build phase's public reads; writes only by `writes`. */
|
|
120
|
+
function allowsWorldNetworkEgress(policy, value, method = 'GET') {
|
|
121
|
+
const to = destination(value, true);
|
|
122
|
+
if (!to) return false;
|
|
123
|
+
if (granted(policy.writes ?? [], to)) return true;
|
|
124
|
+
if (!READ_METHODS.includes(String(method).toUpperCase())) return false;
|
|
125
|
+
return granted(policy.egress, to) || (policy.phase === 'build' && policy.publicReads === true && PUBLIC_BUILD_READS.includes(to.url.origin));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function worldNetworkUsesPassthrough(policy, value) {
|
|
129
|
+
const to = destination(value, true);
|
|
130
|
+
if (!to || policy.phase !== 'build') return false;
|
|
131
|
+
// public build artifacts tunnel unopened: native clients (Turbopack's next/font on macOS) trust only the OS store
|
|
132
|
+
if (policy.publicReads === true && PUBLIC_BUILD_READS.includes(to.url.origin) && !granted(policy.writes ?? [], to)) return true;
|
|
133
|
+
return policy.passthrough?.includes(to.url.origin) === true && policy.egress.includes(to.url.origin);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** This authority must be mediated per request; CONNECT is only a path to the inspector. */
|
|
137
|
+
function worldNetworkNeedsPathInspection(policy, value) {
|
|
56
138
|
let url;
|
|
57
139
|
try { url = new URL(String(value)); } catch { return false; }
|
|
58
|
-
return url.protocol === 'https:' && !
|
|
140
|
+
return url.protocol === 'https:' && !worldNetworkUsesPassthrough(policy, url)
|
|
141
|
+
&& ([...policy.egress, ...(policy.writes ?? [])].some(grant => new URL(grant).origin === url.origin)
|
|
142
|
+
|| (policy.phase === 'build' && policy.publicReads === true && PUBLIC_BUILD_READS.includes(url.origin)));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Parent ceilings keep the narrower path and cannot create opaque transport permission. */
|
|
146
|
+
function intersectWorldNetwork(own, ceiling) {
|
|
147
|
+
const left = normalizeWorldNetwork(own); const right = normalizeWorldNetwork(ceiling);
|
|
148
|
+
const meet = (a, b) => [...new Set(a.flatMap(x => b.flatMap(y => containsGrant(y, x) ? [x] : containsGrant(x, y) ? [y] : [])))].sort();
|
|
149
|
+
const egress = meet(left.egress, right.egress);
|
|
150
|
+
const writes = meet(left.writes, right.writes);
|
|
151
|
+
const passthrough = left.phase === 'build' && right.phase === 'build'
|
|
152
|
+
? left.passthrough.filter(origin => right.passthrough.includes(origin) && egress.includes(origin)) : [];
|
|
153
|
+
// public reads are permission too: only a build ceiling that reads them passes them on
|
|
154
|
+
const publicReads = left.publicReads && right.publicReads;
|
|
155
|
+
return normalizeWorldNetwork({ egress, writes, phase: left.phase, passthrough, publicReads });
|
|
59
156
|
}
|
|
60
157
|
|
|
61
158
|
/** Loopback and private addresses stay inside the machine a World runs on: never refused. */
|
|
@@ -80,15 +177,15 @@ function isWorldInternalHost(hostname) {
|
|
|
80
177
|
* injector does not attach to. Internal addresses pass; strict egress refuses everything else; a
|
|
81
178
|
* published network policy refuses what it does not list. An unreadable policy refuses.
|
|
82
179
|
*/
|
|
83
|
-
function worldEgressRefusal(value, env = process.env) {
|
|
180
|
+
function worldEgressRefusal(value, env = process.env, method = 'GET') {
|
|
84
181
|
let url;
|
|
85
182
|
try { url = new URL(String(value)); } catch { return `unparseable destination ${String(value)}`; }
|
|
86
183
|
if (isWorldInternalHost(url.hostname)) return null;
|
|
87
184
|
if (env.VOLTER_TWIN_STRICT_EGRESS === '1' || env.VOLTER_TWIN_STRICT_EGRESS === 'true') return `sealed World refuses untwinned host ${url.hostname}`;
|
|
88
185
|
let policy;
|
|
89
186
|
try { policy = worldNetworkPolicyFromEnv(env); } catch (error) { return `World network policy unreadable (${error.message}); refusing ${url.hostname}`; }
|
|
90
|
-
if (policy !== undefined && !allowsWorldNetworkEgress(policy, url)) return `World network policy does not allow ${url.origin}`;
|
|
187
|
+
if (policy !== undefined && !allowsWorldNetworkEgress(policy, url, method)) return `World network policy does not allow ${String(method).toUpperCase()} ${url.origin}`;
|
|
91
188
|
return null;
|
|
92
189
|
}
|
|
93
190
|
|
|
94
|
-
module.exports = { isWorldInternalHost, worldEgressRefusal, WORLD_NETWORK_POLICY_ENV, normalizeWorldNetwork, createWorldNetworkPolicy, parseWorldNetworkPolicy, worldNetworkPolicyFromEnv, allowsWorldNetworkEgress };
|
|
191
|
+
module.exports = { PUBLIC_BUILD_READS, READ_METHODS, intersectWorldNetwork, worldNetworkNeedsPathInspection, worldNetworkUsesPassthrough, isWorldInternalHost, worldEgressRefusal, WORLD_NETWORK_POLICY_ENV, normalizeWorldNetwork, createWorldNetworkPolicy, parseWorldNetworkPolicy, worldNetworkPolicyFromEnv, allowsWorldNetworkEgress };
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
export interface WorldNetwork { readonly egress: readonly string[] }
|
|
1
|
+
export interface WorldNetwork { readonly egress: readonly string[]; readonly writes?: readonly string[]; readonly phase?: 'build' | 'runtime'; readonly passthrough?: readonly string[]; readonly publicReads?: boolean }
|
|
2
2
|
export interface WorldNetworkPolicy extends WorldNetwork { readonly version: 1; readonly world: string }
|
|
3
3
|
export const WORLD_NETWORK_POLICY_ENV: 'VOLTER_WORLD_NETWORK_POLICY';
|
|
4
4
|
export function normalizeWorldNetwork(value: unknown): WorldNetwork;
|
|
5
5
|
export function createWorldNetworkPolicy(world: string, network: WorldNetwork): WorldNetworkPolicy;
|
|
6
6
|
export function parseWorldNetworkPolicy(value: unknown): WorldNetworkPolicy;
|
|
7
7
|
export function worldNetworkPolicyFromEnv(env: Readonly<Record<string, string | undefined>>): WorldNetworkPolicy | undefined;
|
|
8
|
-
export
|
|
8
|
+
export const READ_METHODS: readonly string[];
|
|
9
|
+
export const PUBLIC_BUILD_READS: readonly string[];
|
|
10
|
+
export function allowsWorldNetworkEgress(policy: WorldNetworkPolicy, value: string | URL, method?: string): boolean;
|
|
9
11
|
export function isWorldInternalHost(hostname: string): boolean;
|
|
10
|
-
export function worldEgressRefusal(value: string | URL, env?: Readonly<Record<string, string | undefined
|
|
12
|
+
export function worldEgressRefusal(value: string | URL, env?: Readonly<Record<string, string | undefined>>, method?: string): string | null;
|
|
13
|
+
export function worldNetworkNeedsPathInspection(policy: WorldNetworkPolicy, value: string | URL): boolean;
|
|
14
|
+
export function worldNetworkUsesPassthrough(policy: WorldNetworkPolicy, value: string | URL): boolean;
|
|
15
|
+
export function intersectWorldNetwork(own: WorldNetwork, ceiling: WorldNetwork): WorldNetwork;
|
package/dist/src/actions.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseExactJson } from "./exact-json.js";
|
|
1
2
|
// Transaction/action log (scorecard R18) — the semantic correction that separates
|
|
2
3
|
// OBSERVED facts from LOCAL transaction commits.
|
|
3
4
|
//
|
|
@@ -297,7 +298,7 @@ export function listActions(service, root) {
|
|
|
297
298
|
return getActiveWorldStore()
|
|
298
299
|
.readLines(path)
|
|
299
300
|
.filter((line) => line.trim())
|
|
300
|
-
.map((line) =>
|
|
301
|
+
.map((line) => parseExactJson(line));
|
|
301
302
|
}
|
|
302
303
|
const META = new Set(['id', 'type', 'updatedAt']);
|
|
303
304
|
function projectedField(resource, field) {
|
|
@@ -36,4 +36,6 @@ export declare function messageSSE(m: Row, extra?: Row, options?: {
|
|
|
36
36
|
ping?: boolean;
|
|
37
37
|
completeToolInput?: boolean;
|
|
38
38
|
}): string;
|
|
39
|
+
/** An admitted Messages generation failure is an error SSE event, or the native JSON envelope. */
|
|
40
|
+
export declare function messageFailure(error: Row, stream: boolean, requestId?: string): Row | string;
|
|
39
41
|
export {};
|
|
@@ -134,3 +134,8 @@ export function messageSSE(m, extra = {}, options = {}) {
|
|
|
134
134
|
send('message_stop', { ...extra });
|
|
135
135
|
return events.join('');
|
|
136
136
|
}
|
|
137
|
+
/** An admitted Messages generation failure is an error SSE event, or the native JSON envelope. */
|
|
138
|
+
export function messageFailure(error, stream, requestId) {
|
|
139
|
+
const data = { type: 'error', error, ...(stream ? {} : { request_id: requestId ?? null }) };
|
|
140
|
+
return stream ? `event: error\ndata: ${JSON.stringify(data)}\n\n` : data;
|
|
141
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Verify simulated keyless attestations using the World's certificate and transparency roots.
|
|
2
|
+
* World certificate authorities do not run CT; signing time must still be authenticated by a log witness. */
|
|
3
|
+
export declare function verifyAttestationBundle(bundle: unknown, trust: {
|
|
4
|
+
certificates: readonly string[];
|
|
5
|
+
logKeys: readonly string[];
|
|
6
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Offline bundle verification against explicit World trust anchors. No network or persistent TUF state.
|
|
2
|
+
import { certificateOf, digest, publicKeyOf } from "./signing.js";
|
|
3
|
+
/** Verify simulated keyless attestations using the World's certificate and transparency roots.
|
|
4
|
+
* World certificate authorities do not run CT; signing time must still be authenticated by a log witness. */
|
|
5
|
+
export async function verifyAttestationBundle(bundle, trust) {
|
|
6
|
+
if (!trust.certificates.length || !trust.logKeys.length)
|
|
7
|
+
throw new Error('Attestation trust anchors are required');
|
|
8
|
+
// B1: protocol libraries are supplied by the pack and load only when the wire is used.
|
|
9
|
+
const [{ bundleFromJSON }, { TrustedRoot }, { toSignedEntity, toTrustMaterial, Verifier }] = await Promise.all([import('@sigstore/bundle'), import('@sigstore/protobuf-specs'), import('@sigstore/verify')]);
|
|
10
|
+
const root = TrustedRoot.fromJSON({ mediaType: 'application/vnd.dev.sigstore.trustedroot+json;version=0.1',
|
|
11
|
+
certificateAuthorities: trust.certificates.map((pem) => {
|
|
12
|
+
const cert = certificateOf(pem);
|
|
13
|
+
if (!cert)
|
|
14
|
+
throw new Error('Invalid attestation certificate root');
|
|
15
|
+
return { certChain: { certificates: [{ rawBytes: Buffer.from(cert.der).toString('base64') }] }, validFor: { start: cert.notBefore, end: cert.notAfter } };
|
|
16
|
+
}),
|
|
17
|
+
tlogs: trust.logKeys.map((pem) => {
|
|
18
|
+
const key = publicKeyOf(pem);
|
|
19
|
+
return {
|
|
20
|
+
hashAlgorithm: 'SHA2_256', logId: { keyId: Buffer.from(digest('sha256', key.der), 'hex').toString('base64') },
|
|
21
|
+
publicKey: { rawBytes: Buffer.from(key.der).toString('base64'), keyDetails: 'PUBLIC_KEY_DETAILS_UNSPECIFIED' },
|
|
22
|
+
};
|
|
23
|
+
}), ctlogs: [], timestampAuthorities: [],
|
|
24
|
+
});
|
|
25
|
+
const entity = toSignedEntity(bundleFromJSON(bundle));
|
|
26
|
+
new Verifier(toTrustMaterial(root), { tlogThreshold: 1, ctlogThreshold: 0 }).verify(entity);
|
|
27
|
+
}
|
package/dist/src/bytes.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/** The bytes of a gzip member (a SARIF upload, a tarball's contents, a gzipped request body). */
|
|
2
2
|
export declare function gunzip(bytes: Uint8Array): Promise<Uint8Array>;
|
|
3
|
+
/** Compressed HTTP REQUESTS only: async decoding stops at maxOutputLength during inflation.
|
|
4
|
+
* Return the decoder's own buffer; the request consumes it as a stream without copying it again. */
|
|
5
|
+
export declare function decompress(bytes: Uint8Array, coding: 'gzip' | 'deflate' | 'br' | 'zstd', limit?: number): Promise<Uint8Array>;
|
|
3
6
|
/** Bytes as a gzip member. */
|
|
4
7
|
export declare function gzip(bytes: Uint8Array): Promise<Uint8Array>;
|
|
5
8
|
/** Bytes as a zlib (deflate) member: git's object and pack framing. Reading one back is git/inflate.ts, which also
|
package/dist/src/bytes.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// `bun -e "typeof CompressionStream"` prints `undefined`), and a local World is served by Bun, so there the builtin is
|
|
5
5
|
// reached the way the kernel reaches every builtin: `process.getBuiltinModule`, at call time, never at import (the seam
|
|
6
6
|
// serve-http.ts's `nodeBuiltin` uses).
|
|
7
|
+
import { DEFAULT_MAX_DECODED_REQUEST_BODY_SIZE, RequestBodyTooLargeError } from "./request-body.js";
|
|
7
8
|
function zlib(what) {
|
|
8
9
|
const get = globalThis.process?.getBuiltinModule;
|
|
9
10
|
if (typeof get !== 'function')
|
|
@@ -20,6 +21,22 @@ export async function gunzip(bytes) {
|
|
|
20
21
|
return streamed(bytes, new DecompressionStream('gzip'));
|
|
21
22
|
return new Uint8Array(zlib('gunzip').gunzipSync(bytes));
|
|
22
23
|
}
|
|
24
|
+
/** Compressed HTTP REQUESTS only: async decoding stops at maxOutputLength during inflation.
|
|
25
|
+
* Return the decoder's own buffer; the request consumes it as a stream without copying it again. */
|
|
26
|
+
export async function decompress(bytes, coding, limit = DEFAULT_MAX_DECODED_REQUEST_BODY_SIZE) {
|
|
27
|
+
const builtin = zlib('decompress');
|
|
28
|
+
const decode = { gzip: builtin.gunzip, deflate: builtin.inflate, br: builtin.brotliDecompress, zstd: builtin.zstdDecompress }[coding];
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
decode(bytes, { maxOutputLength: limit }, (error, body) => {
|
|
31
|
+
if (error)
|
|
32
|
+
reject(error.code === 'ERR_BUFFER_TOO_LARGE' ? new RequestBodyTooLargeError() : error);
|
|
33
|
+
else if (body.byteLength > limit)
|
|
34
|
+
reject(new RequestBodyTooLargeError());
|
|
35
|
+
else
|
|
36
|
+
resolve(body);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
}
|
|
23
40
|
/** Bytes as a gzip member. */
|
|
24
41
|
export async function gzip(bytes) {
|
|
25
42
|
if (typeof CompressionStream === 'function')
|
package/dist/src/changeset.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseExactJson } from "./exact-json.js";
|
|
1
2
|
import { resolveReferences } from "./references.js";
|
|
2
3
|
import { withHistoryLocks } from "./ancestry.js";
|
|
3
4
|
import { captureParentHistory, historyChanges, historyEntries, historyPrefix, readHistoryView } from "./history.js";
|
|
@@ -268,7 +269,7 @@ export function parseVerifierExpression(expression, id) {
|
|
|
268
269
|
let value;
|
|
269
270
|
if (raw) {
|
|
270
271
|
try {
|
|
271
|
-
value =
|
|
272
|
+
value = parseExactJson(raw);
|
|
272
273
|
}
|
|
273
274
|
catch {
|
|
274
275
|
value = raw;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseExactJson } from "../exact-json.js";
|
|
1
2
|
// The kernel's ClickHouse® SQL engine — deterministic, over rows a pack supplies (Tinybird's Data Sources and pipe nodes,
|
|
2
3
|
// PostHog's events and persons).
|
|
3
4
|
//
|
|
@@ -1442,6 +1443,7 @@ function fnType(e, scope, seen, lambdaTypes) {
|
|
|
1442
1443
|
case 'decodeurlformcomponent':
|
|
1443
1444
|
case 'encodeurlcomponent':
|
|
1444
1445
|
case 'decodeurlcomponent':
|
|
1446
|
+
case 'extract':
|
|
1445
1447
|
case 'extracturlparameter':
|
|
1446
1448
|
case 'jsonextractstring':
|
|
1447
1449
|
case 'jsonextractraw':
|
|
@@ -1543,10 +1545,14 @@ function fnType(e, scope, seen, lambdaTypes) {
|
|
|
1543
1545
|
case 'tosecond':
|
|
1544
1546
|
case 'todayofweek': return 'UInt8';
|
|
1545
1547
|
case 'todatetime64':
|
|
1546
|
-
case 'todatetime64orzero':
|
|
1548
|
+
case 'todatetime64orzero':
|
|
1549
|
+
case 'parsedatetime64besteffort':
|
|
1550
|
+
case 'parsedatetime64besteffortornull':
|
|
1551
|
+
case 'parsedatetime64besteffortorzero': {
|
|
1547
1552
|
const scale = e.args[1]?.k === 'lit' ? Number(e.args[1].v) : 3;
|
|
1548
1553
|
const tz = e.args[2]?.k === 'lit' ? String(e.args[2].v) : undefined;
|
|
1549
|
-
|
|
1554
|
+
const type = tz ? `DateTime64(${scale}, '${tz}')` : `DateTime64(${scale})`;
|
|
1555
|
+
return name.endsWith('ornull') ? `Nullable(${type})` : type;
|
|
1550
1556
|
}
|
|
1551
1557
|
case 'todatetime':
|
|
1552
1558
|
case 'now':
|
|
@@ -1560,7 +1566,8 @@ function fnType(e, scope, seen, lambdaTypes) {
|
|
|
1560
1566
|
case 'parsedatetimebesteffortornull': {
|
|
1561
1567
|
const tzArg = name === 'now' ? a0 : e.args[1];
|
|
1562
1568
|
const tz = tzArg?.k === 'lit' ? String(tzArg.v) : undefined;
|
|
1563
|
-
|
|
1569
|
+
const type = tz ? `DateTime('${tz}')` : 'DateTime';
|
|
1570
|
+
return name.endsWith('ornull') ? `Nullable(${type})` : type;
|
|
1564
1571
|
}
|
|
1565
1572
|
case 'now64': return 'DateTime64(3)';
|
|
1566
1573
|
case 'todate':
|
|
@@ -2167,7 +2174,7 @@ function jsonPathValue(json, keys) {
|
|
|
2167
2174
|
let cur;
|
|
2168
2175
|
if (typeof json === 'string') {
|
|
2169
2176
|
try {
|
|
2170
|
-
cur =
|
|
2177
|
+
cur = parseExactJson(json, (digits) => BigInt(digits));
|
|
2171
2178
|
}
|
|
2172
2179
|
catch {
|
|
2173
2180
|
return undefined;
|
|
@@ -2518,6 +2525,23 @@ function evalFunction(e, env) {
|
|
|
2518
2525
|
const pad = fill.repeat(Math.ceil((n - s.length) / Math.max(1, fill.length))).slice(0, n - s.length);
|
|
2519
2526
|
return name === 'leftpad' ? pad + s : s + pad;
|
|
2520
2527
|
}
|
|
2528
|
+
// ClickHouse string-search-functions#extract: first capturing group, otherwise the whole first match.
|
|
2529
|
+
case 'extract': {
|
|
2530
|
+
argc(2);
|
|
2531
|
+
const haystack = A(0), pattern = A(1);
|
|
2532
|
+
if (haystack === null || pattern === null)
|
|
2533
|
+
return null;
|
|
2534
|
+
if (typeof haystack !== 'string' || typeof pattern !== 'string')
|
|
2535
|
+
return fail('Illegal type of argument of function extract: expected String');
|
|
2536
|
+
let match;
|
|
2537
|
+
try {
|
|
2538
|
+
match = new RegExp(valueToText(pattern)).exec(valueToText(haystack));
|
|
2539
|
+
}
|
|
2540
|
+
catch {
|
|
2541
|
+
return fail('Cannot compile re2: ' + valueToText(pattern));
|
|
2542
|
+
}
|
|
2543
|
+
return match ? (match.length > 1 ? match[1] ?? '' : match[0]) : '';
|
|
2544
|
+
}
|
|
2521
2545
|
case 'match': {
|
|
2522
2546
|
argc(2);
|
|
2523
2547
|
const s = A(0);
|
|
@@ -2667,15 +2691,17 @@ function evalFunction(e, env) {
|
|
|
2667
2691
|
if (j === null)
|
|
2668
2692
|
return null;
|
|
2669
2693
|
const keys = e.args.slice(1).map((_, i) => A(i + 1));
|
|
2670
|
-
const v = jsonPathValue(typeof j === 'string' ? j :
|
|
2694
|
+
const v = jsonPathValue(typeof j === 'string' ? j : stringifyJson(j), keys);
|
|
2671
2695
|
if (name === 'jsonhas')
|
|
2672
2696
|
return v === undefined ? 0 : 1;
|
|
2673
2697
|
if (name === 'jsonextractstring')
|
|
2674
2698
|
return typeof v === 'string' ? v : '';
|
|
2675
2699
|
if (name === 'jsonextractraw')
|
|
2676
|
-
return v === undefined ? '' :
|
|
2700
|
+
return v === undefined ? '' : stringifyJson(v);
|
|
2677
2701
|
if (name === 'jsonextractbool')
|
|
2678
2702
|
return v === true ? 1 : 0;
|
|
2703
|
+
if (typeof v === 'bigint')
|
|
2704
|
+
return name === 'jsonextractint' ? normInt(v) : Number(v);
|
|
2679
2705
|
if (typeof v === 'number')
|
|
2680
2706
|
return name === 'jsonextractint' ? Math.trunc(v) : v;
|
|
2681
2707
|
if (typeof v === 'boolean')
|
|
@@ -2739,7 +2765,7 @@ function evalFunction(e, env) {
|
|
|
2739
2765
|
case 'abs': {
|
|
2740
2766
|
argc(1);
|
|
2741
2767
|
const v = A(0);
|
|
2742
|
-
return v === null ? null : Math.abs(asNumber(v));
|
|
2768
|
+
return v === null ? null : typeof v === 'bigint' ? normInt(v < 0n ? -v : v) : Math.abs(asNumber(v));
|
|
2743
2769
|
}
|
|
2744
2770
|
case 'intdiv': {
|
|
2745
2771
|
argc(2);
|
|
@@ -2747,6 +2773,12 @@ function evalFunction(e, env) {
|
|
|
2747
2773
|
const b = A(1);
|
|
2748
2774
|
if (a === null || b === null)
|
|
2749
2775
|
return null;
|
|
2776
|
+
if (isExactInt(a) && isExactInt(b)) {
|
|
2777
|
+
const divisor = toBigInt(b);
|
|
2778
|
+
if (divisor === 0n)
|
|
2779
|
+
fail('Division by zero');
|
|
2780
|
+
return normInt(toBigInt(a) / divisor);
|
|
2781
|
+
}
|
|
2750
2782
|
if (asNumber(b) === 0)
|
|
2751
2783
|
fail('Division by zero');
|
|
2752
2784
|
return Math.trunc(asNumber(a) / asNumber(b));
|
|
@@ -2791,7 +2823,6 @@ function evalFunction(e, env) {
|
|
|
2791
2823
|
}
|
|
2792
2824
|
case 'todatetime':
|
|
2793
2825
|
case 'parsedatetimebesteffort':
|
|
2794
|
-
case 'parsedatetime64besteffort':
|
|
2795
2826
|
case 'parsedatetimebesteffortornull': {
|
|
2796
2827
|
argc(1, 2);
|
|
2797
2828
|
const v = A(0);
|
|
@@ -2806,7 +2837,30 @@ function evalFunction(e, env) {
|
|
|
2806
2837
|
return null;
|
|
2807
2838
|
}
|
|
2808
2839
|
}
|
|
2809
|
-
return castDateTime(v,
|
|
2840
|
+
return castDateTime(v, 0, tz);
|
|
2841
|
+
}
|
|
2842
|
+
// https://clickhouse.com/docs/en/sql-reference/functions/type-conversion-functions#parseDateTime64BestEffort
|
|
2843
|
+
case 'parsedatetime64besteffort':
|
|
2844
|
+
case 'parsedatetime64besteffortornull':
|
|
2845
|
+
case 'parsedatetime64besteffortorzero': {
|
|
2846
|
+
argc(1, 3);
|
|
2847
|
+
const v = A(0);
|
|
2848
|
+
if (v === null)
|
|
2849
|
+
return null;
|
|
2850
|
+
if (typeof v !== 'string')
|
|
2851
|
+
fail('Illegal type of argument of function ' + e.name + ': expected String');
|
|
2852
|
+
const scale = e.args.length > 1 ? asNumber(A(1)) : 3;
|
|
2853
|
+
const tz = e.args.length > 2 ? tzArg(e, 2, env) : undefined;
|
|
2854
|
+
try {
|
|
2855
|
+
return castDateTime(v, scale, tz);
|
|
2856
|
+
}
|
|
2857
|
+
catch (error) {
|
|
2858
|
+
if (name === 'parsedatetime64besteffortornull')
|
|
2859
|
+
return null;
|
|
2860
|
+
if (name === 'parsedatetime64besteffortorzero')
|
|
2861
|
+
return new DT(0, scale, tz);
|
|
2862
|
+
throw error;
|
|
2863
|
+
}
|
|
2810
2864
|
}
|
|
2811
2865
|
case 'todatetime64':
|
|
2812
2866
|
case 'todatetime64orzero': {
|
|
@@ -3214,7 +3268,7 @@ function evalFunction(e, env) {
|
|
|
3214
3268
|
const arr = A(0);
|
|
3215
3269
|
if (arr === null)
|
|
3216
3270
|
return null;
|
|
3217
|
-
return name === 'arraysum' ? arr
|
|
3271
|
+
return name === 'arraysum' ? sumArray(arr) : arr.filter((x) => truth(x) === true).length;
|
|
3218
3272
|
}
|
|
3219
3273
|
return fail(`${e.name}: first argument must be a lambda`);
|
|
3220
3274
|
}
|
|
@@ -3232,7 +3286,7 @@ function evalFunction(e, env) {
|
|
|
3232
3286
|
if (name === 'arrayall')
|
|
3233
3287
|
return results.every((r) => truth(r) === true) ? 1 : 0;
|
|
3234
3288
|
if (name === 'arraysum')
|
|
3235
|
-
return results
|
|
3289
|
+
return sumArray(results);
|
|
3236
3290
|
const i = results.findIndex((r) => truth(r) === true);
|
|
3237
3291
|
return i < 0 ? arrayAt(arrays[0], 0) : arrays[0][i];
|
|
3238
3292
|
}
|
|
@@ -3249,6 +3303,11 @@ function evalFunction(e, env) {
|
|
|
3249
3303
|
return fail(`Unknown function ${e.name}`);
|
|
3250
3304
|
}
|
|
3251
3305
|
}
|
|
3306
|
+
function sumArray(values) {
|
|
3307
|
+
const held = values.filter((value) => value !== null && value !== undefined);
|
|
3308
|
+
return held.every(isExactInt) ? normInt(held.reduce((sum, value) => sum + toBigInt(value), 0n))
|
|
3309
|
+
: held.reduce((sum, value) => sum + (asNumber(value) ?? 0), 0);
|
|
3310
|
+
}
|
|
3252
3311
|
function roundHalfEven(x) {
|
|
3253
3312
|
const r = Math.round(x);
|
|
3254
3313
|
return Math.abs(x % 1) === 0.5 && r % 2 !== 0 ? r - 1 : r;
|
|
@@ -3498,13 +3557,13 @@ const SCALAR_FUNCTIONS = new Set([
|
|
|
3498
3557
|
'arraypushback', 'arraypushfront', 'arrayreverse', 'arrayreversesort', 'arrayslice', 'arraysort', 'arraystringconcat', 'arraysum',
|
|
3499
3558
|
'assumenotnull', 'base64decode', 'base64encode', 'ceil', 'ceiling', 'char_length', 'coalesce', 'concat', 'cutquerystring', 'date_bin',
|
|
3500
3559
|
'date_diff', 'datediff', 'decodeurlcomponent', 'decodeurlformcomponent', 'divide', 'domain', 'domainwithoutwww', 'empty',
|
|
3501
|
-
'encodeurlcomponent', 'encodeurlformcomponent', 'endswith', 'equals', 'extracturlparameter', 'extracturlparameternames', 'floor', 'formatdatetime',
|
|
3560
|
+
'encodeurlcomponent', 'encodeurlformcomponent', 'endswith', 'equals', 'extract', 'extracturlparameter', 'extracturlparameternames', 'floor', 'formatdatetime',
|
|
3502
3561
|
'mapcontains', 'mapcontainskey', 'mapfilter', 'mapkeys', 'mapvalues',
|
|
3503
3562
|
'fromunixtimestamp', 'fromunixtimestamp64micro', 'fromunixtimestamp64milli', 'fromunixtimestamp64nano', 'greatest', 'has', 'hasall',
|
|
3504
3563
|
'hasany', 'hex', 'identity', 'if', 'ifnull', 'indexof', 'intdiv', 'isnotnull', 'isnull', 'jsonextractbool', 'jsonextractfloat',
|
|
3505
3564
|
'jsonextractint', 'jsonextractraw', 'jsonextractstring', 'jsonhas', 'lcase', 'least', 'leftpad', 'length', 'lengthutf8', 'locate',
|
|
3506
3565
|
'lower', 'lowerutf8', 'ltrim', 'match', 'materialize', 'mid', 'minus', 'modulo', 'multiif', 'multiply', 'notempty', 'notequals', 'now',
|
|
3507
|
-
'now64', 'nullif', 'parsedatetime64besteffort', 'parsedatetimebesteffort', 'parsedatetimebesteffortornull', 'path', 'plus',
|
|
3566
|
+
'now64', 'nullif', 'parsedatetime64besteffort', 'parsedatetime64besteffortornull', 'parsedatetime64besteffortorzero', 'parsedatetimebesteffort', 'parsedatetimebesteffortornull', 'path', 'plus',
|
|
3508
3567
|
'position', 'pow', 'power', 'range', 'replace', 'replaceall', 'replaceone', 'replaceregexpall', 'replaceregexpone', 'reverse',
|
|
3509
3568
|
'rightpad', 'round', 'rtrim', 'splitbychar', 'splitbystring', 'sqrt', 'startswith', 'substr', 'substring', 'subtractdays',
|
|
3510
3569
|
'subtracthours', 'subtractminutes', 'subtractmonths', 'subtractseconds', 'subtractweeks', 'subtractyears', 'time_bucket',
|
|
@@ -3521,7 +3580,7 @@ const INTERVAL_FUNCTIONS = new Set(['millisecond', 'second', 'minute', 'hour', '
|
|
|
3521
3580
|
const STRING_FUNCTIONS = new Set([
|
|
3522
3581
|
'tostring', 'concat', 'replace', 'replaceall', 'replaceone', 'replaceregexpall', 'replaceregexpone', 'lower', 'upper', 'lowerutf8',
|
|
3523
3582
|
'upperutf8', 'substring', 'substr', 'trim', 'trimboth', 'trimleft', 'trimright', 'encodeurlformcomponent', 'decodeurlformcomponent',
|
|
3524
|
-
'encodeurlcomponent', 'decodeurlcomponent', 'extracturlparameter', 'jsonextractstring', 'jsonextractraw', 'formatdatetime', 'domain',
|
|
3583
|
+
'encodeurlcomponent', 'decodeurlcomponent', 'extract', 'extracturlparameter', 'jsonextractstring', 'jsonextractraw', 'formatdatetime', 'domain',
|
|
3525
3584
|
'domainwithoutwww', 'path', 'cutquerystring', 'leftpad', 'rightpad', 'base64encode', 'base64decode', 'hex', 'totypename',
|
|
3526
3585
|
]);
|
|
3527
3586
|
export function isKnownFunction(name) {
|