@opendatalabs/personal-server-ts-core 1.33.8 → 1.34.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/additions/budget.d.ts +28 -0
- package/dist/additions/budget.d.ts.map +1 -0
- package/dist/additions/budget.js +119 -0
- package/dist/additions/budget.js.map +1 -0
- package/dist/additions/durable.d.ts +64 -0
- package/dist/additions/durable.d.ts.map +1 -0
- package/dist/additions/durable.js +591 -0
- package/dist/additions/durable.js.map +1 -0
- package/dist/additions/first-added.d.ts +32 -48
- package/dist/additions/first-added.d.ts.map +1 -1
- package/dist/additions/first-added.js +68 -123
- package/dist/additions/first-added.js.map +1 -1
- package/dist/additions/index.d.ts +3 -0
- package/dist/additions/index.d.ts.map +1 -1
- package/dist/additions/index.js +3 -0
- package/dist/additions/index.js.map +1 -1
- package/dist/additions/ledger-store.js +1 -1
- package/dist/additions/record-rules.d.ts.map +1 -1
- package/dist/additions/record-rules.js +7 -0
- package/dist/additions/record-rules.js.map +1 -1
- package/dist/additions/summary.d.ts +88 -1
- package/dist/additions/summary.d.ts.map +1 -1
- package/dist/additions/summary.js +173 -8
- package/dist/additions/summary.js.map +1 -1
- package/dist/additions/version-inventory.d.ts +80 -0
- package/dist/additions/version-inventory.d.ts.map +1 -0
- package/dist/additions/version-inventory.js +232 -0
- package/dist/additions/version-inventory.js.map +1 -0
- package/dist/api/index.d.ts +70 -2
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +506 -79
- package/dist/api/index.js.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/request.d.ts +6 -0
- package/dist/auth/request.d.ts.map +1 -1
- package/dist/auth/request.js +66 -4
- package/dist/auth/request.js.map +1 -1
- package/dist/contracts/data.d.ts +54 -8
- package/dist/contracts/data.d.ts.map +1 -1
- package/dist/contracts/data.js +178 -35
- package/dist/contracts/data.js.map +1 -1
- package/dist/contracts/index.d.ts +1 -1
- package/dist/contracts/index.d.ts.map +1 -1
- package/dist/derivatives/registration.d.ts +0 -5
- package/dist/derivatives/registration.d.ts.map +1 -1
- package/dist/derivatives/registration.js +2 -1
- package/dist/derivatives/registration.js.map +1 -1
- package/dist/errors/pdpp-catalog.d.ts +36 -0
- package/dist/errors/pdpp-catalog.d.ts.map +1 -0
- package/dist/errors/pdpp-catalog.js +86 -0
- package/dist/errors/pdpp-catalog.js.map +1 -0
- package/dist/grants/index.d.ts +2 -0
- package/dist/grants/index.d.ts.map +1 -1
- package/dist/grants/index.js +4 -0
- package/dist/grants/index.js.map +1 -1
- package/dist/grants/pdpp-binding-store.d.ts +89 -0
- package/dist/grants/pdpp-binding-store.d.ts.map +1 -0
- package/dist/grants/pdpp-binding-store.js +112 -0
- package/dist/grants/pdpp-binding-store.js.map +1 -0
- package/dist/grants/pdpp-binding.d.ts +169 -0
- package/dist/grants/pdpp-binding.d.ts.map +1 -0
- package/dist/grants/pdpp-binding.js +236 -0
- package/dist/grants/pdpp-binding.js.map +1 -0
- package/dist/legacy-projection/bindings.d.ts +28 -1
- package/dist/legacy-projection/bindings.d.ts.map +1 -1
- package/dist/legacy-projection/bindings.js +622 -189
- package/dist/legacy-projection/bindings.js.map +1 -1
- package/dist/legacy-projection/claude-source-record.d.ts +22 -0
- package/dist/legacy-projection/claude-source-record.d.ts.map +1 -0
- package/dist/legacy-projection/claude-source-record.js +360 -0
- package/dist/legacy-projection/claude-source-record.js.map +1 -0
- package/dist/legacy-projection/declared-text.d.ts +41 -0
- package/dist/legacy-projection/declared-text.d.ts.map +1 -0
- package/dist/legacy-projection/declared-text.js +199 -0
- package/dist/legacy-projection/declared-text.js.map +1 -0
- package/dist/legacy-projection/github-browser-bindings.d.ts.map +1 -1
- package/dist/legacy-projection/github-browser-bindings.js +89 -5
- package/dist/legacy-projection/github-browser-bindings.js.map +1 -1
- package/dist/legacy-projection/github-legacy-fields.d.ts +6 -0
- package/dist/legacy-projection/github-legacy-fields.d.ts.map +1 -0
- package/dist/legacy-projection/github-legacy-fields.js +202 -0
- package/dist/legacy-projection/github-legacy-fields.js.map +1 -0
- package/dist/legacy-projection/index.d.ts +5 -1
- package/dist/legacy-projection/index.d.ts.map +1 -1
- package/dist/legacy-projection/index.js +55 -1
- package/dist/legacy-projection/index.js.map +1 -1
- package/dist/legacy-projection/oura-browser-bindings.d.ts.map +1 -1
- package/dist/legacy-projection/oura-browser-bindings.js +43 -41
- package/dist/legacy-projection/oura-browser-bindings.js.map +1 -1
- package/dist/legacy-projection/types.d.ts +38 -2
- package/dist/legacy-projection/types.d.ts.map +1 -1
- package/dist/mcp/read-client.d.ts.map +1 -1
- package/dist/mcp/read-client.js +10 -1
- package/dist/mcp/read-client.js.map +1 -1
- package/dist/mcp/resources.d.ts.map +1 -1
- package/dist/mcp/resources.js +3 -0
- package/dist/mcp/resources.js.map +1 -1
- package/dist/mcp/tools.d.ts.map +1 -1
- package/dist/mcp/tools.js +11 -2
- package/dist/mcp/tools.js.map +1 -1
- package/dist/pdpp/approval.d.ts +271 -0
- package/dist/pdpp/approval.d.ts.map +1 -0
- package/dist/pdpp/approval.js +467 -0
- package/dist/pdpp/approval.js.map +1 -0
- package/dist/pdpp/client-identity.d.ts +88 -0
- package/dist/pdpp/client-identity.d.ts.map +1 -0
- package/dist/pdpp/client-identity.js +196 -0
- package/dist/pdpp/client-identity.js.map +1 -0
- package/dist/pdpp/client-metadata.d.ts +95 -0
- package/dist/pdpp/client-metadata.d.ts.map +1 -0
- package/dist/pdpp/client-metadata.js +96 -0
- package/dist/pdpp/client-metadata.js.map +1 -0
- package/dist/pdpp/commitments.d.ts +75 -0
- package/dist/pdpp/commitments.d.ts.map +1 -0
- package/dist/pdpp/commitments.js +113 -0
- package/dist/pdpp/commitments.js.map +1 -0
- package/dist/pdpp/declaration.d.ts +118 -0
- package/dist/pdpp/declaration.d.ts.map +1 -0
- package/dist/pdpp/declaration.js +836 -0
- package/dist/pdpp/declaration.js.map +1 -0
- package/dist/pdpp/index.d.ts +37 -0
- package/dist/pdpp/index.d.ts.map +1 -0
- package/dist/pdpp/index.js +23 -0
- package/dist/pdpp/index.js.map +1 -0
- package/dist/pdpp/issuance.d.ts +126 -0
- package/dist/pdpp/issuance.d.ts.map +1 -0
- package/dist/pdpp/issuance.js +180 -0
- package/dist/pdpp/issuance.js.map +1 -0
- package/dist/pdpp/pkce.d.ts +53 -0
- package/dist/pdpp/pkce.d.ts.map +1 -0
- package/dist/pdpp/pkce.js +109 -0
- package/dist/pdpp/pkce.js.map +1 -0
- package/dist/pdpp/redirect.d.ts +60 -0
- package/dist/pdpp/redirect.d.ts.map +1 -0
- package/dist/pdpp/redirect.js +125 -0
- package/dist/pdpp/redirect.js.map +1 -0
- package/dist/pdpp/resolve.d.ts +109 -0
- package/dist/pdpp/resolve.d.ts.map +1 -0
- package/dist/pdpp/resolve.js +393 -0
- package/dist/pdpp/resolve.js.map +1 -0
- package/dist/pdpp/review.d.ts +280 -0
- package/dist/pdpp/review.d.ts.map +1 -0
- package/dist/pdpp/review.js +205 -0
- package/dist/pdpp/review.js.map +1 -0
- package/dist/pdpp/selection.d.ts +50 -0
- package/dist/pdpp/selection.d.ts.map +1 -0
- package/dist/pdpp/selection.js +442 -0
- package/dist/pdpp/selection.js.map +1 -0
- package/dist/pdpp/store.d.ts +228 -0
- package/dist/pdpp/store.d.ts.map +1 -0
- package/dist/pdpp/store.js +542 -0
- package/dist/pdpp/store.js.map +1 -0
- package/dist/pdpp/tokens.d.ts +181 -0
- package/dist/pdpp/tokens.d.ts.map +1 -0
- package/dist/pdpp/tokens.js +419 -0
- package/dist/pdpp/tokens.js.map +1 -0
- package/dist/pdpp/types.d.ts +441 -0
- package/dist/pdpp/types.d.ts.map +1 -0
- package/dist/pdpp/types.js +61 -0
- package/dist/pdpp/types.js.map +1 -0
- package/dist/pdpp-version.d.ts +28 -0
- package/dist/pdpp-version.d.ts.map +1 -0
- package/dist/pdpp-version.js +28 -0
- package/dist/pdpp-version.js.map +1 -0
- package/dist/policy/data-read.d.ts +24 -0
- package/dist/policy/data-read.d.ts.map +1 -1
- package/dist/policy/data-read.js +60 -3
- package/dist/policy/data-read.js.map +1 -1
- package/dist/policy/data-write.d.ts.map +1 -1
- package/dist/policy/data-write.js +3 -0
- package/dist/policy/data-write.js.map +1 -1
- package/dist/policy/index.d.ts +1 -0
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +1 -0
- package/dist/policy/index.js.map +1 -1
- package/dist/policy/reserved-scopes.d.ts +3 -0
- package/dist/policy/reserved-scopes.d.ts.map +1 -0
- package/dist/policy/reserved-scopes.js +5 -0
- package/dist/policy/reserved-scopes.js.map +1 -0
- package/dist/ports/index.d.ts +63 -0
- package/dist/ports/index.d.ts.map +1 -1
- package/dist/ports/index.js.map +1 -1
- package/dist/ports/pdpp-auth.d.ts +129 -0
- package/dist/ports/pdpp-auth.d.ts.map +1 -0
- package/dist/ports/pdpp-auth.js +60 -0
- package/dist/ports/pdpp-auth.js.map +1 -0
- package/dist/ports/pdpp-auth.test-utils.d.ts +9 -0
- package/dist/ports/pdpp-auth.test-utils.d.ts.map +1 -0
- package/dist/ports/pdpp-auth.test-utils.js +18 -0
- package/dist/ports/pdpp-auth.test-utils.js.map +1 -0
- package/dist/schemas/server-config.d.ts +44 -0
- package/dist/schemas/server-config.d.ts.map +1 -1
- package/dist/schemas/server-config.js +91 -0
- package/dist/schemas/server-config.js.map +1 -1
- package/dist/signing/request-signer.d.ts +2 -0
- package/dist/signing/request-signer.d.ts.map +1 -1
- package/dist/signing/request-signer.js +1 -0
- package/dist/signing/request-signer.js.map +1 -1
- package/dist/storage/adapters/interface.d.ts +3 -0
- package/dist/storage/adapters/interface.d.ts.map +1 -1
- package/dist/storage/adapters/vana-audience.d.ts +12 -0
- package/dist/storage/adapters/vana-audience.d.ts.map +1 -0
- package/dist/storage/adapters/vana-audience.js +72 -0
- package/dist/storage/adapters/vana-audience.js.map +1 -0
- package/dist/storage/adapters/vana.d.ts +2 -0
- package/dist/storage/adapters/vana.d.ts.map +1 -1
- package/dist/storage/adapters/vana.js +53 -20
- package/dist/storage/adapters/vana.js.map +1 -1
- package/dist/storage/canonical-legacy-projection.d.ts +262 -0
- package/dist/storage/canonical-legacy-projection.d.ts.map +1 -0
- package/dist/storage/canonical-legacy-projection.js +761 -0
- package/dist/storage/canonical-legacy-projection.js.map +1 -0
- package/dist/storage/index/manager.d.ts +29 -2
- package/dist/storage/index/manager.d.ts.map +1 -1
- package/dist/storage/index/schema.d.ts +1 -1
- package/dist/storage/index/schema.js +1 -1
- package/dist/storage/index/types.d.ts +7 -1
- package/dist/storage/index/types.d.ts.map +1 -1
- package/dist/storage/legacy-projection.d.ts +13 -10
- package/dist/storage/legacy-projection.d.ts.map +1 -1
- package/dist/storage/legacy-projection.js +269 -74
- package/dist/storage/legacy-projection.js.map +1 -1
- package/dist/storage/legacy-scope-coverage-exceptions.d.ts +8 -0
- package/dist/storage/legacy-scope-coverage-exceptions.d.ts.map +1 -0
- package/dist/storage/legacy-scope-coverage-exceptions.js +10 -0
- package/dist/storage/legacy-scope-coverage-exceptions.js.map +1 -0
- package/dist/storage/legacy-scope-coverage.d.ts +53 -0
- package/dist/storage/legacy-scope-coverage.d.ts.map +1 -0
- package/dist/storage/legacy-scope-coverage.js +403 -0
- package/dist/storage/legacy-scope-coverage.js.map +1 -0
- package/dist/storage/legacy-scope-entity-keys.d.ts +4 -0
- package/dist/storage/legacy-scope-entity-keys.d.ts.map +1 -0
- package/dist/storage/legacy-scope-entity-keys.js +92 -0
- package/dist/storage/legacy-scope-entity-keys.js.map +1 -0
- package/dist/storage/legacy-scope-view.d.ts +154 -0
- package/dist/storage/legacy-scope-view.d.ts.map +1 -0
- package/dist/storage/legacy-scope-view.js +735 -0
- package/dist/storage/legacy-scope-view.js.map +1 -0
- package/dist/storage/pdpp-records/completion.d.ts +91 -0
- package/dist/storage/pdpp-records/completion.d.ts.map +1 -0
- package/dist/storage/pdpp-records/completion.js +170 -0
- package/dist/storage/pdpp-records/completion.js.map +1 -0
- package/dist/storage/pdpp-records/cursor.d.ts +41 -0
- package/dist/storage/pdpp-records/cursor.d.ts.map +1 -0
- package/dist/storage/pdpp-records/cursor.js +49 -0
- package/dist/storage/pdpp-records/cursor.js.map +1 -0
- package/dist/storage/pdpp-records/declaration-witness.d.ts +58 -0
- package/dist/storage/pdpp-records/declaration-witness.d.ts.map +1 -0
- package/dist/storage/pdpp-records/declaration-witness.js +230 -0
- package/dist/storage/pdpp-records/declaration-witness.js.map +1 -0
- package/dist/storage/pdpp-records/enforcement.d.ts +52 -0
- package/dist/storage/pdpp-records/enforcement.d.ts.map +1 -0
- package/dist/storage/pdpp-records/enforcement.js +116 -0
- package/dist/storage/pdpp-records/enforcement.js.map +1 -0
- package/dist/storage/pdpp-records/index.d.ts +5 -0
- package/dist/storage/pdpp-records/index.d.ts.map +1 -0
- package/dist/storage/pdpp-records/index.js +5 -0
- package/dist/storage/pdpp-records/index.js.map +1 -0
- package/dist/storage/pdpp-records/ingest-plan.d.ts +39 -0
- package/dist/storage/pdpp-records/ingest-plan.d.ts.map +1 -0
- package/dist/storage/pdpp-records/ingest-plan.js +103 -0
- package/dist/storage/pdpp-records/ingest-plan.js.map +1 -0
- package/dist/storage/pdpp-records/interface.d.ts +104 -0
- package/dist/storage/pdpp-records/interface.d.ts.map +1 -0
- package/dist/storage/pdpp-records/interface.js +2 -0
- package/dist/storage/pdpp-records/interface.js.map +1 -0
- package/dist/storage/pdpp-records/memory-store.d.ts +9 -0
- package/dist/storage/pdpp-records/memory-store.d.ts.map +1 -0
- package/dist/storage/pdpp-records/memory-store.js +466 -0
- package/dist/storage/pdpp-records/memory-store.js.map +1 -0
- package/dist/storage/pdpp-records/portable.d.ts +9 -0
- package/dist/storage/pdpp-records/portable.d.ts.map +1 -0
- package/dist/storage/pdpp-records/portable.js +8 -0
- package/dist/storage/pdpp-records/portable.js.map +1 -0
- package/dist/storage/pdpp-records/read-port.d.ts +44 -0
- package/dist/storage/pdpp-records/read-port.d.ts.map +1 -0
- package/dist/storage/pdpp-records/read-port.js +22 -0
- package/dist/storage/pdpp-records/read-port.js.map +1 -0
- package/dist/storage/pdpp-records/record-key.d.ts +52 -0
- package/dist/storage/pdpp-records/record-key.d.ts.map +1 -0
- package/dist/storage/pdpp-records/record-key.js +97 -0
- package/dist/storage/pdpp-records/record-key.js.map +1 -0
- package/dist/storage/pdpp-records/schema.d.ts +41 -0
- package/dist/storage/pdpp-records/schema.d.ts.map +1 -0
- package/dist/storage/pdpp-records/schema.js +153 -0
- package/dist/storage/pdpp-records/schema.js.map +1 -0
- package/dist/storage/pdpp-records/stream-declaration.d.ts +88 -0
- package/dist/storage/pdpp-records/stream-declaration.d.ts.map +1 -0
- package/dist/storage/pdpp-records/stream-declaration.js +57 -0
- package/dist/storage/pdpp-records/stream-declaration.js.map +1 -0
- package/dist/storage/pdpp-records/types.d.ts +138 -0
- package/dist/storage/pdpp-records/types.d.ts.map +1 -0
- package/dist/storage/pdpp-records/types.js +38 -0
- package/dist/storage/pdpp-records/types.js.map +1 -0
- package/dist/sync/data-point-feed.d.ts +3 -0
- package/dist/sync/data-point-feed.d.ts.map +1 -1
- package/dist/sync/data-point-feed.js +17 -1
- package/dist/sync/data-point-feed.js.map +1 -1
- package/dist/sync/delete-data-port.d.ts +2 -0
- package/dist/sync/delete-data-port.d.ts.map +1 -1
- package/dist/sync/delete-data-port.js +1 -1
- package/dist/sync/delete-data-port.js.map +1 -1
- package/dist/sync/engine/sync-manager.d.ts.map +1 -1
- package/dist/sync/engine/sync-manager.js +5 -2
- package/dist/sync/engine/sync-manager.js.map +1 -1
- package/dist/sync/index.d.ts +3 -1
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +4 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/pdpp-import.d.ts +192 -0
- package/dist/sync/pdpp-import.d.ts.map +1 -0
- package/dist/sync/pdpp-import.js +441 -0
- package/dist/sync/pdpp-import.js.map +1 -0
- package/dist/sync/scope-deletions.d.ts +10 -0
- package/dist/sync/scope-deletions.d.ts.map +1 -1
- package/dist/sync/scope-deletions.js +40 -7
- package/dist/sync/scope-deletions.js.map +1 -1
- package/dist/sync/workers/download.d.ts +14 -0
- package/dist/sync/workers/download.d.ts.map +1 -1
- package/dist/sync/workers/download.js +149 -13
- package/dist/sync/workers/download.js.map +1 -1
- package/dist/sync/workers/upload.d.ts +2 -0
- package/dist/sync/workers/upload.d.ts.map +1 -1
- package/dist/sync/workers/upload.js +7 -0
- package/dist/sync/workers/upload.js.map +1 -1
- package/dist/test-utils/memory-storage.d.ts +1 -1
- package/dist/test-utils/memory-storage.d.ts.map +1 -1
- package/dist/test-utils/memory-storage.js +11 -5
- package/dist/test-utils/memory-storage.js.map +1 -1
- package/package.json +54 -4
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable retention for PDPP ↔ chain grant bindings (scope §6).
|
|
3
|
+
*
|
|
4
|
+
* The binding record is the only thing that crosses the gateway/chain
|
|
5
|
+
* boundary on our side; record payloads stay in PS storage and never enter
|
|
6
|
+
* this store. What is retained here is an identity join — PDPP grant id,
|
|
7
|
+
* chain permission ref, owner, grantee — and nothing about the data itself.
|
|
8
|
+
*
|
|
9
|
+
* ## Append-only by construction
|
|
10
|
+
*
|
|
11
|
+
* The port exposes `put` and `get` but no `update` and no `delete`. That is
|
|
12
|
+
* deliberate, and it is the mechanism that makes §6's revocation semantics
|
|
13
|
+
* correct rather than merely intended:
|
|
14
|
+
*
|
|
15
|
+
* - A binding asserts a *historical* fact ("this consent authorized this
|
|
16
|
+
* permission"), which does not stop being true when the grant is revoked.
|
|
17
|
+
* - Revocation is a *current* fact, and lives on the chain grant, read live
|
|
18
|
+
* at verification time.
|
|
19
|
+
*
|
|
20
|
+
* If revocation were mirrored into this store, the two would have to be kept
|
|
21
|
+
* in sync, and every window where they disagreed would be a window where a
|
|
22
|
+
* revoked grant still read as live. Not storing the status at all removes that
|
|
23
|
+
* class of bug instead of managing it.
|
|
24
|
+
*
|
|
25
|
+
* `putBinding` rejects a conflicting rewrite for the same key rather than
|
|
26
|
+
* overwriting, so a second binding cannot silently retarget an existing PDPP
|
|
27
|
+
* grant at a different permission, owner, or app.
|
|
28
|
+
*/
|
|
29
|
+
import { type ChainPermissionRef, type PdppGrantBinding } from "./pdpp-binding.js";
|
|
30
|
+
/**
|
|
31
|
+
* Durable storage for grant bindings.
|
|
32
|
+
*
|
|
33
|
+
* Implementations back this with the deployment's real store (SQLite on
|
|
34
|
+
* desktop, the supplied runtime's durable state in Enclave). The interface is
|
|
35
|
+
* intentionally tiny so both can implement it without sharing a schema.
|
|
36
|
+
*/
|
|
37
|
+
export interface PdppGrantBindingStore {
|
|
38
|
+
/**
|
|
39
|
+
* Retain a binding. Idempotent for an identical re-put; throws on a
|
|
40
|
+
* conflicting one.
|
|
41
|
+
*/
|
|
42
|
+
putBinding(binding: PdppGrantBinding): void;
|
|
43
|
+
/** Look up by the PDPP grant id (the consent artifact). */
|
|
44
|
+
getByPdppGrantId(pdppGrantId: string): PdppGrantBinding | null;
|
|
45
|
+
/**
|
|
46
|
+
* All bindings recorded against a chain permission, oldest first.
|
|
47
|
+
*
|
|
48
|
+
* Plural and non-unique on purpose: distinct PDPP grants can legitimately
|
|
49
|
+
* bind to the same permission over time (e.g. one consent superseding
|
|
50
|
+
* another at the chain level), and each retains its own observed
|
|
51
|
+
* `grantVersion`. Returning a single "the" binding here would silently
|
|
52
|
+
* pick one and hide the others — callers that need "is any binding for
|
|
53
|
+
* this permission still live" must check every entry themselves.
|
|
54
|
+
*/
|
|
55
|
+
getBindingsForPermission(permission: ChainPermissionRef): PdppGrantBinding[];
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* True when two bindings agree on every field that defines the binding.
|
|
59
|
+
*
|
|
60
|
+
* Both `granteeAddress` (the app's wallet) and `granteeId` (the builder id
|
|
61
|
+
* the chain grant names) are compared, which makes rotation of either an
|
|
62
|
+
* explicit conflict rather than a silent follow. That is deliberate. Context
|
|
63
|
+
* Gateway holds one Privy-custodied wallet per app, keyed `(ownerType,
|
|
64
|
+
* ownerId)` with a DB unique index, and its schema *models* rotation
|
|
65
|
+
* (`isCurrent` plus a partial unique index) although no code path performs
|
|
66
|
+
* one today — so the address is currently immutable per app in practice but
|
|
67
|
+
* not by design.
|
|
68
|
+
*
|
|
69
|
+
* If rotation ever ships, a rotated wallet or builder id is a different
|
|
70
|
+
* grantee, and the owner's existing consent must not transfer to it without
|
|
71
|
+
* a new decision. Rejecting the rewrite surfaces that as a failure instead of
|
|
72
|
+
* quietly repointing a retained grant at an identity the owner never
|
|
73
|
+
* approved.
|
|
74
|
+
*/
|
|
75
|
+
export declare function bindingsAgree(a: PdppGrantBinding, b: PdppGrantBinding): boolean;
|
|
76
|
+
export declare function permissionKey(p: ChainPermissionRef): string;
|
|
77
|
+
/** New bindings require a version; only migrated rows may retain null. */
|
|
78
|
+
export declare function assertWritableGrantVersion(binding: PdppGrantBinding): void;
|
|
79
|
+
/**
|
|
80
|
+
* In-memory implementation, used by tests and by callers that have no durable
|
|
81
|
+
* store yet.
|
|
82
|
+
*
|
|
83
|
+
* This is a real implementation of the port's semantics — including the
|
|
84
|
+
* conflict rejection — not a stub that accepts everything. Tests exercising it
|
|
85
|
+
* are therefore testing the actual binding rules; only the persistence medium
|
|
86
|
+
* differs from a deployed store.
|
|
87
|
+
*/
|
|
88
|
+
export declare function createInMemoryPdppGrantBindingStore(): PdppGrantBindingStore;
|
|
89
|
+
//# sourceMappingURL=pdpp-binding-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdpp-binding-store.d.ts","sourceRoot":"","sources":["../../src/grants/pdpp-binding-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EAGL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAE3B;;;;;;GAMG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,UAAU,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC5C,2DAA2D;IAC3D,gBAAgB,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CAAC;IAC/D;;;;;;;;;OASG;IACH,wBAAwB,CAAC,UAAU,EAAE,kBAAkB,GAAG,gBAAgB,EAAE,CAAC;CAC9E;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,aAAa,CAC3B,CAAC,EAAE,gBAAgB,EACnB,CAAC,EAAE,gBAAgB,GAClB,OAAO,CAUT;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAE3D;AAED,0EAA0E;AAC1E,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAS1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mCAAmC,IAAI,qBAAqB,CAyC3E"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Durable retention for PDPP ↔ chain grant bindings (scope §6).
|
|
3
|
+
*
|
|
4
|
+
* The binding record is the only thing that crosses the gateway/chain
|
|
5
|
+
* boundary on our side; record payloads stay in PS storage and never enter
|
|
6
|
+
* this store. What is retained here is an identity join — PDPP grant id,
|
|
7
|
+
* chain permission ref, owner, grantee — and nothing about the data itself.
|
|
8
|
+
*
|
|
9
|
+
* ## Append-only by construction
|
|
10
|
+
*
|
|
11
|
+
* The port exposes `put` and `get` but no `update` and no `delete`. That is
|
|
12
|
+
* deliberate, and it is the mechanism that makes §6's revocation semantics
|
|
13
|
+
* correct rather than merely intended:
|
|
14
|
+
*
|
|
15
|
+
* - A binding asserts a *historical* fact ("this consent authorized this
|
|
16
|
+
* permission"), which does not stop being true when the grant is revoked.
|
|
17
|
+
* - Revocation is a *current* fact, and lives on the chain grant, read live
|
|
18
|
+
* at verification time.
|
|
19
|
+
*
|
|
20
|
+
* If revocation were mirrored into this store, the two would have to be kept
|
|
21
|
+
* in sync, and every window where they disagreed would be a window where a
|
|
22
|
+
* revoked grant still read as live. Not storing the status at all removes that
|
|
23
|
+
* class of bug instead of managing it.
|
|
24
|
+
*
|
|
25
|
+
* `putBinding` rejects a conflicting rewrite for the same key rather than
|
|
26
|
+
* overwriting, so a second binding cannot silently retarget an existing PDPP
|
|
27
|
+
* grant at a different permission, owner, or app.
|
|
28
|
+
*/
|
|
29
|
+
import { InvalidSignatureError } from "../errors/catalog.js";
|
|
30
|
+
import { isValidGrantVersion, samePermission, } from "./pdpp-binding.js";
|
|
31
|
+
/**
|
|
32
|
+
* True when two bindings agree on every field that defines the binding.
|
|
33
|
+
*
|
|
34
|
+
* Both `granteeAddress` (the app's wallet) and `granteeId` (the builder id
|
|
35
|
+
* the chain grant names) are compared, which makes rotation of either an
|
|
36
|
+
* explicit conflict rather than a silent follow. That is deliberate. Context
|
|
37
|
+
* Gateway holds one Privy-custodied wallet per app, keyed `(ownerType,
|
|
38
|
+
* ownerId)` with a DB unique index, and its schema *models* rotation
|
|
39
|
+
* (`isCurrent` plus a partial unique index) although no code path performs
|
|
40
|
+
* one today — so the address is currently immutable per app in practice but
|
|
41
|
+
* not by design.
|
|
42
|
+
*
|
|
43
|
+
* If rotation ever ships, a rotated wallet or builder id is a different
|
|
44
|
+
* grantee, and the owner's existing consent must not transfer to it without
|
|
45
|
+
* a new decision. Rejecting the rewrite surfaces that as a failure instead of
|
|
46
|
+
* quietly repointing a retained grant at an identity the owner never
|
|
47
|
+
* approved.
|
|
48
|
+
*/
|
|
49
|
+
export function bindingsAgree(a, b) {
|
|
50
|
+
return (a.pdppGrantId === b.pdppGrantId &&
|
|
51
|
+
samePermission(a.permission, b.permission) &&
|
|
52
|
+
a.ownerAddress.toLowerCase() === b.ownerAddress.toLowerCase() &&
|
|
53
|
+
a.granteeAddress.toLowerCase() === b.granteeAddress.toLowerCase() &&
|
|
54
|
+
a.granteeId.toLowerCase() === b.granteeId.toLowerCase() &&
|
|
55
|
+
a.pdppClientId === b.pdppClientId &&
|
|
56
|
+
a.grantVersion === b.grantVersion);
|
|
57
|
+
}
|
|
58
|
+
export function permissionKey(p) {
|
|
59
|
+
return `${p.chainId}:${p.contractAddress.toLowerCase()}:${p.permissionId}`;
|
|
60
|
+
}
|
|
61
|
+
/** New bindings require a version; only migrated rows may retain null. */
|
|
62
|
+
export function assertWritableGrantVersion(binding) {
|
|
63
|
+
if (!isValidGrantVersion(binding.grantVersion)) {
|
|
64
|
+
throw new InvalidSignatureError({
|
|
65
|
+
reason: "grantVersion must be a positive decimal uint256 string for a new binding; null is reserved for a preserved legacy row",
|
|
66
|
+
pdppGrantId: binding.pdppGrantId,
|
|
67
|
+
grantVersion: binding.grantVersion,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* In-memory implementation, used by tests and by callers that have no durable
|
|
73
|
+
* store yet.
|
|
74
|
+
*
|
|
75
|
+
* This is a real implementation of the port's semantics — including the
|
|
76
|
+
* conflict rejection — not a stub that accepts everything. Tests exercising it
|
|
77
|
+
* are therefore testing the actual binding rules; only the persistence medium
|
|
78
|
+
* differs from a deployed store.
|
|
79
|
+
*/
|
|
80
|
+
export function createInMemoryPdppGrantBindingStore() {
|
|
81
|
+
const byGrantId = new Map();
|
|
82
|
+
const byPermission = new Map();
|
|
83
|
+
return {
|
|
84
|
+
putBinding(binding) {
|
|
85
|
+
const existingByGrant = byGrantId.get(binding.pdppGrantId);
|
|
86
|
+
if (existingByGrant) {
|
|
87
|
+
if (!bindingsAgree(existingByGrant, binding)) {
|
|
88
|
+
throw new InvalidSignatureError({
|
|
89
|
+
reason: "A different binding already exists for this PDPP grant id",
|
|
90
|
+
pdppGrantId: binding.pdppGrantId,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
assertWritableGrantVersion(binding);
|
|
96
|
+
const key = permissionKey(binding.permission);
|
|
97
|
+
const list = byPermission.get(key) ?? [];
|
|
98
|
+
list.push(binding);
|
|
99
|
+
byPermission.set(key, list);
|
|
100
|
+
byGrantId.set(binding.pdppGrantId, binding);
|
|
101
|
+
},
|
|
102
|
+
getByPdppGrantId(pdppGrantId) {
|
|
103
|
+
return byGrantId.get(pdppGrantId) ?? null;
|
|
104
|
+
},
|
|
105
|
+
getBindingsForPermission(permission) {
|
|
106
|
+
const list = byPermission.get(permissionKey(permission)) ?? [];
|
|
107
|
+
return [...list].sort((a, b) => a.boundAt.localeCompare(b.boundAt) ||
|
|
108
|
+
a.pdppGrantId.localeCompare(b.pdppGrantId));
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=pdpp-binding-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdpp-binding-store.js","sourceRoot":"","sources":["../../src/grants/pdpp-binding-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retains the identity join between a PDPP grant and a Vana gateway grant.
|
|
3
|
+
* `permissionId` stores GatewayGrantResponse.id, including hex grant IDs.
|
|
4
|
+
* Builder IDs and wallet addresses are distinct: creation requires a trusted
|
|
5
|
+
* builder lookup, and verification compares each identity with its counterpart.
|
|
6
|
+
* Deployment fields bind the record to the PS configuration; they are not
|
|
7
|
+
* authenticated fields of the gateway response. Revocation is checked live.
|
|
8
|
+
*/
|
|
9
|
+
import type { Builder, GatewayGrantResponse } from "@opendatalabs/vana-sdk/browser";
|
|
10
|
+
/**
|
|
11
|
+
* The chain-side identity of a grant. This tuple — and not any derived digest
|
|
12
|
+
* — is the binding key.
|
|
13
|
+
*
|
|
14
|
+
* `chainId` and `contractAddress` are the PS's own deployment configuration,
|
|
15
|
+
* not fields the gateway returns; see the module doc for why they are kept.
|
|
16
|
+
* `permissionId` is `GatewayGrantResponse.id` (see module doc) — keying on it
|
|
17
|
+
* alone, without a deployment tag, would also let a record recorded under one
|
|
18
|
+
* deployment configuration silently authorize a read under another.
|
|
19
|
+
*/
|
|
20
|
+
export interface ChainPermissionRef {
|
|
21
|
+
/** EIP-155 chain ID of the deployment the PS was configured against when this was recorded. */
|
|
22
|
+
chainId: number;
|
|
23
|
+
/** The gateway/contract address the PS was configured against when this was recorded. */
|
|
24
|
+
contractAddress: `0x${string}`;
|
|
25
|
+
/** `GatewayGrantResponse.id` — the gateway's grant id (may be hex). */
|
|
26
|
+
permissionId: string;
|
|
27
|
+
}
|
|
28
|
+
/** The builder evidence a caller must resolve before creating or checking a binding. */
|
|
29
|
+
export type ResolvedBuilder = Pick<Builder, "id" | "granteeAddress">;
|
|
30
|
+
/**
|
|
31
|
+
* An immutable binding between one resolved PDPP grant and one chain
|
|
32
|
+
* permission.
|
|
33
|
+
*
|
|
34
|
+
* Immutability is the point: this record is written once, at grant creation,
|
|
35
|
+
* and is never mutated — not even on revocation. Revocation is a *live* fact
|
|
36
|
+
* read from the chain grant (`revokedAt`), never a field edited here. Copying
|
|
37
|
+
* a mutable status into an immutable record is how a stale "still valid" claim
|
|
38
|
+
* survives a revocation, so the two are kept strictly apart.
|
|
39
|
+
*/
|
|
40
|
+
export interface PdppGrantBinding {
|
|
41
|
+
/** `grant_id` of the resolved PDPP grant (the consent artifact). */
|
|
42
|
+
pdppGrantId: string;
|
|
43
|
+
/** Chain identity of the permission that authorizes reads for this grant. */
|
|
44
|
+
permission: ChainPermissionRef;
|
|
45
|
+
/**
|
|
46
|
+
* The data owner. Must equal both the chain grant's `grantorAddress` and the
|
|
47
|
+
* PS's configured `serverOwner` at read time.
|
|
48
|
+
*/
|
|
49
|
+
ownerAddress: `0x${string}`;
|
|
50
|
+
/**
|
|
51
|
+
* The grantee app's wallet address — the app's *existing* identity, carried
|
|
52
|
+
* through unchanged.
|
|
53
|
+
*
|
|
54
|
+
* §6 requires one grantee identity per Context Gateway builder/app: the
|
|
55
|
+
* PDPP `client_id`, the issued grant, the ledger grant, and the access-history
|
|
56
|
+
* grantee must all resolve to this one address. We record the address the app
|
|
57
|
+
* already has; we do not allocate one.
|
|
58
|
+
*/
|
|
59
|
+
granteeAddress: `0x${string}`;
|
|
60
|
+
/** The PDPP OAuth `client_id` that the above address belongs to. */
|
|
61
|
+
pdppClientId: string;
|
|
62
|
+
/**
|
|
63
|
+
* The resolved builder's id (`Builder.id`), as the chain grant's
|
|
64
|
+
* `granteeId` reports it. This is a distinct bytes32-shaped identifier,
|
|
65
|
+
* NOT the wallet address above — see the module doc.
|
|
66
|
+
*/
|
|
67
|
+
granteeId: string;
|
|
68
|
+
/** Gateway version verified at binding time. Later versions invalidate this consent.
|
|
69
|
+
* `null` denotes a preserved legacy row and always denies access.
|
|
70
|
+
*/
|
|
71
|
+
grantVersion: string | null;
|
|
72
|
+
/** When the binding was recorded (ISO 8601). Provenance, not status. */
|
|
73
|
+
boundAt: string;
|
|
74
|
+
}
|
|
75
|
+
export declare function isValidGrantVersion(value: unknown): value is string;
|
|
76
|
+
/** Re-registration can clear revocation, so even a newer version requires new consent. */
|
|
77
|
+
export declare function grantVersionStillAuthorizes(retainedVersion: string | null, liveVersion: unknown): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Compare two chain permission references. All three components must match —
|
|
80
|
+
* see `ChainPermissionRef` for why the address and chain ID are load-bearing.
|
|
81
|
+
*/
|
|
82
|
+
export declare function samePermission(a: ChainPermissionRef, b: ChainPermissionRef): boolean;
|
|
83
|
+
export interface CreateBindingInput {
|
|
84
|
+
pdppGrantId: string;
|
|
85
|
+
permission: ChainPermissionRef;
|
|
86
|
+
/** The PS's configured owner address. */
|
|
87
|
+
serverOwner: `0x${string}`;
|
|
88
|
+
/** The app's existing grantee wallet address. */
|
|
89
|
+
granteeAddress: `0x${string}`;
|
|
90
|
+
pdppClientId: string;
|
|
91
|
+
/**
|
|
92
|
+
* Trusted, already-resolved builder evidence for `granteeAddress` — e.g.
|
|
93
|
+
* `await gateway.getBuilder(granteeAddress)`. This is what lets the binding
|
|
94
|
+
* check the chain grant's `granteeId` (a builder id) against the right
|
|
95
|
+
* counterpart instead of against the wallet address directly.
|
|
96
|
+
*/
|
|
97
|
+
resolvedBuilder: ResolvedBuilder;
|
|
98
|
+
/** The chain grant this PDPP grant is being bound to, as the gateway reports it. */
|
|
99
|
+
chainGrant: GatewayGrantResponse;
|
|
100
|
+
now?: Date;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Create the binding at grant-creation time, refusing to record one that is
|
|
104
|
+
* already inconsistent.
|
|
105
|
+
*
|
|
106
|
+
* This is the *creation* boundary check. It is deliberately strict: a binding
|
|
107
|
+
* written now is trusted later, so anything we fail to verify here becomes an
|
|
108
|
+
* unverifiable assertion at read time. Specifically it rejects:
|
|
109
|
+
*
|
|
110
|
+
* - a chain grant whose `grantorAddress` is not this server's owner (binding
|
|
111
|
+
* another owner's grant to our PDPP consent),
|
|
112
|
+
* - a `resolvedBuilder` whose wallet is not the app's requested address
|
|
113
|
+
* (the caller resolved the wrong builder),
|
|
114
|
+
* - a chain grant whose `granteeId` is not the resolved builder's id
|
|
115
|
+
* (binding a grant issued to a *different* app),
|
|
116
|
+
* - a chain grant that is already revoked (never record a dead grant as live),
|
|
117
|
+
* - a chain grant whose id does not match the permission being bound,
|
|
118
|
+
* - a chain grant whose `grantVersion` is missing or not a valid positive
|
|
119
|
+
* decimal uint256 string (a new binding must pin a real version; `null`
|
|
120
|
+
* is reserved for legacy rows a schema migration preserved, never for
|
|
121
|
+
* something created through this function).
|
|
122
|
+
*/
|
|
123
|
+
export declare function createPdppGrantBinding(input: CreateBindingInput): PdppGrantBinding;
|
|
124
|
+
export interface VerifyBindingInput {
|
|
125
|
+
/** The retained, immutable binding record. */
|
|
126
|
+
binding: PdppGrantBinding;
|
|
127
|
+
/** The PDPP grant id presented by the caller. */
|
|
128
|
+
pdppGrantId: string;
|
|
129
|
+
/** The PS's configured owner address, at read time. */
|
|
130
|
+
serverOwner: `0x${string}`;
|
|
131
|
+
/** The address that signed this request (the app's grantee wallet). */
|
|
132
|
+
requestSigner: `0x${string}`;
|
|
133
|
+
/**
|
|
134
|
+
* The chain grant as read *now*. Revocation is read live from here; it is
|
|
135
|
+
* never taken from the binding record.
|
|
136
|
+
*/
|
|
137
|
+
chainGrant: GatewayGrantResponse | null;
|
|
138
|
+
/** The deployment the PS is configured against, at read time. */
|
|
139
|
+
deployment: {
|
|
140
|
+
chainId: number;
|
|
141
|
+
contractAddress: `0x${string}`;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Verify a binding at read time.
|
|
146
|
+
*
|
|
147
|
+
* Every axis §6 names is checked against the *retained* binding, so a
|
|
148
|
+
* mismatch on any one of owner, app, chain/contract, or record fails closed:
|
|
149
|
+
*
|
|
150
|
+
* - **record**: the presented PDPP grant id must be the one bound,
|
|
151
|
+
* - **chain/contract**: the binding must have been recorded under the same
|
|
152
|
+
* deployment configuration the PS is running under now (see module doc —
|
|
153
|
+
* this is an operator-misconfiguration guard, not gateway-supplied
|
|
154
|
+
* evidence, since the gateway response carries no chain/contract fields),
|
|
155
|
+
* - **owner**: the binding's owner must still be this server's owner, and the
|
|
156
|
+
* live chain grant's grantor must agree,
|
|
157
|
+
* - **app**: the request signer (a wallet) must be the bound grantee
|
|
158
|
+
* address, and the live chain grant's `granteeId` (a builder id) must
|
|
159
|
+
* still agree with the `granteeId` retained on the binding — these two
|
|
160
|
+
* checks are deliberately against different fields, because a wallet and
|
|
161
|
+
* a builder id are different values,
|
|
162
|
+
* - **revocation**: the live chain grant must exist and be unrevoked.
|
|
163
|
+
*
|
|
164
|
+
* No chain I/O happens in this function — the caller supplies the already-read
|
|
165
|
+
* `chainGrant`. That keeps this usable on the hot read path without adding a
|
|
166
|
+
* network round trip per request.
|
|
167
|
+
*/
|
|
168
|
+
export declare function verifyPdppGrantBinding(input: VerifyBindingInput): void;
|
|
169
|
+
//# sourceMappingURL=pdpp-binding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdpp-binding.d.ts","sourceRoot":"","sources":["../../src/grants/pdpp-binding.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,KAAK,EACV,OAAO,EACP,oBAAoB,EACrB,MAAM,gCAAgC,CAAC;AAExC;;;;;;;;;GASG;AACH,MAAM,WAAW,kBAAkB;IACjC,+FAA+F;IAC/F,OAAO,EAAE,MAAM,CAAC;IAChB,yFAAyF;IACzF,eAAe,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,wFAAwF;AACxF,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,GAAG,gBAAgB,CAAC,CAAC;AAErE;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAC/B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,EAAE,kBAAkB,CAAC;IAC/B;;;OAGG;IACH,YAAY,EAAE,KAAK,MAAM,EAAE,CAAC;IAC5B;;;;;;;;OAQG;IACH,cAAc,EAAE,KAAK,MAAM,EAAE,CAAC;IAC9B,oEAAoE;IACpE,YAAY,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC;CACjB;AAMD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAInE;AAED,0FAA0F;AAC1F,wBAAgB,2BAA2B,CACzC,eAAe,EAAE,MAAM,GAAG,IAAI,EAC9B,WAAW,EAAE,OAAO,GACnB,OAAO,CAIT;AAOD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,kBAAkB,EACrB,CAAC,EAAE,kBAAkB,GACpB,OAAO,CAMT;AAED,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,kBAAkB,CAAC;IAC/B,yCAAyC;IACzC,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,iDAAiD;IACjD,cAAc,EAAE,KAAK,MAAM,EAAE,CAAC;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,eAAe,EAAE,eAAe,CAAC;IACjC,oFAAoF;IACpF,UAAU,EAAE,oBAAoB,CAAC;IACjC,GAAG,CAAC,EAAE,IAAI,CAAC;CACZ;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,kBAAkB,GACxB,gBAAgB,CAsElB;AAED,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,WAAW,EAAE,KAAK,MAAM,EAAE,CAAC;IAC3B,uEAAuE;IACvE,aAAa,EAAE,KAAK,MAAM,EAAE,CAAC;IAC7B;;;OAGG;IACH,UAAU,EAAE,oBAAoB,GAAG,IAAI,CAAC;IACxC,iEAAiE;IACjE,UAAU,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,KAAK,MAAM,EAAE,CAAA;KAAE,CAAC;CACjE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI,CA0GtE"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retains the identity join between a PDPP grant and a Vana gateway grant.
|
|
3
|
+
* `permissionId` stores GatewayGrantResponse.id, including hex grant IDs.
|
|
4
|
+
* Builder IDs and wallet addresses are distinct: creation requires a trusted
|
|
5
|
+
* builder lookup, and verification compares each identity with its counterpart.
|
|
6
|
+
* Deployment fields bind the record to the PS configuration; they are not
|
|
7
|
+
* authenticated fields of the gateway response. Revocation is checked live.
|
|
8
|
+
*/
|
|
9
|
+
import { GrantOwnerMismatchError, GrantRevokedError, InvalidSignatureError, ScopeMismatchError, } from "../errors/catalog.js";
|
|
10
|
+
/** Gateway versions are positive decimal uint256 strings without leading zeros. */
|
|
11
|
+
const POSITIVE_DECIMAL_UINT256 = /^(0|[1-9][0-9]*)$/;
|
|
12
|
+
const UINT256_MAX = 2n ** 256n - 1n;
|
|
13
|
+
export function isValidGrantVersion(value) {
|
|
14
|
+
if (typeof value !== "string")
|
|
15
|
+
return false;
|
|
16
|
+
if (!POSITIVE_DECIMAL_UINT256.test(value) || value === "0")
|
|
17
|
+
return false;
|
|
18
|
+
return BigInt(value) <= UINT256_MAX;
|
|
19
|
+
}
|
|
20
|
+
/** Re-registration can clear revocation, so even a newer version requires new consent. */
|
|
21
|
+
export function grantVersionStillAuthorizes(retainedVersion, liveVersion) {
|
|
22
|
+
if (retainedVersion === null)
|
|
23
|
+
return false;
|
|
24
|
+
if (!isValidGrantVersion(liveVersion))
|
|
25
|
+
return false;
|
|
26
|
+
return retainedVersion === liveVersion;
|
|
27
|
+
}
|
|
28
|
+
/** Case-insensitive comparison for hex-ish strings (addresses or bytes32 ids). */
|
|
29
|
+
function sameHex(a, b) {
|
|
30
|
+
return typeof a === "string" && a.toLowerCase() === b.toLowerCase();
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Compare two chain permission references. All three components must match —
|
|
34
|
+
* see `ChainPermissionRef` for why the address and chain ID are load-bearing.
|
|
35
|
+
*/
|
|
36
|
+
export function samePermission(a, b) {
|
|
37
|
+
return (a.chainId === b.chainId &&
|
|
38
|
+
a.contractAddress.toLowerCase() === b.contractAddress.toLowerCase() &&
|
|
39
|
+
a.permissionId === b.permissionId);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create the binding at grant-creation time, refusing to record one that is
|
|
43
|
+
* already inconsistent.
|
|
44
|
+
*
|
|
45
|
+
* This is the *creation* boundary check. It is deliberately strict: a binding
|
|
46
|
+
* written now is trusted later, so anything we fail to verify here becomes an
|
|
47
|
+
* unverifiable assertion at read time. Specifically it rejects:
|
|
48
|
+
*
|
|
49
|
+
* - a chain grant whose `grantorAddress` is not this server's owner (binding
|
|
50
|
+
* another owner's grant to our PDPP consent),
|
|
51
|
+
* - a `resolvedBuilder` whose wallet is not the app's requested address
|
|
52
|
+
* (the caller resolved the wrong builder),
|
|
53
|
+
* - a chain grant whose `granteeId` is not the resolved builder's id
|
|
54
|
+
* (binding a grant issued to a *different* app),
|
|
55
|
+
* - a chain grant that is already revoked (never record a dead grant as live),
|
|
56
|
+
* - a chain grant whose id does not match the permission being bound,
|
|
57
|
+
* - a chain grant whose `grantVersion` is missing or not a valid positive
|
|
58
|
+
* decimal uint256 string (a new binding must pin a real version; `null`
|
|
59
|
+
* is reserved for legacy rows a schema migration preserved, never for
|
|
60
|
+
* something created through this function).
|
|
61
|
+
*/
|
|
62
|
+
export function createPdppGrantBinding(input) {
|
|
63
|
+
const { chainGrant, serverOwner, granteeAddress, resolvedBuilder, permission, } = input;
|
|
64
|
+
if (chainGrant.id !== permission.permissionId) {
|
|
65
|
+
throw new InvalidSignatureError({
|
|
66
|
+
reason: "Chain grant id does not match the permission being bound",
|
|
67
|
+
expected: permission.permissionId,
|
|
68
|
+
actual: chainGrant.id,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
if (!sameHex(chainGrant.grantorAddress, serverOwner)) {
|
|
72
|
+
throw new GrantOwnerMismatchError({
|
|
73
|
+
grantId: chainGrant.id,
|
|
74
|
+
expected: serverOwner,
|
|
75
|
+
actual: chainGrant.grantorAddress ?? null,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// The caller's resolved builder must actually BE the requested app's
|
|
79
|
+
// wallet — otherwise everything below verifies the wrong builder.
|
|
80
|
+
if (!sameHex(resolvedBuilder.granteeAddress, granteeAddress)) {
|
|
81
|
+
throw new InvalidSignatureError({
|
|
82
|
+
reason: "Resolved builder wallet does not match the requested app address",
|
|
83
|
+
expected: granteeAddress,
|
|
84
|
+
actual: resolvedBuilder.granteeAddress,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Bind to the app's EXISTING grantee identity. If the chain grant was
|
|
88
|
+
// issued to a different builder, this PDPP consent does not describe it.
|
|
89
|
+
// `granteeId` is the builder's bytes32 id, NOT its wallet address — compare
|
|
90
|
+
// against `resolvedBuilder.id`, never against `granteeAddress` directly.
|
|
91
|
+
if (!sameHex(chainGrant.granteeId, resolvedBuilder.id)) {
|
|
92
|
+
throw new InvalidSignatureError({
|
|
93
|
+
reason: "Chain grant grantee does not match the app's builder id",
|
|
94
|
+
expected: resolvedBuilder.id,
|
|
95
|
+
actual: chainGrant.granteeId,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
if (chainGrant.revokedAt !== null && chainGrant.revokedAt !== undefined) {
|
|
99
|
+
throw new GrantRevokedError({ grantId: chainGrant.id });
|
|
100
|
+
}
|
|
101
|
+
if (!isValidGrantVersion(chainGrant.grantVersion)) {
|
|
102
|
+
throw new InvalidSignatureError({
|
|
103
|
+
reason: "Chain grant grantVersion is missing or malformed",
|
|
104
|
+
grantId: chainGrant.id,
|
|
105
|
+
actual: chainGrant.grantVersion,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return Object.freeze({
|
|
109
|
+
pdppGrantId: input.pdppGrantId,
|
|
110
|
+
permission,
|
|
111
|
+
ownerAddress: serverOwner,
|
|
112
|
+
granteeAddress,
|
|
113
|
+
pdppClientId: input.pdppClientId,
|
|
114
|
+
granteeId: chainGrant.granteeId,
|
|
115
|
+
grantVersion: chainGrant.grantVersion,
|
|
116
|
+
boundAt: (input.now ?? new Date()).toISOString(),
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Verify a binding at read time.
|
|
121
|
+
*
|
|
122
|
+
* Every axis §6 names is checked against the *retained* binding, so a
|
|
123
|
+
* mismatch on any one of owner, app, chain/contract, or record fails closed:
|
|
124
|
+
*
|
|
125
|
+
* - **record**: the presented PDPP grant id must be the one bound,
|
|
126
|
+
* - **chain/contract**: the binding must have been recorded under the same
|
|
127
|
+
* deployment configuration the PS is running under now (see module doc —
|
|
128
|
+
* this is an operator-misconfiguration guard, not gateway-supplied
|
|
129
|
+
* evidence, since the gateway response carries no chain/contract fields),
|
|
130
|
+
* - **owner**: the binding's owner must still be this server's owner, and the
|
|
131
|
+
* live chain grant's grantor must agree,
|
|
132
|
+
* - **app**: the request signer (a wallet) must be the bound grantee
|
|
133
|
+
* address, and the live chain grant's `granteeId` (a builder id) must
|
|
134
|
+
* still agree with the `granteeId` retained on the binding — these two
|
|
135
|
+
* checks are deliberately against different fields, because a wallet and
|
|
136
|
+
* a builder id are different values,
|
|
137
|
+
* - **revocation**: the live chain grant must exist and be unrevoked.
|
|
138
|
+
*
|
|
139
|
+
* No chain I/O happens in this function — the caller supplies the already-read
|
|
140
|
+
* `chainGrant`. That keeps this usable on the hot read path without adding a
|
|
141
|
+
* network round trip per request.
|
|
142
|
+
*/
|
|
143
|
+
export function verifyPdppGrantBinding(input) {
|
|
144
|
+
const { binding, chainGrant, deployment } = input;
|
|
145
|
+
// Record binding: the consent artifact presented must be the bound one.
|
|
146
|
+
if (binding.pdppGrantId !== input.pdppGrantId) {
|
|
147
|
+
throw new ScopeMismatchError({
|
|
148
|
+
requestedScope: "pdpp:binding",
|
|
149
|
+
reason: "PDPP grant id does not match the binding record",
|
|
150
|
+
expected: binding.pdppGrantId,
|
|
151
|
+
actual: input.pdppGrantId,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
// Deployment binding: a record from another PS deployment configuration is
|
|
155
|
+
// not evidence here. See module doc — this cannot be checked against the
|
|
156
|
+
// gateway response (it carries no chain/contract fields); it guards
|
|
157
|
+
// against the PS itself being reconfigured to a different deployment
|
|
158
|
+
// between when the binding was recorded and when it is read.
|
|
159
|
+
if (binding.permission.chainId !== deployment.chainId ||
|
|
160
|
+
binding.permission.contractAddress.toLowerCase() !==
|
|
161
|
+
deployment.contractAddress.toLowerCase()) {
|
|
162
|
+
throw new ScopeMismatchError({
|
|
163
|
+
requestedScope: "pdpp:binding",
|
|
164
|
+
reason: "Binding is for a different chain deployment",
|
|
165
|
+
expected: `${deployment.chainId}:${deployment.contractAddress}`,
|
|
166
|
+
actual: `${binding.permission.chainId}:${binding.permission.contractAddress}`,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
// Owner binding, against the server's current configuration.
|
|
170
|
+
if (!sameHex(binding.ownerAddress, input.serverOwner)) {
|
|
171
|
+
throw new GrantOwnerMismatchError({
|
|
172
|
+
grantId: binding.permission.permissionId,
|
|
173
|
+
expected: input.serverOwner,
|
|
174
|
+
actual: binding.ownerAddress,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
// App binding: the caller must BE the bound grantee wallet, not merely
|
|
178
|
+
// know its grant id.
|
|
179
|
+
if (!sameHex(input.requestSigner, binding.granteeAddress)) {
|
|
180
|
+
throw new InvalidSignatureError({
|
|
181
|
+
reason: "Request signer is not the bound grantee for this PDPP grant",
|
|
182
|
+
expected: binding.granteeAddress,
|
|
183
|
+
actual: input.requestSigner,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
// Revocation is read live. A missing chain grant is treated as revoked
|
|
187
|
+
// rather than as "unknown": failing open here would let a deleted or
|
|
188
|
+
// unreachable permission authorize reads.
|
|
189
|
+
if (!chainGrant) {
|
|
190
|
+
throw new GrantRevokedError({
|
|
191
|
+
grantId: binding.permission.permissionId,
|
|
192
|
+
reason: "Chain grant not found",
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
if (chainGrant.id !== binding.permission.permissionId) {
|
|
196
|
+
throw new ScopeMismatchError({
|
|
197
|
+
requestedScope: "pdpp:binding",
|
|
198
|
+
reason: "Chain grant id does not match the binding record",
|
|
199
|
+
expected: binding.permission.permissionId,
|
|
200
|
+
actual: chainGrant.id,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
if (chainGrant.revokedAt !== null && chainGrant.revokedAt !== undefined) {
|
|
204
|
+
throw new GrantRevokedError({ grantId: chainGrant.id });
|
|
205
|
+
}
|
|
206
|
+
if (!grantVersionStillAuthorizes(binding.grantVersion, chainGrant.grantVersion)) {
|
|
207
|
+
throw new InvalidSignatureError({
|
|
208
|
+
reason: "Chain grant version no longer matches the bound grantVersion",
|
|
209
|
+
expected: binding.grantVersion,
|
|
210
|
+
actual: chainGrant.grantVersion,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
// The live chain grant must still agree with the binding on both parties.
|
|
214
|
+
// These can diverge from the record only if the gateway is serving a
|
|
215
|
+
// different grant under the same id, which we must not paper over.
|
|
216
|
+
if (!sameHex(chainGrant.grantorAddress, binding.ownerAddress)) {
|
|
217
|
+
throw new GrantOwnerMismatchError({
|
|
218
|
+
grantId: chainGrant.id,
|
|
219
|
+
expected: binding.ownerAddress,
|
|
220
|
+
actual: chainGrant.grantorAddress ?? null,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
// Compare the live grant's builder id (`granteeId`) against the builder id
|
|
224
|
+
// retained on the binding (`binding.granteeId`) — NOT against
|
|
225
|
+
// `binding.granteeAddress`, which is a wallet. The wallet is what
|
|
226
|
+
// `requestSigner` proves above; this checks the separate, gateway-reported
|
|
227
|
+
// builder-id axis has not drifted.
|
|
228
|
+
if (!sameHex(chainGrant.granteeId, binding.granteeId)) {
|
|
229
|
+
throw new InvalidSignatureError({
|
|
230
|
+
reason: "Chain grant grantee no longer matches the bound grantee",
|
|
231
|
+
expected: binding.granteeId,
|
|
232
|
+
actual: chainGrant.granteeId,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=pdpp-binding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdpp-binding.js","sourceRoot":"","sources":["../../src/grants/pdpp-binding.ts"],"names":[],"mappings":"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"}
|