@opendatalabs/personal-server-ts-core 1.5.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/index.d.ts +41 -0
- package/dist/api/index.d.ts.map +1 -1
- package/dist/api/index.js +298 -87
- package/dist/api/index.js.map +1 -1
- package/dist/contracts/binary.d.ts +12 -0
- package/dist/contracts/binary.d.ts.map +1 -1
- package/dist/contracts/binary.js +31 -0
- package/dist/contracts/binary.js.map +1 -1
- package/dist/contracts/data.d.ts +35 -0
- package/dist/contracts/data.d.ts.map +1 -1
- package/dist/contracts/data.js +96 -14
- 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/contracts/index.js +1 -1
- package/dist/contracts/index.js.map +1 -1
- package/dist/errors/catalog.d.ts +34 -0
- package/dist/errors/catalog.d.ts.map +1 -1
- package/dist/errors/catalog.js +41 -0
- package/dist/errors/catalog.js.map +1 -1
- package/dist/lineage/attestation.d.ts +42 -0
- package/dist/lineage/attestation.d.ts.map +1 -0
- package/dist/lineage/attestation.js +25 -0
- package/dist/lineage/attestation.js.map +1 -0
- package/dist/lineage/gateway.d.ts +105 -0
- package/dist/lineage/gateway.d.ts.map +1 -0
- package/dist/lineage/gateway.js +242 -0
- package/dist/lineage/gateway.js.map +1 -0
- package/dist/lineage/index.d.ts +5 -0
- package/dist/lineage/index.d.ts.map +1 -0
- package/dist/lineage/index.js +5 -0
- package/dist/lineage/index.js.map +1 -0
- package/dist/lineage/lineage.d.ts +141 -0
- package/dist/lineage/lineage.d.ts.map +1 -0
- package/dist/lineage/lineage.js +255 -0
- package/dist/lineage/lineage.js.map +1 -0
- package/dist/logging/access-log.d.ts +1 -1
- package/dist/logging/access-log.d.ts.map +1 -1
- package/dist/policy/data-read.d.ts +8 -0
- package/dist/policy/data-read.d.ts.map +1 -1
- package/dist/policy/data-read.js +9 -2
- package/dist/policy/data-read.js.map +1 -1
- package/dist/policy/data-write.d.ts +69 -0
- package/dist/policy/data-write.d.ts.map +1 -0
- package/dist/policy/data-write.js +131 -0
- package/dist/policy/data-write.js.map +1 -0
- package/dist/policy/index.d.ts +2 -1
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +2 -1
- package/dist/policy/index.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/signing/signer.d.ts +8 -0
- package/dist/signing/signer.d.ts.map +1 -1
- package/dist/signing/signer.js +9 -0
- package/dist/signing/signer.js.map +1 -1
- package/dist/sync/data-point-id.d.ts +7 -0
- package/dist/sync/data-point-id.d.ts.map +1 -0
- package/dist/sync/data-point-id.js +16 -0
- package/dist/sync/data-point-id.js.map +1 -0
- package/dist/sync/workers/upload.d.ts +10 -6
- package/dist/sync/workers/upload.d.ts.map +1 -1
- package/dist/sync/workers/upload.js +39 -17
- package/dist/sync/workers/upload.js.map +1 -1
- package/dist/write/attribution.d.ts +167 -0
- package/dist/write/attribution.d.ts.map +1 -0
- package/dist/write/attribution.js +325 -0
- package/dist/write/attribution.js.map +1 -0
- package/dist/write/index.d.ts +3 -0
- package/dist/write/index.d.ts.map +1 -0
- package/dist/write/index.js +3 -0
- package/dist/write/index.js.map +1 -0
- package/dist/write/session.d.ts +96 -0
- package/dist/write/session.d.ts.map +1 -0
- package/dist/write/session.js +136 -0
- package/dist/write/session.js.map +1 -0
- package/package.json +9 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { scopeMatchesPattern } from "@opendatalabs/vana-sdk/browser";
|
|
2
|
+
import { GrantExpiredError, GrantOwnerMismatchError, GrantRequiredError, GrantRevokedError, InvalidSignatureError, PsUnavailableError, ScopeMismatchError, ServerNotConfiguredError, UnregisteredBuilderError, } from "../errors/catalog.js";
|
|
3
|
+
import { parseGrantExpiresAtSeconds } from "./data-read.js";
|
|
4
|
+
/**
|
|
5
|
+
* Write-grant encoding: a grant scope entry prefixed with `write:` authorizes
|
|
6
|
+
* the grantee to WRITE into the scope it names (e.g. `write:notes.entries`,
|
|
7
|
+
* `write:notes.*`). The suffix uses the same pattern grammar as read scopes
|
|
8
|
+
* (`*` / `{prefix}.*` / exact), evaluated with the SDK's scopeMatchesPattern.
|
|
9
|
+
*
|
|
10
|
+
* Why a scope-entry prefix and not a new grant field: the gateway's grant
|
|
11
|
+
* shape (GatewayGrantResponse) has no permission axis — `scopes` is its only
|
|
12
|
+
* capability carrier — and the gateway validates scope entries as opaque
|
|
13
|
+
* non-empty strings, so `write:`-prefixed entries flow through createGrant /
|
|
14
|
+
* getGrant / the EIP-712 GrantRegistration signature unchanged. The Personal
|
|
15
|
+
* Server is the sole interpreter.
|
|
16
|
+
*
|
|
17
|
+
* Separation of powers falls out of the encoding:
|
|
18
|
+
* - read policy matches the REQUESTED scope against grant entries verbatim
|
|
19
|
+
* (scopeCoveredByGrant), and a requested scope never carries the prefix,
|
|
20
|
+
* so `write:x` entries can never satisfy a read;
|
|
21
|
+
* - write policy (below) only honors `write:`-prefixed entries, so plain
|
|
22
|
+
* read entries can never satisfy a write.
|
|
23
|
+
*/
|
|
24
|
+
export const WRITE_SCOPE_PREFIX = "write:";
|
|
25
|
+
export function isWriteScopeEntry(entry) {
|
|
26
|
+
return entry.startsWith(WRITE_SCOPE_PREFIX);
|
|
27
|
+
}
|
|
28
|
+
/** The scope patterns a grant authorizes for writing (prefix stripped). */
|
|
29
|
+
export function writeScopePatterns(grantScopes) {
|
|
30
|
+
return grantScopes
|
|
31
|
+
.filter(isWriteScopeEntry)
|
|
32
|
+
.map((entry) => entry.slice(WRITE_SCOPE_PREFIX.length))
|
|
33
|
+
.filter((pattern) => pattern.length > 0);
|
|
34
|
+
}
|
|
35
|
+
export function scopeCoveredByWriteGrant(requestedScope, grantScopes) {
|
|
36
|
+
return writeScopePatterns(grantScopes).some((pattern) => scopeMatchesPattern(requestedScope, pattern));
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Authorize one builder write against a write-grant. Mirrors
|
|
40
|
+
* verifyDataReadPolicy invariant-for-invariant (builder registered, grant
|
|
41
|
+
* present / not revoked / not expired, scope coverage, grantee binding,
|
|
42
|
+
* owner binding) — but scope coverage only honors `write:`-prefixed grant
|
|
43
|
+
* entries, so a read-grant never confers write access.
|
|
44
|
+
*/
|
|
45
|
+
export async function verifyDataWritePolicy(input, ports) {
|
|
46
|
+
const available = await ports.runtimeAvailability?.isAvailable();
|
|
47
|
+
if (available === false) {
|
|
48
|
+
throw new PsUnavailableError();
|
|
49
|
+
}
|
|
50
|
+
const builder = await ports.authSessionVerifier.getBuilder(input.signer);
|
|
51
|
+
if (!builder) {
|
|
52
|
+
throw new UnregisteredBuilderError();
|
|
53
|
+
}
|
|
54
|
+
if (!input.grantId) {
|
|
55
|
+
throw new GrantRequiredError({
|
|
56
|
+
reason: "No grantId bound to the write session",
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
const grant = await ports.grantVerifier.getGrant(input.grantId);
|
|
60
|
+
if (!grant) {
|
|
61
|
+
throw new GrantRequiredError({
|
|
62
|
+
reason: "Grant not found",
|
|
63
|
+
grantId: input.grantId,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
if (grant.revokedAt !== null) {
|
|
67
|
+
throw new GrantRevokedError({ grantId: grant.id });
|
|
68
|
+
}
|
|
69
|
+
if (!grant.scopes || writeScopePatterns(grant.scopes).length === 0) {
|
|
70
|
+
throw new ScopeMismatchError({
|
|
71
|
+
requestedScope: input.requestedScope,
|
|
72
|
+
reason: "Grant has no write scopes",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
if (grant.expiresAt !== null && grant.expiresAt !== undefined) {
|
|
76
|
+
const expiresAtSec = parseGrantExpiresAtSeconds(grant.expiresAt);
|
|
77
|
+
if (expiresAtSec === null) {
|
|
78
|
+
throw new ScopeMismatchError({
|
|
79
|
+
requestedScope: input.requestedScope,
|
|
80
|
+
reason: "Grant expiry is invalid",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (expiresAtSec > 0) {
|
|
84
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
85
|
+
if (expiresAtSec < nowSec) {
|
|
86
|
+
throw new GrantExpiredError({
|
|
87
|
+
expiresAt: expiresAtSec,
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (!scopeCoveredByWriteGrant(input.requestedScope, grant.scopes)) {
|
|
93
|
+
throw new ScopeMismatchError({
|
|
94
|
+
requestedScope: input.requestedScope,
|
|
95
|
+
grantedScopes: grant.scopes,
|
|
96
|
+
reason: "Grant does not authorize writing to this scope",
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (builder.id.toLowerCase() !== grant.granteeId.toLowerCase()) {
|
|
100
|
+
throw new InvalidSignatureError({
|
|
101
|
+
reason: "Write signer is not the grant builder",
|
|
102
|
+
expected: grant.granteeId,
|
|
103
|
+
actual: input.signer,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// Ownership binding — the grant MUST have been issued by THIS server's
|
|
107
|
+
// owner (same fail-closed rules as verifyDataReadPolicy: a missing
|
|
108
|
+
// serverOwner or a grantor-less gateway response rejects, never skips).
|
|
109
|
+
if (!input.serverOwner) {
|
|
110
|
+
throw new ServerNotConfiguredError({
|
|
111
|
+
reason: "serverOwner is required to verify grant ownership",
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
if (!grant.grantorAddress ||
|
|
115
|
+
grant.grantorAddress.toLowerCase() !== input.serverOwner.toLowerCase()) {
|
|
116
|
+
throw new GrantOwnerMismatchError({
|
|
117
|
+
grantId: grant.id,
|
|
118
|
+
expected: input.serverOwner,
|
|
119
|
+
actual: grant.grantorAddress ?? null,
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
// All authorization invariants passed — apply the fee seam last (default
|
|
123
|
+
// free; see WriteFeeVerifierPort).
|
|
124
|
+
await ports.writeFeeVerifier?.assertWriteAllowed({
|
|
125
|
+
builder: input.signer,
|
|
126
|
+
grant,
|
|
127
|
+
scope: input.requestedScope,
|
|
128
|
+
});
|
|
129
|
+
return grant;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=data-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-write.js","sourceRoot":"","sources":["../../src/policy/data-write.ts"],"names":[],"mappings":"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"}
|
package/dist/policy/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { verifyDataReadPolicy, type DataReadPolicyInput, type DataReadPolicyPorts, } from "./data-read.js";
|
|
1
|
+
export { verifyDataReadPolicy, parseGrantExpiresAtSeconds, type DataReadPolicyInput, type DataReadPolicyPorts, } from "./data-read.js";
|
|
2
|
+
export { WRITE_SCOPE_PREFIX, isWriteScopeEntry, writeScopePatterns, scopeCoveredByWriteGrant, verifyDataWritePolicy, type DataWritePolicyInput, type DataWritePolicyPorts, type WriteFeeVerifierPort, } from "./data-write.js";
|
|
2
3
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GACzB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,iBAAiB,CAAC"}
|
package/dist/policy/index.js
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
export { verifyDataReadPolicy, } from "./data-read.js";
|
|
1
|
+
export { verifyDataReadPolicy, parseGrantExpiresAtSeconds, } from "./data-read.js";
|
|
2
|
+
export { WRITE_SCOPE_PREFIX, isWriteScopeEntry, writeScopePatterns, scopeCoveredByWriteGrant, verifyDataWritePolicy, } from "./data-write.js";
|
|
2
3
|
//# sourceMappingURL=index.js.map
|
package/dist/policy/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAG3B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,GAItB,MAAM,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-signer.d.ts","sourceRoot":"","sources":["../../src/signing/request-signer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,MAAM,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"request-signer.d.ts","sourceRoot":"","sources":["../../src/signing/request-signer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,WAAW,CAAC,MAAM,EAAE;QAClB,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,EAAE,MAAM,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,UAAU,CAAC;QAClB,uEAAuE;QACvE,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,aAAa,GAAG,aAAa,CAazE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request-signer.js","sourceRoot":"","sources":["../../src/signing/request-signer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"request-signer.js","sourceRoot":"","sources":["../../src/signing/request-signer.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AAcvE;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAsB;IACxD,OAAO;QACL,KAAK,CAAC,WAAW,CAAC,MAAM;YACtB,OAAO,qBAAqB,CAAC;gBAC3B,WAAW,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;gBAC9D,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,GAAG,EAAE,MAAM,CAAC,GAAG;gBACf,IAAI,EAAE,MAAM,CAAC,IAAI;gBACjB,OAAO,EAAE,MAAM,CAAC,OAAO;aACxB,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
package/dist/signing/signer.d.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import type { ServerAccount } from "../keys/server-account.js";
|
|
6
6
|
import type { GatewayConfig } from "../schemas/server-config.js";
|
|
7
7
|
import { type GrantRegistrationMessage, type GrantRevocationMessage, type AddDataMessage, type RecordDataAccessMessage } from "@opendatalabs/vana-sdk/browser";
|
|
8
|
+
import { type LineageAttestationMessage } from "../lineage/attestation.js";
|
|
8
9
|
export interface ServerSigner {
|
|
9
10
|
/** Address that signs (the server account). */
|
|
10
11
|
readonly address: `0x${string}`;
|
|
@@ -27,6 +28,13 @@ export interface ServerSigner {
|
|
|
27
28
|
* recordId is a per-event bytes32 the contract pins to prevent replay.
|
|
28
29
|
*/
|
|
29
30
|
signRecordDataAccess(msg: RecordDataAccessMessage): Promise<`0x${string}`>;
|
|
31
|
+
/**
|
|
32
|
+
* LineageAttestation (derivative data): binds a derivative's source list
|
|
33
|
+
* to the exact (owner, scope, version, dataHash) it is registered with,
|
|
34
|
+
* under the DataRegistry domain. The gateway requires it on POST /v1/data
|
|
35
|
+
* with `lineage`; see lineage/attestation.ts for why.
|
|
36
|
+
*/
|
|
37
|
+
signLineageAttestation(msg: LineageAttestationMessage): Promise<`0x${string}`>;
|
|
30
38
|
}
|
|
31
39
|
export declare function createServerSigner(account: ServerAccount, gatewayConfig: GatewayConfig): ServerSigner;
|
|
32
40
|
//# sourceMappingURL=signer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/signing/signer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAQL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC7B,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/signing/signer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAQL,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC7B,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAEL,KAAK,yBAAyB,EAC/B,MAAM,2BAA2B,CAAC;AAEnC,MAAM,WAAW,YAAY;IAC3B,+CAA+C;IAC/C,QAAQ,CAAC,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;IAChC,qBAAqB,CAAC,GAAG,EAAE,wBAAwB,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IAC7E,mBAAmB,CAAC,GAAG,EAAE,sBAAsB,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IACzE;;;;;OAKG;IACH,WAAW,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IACzD;;;;;;;;OAQG;IACH,oBAAoB,CAAC,GAAG,EAAE,uBAAuB,GAAG,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;IAC3E;;;;;OAKG;IACH,sBAAsB,CACpB,GAAG,EAAE,yBAAyB,GAC7B,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC;CAC3B;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,aAAa,EACtB,aAAa,EAAE,aAAa,GAC3B,YAAY,CA6Dd"}
|
package/dist/signing/signer.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Uses the ServerAccount's derived key for all signatures.
|
|
4
4
|
*/
|
|
5
5
|
import { grantRegistrationDomain, grantRevocationDomain, dataRegistryDomain, GRANT_REGISTRATION_TYPES, GRANT_REVOCATION_TYPES, ADD_DATA_TYPES, RECORD_DATA_ACCESS_TYPES, } from "@opendatalabs/vana-sdk/browser";
|
|
6
|
+
import { LINEAGE_ATTESTATION_TYPES, } from "../lineage/attestation.js";
|
|
6
7
|
export function createServerSigner(account, gatewayConfig) {
|
|
7
8
|
return {
|
|
8
9
|
address: account.address,
|
|
@@ -34,6 +35,14 @@ export function createServerSigner(account, gatewayConfig) {
|
|
|
34
35
|
message: msg,
|
|
35
36
|
});
|
|
36
37
|
},
|
|
38
|
+
async signLineageAttestation(msg) {
|
|
39
|
+
return account.signTypedData({
|
|
40
|
+
domain: dataRegistryDomain(gatewayConfig),
|
|
41
|
+
types: LINEAGE_ATTESTATION_TYPES,
|
|
42
|
+
primaryType: "LineageAttestation",
|
|
43
|
+
message: { ...msg, sources: [...msg.sources] },
|
|
44
|
+
});
|
|
45
|
+
},
|
|
37
46
|
async signRecordDataAccess(msg) {
|
|
38
47
|
return account.signTypedData({
|
|
39
48
|
domain: dataRegistryDomain(gatewayConfig),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signer.js","sourceRoot":"","sources":["../../src/signing/signer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,cAAc,EACd,wBAAwB,GAKzB,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"signer.js","sourceRoot":"","sources":["../../src/signing/signer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACL,uBAAuB,EACvB,qBAAqB,EACrB,kBAAkB,EAClB,wBAAwB,EACxB,sBAAsB,EACtB,cAAc,EACd,wBAAwB,GAKzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,yBAAyB,GAE1B,MAAM,2BAA2B,CAAC;AAmCnC,MAAM,UAAU,kBAAkB,CAChC,OAAsB,EACtB,aAA4B;IAE5B,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,OAAO;QAExB,KAAK,CAAC,qBAAqB,CACzB,GAA6B;YAE7B,OAAO,OAAO,CAAC,aAAa,CAAC;gBAC3B,MAAM,EAAE,uBAAuB,CAAC,aAAa,CAAC;gBAC9C,KAAK,EAAE,wBAAwB;gBAC/B,WAAW,EAAE,mBAAmB;gBAChC,iDAAiD;gBACjD,iEAAiE;gBACjE,8DAA8D;gBAC9D,0DAA0D;gBAC1D,OAAO,EAAE,GAAyC;aACnD,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,mBAAmB,CACvB,GAA2B;YAE3B,OAAO,OAAO,CAAC,aAAa,CAAC;gBAC3B,MAAM,EAAE,qBAAqB,CAAC,aAAa,CAAC;gBAC5C,KAAK,EAAE,sBAAsB;gBAC7B,WAAW,EAAE,iBAAiB;gBAC9B,OAAO,EAAE,GAAyC;aACnD,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,WAAW,CAAC,GAAmB;YACnC,OAAO,OAAO,CAAC,aAAa,CAAC;gBAC3B,MAAM,EAAE,kBAAkB,CAAC,aAAa,CAAC;gBACzC,KAAK,EAAE,cAAc;gBACrB,WAAW,EAAE,SAAS;gBACtB,OAAO,EAAE,GAAyC;aACnD,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,sBAAsB,CAC1B,GAA8B;YAE9B,OAAO,OAAO,CAAC,aAAa,CAAC;gBAC3B,MAAM,EAAE,kBAAkB,CAAC,aAAa,CAAC;gBACzC,KAAK,EAAE,yBAAyB;gBAChC,WAAW,EAAE,oBAAoB;gBACjC,OAAO,EAAE,EAAE,GAAG,GAAG,EAAE,OAAO,EAAE,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,EAAE;aAC/C,CAAC,CAAC;QACL,CAAC;QAED,KAAK,CAAC,oBAAoB,CACxB,GAA4B;YAE5B,OAAO,OAAO,CAAC,aAAa,CAAC;gBAC3B,MAAM,EAAE,kBAAkB,CAAC,aAAa,CAAC;gBACzC,KAAK,EAAE,wBAAwB;gBAC/B,WAAW,EAAE,kBAAkB;gBAC/B,OAAO,EAAE,GAAyC;aACnD,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deterministic DPv2 data-point id: `keccak256(abi.encode(owner, scope))`,
|
|
3
|
+
* the same primary key DataRegistryV2 and the gateway use. Every version of
|
|
4
|
+
* a scope shares this id; the registry row carries the current version.
|
|
5
|
+
*/
|
|
6
|
+
export declare function computeDataPointId(ownerAddress: string, scope: string): `0x${string}`;
|
|
7
|
+
//# sourceMappingURL=data-point-id.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-point-id.d.ts","sourceRoot":"","sources":["../../src/sync/data-point-id.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,GACZ,KAAK,MAAM,EAAE,CAaf"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { encodeAbiParameters, keccak256 } from "viem";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic DPv2 data-point id: `keccak256(abi.encode(owner, scope))`,
|
|
4
|
+
* the same primary key DataRegistryV2 and the gateway use. Every version of
|
|
5
|
+
* a scope shares this id; the registry row carries the current version.
|
|
6
|
+
*/
|
|
7
|
+
export function computeDataPointId(ownerAddress, scope) {
|
|
8
|
+
// ABI-encoding an address is checksum-insensitive (same bytes either way),
|
|
9
|
+
// but viem rejects mixed-case strings that fail checksum validation;
|
|
10
|
+
// normalize so config-sourced owner strings can't trip it.
|
|
11
|
+
return keccak256(encodeAbiParameters([
|
|
12
|
+
{ name: "ownerAddress", type: "address" },
|
|
13
|
+
{ name: "scope", type: "string" },
|
|
14
|
+
], [ownerAddress.toLowerCase(), scope]));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=data-point-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-point-id.js","sourceRoot":"","sources":["../../src/sync/data-point-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEtD;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,YAAoB,EACpB,KAAa;IAEb,2EAA2E;IAC3E,qEAAqE;IACrE,2DAA2D;IAC3D,OAAO,SAAS,CACd,mBAAmB,CACjB;QACE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,EAAE;QACzC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE;KAClC,EACD,CAAC,YAAY,CAAC,WAAW,EAAmB,EAAE,KAAK,CAAC,CACrD,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -4,6 +4,8 @@ import type { ServerSigner } from "../../signing/signer.js";
|
|
|
4
4
|
import type { Logger } from "../../logger/index.js";
|
|
5
5
|
import type { IndexEntry } from "../../storage/index/types.js";
|
|
6
6
|
import type { DataStoragePort } from "../../ports/index.js";
|
|
7
|
+
import type { LineageGatewayPort } from "../../lineage/gateway.js";
|
|
8
|
+
export { computeDataPointId } from "../data-point-id.js";
|
|
7
9
|
export interface UploadWorkerDeps {
|
|
8
10
|
storage: DataStoragePort;
|
|
9
11
|
storageAdapter: StorageAdapter;
|
|
@@ -12,6 +14,14 @@ export interface UploadWorkerDeps {
|
|
|
12
14
|
masterKey: Uint8Array;
|
|
13
15
|
serverOwner: string;
|
|
14
16
|
logger: Logger;
|
|
17
|
+
/**
|
|
18
|
+
* Registers derivative records (envelopes stamped with `$lineage`) with
|
|
19
|
+
* their lineage. The SDK client's registerDataPoint sends only the AddData
|
|
20
|
+
* fields, so a derivative needs this direct client; without it a derivative
|
|
21
|
+
* upload fails (and retries next cycle) rather than silently registering as
|
|
22
|
+
* a root record whose lineage exists only inside the ciphertext.
|
|
23
|
+
*/
|
|
24
|
+
lineageGateway?: Pick<LineageGatewayPort, "registerDataPoint">;
|
|
15
25
|
}
|
|
16
26
|
export interface UploadResult {
|
|
17
27
|
path: string;
|
|
@@ -55,10 +65,4 @@ export declare function uploadOne(deps: UploadWorkerDeps, entry: IndexEntry): Pr
|
|
|
55
65
|
*/
|
|
56
66
|
export declare function uploadAll(deps: UploadWorkerDeps, options?: UploadAllOptions): Promise<UploadResult[]>;
|
|
57
67
|
export declare function parseGatewayNextVersion(message: string): number | null;
|
|
58
|
-
/**
|
|
59
|
-
* Deterministic DPv2 data-point id — `keccak256(abi.encode(owner, scope))`,
|
|
60
|
-
* the same primary key DataRegistryV2 and the gateway use. Lets the upload
|
|
61
|
-
* worker look up the registry's live row for a scope without a list call.
|
|
62
|
-
*/
|
|
63
|
-
export declare function computeDataPointId(ownerAddress: string, scope: string): `0x${string}`;
|
|
64
68
|
//# sourceMappingURL=upload.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/sync/workers/upload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"upload.d.ts","sourceRoot":"","sources":["../../../src/sync/workers/upload.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAC;AAC1E,OAAO,EAGL,KAAK,aAAa,EACnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAEzD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,CAAC;IACzB,cAAc,EAAE,cAAc,CAAC;IAC/B,OAAO,EAAE,aAAa,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,EAAE,UAAU,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,cAAc,CAAC,EAAE,IAAI,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;CAChE;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CACrD;AAED;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,IAAI,EAAE,MAAM;CAIzB;AAcD;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,UAAU,GAChB,OAAO,CAAC,YAAY,CAAC,CA2PvB;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,gBAAgB,EACtB,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,YAAY,EAAE,CAAC,CA2BzB;AAsBD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUtE"}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { keccak256, stringToHex } from "viem";
|
|
2
2
|
import { deriveScopeKey, encryptWithPassword, } from "@opendatalabs/vana-sdk/browser";
|
|
3
|
+
import { computeDataPointId } from "../data-point-id.js";
|
|
4
|
+
import { readStoredLineage } from "../../lineage/lineage.js";
|
|
5
|
+
export { computeDataPointId } from "../data-point-id.js";
|
|
3
6
|
/**
|
|
4
7
|
* Thrown when an unsynced entry's local payload file is gone, so the entry was
|
|
5
8
|
* dropped from the index rather than uploaded. `uploadAll` treats it as a
|
|
@@ -104,14 +107,47 @@ export async function uploadOne(deps, entry) {
|
|
|
104
107
|
metadataHash,
|
|
105
108
|
expectedVersion: version,
|
|
106
109
|
});
|
|
107
|
-
const
|
|
110
|
+
const registration = {
|
|
108
111
|
ownerAddress: serverOwner,
|
|
109
112
|
scope: entry.scope,
|
|
110
113
|
dataHash,
|
|
111
114
|
metadataHash,
|
|
112
115
|
expectedVersion: String(version),
|
|
113
116
|
signature: addDataSignature,
|
|
114
|
-
}
|
|
117
|
+
};
|
|
118
|
+
// A derivative carries its validated `$lineage` inside the envelope;
|
|
119
|
+
// the gateway stores the same sources next to this (dataPointId,
|
|
120
|
+
// version) so lineage can be walked without the plaintext. The
|
|
121
|
+
// AddData signature is unchanged (dataHash already commits to the
|
|
122
|
+
// plaintext, `$lineage` included); the plaintext list the gateway
|
|
123
|
+
// keeps is covered by a separate LineageAttestation signature bound
|
|
124
|
+
// to this version and dataHash, so a replayed registration cannot
|
|
125
|
+
// swap it (see lineage/attestation.ts).
|
|
126
|
+
const lineage = readStoredLineage(envelope.data);
|
|
127
|
+
// An empty `$lineage` is an explicit root statement and is registered
|
|
128
|
+
// as such (attested empty list); only an ABSENT `$lineage` makes no
|
|
129
|
+
// statement and goes through the plain client.
|
|
130
|
+
let dataPointResult;
|
|
131
|
+
if (lineage) {
|
|
132
|
+
if (!deps.lineageGateway) {
|
|
133
|
+
throw new Error(`Cannot register derivative ${entry.path} (scope=${entry.scope}): lineage registration needs a gateway URL (lineageGateway is not configured)`);
|
|
134
|
+
}
|
|
135
|
+
const lineageSignature = await signer.signLineageAttestation({
|
|
136
|
+
ownerAddress: serverOwner,
|
|
137
|
+
scope: entry.scope,
|
|
138
|
+
expectedVersion: version,
|
|
139
|
+
dataHash,
|
|
140
|
+
sources: lineage.sources,
|
|
141
|
+
});
|
|
142
|
+
dataPointResult = await deps.lineageGateway.registerDataPoint({
|
|
143
|
+
...registration,
|
|
144
|
+
lineage: lineage.sources,
|
|
145
|
+
lineageSignature,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
dataPointResult = await gateway.registerDataPoint(registration);
|
|
150
|
+
}
|
|
115
151
|
const id = dataPointResult.dataPointId ?? null;
|
|
116
152
|
if (!id) {
|
|
117
153
|
throw new Error(`Gateway registerDataPoint did not return a dataPointId for ${entry.path} (scope=${entry.scope}, version=${version})`);
|
|
@@ -269,18 +305,4 @@ export function parseGatewayNextVersion(message) {
|
|
|
269
305
|
return Number(storedValue[1]) + 1;
|
|
270
306
|
return null;
|
|
271
307
|
}
|
|
272
|
-
/**
|
|
273
|
-
* Deterministic DPv2 data-point id — `keccak256(abi.encode(owner, scope))`,
|
|
274
|
-
* the same primary key DataRegistryV2 and the gateway use. Lets the upload
|
|
275
|
-
* worker look up the registry's live row for a scope without a list call.
|
|
276
|
-
*/
|
|
277
|
-
export function computeDataPointId(ownerAddress, scope) {
|
|
278
|
-
// ABI-encoding an address is checksum-insensitive (same bytes either way),
|
|
279
|
-
// but viem rejects mixed-case strings that fail checksum validation —
|
|
280
|
-
// normalize so config-sourced owner strings can't trip it.
|
|
281
|
-
return keccak256(encodeAbiParameters([
|
|
282
|
-
{ name: "ownerAddress", type: "address" },
|
|
283
|
-
{ name: "scope", type: "string" },
|
|
284
|
-
], [ownerAddress.toLowerCase(), scope]));
|
|
285
|
-
}
|
|
286
308
|
//# sourceMappingURL=upload.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../src/sync/workers/upload.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"upload.js","sourceRoot":"","sources":["../../../src/sync/workers/upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builder attribution for delegated writes.
|
|
3
|
+
*
|
|
4
|
+
* The write-session token authorizes a write; it does not PROVE who authored
|
|
5
|
+
* the payload (a bearer token is not a signature). For cryptographic
|
|
6
|
+
* attribution the builder also signs the payload: a Web3Signed proof over the
|
|
7
|
+
* exact write request (aud / method / uri / bodyHash / iat / exp), carried in
|
|
8
|
+
* the `X-Vana-Write-Signature` header and signed by the builder key proven at
|
|
9
|
+
* handshake. The PS verifies the proof recovers to the session's builder and
|
|
10
|
+
* that its bodyHash commits to the received bytes, then stores the proof and
|
|
11
|
+
* the builder identity WITH the record — inside the envelope's `data` under
|
|
12
|
+
* the reserved `$writtenBy` key (same in-`data` marker idiom as `$binary`),
|
|
13
|
+
* so attribution travels through the unchanged encrypt / upload / register
|
|
14
|
+
* path and back out on read. The on-chain shape is untouched.
|
|
15
|
+
*
|
|
16
|
+
* The proof binds the write to its context, not just its bytes: the signed
|
|
17
|
+
* claims carry the request path (whose last segment is the scope), the
|
|
18
|
+
* method, the audience (this server's origin) and the session's grantId,
|
|
19
|
+
* which the PS requires to match the session at ingest. A stored `$writtenBy`
|
|
20
|
+
* therefore cannot be lifted onto another scope's record or relabelled with a
|
|
21
|
+
* different grant and still verify.
|
|
22
|
+
*
|
|
23
|
+
* What the builder signs is the STORED representation, not the wire body:
|
|
24
|
+
* the compact JSON of the envelope `data` record the PS will write (minus
|
|
25
|
+
* `$writtenBy`). A third party holding the envelope can therefore verify
|
|
26
|
+
* authorship from the envelope ALONE (verifyStoredWriterAttribution): recover
|
|
27
|
+
* the signer over the stored proof's base64url payload (EIP-191), check the
|
|
28
|
+
* signed claims against the envelope's scope and stored grantId, and hash
|
|
29
|
+
* JSON.stringify(data minus the server-stamped keys `$writtenBy` and
|
|
30
|
+
* `$lineage`) against the signed bodyHash.
|
|
31
|
+
* - JSON writes: the body IS the stored record, so the builder signs the
|
|
32
|
+
* body bytes, which must be compact JSON (what JSON.stringify emits: no
|
|
33
|
+
* insignificant whitespace, keys in the order given). JSON.parse /
|
|
34
|
+
* JSON.stringify round-trips that byte-for-byte; a body that does not
|
|
35
|
+
* round-trip is rejected at write time (WRITE_BODY_NOT_CANONICAL) instead
|
|
36
|
+
* of being stored with an attribution nobody can check.
|
|
37
|
+
* - Binary writes: the stored record is the `$binary` envelope data (media
|
|
38
|
+
* type, filename, caller metadata, size, content hash, base64 content),
|
|
39
|
+
* so the builder signs its compact JSON (binaryWriteSignedBytes). That
|
|
40
|
+
* binds the caller-controlled representation headers (Content-Type,
|
|
41
|
+
* X-Filename / Content-Disposition, X-Vana-Metadata) to the signature and
|
|
42
|
+
* makes a JSON-vs-binary switch of the same bytes fail verification.
|
|
43
|
+
*/
|
|
44
|
+
import { type Web3SignedPayload } from "@opendatalabs/vana-sdk/browser";
|
|
45
|
+
import type { WriteProofReplayStore } from "./session.js";
|
|
46
|
+
/** Header carrying the builder's signed-payload proof on a session write. */
|
|
47
|
+
export declare const WRITE_SIGNATURE_HEADER = "x-vana-write-signature";
|
|
48
|
+
/**
|
|
49
|
+
* Reserved key inside the envelope's `data` record for builder attribution.
|
|
50
|
+
* Mirrors the `$binary` marker convention (contracts/binary.ts).
|
|
51
|
+
*/
|
|
52
|
+
export declare const WRITER_ATTRIBUTION_KEY: "$writtenBy";
|
|
53
|
+
export interface WriterAttribution {
|
|
54
|
+
/** The builder address the proof recovered to. */
|
|
55
|
+
builder: `0x${string}`;
|
|
56
|
+
/** The write-grant the record was written under. */
|
|
57
|
+
grantId: string;
|
|
58
|
+
/**
|
|
59
|
+
* The builder's compact Web3Signed proof (`{base64url(payload)}.{sig}`,
|
|
60
|
+
* scheme prefix stripped). Verifiable offline: recover the EIP-191 signer
|
|
61
|
+
* over the base64url payload string; the decoded payload's `bodyHash`
|
|
62
|
+
* commits to the written bytes.
|
|
63
|
+
*/
|
|
64
|
+
signature: string;
|
|
65
|
+
/** `bodyHash` claim from the proof (sha-256 of the request body bytes). */
|
|
66
|
+
bodyHash: string;
|
|
67
|
+
/** ISO timestamp the PS accepted the write. */
|
|
68
|
+
writtenAt: string;
|
|
69
|
+
}
|
|
70
|
+
export interface VerifyWriterAttributionInput {
|
|
71
|
+
request: Request;
|
|
72
|
+
/** The builder address bound to the write session at handshake. */
|
|
73
|
+
builderAddress: `0x${string}`;
|
|
74
|
+
/** The grant the session (and therefore this write) is bound to. */
|
|
75
|
+
grantId: string;
|
|
76
|
+
serverOrigin: string | (() => string);
|
|
77
|
+
now?: () => Date;
|
|
78
|
+
/**
|
|
79
|
+
* Replay guard for the per-write proof. When supplied, a proof is consumed
|
|
80
|
+
* on successful verification (keyed by a digest of the exact header,
|
|
81
|
+
* remembered until the proof's own expiry) and a second write carrying the
|
|
82
|
+
* same proof is rejected: holding the session bearer plus one captured
|
|
83
|
+
* signed request must not allow re-storing it until the proof expires.
|
|
84
|
+
*/
|
|
85
|
+
replayStore?: WriteProofReplayStore;
|
|
86
|
+
}
|
|
87
|
+
/** verifyWriterAttribution's result: the record to store plus a rollback. */
|
|
88
|
+
export interface VerifiedWriterAttribution extends WriterAttribution {
|
|
89
|
+
/**
|
|
90
|
+
* Present when a replay store consumed the proof. Callers whose write then
|
|
91
|
+
* FAILS before the record is committed should call it so the builder can
|
|
92
|
+
* retry with the same still-valid proof (a retry after success is a replay).
|
|
93
|
+
*/
|
|
94
|
+
releaseProof?: () => Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
export interface BinaryWriteSignedBytesInput {
|
|
97
|
+
/** The raw body bytes the write will send. */
|
|
98
|
+
bytes: Uint8Array;
|
|
99
|
+
/** The Content-Type header the write will send (parameters are ignored). */
|
|
100
|
+
contentType: string;
|
|
101
|
+
/** The X-Filename header value the write will send, if any. */
|
|
102
|
+
filename?: string;
|
|
103
|
+
/** The exact X-Vana-Metadata header value the write will send, if any. */
|
|
104
|
+
metadataHeader?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The bytes a builder signs (as the Web3Signed body) for a BINARY session
|
|
108
|
+
* write: the compact JSON of the `$binary` record the PS stores for these
|
|
109
|
+
* headers and bytes. Mirrors ingest exactly (same media-type normalization,
|
|
110
|
+
* metadata parsing and envelope builder), so the signature covers the stored
|
|
111
|
+
* representation and verifyStoredWriterAttribution can re-derive it.
|
|
112
|
+
*/
|
|
113
|
+
export declare function binaryWriteSignedBytes(input: BinaryWriteSignedBytesInput): Promise<Uint8Array>;
|
|
114
|
+
/**
|
|
115
|
+
* Verify the `X-Vana-Write-Signature` proof on a session write and produce
|
|
116
|
+
* the attribution record to store with the data. Throws ProtocolError(401)
|
|
117
|
+
* when the proof is missing, malformed, expired, fails EIP-191 recovery /
|
|
118
|
+
* bodyHash binding (the hash covers the stored representation, see
|
|
119
|
+
* signedBytesFor), recovers to a different key than the session builder, or
|
|
120
|
+
* does not carry the session's grantId as a signed claim.
|
|
121
|
+
*/
|
|
122
|
+
export declare function verifyWriterAttribution(input: VerifyWriterAttributionInput): Promise<VerifiedWriterAttribution>;
|
|
123
|
+
/**
|
|
124
|
+
* Stamp attribution into an envelope `data` record. The reserved key must not
|
|
125
|
+
* appear in the caller's payload — a builder must not be able to forge (or
|
|
126
|
+
* shadow) its own attribution.
|
|
127
|
+
*/
|
|
128
|
+
export declare function stampWriterAttribution(data: Record<string, unknown>, attribution: WriterAttribution): Record<string, unknown>;
|
|
129
|
+
export declare function hasReservedWriterKey(data: Record<string, unknown>): boolean;
|
|
130
|
+
export declare class WriterAttributionVerificationError extends Error {
|
|
131
|
+
readonly reason: "ATTRIBUTION_MISSING" | "BODY_HASH_MISMATCH" | "PROOF_INVALID" | "SIGNER_MISMATCH" | "SCOPE_MISMATCH" | "GRANT_MISMATCH" | "AUDIENCE_MISMATCH" | "LINEAGE_MISMATCH";
|
|
132
|
+
constructor(reason: "ATTRIBUTION_MISSING" | "BODY_HASH_MISMATCH" | "PROOF_INVALID" | "SIGNER_MISMATCH" | "SCOPE_MISMATCH" | "GRANT_MISMATCH" | "AUDIENCE_MISMATCH" | "LINEAGE_MISMATCH", message: string);
|
|
133
|
+
}
|
|
134
|
+
export interface StoredWriterAttributionVerification {
|
|
135
|
+
/** Signer recovered from the stored proof (equals the stored builder). */
|
|
136
|
+
builder: `0x${string}`;
|
|
137
|
+
grantId: string;
|
|
138
|
+
/** Hash re-derived from the stored data; equals the proof's bodyHash. */
|
|
139
|
+
bodyHash: string;
|
|
140
|
+
/** The signed claims (aud / method / uri / bodyHash / iat / exp). */
|
|
141
|
+
payload: Web3SignedPayload;
|
|
142
|
+
}
|
|
143
|
+
export interface VerifyStoredWriterAttributionOptions {
|
|
144
|
+
/**
|
|
145
|
+
* When known, the origin of the Personal Server the record was written to;
|
|
146
|
+
* the proof's signed audience must match it. Omit for records whose server
|
|
147
|
+
* is not known to the verifier.
|
|
148
|
+
*/
|
|
149
|
+
expectedOrigin?: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Verify builder attribution from a stored envelope alone (no request, no
|
|
153
|
+
* server state, no expiry check: the proof is evidence of who wrote the
|
|
154
|
+
* record at the time, not a live credential). Checks, in order: the envelope
|
|
155
|
+
* carries an attribution; the stored representation (compact JSON of the
|
|
156
|
+
* data minus the server-stamped `$writtenBy` and `$lineage` keys, for JSON
|
|
157
|
+
* and `$binary` records alike) re-hashes
|
|
158
|
+
* to the signed bodyHash; the proof parses and recovers to the attributed
|
|
159
|
+
* builder; and the signed claims bind the proof to THIS record: a POST whose
|
|
160
|
+
* path names the envelope's scope, the stored grantId, and (when given) the
|
|
161
|
+
* server origin. Throws WriterAttributionVerificationError with the reason.
|
|
162
|
+
*/
|
|
163
|
+
export declare function verifyStoredWriterAttribution(envelope: {
|
|
164
|
+
scope: string;
|
|
165
|
+
data: Record<string, unknown>;
|
|
166
|
+
}, options?: VerifyStoredWriterAttributionOptions): Promise<StoredWriterAttributionVerification>;
|
|
167
|
+
//# sourceMappingURL=attribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attribution.d.ts","sourceRoot":"","sources":["../../src/write/attribution.ts"],"names":[],"mappings":"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"}
|