@stigmer/server 3.24.0 → 3.26.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.
- package/dist/authorization/authorizer.d.ts +10 -4
- package/dist/authorization/authorizer.d.ts.map +1 -1
- package/dist/authorization/authorizer.js +11 -4
- package/dist/authorization/authorizer.js.map +1 -1
- package/dist/authorization/model/index.d.ts +4 -4
- package/dist/authorization/model/index.d.ts.map +1 -1
- package/dist/authorization/model/index.js +2 -0
- package/dist/authorization/model/index.js.map +1 -1
- package/dist/authorization/model/oauth_app.d.ts.map +1 -1
- package/dist/authorization/model/oauth_app.js +3 -2
- package/dist/authorization/model/oauth_app.js.map +1 -1
- package/dist/authorization/model/platform_client.d.ts +2 -0
- package/dist/authorization/model/platform_client.d.ts.map +1 -0
- package/dist/authorization/model/platform_client.js +31 -0
- package/dist/authorization/model/platform_client.js.map +1 -0
- package/dist/boot/compose.d.ts.map +1 -1
- package/dist/boot/compose.js +99 -13
- package/dist/boot/compose.js.map +1 -1
- package/dist/boot/list-indexes.d.ts +3 -0
- package/dist/boot/list-indexes.d.ts.map +1 -0
- package/dist/boot/list-indexes.js +24 -0
- package/dist/boot/list-indexes.js.map +1 -0
- package/dist/boot/route-shadowing.d.ts +25 -0
- package/dist/boot/route-shadowing.d.ts.map +1 -0
- package/dist/boot/route-shadowing.js +17 -0
- package/dist/boot/route-shadowing.js.map +1 -0
- package/dist/domain/agentexecution/controller.d.ts.map +1 -1
- package/dist/domain/agentexecution/controller.js +6 -8
- package/dist/domain/agentexecution/controller.js.map +1 -1
- package/dist/domain/agentexecution/list-index.d.ts +2 -0
- package/dist/domain/agentexecution/list-index.d.ts.map +1 -0
- package/dist/domain/agentexecution/list-index.js +23 -0
- package/dist/domain/agentexecution/list-index.js.map +1 -0
- package/dist/domain/agentexecution/steps.d.ts +17 -33
- package/dist/domain/agentexecution/steps.d.ts.map +1 -1
- package/dist/domain/agentexecution/steps.js +94 -95
- package/dist/domain/agentexecution/steps.js.map +1 -1
- package/dist/domain/agentexecution/usage.d.ts.map +1 -1
- package/dist/domain/agentexecution/usage.js +37 -14
- package/dist/domain/agentexecution/usage.js.map +1 -1
- package/dist/domain/artifact/controller.d.ts.map +1 -1
- package/dist/domain/artifact/controller.js +27 -15
- package/dist/domain/artifact/controller.js.map +1 -1
- package/dist/domain/artifact/list-index.d.ts +2 -0
- package/dist/domain/artifact/list-index.d.ts.map +1 -0
- package/dist/domain/artifact/list-index.js +21 -0
- package/dist/domain/artifact/list-index.js.map +1 -0
- package/dist/domain/iampolicy/membership.d.ts +6 -1
- package/dist/domain/iampolicy/membership.d.ts.map +1 -1
- package/dist/domain/iampolicy/membership.js +8 -2
- package/dist/domain/iampolicy/membership.js.map +1 -1
- package/dist/domain/identityaccount/constants.d.ts +13 -0
- package/dist/domain/identityaccount/constants.d.ts.map +1 -1
- package/dist/domain/identityaccount/constants.js +17 -0
- package/dist/domain/identityaccount/constants.js.map +1 -1
- package/dist/domain/identityaccount/controller.d.ts +3 -1
- package/dist/domain/identityaccount/controller.d.ts.map +1 -1
- package/dist/domain/identityaccount/controller.js +15 -6
- package/dist/domain/identityaccount/controller.js.map +1 -1
- package/dist/domain/identityaccount/operator.d.ts.map +1 -1
- package/dist/domain/identityaccount/operator.js +1 -0
- package/dist/domain/identityaccount/operator.js.map +1 -1
- package/dist/domain/identityaccount/provisioning.d.ts +18 -0
- package/dist/domain/identityaccount/provisioning.d.ts.map +1 -1
- package/dist/domain/identityaccount/provisioning.js +1 -0
- package/dist/domain/identityaccount/provisioning.js.map +1 -1
- package/dist/domain/identityaccount/resource-store.js +9 -5
- package/dist/domain/identityaccount/resource-store.js.map +1 -1
- package/dist/domain/identityaccount/steps.d.ts +11 -2
- package/dist/domain/identityaccount/steps.d.ts.map +1 -1
- package/dist/domain/identityaccount/steps.js +42 -4
- package/dist/domain/identityaccount/steps.js.map +1 -1
- package/dist/domain/identityaccount/store-contract.d.ts.map +1 -1
- package/dist/domain/identityaccount/store-contract.js +33 -0
- package/dist/domain/identityaccount/store-contract.js.map +1 -1
- package/dist/domain/identityaccount/store.d.ts +7 -5
- package/dist/domain/identityaccount/store.d.ts.map +1 -1
- package/dist/domain/identityaccount/store.js.map +1 -1
- package/dist/domain/platform/controller.d.ts +10 -0
- package/dist/domain/platform/controller.d.ts.map +1 -1
- package/dist/domain/platform/controller.js +2 -1
- package/dist/domain/platform/controller.js.map +1 -1
- package/dist/domain/platformclient/constants.d.ts +60 -0
- package/dist/domain/platformclient/constants.d.ts.map +1 -0
- package/dist/domain/platformclient/constants.js +78 -0
- package/dist/domain/platformclient/constants.js.map +1 -0
- package/dist/domain/platformclient/controller.d.ts +59 -0
- package/dist/domain/platformclient/controller.d.ts.map +1 -0
- package/dist/domain/platformclient/controller.js +191 -0
- package/dist/domain/platformclient/controller.js.map +1 -0
- package/dist/domain/platformclient/credentials.d.ts +13 -0
- package/dist/domain/platformclient/credentials.d.ts.map +1 -0
- package/dist/domain/platformclient/credentials.js +56 -0
- package/dist/domain/platformclient/credentials.js.map +1 -0
- package/dist/domain/platformclient/mint.d.ts +23 -0
- package/dist/domain/platformclient/mint.d.ts.map +1 -0
- package/dist/domain/platformclient/mint.js +254 -0
- package/dist/domain/platformclient/mint.js.map +1 -0
- package/dist/domain/platformclient/origin-guard.d.ts +9 -0
- package/dist/domain/platformclient/origin-guard.d.ts.map +1 -0
- package/dist/domain/platformclient/origin-guard.js +81 -0
- package/dist/domain/platformclient/origin-guard.js.map +1 -0
- package/dist/domain/platformclient/resource-store.d.ts +4 -0
- package/dist/domain/platformclient/resource-store.d.ts.map +1 -0
- package/dist/domain/platformclient/resource-store.js +117 -0
- package/dist/domain/platformclient/resource-store.js.map +1 -0
- package/dist/domain/platformclient/steps.d.ts +51 -0
- package/dist/domain/platformclient/steps.d.ts.map +1 -0
- package/dist/domain/platformclient/steps.js +339 -0
- package/dist/domain/platformclient/steps.js.map +1 -0
- package/dist/domain/platformclient/store-contract.d.ts +8 -0
- package/dist/domain/platformclient/store-contract.d.ts.map +1 -0
- package/dist/domain/platformclient/store-contract.js +208 -0
- package/dist/domain/platformclient/store-contract.js.map +1 -0
- package/dist/domain/platformclient/store.d.ts +58 -0
- package/dist/domain/platformclient/store.d.ts.map +1 -0
- package/dist/domain/platformclient/store.js +13 -0
- package/dist/domain/platformclient/store.js.map +1 -0
- package/dist/domain/platformclient/system-managed.d.ts +18 -0
- package/dist/domain/platformclient/system-managed.d.ts.map +1 -0
- package/dist/domain/platformclient/system-managed.js +80 -0
- package/dist/domain/platformclient/system-managed.js.map +1 -0
- package/dist/domain/platformclient/token-controller.d.ts +11 -0
- package/dist/domain/platformclient/token-controller.d.ts.map +1 -0
- package/dist/domain/platformclient/token-controller.js +32 -0
- package/dist/domain/platformclient/token-controller.js.map +1 -0
- package/dist/domain/platformclient/verifier.d.ts +10 -0
- package/dist/domain/platformclient/verifier.d.ts.map +1 -0
- package/dist/domain/platformclient/verifier.js +76 -0
- package/dist/domain/platformclient/verifier.js.map +1 -0
- package/dist/domain/session/list-index.d.ts +4 -0
- package/dist/domain/session/list-index.d.ts.map +1 -0
- package/dist/domain/session/list-index.js +26 -0
- package/dist/domain/session/list-index.js.map +1 -0
- package/dist/domain/session/steps.d.ts +7 -8
- package/dist/domain/session/steps.d.ts.map +1 -1
- package/dist/domain/session/steps.js +76 -78
- package/dist/domain/session/steps.js.map +1 -1
- package/dist/domain/workflowexecution/controller.d.ts.map +1 -1
- package/dist/domain/workflowexecution/controller.js +53 -55
- package/dist/domain/workflowexecution/controller.js.map +1 -1
- package/dist/domain/workflowexecution/execution-filter.d.ts +4 -0
- package/dist/domain/workflowexecution/execution-filter.d.ts.map +1 -1
- package/dist/domain/workflowexecution/execution-filter.js +11 -5
- package/dist/domain/workflowexecution/execution-filter.js.map +1 -1
- package/dist/domain/workflowexecution/get-execution-summary.d.ts.map +1 -1
- package/dist/domain/workflowexecution/get-execution-summary.js +23 -17
- package/dist/domain/workflowexecution/get-execution-summary.js.map +1 -1
- package/dist/domain/workflowexecution/list-index.d.ts +2 -0
- package/dist/domain/workflowexecution/list-index.d.ts.map +1 -0
- package/dist/domain/workflowexecution/list-index.js +21 -0
- package/dist/domain/workflowexecution/list-index.js.map +1 -0
- package/dist/domain/workflowexecution/list-pending-approvals.d.ts.map +1 -1
- package/dist/domain/workflowexecution/list-pending-approvals.js +69 -32
- package/dist/domain/workflowexecution/list-pending-approvals.js.map +1 -1
- package/dist/domain/workflowexecution/queries.d.ts +30 -4
- package/dist/domain/workflowexecution/queries.d.ts.map +1 -1
- package/dist/domain/workflowexecution/queries.js +76 -22
- package/dist/domain/workflowexecution/queries.js.map +1 -1
- package/dist/encryption/key-manager.d.ts +20 -3
- package/dist/encryption/key-manager.d.ts.map +1 -1
- package/dist/encryption/key-manager.js +64 -42
- package/dist/encryption/key-manager.js.map +1 -1
- package/dist/extensions/caller-guards.d.ts +8 -3
- package/dist/extensions/caller-guards.d.ts.map +1 -1
- package/dist/extensions/drivers.d.ts +37 -0
- package/dist/extensions/drivers.d.ts.map +1 -1
- package/dist/extensions/guest-token-minting.d.ts +26 -0
- package/dist/extensions/guest-token-minting.d.ts.map +1 -0
- package/dist/extensions/guest-token-minting.js +2 -0
- package/dist/extensions/guest-token-minting.js.map +1 -0
- package/dist/extensions/identity.d.ts +6 -4
- package/dist/extensions/identity.d.ts.map +1 -1
- package/dist/extensions/identity.js.map +1 -1
- package/dist/extensions/list-read-scope.d.ts +9 -12
- package/dist/extensions/list-read-scope.d.ts.map +1 -1
- package/dist/extensions/list-read-scope.js.map +1 -1
- package/dist/extensions/registry.d.ts +30 -1
- package/dist/extensions/registry.d.ts.map +1 -1
- package/dist/extensions/registry.js +34 -1
- package/dist/extensions/registry.js.map +1 -1
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline/interceptors/auth.d.ts +14 -0
- package/dist/pipeline/interceptors/auth.d.ts.map +1 -1
- package/dist/pipeline/interceptors/auth.js +24 -0
- package/dist/pipeline/interceptors/auth.js.map +1 -1
- package/dist/pipeline/steps/build-update-state.d.ts +11 -1
- package/dist/pipeline/steps/build-update-state.d.ts.map +1 -1
- package/dist/pipeline/steps/build-update-state.js +5 -2
- package/dist/pipeline/steps/build-update-state.js.map +1 -1
- package/dist/pipeline/steps/list-page.d.ts +63 -0
- package/dist/pipeline/steps/list-page.d.ts.map +1 -0
- package/dist/pipeline/steps/list-page.js +187 -0
- package/dist/pipeline/steps/list-page.js.map +1 -0
- package/dist/platformtoken/envelope.d.ts +100 -0
- package/dist/platformtoken/envelope.d.ts.map +1 -0
- package/dist/platformtoken/envelope.js +184 -0
- package/dist/platformtoken/envelope.js.map +1 -0
- package/dist/platformtoken/key-ring.d.ts +85 -0
- package/dist/platformtoken/key-ring.d.ts.map +1 -0
- package/dist/platformtoken/key-ring.js +164 -0
- package/dist/platformtoken/key-ring.js.map +1 -0
- package/dist/query/activity/handler.d.ts +6 -7
- package/dist/query/activity/handler.d.ts.map +1 -1
- package/dist/query/activity/handler.js +42 -59
- package/dist/query/activity/handler.js.map +1 -1
- package/dist/store/interface.d.ts +29 -0
- package/dist/store/interface.d.ts.map +1 -1
- package/dist/store/interface.js.map +1 -1
- package/dist/store/list-index.d.ts +123 -0
- package/dist/store/list-index.d.ts.map +1 -0
- package/dist/store/list-index.js +277 -0
- package/dist/store/list-index.js.map +1 -0
- package/dist/store/logger.d.ts +3 -0
- package/dist/store/logger.d.ts.map +1 -1
- package/dist/store/logger.js +5 -1
- package/dist/store/logger.js.map +1 -1
- package/dist/store/postgres/migrations.d.ts +10 -6
- package/dist/store/postgres/migrations.d.ts.map +1 -1
- package/dist/store/postgres/migrations.js +64 -6
- package/dist/store/postgres/migrations.js.map +1 -1
- package/dist/store/postgres/store.d.ts +26 -5
- package/dist/store/postgres/store.d.ts.map +1 -1
- package/dist/store/postgres/store.js +377 -22
- package/dist/store/postgres/store.js.map +1 -1
- package/dist/store/sqlite/migrations.d.ts +11 -5
- package/dist/store/sqlite/migrations.d.ts.map +1 -1
- package/dist/store/sqlite/migrations.js +50 -4
- package/dist/store/sqlite/migrations.js.map +1 -1
- package/dist/store/sqlite/store.d.ts +18 -3
- package/dist/store/sqlite/store.d.ts.map +1 -1
- package/dist/store/sqlite/store.js +321 -15
- package/dist/store/sqlite/store.js.map +1 -1
- package/package.json +6 -6
- package/src/authorization/README.md +1 -1
- package/src/authorization/__tests__/authorizer.test.ts +6 -2
- package/src/authorization/__tests__/drivers.ts +6 -1
- package/src/authorization/__tests__/wire-permissions.test.ts +1 -0
- package/src/authorization/authorizer.ts +11 -4
- package/src/authorization/model/__tests__/registry.test.ts +8 -1
- package/src/authorization/model/index.ts +6 -4
- package/src/authorization/model/oauth_app.ts +3 -2
- package/src/authorization/model/platform_client.ts +43 -0
- package/src/boot/__tests__/auth-enabled-composition.test.ts +2 -1
- package/src/boot/__tests__/list-indexes.test.ts +65 -0
- package/src/boot/__tests__/route-shadowing.test.ts +67 -0
- package/src/boot/compose.ts +113 -18
- package/src/boot/list-indexes.ts +25 -0
- package/src/boot/route-shadowing.ts +47 -0
- package/src/domain/agentexecution/__tests__/agentexecution.test.ts +85 -3
- package/src/domain/agentexecution/controller.ts +8 -10
- package/src/domain/agentexecution/list-index.ts +24 -0
- package/src/domain/agentexecution/steps.ts +118 -115
- package/src/domain/agentexecution/usage.ts +38 -17
- package/src/domain/artifact/controller.ts +28 -18
- package/src/domain/artifact/list-index.ts +22 -0
- package/src/domain/iampolicy/__tests__/membership.test.ts +7 -0
- package/src/domain/iampolicy/membership.ts +8 -2
- package/src/domain/identityaccount/__tests__/platform-client-accounts.test.ts +124 -0
- package/src/domain/identityaccount/__tests__/resource-store.test.ts +1 -0
- package/src/domain/identityaccount/constants.ts +20 -0
- package/src/domain/identityaccount/controller.ts +16 -4
- package/src/domain/identityaccount/operator.ts +1 -0
- package/src/domain/identityaccount/provisioning.ts +17 -0
- package/src/domain/identityaccount/resource-store.ts +9 -5
- package/src/domain/identityaccount/steps.ts +58 -3
- package/src/domain/identityaccount/store-contract.ts +51 -0
- package/src/domain/identityaccount/store.ts +7 -5
- package/src/domain/platform/__tests__/platform.test.ts +7 -1
- package/src/domain/platform/controller.ts +12 -1
- package/src/domain/platformclient/__tests__/controller.test.ts +397 -0
- package/src/domain/platformclient/__tests__/credentials.test.ts +46 -0
- package/src/domain/platformclient/__tests__/mint.test.ts +415 -0
- package/src/domain/platformclient/__tests__/resource-store.test.ts +140 -0
- package/src/domain/platformclient/__tests__/system-managed.test.ts +101 -0
- package/src/domain/platformclient/__tests__/verifier-and-guard.test.ts +207 -0
- package/src/domain/platformclient/constants.ts +120 -0
- package/src/domain/platformclient/controller.ts +449 -0
- package/src/domain/platformclient/credentials.ts +68 -0
- package/src/domain/platformclient/mint.ts +412 -0
- package/src/domain/platformclient/origin-guard.ts +117 -0
- package/src/domain/platformclient/resource-store.ts +150 -0
- package/src/domain/platformclient/steps.ts +472 -0
- package/src/domain/platformclient/store-contract.ts +318 -0
- package/src/domain/platformclient/store.ts +63 -0
- package/src/domain/platformclient/system-managed.ts +115 -0
- package/src/domain/platformclient/token-controller.ts +49 -0
- package/src/domain/platformclient/verifier.ts +106 -0
- package/src/domain/session/list-index.ts +28 -0
- package/src/domain/session/steps.ts +108 -123
- package/src/domain/workflowexecution/__tests__/list-read-scope-summaries.test.ts +155 -99
- package/src/domain/workflowexecution/__tests__/workflowexecution.test.ts +193 -31
- package/src/domain/workflowexecution/controller.ts +54 -82
- package/src/domain/workflowexecution/execution-filter.ts +20 -7
- package/src/domain/workflowexecution/get-execution-summary.ts +31 -24
- package/src/domain/workflowexecution/list-index.ts +22 -0
- package/src/domain/workflowexecution/list-pending-approvals.ts +82 -25
- package/src/domain/workflowexecution/queries.ts +134 -23
- package/src/encryption/key-manager.ts +87 -44
- package/src/extensions/__tests__/extension-composition.test.ts +3 -2
- package/src/extensions/__tests__/platform-client-composed.test.ts +288 -0
- package/src/extensions/__tests__/registry.test.ts +4 -1
- package/src/extensions/__tests__/tier-truthfulness.test.ts +8 -0
- package/src/extensions/caller-guards.ts +8 -3
- package/src/extensions/drivers.ts +37 -0
- package/src/extensions/guest-token-minting.ts +32 -0
- package/src/extensions/identity.ts +6 -4
- package/src/extensions/list-read-scope.ts +9 -12
- package/src/extensions/registry.ts +77 -3
- package/src/index.ts +65 -1
- package/src/pipeline/interceptors/auth.ts +27 -0
- package/src/pipeline/steps/__tests__/list-page.test.ts +186 -0
- package/src/pipeline/steps/__tests__/references.test.ts +2 -0
- package/src/pipeline/steps/build-update-state.ts +5 -2
- package/src/pipeline/steps/list-page.ts +284 -0
- package/src/platformtoken/__tests__/envelope.test.ts +277 -0
- package/src/platformtoken/__tests__/key-ring.test.ts +205 -0
- package/src/platformtoken/envelope.ts +276 -0
- package/src/platformtoken/key-ring.ts +266 -0
- package/src/query/activity/handler.ts +57 -78
- package/src/runnerauth/__tests__/runner-subject-composed.test.ts +9 -3
- package/src/store/README.md +51 -32
- package/src/store/__tests__/list-index.measure.test.ts +293 -0
- package/src/store/__tests__/list-index.test.ts +328 -0
- package/src/store/__tests__/store-contract.ts +346 -3
- package/src/store/interface.ts +39 -0
- package/src/store/list-index.ts +465 -0
- package/src/store/logger.ts +8 -1
- package/src/store/postgres/__tests__/list-index-repair.test.ts +133 -0
- package/src/store/postgres/__tests__/migrations.test.ts +27 -19
- package/src/store/postgres/__tests__/store-contract.test.ts +50 -3
- package/src/store/postgres/migrations.ts +69 -7
- package/src/store/postgres/store.ts +485 -29
- package/src/store/sqlite/__tests__/migrations.test.ts +51 -7
- package/src/store/sqlite/__tests__/store-contract.test.ts +70 -16
- package/src/store/sqlite/__tests__/support.ts +12 -3
- package/src/store/sqlite/migrations.ts +57 -6
- package/src/store/sqlite/store.ts +462 -21
|
@@ -18,14 +18,24 @@
|
|
|
18
18
|
* list-mode newest-first at exactly 1.0 — search-mode ranking ORDER is
|
|
19
19
|
* deliberately NOT asserted here, it is driver-relative), the two-phase
|
|
20
20
|
* signal-dedupe hold (oss#442), OAuth grants, once-only pending-state
|
|
21
|
-
* redemption with its 10-minute TTL,
|
|
21
|
+
* redemption with its 10-minute TTL, the closed-store failure mode, and
|
|
22
|
+
* the list index (../list-index.ts): one organization's or one parent's
|
|
23
|
+
* rows newest first, a cursor walk with no gap and no duplicate, keys
|
|
24
|
+
* that follow an update and vanish with a delete, and exactness whoever
|
|
25
|
+
* wrote the row — a row written the way a binary that does not know the
|
|
26
|
+
* index writes it is read from its bytes and repaired, the reconciliation
|
|
27
|
+
* at open leaves nothing unproven, a row written under another revision
|
|
28
|
+
* of a declaration is re-derived, and an undecodable one is skipped.
|
|
22
29
|
*
|
|
23
30
|
* Driver-physical behavior (column layouts, FTS5/tsvector internals,
|
|
24
|
-
* migration chains) stays in each driver's own
|
|
31
|
+
* migration chains, the repair's lock ordering) stays in each driver's own
|
|
32
|
+
* tests.
|
|
25
33
|
*/
|
|
26
|
-
import { fromBinary, toBinary } from "@bufbuild/protobuf";
|
|
34
|
+
import { create, fromBinary, toBinary } from "@bufbuild/protobuf";
|
|
27
35
|
import { afterEach, beforeEach, describe, expect, it } from "vitest";
|
|
28
36
|
|
|
37
|
+
import { SessionSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
38
|
+
import type { Session } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
|
|
29
39
|
import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
30
40
|
import { OrganizationSchema } from "@stigmer/protos/ai/stigmer/tenancy/organization/v1/api_pb";
|
|
31
41
|
|
|
@@ -39,13 +49,53 @@ import type {
|
|
|
39
49
|
PendingOAuthState,
|
|
40
50
|
SearchIndexEntry,
|
|
41
51
|
Store,
|
|
52
|
+
StoreOpenOptions,
|
|
42
53
|
WorkflowExecutionEventRecord,
|
|
43
54
|
} from "../interface.js";
|
|
55
|
+
import { declareListIndex, field, label } from "../list-index.js";
|
|
56
|
+
import type { ListIndexRow } from "../list-index.js";
|
|
44
57
|
import { makeOrganization } from "./support.js";
|
|
45
58
|
|
|
59
|
+
/** The kit's own declaration, so the arms do not depend on the server's list. */
|
|
60
|
+
export const CONTRACT_SESSION_INDEX = declareListIndex({
|
|
61
|
+
kind: ApiResourceKind.session,
|
|
62
|
+
schema: SessionSchema,
|
|
63
|
+
revision: 1,
|
|
64
|
+
keys: {
|
|
65
|
+
agent_instance: field("spec.agent_instance_id"),
|
|
66
|
+
channel: label("stigmer.ai/channel-id"),
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
/** What every contract store opens with. */
|
|
71
|
+
export const CONTRACT_STORE_OPTIONS: StoreOpenOptions = {
|
|
72
|
+
listIndexes: [CONTRACT_SESSION_INDEX],
|
|
73
|
+
};
|
|
74
|
+
|
|
46
75
|
/** One fresh, isolated store per test, plus the driver escape hatches. */
|
|
47
76
|
export interface StoreContractFixture {
|
|
48
77
|
store: Store;
|
|
78
|
+
/**
|
|
79
|
+
* Writes a resource exactly as a binary that does not know the list
|
|
80
|
+
* index writes it — the row and `updated_at`, nothing else — the way
|
|
81
|
+
* the old pod writes while a roll overlaps it with the new one.
|
|
82
|
+
*/
|
|
83
|
+
writeAsOlderBinary(
|
|
84
|
+
kind: ApiResourceKind,
|
|
85
|
+
id: string,
|
|
86
|
+
data: Uint8Array,
|
|
87
|
+
): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Counts a kind's rows whose list facts are not proven current under
|
|
90
|
+
* `revision`, as the driver judges it; without a revision (an undeclared
|
|
91
|
+
* kind carries none), its unstamped rows.
|
|
92
|
+
*/
|
|
93
|
+
countUnproven(kind: ApiResourceKind, revision?: number): Promise<number>;
|
|
94
|
+
/**
|
|
95
|
+
* Opens a second store over the same database (running its
|
|
96
|
+
* reconciliation at open); the fixture closes it at cleanup.
|
|
97
|
+
*/
|
|
98
|
+
openAnother(options: StoreOpenOptions): Promise<Store>;
|
|
49
99
|
/**
|
|
50
100
|
* Ages a signal-dedupe row directly (crash-recovery arm: a hold whose
|
|
51
101
|
* delivery died must self-heal at the next claim). The interface has no
|
|
@@ -78,6 +128,10 @@ function event(
|
|
|
78
128
|
};
|
|
79
129
|
}
|
|
80
130
|
|
|
131
|
+
/**
|
|
132
|
+
* Every driver passes its fixture factory; the factory opens its store
|
|
133
|
+
* with `CONTRACT_STORE_OPTIONS`.
|
|
134
|
+
*/
|
|
81
135
|
export function describeStoreContract(
|
|
82
136
|
makeFixture: () => Promise<StoreContractFixture>,
|
|
83
137
|
): void {
|
|
@@ -1523,6 +1577,295 @@ export function describeStoreContract(
|
|
|
1523
1577
|
});
|
|
1524
1578
|
});
|
|
1525
1579
|
|
|
1580
|
+
describe("list index", () => {
|
|
1581
|
+
const SESSION = ApiResourceKind.session;
|
|
1582
|
+
|
|
1583
|
+
function session(
|
|
1584
|
+
id: string,
|
|
1585
|
+
org: string,
|
|
1586
|
+
createdSeconds: number | undefined,
|
|
1587
|
+
extras: { agentInstanceId?: string; channel?: string } = {},
|
|
1588
|
+
): Session {
|
|
1589
|
+
return create(SessionSchema, {
|
|
1590
|
+
metadata: {
|
|
1591
|
+
id,
|
|
1592
|
+
org,
|
|
1593
|
+
labels:
|
|
1594
|
+
extras.channel === undefined
|
|
1595
|
+
? {}
|
|
1596
|
+
: { "stigmer.ai/channel-id": extras.channel },
|
|
1597
|
+
},
|
|
1598
|
+
spec: { agentInstanceId: extras.agentInstanceId ?? "" },
|
|
1599
|
+
status:
|
|
1600
|
+
createdSeconds === undefined
|
|
1601
|
+
? {}
|
|
1602
|
+
: {
|
|
1603
|
+
audit: {
|
|
1604
|
+
specAudit: {
|
|
1605
|
+
createdAt: { seconds: BigInt(createdSeconds), nanos: 0 },
|
|
1606
|
+
},
|
|
1607
|
+
},
|
|
1608
|
+
},
|
|
1609
|
+
});
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
async function save(s: Session): Promise<void> {
|
|
1613
|
+
await fx.store.saveResource(SESSION, s.metadata!.id, SessionSchema, s);
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
function ids(rows: ReadonlyArray<ListIndexRow>): string[] {
|
|
1617
|
+
return rows.map((r) => r.id);
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
it("reads one organization's rows newest first, ids breaking ties, unstamped last", async () => {
|
|
1621
|
+
await save(session("ses_a", "acme", 100));
|
|
1622
|
+
await save(session("ses_b", "acme", 300));
|
|
1623
|
+
await save(session("ses_c", "acme", 300));
|
|
1624
|
+
await save(session("ses_d", "acme", undefined));
|
|
1625
|
+
await save(session("ses_e", "other", 500));
|
|
1626
|
+
|
|
1627
|
+
const rows = await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1628
|
+
org: "acme",
|
|
1629
|
+
});
|
|
1630
|
+
expect(ids(rows)).toEqual(["ses_c", "ses_b", "ses_a", "ses_d"]);
|
|
1631
|
+
expect(
|
|
1632
|
+
fromBinary(SessionSchema, rows[0]!.data).metadata?.id,
|
|
1633
|
+
"the row's bytes ride the result",
|
|
1634
|
+
).toBe("ses_c");
|
|
1635
|
+
expect(
|
|
1636
|
+
ids(await fx.store.queryResources(CONTRACT_SESSION_INDEX, {})),
|
|
1637
|
+
"no organization reads every organization",
|
|
1638
|
+
).toEqual(["ses_e", "ses_c", "ses_b", "ses_a", "ses_d"]);
|
|
1639
|
+
});
|
|
1640
|
+
|
|
1641
|
+
it("walks every row by cursor with no gap and no duplicate", async () => {
|
|
1642
|
+
for (let i = 0; i < 7; i++) {
|
|
1643
|
+
await save(session(`ses_${i}`, "acme", i % 3 === 0 ? 10 : 100 + i));
|
|
1644
|
+
}
|
|
1645
|
+
const all = ids(
|
|
1646
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, { org: "acme" }),
|
|
1647
|
+
);
|
|
1648
|
+
|
|
1649
|
+
const walked: string[] = [];
|
|
1650
|
+
let after: ListIndexRow["cursor"] | undefined;
|
|
1651
|
+
for (;;) {
|
|
1652
|
+
const page = await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1653
|
+
org: "acme",
|
|
1654
|
+
limit: 3,
|
|
1655
|
+
...(after === undefined ? {} : { after }),
|
|
1656
|
+
});
|
|
1657
|
+
walked.push(...ids(page));
|
|
1658
|
+
if (page.length < 3) {
|
|
1659
|
+
break;
|
|
1660
|
+
}
|
|
1661
|
+
after = page[page.length - 1]!.cursor;
|
|
1662
|
+
}
|
|
1663
|
+
expect(walked).toEqual(all);
|
|
1664
|
+
expect(new Set(walked).size).toBe(7);
|
|
1665
|
+
});
|
|
1666
|
+
|
|
1667
|
+
it("reads a parent's rows through a key, or through any of several", async () => {
|
|
1668
|
+
await save(session("ses_1", "acme", 1, { agentInstanceId: "ain_1" }));
|
|
1669
|
+
await save(session("ses_2", "acme", 2, { channel: "ach_1" }));
|
|
1670
|
+
await save(session("ses_3", "acme", 3, { agentInstanceId: "ain_2" }));
|
|
1671
|
+
|
|
1672
|
+
expect(
|
|
1673
|
+
ids(
|
|
1674
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1675
|
+
anyKey: [{ name: "agent_instance", value: "ain_1" }],
|
|
1676
|
+
}),
|
|
1677
|
+
),
|
|
1678
|
+
).toEqual(["ses_1"]);
|
|
1679
|
+
expect(
|
|
1680
|
+
ids(
|
|
1681
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1682
|
+
anyKey: [
|
|
1683
|
+
{ name: "agent_instance", value: "ain_1" },
|
|
1684
|
+
{ name: "channel", value: "ach_1" },
|
|
1685
|
+
],
|
|
1686
|
+
}),
|
|
1687
|
+
),
|
|
1688
|
+
).toEqual(["ses_2", "ses_1"]);
|
|
1689
|
+
expect(
|
|
1690
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, { anyKey: [] }),
|
|
1691
|
+
"an empty key list matches nothing",
|
|
1692
|
+
).toEqual([]);
|
|
1693
|
+
});
|
|
1694
|
+
|
|
1695
|
+
it("keeps rows created at or after a bound, and rows with no stamp", async () => {
|
|
1696
|
+
await save(session("ses_old", "acme", 100));
|
|
1697
|
+
await save(session("ses_new", "acme", 200));
|
|
1698
|
+
await save(session("ses_unstamped", "acme", undefined));
|
|
1699
|
+
expect(
|
|
1700
|
+
ids(
|
|
1701
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1702
|
+
createdAtOrAfter: "1970-01-01T00:02:30.000000000Z",
|
|
1703
|
+
}),
|
|
1704
|
+
),
|
|
1705
|
+
).toEqual(["ses_new", "ses_unstamped"]);
|
|
1706
|
+
});
|
|
1707
|
+
|
|
1708
|
+
it("follows a key an update changes, and forgets a deleted row", async () => {
|
|
1709
|
+
await save(session("ses_1", "acme", 1, { agentInstanceId: "ain_1" }));
|
|
1710
|
+
await fx.store.updateResource(SESSION, "ses_1", SessionSchema, (s) => {
|
|
1711
|
+
s.spec!.agentInstanceId = "ain_2";
|
|
1712
|
+
});
|
|
1713
|
+
const byInstance = (value: string) =>
|
|
1714
|
+
fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1715
|
+
anyKey: [{ name: "agent_instance", value }],
|
|
1716
|
+
});
|
|
1717
|
+
expect(ids(await byInstance("ain_1"))).toEqual([]);
|
|
1718
|
+
expect(ids(await byInstance("ain_2"))).toEqual(["ses_1"]);
|
|
1719
|
+
|
|
1720
|
+
await fx.store.deleteResource(SESSION, "ses_1");
|
|
1721
|
+
expect(ids(await byInstance("ain_2"))).toEqual([]);
|
|
1722
|
+
expect(await fx.store.queryResources(CONTRACT_SESSION_INDEX, {})).toEqual(
|
|
1723
|
+
[],
|
|
1724
|
+
);
|
|
1725
|
+
});
|
|
1726
|
+
|
|
1727
|
+
it("reads a row written by a binary that does not know the index from its bytes, and repairs it", async () => {
|
|
1728
|
+
await save(
|
|
1729
|
+
session("ses_moved", "acme", 100, { agentInstanceId: "ain_1" }),
|
|
1730
|
+
);
|
|
1731
|
+
// The older binary rewrites one row into another organization and
|
|
1732
|
+
// instance, and creates another row outright.
|
|
1733
|
+
await fx.writeAsOlderBinary(
|
|
1734
|
+
SESSION,
|
|
1735
|
+
"ses_moved",
|
|
1736
|
+
toBinary(
|
|
1737
|
+
SessionSchema,
|
|
1738
|
+
session("ses_moved", "other", 100, { agentInstanceId: "ain_2" }),
|
|
1739
|
+
),
|
|
1740
|
+
);
|
|
1741
|
+
await fx.writeAsOlderBinary(
|
|
1742
|
+
SESSION,
|
|
1743
|
+
"ses_created",
|
|
1744
|
+
toBinary(SessionSchema, session("ses_created", "acme", 50)),
|
|
1745
|
+
);
|
|
1746
|
+
await save(session("ses_proven", "acme", 75));
|
|
1747
|
+
expect(await fx.countUnproven(SESSION, 1)).toBe(2);
|
|
1748
|
+
|
|
1749
|
+
expect(
|
|
1750
|
+
ids(
|
|
1751
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1752
|
+
org: "acme",
|
|
1753
|
+
}),
|
|
1754
|
+
),
|
|
1755
|
+
).toEqual(["ses_proven", "ses_created"]);
|
|
1756
|
+
expect(
|
|
1757
|
+
ids(
|
|
1758
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1759
|
+
anyKey: [{ name: "agent_instance", value: "ain_2" }],
|
|
1760
|
+
}),
|
|
1761
|
+
),
|
|
1762
|
+
).toEqual(["ses_moved"]);
|
|
1763
|
+
expect(
|
|
1764
|
+
await fx.countUnproven(SESSION, 1),
|
|
1765
|
+
"both rows repaired by the read",
|
|
1766
|
+
).toBe(0);
|
|
1767
|
+
expect(
|
|
1768
|
+
ids(
|
|
1769
|
+
await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1770
|
+
org: "other",
|
|
1771
|
+
}),
|
|
1772
|
+
),
|
|
1773
|
+
"and read through the index once repaired",
|
|
1774
|
+
).toEqual(["ses_moved"]);
|
|
1775
|
+
});
|
|
1776
|
+
|
|
1777
|
+
it("merges an unproven row into the right page of a cursor walk", async () => {
|
|
1778
|
+
for (let i = 0; i < 4; i++) {
|
|
1779
|
+
await save(session(`ses_${i}`, "acme", 100 + i));
|
|
1780
|
+
}
|
|
1781
|
+
await fx.writeAsOlderBinary(
|
|
1782
|
+
SESSION,
|
|
1783
|
+
"ses_mid",
|
|
1784
|
+
toBinary(SessionSchema, session("ses_mid", "acme", 102)),
|
|
1785
|
+
);
|
|
1786
|
+
const first = await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1787
|
+
org: "acme",
|
|
1788
|
+
limit: 2,
|
|
1789
|
+
});
|
|
1790
|
+
const second = await fx.store.queryResources(CONTRACT_SESSION_INDEX, {
|
|
1791
|
+
org: "acme",
|
|
1792
|
+
limit: 2,
|
|
1793
|
+
after: first[1]!.cursor,
|
|
1794
|
+
});
|
|
1795
|
+
expect([...ids(first), ...ids(second)]).toEqual([
|
|
1796
|
+
"ses_3",
|
|
1797
|
+
"ses_mid",
|
|
1798
|
+
"ses_2",
|
|
1799
|
+
"ses_1",
|
|
1800
|
+
]);
|
|
1801
|
+
});
|
|
1802
|
+
|
|
1803
|
+
it("skips an unproven row that does not decode", async () => {
|
|
1804
|
+
await save(session("ses_good", "acme", 1));
|
|
1805
|
+
await fx.writeAsOlderBinary(
|
|
1806
|
+
SESSION,
|
|
1807
|
+
"ses_garbage",
|
|
1808
|
+
new Uint8Array([0xff, 0xff, 0xff]),
|
|
1809
|
+
);
|
|
1810
|
+
expect(
|
|
1811
|
+
ids(await fx.store.queryResources(CONTRACT_SESSION_INDEX, {})),
|
|
1812
|
+
).toEqual(["ses_good"]);
|
|
1813
|
+
});
|
|
1814
|
+
|
|
1815
|
+
it("leaves nothing unproven once a store has opened", async () => {
|
|
1816
|
+
await fx.writeAsOlderBinary(
|
|
1817
|
+
SESSION,
|
|
1818
|
+
"ses_1",
|
|
1819
|
+
toBinary(SessionSchema, session("ses_1", "acme", 1)),
|
|
1820
|
+
);
|
|
1821
|
+
await fx.writeAsOlderBinary(
|
|
1822
|
+
KIND,
|
|
1823
|
+
"acme",
|
|
1824
|
+
toBinary(OrganizationSchema, makeOrganization({ id: "acme" })),
|
|
1825
|
+
);
|
|
1826
|
+
expect(await fx.countUnproven(SESSION, 1)).toBe(1);
|
|
1827
|
+
|
|
1828
|
+
await fx.openAnother(CONTRACT_STORE_OPTIONS);
|
|
1829
|
+
expect(
|
|
1830
|
+
await fx.countUnproven(SESSION, 1),
|
|
1831
|
+
"a declared kind is derived",
|
|
1832
|
+
).toBe(0);
|
|
1833
|
+
expect(
|
|
1834
|
+
await fx.countUnproven(KIND),
|
|
1835
|
+
"an undeclared kind is stamped, so it never widens the unproven set",
|
|
1836
|
+
).toBe(0);
|
|
1837
|
+
});
|
|
1838
|
+
|
|
1839
|
+
it("re-derives rows written under another revision of a declaration", async () => {
|
|
1840
|
+
await save(session("ses_1", "acme", 1));
|
|
1841
|
+
const revised = declareListIndex({
|
|
1842
|
+
...CONTRACT_SESSION_INDEX,
|
|
1843
|
+
revision: 2,
|
|
1844
|
+
keys: { org_copy: field("metadata.org") },
|
|
1845
|
+
});
|
|
1846
|
+
expect(await fx.countUnproven(SESSION, 2)).toBe(1);
|
|
1847
|
+
const other = await fx.openAnother({ listIndexes: [revised] });
|
|
1848
|
+
expect(await fx.countUnproven(SESSION, 2)).toBe(0);
|
|
1849
|
+
expect(
|
|
1850
|
+
ids(
|
|
1851
|
+
await other.queryResources(revised, {
|
|
1852
|
+
anyKey: [{ name: "org_copy", value: "acme" }],
|
|
1853
|
+
}),
|
|
1854
|
+
),
|
|
1855
|
+
).toEqual(["ses_1"]);
|
|
1856
|
+
});
|
|
1857
|
+
|
|
1858
|
+
it("refuses a declaration it was not opened with, and a limit no caller means", async () => {
|
|
1859
|
+
const stranger = declareListIndex({ ...CONTRACT_SESSION_INDEX });
|
|
1860
|
+
await expect(fx.store.queryResources(stranger, {})).rejects.toThrow(
|
|
1861
|
+
"list index for session is not registered with this store",
|
|
1862
|
+
);
|
|
1863
|
+
await expect(
|
|
1864
|
+
fx.store.queryResources(CONTRACT_SESSION_INDEX, { limit: 0 }),
|
|
1865
|
+
).rejects.toThrow("list index limit must be a positive integer, got 0");
|
|
1866
|
+
});
|
|
1867
|
+
});
|
|
1868
|
+
|
|
1526
1869
|
describe("lifecycle", () => {
|
|
1527
1870
|
it("every method fails with 'store is closed' after close; close is idempotent", async () => {
|
|
1528
1871
|
await fx.store.close();
|
package/src/store/interface.ts
CHANGED
|
@@ -30,6 +30,12 @@ import type { DescMessage, MessageShape } from "@bufbuild/protobuf";
|
|
|
30
30
|
|
|
31
31
|
import type { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
|
|
32
32
|
|
|
33
|
+
import type {
|
|
34
|
+
ListIndexDeclaration,
|
|
35
|
+
ListIndexQuery,
|
|
36
|
+
ListIndexRow,
|
|
37
|
+
} from "./list-index.js";
|
|
38
|
+
|
|
33
39
|
// =============================================================================
|
|
34
40
|
// Sentinel errors
|
|
35
41
|
// =============================================================================
|
|
@@ -434,6 +440,16 @@ export interface RawResourceDocument {
|
|
|
434
440
|
readonly data: Uint8Array;
|
|
435
441
|
}
|
|
436
442
|
|
|
443
|
+
/**
|
|
444
|
+
* What a driver opens with beyond its connection. `listIndexes` is the
|
|
445
|
+
* composition root's one list of list-index declarations
|
|
446
|
+
* (boot/list-indexes.ts); a store opened without it keeps no list index
|
|
447
|
+
* and refuses every `queryResources`.
|
|
448
|
+
*/
|
|
449
|
+
export interface StoreOpenOptions {
|
|
450
|
+
readonly listIndexes?: ReadonlyArray<ListIndexDeclaration>;
|
|
451
|
+
}
|
|
452
|
+
|
|
437
453
|
// =============================================================================
|
|
438
454
|
// The store contract
|
|
439
455
|
// =============================================================================
|
|
@@ -492,6 +508,29 @@ export interface Store {
|
|
|
492
508
|
*/
|
|
493
509
|
listResources(kind: ApiResourceKind): Promise<Uint8Array[]>;
|
|
494
510
|
|
|
511
|
+
/**
|
|
512
|
+
* The rows of a list-indexed kind that match the query, newest first on
|
|
513
|
+
* (creation instant, id) compared as bytes, strictly after
|
|
514
|
+
* `query.after`, at most `query.limit` of them (list-index.ts states the
|
|
515
|
+
* order and the predicates). Fewer than `limit` rows means there are no
|
|
516
|
+
* more.
|
|
517
|
+
*
|
|
518
|
+
* EXACT whoever wrote the rows: a row whose index facts are proven
|
|
519
|
+
* current is answered through the index; every other row of the kind —
|
|
520
|
+
* one written by a binary that does not know the index, or under
|
|
521
|
+
* another revision of the declaration — is evaluated from its bytes with
|
|
522
|
+
* the declaration, and repaired by a compare-and-set on those bytes so a
|
|
523
|
+
* newer write is never overwritten. An unproven row that cannot be
|
|
524
|
+
* decoded is skipped and logged, as the list lanes skip one.
|
|
525
|
+
*
|
|
526
|
+
* Throws when `declaration` is not the one this store was opened with,
|
|
527
|
+
* or on a limit that is not a positive integer.
|
|
528
|
+
*/
|
|
529
|
+
queryResources<K extends string>(
|
|
530
|
+
declaration: ListIndexDeclaration<K>,
|
|
531
|
+
query: ListIndexQuery<K>,
|
|
532
|
+
): Promise<ListIndexRow[]>;
|
|
533
|
+
|
|
495
534
|
/** Removes a resource; NO error if it does not exist. */
|
|
496
535
|
deleteResource(kind: ApiResourceKind, id: string): Promise<void>;
|
|
497
536
|
|