@opendatalabs/personal-server-ts-server 1.3.5 → 1.4.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.
@@ -109469,6 +109469,30 @@ function createIndexedDbPsLiteAccessLogStore(options = {}) {
109469
109469
  }
109470
109470
  };
109471
109471
  }
109472
+ function indexedDbAvailable() {
109473
+ return typeof indexedDB !== "undefined";
109474
+ }
109475
+ function createDefaultPsLiteAccessLogStore() {
109476
+ if (!indexedDbAvailable()) {
109477
+ throw new Error("IndexedDB is required for default PS Lite access log persistence.");
109478
+ }
109479
+ return createIndexedDbPsLiteAccessLogStore();
109480
+ }
109481
+ function createDefaultPsLiteTokenStore() {
109482
+ if (!indexedDbAvailable()) {
109483
+ throw new Error("IndexedDB is required for default PS Lite token storage.");
109484
+ }
109485
+ return createIndexedDbPsLiteTokenStore();
109486
+ }
109487
+ function createDefaultPsLiteSaveConfig() {
109488
+ if (!indexedDbAvailable()) {
109489
+ throw new Error("IndexedDB is required for default PS Lite config persistence.");
109490
+ }
109491
+ const stateStore = createIndexedDbPsLiteStateStore();
109492
+ return async (nextConfig) => {
109493
+ await savePsLiteConfig(stateStore, nextConfig);
109494
+ };
109495
+ }
109472
109496
  async function loadOrCreatePsLiteConfig(store, defaults) {
109473
109497
  const existing = await store.get(CONFIG_KEY);
109474
109498
  if (!existing) {
@@ -126576,15 +126600,6 @@ function toDataStoragePort(storage) {
126576
126600
  }
126577
126601
  throw new Error("PS Lite runtime requires a persistent DataStoragePort. Use createIndexedDbPsLiteRuntime() or createPersistentPsLiteStorage().");
126578
126602
  }
126579
- function indexedDbAvailable() {
126580
- return typeof indexedDB !== "undefined";
126581
- }
126582
- function createDefaultAccessLogStore() {
126583
- if (!indexedDbAvailable()) {
126584
- throw new Error("IndexedDB is required for default PS Lite access log persistence.");
126585
- }
126586
- return createIndexedDbPsLiteAccessLogStore();
126587
- }
126588
126603
  function createLogId() {
126589
126604
  return globalThis.crypto?.randomUUID?.() ?? `log-${Date.now()}`;
126590
126605
  }
@@ -126593,27 +126608,32 @@ function randomHex(byteLength) {
126593
126608
  globalThis.crypto.getRandomValues(bytes2);
126594
126609
  return Array.from(bytes2, (byte) => byte.toString(16).padStart(2, "0")).join("");
126595
126610
  }
126596
- function createDefaultTokenStore() {
126597
- if (!indexedDbAvailable()) {
126598
- throw new Error("IndexedDB is required for default PS Lite token storage.");
126599
- }
126600
- return createIndexedDbPsLiteTokenStore();
126601
- }
126602
- function createDefaultSaveConfig() {
126603
- if (!indexedDbAvailable()) {
126604
- throw new Error("IndexedDB is required for default PS Lite config persistence.");
126605
- }
126606
- const stateStore = createIndexedDbPsLiteStateStore();
126607
- return async (nextConfig) => {
126608
- await savePsLiteConfig(stateStore, nextConfig);
126609
- };
126610
- }
126611
126611
  function bearerToken(request2) {
126612
126612
  const authorization = request2.headers.get("authorization");
126613
126613
  if (!authorization?.startsWith("Bearer "))
126614
126614
  return null;
126615
126615
  return authorization.slice(7);
126616
126616
  }
126617
+ function snapshotGatewayConfig(config2) {
126618
+ const gateway = config2?.gateway;
126619
+ if (!gateway)
126620
+ return void 0;
126621
+ return {
126622
+ ...gateway,
126623
+ ...gateway.contracts ? { contracts: { ...gateway.contracts } } : {}
126624
+ };
126625
+ }
126626
+ function resolveX402Settings(config2, gateway = config2?.gateway) {
126627
+ const paymentEnabled = config2?.payment?.enabled ?? false;
126628
+ const gatewayConfigComplete = Boolean(gateway && typeof gateway.url === "string" && typeof gateway.chainId === "number" && gateway.contracts && typeof gateway.contracts.dataPortabilityEscrow === "string" && typeof gateway.contracts.dataRegistry === "string");
126629
+ if (paymentEnabled && !gatewayConfigComplete) {
126630
+ throw new Error("PS-Lite x402 payment is enabled (config.payment.enabled) but the gateway config is incomplete. A complete gateway config \u2014 url, chainId, and contracts (dataPortabilityEscrow, dataRegistry) \u2014 is required to charge for reads. Provide the full config or disable payment.");
126631
+ }
126632
+ return {
126633
+ paymentEnabled,
126634
+ gatewayConfig: gatewayConfigComplete ? gateway : void 0
126635
+ };
126636
+ }
126617
126637
  function createPsLiteRuntime(options) {
126618
126638
  let active = options.active ?? false;
126619
126639
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
@@ -126625,19 +126645,14 @@ function createPsLiteRuntime(options) {
126625
126645
  let accessLogReader = options.accessLogReader;
126626
126646
  let accessLogWriter = options.accessLogWriter;
126627
126647
  if (!accessLogReader || !accessLogWriter) {
126628
- const accessLogStore = createDefaultAccessLogStore();
126648
+ const accessLogStore = createDefaultPsLiteAccessLogStore();
126629
126649
  accessLogReader ??= accessLogStore;
126630
126650
  accessLogWriter ??= accessLogStore;
126631
126651
  }
126632
- const tokenStore = options.tokenStore ?? createDefaultTokenStore();
126633
- const saveConfig = options.saveConfig ?? createDefaultSaveConfig();
126634
- const paymentEnabled = options.config?.payment?.enabled ?? false;
126635
- const gw2 = options.config?.gateway;
126636
- const gatewayConfigComplete = Boolean(gw2 && typeof gw2.url === "string" && typeof gw2.chainId === "number" && gw2.contracts && typeof gw2.contracts.dataPortabilityEscrow === "string" && typeof gw2.contracts.dataRegistry === "string");
126637
- if (paymentEnabled && !gatewayConfigComplete) {
126638
- throw new Error("PS-Lite x402 payment is enabled (config.payment.enabled) but the gateway config is incomplete. A complete gateway config \u2014 url, chainId, and contracts (dataPortabilityEscrow, dataRegistry) \u2014 is required to charge for reads. Provide the full config or disable payment.");
126639
- }
126640
- const x402GatewayConfig = gatewayConfigComplete ? gw2 : void 0;
126652
+ const tokenStore = options.tokenStore ?? createDefaultPsLiteTokenStore();
126653
+ const saveConfig = options.saveConfig ?? createDefaultPsLiteSaveConfig();
126654
+ const boundGatewayConfig = snapshotGatewayConfig(options.config);
126655
+ resolveX402Settings(options.config, boundGatewayConfig);
126641
126656
  const x402ServerSigner = options.serverSigner?.signRecordDataAccess ? { signRecordDataAccess: options.serverSigner.signRecordDataAccess } : void 0;
126642
126657
  const deviceSessions = createMemoryDeviceSessionStore();
126643
126658
  const mcpOAuthAuthorizationStore = options.mcpOAuthAuthorizationStore ?? createInMemoryMcpOAuthAuthorizationStore();
@@ -126847,6 +126862,7 @@ function createPsLiteRuntime(options) {
126847
126862
  }
126848
126863
  const dataPrefix = "/v1/data";
126849
126864
  if (url2.pathname === dataPrefix || url2.pathname.startsWith(`${dataPrefix}/`)) {
126865
+ const x402 = resolveX402Settings(options.config, boundGatewayConfig);
126850
126866
  return handlePersonalServerDataRequest(request2, {
126851
126867
  storage: dataStorage,
126852
126868
  auth,
@@ -126859,10 +126875,10 @@ function createPsLiteRuntime(options) {
126859
126875
  // complete gateway config (validated at construction); a partial
126860
126876
  // config leaves these undefined so reads are served free instead
126861
126877
  // of yielding a malformed challenge.
126862
- paymentEnabled,
126878
+ paymentEnabled: x402.paymentEnabled,
126863
126879
  gateway: options.gateway,
126864
- gatewayConfig: x402GatewayConfig,
126865
- gatewayUrl: x402GatewayConfig?.url,
126880
+ gatewayConfig: x402.gatewayConfig,
126881
+ gatewayUrl: x402.gatewayConfig?.url,
126866
126882
  serverAddress: options.identity?.address,
126867
126883
  // The data owner signed into the RecordDataAccess attestation.
126868
126884
  // Distinct from serverAddress (the server keypair): the core only
@@ -126930,7 +126946,11 @@ function createPsLiteRuntime(options) {
126930
126946
  return options.config ?? {};
126931
126947
  },
126932
126948
  async writeConfig(config2) {
126949
+ resolveX402Settings(config2, boundGatewayConfig);
126933
126950
  await saveConfig(config2);
126951
+ if (options.config && typeof config2 === "object" && config2 !== null) {
126952
+ Object.assign(options.config, config2);
126953
+ }
126934
126954
  }
126935
126955
  });
126936
126956
  }
@@ -126949,7 +126969,9 @@ function createPsLiteRuntime(options) {
126949
126969
  runtimeAvailability: { isAvailable: () => active },
126950
126970
  serverOrigin: url2.origin,
126951
126971
  gateway: options.gateway,
126952
- gatewayConfig: options.config?.gateway,
126972
+ // Pinned like the x402 path: grant registration is signed with the
126973
+ // startup EIP-712 domain, so the MCP route must see the same one.
126974
+ gatewayConfig: boundGatewayConfig,
126953
126975
  serverOwner: options.serverOwner ?? options.identity?.address,
126954
126976
  serverSigner: options.serverSigner,
126955
126977
  activityRecorder
@@ -128488,10 +128510,33 @@ async function createPsLiteSyncManager(options) {
128488
128510
  return { syncManager, serverOwner };
128489
128511
  }
128490
128512
 
128513
+ // ../lite/dist/persistence.js
128514
+ function assertCompletePsLitePersistenceBundle(bundle) {
128515
+ if (!bundle || typeof bundle !== "object") {
128516
+ throw new Error("PS Lite persistence bundle must be a complete object");
128517
+ }
128518
+ const required2 = [
128519
+ "storage",
128520
+ "state",
128521
+ "tokens",
128522
+ "accessLog",
128523
+ "mcpConnections",
128524
+ "mcpOAuthAuthorizations",
128525
+ "relayTlsIdentity"
128526
+ ];
128527
+ const missing = required2.filter((key) => bundle[key] == null);
128528
+ if (missing.length > 0) {
128529
+ throw new Error(`PS Lite persistence bundle must be complete; missing ${missing.join(", ")}`);
128530
+ }
128531
+ }
128532
+
128491
128533
  // ../lite/dist/browser-runtime.js
128492
128534
  async function createIndexedDbPsLiteRuntime(options) {
128493
128535
  const dbName = options.dbName ?? "personal-server-lite";
128494
- const stateStore = createIndexedDbPsLiteStateStore({
128536
+ const injected = options.persistence;
128537
+ if (injected !== void 0)
128538
+ assertCompletePsLitePersistenceBundle(injected);
128539
+ const stateStore = injected?.state ?? createIndexedDbPsLiteStateStore({
128495
128540
  dbName,
128496
128541
  storeName: options.stateStoreName ?? "state"
128497
128542
  });
@@ -128500,15 +128545,15 @@ async function createIndexedDbPsLiteRuntime(options) {
128500
128545
  store: stateStore,
128501
128546
  ownerSignature: options.ownerSignature
128502
128547
  });
128503
- const tokenStore = createIndexedDbPsLiteTokenStore({
128548
+ const tokenStore = injected?.tokens ?? createIndexedDbPsLiteTokenStore({
128504
128549
  dbName,
128505
128550
  storeName: "tokens"
128506
128551
  });
128507
- const accessLogStore = createIndexedDbPsLiteAccessLogStore({
128552
+ const accessLogStore = injected?.accessLog ?? createIndexedDbPsLiteAccessLogStore({
128508
128553
  dbName,
128509
128554
  storeName: "accessLogs"
128510
128555
  });
128511
- const storage = await createPersistentPsLiteStorage({ kind: "indexeddb" }, createIndexedDbPsLitePersistence({
128556
+ const storage = injected?.storage ?? await createPersistentPsLiteStorage({ kind: "indexeddb" }, createIndexedDbPsLitePersistence({
128512
128557
  dbName: options.storageDbName ?? `${dbName}-storage`,
128513
128558
  storeName: options.storageStoreName ?? "state",
128514
128559
  key: options.storageKey ?? "data-storage-v1"
@@ -128569,10 +128614,14 @@ async function createIndexedDbPsLiteRuntime(options) {
128569
128614
  const saved = await savePsLiteConfig(stateStore, nextConfig);
128570
128615
  Object.assign(config2, saved);
128571
128616
  },
128572
- stateCapabilities: { config: "indexeddb" },
128617
+ stateCapabilities: { config: injected?.state ? "custom" : "indexeddb" },
128573
128618
  tokenStore,
128574
128619
  accessLogReader: accessLogStore,
128575
- accessLogWriter: accessLogStore
128620
+ accessLogWriter: accessLogStore,
128621
+ // A complete host bundle owns both MCP records too. Direct options remain
128622
+ // available only on the default Web path for backwards compatibility.
128623
+ mcpConnectionStore: injected?.mcpConnections ?? options.mcpConnectionStore,
128624
+ mcpOAuthAuthorizationStore: injected?.mcpOAuthAuthorizations ?? options.mcpOAuthAuthorizationStore
128576
128625
  });
128577
128626
  runtimeRef = runtime;
128578
128627
  return {
@@ -129601,13 +129650,14 @@ function createRustlsPsLiteRelayTlsFactory(options) {
129601
129650
  let trustedIdentity;
129602
129651
  let inFlight;
129603
129652
  let inFlightToken;
129653
+ const identityStore = options.identityStore ?? (options.storage ? createLocalStoragePsLiteRelayTlsIdentityStore(options.storage) : void 0);
129604
129654
  async function resolveIdentity(input) {
129605
129655
  if (trustedIdentity) {
129606
129656
  return trustedIdentity;
129607
129657
  }
129608
129658
  const token = input.issueToken ?? "";
129609
129659
  if (!inFlight || token && token !== inFlightToken) {
129610
- const attempt = createTlsIdentity(input, options).finally(() => {
129660
+ const attempt = createTlsIdentity(input, options, identityStore ?? createLocalStoragePsLiteRelayTlsIdentityStore()).finally(() => {
129611
129661
  if (inFlight === attempt) {
129612
129662
  inFlight = void 0;
129613
129663
  inFlightToken = void 0;
@@ -129666,9 +129716,9 @@ function normalizeTlsStep(value) {
129666
129716
  handshaking: Boolean(step.handshaking)
129667
129717
  };
129668
129718
  }
129669
- async function createTlsIdentity(input, options) {
129719
+ async function createTlsIdentity(input, options, identityStore) {
129670
129720
  const hostname3 = psLiteRelayPublicHost(input.sessionId, options.publicSuffix);
129671
- const cached2 = readCachedTlsIdentity(hostname3, options.storage);
129721
+ const cached2 = await readCachedTlsIdentity(hostname3, identityStore);
129672
129722
  if (cached2) {
129673
129723
  return cached2;
129674
129724
  }
@@ -129677,7 +129727,7 @@ async function createTlsIdentity(input, options) {
129677
129727
  sessionId: input.sessionId,
129678
129728
  issueToken: input.issueToken ?? "",
129679
129729
  hostname: hostname3,
129680
- storage: options.storage,
129730
+ identityStore,
129681
129731
  logger: options.logger,
129682
129732
  timeoutMs: options.issueCertTimeoutMs ?? DEFAULT_ISSUE_CERT_TIMEOUT_MS
129683
129733
  });
@@ -129796,20 +129846,27 @@ async function fetchSessionCert(input) {
129796
129846
  trusted: true
129797
129847
  };
129798
129848
  try {
129799
- cacheTlsIdentity(identity, input.storage);
129849
+ await cacheTlsIdentity(identity, input.identityStore);
129800
129850
  } catch (error51) {
129801
129851
  input.logger?.(`failed to persist session certificate (${error51 instanceof Error ? error51.message : String(error51)}); continuing with the in-memory identity`);
129802
129852
  }
129803
129853
  return identity;
129804
129854
  }
129805
- function readCachedTlsIdentity(hostname3, storage = globalThis.localStorage) {
129806
- try {
129807
- const raw = storage.getItem(`${TLS_IDENTITY_CACHE_KEY}:${hostname3}`);
129808
- if (!raw) {
129809
- return void 0;
129855
+ function createLocalStoragePsLiteRelayTlsIdentityStore(storage = globalThis.localStorage) {
129856
+ return {
129857
+ read(hostname3) {
129858
+ const raw = storage.getItem(`${TLS_IDENTITY_CACHE_KEY}:${hostname3}`);
129859
+ return raw ? JSON.parse(raw) : null;
129860
+ },
129861
+ write(identity) {
129862
+ storage.setItem(`${TLS_IDENTITY_CACHE_KEY}:${identity.hostname}`, JSON.stringify(identity));
129810
129863
  }
129811
- const identity = JSON.parse(raw);
129812
- if (identity.hostname !== hostname3 || !identity.certPem || !identity.keyPem || identity.source !== "acme") {
129864
+ };
129865
+ }
129866
+ async function readCachedTlsIdentity(hostname3, identityStore) {
129867
+ try {
129868
+ const identity = await identityStore.read(hostname3);
129869
+ if (!identity || identity.hostname !== hostname3 || !identity.certPem || !identity.keyPem || identity.source !== "acme") {
129813
129870
  return void 0;
129814
129871
  }
129815
129872
  const notAfter = firstCertificateNotAfter(identity.certPem);
@@ -129825,11 +129882,11 @@ function readCachedTlsIdentity(hostname3, storage = globalThis.localStorage) {
129825
129882
  return void 0;
129826
129883
  }
129827
129884
  }
129828
- function cacheTlsIdentity(identity, storage = globalThis.localStorage) {
129885
+ async function cacheTlsIdentity(identity, identityStore) {
129829
129886
  if (identity.source !== "acme") {
129830
129887
  return;
129831
129888
  }
129832
- storage.setItem(`${TLS_IDENTITY_CACHE_KEY}:${identity.hostname}`, JSON.stringify(identity));
129889
+ await identityStore.write(identity);
129833
129890
  }
129834
129891
  function firstCertificateNotAfter(certPem) {
129835
129892
  const match = certPem.match(/-----BEGIN CERTIFICATE-----[\s\S]+?-----END CERTIFICATE-----/);
@@ -129869,6 +129926,7 @@ function startPsLiteRelayClient(options) {
129869
129926
  controlUrl: baseControlUrl,
129870
129927
  publicSuffix: options.publicSuffix,
129871
129928
  certIssuerUrl: options.certIssuerUrl,
129929
+ identityStore: options.tlsIdentityStore,
129872
129930
  logger: options.logger
129873
129931
  }) : options.tls;
129874
129932
  const streams = /* @__PURE__ */ new Map();
@@ -130376,9 +130434,15 @@ function httpStatusText(status2) {
130376
130434
  // ../lite/dist/client.js
130377
130435
  var DEFAULT_LITE_ORIGIN = "https://ps-lite.local";
130378
130436
  async function startPersonalServer(options) {
130437
+ if (options.persistence && options.runtime) {
130438
+ throw new Error("runtime cannot be supplied with a complete persistence bundle");
130439
+ }
130440
+ if (options.persistence && options.relayStateStore) {
130441
+ throw new Error("relayStateStore cannot be supplied with a complete persistence bundle");
130442
+ }
130379
130443
  const localOrigin = options.localOrigin ?? DEFAULT_LITE_ORIGIN;
130380
130444
  const relayOptions = options.relay || void 0;
130381
- const relayStateStore = relayOptions ? options.relayStateStore ?? (options.runtime ? void 0 : createIndexedDbPsLiteStateStore({
130445
+ const relayStateStore = relayOptions ? options.relayStateStore ?? options.persistence?.state ?? (options.runtime ? void 0 : createIndexedDbPsLiteStateStore({
130382
130446
  dbName: options.dbName ?? "personal-server-lite",
130383
130447
  storeName: options.stateStoreName ?? "state"
130384
130448
  })) : void 0;
@@ -130421,6 +130485,7 @@ async function startPersonalServer(options) {
130421
130485
  ...resolvedRelayOptions,
130422
130486
  runtime,
130423
130487
  origin: runtimeOrigin,
130488
+ tlsIdentityStore: options.persistence?.relayTlsIdentity ?? resolvedRelayOptions.tlsIdentityStore,
130424
130489
  onStatus(nextRelayStatus, detail) {
130425
130490
  relayStatus2 = nextRelayStatus;
130426
130491
  if (nextRelayStatus === "error")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opendatalabs/personal-server-ts-server",
3
- "version": "1.3.5",
3
+ "version": "1.4.0",
4
4
  "description": "Hono HTTP server for the Vana Personal Server — routes, middleware, composition root",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -44,8 +44,8 @@
44
44
  },
45
45
  "dependencies": {
46
46
  "@hono/node-server": "^1.19.13",
47
- "@opendatalabs/personal-server-ts-core": "1.3.5",
48
- "@opendatalabs/personal-server-ts-lite": "1.3.5",
47
+ "@opendatalabs/personal-server-ts-core": "1.4.0",
48
+ "@opendatalabs/personal-server-ts-lite": "1.4.0",
49
49
  "@opendatalabs/vana-sdk": "3.14.0",
50
50
  "better-sqlite3": "^12.11.1",
51
51
  "hono": "^4.12.27",