@opendatalabs/personal-server-ts-server 0.0.1-canary.e9e40b0 → 0.0.1-canary.eee90fe
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/ui/ps-lite-debug.js
CHANGED
|
@@ -52520,13 +52520,6 @@ function createStorageReadMethods(entries, entriesForScope) {
|
|
|
52520
52520
|
}
|
|
52521
52521
|
};
|
|
52522
52522
|
}
|
|
52523
|
-
function readEnvelopeFromMap(envelopes, key) {
|
|
52524
|
-
const envelope = envelopes.get(key);
|
|
52525
|
-
if (!envelope) {
|
|
52526
|
-
throw new Error("Envelope not found");
|
|
52527
|
-
}
|
|
52528
|
-
return envelope;
|
|
52529
|
-
}
|
|
52530
52523
|
function summarizeScopes(entries, options) {
|
|
52531
52524
|
const summaries = /* @__PURE__ */ new Map();
|
|
52532
52525
|
for (const entry of entries) {
|
|
@@ -69648,33 +69641,16 @@ function toDataStoragePort(storage) {
|
|
|
69648
69641
|
if ("listScopes" in storage) {
|
|
69649
69642
|
return storage;
|
|
69650
69643
|
}
|
|
69651
|
-
|
|
69652
|
-
}
|
|
69653
|
-
function createMemoryAccessLogStore() {
|
|
69654
|
-
const logs = [];
|
|
69655
|
-
return {
|
|
69656
|
-
capabilities: { accessLogs: "memory" },
|
|
69657
|
-
async write(entry) {
|
|
69658
|
-
logs.push(entry);
|
|
69659
|
-
},
|
|
69660
|
-
async read(options) {
|
|
69661
|
-
const limit = options?.limit ?? 50;
|
|
69662
|
-
const offset = options?.offset ?? 0;
|
|
69663
|
-
const sorted = [...logs].sort((a2, b2) => new Date(b2.timestamp).getTime() - new Date(a2.timestamp).getTime());
|
|
69664
|
-
return {
|
|
69665
|
-
logs: sorted.slice(offset, offset + limit),
|
|
69666
|
-
total: sorted.length,
|
|
69667
|
-
limit,
|
|
69668
|
-
offset
|
|
69669
|
-
};
|
|
69670
|
-
}
|
|
69671
|
-
};
|
|
69644
|
+
throw new Error("PS Lite runtime requires a persistent DataStoragePort. Use createIndexedDbPsLiteRuntime() or createPersistentPsLiteStorage().");
|
|
69672
69645
|
}
|
|
69673
69646
|
function indexedDbAvailable() {
|
|
69674
69647
|
return typeof indexedDB !== "undefined";
|
|
69675
69648
|
}
|
|
69676
69649
|
function createDefaultAccessLogStore() {
|
|
69677
|
-
|
|
69650
|
+
if (!indexedDbAvailable()) {
|
|
69651
|
+
throw new Error("IndexedDB is required for default PS Lite access log persistence.");
|
|
69652
|
+
}
|
|
69653
|
+
return createIndexedDbPsLiteAccessLogStore();
|
|
69678
69654
|
}
|
|
69679
69655
|
function createLogId() {
|
|
69680
69656
|
return globalThis.crypto?.randomUUID?.() ?? `log-${Date.now()}`;
|
|
@@ -69684,46 +69660,21 @@ function randomHex(byteLength) {
|
|
|
69684
69660
|
globalThis.crypto.getRandomValues(bytes);
|
|
69685
69661
|
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
69686
69662
|
}
|
|
69687
|
-
function
|
|
69688
|
-
|
|
69689
|
-
|
|
69690
|
-
if (value == null)
|
|
69691
|
-
return null;
|
|
69692
|
-
const date9 = value instanceof Date ? value : new Date(value);
|
|
69693
|
-
if (Number.isNaN(date9.getTime())) {
|
|
69694
|
-
throw new Error("Invalid token expiry");
|
|
69695
|
-
}
|
|
69696
|
-
return date9.toISOString();
|
|
69663
|
+
function createDefaultTokenStore() {
|
|
69664
|
+
if (!indexedDbAvailable()) {
|
|
69665
|
+
throw new Error("IndexedDB is required for default PS Lite token storage.");
|
|
69697
69666
|
}
|
|
69698
|
-
|
|
69699
|
-
|
|
69667
|
+
return createIndexedDbPsLiteTokenStore();
|
|
69668
|
+
}
|
|
69669
|
+
function createDefaultSaveConfig() {
|
|
69670
|
+
if (!indexedDbAvailable()) {
|
|
69671
|
+
throw new Error("IndexedDB is required for default PS Lite config persistence.");
|
|
69700
69672
|
}
|
|
69701
|
-
|
|
69702
|
-
|
|
69703
|
-
|
|
69704
|
-
return Array.from(tokens.entries()).filter(([, expiresAt]) => !isExpired(expiresAt)).map(([token]) => token);
|
|
69705
|
-
},
|
|
69706
|
-
async isValid(token) {
|
|
69707
|
-
const expiresAt = tokens.get(token);
|
|
69708
|
-
if (expiresAt === void 0)
|
|
69709
|
-
return false;
|
|
69710
|
-
if (isExpired(expiresAt)) {
|
|
69711
|
-
tokens.delete(token);
|
|
69712
|
-
return false;
|
|
69713
|
-
}
|
|
69714
|
-
return true;
|
|
69715
|
-
},
|
|
69716
|
-
async addToken(token, options) {
|
|
69717
|
-
tokens.set(token, normalizeExpiresAt(options?.expiresAt));
|
|
69718
|
-
},
|
|
69719
|
-
async removeToken(token) {
|
|
69720
|
-
tokens.delete(token);
|
|
69721
|
-
}
|
|
69673
|
+
const stateStore = createIndexedDbPsLiteStateStore();
|
|
69674
|
+
return async (nextConfig) => {
|
|
69675
|
+
await savePsLiteConfig(stateStore, nextConfig);
|
|
69722
69676
|
};
|
|
69723
69677
|
}
|
|
69724
|
-
function createDefaultTokenStore() {
|
|
69725
|
-
return indexedDbAvailable() ? createIndexedDbPsLiteTokenStore() : createMemoryTokenStore();
|
|
69726
|
-
}
|
|
69727
69678
|
function bearerToken(request2) {
|
|
69728
69679
|
const authorization = request2.headers.get("authorization");
|
|
69729
69680
|
if (!authorization?.startsWith("Bearer "))
|
|
@@ -69733,75 +69684,6 @@ function bearerToken(request2) {
|
|
|
69733
69684
|
async function readForm(request2) {
|
|
69734
69685
|
return new URLSearchParams(await request2.text());
|
|
69735
69686
|
}
|
|
69736
|
-
function createMemoryPsLiteStorage(adapter = { kind: "indexeddb" }) {
|
|
69737
|
-
const entries = /* @__PURE__ */ new Map();
|
|
69738
|
-
const envelopes = /* @__PURE__ */ new Map();
|
|
69739
|
-
let nextId = 1;
|
|
69740
|
-
function envelopeKey(scope, collectedAt) {
|
|
69741
|
-
return `${scope}
|
|
69742
|
-
${collectedAt}`;
|
|
69743
|
-
}
|
|
69744
|
-
function entriesForScope(scope) {
|
|
69745
|
-
return sortEntries(Array.from(entries.values()).filter((entry) => entry.scope === scope));
|
|
69746
|
-
}
|
|
69747
|
-
const storagePort = {
|
|
69748
|
-
kind: adapter.kind === "custom" ? "custom" : "browser-indexeddb-opfs",
|
|
69749
|
-
capabilities: {
|
|
69750
|
-
metadata: "memory",
|
|
69751
|
-
files: "memory",
|
|
69752
|
-
opfsAvailable: false
|
|
69753
|
-
},
|
|
69754
|
-
...createStorageReadMethods(() => entries.values(), entriesForScope),
|
|
69755
|
-
findByFileId(fileId) {
|
|
69756
|
-
return Array.from(entries.values()).find((entry) => entry.fileId === fileId);
|
|
69757
|
-
},
|
|
69758
|
-
findUnsynced(options) {
|
|
69759
|
-
const unsynced = Array.from(entries.values()).filter((entry) => entry.fileId === null).sort((a2, b2) => a2.createdAt.localeCompare(b2.createdAt));
|
|
69760
|
-
return options?.limit === void 0 ? unsynced : unsynced.slice(0, options.limit);
|
|
69761
|
-
},
|
|
69762
|
-
async readEnvelope(scope, collectedAt) {
|
|
69763
|
-
return readEnvelopeFromMap(envelopes, envelopeKey(scope, collectedAt));
|
|
69764
|
-
},
|
|
69765
|
-
async writeEnvelope(envelope) {
|
|
69766
|
-
envelopes.set(envelopeKey(envelope.scope, envelope.collectedAt), envelope);
|
|
69767
|
-
return {
|
|
69768
|
-
path: `${envelope.scope}/${envelope.collectedAt}.json`,
|
|
69769
|
-
relativePath: `${envelope.scope}/${envelope.collectedAt}.json`,
|
|
69770
|
-
sizeBytes: new TextEncoder().encode(JSON.stringify(envelope)).length
|
|
69771
|
-
};
|
|
69772
|
-
},
|
|
69773
|
-
insertEntry(entry) {
|
|
69774
|
-
const indexed = {
|
|
69775
|
-
...entry,
|
|
69776
|
-
schemaId: entry.schemaId ?? null,
|
|
69777
|
-
id: nextId,
|
|
69778
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
69779
|
-
};
|
|
69780
|
-
nextId += 1;
|
|
69781
|
-
entries.set(entry.path, indexed);
|
|
69782
|
-
return indexed;
|
|
69783
|
-
},
|
|
69784
|
-
updateFileId(path, fileId) {
|
|
69785
|
-
const entry = entries.get(path);
|
|
69786
|
-
if (!entry)
|
|
69787
|
-
return false;
|
|
69788
|
-
entries.set(path, { ...entry, fileId });
|
|
69789
|
-
return true;
|
|
69790
|
-
},
|
|
69791
|
-
async deleteScope(scope) {
|
|
69792
|
-
let deleted = 0;
|
|
69793
|
-
for (const [path, entry] of entries.entries()) {
|
|
69794
|
-
if (entry.scope === scope) {
|
|
69795
|
-
entries.delete(path);
|
|
69796
|
-
envelopes.delete(envelopeKey(entry.scope, entry.collectedAt));
|
|
69797
|
-
deleted += 1;
|
|
69798
|
-
}
|
|
69799
|
-
}
|
|
69800
|
-
return deleted;
|
|
69801
|
-
}
|
|
69802
|
-
};
|
|
69803
|
-
return storagePort;
|
|
69804
|
-
}
|
|
69805
69687
|
function parseScope(pathPart) {
|
|
69806
69688
|
const scopeResult = parseDataScopeContract(decodeURIComponent(pathPart));
|
|
69807
69689
|
if (!scopeResult.ok)
|
|
@@ -69833,13 +69715,15 @@ function createPsLiteRuntime(options) {
|
|
|
69833
69715
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
69834
69716
|
const auth = options.auth ?? createMissingAuthAdapter();
|
|
69835
69717
|
const dataStorage = toDataStoragePort(options.storage);
|
|
69836
|
-
|
|
69837
|
-
|
|
69838
|
-
|
|
69718
|
+
let accessLogReader = options.accessLogReader;
|
|
69719
|
+
let accessLogWriter = options.accessLogWriter;
|
|
69720
|
+
if (!accessLogReader || !accessLogWriter) {
|
|
69721
|
+
const accessLogStore = createDefaultAccessLogStore();
|
|
69722
|
+
accessLogReader ??= accessLogStore;
|
|
69723
|
+
accessLogWriter ??= accessLogStore;
|
|
69724
|
+
}
|
|
69839
69725
|
const tokenStore = options.tokenStore ?? createDefaultTokenStore();
|
|
69840
|
-
const saveConfig = options.saveConfig ?? (
|
|
69841
|
-
await savePsLiteConfig(createIndexedDbPsLiteStateStore(), nextConfig);
|
|
69842
|
-
} : void 0);
|
|
69726
|
+
const saveConfig = options.saveConfig ?? createDefaultSaveConfig();
|
|
69843
69727
|
const deviceSessions = createMemoryDeviceSessionStore();
|
|
69844
69728
|
async function withProtocolErrors(handler) {
|
|
69845
69729
|
try {
|
|
@@ -70036,7 +69920,7 @@ function createPsLiteRuntime(options) {
|
|
|
70036
69920
|
const stateCapabilities = {
|
|
70037
69921
|
tokens: tokenStore.capabilities?.tokens ?? "custom",
|
|
70038
69922
|
accessLogs: accessLogReader.capabilities?.accessLogs ?? "custom",
|
|
70039
|
-
config: options.stateCapabilities?.config ?? (options.saveConfig ? "custom" :
|
|
69923
|
+
config: options.stateCapabilities?.config ?? (options.saveConfig ? "custom" : "indexeddb")
|
|
70040
69924
|
};
|
|
70041
69925
|
return jsonResponse({
|
|
70042
69926
|
status: active ? "healthy" : "unavailable",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opendatalabs/personal-server-ts-server",
|
|
3
|
-
"version": "0.0.1-canary.
|
|
3
|
+
"version": "0.0.1-canary.eee90fe",
|
|
4
4
|
"description": "Hono HTTP server for the Vana Personal Server — routes, middleware, composition root",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@hono/node-server": "^1.19.13",
|
|
43
|
-
"@opendatalabs/personal-server-ts-core": "0.0.1-canary.
|
|
43
|
+
"@opendatalabs/personal-server-ts-core": "0.0.1-canary.eee90fe",
|
|
44
44
|
"@opendatalabs/personal-server-ts-lite": "*",
|
|
45
45
|
"@opendatalabs/vana-sdk": "file:../../../vana-sdk/packages/vana-sdk",
|
|
46
46
|
"hono": "^4.12.18",
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import type { MiddlewareHandler } from "hono";
|
|
2
|
-
import type { GatewayClient } from "@opendatalabs/vana-sdk/node";
|
|
3
|
-
/**
|
|
4
|
-
* Enforces grant for data reads. Must run AFTER web3-auth middleware.
|
|
5
|
-
* Fetches grant from Gateway, checks revocation/expiry/scope/grantee.
|
|
6
|
-
* Sets c.set('grant', grantResponse).
|
|
7
|
-
*/
|
|
8
|
-
export declare function createGrantCheckMiddleware(params: {
|
|
9
|
-
gateway: GatewayClient;
|
|
10
|
-
serverOwner?: `0x${string}`;
|
|
11
|
-
}): MiddlewareHandler;
|
|
12
|
-
//# sourceMappingURL=grant-check.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grant-check.d.ts","sourceRoot":"","sources":["../../src/middleware/grant-check.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AAC9C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAmCjE;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE;IACjD,OAAO,EAAE,aAAa,CAAC;IACvB,WAAW,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CAC7B,GAAG,iBAAiB,CAyEpB"}
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { scopeCoveredByGrant } from "@opendatalabs/vana-sdk/node";
|
|
2
|
-
import { GrantRequiredError, GrantRevokedError, GrantExpiredError, ScopeMismatchError, InvalidSignatureError, ProtocolError, } from "@opendatalabs/personal-server-ts-core/errors";
|
|
3
|
-
/**
|
|
4
|
-
* Parse the opaque `grant` string from the gateway response.
|
|
5
|
-
* The grant field is a JSON-serialized EIP-712 grant payload containing
|
|
6
|
-
* { user, builder, scopes, expiresAt, nonce }.
|
|
7
|
-
*/
|
|
8
|
-
function parseGrantPayload(grantString) {
|
|
9
|
-
try {
|
|
10
|
-
const parsed = JSON.parse(grantString);
|
|
11
|
-
return {
|
|
12
|
-
scopes: Array.isArray(parsed.scopes) ? parsed.scopes : [],
|
|
13
|
-
expiresAt: typeof parsed.expiresAt === "number" ? parsed.expiresAt : 0,
|
|
14
|
-
};
|
|
15
|
-
}
|
|
16
|
-
catch {
|
|
17
|
-
return { scopes: [], expiresAt: 0 };
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Enforces grant for data reads. Must run AFTER web3-auth middleware.
|
|
22
|
-
* Fetches grant from Gateway, checks revocation/expiry/scope/grantee.
|
|
23
|
-
* Sets c.set('grant', grantResponse).
|
|
24
|
-
*/
|
|
25
|
-
export function createGrantCheckMiddleware(params) {
|
|
26
|
-
const { gateway } = params;
|
|
27
|
-
return async (c, next) => {
|
|
28
|
-
if (c.get("isPolicyBypass") ?? c.get("devBypass")) {
|
|
29
|
-
await next();
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const auth = c.get("auth");
|
|
33
|
-
try {
|
|
34
|
-
// 1. Extract grantId from auth payload
|
|
35
|
-
const grantId = auth.payload.grantId;
|
|
36
|
-
if (!grantId) {
|
|
37
|
-
throw new GrantRequiredError({
|
|
38
|
-
reason: "No grantId in authorization payload",
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
// 2. Fetch grant from Gateway
|
|
42
|
-
const grant = await gateway.getGrant(grantId);
|
|
43
|
-
if (!grant) {
|
|
44
|
-
throw new GrantRequiredError({ reason: "Grant not found", grantId });
|
|
45
|
-
}
|
|
46
|
-
// 3. Check revocation — gateway uses revokedAt (null = not revoked)
|
|
47
|
-
if (grant.revokedAt !== null) {
|
|
48
|
-
throw new GrantRevokedError({ grantId: grant.id });
|
|
49
|
-
}
|
|
50
|
-
// 4. Parse the opaque grant string to extract scopes and expiresAt
|
|
51
|
-
const grantPayload = parseGrantPayload(grant.grant);
|
|
52
|
-
// 5. Check expiry (expiresAt > 0 && expiresAt < now means expired)
|
|
53
|
-
if (grantPayload.expiresAt > 0) {
|
|
54
|
-
const now = Math.floor(Date.now() / 1000);
|
|
55
|
-
if (grantPayload.expiresAt < now) {
|
|
56
|
-
throw new GrantExpiredError({ expiresAt: grantPayload.expiresAt });
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
// 6. Check scope coverage — extract scope from route param
|
|
60
|
-
const scope = c.req.param("scope");
|
|
61
|
-
if (scope && !scopeCoveredByGrant(scope, grantPayload.scopes)) {
|
|
62
|
-
throw new ScopeMismatchError({
|
|
63
|
-
requestedScope: scope,
|
|
64
|
-
grantedScopes: grantPayload.scopes,
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
// 7. Check grantee — signer must be the grant's builder.
|
|
68
|
-
// Gateway returns granteeId (bytes32 builderId), not an address.
|
|
69
|
-
// Look up builder by signer address, then compare builder.id === grant.granteeId.
|
|
70
|
-
const builder = await gateway.getBuilder(auth.signer);
|
|
71
|
-
if (!builder || builder.id !== grant.granteeId) {
|
|
72
|
-
throw new InvalidSignatureError({
|
|
73
|
-
reason: "Request signer is not the grant builder",
|
|
74
|
-
expected: grant.granteeId,
|
|
75
|
-
actual: auth.signer,
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
// Set grant on context for downstream handlers
|
|
79
|
-
c.set("grant", grant);
|
|
80
|
-
await next();
|
|
81
|
-
}
|
|
82
|
-
catch (err) {
|
|
83
|
-
if (err instanceof ProtocolError) {
|
|
84
|
-
return c.json(err.toJSON(), err.code);
|
|
85
|
-
}
|
|
86
|
-
throw err;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
//# sourceMappingURL=grant-check.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"grant-check.js","sourceRoot":"","sources":["../../src/middleware/grant-check.ts"],"names":[],"mappings":"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"}
|