@riffdb/client 0.2.3 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/conformance-manifest-v1.json +4 -2
- package/dist/driver.d.ts +1 -0
- package/dist/driver.js +26 -2
- package/dist/index.js +10 -8
- package/dist/operator.js +2 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,8 +7,8 @@ compiler IDs, storage keys, or an authorization bypass.
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install --save-dev @riffdb/cli@0.2.
|
|
11
|
-
npm install @riffdb/client@0.2.
|
|
10
|
+
npm install --save-dev @riffdb/cli@0.2.5
|
|
11
|
+
npm install @riffdb/client@0.2.5
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Four-step application story
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
"language": "typescript",
|
|
4
4
|
"artifact": "offline-npm-tree",
|
|
5
5
|
"transport": "retained-rust-driver-host",
|
|
6
|
-
"platforms": [
|
|
7
|
-
|
|
6
|
+
"platforms": [
|
|
7
|
+
"linux-x86_64"
|
|
8
|
+
],
|
|
9
|
+
"corpus_sha256": "57db5444d3e92f6e4b911b4db42c4d265c5dc55cae80c8270a5428dbbd7b6b74",
|
|
8
10
|
"remote_tls": "installed",
|
|
9
11
|
"typed_errors": "installed",
|
|
10
12
|
"read_after_commit": "installed",
|
package/dist/driver.d.ts
CHANGED
|
@@ -159,6 +159,7 @@ export interface DriverErrorDetails {
|
|
|
159
159
|
readonly category: string;
|
|
160
160
|
readonly operation?: string;
|
|
161
161
|
readonly symbolPath: ReadonlyArray<string>;
|
|
162
|
+
readonly authorizationDiagnostic?: string;
|
|
162
163
|
readonly contractLineage?: string;
|
|
163
164
|
readonly contractVersion?: bigint;
|
|
164
165
|
readonly traceId?: string;
|
package/dist/driver.js
CHANGED
|
@@ -50,7 +50,14 @@ export class DriverApplicationError extends Error {
|
|
|
50
50
|
details;
|
|
51
51
|
name = "DriverApplicationError";
|
|
52
52
|
constructor(details) {
|
|
53
|
-
|
|
53
|
+
let text = `${details.code}: ${details.message}`;
|
|
54
|
+
if (details.symbolPath.length > 0) {
|
|
55
|
+
text += ` (${details.symbolPath.join(".")})`;
|
|
56
|
+
}
|
|
57
|
+
if (details.authorizationDiagnostic !== undefined) {
|
|
58
|
+
text += ` [diagnostic: ${details.authorizationDiagnostic}]`;
|
|
59
|
+
}
|
|
60
|
+
super(text);
|
|
54
61
|
this.details = details;
|
|
55
62
|
}
|
|
56
63
|
}
|
|
@@ -940,6 +947,17 @@ function decodeBatchResult(response, expectedTotal, requestedCheckpoint) {
|
|
|
940
947
|
});
|
|
941
948
|
return { items, checkpoint, total };
|
|
942
949
|
}
|
|
950
|
+
const AUTHORIZATION_DIAGNOSTIC_CODES = new Set([
|
|
951
|
+
"missing_permission",
|
|
952
|
+
"scan_budget_exceeded",
|
|
953
|
+
"tenant_scope_mismatch",
|
|
954
|
+
"partition_scope_mismatch",
|
|
955
|
+
"field_visibility_denied",
|
|
956
|
+
"row_policy_denied",
|
|
957
|
+
"approval_required",
|
|
958
|
+
"delegation_exceeds_authority",
|
|
959
|
+
"inactive_or_stale_capability",
|
|
960
|
+
]);
|
|
943
961
|
function decodeError(response) {
|
|
944
962
|
const code = boundedPattern(response.code, /^[A-Z0-9-]{1,64}$/);
|
|
945
963
|
const category = boundedPattern(response.category, /^[a-z_]{1,64}$/);
|
|
@@ -950,6 +968,11 @@ function decodeError(response) {
|
|
|
950
968
|
throw new Error("RiffDB driver returned invalid error context");
|
|
951
969
|
}
|
|
952
970
|
const symbolPath = response.symbol_path.map((value) => boundedPattern(value, SYMBOL));
|
|
971
|
+
const authorizationDiagnostic = optionalPattern(response.authorization_diagnostic, SYMBOL);
|
|
972
|
+
if (authorizationDiagnostic !== undefined &&
|
|
973
|
+
(code !== "RDB-AUTH-0214" || !AUTHORIZATION_DIAGNOSTIC_CODES.has(authorizationDiagnostic))) {
|
|
974
|
+
throw new Error("RiffDB driver returned invalid error context");
|
|
975
|
+
}
|
|
953
976
|
const operation = optionalPattern(response.operation, SYMBOL);
|
|
954
977
|
const contractLineage = optionalPattern(response.contract_lineage, SYMBOL);
|
|
955
978
|
const contractVersion = optionalPositiveBigInt(response.contract_version);
|
|
@@ -963,6 +986,7 @@ function decodeError(response) {
|
|
|
963
986
|
return new DriverApplicationError({
|
|
964
987
|
code, category, symbolPath, message, retryability, recoveryAction,
|
|
965
988
|
outcomeUncertain: response.outcome_uncertain,
|
|
989
|
+
...(authorizationDiagnostic === undefined ? {} : { authorizationDiagnostic }),
|
|
966
990
|
...(operation === undefined ? {} : { operation }),
|
|
967
991
|
...(contractLineage === undefined ? {} : { contractLineage }),
|
|
968
992
|
...(contractVersion === undefined ? {} : { contractVersion }),
|
|
@@ -1113,7 +1137,7 @@ function validateDriverValue(value, depth) {
|
|
|
1113
1137
|
BigInt(boundedPattern(item.value, /^[0-9]{1,20}$/));
|
|
1114
1138
|
return item;
|
|
1115
1139
|
}
|
|
1116
|
-
if (type === "string" && typeof item.value === "string" && item.value
|
|
1140
|
+
if (type === "string" && typeof item.value === "string" && Buffer.byteLength(item.value, "utf8") <= 1_048_576)
|
|
1117
1141
|
return item;
|
|
1118
1142
|
// Byte values use padded Base64 on this bounded JSON protocol. Their
|
|
1119
1143
|
// canonical decoded size is checked by the generated facade and service;
|
package/dist/index.js
CHANGED
|
@@ -1247,13 +1247,13 @@ function encodeDriverValue(value, schema, budgetPath) {
|
|
|
1247
1247
|
return { type: "u64", value: parsed.toString() };
|
|
1248
1248
|
}
|
|
1249
1249
|
case "string": {
|
|
1250
|
-
const string = expectBoundedString(value,
|
|
1250
|
+
const string = expectBoundedString(value, 1_048_576);
|
|
1251
1251
|
if (schema.maximumBytes !== undefined && new TextEncoder().encode(string).length > schema.maximumBytes && budgetPath !== undefined) {
|
|
1252
1252
|
throw new InputBudgetError("individual_value_bytes", budgetPath);
|
|
1253
1253
|
}
|
|
1254
1254
|
return { type: "string", value: string };
|
|
1255
1255
|
}
|
|
1256
|
-
case "cursor": return { type: "string", value: expectBoundedString(value,
|
|
1256
|
+
case "cursor": return { type: "string", value: expectBoundedString(value, 1_048_576) };
|
|
1257
1257
|
case "uuid":
|
|
1258
1258
|
if (typeof value !== "string" || !UUID.test(value))
|
|
1259
1259
|
throw new Error("invalid generated RiffDB UUID input");
|
|
@@ -1481,7 +1481,7 @@ function decodeDriverValue(value, schema) {
|
|
|
1481
1481
|
case "string":
|
|
1482
1482
|
case "cursor":
|
|
1483
1483
|
if (value.type === "string")
|
|
1484
|
-
return expectBoundedString(value.value,
|
|
1484
|
+
return expectBoundedString(value.value, 1_048_576);
|
|
1485
1485
|
break;
|
|
1486
1486
|
case "uuid":
|
|
1487
1487
|
if (value.type === "uuid" && UUID.test(value.value))
|
|
@@ -1693,13 +1693,13 @@ function encodeValue(value, schema, budgetPath) {
|
|
|
1693
1693
|
case "enum":
|
|
1694
1694
|
return { $enum: expectSymbol(value) };
|
|
1695
1695
|
case "string": {
|
|
1696
|
-
const string = expectBoundedString(value,
|
|
1696
|
+
const string = expectBoundedString(value, 1_048_576);
|
|
1697
1697
|
if (schema.maximumBytes !== undefined && new TextEncoder().encode(string).length > schema.maximumBytes && budgetPath !== undefined) {
|
|
1698
1698
|
throw new InputBudgetError("individual_value_bytes", budgetPath);
|
|
1699
1699
|
}
|
|
1700
1700
|
return string;
|
|
1701
1701
|
}
|
|
1702
|
-
case "cursor": return expectBoundedString(value,
|
|
1702
|
+
case "cursor": return expectBoundedString(value, 1_048_576);
|
|
1703
1703
|
case "bool":
|
|
1704
1704
|
if (typeof value !== "boolean")
|
|
1705
1705
|
throw new Error("invalid boolean input");
|
|
@@ -1790,7 +1790,7 @@ function canonicalValueEncodedLength(value, schema) {
|
|
|
1790
1790
|
case "decimal": return 20;
|
|
1791
1791
|
case "money": return 23;
|
|
1792
1792
|
case "string":
|
|
1793
|
-
case "cursor": return 6 + new TextEncoder().encode(expectBoundedString(value,
|
|
1793
|
+
case "cursor": return 6 + new TextEncoder().encode(expectBoundedString(value, 1_048_576)).byteLength;
|
|
1794
1794
|
case "bytes": {
|
|
1795
1795
|
if (!(value instanceof Uint8Array))
|
|
1796
1796
|
throw new Error("invalid generated application input");
|
|
@@ -1859,7 +1859,7 @@ function decodeTagged(value) {
|
|
|
1859
1859
|
case "i64":
|
|
1860
1860
|
case "u64": return BigInt(expectDecimal(input.value));
|
|
1861
1861
|
case "string":
|
|
1862
|
-
case "uuid": return expectBoundedString(input.value,
|
|
1862
|
+
case "uuid": return expectBoundedString(input.value, 1_048_576);
|
|
1863
1863
|
case "enum": return expectSymbol(input.name);
|
|
1864
1864
|
case "date": return Number(expectDecimal(input.days_since_unix_epoch));
|
|
1865
1865
|
case "timestamp": return createTimestampValue(BigInt(expectDecimal(input.seconds)), nonnegativeNumber(input.nanos));
|
|
@@ -2040,6 +2040,8 @@ function normalizeError(input) {
|
|
|
2040
2040
|
output.contractVersion = Number(expectDecimal(input.contract_version));
|
|
2041
2041
|
if (input.operation_symbol !== undefined)
|
|
2042
2042
|
output.operationSymbol = input.operation_symbol;
|
|
2043
|
+
if (input.authorization_diagnostic !== undefined)
|
|
2044
|
+
output.authorizationDiagnostic = input.authorization_diagnostic;
|
|
2043
2045
|
if (input.source_span !== undefined) {
|
|
2044
2046
|
const span = exactObject(input.source_span);
|
|
2045
2047
|
output.sourceSpan = { start: Number(expectDecimal(span.start)), end: Number(expectDecimal(span.end)) };
|
|
@@ -2117,7 +2119,7 @@ function encodeCliReactiveValue(value, schema) {
|
|
|
2117
2119
|
return { type: "u64", value: value.toString() };
|
|
2118
2120
|
case "string":
|
|
2119
2121
|
case "cursor":
|
|
2120
|
-
return { type: "string", value: expectBoundedString(value,
|
|
2122
|
+
return { type: "string", value: expectBoundedString(value, 1_048_576) };
|
|
2121
2123
|
case "uuid":
|
|
2122
2124
|
if (typeof value !== "string" || !UUID.test(value))
|
|
2123
2125
|
return fail();
|
package/dist/operator.js
CHANGED
|
@@ -22,14 +22,12 @@ export class OperatorError extends Error {
|
|
|
22
22
|
*/
|
|
23
23
|
export class OperatorTransport {
|
|
24
24
|
#socket;
|
|
25
|
-
#identity;
|
|
26
25
|
#input = Buffer.alloc(0);
|
|
27
26
|
#pending;
|
|
28
27
|
#nextRequest = 1;
|
|
29
28
|
#closed = false;
|
|
30
|
-
constructor(socket
|
|
29
|
+
constructor(socket) {
|
|
31
30
|
this.#socket = socket;
|
|
32
|
-
this.#identity = identity;
|
|
33
31
|
socket.on("data", (chunk) => this.#receive(chunk));
|
|
34
32
|
socket.on("error", () => this.#fail(new Error("RiffDB operator session failed")));
|
|
35
33
|
socket.on("close", () => this.#fail(new Error("RiffDB operator session closed")));
|
|
@@ -42,7 +40,7 @@ export class OperatorTransport {
|
|
|
42
40
|
socket.once("connect", () => { socket.off("error", onError); resolve(); });
|
|
43
41
|
socket.once("error", onError);
|
|
44
42
|
});
|
|
45
|
-
const transport = new OperatorTransport(socket
|
|
43
|
+
const transport = new OperatorTransport(socket);
|
|
46
44
|
try {
|
|
47
45
|
const requestId = transport.#requestId("handshake");
|
|
48
46
|
const response = await transport.#request({
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"description":"First-party application runtime for the Rust-owned RiffDB driver host","engines":{"node":">=22"},"exports":{".":"./dist/index.js","./operator":"./dist/operator.js"},"files":["dist","README.md","conformance-manifest-v1.json"],"license":"MIT OR Apache-2.0","name":"@riffdb/client","repository":{"type":"git","url":"git+https://github.com/riffdb/riffdb.git"},"type":"module","types":"./dist/index.d.ts","version":"0.2.
|
|
1
|
+
{"description":"First-party application runtime for the Rust-owned RiffDB driver host","engines":{"node":">=22"},"exports":{".":"./dist/index.js","./operator":"./dist/operator.js"},"files":["dist","README.md","conformance-manifest-v1.json"],"license":"MIT OR Apache-2.0","name":"@riffdb/client","repository":{"type":"git","url":"git+https://github.com/riffdb/riffdb.git"},"type":"module","types":"./dist/index.d.ts","version":"0.2.5"}
|