@hypequery/protocol-conformance 0.10.4 → 0.11.1
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/dist/adapters/generators.d.ts +1 -0
- package/dist/adapters/generators.d.ts.map +1 -1
- package/dist/adapters/generators.js +163 -2
- package/dist/adapters/reference.d.ts +1 -1
- package/dist/adapters/reference.d.ts.map +1 -1
- package/dist/adapters/reference.js +26 -3
- package/fixtures/deployments-v1/README.md +2 -0
- package/fixtures/deployments-v1/identity.json +5 -0
- package/fixtures/deployments-v1/rejections.json +6 -0
- package/fixtures/deployments-v1/success.json +58 -0
- package/fixtures/expressions-v1/README.md +10 -3
- package/fixtures/expressions-v1/rejections.json +11 -2
- package/fixtures/expressions-v1/success.json +7 -1
- package/fixtures/manifest.json +17 -0
- package/fixtures/semantic-invocations-v1/README.md +10 -0
- package/fixtures/semantic-invocations-v1/rejections.json +29 -0
- package/fixtures/semantic-invocations-v1/success.json +102 -0
- package/package.json +2 -2
|
@@ -4,6 +4,7 @@ export declare function materializeIdentifier(spec: Spec): string;
|
|
|
4
4
|
export declare function materializeExpression(spec: Spec): unknown;
|
|
5
5
|
export declare function materializeSchema(spec: Spec): unknown;
|
|
6
6
|
export declare function materializeImplementation(spec: Spec): unknown;
|
|
7
|
+
export declare function materializeSemanticInvocation(spec: Spec): unknown;
|
|
7
8
|
export declare function materializeEvent(spec: Spec): unknown;
|
|
8
9
|
export declare function materializeDiagnostics(spec: Spec): unknown;
|
|
9
10
|
export declare function materializeDeployment(spec: Spec): unknown;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/adapters/generators.ts"],"names":[],"mappings":"AAIA,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAkBpC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuC1D;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAMxD;AAMD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../src/adapters/generators.ts"],"names":[],"mappings":"AAIA,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAkBpC,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuC1D;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAMxD;AAMD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAoCzD;AAID,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CA2BrD;AAgBD,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAuB7D;AA4CD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAsFjE;AAkBD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAyBpD;AAeD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAoB1D;AA2BD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAyFzD;AAkBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAmBrD;AAaD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAgBtD"}
|
|
@@ -83,10 +83,10 @@ export function materializeExpression(spec) {
|
|
|
83
83
|
return {
|
|
84
84
|
kind: 'logical',
|
|
85
85
|
operator: 'and',
|
|
86
|
-
operands: Array.from({ length: 10 }, () => ({
|
|
86
|
+
operands: Array.from({ length: 10 }, (_, groupIndex) => ({
|
|
87
87
|
kind: 'logical',
|
|
88
88
|
operator: 'and',
|
|
89
|
-
operands: Array.from({ length: 100 }, () => ({ ...EXPR_LITERAL })),
|
|
89
|
+
operands: Array.from({ length: groupIndex === 9 ? spec.lastGroupItems : 100 }, () => ({ ...EXPR_LITERAL })),
|
|
90
90
|
})),
|
|
91
91
|
};
|
|
92
92
|
case 'unsafe-accessor': {
|
|
@@ -162,6 +162,134 @@ export function materializeImplementation(spec) {
|
|
|
162
162
|
throw new Error(`Unknown implementation generator: ${String(spec.type)}`);
|
|
163
163
|
}
|
|
164
164
|
}
|
|
165
|
+
// --- semantic-invocations-v1 ---
|
|
166
|
+
const INVOCATION_REVISION = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
|
167
|
+
const INVOCATION_LIMITS = {
|
|
168
|
+
maxRows: 10_000,
|
|
169
|
+
maxColumnsPerRow: 256,
|
|
170
|
+
maxValueBytes: 65_536,
|
|
171
|
+
maxDeadlineMs: 3_600_000,
|
|
172
|
+
maxMessageBytes: 1_024,
|
|
173
|
+
};
|
|
174
|
+
function baseInvocation() {
|
|
175
|
+
return {
|
|
176
|
+
kind: 'hypequery-semantic-invocation',
|
|
177
|
+
version: 1,
|
|
178
|
+
target: { project: 'acme', environment: 'production' },
|
|
179
|
+
operation: { kind: 'dataset', dataset: 'orders', measures: ['revenue'] },
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function baseInvocationResult() {
|
|
183
|
+
return {
|
|
184
|
+
kind: 'hypequery-semantic-invocation-result',
|
|
185
|
+
version: 1,
|
|
186
|
+
activationRevision: INVOCATION_REVISION,
|
|
187
|
+
data: [{ status: 'paid' }],
|
|
188
|
+
meta: { rowCount: 1 },
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function baseInvocationFailure() {
|
|
192
|
+
return {
|
|
193
|
+
kind: 'hypequery-semantic-invocation-failure',
|
|
194
|
+
version: 1,
|
|
195
|
+
category: 'input-invalid',
|
|
196
|
+
code: 'HQ_SEMANTIC_UNKNOWN_DIMENSION',
|
|
197
|
+
message: 'The semantic query is invalid.',
|
|
198
|
+
retryable: false,
|
|
199
|
+
relist: false,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
export function materializeSemanticInvocation(spec) {
|
|
203
|
+
switch (spec.type) {
|
|
204
|
+
case 'wrong-root-type': return [];
|
|
205
|
+
case 'unknown-root-field': return { ...baseInvocation(), extra: true };
|
|
206
|
+
case 'unsupported-version': return { ...baseInvocation(), version: 2 };
|
|
207
|
+
// A caller can never name a tenant; the field does not exist in the record.
|
|
208
|
+
case 'caller-supplied-tenant': return { ...baseInvocation(), tenant: 'acme' };
|
|
209
|
+
// Identifiers are normalized into `operation`; a second copy could disagree.
|
|
210
|
+
case 'redundant-operation-dataset': return { ...baseInvocation(), dataset: 'orders' };
|
|
211
|
+
case 'malformed-activation-revision':
|
|
212
|
+
return { ...baseInvocation(), activationRevision: 'not-a-digest' };
|
|
213
|
+
case 'empty-budget': return { ...baseInvocation(), budget: {} };
|
|
214
|
+
case 'zero-deadline': return { ...baseInvocation(), budget: { deadlineMs: 0 } };
|
|
215
|
+
case 'deadline-too-large':
|
|
216
|
+
return { ...baseInvocation(), budget: { deadlineMs: INVOCATION_LIMITS.maxDeadlineMs + 1 } };
|
|
217
|
+
case 'correlation-id-control-character':
|
|
218
|
+
return { ...baseInvocation(), correlationId: 'req\u0007id' };
|
|
219
|
+
case 'unsafe-accessor': {
|
|
220
|
+
const unsafe = baseInvocation();
|
|
221
|
+
Object.defineProperty(unsafe, 'kind', {
|
|
222
|
+
enumerable: true,
|
|
223
|
+
get: () => 'hypequery-semantic-invocation',
|
|
224
|
+
});
|
|
225
|
+
return unsafe;
|
|
226
|
+
}
|
|
227
|
+
case 'too-many-rows': {
|
|
228
|
+
const rows = INVOCATION_LIMITS.maxRows + 1;
|
|
229
|
+
return {
|
|
230
|
+
...baseInvocationResult(),
|
|
231
|
+
data: Array.from({ length: rows }, () => ({ status: 'paid' })),
|
|
232
|
+
meta: { rowCount: rows },
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
case 'too-many-columns':
|
|
236
|
+
return {
|
|
237
|
+
...baseInvocationResult(),
|
|
238
|
+
data: [Object.fromEntries(Array.from({ length: INVOCATION_LIMITS.maxColumnsPerRow + 1 }, (_, i) => [`c${i}`, i]))],
|
|
239
|
+
};
|
|
240
|
+
case 'non-finite-cell':
|
|
241
|
+
return { ...baseInvocationResult(), data: [{ revenue: Number.POSITIVE_INFINITY }] };
|
|
242
|
+
case 'nested-cell':
|
|
243
|
+
return { ...baseInvocationResult(), data: [{ breakdown: { paid: 1 } }] };
|
|
244
|
+
case 'cell-too-large':
|
|
245
|
+
return {
|
|
246
|
+
...baseInvocationResult(),
|
|
247
|
+
data: [{ note: repeat('a', INVOCATION_LIMITS.maxValueBytes + 1) }],
|
|
248
|
+
};
|
|
249
|
+
case 'row-count-mismatch':
|
|
250
|
+
return { ...baseInvocationResult(), meta: { rowCount: 9 } };
|
|
251
|
+
case 'sparse-data-array': {
|
|
252
|
+
const data = [{ status: 'paid' }];
|
|
253
|
+
data.length = 3;
|
|
254
|
+
return { ...baseInvocationResult(), data, meta: { rowCount: 3 } };
|
|
255
|
+
}
|
|
256
|
+
case 'unknown-failure-category':
|
|
257
|
+
return { ...baseInvocationFailure(), category: 'exploded' };
|
|
258
|
+
case 'provider-shaped-failure-code':
|
|
259
|
+
return { ...baseInvocationFailure(), code: 'ClickHouseException: DB::Exception' };
|
|
260
|
+
case 'cell-control-character': {
|
|
261
|
+
return { ...baseInvocationResult(), data: [{ status: 'paid\u0007' }] };
|
|
262
|
+
}
|
|
263
|
+
case 'provider-shaped-failure-message': {
|
|
264
|
+
return { ...baseInvocationFailure(), message: 'SELECT * FROM private.orders WHERE tenant = acme' };
|
|
265
|
+
}
|
|
266
|
+
case 'custom-prototype-data-array': {
|
|
267
|
+
return { ...baseInvocationResult(), data: Object.setPrototypeOf([{ status: 'paid' }], {}) };
|
|
268
|
+
}
|
|
269
|
+
case 'accessor-data-array': {
|
|
270
|
+
const data = [{ status: 'paid' }];
|
|
271
|
+
Object.defineProperty(data, '0', { enumerable: true, get() { throw new Error('Getter must not execute'); } });
|
|
272
|
+
return { ...baseInvocationResult(), data };
|
|
273
|
+
}
|
|
274
|
+
case 'hidden-data-array-property': {
|
|
275
|
+
const data = [{ status: 'paid' }];
|
|
276
|
+
Object.defineProperty(data, 'hidden', { value: true });
|
|
277
|
+
return { ...baseInvocationResult(), data };
|
|
278
|
+
}
|
|
279
|
+
case 'symbol-data-array-property': {
|
|
280
|
+
const data = [{ status: 'paid' }];
|
|
281
|
+
Object.defineProperty(data, Symbol('hidden'), { value: true });
|
|
282
|
+
return { ...baseInvocationResult(), data };
|
|
283
|
+
}
|
|
284
|
+
case 'failure-message-too-large':
|
|
285
|
+
return {
|
|
286
|
+
...baseInvocationFailure(),
|
|
287
|
+
message: repeat('a', INVOCATION_LIMITS.maxMessageBytes + 1),
|
|
288
|
+
};
|
|
289
|
+
default:
|
|
290
|
+
throw new Error(`Unknown semantic invocation generator: ${String(spec.type)}`);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
165
293
|
// --- query-events-v1 ---
|
|
166
294
|
function baseEvent() {
|
|
167
295
|
return {
|
|
@@ -307,8 +435,41 @@ export function materializeDeployment(spec) {
|
|
|
307
435
|
});
|
|
308
436
|
return { ...value, queries: [namedQuery('first'), namedQuery('second')] };
|
|
309
437
|
}
|
|
438
|
+
case 'invalid-sensitivity':
|
|
439
|
+
return { ...value, datasets: [{ ...minimalDataset(), sensitivity: 'secret' }] };
|
|
440
|
+
case 'invalid-currency':
|
|
441
|
+
return { ...value, datasets: [{ ...minimalDataset(), currency: 'usd' }] };
|
|
442
|
+
case 'empty-defaults':
|
|
443
|
+
return { ...value, datasets: [{ ...minimalDataset(), defaults: {} }] };
|
|
444
|
+
case 'default-dimension-not-groupable':
|
|
445
|
+
return {
|
|
446
|
+
...value,
|
|
447
|
+
datasets: [{
|
|
448
|
+
...minimalDataset(),
|
|
449
|
+
dimensions: [{
|
|
450
|
+
name: 'status',
|
|
451
|
+
type: 'string',
|
|
452
|
+
source: { kind: 'column', column: 'status' },
|
|
453
|
+
filterable: true,
|
|
454
|
+
groupable: false,
|
|
455
|
+
}],
|
|
456
|
+
defaults: { dimensions: ['status'] },
|
|
457
|
+
}],
|
|
458
|
+
};
|
|
459
|
+
case 'default-grain-without-time-field':
|
|
460
|
+
// `timeGrain` has nothing to apply to unless the dataset declares
|
|
461
|
+
// `timeField`, so the reference reports it as a broken reference.
|
|
462
|
+
return { ...value, datasets: [{ ...minimalDataset(), defaults: { timeGrain: 'day' } }] };
|
|
310
463
|
case 'too-many-datasets':
|
|
311
464
|
return { ...value, datasets: Array.from({ length: 101 }, (_, i) => minimalDataset(`dataset_${i}`)) };
|
|
465
|
+
case 'too-many-synonyms':
|
|
466
|
+
return {
|
|
467
|
+
...value,
|
|
468
|
+
datasets: [{
|
|
469
|
+
...minimalDataset(),
|
|
470
|
+
synonyms: Array.from({ length: 101 }, (_, i) => `synonym_${i}`),
|
|
471
|
+
}],
|
|
472
|
+
};
|
|
312
473
|
case 'source-too-large':
|
|
313
474
|
return { ...value, datasets: [{ ...minimalDataset(), source: repeat('a', 1_025) }] };
|
|
314
475
|
case 'unsafe-accessor': {
|
|
@@ -9,7 +9,7 @@ export declare const REFERENCE_HOSTILE_OBJECT_SUITE: {
|
|
|
9
9
|
readonly count: 7;
|
|
10
10
|
readonly mechanisms: readonly ["getter", "toJSON", "proxy", "custom-prototype", "symbol-key", "sparse-array", "cycle"];
|
|
11
11
|
};
|
|
12
|
-
export declare const REFERENCE_FAMILIES: readonly ["cache-keys-v1", "tagged-values-v1", "identifiers-v1", "expressions-v1", "query-schemas-v1", "query-implementations-v1", "query-events-v1", "query-diagnostics-v1", "deployments-v1", "deployment-bundles-v1", "deployment-releases-v1"];
|
|
12
|
+
export declare const REFERENCE_FAMILIES: readonly ["cache-keys-v1", "tagged-values-v1", "identifiers-v1", "expressions-v1", "query-schemas-v1", "query-implementations-v1", "query-events-v1", "query-diagnostics-v1", "deployments-v1", "deployment-bundles-v1", "deployment-releases-v1", "semantic-invocations-v1"];
|
|
13
13
|
export declare function referenceHandle(family: string, role: FixtureRole, c: Case, section?: string): HandlerResult;
|
|
14
14
|
export {};
|
|
15
15
|
//# sourceMappingURL=reference.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/adapters/reference.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"reference.d.ts","sourceRoot":"","sources":["../../src/adapters/reference.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAe9D,KAAK,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA0BpC;;;;GAIG;AACH,eAAO,MAAM,8BAA8B;;;CAWjC,CAAC;AAEX,eAAO,MAAM,kBAAkB,+QAarB,CAAC;AAEX,wBAAgB,eAAe,CAC7B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,WAAW,EACjB,CAAC,EAAE,IAAI,EACP,OAAO,CAAC,EAAE,MAAM,GACf,aAAa,CAsCf"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// root export of @hypequery/protocol and returns a wire result. Every operation
|
|
3
3
|
// goes through the package's supported surface — this is exactly what a second
|
|
4
4
|
// implementation must reproduce.
|
|
5
|
-
import { decodeCanonicalValue, deriveProtocolCacheKey, deriveProtocolCacheNamespaceToken, encodeCanonicalValue, hashCanonicalValue, parseProtocolIdentifier, parseProtocolQualifiedIdentifier, prepareProtocolDeploymentBundleManifest, prepareProtocolDeploymentContract, prepareProtocolDeploymentReleaseEnvelope, splitProtocolQualifiedIdentifier, validateCanonicalValue, validateProtocolDeploymentBundleManifest, validateProtocolDeploymentContract, validateProtocolDeploymentReleaseEnvelope, validateProtocolExpression, validateProtocolQueryDiagnostics, validateProtocolQueryEvent, validateProtocolQueryImplementation, validateProtocolSchema, validateProtocolSemanticQuery, validateProtocolSqlExpression, } from '@hypequery/protocol';
|
|
6
|
-
import { materializeBundle, materializeDeployment, materializeDiagnostics, materializeEvent, materializeExpression, materializeIdentifier, materializeImplementation, materializeRelease, materializeSchema, materializeTaggedValue, } from './generators.js';
|
|
5
|
+
import { decodeCanonicalValue, deriveProtocolCacheKey, deriveProtocolCacheNamespaceToken, encodeCanonicalValue, hashCanonicalValue, parseProtocolIdentifier, parseProtocolQualifiedIdentifier, prepareProtocolDeploymentBundleManifest, prepareProtocolDeploymentContract, prepareProtocolDeploymentReleaseEnvelope, splitProtocolQualifiedIdentifier, validateCanonicalValue, validateProtocolDeploymentBundleManifest, validateProtocolDeploymentContract, validateProtocolDeploymentReleaseEnvelope, validateProtocolExpression, validateProtocolQueryDiagnostics, validateProtocolQueryEvent, validateProtocolQueryImplementation, validateProtocolSchema, validateProtocolSemanticInvocation, validateProtocolSemanticInvocationFailure, validateProtocolSemanticInvocationResult, validateProtocolSemanticQuery, validateProtocolSqlExpression, } from '@hypequery/protocol';
|
|
6
|
+
import { materializeBundle, materializeDeployment, materializeDiagnostics, materializeEvent, materializeSemanticInvocation, materializeExpression, materializeIdentifier, materializeImplementation, materializeRelease, materializeSchema, materializeTaggedValue, } from './generators.js';
|
|
7
7
|
const STABLE_CODE = /^HQ_[A-Z0-9_]+$/;
|
|
8
8
|
/** Turns a thrown protocol error into a wire rejection; rethrows anything else. */
|
|
9
9
|
function mapError(error) {
|
|
@@ -54,6 +54,7 @@ export const REFERENCE_FAMILIES = [
|
|
|
54
54
|
'deployments-v1',
|
|
55
55
|
'deployment-bundles-v1',
|
|
56
56
|
'deployment-releases-v1',
|
|
57
|
+
'semantic-invocations-v1',
|
|
57
58
|
];
|
|
58
59
|
export function referenceHandle(family, role, c, section) {
|
|
59
60
|
switch (family) {
|
|
@@ -86,12 +87,34 @@ export function referenceHandle(family, role, c, section) {
|
|
|
86
87
|
return handleBundle(role, c);
|
|
87
88
|
case 'deployment-releases-v1':
|
|
88
89
|
return handleRelease(role, c);
|
|
90
|
+
case 'semantic-invocations-v1':
|
|
91
|
+
return handleSemanticInvocation(c);
|
|
89
92
|
case 'cache-keys-v1':
|
|
90
93
|
return handleCacheKey(role, c);
|
|
91
94
|
default:
|
|
92
95
|
throw new Error(`reference adapter does not support family ${family}`);
|
|
93
96
|
}
|
|
94
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* One family covers the invocation, result, and failure records, so each case
|
|
100
|
+
* names which one it validates against.
|
|
101
|
+
*/
|
|
102
|
+
function handleSemanticInvocation(c) {
|
|
103
|
+
const validators = {
|
|
104
|
+
invocation: validateProtocolSemanticInvocation,
|
|
105
|
+
result: validateProtocolSemanticInvocationResult,
|
|
106
|
+
failure: validateProtocolSemanticInvocationFailure,
|
|
107
|
+
};
|
|
108
|
+
const record = c.record;
|
|
109
|
+
const validate = record === undefined ? undefined : validators[record];
|
|
110
|
+
if (!validate) {
|
|
111
|
+
throw new Error(`semantic invocation case is missing a known record: ${String(c.record)}`);
|
|
112
|
+
}
|
|
113
|
+
return attempt(() => {
|
|
114
|
+
validate(validationInput(c, materializeSemanticInvocation));
|
|
115
|
+
return ACCEPT;
|
|
116
|
+
});
|
|
117
|
+
}
|
|
95
118
|
function hexToBytes(hex) {
|
|
96
119
|
const out = new Uint8Array(hex.length / 2);
|
|
97
120
|
for (let index = 0; index < out.length; index += 1) {
|
|
@@ -167,7 +190,7 @@ function handleExpression(role, c, section) {
|
|
|
167
190
|
const validate = isQuery ? validateProtocolSemanticQuery : validateProtocolExpression;
|
|
168
191
|
if (role === 'success') {
|
|
169
192
|
return attempt(() => {
|
|
170
|
-
validate(c
|
|
193
|
+
validate(validationInput(c, materializeExpression));
|
|
171
194
|
return ACCEPT;
|
|
172
195
|
});
|
|
173
196
|
}
|
|
@@ -7,3 +7,5 @@ These fixtures exercise RFC 0006 deployment envelopes containing datasets, named
|
|
|
7
7
|
- `identity.json` pins canonical bytes and deployment identities.
|
|
8
8
|
|
|
9
9
|
Coverage includes closed fields, versions, identifiers, relationship queryability, missing runtime artifacts, ambiguous routes, collection limits, source limits, and unsafe accessors.
|
|
10
|
+
|
|
11
|
+
Semantic metadata (`examples`, `synonyms`, `format`, `unit`, `currency`, `timezone`, `sensitivity`) plus dataset `description`, `owner`, `freshness`, and `defaults` are covered by the `dataset-with-semantic-metadata` success case and by rejections for an unsupported sensitivity, a non-ISO currency, empty defaults, a default dimension that is not groupable, a default grain without a time field, and a synonym list above the 100-item semantic-metadata ceiling.
|
|
@@ -3,5 +3,10 @@
|
|
|
3
3
|
"id": "dataset-and-runtime-query",
|
|
4
4
|
"canonical": "{\"artifacts\":[{\"artifactSha256\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"runtime\":\"node\"}],\"datasets\":[{\"dimensions\":[{\"filterable\":true,\"groupable\":true,\"name\":\"status\",\"source\":{\"column\":\"status\",\"kind\":\"column\"},\"type\":\"string\"}],\"endpoint\":{\"access\":{\"kind\":\"authenticated\",\"roles\":[],\"scopes\":[\"read:orders\"]},\"maxLimit\":1000,\"path\":\"/api/analytics/datasets/orders/query\",\"tenant\":{\"column\":\"tenant_id\",\"kind\":\"required\",\"mode\":\"auto-inject\"}},\"filters\":[{\"field\":\"status\",\"name\":\"status\",\"operators\":[\"eq\",\"neq\"]}],\"limits\":{\"maxResultSize\":1000},\"measures\":[{\"aggregation\":\"sum\",\"field\":\"amount\",\"filters\":[],\"name\":\"revenue\"}],\"metrics\":[],\"name\":\"orders\",\"relationships\":[],\"source\":\"analytics.orders\",\"tenant\":{\"field\":\"tenant_id\",\"kind\":\"required\"},\"timeField\":\"created_at\"}],\"kind\":\"hypequery-deployment\",\"queries\":[{\"endpoint\":{\"access\":{\"kind\":\"public\"},\"method\":\"GET\",\"path\":\"/api/analytics/queries/health\",\"tenant\":{\"kind\":\"not-required\"}},\"implementation\":{\"artifactSha256\":\"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\",\"entrypoint\":\"queries.health\",\"kind\":\"runtime-reference\",\"runtime\":\"node\"},\"input\":{\"kind\":\"any\"},\"name\":\"health\",\"output\":{\"kind\":\"object\",\"properties\":{\"ok\":{\"kind\":\"boolean\"}},\"required\":[\"ok\"],\"unknownProperties\":\"strip\"},\"tags\":[\"system\"]}],\"version\":1}",
|
|
5
5
|
"sha256": "1ec521ddeb1bf29205a2c0e2876b24b0eab49c0002825bc569071fbf6ad23e2d"
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
"id": "dataset-with-semantic-metadata",
|
|
9
|
+
"canonical": "{\"artifacts\":[],\"datasets\":[{\"defaults\":{\"dimensions\":[\"status\"],\"timeGrain\":\"day\"},\"description\":\"Completed customer orders.\",\"dimensions\":[{\"examples\":[\"paid\",\"refunded\"],\"filterable\":true,\"groupable\":true,\"name\":\"status\",\"sensitivity\":\"public\",\"source\":{\"column\":\"status\",\"kind\":\"column\"},\"synonyms\":[\"state\"],\"type\":\"string\"}],\"filters\":[{\"examples\":[\"paid\"],\"field\":\"status\",\"name\":\"status\",\"operators\":[\"eq\",\"neq\"]}],\"freshness\":{\"maxAgeSeconds\":3600},\"measures\":[{\"aggregation\":\"sum\",\"currency\":\"USD\",\"field\":\"amount\",\"filters\":[],\"format\":\"0,0.00\",\"name\":\"revenue\",\"sensitivity\":\"confidential\",\"unit\":\"currency\"}],\"metrics\":[],\"name\":\"orders\",\"owner\":\"revenue-team\",\"relationships\":[],\"sensitivity\":\"internal\",\"source\":\"analytics.orders\",\"synonyms\":[\"purchases\",\"sales\"],\"tenant\":{\"field\":\"tenant_id\",\"kind\":\"required\"},\"timeField\":\"created_at\",\"timezone\":\"UTC\"}],\"kind\":\"hypequery-deployment\",\"queries\":[],\"version\":1}",
|
|
10
|
+
"sha256": "c5c349d90561634fa773753d0bccddfb8af60925f09bb0c9310af8fae3762ca9"
|
|
6
11
|
}
|
|
7
12
|
]
|
|
@@ -6,7 +6,13 @@
|
|
|
6
6
|
{ "id": "invalid-relationship-queryability", "generator": { "type": "invalid-relationship-queryability" }, "error": "HQ_DEPLOYMENT_INVALID_VALUE" },
|
|
7
7
|
{ "id": "missing-runtime-artifact", "generator": { "type": "missing-runtime-artifact" }, "error": "HQ_DEPLOYMENT_INVALID_REFERENCE" },
|
|
8
8
|
{ "id": "ambiguous-query-route", "generator": { "type": "ambiguous-query-route" }, "error": "HQ_DEPLOYMENT_INVALID_VALUE" },
|
|
9
|
+
{ "id": "invalid-sensitivity", "generator": { "type": "invalid-sensitivity" }, "error": "HQ_DEPLOYMENT_INVALID_VALUE" },
|
|
10
|
+
{ "id": "invalid-currency", "generator": { "type": "invalid-currency" }, "error": "HQ_DEPLOYMENT_INVALID_VALUE" },
|
|
11
|
+
{ "id": "empty-defaults", "generator": { "type": "empty-defaults" }, "error": "HQ_DEPLOYMENT_INVALID_VALUE" },
|
|
12
|
+
{ "id": "default-dimension-not-groupable", "generator": { "type": "default-dimension-not-groupable" }, "error": "HQ_DEPLOYMENT_INVALID_REFERENCE" },
|
|
13
|
+
{ "id": "default-grain-without-time-field", "generator": { "type": "default-grain-without-time-field" }, "error": "HQ_DEPLOYMENT_INVALID_REFERENCE" },
|
|
9
14
|
{ "id": "too-many-datasets", "generator": { "type": "too-many-datasets" }, "error": "HQ_DEPLOYMENT_TOO_MANY_ITEMS" },
|
|
15
|
+
{ "id": "too-many-synonyms", "generator": { "type": "too-many-synonyms" }, "error": "HQ_DEPLOYMENT_TOO_MANY_ITEMS" },
|
|
10
16
|
{ "id": "source-too-large", "generator": { "type": "source-too-large" }, "error": "HQ_DEPLOYMENT_TOO_LARGE" },
|
|
11
17
|
{ "id": "unsafe-accessor", "generator": { "type": "unsafe-accessor" }, "error": "HQ_DEPLOYMENT_UNSAFE_OBJECT" }
|
|
12
18
|
]
|
|
@@ -77,5 +77,63 @@
|
|
|
77
77
|
}
|
|
78
78
|
]
|
|
79
79
|
}
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": "dataset-with-semantic-metadata",
|
|
83
|
+
"value": {
|
|
84
|
+
"kind": "hypequery-deployment",
|
|
85
|
+
"version": 1,
|
|
86
|
+
"datasets": [
|
|
87
|
+
{
|
|
88
|
+
"name": "orders",
|
|
89
|
+
"description": "Completed customer orders.",
|
|
90
|
+
"source": "analytics.orders",
|
|
91
|
+
"owner": "revenue-team",
|
|
92
|
+
"freshness": { "maxAgeSeconds": 3600 },
|
|
93
|
+
"defaults": { "dimensions": ["status"], "timeGrain": "day" },
|
|
94
|
+
"synonyms": ["purchases", "sales"],
|
|
95
|
+
"timezone": "UTC",
|
|
96
|
+
"sensitivity": "internal",
|
|
97
|
+
"tenant": { "kind": "required", "field": "tenant_id" },
|
|
98
|
+
"timeField": "created_at",
|
|
99
|
+
"dimensions": [
|
|
100
|
+
{
|
|
101
|
+
"name": "status",
|
|
102
|
+
"type": "string",
|
|
103
|
+
"source": { "kind": "column", "column": "status" },
|
|
104
|
+
"filterable": true,
|
|
105
|
+
"groupable": true,
|
|
106
|
+
"examples": ["paid", "refunded"],
|
|
107
|
+
"synonyms": ["state"],
|
|
108
|
+
"sensitivity": "public"
|
|
109
|
+
}
|
|
110
|
+
],
|
|
111
|
+
"measures": [
|
|
112
|
+
{
|
|
113
|
+
"name": "revenue",
|
|
114
|
+
"aggregation": "sum",
|
|
115
|
+
"field": "amount",
|
|
116
|
+
"filters": [],
|
|
117
|
+
"format": "0,0.00",
|
|
118
|
+
"unit": "currency",
|
|
119
|
+
"currency": "USD",
|
|
120
|
+
"sensitivity": "confidential"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"filters": [
|
|
124
|
+
{
|
|
125
|
+
"name": "status",
|
|
126
|
+
"field": "status",
|
|
127
|
+
"operators": ["eq", "neq"],
|
|
128
|
+
"examples": ["paid"]
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
"metrics": [],
|
|
132
|
+
"relationships": []
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"queries": [],
|
|
136
|
+
"artifacts": []
|
|
137
|
+
}
|
|
80
138
|
}
|
|
81
139
|
]
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# Portable expression v1 fixtures
|
|
2
2
|
|
|
3
|
-
This family accompanies RFC 0003 and covers the closed semantic expression registry plus metric and dataset query envelopes.
|
|
3
|
+
This family accompanies accepted RFC 0003 and covers the closed semantic expression registry plus metric and dataset query envelopes.
|
|
4
4
|
|
|
5
|
-
`success.json` exercises accepted expressions and queries. `rejections.json` pins every stable failure code, including generated depth, width, node-count, and unsafe-accessor cases.
|
|
5
|
+
`success.json` exercises accepted expressions and queries. `rejections.json` pins every stable failure code, including generated depth, width, node-count, and unsafe-accessor cases. Together they pin the exact protocol boundaries: depth 16/17, 1,000/1,001 nodes, and 100/101 collection items.
|
|
6
6
|
|
|
7
|
-
Each rejection selects the `expression` or `query` validation surface
|
|
7
|
+
Each case contains exactly one literal `value` or deterministic `generator`. Each rejection also selects the `expression` or `query` validation surface.
|
|
8
|
+
|
|
9
|
+
Generators have these language-neutral meanings:
|
|
10
|
+
|
|
11
|
+
- `nested-not` wraps the literal expression `{ "kind": "literal", "value": false }` in exactly `depth` logical `not` nodes.
|
|
12
|
+
- `logical-operands` creates one logical `and` node containing `count` distinct copies of that literal expression.
|
|
13
|
+
- `logical-tree` creates a logical `and` root with ten logical `and` groups. The first nine groups contain 100 distinct literal expressions and the tenth contains `lastGroupItems`. The resulting expression has exactly `911 + lastGroupItems` nodes.
|
|
14
|
+
- `unsafe-accessor` is host-model conditional under RFC 0012 and exposes a reference's `name` through an accessor rather than a data property.
|
|
@@ -9,9 +9,18 @@
|
|
|
9
9
|
{ "id": "comparison-empty-in-list", "mode": "expression", "value": { "kind": "comparison", "operator": "in", "left": { "kind": "reference", "name": "status" }, "right": { "kind": "literal", "value": { "$hypequery": { "type": "array", "version": 1, "values": [] } } } }, "error": "HQ_EXPRESSION_INVALID_ARITY" },
|
|
10
10
|
{ "id": "comparison-like-non-string", "mode": "expression", "value": { "kind": "comparison", "operator": "like", "left": { "kind": "reference", "name": "status" }, "right": { "kind": "literal", "value": 1.5 } }, "error": "HQ_EXPRESSION_INVALID_VALUE" },
|
|
11
11
|
{ "id": "expression-invalid-aggregation", "mode": "expression", "value": { "kind": "aggregate", "aggregation": "percentile", "field": "amount", "level": 2.0 }, "error": "HQ_EXPRESSION_INVALID_AGGREGATION" },
|
|
12
|
+
{ "id": "aggregate-arg-with-filters", "mode": "expression", "value": { "kind": "aggregate", "aggregation": "argMax", "field": "status", "argField": "created_at", "filters": [] }, "error": "HQ_EXPRESSION_INVALID_AGGREGATION" },
|
|
13
|
+
{ "id": "aggregate-non-arg-with-arg-field", "mode": "expression", "value": { "kind": "aggregate", "aggregation": "sum", "field": "amount", "argField": "created_at" }, "error": "HQ_EXPRESSION_INVALID_AGGREGATION" },
|
|
14
|
+
{ "id": "aggregate-percentile-missing-level", "mode": "expression", "value": { "kind": "aggregate", "aggregation": "percentile", "field": "amount" }, "error": "HQ_EXPRESSION_INVALID_AGGREGATION" },
|
|
15
|
+
{ "id": "aggregate-filter-not-predicate", "mode": "expression", "value": { "kind": "aggregate", "aggregation": "sum", "field": "amount", "filters": [{ "kind": "literal", "value": true }] }, "error": "HQ_EXPRESSION_INVALID_AGGREGATION" },
|
|
12
16
|
{ "id": "query-invalid-grain", "mode": "query", "value": { "kind": "dataset", "dataset": "orders", "by": "hour" }, "error": "HQ_EXPRESSION_INVALID_QUERY" },
|
|
13
|
-
{ "id": "
|
|
14
|
-
{ "id": "
|
|
17
|
+
{ "id": "query-filter-not-predicate", "mode": "query", "value": { "kind": "dataset", "dataset": "orders", "filters": [{ "kind": "literal", "value": true }] }, "error": "HQ_EXPRESSION_INVALID_QUERY" },
|
|
18
|
+
{ "id": "metric-query-measures-unknown", "mode": "query", "value": { "kind": "metric", "dataset": "orders", "metric": "revenue", "measures": [] }, "error": "HQ_EXPRESSION_UNKNOWN_FIELD" },
|
|
19
|
+
{ "id": "query-limit-unsafe-integer", "mode": "query", "value": { "kind": "dataset", "dataset": "orders", "limit": 9007199254740992 }, "error": "HQ_EXPRESSION_INVALID_QUERY" },
|
|
20
|
+
{ "id": "query-offset-negative", "mode": "query", "value": { "kind": "dataset", "dataset": "orders", "offset": -1 }, "error": "HQ_EXPRESSION_INVALID_QUERY" },
|
|
21
|
+
{ "id": "query-order-direction-invalid", "mode": "query", "value": { "kind": "dataset", "dataset": "orders", "orderBy": [{ "field": "revenue", "direction": "ascending" }] }, "error": "HQ_EXPRESSION_INVALID_QUERY" },
|
|
22
|
+
{ "id": "expression-too-deep", "mode": "expression", "generator": { "type": "nested-not", "depth": 16 }, "error": "HQ_EXPRESSION_TOO_DEEP" },
|
|
23
|
+
{ "id": "expression-too-many-nodes", "mode": "expression", "generator": { "type": "logical-tree", "lastGroupItems": 90 }, "error": "HQ_EXPRESSION_TOO_MANY_NODES" },
|
|
15
24
|
{ "id": "expression-too-many-items", "mode": "expression", "generator": { "type": "logical-operands", "count": 101 }, "error": "HQ_EXPRESSION_TOO_MANY_ITEMS" },
|
|
16
25
|
{ "id": "expression-unsafe-accessor", "mode": "expression", "generator": { "type": "unsafe-accessor" }, "error": "HQ_EXPRESSION_UNSAFE_OBJECT" }
|
|
17
26
|
]
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
{ "id": "binary-divide", "value": { "kind": "binary", "operator": "divide", "left": { "kind": "reference", "name": "revenue" }, "right": { "kind": "literal", "value": 1.5 } } },
|
|
9
9
|
{ "id": "call-nullIfZero", "value": { "kind": "call", "function": "nullIfZero", "args": [{ "kind": "reference", "name": "orders" }] } },
|
|
10
10
|
{ "id": "call-coalesce", "value": { "kind": "call", "function": "coalesce", "args": [{ "kind": "reference", "name": "revenue" }, { "kind": "literal", "value": 0.5 }] } },
|
|
11
|
+
{ "id": "call-round-one-argument", "value": { "kind": "call", "function": "round", "args": [{ "kind": "reference", "name": "revenue" }] } },
|
|
11
12
|
{ "id": "call-round", "value": { "kind": "call", "function": "round", "args": [{ "kind": "reference", "name": "revenue" }, { "kind": "literal", "value": 2.0 }] } },
|
|
12
13
|
{ "id": "call-floor", "value": { "kind": "call", "function": "floor", "args": [{ "kind": "reference", "name": "revenue" }] } },
|
|
13
14
|
{ "id": "call-ceil", "value": { "kind": "call", "function": "ceil", "args": [{ "kind": "reference", "name": "revenue" }] } },
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
{ "id": "logical-or", "value": { "kind": "logical", "operator": "or", "operands": [{ "kind": "literal", "value": true }, { "kind": "literal", "value": false }] } },
|
|
26
27
|
{ "id": "logical-not", "value": { "kind": "logical", "operator": "not", "operand": { "kind": "literal", "value": false } } },
|
|
27
28
|
{ "id": "aggregate-sum-filtered", "value": { "kind": "aggregate", "aggregation": "sum", "field": "amount", "filters": [{ "kind": "comparison", "operator": "eq", "left": { "kind": "reference", "name": "status" }, "right": { "kind": "literal", "value": "paid" } }] } },
|
|
29
|
+
{ "id": "aggregate-sum-empty-filters", "value": { "kind": "aggregate", "aggregation": "sum", "field": "amount", "filters": [] } },
|
|
28
30
|
{ "id": "aggregate-count", "value": { "kind": "aggregate", "aggregation": "count", "field": "id" } },
|
|
29
31
|
{ "id": "aggregate-countDistinct", "value": { "kind": "aggregate", "aggregation": "countDistinct", "field": "customer_id" } },
|
|
30
32
|
{ "id": "aggregate-avg", "value": { "kind": "aggregate", "aggregation": "avg", "field": "amount" } },
|
|
@@ -35,11 +37,15 @@
|
|
|
35
37
|
{ "id": "aggregate-percentile", "value": { "kind": "aggregate", "aggregation": "percentile", "field": "amount", "level": 0.95 } },
|
|
36
38
|
{ "id": "aggregate-median-normalized", "value": { "kind": "aggregate", "aggregation": "percentile", "field": "amount", "level": 0.5 } },
|
|
37
39
|
{ "id": "aggregate-stddev", "value": { "kind": "aggregate", "aggregation": "stddev", "field": "amount" } },
|
|
38
|
-
{ "id": "aggregate-variance", "value": { "kind": "aggregate", "aggregation": "variance", "field": "amount" } }
|
|
40
|
+
{ "id": "aggregate-variance", "value": { "kind": "aggregate", "aggregation": "variance", "field": "amount" } },
|
|
41
|
+
{ "id": "limit-depth-16", "generator": { "type": "nested-not", "depth": 15 } },
|
|
42
|
+
{ "id": "limit-nodes-1000", "generator": { "type": "logical-tree", "lastGroupItems": 89 } },
|
|
43
|
+
{ "id": "limit-items-100", "generator": { "type": "logical-operands", "count": 100 } }
|
|
39
44
|
],
|
|
40
45
|
"queries": [
|
|
41
46
|
{ "id": "dataset-all-query-features", "value": { "kind": "dataset", "dataset": "orders", "dimensions": ["status", "customer.country"], "measures": ["revenue", "orders"], "filters": [{ "kind": "comparison", "operator": "eq", "left": { "kind": "reference", "name": "status" }, "right": { "kind": "literal", "value": "paid" } }], "orderBy": [{ "field": "customer.country", "direction": "asc" }, { "field": "revenue", "direction": "desc" }], "limit": 100, "offset": 0, "by": "quarter", "includeMeta": true } },
|
|
42
47
|
{ "id": "metric-all-query-features", "value": { "kind": "metric", "dataset": "orders", "metric": "average_order_value", "dimensions": ["customer.country"], "filters": [], "orderBy": [{ "field": "period", "direction": "asc" }], "limit": 25, "offset": 50, "by": "week", "includeMeta": false } },
|
|
48
|
+
{ "id": "query-safe-integer-maximum", "value": { "kind": "dataset", "dataset": "orders", "limit": 9007199254740991, "offset": 9007199254740991 } },
|
|
43
49
|
{ "id": "grain-day", "value": { "kind": "dataset", "dataset": "orders", "by": "day" } },
|
|
44
50
|
{ "id": "grain-month", "value": { "kind": "dataset", "dataset": "orders", "by": "month" } },
|
|
45
51
|
{ "id": "grain-year", "value": { "kind": "dataset", "dataset": "orders", "by": "year", "limit": 0 } }
|
package/fixtures/manifest.json
CHANGED
|
@@ -221,6 +221,23 @@
|
|
|
221
221
|
"role": "rejection"
|
|
222
222
|
}
|
|
223
223
|
]
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"name": "semantic-invocations-v1",
|
|
227
|
+
"rfc": "0014",
|
|
228
|
+
"codePrefixes": [
|
|
229
|
+
"HQ_INVOCATION_"
|
|
230
|
+
],
|
|
231
|
+
"files": [
|
|
232
|
+
{
|
|
233
|
+
"path": "semantic-invocations-v1/success.json",
|
|
234
|
+
"role": "success"
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
"path": "semantic-invocations-v1/rejections.json",
|
|
238
|
+
"role": "rejection"
|
|
239
|
+
}
|
|
240
|
+
]
|
|
224
241
|
}
|
|
225
242
|
],
|
|
226
243
|
"fuzz": [
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Semantic invocation v1 fixtures
|
|
2
|
+
|
|
3
|
+
These fixtures exercise RFC 0014 semantic invocation records: the dataset/metric invocation request, the successful result, and the closed failure record.
|
|
4
|
+
|
|
5
|
+
- `success.json` contains accepted language-neutral records, each tagged with the `record` it validates against.
|
|
6
|
+
- `rejections.json` pins generated invalid inputs and stable error codes.
|
|
7
|
+
|
|
8
|
+
Coverage includes closed fields, versions, the normalized single identifier location, activation-revision format, budget floors and ceilings, an empty budget, row and column limits, non-finite and non-scalar cells, a `rowCount` that disagrees with `data`, failure categories, provider-shaped failure codes, control characters, and unsafe accessors.
|
|
9
|
+
|
|
10
|
+
Every record carries a `record` discriminator (`invocation`, `result`, or `failure`) so one family covers all three without three near-identical fixture sets.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[
|
|
2
|
+
{"id": "wrong-root-type", "record": "invocation", "generator": {"type": "wrong-root-type"}, "error": "HQ_INVOCATION_TYPE"},
|
|
3
|
+
{"id": "unknown-root-field", "record": "invocation", "generator": {"type": "unknown-root-field"}, "error": "HQ_INVOCATION_UNKNOWN_FIELD"},
|
|
4
|
+
{"id": "unsupported-version", "record": "invocation", "generator": {"type": "unsupported-version"}, "error": "HQ_INVOCATION_INVALID_VERSION"},
|
|
5
|
+
{"id": "caller-supplied-tenant", "record": "invocation", "generator": {"type": "caller-supplied-tenant"}, "error": "HQ_INVOCATION_UNKNOWN_FIELD"},
|
|
6
|
+
{"id": "redundant-operation-dataset", "record": "invocation", "generator": {"type": "redundant-operation-dataset"}, "error": "HQ_INVOCATION_UNKNOWN_FIELD"},
|
|
7
|
+
{"id": "malformed-activation-revision", "record": "invocation", "generator": {"type": "malformed-activation-revision"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
8
|
+
{"id": "empty-budget", "record": "invocation", "generator": {"type": "empty-budget"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
9
|
+
{"id": "zero-deadline", "record": "invocation", "generator": {"type": "zero-deadline"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
10
|
+
{"id": "deadline-too-large", "record": "invocation", "generator": {"type": "deadline-too-large"}, "error": "HQ_INVOCATION_TOO_LARGE"},
|
|
11
|
+
{"id": "correlation-id-control-character", "record": "invocation", "generator": {"type": "correlation-id-control-character"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
12
|
+
{"id": "unsafe-accessor", "record": "invocation", "generator": {"type": "unsafe-accessor"}, "error": "HQ_INVOCATION_UNSAFE_OBJECT"},
|
|
13
|
+
{"id": "too-many-rows", "record": "result", "generator": {"type": "too-many-rows"}, "error": "HQ_INVOCATION_TOO_MANY_ITEMS"},
|
|
14
|
+
{"id": "too-many-columns", "record": "result", "generator": {"type": "too-many-columns"}, "error": "HQ_INVOCATION_TOO_MANY_ITEMS"},
|
|
15
|
+
{"id": "non-finite-cell", "record": "result", "generator": {"type": "non-finite-cell"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
16
|
+
{"id": "nested-cell", "record": "result", "generator": {"type": "nested-cell"}, "error": "HQ_INVOCATION_TYPE"},
|
|
17
|
+
{"id": "cell-too-large", "record": "result", "generator": {"type": "cell-too-large"}, "error": "HQ_INVOCATION_TOO_LARGE"},
|
|
18
|
+
{"id": "row-count-mismatch", "record": "result", "generator": {"type": "row-count-mismatch"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
19
|
+
{"id": "sparse-data-array", "record": "result", "generator": {"type": "sparse-data-array"}, "error": "HQ_INVOCATION_UNSAFE_OBJECT"},
|
|
20
|
+
{"id": "unknown-failure-category", "record": "failure", "generator": {"type": "unknown-failure-category"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
21
|
+
{"id": "provider-shaped-failure-code", "record": "failure", "generator": {"type": "provider-shaped-failure-code"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
22
|
+
{"id": "failure-message-too-large", "record": "failure", "generator": {"type": "failure-message-too-large"}, "error": "HQ_INVOCATION_TOO_LARGE"},
|
|
23
|
+
{"id": "cell-control-character", "record": "result", "generator": {"type": "cell-control-character"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
24
|
+
{"id": "provider-shaped-failure-message", "record": "failure", "generator": {"type": "provider-shaped-failure-message"}, "error": "HQ_INVOCATION_INVALID_VALUE"},
|
|
25
|
+
{"id": "custom-prototype-data-array", "record": "result", "generator": {"type": "custom-prototype-data-array"}, "error": "HQ_INVOCATION_UNSAFE_OBJECT"},
|
|
26
|
+
{"id": "accessor-data-array", "record": "result", "generator": {"type": "accessor-data-array"}, "error": "HQ_INVOCATION_UNSAFE_OBJECT"},
|
|
27
|
+
{"id": "hidden-data-array-property", "record": "result", "generator": {"type": "hidden-data-array-property"}, "error": "HQ_INVOCATION_UNSAFE_OBJECT"},
|
|
28
|
+
{"id": "symbol-data-array-property", "record": "result", "generator": {"type": "symbol-data-array-property"}, "error": "HQ_INVOCATION_UNSAFE_OBJECT"}
|
|
29
|
+
]
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
[
|
|
2
|
+
{
|
|
3
|
+
"id": "minimal-dataset-invocation",
|
|
4
|
+
"record": "invocation",
|
|
5
|
+
"value": {
|
|
6
|
+
"kind": "hypequery-semantic-invocation",
|
|
7
|
+
"version": 1,
|
|
8
|
+
"target": { "project": "acme", "environment": "production" },
|
|
9
|
+
"operation": { "kind": "dataset", "dataset": "orders", "measures": ["revenue"] }
|
|
10
|
+
}
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
"id": "pinned-metric-invocation-with-budget",
|
|
14
|
+
"record": "invocation",
|
|
15
|
+
"value": {
|
|
16
|
+
"kind": "hypequery-semantic-invocation",
|
|
17
|
+
"version": 1,
|
|
18
|
+
"target": { "project": "acme", "environment": "production" },
|
|
19
|
+
"activationRevision": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
20
|
+
"operation": {
|
|
21
|
+
"kind": "metric",
|
|
22
|
+
"dataset": "orders",
|
|
23
|
+
"metric": "total_revenue",
|
|
24
|
+
"dimensions": ["status"],
|
|
25
|
+
"by": "day",
|
|
26
|
+
"limit": 100,
|
|
27
|
+
"offset": 0
|
|
28
|
+
},
|
|
29
|
+
"budget": { "deadlineMs": 30000, "maxRows": 1000, "maxResponseBytes": 1048576 },
|
|
30
|
+
"correlationId": "req-7f3a"
|
|
31
|
+
}
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "empty-result",
|
|
35
|
+
"record": "result",
|
|
36
|
+
"value": {
|
|
37
|
+
"kind": "hypequery-semantic-invocation-result",
|
|
38
|
+
"version": 1,
|
|
39
|
+
"activationRevision": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
40
|
+
"data": [],
|
|
41
|
+
"meta": { "rowCount": 0 }
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"id": "paginated-result",
|
|
46
|
+
"record": "result",
|
|
47
|
+
"value": {
|
|
48
|
+
"kind": "hypequery-semantic-invocation-result",
|
|
49
|
+
"version": 1,
|
|
50
|
+
"activationRevision": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
51
|
+
"data": [
|
|
52
|
+
{ "status": "paid", "revenue": 1234.5, "refunded": false, "note": null },
|
|
53
|
+
{ "status": "pending", "revenue": 0, "refunded": true, "note": "partial" }
|
|
54
|
+
],
|
|
55
|
+
"meta": {
|
|
56
|
+
"rowCount": 2,
|
|
57
|
+
"pagination": { "limit": 2, "offset": 0, "hasMore": true }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
"id": "correctable-failure",
|
|
63
|
+
"record": "failure",
|
|
64
|
+
"value": {
|
|
65
|
+
"kind": "hypequery-semantic-invocation-failure",
|
|
66
|
+
"version": 1,
|
|
67
|
+
"category": "input-invalid",
|
|
68
|
+
"code": "HQ_SEMANTIC_UNKNOWN_DIMENSION",
|
|
69
|
+
"message": "The semantic query is invalid.",
|
|
70
|
+
"path": "$.operation.dimensions[0]",
|
|
71
|
+
"retryable": false,
|
|
72
|
+
"relist": false
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"id": "stale-activation-failure",
|
|
77
|
+
"record": "failure",
|
|
78
|
+
"value": {
|
|
79
|
+
"kind": "hypequery-semantic-invocation-failure",
|
|
80
|
+
"version": 1,
|
|
81
|
+
"category": "stale-activation",
|
|
82
|
+
"code": "HQ_SEMANTIC_STALE_ACTIVATION",
|
|
83
|
+
"message": "The pinned activation is no longer active.",
|
|
84
|
+
"retryable": true,
|
|
85
|
+
"relist": true,
|
|
86
|
+
"activationRevision": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "unsupported-capability-failure",
|
|
91
|
+
"record": "failure",
|
|
92
|
+
"value": {
|
|
93
|
+
"kind": "hypequery-semantic-invocation-failure",
|
|
94
|
+
"version": 1,
|
|
95
|
+
"category": "unsupported-capability",
|
|
96
|
+
"code": "HQ_SEMANTIC_DERIVED_METRIC_UNSUPPORTED",
|
|
97
|
+
"message": "Portable execution cannot reproduce this target.",
|
|
98
|
+
"retryable": false,
|
|
99
|
+
"relist": false
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
]
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hypequery/protocol-conformance",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Cross-language conformance runner for the Hypequery analytics security protocol",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hypequery",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@hypequery/protocol": "^0.
|
|
34
|
+
"@hypequery/protocol": "^0.13.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^22.5.0",
|