@dashevo/dapi-grpc 4.2.0-dev.7 → 4.2.0-dev.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dashevo/dapi-grpc",
3
- "version": "4.2.0-dev.7",
3
+ "version": "4.2.0-dev.8",
4
4
  "description": "DAPI GRPC definition file and generated clients",
5
5
  "browser": "browser.js",
6
6
  "main": "node.js",
@@ -45,7 +45,7 @@
45
45
  },
46
46
  "homepage": "https://github.com/dashevo/dapi-grpc#readme",
47
47
  "dependencies": {
48
- "@dashevo/grpc-common": "4.2.0-dev.7",
48
+ "@dashevo/grpc-common": "4.2.0-dev.8",
49
49
  "@dashevo/protobufjs": "6.10.5",
50
50
  "@grpc/grpc-js": "^1.14.3",
51
51
  "@improbable-eng/grpc-web": "^0.15.0",
@@ -596,15 +596,15 @@ message GetDocumentsRequest {
596
596
  STARTS_WITH = 10;
597
597
  // Time-range bucket selection (v1 only; the v0 CBOR surface is
598
598
  // unaffected). `field` names a timestamp covered by a `timeRange`
599
- // index. Operand: `text` selector `"newest"`/`"oldest"` when one grid
600
- // buckets the field, or `list` `[selector, range, step(, phase)]` in
601
- // the contract's declared seconds to name one of several grids (zero
602
- // phase is spelled by omission one wire spelling per grid). The
603
- // server resolves it to a bucket-start equality from current block
604
- // time; the verifier re-derives the same bucket from the quorum-signed
605
- // metadata time an ordinary index/count proof. See `timeRange` in
606
- // the document meta-schema and
607
- // `drive::query::resolve_time_range_bucket_clause`.
599
+ // index. The operand is `WhereClause.time_range` (a
600
+ // `TimeRangeSelection`); `WhereClause.value` must be unset. For the
601
+ // relative selectors (`NEWEST` / `OLDEST`) the server resolves the
602
+ // selection to a bucket-start equality from current block time and
603
+ // the verifier re-derives the same bucket from the quorum-signed
604
+ // metadata time; `BY_START` names the window absolutely, so both
605
+ // sides read the start straight from the query an ordinary
606
+ // index/count proof either way. See `timeRange` in the document
607
+ // meta-schema and `drive::query::resolve_time_range_bucket_clause`.
608
608
  IN_TIME_RANGE = 11;
609
609
  }
610
610
 
@@ -658,6 +658,54 @@ message GetDocumentsRequest {
658
658
  }
659
659
  }
660
660
 
661
+ // Operand of an `IN_TIME_RANGE` where clause: which window of a
662
+ // `timeRange` grid the query selects. Typed rather than riding
663
+ // `DocumentFieldValue` — the selection is not a field value, and a
664
+ // structured message keeps the selector an enum instead of a
665
+ // magic string.
666
+ //
667
+ // The relative selectors are resolved server-side: `NEWEST` is the
668
+ // freshest started window (largest grid start <= block time; the
669
+ // latest partial slice of history), `OLDEST` the oldest window still
670
+ // active at block time (a near-full trailing window of ~`range` —
671
+ // best for "trending over the last window"). The proof verifier
672
+ // re-derives the same window from the quorum-signed response
673
+ // metadata time, so neither side trusts the other's clock.
674
+ //
675
+ // `BY_START` names a window absolutely — any window, current or
676
+ // historic — by its start. `start_ms` is then required and must lie
677
+ // on the grid (`start_ms == phase + k * step`, in milliseconds);
678
+ // an unaligned start is rejected rather than snapped. A window with
679
+ // no documents (including one that has not started yet) is a
680
+ // provable empty answer, not an error. The relative selectors must
681
+ // NOT carry `start_ms` — one wire spelling per meaning.
682
+ message TimeRangeSelection {
683
+ enum Selector {
684
+ NEWEST = 0;
685
+ OLDEST = 1;
686
+ BY_START = 2;
687
+ }
688
+ // Names one of the field's declared grids, in the contract's own
689
+ // seconds — verbatim from the contract's `timeRange` declaration.
690
+ // Required when more than one `timeRange` grid buckets the field
691
+ // (the bare selector is ambiguous there and rejected); optional
692
+ // while exactly one grid does. A zero `phase` is the proto3
693
+ // default, matching the contract grammar where `phase` is an
694
+ // omittable key — every grid has exactly one wire spelling by
695
+ // construction.
696
+ message Grid {
697
+ uint64 range = 1 [jstype = JS_STRING];
698
+ uint64 step = 2 [jstype = JS_STRING];
699
+ uint64 phase = 3 [jstype = JS_STRING];
700
+ }
701
+ Selector selector = 1;
702
+ // `BY_START` only: the selected window's start, as a millisecond
703
+ // timestamp on the grid (see the message docstring). Rejected on
704
+ // the relative selectors.
705
+ optional uint64 start_ms = 2 [jstype = JS_STRING];
706
+ Grid grid = 3;
707
+ }
708
+
661
709
  // Single `field <op> value` clause. The server reassembles a
662
710
  // `Vec<WhereClause>` from the request's `where_clauses` field,
663
711
  // runs the same `WhereClause::group_clauses` validator (rejects
@@ -666,10 +714,16 @@ message GetDocumentsRequest {
666
714
  // then hands the structured clauses to the executor. Wire
667
715
  // semantics are identical to v0's CBOR `[field, op, value]`
668
716
  // triples — only the envelope differs.
717
+ //
718
+ // Exactly one operand field is set, keyed by the operator:
719
+ // `operator = IN_TIME_RANGE` carries its operand in `time_range`
720
+ // (`value` must be unset); every other operator carries `value`
721
+ // (`time_range` must be unset). Either mismatch is rejected.
669
722
  message WhereClause {
670
723
  string field = 1;
671
724
  WhereOperator operator = 2;
672
725
  DocumentFieldValue value = 3;
726
+ TimeRangeSelection time_range = 4;
673
727
  }
674
728
 
675
729
  // Per-group aggregate operand for the left side of a
@@ -1158,6 +1212,47 @@ message GetDocumentsRequest {
1158
1212
  // no ranked executor. Cursor pagination via `start_after` /
1159
1213
  // `start_at` remains the supported way to page through documents.
1160
1214
  optional uint32 offset = 12;
1215
+
1216
+ // Chained mode — a provable semi-join:
1217
+ // `SELECT * FROM <outer_document_type> WHERE $id IN
1218
+ // (SELECT <join_property> FROM <document_type> WHERE ...)`.
1219
+ //
1220
+ // Presence of this message selects chained mode: this request's
1221
+ // own `document_type` / `where_clauses` / `order_by` / `limit`
1222
+ // describe the INNER indexOnly query, and the outer half is
1223
+ // DERIVED from its results — the request carries no outer
1224
+ // clauses by design, and the verifier re-derives the outer
1225
+ // query from the proven inner values, so the join cannot be
1226
+ // steered by the responding node.
1227
+ //
1228
+ // Mode gates (rejected otherwise): the inner type must be
1229
+ // indexOnly and resolve to an index carrying `join_property`;
1230
+ // `join_property` must declare a same-contract
1231
+ // `refersTo: permanentDocument` targeting
1232
+ // `outer_document_type`; `limit` is REQUIRED (it bounds the
1233
+ // derived outer query — no server-default fallback) and capped
1234
+ // by the outer `$id IN` clause's 100-value limit; `selects`
1235
+ // must be empty or a single DOCUMENTS projection; `group_by`,
1236
+ // `having`, time-range clauses, cursors, and `offset` are all
1237
+ // rejected. Pagination is a range clause on `join_property`.
1238
+ //
1239
+ // The verifier needs nothing beyond the proof itself: it
1240
+ // subset-verifies the inner query against the merged proof to
1241
+ // extract the join values, re-derives the outer component, and
1242
+ // verifies the whole composition. A node that predates this
1243
+ // field ignores it (proto3 unknown field) and serves the plain
1244
+ // inner query — which FAILS CLOSED client-side: an inner-only
1245
+ // proof cannot satisfy the re-derived merged query for a
1246
+ // non-empty page, and an unproven response carries the wrong
1247
+ // ResultData variant.
1248
+ message ChainedJoin {
1249
+ // The inner property whose proven values become the outer
1250
+ // documents' `$id`s.
1251
+ string join_property = 1;
1252
+ // The joined document type — the `refersTo` target.
1253
+ string outer_document_type = 2;
1254
+ }
1255
+ ChainedJoin chained = 13;
1161
1256
  }
1162
1257
 
1163
1258
  oneof version {
@@ -1503,9 +1598,23 @@ message GetDocumentsResponse {
1503
1598
  // `skipped` carries the page's starting rank — see
1504
1599
  // `RankedEntries`.
1505
1600
  RankedEntries ranked = 5;
1601
+ // Chained-mode result: both halves of the provable
1602
+ // semi-join, in inner order (the last inner projection's
1603
+ // join-property value is the pagination cursor; outer
1604
+ // documents are ordered by first appearance of their id
1605
+ // among the inner projections, deduplicated). Routed when
1606
+ // the request's `chained` message is present.
1607
+ ChainedDocuments chained = 6;
1506
1608
  }
1507
1609
  }
1508
1610
 
1611
+ // Both halves of a chained (semi-join) query, each serialized
1612
+ // with its own document type.
1613
+ message ChainedDocuments {
1614
+ repeated bytes inner_documents = 1;
1615
+ repeated bytes outer_documents = 2;
1616
+ }
1617
+
1509
1618
  oneof result {
1510
1619
  ResultData data = 1;
1511
1620
  Proof proof = 2;