@hypequery/protocol-conformance 0.11.2 → 0.13.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.
@@ -1,15 +1,226 @@
1
1
  [
2
- { "id": "not-object", "value": null, "error": "HQ_SCHEMA_TYPE" },
3
- { "id": "unknown-field", "value": { "kind": "string", "format": "uuid" }, "error": "HQ_SCHEMA_UNKNOWN_FIELD" },
4
- { "id": "unknown-kind", "value": { "kind": "function" }, "error": "HQ_SCHEMA_UNKNOWN_KIND" },
5
- { "id": "invalid-property-identifier", "value": { "kind": "object", "properties": { "bad-name": { "kind": "string" } }, "required": [], "unknownProperties": "reject" }, "error": "HQ_SCHEMA_INVALID_IDENTIFIER" },
6
- { "id": "invalid-raw-default", "value": { "kind": "object", "properties": {}, "required": [], "unknownProperties": "strip", "default": {} }, "error": "HQ_SCHEMA_INVALID_VALUE" },
7
- { "id": "reversed-bounds", "value": { "kind": "integer", "minimum": 10, "maximum": 1 }, "error": "HQ_SCHEMA_INVALID_CONSTRAINT" },
8
- { "id": "required-name-not-declared", "value": { "kind": "object", "properties": {}, "required": ["missing"], "unknownProperties": "reject" }, "error": "HQ_SCHEMA_INVALID_REQUIRED" },
9
- { "id": "duplicate-enum", "value": { "kind": "enum", "values": ["same", "same"] }, "error": "HQ_SCHEMA_DUPLICATE_VALUE" },
10
- { "id": "too-deep", "generator": { "type": "nested-array", "depth": 17 }, "error": "HQ_SCHEMA_TOO_DEEP" },
11
- { "id": "too-many-nodes", "generator": { "type": "union-tree" }, "error": "HQ_SCHEMA_TOO_MANY_NODES" },
12
- { "id": "too-many-items", "generator": { "type": "enum-values", "count": 101 }, "error": "HQ_SCHEMA_TOO_MANY_ITEMS" },
13
- { "id": "description-too-large", "generator": { "type": "description", "bytes": 4097 }, "error": "HQ_SCHEMA_TOO_LARGE" },
14
- { "id": "unsafe-accessor", "generator": { "type": "unsafe-accessor" }, "error": "HQ_SCHEMA_UNSAFE_OBJECT" }
2
+ {
3
+ "id": "not-object",
4
+ "value": null,
5
+ "error": "HQ_SCHEMA_TYPE"
6
+ },
7
+ {
8
+ "id": "unknown-field",
9
+ "value": {
10
+ "kind": "string",
11
+ "format": "uuid"
12
+ },
13
+ "error": "HQ_SCHEMA_UNKNOWN_FIELD"
14
+ },
15
+ {
16
+ "id": "unknown-kind",
17
+ "value": {
18
+ "kind": "function"
19
+ },
20
+ "error": "HQ_SCHEMA_UNKNOWN_KIND"
21
+ },
22
+ {
23
+ "id": "invalid-property-identifier",
24
+ "value": {
25
+ "kind": "object",
26
+ "properties": {
27
+ "bad-name": {
28
+ "kind": "string"
29
+ }
30
+ },
31
+ "required": [],
32
+ "unknownProperties": "reject"
33
+ },
34
+ "error": "HQ_SCHEMA_INVALID_IDENTIFIER"
35
+ },
36
+ {
37
+ "id": "invalid-raw-default",
38
+ "value": {
39
+ "kind": "object",
40
+ "properties": {},
41
+ "required": [],
42
+ "unknownProperties": "strip",
43
+ "default": {}
44
+ },
45
+ "error": "HQ_SCHEMA_INVALID_VALUE"
46
+ },
47
+ {
48
+ "id": "reversed-bounds",
49
+ "value": {
50
+ "kind": "integer",
51
+ "minimum": 10,
52
+ "maximum": 1
53
+ },
54
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
55
+ },
56
+ {
57
+ "id": "required-name-not-declared",
58
+ "value": {
59
+ "kind": "object",
60
+ "properties": {},
61
+ "required": [
62
+ "missing"
63
+ ],
64
+ "unknownProperties": "reject"
65
+ },
66
+ "error": "HQ_SCHEMA_INVALID_REQUIRED"
67
+ },
68
+ {
69
+ "id": "duplicate-enum",
70
+ "value": {
71
+ "kind": "enum",
72
+ "values": [
73
+ "same",
74
+ "same"
75
+ ]
76
+ },
77
+ "error": "HQ_SCHEMA_DUPLICATE_VALUE"
78
+ },
79
+ {
80
+ "id": "void-default",
81
+ "value": {
82
+ "kind": "void",
83
+ "default": null
84
+ },
85
+ "error": "HQ_SCHEMA_UNKNOWN_FIELD"
86
+ },
87
+ {
88
+ "id": "default-rejected-by-own-schema",
89
+ "value": {
90
+ "kind": "integer",
91
+ "default": 1.5
92
+ },
93
+ "error": "HQ_SCHEMA_INVALID_VALUE"
94
+ },
95
+ {
96
+ "id": "raw-array-default",
97
+ "value": {
98
+ "kind": "array",
99
+ "items": {
100
+ "kind": "string"
101
+ },
102
+ "default": [
103
+ "a"
104
+ ]
105
+ },
106
+ "error": "HQ_SCHEMA_INVALID_VALUE"
107
+ },
108
+ {
109
+ "id": "empty-enum",
110
+ "value": {
111
+ "kind": "enum",
112
+ "values": []
113
+ },
114
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
115
+ },
116
+ {
117
+ "id": "single-variant-union",
118
+ "value": {
119
+ "kind": "union",
120
+ "variants": [
121
+ {
122
+ "kind": "string"
123
+ }
124
+ ]
125
+ },
126
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
127
+ },
128
+ {
129
+ "id": "duplicate-required",
130
+ "value": {
131
+ "kind": "object",
132
+ "properties": {
133
+ "a": {
134
+ "kind": "any"
135
+ }
136
+ },
137
+ "required": [
138
+ "a",
139
+ "a"
140
+ ],
141
+ "unknownProperties": "reject"
142
+ },
143
+ "error": "HQ_SCHEMA_INVALID_REQUIRED"
144
+ },
145
+ {
146
+ "id": "missing-unknown-properties",
147
+ "value": {
148
+ "kind": "object",
149
+ "properties": {},
150
+ "required": []
151
+ },
152
+ "error": "HQ_SCHEMA_TYPE"
153
+ },
154
+ {
155
+ "id": "inclusive-and-exclusive-bound",
156
+ "value": {
157
+ "kind": "number",
158
+ "minimum": 1,
159
+ "exclusiveMinimum": 2
160
+ },
161
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
162
+ },
163
+ {
164
+ "id": "empty-exclusive-range",
165
+ "value": {
166
+ "kind": "number",
167
+ "exclusiveMinimum": 1,
168
+ "maximum": 1
169
+ },
170
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
171
+ },
172
+ {
173
+ "id": "non-integral-integer-bound",
174
+ "value": {
175
+ "kind": "integer",
176
+ "minimum": 1.5
177
+ },
178
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
179
+ },
180
+ {
181
+ "id": "negative-collection-bound",
182
+ "value": {
183
+ "kind": "string",
184
+ "minLength": -1
185
+ },
186
+ "error": "HQ_SCHEMA_INVALID_CONSTRAINT"
187
+ },
188
+ {
189
+ "id": "too-deep",
190
+ "generator": {
191
+ "type": "nested-array",
192
+ "depth": 17
193
+ },
194
+ "error": "HQ_SCHEMA_TOO_DEEP"
195
+ },
196
+ {
197
+ "id": "too-many-nodes",
198
+ "generator": {
199
+ "type": "union-tree"
200
+ },
201
+ "error": "HQ_SCHEMA_TOO_MANY_NODES"
202
+ },
203
+ {
204
+ "id": "too-many-items",
205
+ "generator": {
206
+ "type": "enum-values",
207
+ "count": 101
208
+ },
209
+ "error": "HQ_SCHEMA_TOO_MANY_ITEMS"
210
+ },
211
+ {
212
+ "id": "description-too-large",
213
+ "generator": {
214
+ "type": "description",
215
+ "bytes": 4097
216
+ },
217
+ "error": "HQ_SCHEMA_TOO_LARGE"
218
+ },
219
+ {
220
+ "id": "unsafe-accessor",
221
+ "generator": {
222
+ "type": "unsafe-accessor"
223
+ },
224
+ "error": "HQ_SCHEMA_UNSAFE_OBJECT"
225
+ }
15
226
  ]
@@ -0,0 +1,9 @@
1
+ # Semantic invocation v2 fixtures
2
+
3
+ This family accompanies accepted RFC 0015. Semantic invocation 2 is identical to invocation 1 (RFC 0014), except that the `operation` is validated under expression extension 2. It may therefore name segments, `minute`/`hour` grains, and relationship-qualified measures.
4
+
5
+ Only the invocation request has a version 2. Results and failures remain version 1, and `semantic-invocations-v1` covers them.
6
+
7
+ The lowest-version rule applies. A version 2 request whose operation uses no extension 2 feature must be sent as version 1, and is rejected with `HQ_INVOCATION_INVALID_VERSION`. An empty `segments` array names no segment, so it does not count as a feature.
8
+
9
+ Every case was checked against the TypeScript reference implementation. The Python implementation does not announce this family yet.
@@ -0,0 +1,9 @@
1
+ [
2
+ {"id": "lowest-version-rule", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "measures": ["revenue"]}}, "error": "HQ_INVOCATION_INVALID_VERSION"},
3
+ {"id": "lowest-version-empty-segments", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "segments": []}}, "error": "HQ_INVOCATION_INVALID_VERSION"},
4
+ {"id": "version-1-under-v2", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 1, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "segments": ["enterprise"]}}, "error": "HQ_INVOCATION_INVALID_VERSION"},
5
+ {"id": "unknown-version", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 3, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "segments": ["enterprise"]}}, "error": "HQ_INVOCATION_INVALID_VERSION"},
6
+ {"id": "duplicate-segment", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "segments": ["a", "a"]}}, "error": "HQ_INVOCATION_INVALID_VALUE"},
7
+ {"id": "grain-still-closed", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "by": "second"}}, "error": "HQ_INVOCATION_INVALID_VALUE"},
8
+ {"id": "tenant-field-still-forbidden", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "segments": ["enterprise"]}, "tenant": "t1"}, "error": "HQ_INVOCATION_UNKNOWN_FIELD"}
9
+ ]
@@ -0,0 +1,5 @@
1
+ [
2
+ {"id": "segments", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "measures": ["revenue"], "segments": ["enterprise"]}}},
3
+ {"id": "sub-day-grain-metric", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "metric", "dataset": "events", "metric": "sessions", "by": "hour", "limit": 24}}},
4
+ {"id": "relationship-measure", "record": "invocation", "value": {"kind": "hypequery-semantic-invocation", "version": 2, "target": {"project": "acme", "environment": "production"}, "operation": {"kind": "dataset", "dataset": "orders", "dimensions": ["status"], "measures": ["customer.customerCount"]}, "budget": {"maxRows": 100}}}
5
+ ]
@@ -3,4 +3,6 @@
3
3
  - `portable.json` maps accepted SQL expression fragments to RFC 0003 expression trees and sorted dependencies.
4
4
  - `non-portable.json` maps unsupported input to the first issue code and source offset.
5
5
 
6
+ Source offsets are zero-based and counted in UTF-16 code units, so a character outside the Basic Multilingual Plane (such as an emoji) advances every later offset by two. This is the unit JavaScript strings and most editors use; implementations whose native strings index by code point must convert.
7
+
6
8
  The portable subset covers identifiers, literals, arithmetic, comparisons, literal `IN` lists, literal `BETWEEN`, `LIKE`, boolean logic, parentheses, and the approved formula functions. Statements, subqueries, casts, lambdas, comments, unapproved functions, and dynamic list/range operands remain non-portable by construction.
@@ -142,5 +142,126 @@
142
142
  "sql": "x IN (1, 2, )",
143
143
  "code": "HQ_SQL_PORT_SYNTAX",
144
144
  "start": 10
145
+ },
146
+ {
147
+ "id": "astral-offset-after-string-literal",
148
+ "sql": "name = '\ud83d\ude00' AND ;",
149
+ "code": "HQ_SQL_PORT_UNSUPPORTED_SYNTAX",
150
+ "start": 16
151
+ },
152
+ {
153
+ "id": "astral-offset-unterminated-string",
154
+ "sql": "'\ud83d\ude00' = 'x",
155
+ "code": "HQ_SQL_PORT_SYNTAX",
156
+ "start": 7
157
+ },
158
+ {
159
+ "id": "astral-unexpected-character",
160
+ "sql": "a + \ud83d\ude00",
161
+ "code": "HQ_SQL_PORT_UNSUPPORTED_SYNTAX",
162
+ "start": 4
163
+ },
164
+ {
165
+ "id": "astral-offset-unsupported-function",
166
+ "sql": "coalesce(name, '\ud83d\ude00\ud83d\ude00') = lower(name)",
167
+ "code": "HQ_SQL_PORT_UNSUPPORTED_FUNCTION",
168
+ "start": 25
169
+ },
170
+ {
171
+ "id": "like-column-pattern",
172
+ "sql": "name LIKE pattern",
173
+ "code": "HQ_SQL_PORT_UNSUPPORTED_SYNTAX",
174
+ "start": 5
175
+ },
176
+ {
177
+ "id": "like-numeric-pattern",
178
+ "sql": "name LIKE 1",
179
+ "code": "HQ_SQL_PORT_UNSUPPORTED_SYNTAX",
180
+ "start": 5
181
+ },
182
+ {
183
+ "id": "additive-chain-too-deep",
184
+ "sqlRepeat": {
185
+ "prefix": "a",
186
+ "value": " + a",
187
+ "suffix": "",
188
+ "count": 16
189
+ },
190
+ "code": "HQ_SQL_PORT_TOO_COMPLEX",
191
+ "start": 62
192
+ },
193
+ {
194
+ "id": "multiplicative-chain-too-deep",
195
+ "sqlRepeat": {
196
+ "prefix": "a",
197
+ "value": " * a",
198
+ "suffix": "",
199
+ "count": 16
200
+ },
201
+ "code": "HQ_SQL_PORT_TOO_COMPLEX",
202
+ "start": 62
203
+ },
204
+ {
205
+ "id": "or-operands-over-limit",
206
+ "sqlRepeat": {
207
+ "prefix": "a",
208
+ "value": " OR a",
209
+ "suffix": "",
210
+ "count": 100
211
+ },
212
+ "code": "HQ_SQL_PORT_TOO_COMPLEX",
213
+ "start": 497
214
+ },
215
+ {
216
+ "id": "and-operands-over-limit",
217
+ "sqlRepeat": {
218
+ "prefix": "a = 1",
219
+ "value": " AND a = 1",
220
+ "suffix": "",
221
+ "count": 100
222
+ },
223
+ "code": "HQ_SQL_PORT_TOO_COMPLEX",
224
+ "start": 996
225
+ },
226
+ {
227
+ "id": "negative-in-list-over-node-limit",
228
+ "sqlRepeat": {
229
+ "prefix": "a IN (-1",
230
+ "value": ", -1",
231
+ "suffix": ")",
232
+ "count": 1000
233
+ },
234
+ "code": "HQ_SQL_PORT_TOO_COMPLEX",
235
+ "start": 4003
236
+ },
237
+ {
238
+ "id": "string-control-character",
239
+ "sql": "name = 'a\u0001b'",
240
+ "code": "HQ_SQL_PORT_UNSUPPORTED_LITERAL",
241
+ "start": 9
242
+ },
243
+ {
244
+ "id": "string-delete-character",
245
+ "sql": "name = 'a\u007fb'",
246
+ "code": "HQ_SQL_PORT_UNSUPPORTED_LITERAL",
247
+ "start": 9
248
+ },
249
+ {
250
+ "id": "string-c1-control-character",
251
+ "sql": "name = '\u0085'",
252
+ "code": "HQ_SQL_PORT_UNSUPPORTED_LITERAL",
253
+ "start": 8
254
+ },
255
+ {
256
+ "id": "string-lone-high-surrogate",
257
+ "sql": "name = '\ud800'",
258
+ "code": "HQ_SQL_PORT_UNSUPPORTED_LITERAL",
259
+ "start": 8
260
+ },
261
+ {
262
+ "id": "string-lone-low-surrogate",
263
+ "sql": "name = 'a\udc00'",
264
+ "code": "HQ_SQL_PORT_UNSUPPORTED_LITERAL",
265
+ "start": 9
145
266
  }
146
267
  ]
@@ -331,6 +331,24 @@
331
331
  "value": "before\u000bafter",
332
332
  "error": "HQ_VALUE_CONTROL_CHARACTER"
333
333
  },
334
+ {
335
+ "id": "model-trailing-lone-high-surrogate",
336
+ "phase": "model",
337
+ "value": "\ud800",
338
+ "error": "HQ_VALUE_INVALID_UNICODE"
339
+ },
340
+ {
341
+ "id": "model-suffix-lone-high-surrogate",
342
+ "phase": "model",
343
+ "value": "before\ud800",
344
+ "error": "HQ_VALUE_INVALID_UNICODE"
345
+ },
346
+ {
347
+ "id": "model-lone-low-surrogate",
348
+ "phase": "model",
349
+ "value": "\udc00after",
350
+ "error": "HQ_VALUE_INVALID_UNICODE"
351
+ },
334
352
  {
335
353
  "id": "value-unsafe-accessor",
336
354
  "phase": "model",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hypequery/protocol-conformance",
3
- "version": "0.11.2",
3
+ "version": "0.13.0",
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.14.0"
34
+ "@hypequery/protocol": "^0.16.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "^22.5.0",