@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,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import qualifying synced DataPipe envelopes into the PDPP record store.
|
|
3
|
+
*
|
|
4
|
+
* The production path already existed end to end: Unity's OwnerDataClient
|
|
5
|
+
* writes an encrypted `DataFileEnvelope` and registers it with the Gateway,
|
|
6
|
+
* and `sync/workers/download.ts` downloads, decrypts and indexes it. What was
|
|
7
|
+
* missing was the last hop — that decrypted envelope reaching the PDPP record
|
|
8
|
+
* store, so a grant-bound client can read it. This module is that hop, and
|
|
9
|
+
* nothing else: it does not fetch, does not decrypt, and does not open a
|
|
10
|
+
* second ingestion surface. There is no web HTTP ingest here by design; the
|
|
11
|
+
* encrypted owner-data transport stays the only way data arrives.
|
|
12
|
+
*
|
|
13
|
+
* Why the metadata lives in `data.$pdpp`
|
|
14
|
+
* -------------------------------------
|
|
15
|
+
* The SDK's `DataFileEnvelopeSchema` accepts only `$schema`, `version`,
|
|
16
|
+
* `scope`, `schemaId`, `collectedAt` and `data`, and STRIPS unknown top-level
|
|
17
|
+
* keys. A `$pdpp` sibling of `scope` would therefore be silently deleted in
|
|
18
|
+
* transit — not rejected, deleted — so the producer nests it inside `data`,
|
|
19
|
+
* the one field whose interior the transport preserves verbatim. That is a
|
|
20
|
+
* transport constraint, not a preference.
|
|
21
|
+
*
|
|
22
|
+
* The consequence this module owns: `$pdpp` is import metadata that arrived
|
|
23
|
+
* inside the payload, so it must be removed before the record is stored.
|
|
24
|
+
* Otherwise every PDPP read would serve back a `$pdpp` blob that is not part
|
|
25
|
+
* of the source's declared schema, and a field projection computed from the
|
|
26
|
+
* declaration would not cover it.
|
|
27
|
+
*
|
|
28
|
+
* What is verified before anything is written
|
|
29
|
+
* -------------------------------------------
|
|
30
|
+
* Every check below is a fail-closed rejection, because the alternative is
|
|
31
|
+
* importing a record whose identity or authority we could not confirm:
|
|
32
|
+
*
|
|
33
|
+
* 1. `$pdpp.version === 1`. An unknown metadata version is refused rather
|
|
34
|
+
* than interpreted under this version's assumptions.
|
|
35
|
+
* 2. The declaration digest is recomputed over the EXACT retained
|
|
36
|
+
* declaration document this deployment booted with, and must equal the
|
|
37
|
+
* digest the producer claims. This is the check that makes the rest
|
|
38
|
+
* meaningful: without it the producer would be asserting its own
|
|
39
|
+
* authority over the stream shape it is being validated against.
|
|
40
|
+
* 3. `scope`, `stream.name` and `primaryKey` must agree with that same
|
|
41
|
+
* declaration, and `record.key` must agree with the payload's actual
|
|
42
|
+
* primary-key values.
|
|
43
|
+
*
|
|
44
|
+
* Only then is `$pdpp` stripped and the record handed to the store.
|
|
45
|
+
*
|
|
46
|
+
* Instance derivation is PS-owned
|
|
47
|
+
* -------------------------------
|
|
48
|
+
* The producer supplies no instance id and must not: an instance handle is a
|
|
49
|
+
* statement about this deployment's connection inventory, which the producer
|
|
50
|
+
* cannot observe. The importer derives it through the same function the
|
|
51
|
+
* authorization and resource servers use, so an imported record is readable
|
|
52
|
+
* under a grant issued for the same source. An id that cannot be derived is a
|
|
53
|
+
* rejection, never an invention.
|
|
54
|
+
*/
|
|
55
|
+
import type { PdppRecordStore, StreamSemantics } from "../storage/pdpp-records/index.js";
|
|
56
|
+
import type { Logger } from "../logger/index.js";
|
|
57
|
+
/** The reserved key carrying PDPP import metadata inside `data`. */
|
|
58
|
+
export declare const PDPP_METADATA_KEY = "$pdpp";
|
|
59
|
+
/** The only `$pdpp.version` this importer understands. */
|
|
60
|
+
export declare const SUPPORTED_PDPP_METADATA_VERSION = 1;
|
|
61
|
+
/**
|
|
62
|
+
* The stream shape the importer validates against, projected from the
|
|
63
|
+
* deployment's retained declaration. Deliberately not the full declaration
|
|
64
|
+
* model: the importer only needs to answer "does this envelope match the
|
|
65
|
+
* document we retained?".
|
|
66
|
+
*/
|
|
67
|
+
export interface ImportStreamShape {
|
|
68
|
+
name: string;
|
|
69
|
+
primaryKey: string[];
|
|
70
|
+
semantics: StreamSemantics;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* One retained declaration, as this deployment booted with it.
|
|
74
|
+
*
|
|
75
|
+
* The digest must be taken over the exact retained bytes, not over a
|
|
76
|
+
* re-serialization of a parsed snapshot. The distinction is the whole point
|
|
77
|
+
* of the check: the authorization store persists a parsed `snapshot_json`,
|
|
78
|
+
* and re-digesting that would produce a different value than the digest
|
|
79
|
+
* recorded at retrieval (key order, whitespace, and fields the parser does
|
|
80
|
+
* not carry). Digesting anything other than the retrieved bytes would be a
|
|
81
|
+
* check that passes against itself while proving nothing about what the
|
|
82
|
+
* producer actually read.
|
|
83
|
+
*/
|
|
84
|
+
export interface RetainedDeclaration {
|
|
85
|
+
sourceId: string;
|
|
86
|
+
version: string;
|
|
87
|
+
/**
|
|
88
|
+
* SHA-256 over the exact retained document, as bare lowercase hex.
|
|
89
|
+
*
|
|
90
|
+
* Passed in already computed rather than hashed here on purpose. This
|
|
91
|
+
* module is bundled into the browser lite runtime, where `node:crypto` does
|
|
92
|
+
* not exist; hashing here would break that build. The server computes it
|
|
93
|
+
* once at boot from the document it read — which is also the only place the
|
|
94
|
+
* original bytes exist — so doing it there costs nothing and keeps this
|
|
95
|
+
* module runtime-agnostic.
|
|
96
|
+
*/
|
|
97
|
+
documentDigest: string;
|
|
98
|
+
streams: ImportStreamShape[];
|
|
99
|
+
}
|
|
100
|
+
export type PdppImportRejectionCode = "no_metadata" | "malformed_metadata" | "unsupported_metadata_version" | "unknown_source" | "digest_mismatch" | "declaration_version_mismatch" | "scope_mismatch" | "unknown_stream" | "primary_key_mismatch" | "semantics_mismatch" | "record_key_mismatch" | "no_instance" | "method_authority" | "store_rejected";
|
|
101
|
+
export interface PdppImportRejection {
|
|
102
|
+
code: PdppImportRejectionCode;
|
|
103
|
+
message: string;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Whether a rejection is a settled verdict about the envelope itself.
|
|
107
|
+
*
|
|
108
|
+
* Callers use this to decide whether re-offering the same envelope later
|
|
109
|
+
* could ever change the answer. Fail-closed by construction: an unrecognized
|
|
110
|
+
* code is treated as transient, so a new failure mode is retried (visibly,
|
|
111
|
+
* with a logged outcome) rather than silently abandoned.
|
|
112
|
+
*/
|
|
113
|
+
export declare function isPermanentRejection(rejection: PdppImportRejection): boolean;
|
|
114
|
+
export type PdppImportOutcome =
|
|
115
|
+
/** Not a PDPP-bearing envelope. Legacy-only, and not an error. */
|
|
116
|
+
{
|
|
117
|
+
status: "skipped";
|
|
118
|
+
}
|
|
119
|
+
/** Imported a new version. */
|
|
120
|
+
| {
|
|
121
|
+
status: "imported";
|
|
122
|
+
instance: string;
|
|
123
|
+
stream: string;
|
|
124
|
+
recordKey: string;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Verified and already present unchanged. Deliberately distinct from
|
|
128
|
+
* "imported": re-writing it would allocate a new version and publish a
|
|
129
|
+
* spurious `changes_since` entry for a record that did not change.
|
|
130
|
+
*/
|
|
131
|
+
| {
|
|
132
|
+
status: "unchanged";
|
|
133
|
+
instance: string;
|
|
134
|
+
stream: string;
|
|
135
|
+
recordKey: string;
|
|
136
|
+
} | {
|
|
137
|
+
status: "rejected";
|
|
138
|
+
rejection: PdppImportRejection;
|
|
139
|
+
};
|
|
140
|
+
/** The envelope fields this importer reads. */
|
|
141
|
+
export interface ImportableEnvelope {
|
|
142
|
+
scope: string;
|
|
143
|
+
collectedAt: string;
|
|
144
|
+
data: unknown;
|
|
145
|
+
}
|
|
146
|
+
export interface PdppImporterDeps {
|
|
147
|
+
store: PdppRecordStore;
|
|
148
|
+
/** The exact declarations this deployment retained at boot. */
|
|
149
|
+
declarations: RetainedDeclaration[];
|
|
150
|
+
/**
|
|
151
|
+
* PS-owned instance derivation, wired to the same inventory the AS and RS
|
|
152
|
+
* use so an imported record is readable under a grant for that source.
|
|
153
|
+
*/
|
|
154
|
+
instanceFor: (sourceId: string) => string | undefined;
|
|
155
|
+
logger: Logger;
|
|
156
|
+
}
|
|
157
|
+
export interface PdppImporter {
|
|
158
|
+
/** Import one decrypted envelope. Never throws; failures are outcomes. */
|
|
159
|
+
importEnvelope(envelope: ImportableEnvelope): PdppImportOutcome;
|
|
160
|
+
/**
|
|
161
|
+
* Whether re-offering this already-indexed (scope, collectedAt) could still
|
|
162
|
+
* change anything.
|
|
163
|
+
*
|
|
164
|
+
* The retry path uses this to decide whether reading the envelope back off
|
|
165
|
+
* disk is worth doing at all. It answers false once an offer for that exact
|
|
166
|
+
* version has settled — imported, verified-unchanged, permanently rejected,
|
|
167
|
+
* or found to carry no `$pdpp` — because none of those can be changed by
|
|
168
|
+
* looking again. It answers true for a version never offered, and for one
|
|
169
|
+
* whose last attempt failed transiently.
|
|
170
|
+
*
|
|
171
|
+
* Deliberately in-memory and process-scoped. The answers it caches are all
|
|
172
|
+
* re-derivable: after a restart the first cycle re-reads each entry once and
|
|
173
|
+
* re-settles it. Persisting them would add schema and a migration to avoid
|
|
174
|
+
* a single bounded read per entry per boot, and would risk a stale "settled"
|
|
175
|
+
* row outliving the condition that produced it — the exact class of bug this
|
|
176
|
+
* whole retry path exists to fix.
|
|
177
|
+
*/
|
|
178
|
+
needsRetry(scope: string, collectedAt: string): boolean;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Normalize a claimed digest to bare lowercase hex.
|
|
182
|
+
*
|
|
183
|
+
* The producer contract writes `sha256:<hex>`; this repo's
|
|
184
|
+
* `computeDeclarationDigest` returns bare hex with no prefix. Accepting both
|
|
185
|
+
* spellings of the same SHA-256 value keeps the two sides interoperable
|
|
186
|
+
* without either silently coercing the other. Any OTHER algorithm prefix
|
|
187
|
+
* returns null and fails the import: treating `md5:...` as if it were the
|
|
188
|
+
* SHA-256 we computed would turn the digest check into decoration.
|
|
189
|
+
*/
|
|
190
|
+
export declare function normalizeDigest(claimed: string): string | null;
|
|
191
|
+
export declare function createPdppImporter(deps: PdppImporterDeps): PdppImporter;
|
|
192
|
+
//# sourceMappingURL=pdpp-import.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdpp-import.d.ts","sourceRoot":"","sources":["../../src/sync/pdpp-import.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AAEH,OAAO,KAAK,EAEV,eAAe,EACf,eAAe,EAChB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAEjD,oEAAoE;AACpE,eAAO,MAAM,iBAAiB,UAAU,CAAC;AAEzC,0DAA0D;AAC1D,eAAO,MAAM,+BAA+B,IAAI,CAAC;AAEjD;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;;OASG;IACH,cAAc,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,iBAAiB,EAAE,CAAC;CAC9B;AAED,MAAM,MAAM,uBAAuB,GAC/B,aAAa,GACb,oBAAoB,GACpB,8BAA8B,GAC9B,gBAAgB,GAChB,iBAAiB,GACjB,8BAA8B,GAC9B,gBAAgB,GAChB,gBAAgB,GAChB,sBAAsB,GACtB,oBAAoB,GACpB,qBAAqB,GACrB,aAAa,GACb,kBAAkB,GAClB,gBAAgB,CAAC;AAErB,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,uBAAuB,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;CACjB;AA+CD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,mBAAmB,GAAG,OAAO,CAE5E;AAED,MAAM,MAAM,iBAAiB;AAC3B,kEAAkE;AAChE;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE;AACvB,8BAA8B;GAC5B;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AAC7E;;;;GAIG;GACD;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC5E;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,SAAS,EAAE,mBAAmB,CAAA;CAAE,CAAC;AAE3D,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,eAAe,CAAC;IACvB,+DAA+D;IAC/D,YAAY,EAAE,mBAAmB,EAAE,CAAC;IACpC;;;OAGG;IACH,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IACtD,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,YAAY;IAC3B,0EAA0E;IAC1E,cAAc,CAAC,QAAQ,EAAE,kBAAkB,GAAG,iBAAiB,CAAC;IAChE;;;;;;;;;;;;;;;;;OAiBG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;CACzD;AA4BD;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO9D;AAgJD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,CAqPvE"}
|
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Import qualifying synced DataPipe envelopes into the PDPP record store.
|
|
3
|
+
*
|
|
4
|
+
* The production path already existed end to end: Unity's OwnerDataClient
|
|
5
|
+
* writes an encrypted `DataFileEnvelope` and registers it with the Gateway,
|
|
6
|
+
* and `sync/workers/download.ts` downloads, decrypts and indexes it. What was
|
|
7
|
+
* missing was the last hop — that decrypted envelope reaching the PDPP record
|
|
8
|
+
* store, so a grant-bound client can read it. This module is that hop, and
|
|
9
|
+
* nothing else: it does not fetch, does not decrypt, and does not open a
|
|
10
|
+
* second ingestion surface. There is no web HTTP ingest here by design; the
|
|
11
|
+
* encrypted owner-data transport stays the only way data arrives.
|
|
12
|
+
*
|
|
13
|
+
* Why the metadata lives in `data.$pdpp`
|
|
14
|
+
* -------------------------------------
|
|
15
|
+
* The SDK's `DataFileEnvelopeSchema` accepts only `$schema`, `version`,
|
|
16
|
+
* `scope`, `schemaId`, `collectedAt` and `data`, and STRIPS unknown top-level
|
|
17
|
+
* keys. A `$pdpp` sibling of `scope` would therefore be silently deleted in
|
|
18
|
+
* transit — not rejected, deleted — so the producer nests it inside `data`,
|
|
19
|
+
* the one field whose interior the transport preserves verbatim. That is a
|
|
20
|
+
* transport constraint, not a preference.
|
|
21
|
+
*
|
|
22
|
+
* The consequence this module owns: `$pdpp` is import metadata that arrived
|
|
23
|
+
* inside the payload, so it must be removed before the record is stored.
|
|
24
|
+
* Otherwise every PDPP read would serve back a `$pdpp` blob that is not part
|
|
25
|
+
* of the source's declared schema, and a field projection computed from the
|
|
26
|
+
* declaration would not cover it.
|
|
27
|
+
*
|
|
28
|
+
* What is verified before anything is written
|
|
29
|
+
* -------------------------------------------
|
|
30
|
+
* Every check below is a fail-closed rejection, because the alternative is
|
|
31
|
+
* importing a record whose identity or authority we could not confirm:
|
|
32
|
+
*
|
|
33
|
+
* 1. `$pdpp.version === 1`. An unknown metadata version is refused rather
|
|
34
|
+
* than interpreted under this version's assumptions.
|
|
35
|
+
* 2. The declaration digest is recomputed over the EXACT retained
|
|
36
|
+
* declaration document this deployment booted with, and must equal the
|
|
37
|
+
* digest the producer claims. This is the check that makes the rest
|
|
38
|
+
* meaningful: without it the producer would be asserting its own
|
|
39
|
+
* authority over the stream shape it is being validated against.
|
|
40
|
+
* 3. `scope`, `stream.name` and `primaryKey` must agree with that same
|
|
41
|
+
* declaration, and `record.key` must agree with the payload's actual
|
|
42
|
+
* primary-key values.
|
|
43
|
+
*
|
|
44
|
+
* Only then is `$pdpp` stripped and the record handed to the store.
|
|
45
|
+
*
|
|
46
|
+
* Instance derivation is PS-owned
|
|
47
|
+
* -------------------------------
|
|
48
|
+
* The producer supplies no instance id and must not: an instance handle is a
|
|
49
|
+
* statement about this deployment's connection inventory, which the producer
|
|
50
|
+
* cannot observe. The importer derives it through the same function the
|
|
51
|
+
* authorization and resource servers use, so an imported record is readable
|
|
52
|
+
* under a grant issued for the same source. An id that cannot be derived is a
|
|
53
|
+
* rejection, never an invention.
|
|
54
|
+
*/
|
|
55
|
+
import { computeRecordKeyFromData } from "../storage/pdpp-records/record-key.js";
|
|
56
|
+
/** The reserved key carrying PDPP import metadata inside `data`. */
|
|
57
|
+
export const PDPP_METADATA_KEY = "$pdpp";
|
|
58
|
+
/** The only `$pdpp.version` this importer understands. */
|
|
59
|
+
export const SUPPORTED_PDPP_METADATA_VERSION = 1;
|
|
60
|
+
/**
|
|
61
|
+
* Rejection codes that describe the ENVELOPE rather than this deployment's
|
|
62
|
+
* current state. They are permanent verdicts: the same bytes re-read on a
|
|
63
|
+
* later cycle produce the same answer, so retrying them is work that can
|
|
64
|
+
* never succeed.
|
|
65
|
+
*
|
|
66
|
+
* `unknown_source` and `no_instance` are deliberately NOT here. Both depend
|
|
67
|
+
* on what this deployment has mounted — a declaration that is not retained
|
|
68
|
+
* yet, or an instance inventory that is not populated yet — and both start
|
|
69
|
+
* working once boot completes or an operator provisions the declaration.
|
|
70
|
+
* Treating them as permanent is exactly how an envelope gets stranded.
|
|
71
|
+
* `store_rejected` is likewise excluded: the store is infrastructure, and a
|
|
72
|
+
* write it refuses today may be accepted once it is healthy.
|
|
73
|
+
* `method_authority` IS here: the importer carries no acquisition method, so
|
|
74
|
+
* the store's method and binding checks (P8a, P8c) refuse it on every cycle.
|
|
75
|
+
*/
|
|
76
|
+
const PERMANENT_REJECTION_CODES = new Set([
|
|
77
|
+
"malformed_metadata",
|
|
78
|
+
"unsupported_metadata_version",
|
|
79
|
+
"digest_mismatch",
|
|
80
|
+
"declaration_version_mismatch",
|
|
81
|
+
"scope_mismatch",
|
|
82
|
+
"unknown_stream",
|
|
83
|
+
"primary_key_mismatch",
|
|
84
|
+
"semantics_mismatch",
|
|
85
|
+
"record_key_mismatch",
|
|
86
|
+
"method_authority",
|
|
87
|
+
]);
|
|
88
|
+
/**
|
|
89
|
+
* Store reasons from the method and binding checks. The importer writes
|
|
90
|
+
* without a method, so none of these can clear on a later cycle.
|
|
91
|
+
*/
|
|
92
|
+
const METHOD_AUTHORITY_REASONS = new Set([
|
|
93
|
+
"method_required",
|
|
94
|
+
"method_inactive",
|
|
95
|
+
"config_multiple_active_methods",
|
|
96
|
+
"binding_generation_mismatch",
|
|
97
|
+
"instance_bound_to_other_method",
|
|
98
|
+
"binding_required",
|
|
99
|
+
"blob_unclaimed",
|
|
100
|
+
]);
|
|
101
|
+
/**
|
|
102
|
+
* Whether a rejection is a settled verdict about the envelope itself.
|
|
103
|
+
*
|
|
104
|
+
* Callers use this to decide whether re-offering the same envelope later
|
|
105
|
+
* could ever change the answer. Fail-closed by construction: an unrecognized
|
|
106
|
+
* code is treated as transient, so a new failure mode is retried (visibly,
|
|
107
|
+
* with a logged outcome) rather than silently abandoned.
|
|
108
|
+
*/
|
|
109
|
+
export function isPermanentRejection(rejection) {
|
|
110
|
+
return PERMANENT_REJECTION_CODES.has(rejection.code);
|
|
111
|
+
}
|
|
112
|
+
function reject(code, message) {
|
|
113
|
+
return { status: "rejected", rejection: { code, message } };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Normalize a claimed digest to bare lowercase hex.
|
|
117
|
+
*
|
|
118
|
+
* The producer contract writes `sha256:<hex>`; this repo's
|
|
119
|
+
* `computeDeclarationDigest` returns bare hex with no prefix. Accepting both
|
|
120
|
+
* spellings of the same SHA-256 value keeps the two sides interoperable
|
|
121
|
+
* without either silently coercing the other. Any OTHER algorithm prefix
|
|
122
|
+
* returns null and fails the import: treating `md5:...` as if it were the
|
|
123
|
+
* SHA-256 we computed would turn the digest check into decoration.
|
|
124
|
+
*/
|
|
125
|
+
export function normalizeDigest(claimed) {
|
|
126
|
+
const trimmed = claimed.trim().toLowerCase();
|
|
127
|
+
const colon = trimmed.indexOf(":");
|
|
128
|
+
if (colon === -1)
|
|
129
|
+
return /^[0-9a-f]{64}$/.test(trimmed) ? trimmed : null;
|
|
130
|
+
if (trimmed.slice(0, colon) !== "sha256")
|
|
131
|
+
return null;
|
|
132
|
+
const hex = trimmed.slice(colon + 1);
|
|
133
|
+
return /^[0-9a-f]{64}$/.test(hex) ? hex : null;
|
|
134
|
+
}
|
|
135
|
+
function isRecord(value) {
|
|
136
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Read `data.$pdpp` into a typed shape, or explain why it is not usable.
|
|
140
|
+
*
|
|
141
|
+
* Returns `null` for "no metadata present", which is the ordinary legacy
|
|
142
|
+
* case and must stay distinguishable from a malformed `$pdpp` — a producer
|
|
143
|
+
* that writes broken metadata should be visible, not silently treated as a
|
|
144
|
+
* legacy write.
|
|
145
|
+
*/
|
|
146
|
+
function readMetadata(data) {
|
|
147
|
+
if (!isRecord(data))
|
|
148
|
+
return null;
|
|
149
|
+
const raw = data[PDPP_METADATA_KEY];
|
|
150
|
+
if (raw === undefined)
|
|
151
|
+
return null;
|
|
152
|
+
if (!isRecord(raw))
|
|
153
|
+
return { ok: false, reason: "$pdpp is not an object" };
|
|
154
|
+
if (typeof raw.version !== "number") {
|
|
155
|
+
return { ok: false, reason: "$pdpp.version is missing or not a number" };
|
|
156
|
+
}
|
|
157
|
+
if (typeof raw.sourceId !== "string" || raw.sourceId.length === 0) {
|
|
158
|
+
return { ok: false, reason: "$pdpp.sourceId is missing" };
|
|
159
|
+
}
|
|
160
|
+
const declaration = raw.declaration;
|
|
161
|
+
if (!isRecord(declaration)) {
|
|
162
|
+
return { ok: false, reason: "$pdpp.declaration is missing" };
|
|
163
|
+
}
|
|
164
|
+
if (typeof declaration.digest !== "string" ||
|
|
165
|
+
declaration.digest.length === 0) {
|
|
166
|
+
return { ok: false, reason: "$pdpp.declaration.digest is missing" };
|
|
167
|
+
}
|
|
168
|
+
if (typeof declaration.version !== "string") {
|
|
169
|
+
return { ok: false, reason: "$pdpp.declaration.version is missing" };
|
|
170
|
+
}
|
|
171
|
+
const stream = raw.stream;
|
|
172
|
+
if (!isRecord(stream))
|
|
173
|
+
return { ok: false, reason: "$pdpp.stream is missing" };
|
|
174
|
+
if (typeof stream.name !== "string" || stream.name.length === 0) {
|
|
175
|
+
return { ok: false, reason: "$pdpp.stream.name is missing" };
|
|
176
|
+
}
|
|
177
|
+
if (typeof stream.scope !== "string" || stream.scope.length === 0) {
|
|
178
|
+
return { ok: false, reason: "$pdpp.stream.scope is missing" };
|
|
179
|
+
}
|
|
180
|
+
if (!Array.isArray(stream.primaryKey) ||
|
|
181
|
+
stream.primaryKey.length === 0 ||
|
|
182
|
+
!stream.primaryKey.every((f) => typeof f === "string")) {
|
|
183
|
+
return { ok: false, reason: "$pdpp.stream.primaryKey is missing" };
|
|
184
|
+
}
|
|
185
|
+
const record = raw.record;
|
|
186
|
+
if (!isRecord(record))
|
|
187
|
+
return { ok: false, reason: "$pdpp.record is missing" };
|
|
188
|
+
if (!isRecord(record.key)) {
|
|
189
|
+
return { ok: false, reason: "$pdpp.record.key is missing" };
|
|
190
|
+
}
|
|
191
|
+
const op = record.op ?? "upsert";
|
|
192
|
+
if (op !== "upsert" && op !== "delete") {
|
|
193
|
+
return {
|
|
194
|
+
ok: false,
|
|
195
|
+
reason: `$pdpp.record.op '${String(op)}' is not valid`,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
ok: true,
|
|
200
|
+
meta: {
|
|
201
|
+
version: raw.version,
|
|
202
|
+
sourceId: raw.sourceId,
|
|
203
|
+
declaration: {
|
|
204
|
+
source: typeof declaration.source === "string" ? declaration.source : "",
|
|
205
|
+
version: declaration.version,
|
|
206
|
+
upstreamCommit: typeof declaration.upstreamCommit === "string"
|
|
207
|
+
? declaration.upstreamCommit
|
|
208
|
+
: null,
|
|
209
|
+
digest: declaration.digest,
|
|
210
|
+
},
|
|
211
|
+
stream: {
|
|
212
|
+
name: stream.name,
|
|
213
|
+
scope: stream.scope,
|
|
214
|
+
semantics: typeof stream.semantics === "string" ? stream.semantics : "",
|
|
215
|
+
primaryKey: stream.primaryKey,
|
|
216
|
+
},
|
|
217
|
+
record: { key: record.key, op },
|
|
218
|
+
...(isRecord(raw.run) && {
|
|
219
|
+
run: {
|
|
220
|
+
...(typeof raw.run.id === "string" && { id: raw.run.id }),
|
|
221
|
+
...(typeof raw.run.source === "string" && { source: raw.run.source }),
|
|
222
|
+
},
|
|
223
|
+
}),
|
|
224
|
+
},
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/** Remove `$pdpp` without mutating the caller's object. */
|
|
228
|
+
function stripMetadata(data) {
|
|
229
|
+
const { [PDPP_METADATA_KEY]: _dropped, ...rest } = data;
|
|
230
|
+
return rest;
|
|
231
|
+
}
|
|
232
|
+
function sameArray(a, b) {
|
|
233
|
+
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Deep structural equality over JSON-shaped values.
|
|
237
|
+
*
|
|
238
|
+
* Used only to decide "did this record actually change?". Key order must not
|
|
239
|
+
* count as a change: the producer re-serializes the payload on every run, so
|
|
240
|
+
* an order-sensitive comparison would report every re-sync as a new version
|
|
241
|
+
* and fill `changes_since` with records that are byte-identical to what a
|
|
242
|
+
* client already read.
|
|
243
|
+
*/
|
|
244
|
+
function jsonEqual(a, b) {
|
|
245
|
+
if (a === b)
|
|
246
|
+
return true;
|
|
247
|
+
if (typeof a !== typeof b)
|
|
248
|
+
return false;
|
|
249
|
+
if (a === null || b === null)
|
|
250
|
+
return false;
|
|
251
|
+
if (Array.isArray(a) || Array.isArray(b)) {
|
|
252
|
+
if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
return a.every((item, i) => jsonEqual(item, b[i]));
|
|
256
|
+
}
|
|
257
|
+
if (typeof a !== "object")
|
|
258
|
+
return false;
|
|
259
|
+
const ao = a;
|
|
260
|
+
const bo = b;
|
|
261
|
+
const aKeys = Object.keys(ao).sort();
|
|
262
|
+
const bKeys = Object.keys(bo).sort();
|
|
263
|
+
if (!sameArray(aKeys, bKeys))
|
|
264
|
+
return false;
|
|
265
|
+
return aKeys.every((k) => jsonEqual(ao[k], bo[k]));
|
|
266
|
+
}
|
|
267
|
+
export function createPdppImporter(deps) {
|
|
268
|
+
const { store, logger } = deps;
|
|
269
|
+
const bySourceId = new Map();
|
|
270
|
+
for (const declaration of deps.declarations) {
|
|
271
|
+
bySourceId.set(declaration.sourceId, declaration);
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Versions whose import outcome cannot change on a later offer. Bounded by
|
|
275
|
+
* the number of distinct (scope, collectedAt) pairs this process sees, and
|
|
276
|
+
* holding only a short key per entry.
|
|
277
|
+
*/
|
|
278
|
+
const settled = new Set();
|
|
279
|
+
const versionKey = (scope, collectedAt) => `${scope}@${collectedAt}`;
|
|
280
|
+
function needsRetry(scope, collectedAt) {
|
|
281
|
+
return !settled.has(versionKey(scope, collectedAt));
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Record whether this version is done with, so the retry path can stop
|
|
285
|
+
* reading it back off disk every cycle.
|
|
286
|
+
*
|
|
287
|
+
* Only a transient rejection stays unsettled — that is the one outcome a
|
|
288
|
+
* later cycle can genuinely improve on.
|
|
289
|
+
*/
|
|
290
|
+
function importAndSettle(envelope) {
|
|
291
|
+
const outcome = importEnvelope(envelope);
|
|
292
|
+
const retryable = outcome.status === "rejected" && !isPermanentRejection(outcome.rejection);
|
|
293
|
+
if (!retryable) {
|
|
294
|
+
settled.add(versionKey(envelope.scope, envelope.collectedAt));
|
|
295
|
+
}
|
|
296
|
+
return outcome;
|
|
297
|
+
}
|
|
298
|
+
function importEnvelope(envelope) {
|
|
299
|
+
const read = readMetadata(envelope.data);
|
|
300
|
+
if (read === null)
|
|
301
|
+
return { status: "skipped" };
|
|
302
|
+
if (!read.ok)
|
|
303
|
+
return reject("malformed_metadata", read.reason);
|
|
304
|
+
const meta = read.meta;
|
|
305
|
+
if (meta.version !== SUPPORTED_PDPP_METADATA_VERSION) {
|
|
306
|
+
return reject("unsupported_metadata_version", `$pdpp.version ${meta.version} is not supported (expected ${SUPPORTED_PDPP_METADATA_VERSION})`);
|
|
307
|
+
}
|
|
308
|
+
const retained = bySourceId.get(meta.sourceId);
|
|
309
|
+
if (!retained) {
|
|
310
|
+
return reject("unknown_source", `no retained declaration for source '${meta.sourceId}'`);
|
|
311
|
+
}
|
|
312
|
+
// The digest gate. Everything after this point is validated against a
|
|
313
|
+
// document we have confirmed is the one the producer claims to have read.
|
|
314
|
+
const claimed = normalizeDigest(meta.declaration.digest);
|
|
315
|
+
if (claimed === null) {
|
|
316
|
+
return reject("digest_mismatch", `declaration digest '${meta.declaration.digest}' is not a recognized sha256 digest`);
|
|
317
|
+
}
|
|
318
|
+
if (claimed !== retained.documentDigest.trim().toLowerCase()) {
|
|
319
|
+
return reject("digest_mismatch", `declaration digest does not match the retained declaration for '${meta.sourceId}'`);
|
|
320
|
+
}
|
|
321
|
+
if (meta.declaration.version !== retained.version) {
|
|
322
|
+
return reject("declaration_version_mismatch", `declaration version '${meta.declaration.version}' does not match retained version '${retained.version}'`);
|
|
323
|
+
}
|
|
324
|
+
// The scope the envelope was transported under must be the scope the
|
|
325
|
+
// metadata claims. Without this, metadata for one scope could ride on a
|
|
326
|
+
// blob decrypted under another scope's key.
|
|
327
|
+
if (meta.stream.scope !== envelope.scope) {
|
|
328
|
+
return reject("scope_mismatch", `$pdpp.stream.scope '${meta.stream.scope}' does not match envelope scope '${envelope.scope}'`);
|
|
329
|
+
}
|
|
330
|
+
const declaredStream = retained.streams.find((s) => s.name === meta.stream.name);
|
|
331
|
+
if (!declaredStream) {
|
|
332
|
+
return reject("unknown_stream", `stream '${meta.stream.name}' is not declared by the retained declaration for '${meta.sourceId}'`);
|
|
333
|
+
}
|
|
334
|
+
if (!sameArray(meta.stream.primaryKey, declaredStream.primaryKey)) {
|
|
335
|
+
return reject("primary_key_mismatch", `stream '${meta.stream.name}' declares primary key [${declaredStream.primaryKey.join(", ")}] but the envelope claims [${meta.stream.primaryKey.join(", ")}]`);
|
|
336
|
+
}
|
|
337
|
+
if (meta.stream.semantics.length > 0 &&
|
|
338
|
+
meta.stream.semantics !== declaredStream.semantics) {
|
|
339
|
+
return reject("semantics_mismatch", `stream '${meta.stream.name}' is ${declaredStream.semantics} here but the envelope claims '${meta.stream.semantics}'`);
|
|
340
|
+
}
|
|
341
|
+
const instance = deps.instanceFor(meta.sourceId);
|
|
342
|
+
if (!instance) {
|
|
343
|
+
return reject("no_instance", `no instance handle could be derived for source '${meta.sourceId}'`);
|
|
344
|
+
}
|
|
345
|
+
if (!isRecord(envelope.data)) {
|
|
346
|
+
return reject("malformed_metadata", "envelope data is not an object");
|
|
347
|
+
}
|
|
348
|
+
const payload = stripMetadata(envelope.data);
|
|
349
|
+
// `record.key` is the producer's claim about identity; the payload is the
|
|
350
|
+
// record. They must agree, or the record would be stored under a key that
|
|
351
|
+
// does not describe it — and a grant naming that key would authorize the
|
|
352
|
+
// wrong row.
|
|
353
|
+
let keyFromData;
|
|
354
|
+
let keyFromClaim;
|
|
355
|
+
try {
|
|
356
|
+
keyFromData = computeRecordKeyFromData(payload, declaredStream.primaryKey);
|
|
357
|
+
keyFromClaim = computeRecordKeyFromData(meta.record.key, declaredStream.primaryKey);
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
return reject("record_key_mismatch", err.message);
|
|
361
|
+
}
|
|
362
|
+
if (keyFromData !== keyFromClaim) {
|
|
363
|
+
return reject("record_key_mismatch", "$pdpp.record.key does not match the payload's primary key values");
|
|
364
|
+
}
|
|
365
|
+
// Idempotency. `ingestBatch` allocates a NEW version on every accepted
|
|
366
|
+
// mutable_state upsert, so an unconditional re-ingest would bump the
|
|
367
|
+
// version and publish a `changes_since` entry every time the sync worker
|
|
368
|
+
// re-downloads an unchanged record — which it does on any full reconcile
|
|
369
|
+
// or retry. Comparing against the stored row first is what makes a repeat
|
|
370
|
+
// sync a no-op rather than a fabricated change.
|
|
371
|
+
// `getRecord` returns undefined for a deleted row as well as an absent
|
|
372
|
+
// one, which is exactly the distinction both branches below need.
|
|
373
|
+
const existing = store.getRecord(instance, meta.stream.name, keyFromData);
|
|
374
|
+
const unchanged = {
|
|
375
|
+
status: "unchanged",
|
|
376
|
+
instance,
|
|
377
|
+
stream: meta.stream.name,
|
|
378
|
+
recordKey: keyFromData,
|
|
379
|
+
};
|
|
380
|
+
if (meta.record.op === "delete") {
|
|
381
|
+
// A delete for a record we do not currently hold changes nothing.
|
|
382
|
+
// Ingesting it would write a tombstone announcing the removal of
|
|
383
|
+
// something this store never served — a fabricated change.
|
|
384
|
+
if (!existing)
|
|
385
|
+
return unchanged;
|
|
386
|
+
}
|
|
387
|
+
else if (existing &&
|
|
388
|
+
jsonEqual(existing.data, payload) &&
|
|
389
|
+
existing.emittedAt === envelope.collectedAt) {
|
|
390
|
+
return unchanged;
|
|
391
|
+
}
|
|
392
|
+
// A single-field key must stay a bare string. `encodeRecordKey` treats an
|
|
393
|
+
// array as a COMPOUND key and JSON-encodes it, so wrapping a lone value
|
|
394
|
+
// in an array would produce `["235680975"]` where the data yields
|
|
395
|
+
// `235680975` — a key/data mismatch the store rejects, on every record of
|
|
396
|
+
// every single-key stream.
|
|
397
|
+
const components = declaredStream.primaryKey.map((f) => String(payload[f]));
|
|
398
|
+
const input = {
|
|
399
|
+
instance,
|
|
400
|
+
stream: meta.stream.name,
|
|
401
|
+
key: components.length === 1 ? components[0] : components,
|
|
402
|
+
data: meta.record.op === "delete" ? null : payload,
|
|
403
|
+
emitted_at: envelope.collectedAt,
|
|
404
|
+
op: meta.record.op,
|
|
405
|
+
};
|
|
406
|
+
// One envelope per call, but through the batch API so the store's own
|
|
407
|
+
// transaction wraps the write: a failure rolls back rather than leaving
|
|
408
|
+
// a row without its history entry.
|
|
409
|
+
const result = store.ingestBatch([input], () => declaredStream.semantics, () => declaredStream.primaryKey);
|
|
410
|
+
if (result.rejected.length > 0) {
|
|
411
|
+
const reason = result.rejected[0].reason;
|
|
412
|
+
return reject(METHOD_AUTHORITY_REASONS.has(reason)
|
|
413
|
+
? "method_authority"
|
|
414
|
+
: "store_rejected", reason);
|
|
415
|
+
}
|
|
416
|
+
if (result.accepted === 0) {
|
|
417
|
+
// append_only duplicate: the store treats it as a no-op, and so do we.
|
|
418
|
+
return {
|
|
419
|
+
status: "unchanged",
|
|
420
|
+
instance,
|
|
421
|
+
stream: meta.stream.name,
|
|
422
|
+
recordKey: keyFromData,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
logger.info({
|
|
426
|
+
instance,
|
|
427
|
+
stream: meta.stream.name,
|
|
428
|
+
sourceId: meta.sourceId,
|
|
429
|
+
op: meta.record.op,
|
|
430
|
+
...(meta.run?.id && { runId: meta.run.id }),
|
|
431
|
+
}, "Imported synced DataPipe record into the PDPP record store");
|
|
432
|
+
return {
|
|
433
|
+
status: "imported",
|
|
434
|
+
instance,
|
|
435
|
+
stream: meta.stream.name,
|
|
436
|
+
recordKey: keyFromData,
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
return { importEnvelope: importAndSettle, needsRetry };
|
|
440
|
+
}
|
|
441
|
+
//# sourceMappingURL=pdpp-import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pdpp-import.js","sourceRoot":"","sources":["../../src/sync/pdpp-import.ts"],"names":[],"mappings":"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"}
|