holosphere 2.0.0-alpha12 → 2.0.0-alpha13
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/{2019-DQdDE6DG.js → 2019-CLMqIAfQ.js} +1722 -1668
- package/dist/{2019-DQdDE6DG.js.map → 2019-CLMqIAfQ.js.map} +1 -1
- package/dist/2019-Cp3uYhyY.cjs +8 -0
- package/dist/{2019-Ew-DTDlI.cjs.map → 2019-Cp3uYhyY.cjs.map} +1 -1
- package/dist/{browser-D2qtVhH5.cjs → browser-D6cNVl0v.cjs} +2 -2
- package/dist/{browser-D2qtVhH5.cjs.map → browser-D6cNVl0v.cjs.map} +1 -1
- package/dist/{browser-CckFyRI9.js → browser-nUQt1cnB.js} +2 -2
- package/dist/{browser-CckFyRI9.js.map → browser-nUQt1cnB.js.map} +1 -1
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +1 -1
- package/dist/{index-TDDyakLc.js → index-BN_uoxQK.js} +610 -128
- package/dist/index-BN_uoxQK.js.map +1 -0
- package/dist/{index-DrYM1LOY.js → index-CoAjtqsD.js} +2 -2
- package/dist/{index-DrYM1LOY.js.map → index-CoAjtqsD.js.map} +1 -1
- package/dist/{index-kyf1sjaC.cjs → index-Cp3tI53z.cjs} +2 -2
- package/dist/{index-kyf1sjaC.cjs.map → index-Cp3tI53z.cjs.map} +1 -1
- package/dist/{index-C0ITDyFo.cjs → index-DJjGSwXG.cjs} +2 -2
- package/dist/{index-C0ITDyFo.cjs.map → index-DJjGSwXG.cjs.map} +1 -1
- package/dist/index-V8EHMYEY.cjs +29 -0
- package/dist/index-V8EHMYEY.cjs.map +1 -0
- package/dist/{index-lbSQUoRz.js → index-Z5TstN1e.js} +2 -2
- package/dist/{index-lbSQUoRz.js.map → index-Z5TstN1e.js.map} +1 -1
- package/dist/indexeddb-storage-CZK5A7XH.cjs +2 -0
- package/dist/indexeddb-storage-CZK5A7XH.cjs.map +1 -0
- package/dist/{indexeddb-storage-CXhjqwhA.js → indexeddb-storage-bpA01pAU.js} +39 -2
- package/dist/indexeddb-storage-bpA01pAU.js.map +1 -0
- package/dist/{memory-storage-D1tc1bjk.cjs → memory-storage-B1k8Jszd.cjs} +2 -2
- package/dist/{memory-storage-D1tc1bjk.cjs.map → memory-storage-B1k8Jszd.cjs.map} +1 -1
- package/dist/{memory-storage-DkewsdcM.js → memory-storage-BqhmytP_.js} +2 -2
- package/dist/{memory-storage-DkewsdcM.js.map → memory-storage-BqhmytP_.js.map} +1 -1
- package/package.json +1 -1
- package/src/crypto/secp256k1.js +58 -9
- package/src/federation/card-storage.js +72 -0
- package/src/federation/handshake.js +363 -8
- package/src/federation/hologram.js +31 -3
- package/src/federation/holon-registry.js +22 -1
- package/src/federation/registry.js +54 -4
- package/src/index.js +52 -4
- package/src/storage/indexeddb-storage.js +41 -0
- package/src/storage/nostr-async.js +12 -3
- package/src/storage/nostr-client.js +112 -11
- package/src/storage/nostr-wrapper.js +5 -2
- package/dist/2019-Ew-DTDlI.cjs +0 -8
- package/dist/index-9sqetkAn.cjs +0 -29
- package/dist/index-9sqetkAn.cjs.map +0 -1
- package/dist/index-TDDyakLc.js.map +0 -1
- package/dist/indexeddb-storage-CXhjqwhA.js.map +0 -1
- package/dist/indexeddb-storage-DFESDYIj.cjs +0 -2
- package/dist/indexeddb-storage-DFESDYIj.cjs.map +0 -1
|
@@ -18010,12 +18010,12 @@ async function createPersistentStorage(namespace, options = {}) {
|
|
|
18010
18010
|
const isBrowser = typeof window !== "undefined" && typeof window.indexedDB !== "undefined";
|
|
18011
18011
|
typeof process !== "undefined" && process.versions && void 0;
|
|
18012
18012
|
if (isBrowser) {
|
|
18013
|
-
const { IndexedDBStorage } = await import("./indexeddb-storage-
|
|
18013
|
+
const { IndexedDBStorage } = await import("./indexeddb-storage-bpA01pAU.js");
|
|
18014
18014
|
const storage = new IndexedDBStorage();
|
|
18015
18015
|
await storage.init(namespace);
|
|
18016
18016
|
return storage;
|
|
18017
18017
|
} else {
|
|
18018
|
-
const { MemoryStorage } = await import("./memory-storage-
|
|
18018
|
+
const { MemoryStorage } = await import("./memory-storage-BqhmytP_.js");
|
|
18019
18019
|
const storage = new MemoryStorage();
|
|
18020
18020
|
await storage.init(namespace);
|
|
18021
18021
|
return storage;
|
|
@@ -18028,7 +18028,7 @@ async function loadNDKCacheAdapter() {
|
|
|
18028
18028
|
ndkCacheAdapterLoaded = true;
|
|
18029
18029
|
if (typeof window !== "undefined" && typeof indexedDB !== "undefined") {
|
|
18030
18030
|
try {
|
|
18031
|
-
const module2 = await import("./index-
|
|
18031
|
+
const module2 = await import("./index-Z5TstN1e.js");
|
|
18032
18032
|
NDKCacheAdapterDexie = module2.default || module2.NDKCacheAdapterDexie;
|
|
18033
18033
|
} catch (e) {
|
|
18034
18034
|
console.debug("[nostr] NDK cache adapter not available, using LRU cache");
|
|
@@ -18197,13 +18197,20 @@ class NostrClient {
|
|
|
18197
18197
|
const CacheAdapter = await loadNDKCacheAdapter();
|
|
18198
18198
|
let cacheAdapter = null;
|
|
18199
18199
|
if (CacheAdapter && this.config.appName) {
|
|
18200
|
+
const dbName = `holosphere_ndk_${this.config.appName}`;
|
|
18201
|
+
await this._clearIncompatibleNDKCache(dbName);
|
|
18200
18202
|
try {
|
|
18201
|
-
cacheAdapter = new CacheAdapter({
|
|
18202
|
-
dbName: `holosphere_${this.config.appName}`
|
|
18203
|
-
});
|
|
18203
|
+
cacheAdapter = new CacheAdapter({ dbName });
|
|
18204
18204
|
this._useNDKCache = true;
|
|
18205
18205
|
} catch (e) {
|
|
18206
18206
|
console.warn("[nostr] Failed to initialize NDK cache adapter:", e.message);
|
|
18207
|
+
await this._deleteDexieDatabase(dbName);
|
|
18208
|
+
try {
|
|
18209
|
+
cacheAdapter = new CacheAdapter({ dbName });
|
|
18210
|
+
this._useNDKCache = true;
|
|
18211
|
+
} catch (retryError) {
|
|
18212
|
+
console.warn("[nostr] Failed to initialize NDK cache adapter after reset:", retryError.message);
|
|
18213
|
+
}
|
|
18207
18214
|
}
|
|
18208
18215
|
}
|
|
18209
18216
|
if (this.relays.length > 0) {
|
|
@@ -18312,6 +18319,67 @@ class NostrClient {
|
|
|
18312
18319
|
}
|
|
18313
18320
|
}
|
|
18314
18321
|
}
|
|
18322
|
+
/**
|
|
18323
|
+
* Check if NDK cache database exists with potentially incompatible schema.
|
|
18324
|
+
* NDK cache adapter uses Dexie which can't handle primary key changes.
|
|
18325
|
+
* We detect this by checking if the database exists and clearing it if needed.
|
|
18326
|
+
* @param {string} dbName - The database name to check
|
|
18327
|
+
* @returns {Promise<void>}
|
|
18328
|
+
* @private
|
|
18329
|
+
*/
|
|
18330
|
+
async _clearIncompatibleNDKCache(dbName) {
|
|
18331
|
+
if (typeof indexedDB === "undefined") return;
|
|
18332
|
+
const databases = await indexedDB.databases?.() || [];
|
|
18333
|
+
const existingDb = databases.find((db) => db.name === dbName);
|
|
18334
|
+
if (existingDb) {
|
|
18335
|
+
try {
|
|
18336
|
+
await new Promise((resolve, reject) => {
|
|
18337
|
+
const request = indexedDB.open(dbName);
|
|
18338
|
+
request.onsuccess = () => {
|
|
18339
|
+
const db = request.result;
|
|
18340
|
+
const storeNames = Array.from(db.objectStoreNames);
|
|
18341
|
+
db.close();
|
|
18342
|
+
const requiredStores = ["events", "eventTags"];
|
|
18343
|
+
const hasRequiredStores = requiredStores.every((name2) => storeNames.includes(name2));
|
|
18344
|
+
if (!hasRequiredStores && storeNames.length > 0) {
|
|
18345
|
+
console.warn(`[nostr] NDK cache database ${dbName} has incompatible schema, clearing...`);
|
|
18346
|
+
this._deleteDexieDatabase(dbName).then(resolve).catch(resolve);
|
|
18347
|
+
} else {
|
|
18348
|
+
resolve();
|
|
18349
|
+
}
|
|
18350
|
+
};
|
|
18351
|
+
request.onerror = () => resolve();
|
|
18352
|
+
request.onblocked = () => resolve();
|
|
18353
|
+
});
|
|
18354
|
+
} catch {
|
|
18355
|
+
}
|
|
18356
|
+
}
|
|
18357
|
+
}
|
|
18358
|
+
/**
|
|
18359
|
+
* Delete a Dexie database by name.
|
|
18360
|
+
* Used to recover from schema upgrade errors.
|
|
18361
|
+
* @param {string} dbName - The database name to delete
|
|
18362
|
+
* @returns {Promise<void>}
|
|
18363
|
+
* @private
|
|
18364
|
+
*/
|
|
18365
|
+
async _deleteDexieDatabase(dbName) {
|
|
18366
|
+
if (typeof indexedDB === "undefined") return;
|
|
18367
|
+
return new Promise((resolve) => {
|
|
18368
|
+
const request = indexedDB.deleteDatabase(dbName);
|
|
18369
|
+
request.onsuccess = () => {
|
|
18370
|
+
console.log(`[nostr] Deleted incompatible database: ${dbName}`);
|
|
18371
|
+
resolve();
|
|
18372
|
+
};
|
|
18373
|
+
request.onerror = () => {
|
|
18374
|
+
console.warn(`[nostr] Failed to delete database: ${dbName}`);
|
|
18375
|
+
resolve();
|
|
18376
|
+
};
|
|
18377
|
+
request.onblocked = () => {
|
|
18378
|
+
console.warn(`[nostr] Database deletion blocked: ${dbName}`);
|
|
18379
|
+
resolve();
|
|
18380
|
+
};
|
|
18381
|
+
});
|
|
18382
|
+
}
|
|
18315
18383
|
/**
|
|
18316
18384
|
* Load events from persistent storage into cache
|
|
18317
18385
|
* @private
|
|
@@ -18412,6 +18480,7 @@ class NostrClient {
|
|
|
18412
18480
|
* @param {Object} [options={}] - Publish options
|
|
18413
18481
|
* @param {boolean} [options.waitForRelays=false] - Wait for relay confirmation
|
|
18414
18482
|
* @param {boolean} [options.debounce=true] - Debounce rapid writes to same d-tag
|
|
18483
|
+
* @param {string} [options.signingKey] - Private key to sign with (hex format). If not provided, uses client's default key.
|
|
18415
18484
|
* @returns {Promise<Object>} Signed event with relay publish results
|
|
18416
18485
|
* @example
|
|
18417
18486
|
* const result = await client.publish({
|
|
@@ -18459,7 +18528,7 @@ class NostrClient {
|
|
|
18459
18528
|
}
|
|
18460
18529
|
}, WRITE_DEBOUNCE_MS);
|
|
18461
18530
|
pendingWrites.set(dTagPath, { event, timer, resolve, reject });
|
|
18462
|
-
const signedEvent = this._createSignedEvent(event);
|
|
18531
|
+
const signedEvent = this._createSignedEvent(event, options.signingKey);
|
|
18463
18532
|
this._cacheEvent(signedEvent);
|
|
18464
18533
|
});
|
|
18465
18534
|
}
|
|
@@ -18467,9 +18536,12 @@ class NostrClient {
|
|
|
18467
18536
|
* Create a signed event using NDK or nostr-tools fallback.
|
|
18468
18537
|
* @private
|
|
18469
18538
|
* @param {Object} event - Unsigned event
|
|
18539
|
+
* @param {string} [signingKey] - Optional private key to sign with (hex format)
|
|
18470
18540
|
* @returns {Object} Signed event
|
|
18471
18541
|
*/
|
|
18472
|
-
_createSignedEvent(event) {
|
|
18542
|
+
_createSignedEvent(event, signingKey = null) {
|
|
18543
|
+
const keyToUse = signingKey || this.privateKey;
|
|
18544
|
+
const pubkeyToUse = signingKey ? getPublicKey$2(hexToBytes$2(signingKey)) : this.publicKey;
|
|
18473
18545
|
if (this.ndk) {
|
|
18474
18546
|
const ndkEvent = new NDKEvent(this.ndk);
|
|
18475
18547
|
ndkEvent.kind = event.kind;
|
|
@@ -18481,7 +18553,7 @@ class NostrClient {
|
|
|
18481
18553
|
content: ndkEvent.content,
|
|
18482
18554
|
tags: ndkEvent.tags,
|
|
18483
18555
|
created_at: ndkEvent.created_at,
|
|
18484
|
-
pubkey:
|
|
18556
|
+
pubkey: pubkeyToUse,
|
|
18485
18557
|
id: "",
|
|
18486
18558
|
// Will be set during actual publish
|
|
18487
18559
|
sig: ""
|
|
@@ -18489,11 +18561,11 @@ class NostrClient {
|
|
|
18489
18561
|
};
|
|
18490
18562
|
}
|
|
18491
18563
|
try {
|
|
18492
|
-
return finalizeEvent(event, hexToBytes$2(
|
|
18564
|
+
return finalizeEvent(event, hexToBytes$2(keyToUse));
|
|
18493
18565
|
} catch (e) {
|
|
18494
18566
|
return {
|
|
18495
18567
|
...event,
|
|
18496
|
-
pubkey:
|
|
18568
|
+
pubkey: pubkeyToUse,
|
|
18497
18569
|
id: Math.random().toString(16).slice(2).padStart(64, "0"),
|
|
18498
18570
|
sig: "mock-signature",
|
|
18499
18571
|
created_at: event.created_at || Math.floor(Date.now() / 1e3)
|
|
@@ -18506,6 +18578,7 @@ class NostrClient {
|
|
|
18506
18578
|
*/
|
|
18507
18579
|
async _doPublish(event, options = {}) {
|
|
18508
18580
|
const waitForRelays = options.waitForRelays || false;
|
|
18581
|
+
const signingKey = options.signingKey || null;
|
|
18509
18582
|
let signedEvent;
|
|
18510
18583
|
if (event.id && event.sig) {
|
|
18511
18584
|
signedEvent = event;
|
|
@@ -18515,10 +18588,15 @@ class NostrClient {
|
|
|
18515
18588
|
ndkEvent.content = event.content;
|
|
18516
18589
|
ndkEvent.tags = event.tags || [];
|
|
18517
18590
|
ndkEvent.created_at = event.created_at || Math.floor(Date.now() / 1e3);
|
|
18518
|
-
|
|
18591
|
+
if (signingKey) {
|
|
18592
|
+
const tempSigner = new NDKPrivateKeySigner(signingKey);
|
|
18593
|
+
await ndkEvent.sign(tempSigner);
|
|
18594
|
+
} else {
|
|
18595
|
+
await ndkEvent.sign(this.signer);
|
|
18596
|
+
}
|
|
18519
18597
|
signedEvent = ndkEvent.rawEvent();
|
|
18520
18598
|
} else {
|
|
18521
|
-
signedEvent = this._createSignedEvent(event);
|
|
18599
|
+
signedEvent = this._createSignedEvent(event, signingKey);
|
|
18522
18600
|
}
|
|
18523
18601
|
await this._cacheEvent(signedEvent);
|
|
18524
18602
|
if (this.outboxQueue) {
|
|
@@ -20885,7 +20963,7 @@ class GunSchemaValidator {
|
|
|
20885
20963
|
return true;
|
|
20886
20964
|
}
|
|
20887
20965
|
try {
|
|
20888
|
-
const AjvModule = await import("./2019-
|
|
20966
|
+
const AjvModule = await import("./2019-CLMqIAfQ.js").then((n2) => n2._);
|
|
20889
20967
|
this.Ajv = AjvModule.default || AjvModule;
|
|
20890
20968
|
this.validator = new this.Ajv({
|
|
20891
20969
|
allErrors: true,
|
|
@@ -21106,7 +21184,7 @@ class GunDBBackend extends StorageBackend {
|
|
|
21106
21184
|
let Gun;
|
|
21107
21185
|
try {
|
|
21108
21186
|
console.log("[gundb-backend] Importing Gun...");
|
|
21109
|
-
const gunModule = await import("./browser-
|
|
21187
|
+
const gunModule = await import("./browser-nUQt1cnB.js").then((n2) => n2.b);
|
|
21110
21188
|
Gun = gunModule.default || gunModule;
|
|
21111
21189
|
console.log("[gundb-backend] Gun imported:", typeof Gun);
|
|
21112
21190
|
} catch (error) {
|
|
@@ -22506,7 +22584,9 @@ const globalSubscriptions = /* @__PURE__ */ new Map();
|
|
|
22506
22584
|
const singlePathSubscriptions = /* @__PURE__ */ new Map();
|
|
22507
22585
|
const pendingQueries = /* @__PURE__ */ new Map();
|
|
22508
22586
|
const QUERY_DEDUP_WINDOW = 2e3;
|
|
22509
|
-
async function nostrPut(client, path, data,
|
|
22587
|
+
async function nostrPut(client, path, data, kindOrOptions = 3e4) {
|
|
22588
|
+
const options = typeof kindOrOptions === "number" ? { kind: kindOrOptions } : kindOrOptions;
|
|
22589
|
+
const kind2 = options.kind || 3e4;
|
|
22510
22590
|
const dataEvent = {
|
|
22511
22591
|
kind: kind2,
|
|
22512
22592
|
created_at: Math.floor(Date.now() / 1e3),
|
|
@@ -22516,7 +22596,8 @@ async function nostrPut(client, path, data, kind2 = 3e4) {
|
|
|
22516
22596
|
],
|
|
22517
22597
|
content: JSON.stringify(data)
|
|
22518
22598
|
};
|
|
22519
|
-
const
|
|
22599
|
+
const publishOptions = options.signingKey ? { signingKey: options.signingKey } : {};
|
|
22600
|
+
const result = await client.publish(dataEvent, publishOptions);
|
|
22520
22601
|
return result;
|
|
22521
22602
|
}
|
|
22522
22603
|
async function nostrGet(client, path, kind2 = 3e4, options = {}) {
|
|
@@ -23057,9 +23138,10 @@ function buildPath$1(appname, holon, lens, key = null) {
|
|
|
23057
23138
|
function encodePathComponent(component) {
|
|
23058
23139
|
return encodeURIComponent(component).replace(/%2F/g, "/");
|
|
23059
23140
|
}
|
|
23060
|
-
async function write$1(client, path, data) {
|
|
23141
|
+
async function write$1(client, path, data, options = {}) {
|
|
23061
23142
|
try {
|
|
23062
|
-
const
|
|
23143
|
+
const putOptions = options.signingKey ? { signingKey: options.signingKey } : {};
|
|
23144
|
+
const result = await nostrPut(client, path, data, putOptions);
|
|
23063
23145
|
const success = result.results.length === 0 ? true : result.results.some((r) => r.status === "fulfilled");
|
|
23064
23146
|
return success;
|
|
23065
23147
|
} catch (error) {
|
|
@@ -23782,28 +23864,72 @@ async function issueSelfCapability(permissions, scope, authorPubKey, options = {
|
|
|
23782
23864
|
async function verifyCapability$1(token, requiredPermission, scope) {
|
|
23783
23865
|
try {
|
|
23784
23866
|
let tokenObj;
|
|
23867
|
+
if (token && typeof token === "object" && token.token) {
|
|
23868
|
+
token = token.token;
|
|
23869
|
+
}
|
|
23785
23870
|
if (typeof token === "string") {
|
|
23786
|
-
|
|
23787
|
-
|
|
23788
|
-
|
|
23789
|
-
|
|
23790
|
-
|
|
23871
|
+
if (token.startsWith("ey") || !token.includes(".") && !token.startsWith("{")) {
|
|
23872
|
+
try {
|
|
23873
|
+
const payload = token.includes(".") ? token.split(".")[0] : token;
|
|
23874
|
+
const decoded = Buffer.from ? Buffer.from(payload, "base64").toString("utf8") : atob(payload);
|
|
23875
|
+
tokenObj = JSON.parse(decoded);
|
|
23876
|
+
} catch (e) {
|
|
23877
|
+
console.log("[verifyCapability] ❌ Token is not valid base64 JSON:", {
|
|
23878
|
+
preview: token.substring(0, 50),
|
|
23879
|
+
error: e.message
|
|
23880
|
+
});
|
|
23881
|
+
return false;
|
|
23882
|
+
}
|
|
23883
|
+
} else if (token.startsWith("{")) {
|
|
23884
|
+
try {
|
|
23885
|
+
tokenObj = JSON.parse(token);
|
|
23886
|
+
} catch (e) {
|
|
23887
|
+
console.log("[verifyCapability] ❌ Token is not valid JSON:", {
|
|
23888
|
+
preview: token.substring(0, 50),
|
|
23889
|
+
error: e.message
|
|
23890
|
+
});
|
|
23891
|
+
return false;
|
|
23892
|
+
}
|
|
23893
|
+
} else {
|
|
23894
|
+
console.log("[verifyCapability] ❌ Unknown token format:", token.substring(0, 50));
|
|
23895
|
+
return false;
|
|
23896
|
+
}
|
|
23897
|
+
} else if (token && typeof token === "object") {
|
|
23791
23898
|
tokenObj = token;
|
|
23899
|
+
} else {
|
|
23900
|
+
console.log("[verifyCapability] ❌ Invalid token:", typeof token);
|
|
23901
|
+
return false;
|
|
23792
23902
|
}
|
|
23793
23903
|
if (!tokenObj || tokenObj.type !== "capability") {
|
|
23904
|
+
console.log("[verifyCapability] ❌ Invalid token type:", { type: tokenObj?.type, tokenObj });
|
|
23794
23905
|
return false;
|
|
23795
23906
|
}
|
|
23796
23907
|
if (Date.now() > tokenObj.expires) {
|
|
23908
|
+
console.log("[verifyCapability] ❌ Token expired:", {
|
|
23909
|
+
expires: tokenObj.expires,
|
|
23910
|
+
now: Date.now(),
|
|
23911
|
+
expiredAgo: `${(Date.now() - tokenObj.expires) / 1e3}s ago`
|
|
23912
|
+
});
|
|
23797
23913
|
return false;
|
|
23798
23914
|
}
|
|
23799
23915
|
if (!matchScope(tokenObj.scope, scope)) {
|
|
23916
|
+
console.log("[verifyCapability] ❌ Scope mismatch:", {
|
|
23917
|
+
tokenScope: tokenObj.scope,
|
|
23918
|
+
requestedScope: scope
|
|
23919
|
+
});
|
|
23800
23920
|
return false;
|
|
23801
23921
|
}
|
|
23802
23922
|
if (!tokenObj.permissions.includes(requiredPermission)) {
|
|
23923
|
+
console.log("[verifyCapability] ❌ Permission denied:", {
|
|
23924
|
+
required: requiredPermission,
|
|
23925
|
+
has: tokenObj.permissions
|
|
23926
|
+
});
|
|
23803
23927
|
return false;
|
|
23804
23928
|
}
|
|
23929
|
+
console.log("[verifyCapability] ✅ Capability valid");
|
|
23805
23930
|
return true;
|
|
23806
23931
|
} catch (error) {
|
|
23932
|
+
console.log("[verifyCapability] ❌ Error:", error.message);
|
|
23807
23933
|
return false;
|
|
23808
23934
|
}
|
|
23809
23935
|
}
|
|
@@ -23889,21 +24015,60 @@ async function getFederatedPartner(client, appname, partnerPubKey) {
|
|
|
23889
24015
|
}
|
|
23890
24016
|
async function getCapabilityForAuthor(client, appname, authorPubKey, scope) {
|
|
23891
24017
|
const registry2 = await getFederationRegistry(client, appname);
|
|
24018
|
+
console.log("[Registry] 🔍 getCapabilityForAuthor called:", {
|
|
24019
|
+
authorPubKey: authorPubKey?.slice(0, 12) + "...",
|
|
24020
|
+
scope,
|
|
24021
|
+
federatedWithCount: registry2.federatedWith?.length || 0,
|
|
24022
|
+
federatedPartners: registry2.federatedWith?.map((p) => p.pubKey?.slice(0, 12) + "...") || []
|
|
24023
|
+
});
|
|
23892
24024
|
const partner = registry2.federatedWith.find((p) => p.pubKey === authorPubKey);
|
|
23893
|
-
if (!partner
|
|
24025
|
+
if (!partner) {
|
|
24026
|
+
console.log("[Registry] ❌ Partner not found in federatedWith");
|
|
24027
|
+
return null;
|
|
24028
|
+
}
|
|
24029
|
+
if (!partner.inboundCapabilities || partner.inboundCapabilities.length === 0) {
|
|
24030
|
+
console.log("[Registry] ❌ Partner has no inboundCapabilities:", {
|
|
24031
|
+
partnerPubKey: authorPubKey?.slice(0, 12) + "...",
|
|
24032
|
+
hasInboundCaps: !!partner.inboundCapabilities,
|
|
24033
|
+
inboundCapsLength: partner.inboundCapabilities?.length || 0
|
|
24034
|
+
});
|
|
23894
24035
|
return null;
|
|
23895
24036
|
}
|
|
23896
|
-
|
|
24037
|
+
console.log("[Registry] Partner found with inboundCapabilities:", {
|
|
24038
|
+
partnerPubKey: authorPubKey?.slice(0, 12) + "...",
|
|
24039
|
+
capsCount: partner.inboundCapabilities.length,
|
|
24040
|
+
capScopes: partner.inboundCapabilities.map((c) => c.scope)
|
|
24041
|
+
});
|
|
24042
|
+
const result = partner.inboundCapabilities.find((cap) => {
|
|
23897
24043
|
if (cap.expires && cap.expires < Date.now()) {
|
|
24044
|
+
console.log("[Registry] Capability expired:", { expires: cap.expires, now: Date.now() });
|
|
23898
24045
|
return false;
|
|
23899
24046
|
}
|
|
23900
|
-
|
|
24047
|
+
const matches = matchScope(cap.scope, scope);
|
|
24048
|
+
console.log("[Registry] Scope match check:", {
|
|
24049
|
+
capScope: cap.scope,
|
|
24050
|
+
requestedScope: scope,
|
|
24051
|
+
matches
|
|
24052
|
+
});
|
|
24053
|
+
return matches;
|
|
23901
24054
|
}) || null;
|
|
24055
|
+
if (result) {
|
|
24056
|
+
console.log("[Registry] ✅ Matching capability found");
|
|
24057
|
+
} else {
|
|
24058
|
+
console.log("[Registry] ❌ No matching capability found");
|
|
24059
|
+
}
|
|
24060
|
+
return result;
|
|
23902
24061
|
}
|
|
23903
24062
|
async function storeInboundCapability(client, appname, partnerPubKey, capabilityInfo) {
|
|
24063
|
+
console.log("[Registry] 📥 storeInboundCapability called:", {
|
|
24064
|
+
partnerPubKey: partnerPubKey?.slice(0, 12) + "...",
|
|
24065
|
+
scope: capabilityInfo?.scope,
|
|
24066
|
+
hasToken: !!capabilityInfo?.token
|
|
24067
|
+
});
|
|
23904
24068
|
const registry2 = await getFederationRegistry(client, appname);
|
|
23905
24069
|
const partner = registry2.federatedWith.find((p) => p.pubKey === partnerPubKey);
|
|
23906
24070
|
if (!partner) {
|
|
24071
|
+
console.log("[Registry] Partner not in registry, auto-adding with capability");
|
|
23907
24072
|
return addFederatedPartner(client, appname, partnerPubKey, {
|
|
23908
24073
|
addedVia: "capability_received",
|
|
23909
24074
|
inboundCapabilities: [capabilityInfo]
|
|
@@ -23916,17 +24081,21 @@ async function storeInboundCapability(client, appname, partnerPubKey, capability
|
|
|
23916
24081
|
(cap) => JSON.stringify(cap.scope) === JSON.stringify(capabilityInfo.scope)
|
|
23917
24082
|
);
|
|
23918
24083
|
if (existingIndex >= 0) {
|
|
24084
|
+
console.log("[Registry] Updating existing capability at index:", existingIndex);
|
|
23919
24085
|
partner.inboundCapabilities[existingIndex] = {
|
|
23920
24086
|
...capabilityInfo,
|
|
23921
24087
|
updatedAt: Date.now()
|
|
23922
24088
|
};
|
|
23923
24089
|
} else {
|
|
24090
|
+
console.log("[Registry] Adding new capability, total will be:", partner.inboundCapabilities.length + 1);
|
|
23924
24091
|
partner.inboundCapabilities.push({
|
|
23925
24092
|
...capabilityInfo,
|
|
23926
24093
|
receivedAt: Date.now()
|
|
23927
24094
|
});
|
|
23928
24095
|
}
|
|
23929
|
-
|
|
24096
|
+
const result = await saveFederationRegistry(client, appname, registry2);
|
|
24097
|
+
console.log("[Registry] ✅ Capability stored, registry saved:", result);
|
|
24098
|
+
return result;
|
|
23930
24099
|
}
|
|
23931
24100
|
async function storeOutboundCapability(client, appname, partnerPubKey, capabilityInfo) {
|
|
23932
24101
|
const registry2 = await getFederationRegistry(client, appname);
|
|
@@ -24137,13 +24306,17 @@ async function wouldCreateCircularHologram(client, appname, sourceHolon, targetH
|
|
|
24137
24306
|
return { isCircular: true, chain, reason: "max_depth_exceeded" };
|
|
24138
24307
|
}
|
|
24139
24308
|
function createHologram(sourceHolon, targetHolon, lensName, dataId, appname, options = {}) {
|
|
24140
|
-
const { authorPubKey
|
|
24309
|
+
const { authorPubKey } = options;
|
|
24310
|
+
let { capability } = options;
|
|
24141
24311
|
if (!authorPubKey) {
|
|
24142
24312
|
throw new Error("authorPubKey is required for hologram creation (unified model)");
|
|
24143
24313
|
}
|
|
24144
24314
|
if (!capability) {
|
|
24145
24315
|
throw new Error("capability is required for hologram creation (unified model)");
|
|
24146
24316
|
}
|
|
24317
|
+
if (typeof capability === "object" && capability.token) {
|
|
24318
|
+
capability = capability.token;
|
|
24319
|
+
}
|
|
24147
24320
|
const soul = buildPath(appname, sourceHolon, lensName, dataId);
|
|
24148
24321
|
const hologram2 = {
|
|
24149
24322
|
id: dataId,
|
|
@@ -24158,7 +24331,7 @@ function createHologram(sourceHolon, targetHolon, lensName, dataId, appname, opt
|
|
|
24158
24331
|
// Always present in unified model
|
|
24159
24332
|
},
|
|
24160
24333
|
capability,
|
|
24161
|
-
// Always
|
|
24334
|
+
// Always the token string (normalized above)
|
|
24162
24335
|
_meta: {
|
|
24163
24336
|
created: Date.now(),
|
|
24164
24337
|
sourceHolon,
|
|
@@ -24246,6 +24419,9 @@ async function resolveHologram(client, hologram2, visited = /* @__PURE__ */ new
|
|
|
24246
24419
|
let sourceData;
|
|
24247
24420
|
let capability = hologram2.capability;
|
|
24248
24421
|
const authorPubKey = target.authorPubKey;
|
|
24422
|
+
if (capability && typeof capability === "object" && capability.token) {
|
|
24423
|
+
capability = capability.token;
|
|
24424
|
+
}
|
|
24249
24425
|
if (!capability && options.appname && authorPubKey) {
|
|
24250
24426
|
const capEntry = await getCapabilityForAuthor(
|
|
24251
24427
|
client,
|
|
@@ -24258,7 +24434,7 @@ async function resolveHologram(client, hologram2, visited = /* @__PURE__ */ new
|
|
|
24258
24434
|
}
|
|
24259
24435
|
);
|
|
24260
24436
|
if (capEntry) {
|
|
24261
|
-
capability = capEntry.token;
|
|
24437
|
+
capability = capEntry.token || capEntry;
|
|
24262
24438
|
}
|
|
24263
24439
|
}
|
|
24264
24440
|
if (!skipCapabilityVerification) {
|
|
@@ -24458,6 +24634,15 @@ async function propagateData(client, appname, data, sourceHolon, targetHolon, le
|
|
|
24458
24634
|
return false;
|
|
24459
24635
|
}
|
|
24460
24636
|
const sourceAuthorPubKey = options.sourceAuthorPubKey || client.publicKey;
|
|
24637
|
+
const isPubkey2 = typeof targetHolon === "string" && /^[0-9a-f]{64}$/i.test(targetHolon);
|
|
24638
|
+
const targetAuthorPubKey = options.targetAuthorPubKey || (isPubkey2 ? targetHolon : client.publicKey);
|
|
24639
|
+
console.log("[propagateData] Creating hologram with capability:", {
|
|
24640
|
+
sourceHolon: sourceHolon?.slice(0, 12) + "...",
|
|
24641
|
+
targetHolon: targetHolon?.slice(0, 12) + "...",
|
|
24642
|
+
sourceAuthorPubKey: sourceAuthorPubKey?.slice(0, 12) + "...",
|
|
24643
|
+
targetAuthorPubKey: targetAuthorPubKey?.slice(0, 12) + "...",
|
|
24644
|
+
hasProvidedCapability: !!options.capability
|
|
24645
|
+
});
|
|
24461
24646
|
const hologram2 = await createHologramWithCapability(
|
|
24462
24647
|
client,
|
|
24463
24648
|
sourceHolon,
|
|
@@ -24467,6 +24652,7 @@ async function propagateData(client, appname, data, sourceHolon, targetHolon, le
|
|
|
24467
24652
|
appname,
|
|
24468
24653
|
{
|
|
24469
24654
|
sourceAuthorPubKey,
|
|
24655
|
+
targetAuthorPubKey,
|
|
24470
24656
|
capability: options.capability,
|
|
24471
24657
|
permissions: ["read"]
|
|
24472
24658
|
}
|
|
@@ -25055,6 +25241,108 @@ const nostrUtils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
|
|
|
25055
25241
|
signEvent,
|
|
25056
25242
|
verifyEvent
|
|
25057
25243
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
25244
|
+
const HOLON_REGISTRY_TABLE = "_holon-registry";
|
|
25245
|
+
function isPubkey(str2) {
|
|
25246
|
+
return typeof str2 === "string" && /^[0-9a-f]{64}$/i.test(str2);
|
|
25247
|
+
}
|
|
25248
|
+
async function registerHolon(client, appname, holonId, publicKey, options = {}) {
|
|
25249
|
+
if (!isPubkey(publicKey)) {
|
|
25250
|
+
throw new Error(`Invalid public key format: ${publicKey}`);
|
|
25251
|
+
}
|
|
25252
|
+
if (isPubkey(holonId)) {
|
|
25253
|
+
console.log("[HolonRegistry] registerHolon: holonId is already a pubkey, skipping registration");
|
|
25254
|
+
return true;
|
|
25255
|
+
}
|
|
25256
|
+
const entry = {
|
|
25257
|
+
id: holonId,
|
|
25258
|
+
holonId,
|
|
25259
|
+
publicKey,
|
|
25260
|
+
alias: options.alias || null,
|
|
25261
|
+
createdAt: Date.now(),
|
|
25262
|
+
updatedAt: Date.now(),
|
|
25263
|
+
createdBy: client.publicKey
|
|
25264
|
+
};
|
|
25265
|
+
console.log("[HolonRegistry] 📝 registerHolon:", {
|
|
25266
|
+
holonId,
|
|
25267
|
+
publicKey: publicKey?.slice(0, 12) + "...",
|
|
25268
|
+
alias: options.alias
|
|
25269
|
+
});
|
|
25270
|
+
const result = await writeGlobal(client, appname, HOLON_REGISTRY_TABLE, entry);
|
|
25271
|
+
console.log("[HolonRegistry] registerHolon result:", result);
|
|
25272
|
+
return result;
|
|
25273
|
+
}
|
|
25274
|
+
async function lookupHolon(client, appname, holonId) {
|
|
25275
|
+
if (isPubkey(holonId)) {
|
|
25276
|
+
return {
|
|
25277
|
+
holonId,
|
|
25278
|
+
publicKey: holonId,
|
|
25279
|
+
isDirect: true
|
|
25280
|
+
};
|
|
25281
|
+
}
|
|
25282
|
+
return readGlobal(client, appname, HOLON_REGISTRY_TABLE, holonId);
|
|
25283
|
+
}
|
|
25284
|
+
async function resolveHolonToPubkey(client, appname, holonId) {
|
|
25285
|
+
if (isPubkey(holonId)) {
|
|
25286
|
+
console.log("[HolonRegistry] resolveHolonToPubkey: holonId is already a pubkey:", holonId?.slice(0, 12) + "...");
|
|
25287
|
+
return holonId;
|
|
25288
|
+
}
|
|
25289
|
+
const entry = await lookupHolon(client, appname, holonId);
|
|
25290
|
+
if (entry?.publicKey) {
|
|
25291
|
+
console.log("[HolonRegistry] ✅ resolveHolonToPubkey: Found mapping", {
|
|
25292
|
+
holonId,
|
|
25293
|
+
publicKey: entry.publicKey?.slice(0, 12) + "...",
|
|
25294
|
+
alias: entry.alias
|
|
25295
|
+
});
|
|
25296
|
+
} else {
|
|
25297
|
+
console.log("[HolonRegistry] ❌ resolveHolonToPubkey: No mapping found for holonId:", holonId);
|
|
25298
|
+
}
|
|
25299
|
+
return entry?.publicKey || null;
|
|
25300
|
+
}
|
|
25301
|
+
async function unregisterHolon(client, appname, holonId) {
|
|
25302
|
+
if (isPubkey(holonId)) {
|
|
25303
|
+
return false;
|
|
25304
|
+
}
|
|
25305
|
+
const entry = {
|
|
25306
|
+
id: holonId,
|
|
25307
|
+
holonId,
|
|
25308
|
+
publicKey: null,
|
|
25309
|
+
_deleted: true,
|
|
25310
|
+
deletedAt: Date.now(),
|
|
25311
|
+
deletedBy: client.publicKey
|
|
25312
|
+
};
|
|
25313
|
+
return writeGlobal(client, appname, HOLON_REGISTRY_TABLE, entry);
|
|
25314
|
+
}
|
|
25315
|
+
async function updateHolon(client, appname, holonId, updates = {}) {
|
|
25316
|
+
const existing = await lookupHolon(client, appname, holonId);
|
|
25317
|
+
if (!existing || existing.isDirect) {
|
|
25318
|
+
return false;
|
|
25319
|
+
}
|
|
25320
|
+
const entry = {
|
|
25321
|
+
...existing,
|
|
25322
|
+
...updates,
|
|
25323
|
+
updatedAt: Date.now()
|
|
25324
|
+
};
|
|
25325
|
+
return writeGlobal(client, appname, HOLON_REGISTRY_TABLE, entry);
|
|
25326
|
+
}
|
|
25327
|
+
async function listRegisteredHolons(client, appname) {
|
|
25328
|
+
const entries = await getAllGlobal(client, appname, HOLON_REGISTRY_TABLE);
|
|
25329
|
+
return (entries || []).filter((e) => !e._deleted);
|
|
25330
|
+
}
|
|
25331
|
+
async function findHolonsByPubkey(client, appname, publicKey) {
|
|
25332
|
+
const all = await listRegisteredHolons(client, appname);
|
|
25333
|
+
return all.filter((e) => e.publicKey === publicKey);
|
|
25334
|
+
}
|
|
25335
|
+
const holonRegistry = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
25336
|
+
__proto__: null,
|
|
25337
|
+
findHolonsByPubkey,
|
|
25338
|
+
isPubkey,
|
|
25339
|
+
listRegisteredHolons,
|
|
25340
|
+
lookupHolon,
|
|
25341
|
+
registerHolon,
|
|
25342
|
+
resolveHolonToPubkey,
|
|
25343
|
+
unregisterHolon,
|
|
25344
|
+
updateHolon
|
|
25345
|
+
}, Symbol.toStringTag, { value: "Module" }));
|
|
25058
25346
|
async function issueCapability(client, targetPubKey, scope, permissions, options = {}) {
|
|
25059
25347
|
const {
|
|
25060
25348
|
expiresIn = 36e5,
|
|
@@ -25362,6 +25650,8 @@ const requestCard$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defin
|
|
|
25362
25650
|
const FEDERATION_CARDS_TABLE = "_federation-cards";
|
|
25363
25651
|
const DISMISSED_REQUESTS_TABLE = "_dismissed-federation-requests";
|
|
25364
25652
|
const PROCESSED_RESPONSES_TABLE = "_processed-federation-responses";
|
|
25653
|
+
const DM_STATE_TABLE = "_federation-dm-state";
|
|
25654
|
+
const PROCESSED_DMS_TABLE = "_processed-federation-dms";
|
|
25365
25655
|
async function saveCard(client, appname, card) {
|
|
25366
25656
|
const serialized = serializeCard(card);
|
|
25367
25657
|
serialized.id = card.id;
|
|
@@ -25484,6 +25774,32 @@ async function cleanupOldEntries(client, appname, maxAge = 30 * 24 * 60 * 60 * 1
|
|
|
25484
25774
|
}
|
|
25485
25775
|
return result;
|
|
25486
25776
|
}
|
|
25777
|
+
async function getLastDMFetchTime(client, appname) {
|
|
25778
|
+
const entry = await readGlobal(client, appname, DM_STATE_TABLE, "lastFetch");
|
|
25779
|
+
return entry?.timestamp || 0;
|
|
25780
|
+
}
|
|
25781
|
+
async function setLastDMFetchTime(client, appname, timestamp) {
|
|
25782
|
+
return writeGlobal(client, appname, DM_STATE_TABLE, {
|
|
25783
|
+
id: "lastFetch",
|
|
25784
|
+
timestamp,
|
|
25785
|
+
updatedAt: Date.now()
|
|
25786
|
+
});
|
|
25787
|
+
}
|
|
25788
|
+
async function markDMProcessed(client, appname, eventId, type2 = "unknown") {
|
|
25789
|
+
return writeGlobal(client, appname, PROCESSED_DMS_TABLE, {
|
|
25790
|
+
id: eventId,
|
|
25791
|
+
type: type2,
|
|
25792
|
+
processedAt: Date.now()
|
|
25793
|
+
});
|
|
25794
|
+
}
|
|
25795
|
+
async function isDMProcessed(client, appname, eventId) {
|
|
25796
|
+
const entry = await readGlobal(client, appname, PROCESSED_DMS_TABLE, eventId);
|
|
25797
|
+
return !!entry;
|
|
25798
|
+
}
|
|
25799
|
+
async function getProcessedDMIds(client, appname) {
|
|
25800
|
+
const entries = await getAllGlobal(client, appname, PROCESSED_DMS_TABLE);
|
|
25801
|
+
return new Set((entries || []).map((e) => e.id));
|
|
25802
|
+
}
|
|
25487
25803
|
const cardStorage = {
|
|
25488
25804
|
saveCard,
|
|
25489
25805
|
getCard,
|
|
@@ -25500,7 +25816,12 @@ const cardStorage = {
|
|
|
25500
25816
|
getProcessedResponseIds,
|
|
25501
25817
|
updateCardStatus,
|
|
25502
25818
|
findPendingCardsForPartner,
|
|
25503
|
-
cleanupOldEntries
|
|
25819
|
+
cleanupOldEntries,
|
|
25820
|
+
getLastDMFetchTime,
|
|
25821
|
+
setLastDMFetchTime,
|
|
25822
|
+
markDMProcessed,
|
|
25823
|
+
isDMProcessed,
|
|
25824
|
+
getProcessedDMIds
|
|
25504
25825
|
};
|
|
25505
25826
|
const cardStorage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
25506
25827
|
__proto__: null,
|
|
@@ -25515,11 +25836,16 @@ const cardStorage$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defin
|
|
|
25515
25836
|
getCardByPartner,
|
|
25516
25837
|
getDismissedRequestIds,
|
|
25517
25838
|
getDisplayableCards,
|
|
25839
|
+
getLastDMFetchTime,
|
|
25840
|
+
getProcessedDMIds,
|
|
25518
25841
|
getProcessedResponseIds,
|
|
25842
|
+
isDMProcessed,
|
|
25519
25843
|
isRequestDismissed,
|
|
25520
25844
|
isResponseProcessed,
|
|
25845
|
+
markDMProcessed,
|
|
25521
25846
|
markResponseProcessed,
|
|
25522
25847
|
saveCard,
|
|
25848
|
+
setLastDMFetchTime,
|
|
25523
25849
|
updateCardStatus
|
|
25524
25850
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
25525
25851
|
function createFederationRequest({
|
|
@@ -25604,17 +25930,22 @@ async function sendFederationResponse(client, privateKey, recipientPubKey, respo
|
|
|
25604
25930
|
}
|
|
25605
25931
|
}
|
|
25606
25932
|
function subscribeToFederationDMs(client, privateKey, publicKey, handlers, options = {}) {
|
|
25607
|
-
const { onRequest, onResponse } = handlers;
|
|
25933
|
+
const { onRequest, onResponse, onUpdate, onUpdateResponse } = handlers;
|
|
25608
25934
|
const { appname } = options;
|
|
25609
25935
|
let isActive = true;
|
|
25610
25936
|
const processedEventIds = /* @__PURE__ */ new Set();
|
|
25937
|
+
let processedDMIds = /* @__PURE__ */ new Set();
|
|
25611
25938
|
let processedResponseIds = /* @__PURE__ */ new Set();
|
|
25612
|
-
|
|
25939
|
+
let lastFetchTime = 0;
|
|
25940
|
+
const loadPersistedState = async () => {
|
|
25613
25941
|
if (appname && client?.client) {
|
|
25614
25942
|
try {
|
|
25943
|
+
processedDMIds = await getProcessedDMIds(client.client, appname);
|
|
25615
25944
|
processedResponseIds = await getProcessedResponseIds(client.client, appname);
|
|
25945
|
+
lastFetchTime = await getLastDMFetchTime(client.client, appname);
|
|
25946
|
+
console.log("[Handshake] Loaded persisted state - last fetch:", lastFetchTime, "processed DMs:", processedDMIds.size);
|
|
25616
25947
|
} catch (err) {
|
|
25617
|
-
console.warn("[Handshake] Could not load
|
|
25948
|
+
console.warn("[Handshake] Could not load persisted state:", err.message);
|
|
25618
25949
|
}
|
|
25619
25950
|
}
|
|
25620
25951
|
};
|
|
@@ -25622,6 +25953,9 @@ function subscribeToFederationDMs(client, privateKey, publicKey, handlers, optio
|
|
|
25622
25953
|
if (!isActive) return;
|
|
25623
25954
|
if (processedEventIds.has(event.id)) return;
|
|
25624
25955
|
processedEventIds.add(event.id);
|
|
25956
|
+
if (processedDMIds.has(event.id)) {
|
|
25957
|
+
return;
|
|
25958
|
+
}
|
|
25625
25959
|
if (event.kind !== 4) return;
|
|
25626
25960
|
const pTag = event.tags?.find((t) => t[0] === "p");
|
|
25627
25961
|
if (!pTag || pTag[1] !== publicKey) return;
|
|
@@ -25638,9 +25972,15 @@ function subscribeToFederationDMs(client, privateKey, publicKey, handlers, optio
|
|
|
25638
25972
|
const isDismissed = await isRequestDismissed(client.client, appname, payload.requestId);
|
|
25639
25973
|
if (isDismissed) {
|
|
25640
25974
|
console.log("[Handshake] Skipping dismissed request:", payload.requestId);
|
|
25975
|
+
await markDMProcessed(client.client, appname, event.id, "request");
|
|
25976
|
+
processedDMIds.add(event.id);
|
|
25641
25977
|
return;
|
|
25642
25978
|
}
|
|
25643
25979
|
}
|
|
25980
|
+
if (appname && client?.client) {
|
|
25981
|
+
await markDMProcessed(client.client, appname, event.id, "request");
|
|
25982
|
+
processedDMIds.add(event.id);
|
|
25983
|
+
}
|
|
25644
25984
|
console.log("[Handshake] Received federation request from:", event.pubkey.substring(0, 8) + "...");
|
|
25645
25985
|
onRequest?.(payload, event.pubkey);
|
|
25646
25986
|
} else if (payload.type === "federation_response" && payload.version === "1.0") {
|
|
@@ -25651,31 +25991,68 @@ function subscribeToFederationDMs(client, privateKey, publicKey, handlers, optio
|
|
|
25651
25991
|
}
|
|
25652
25992
|
if (appname && client?.client) {
|
|
25653
25993
|
await markResponseProcessed(client.client, appname, payload.requestId, event.pubkey);
|
|
25994
|
+
await markDMProcessed(client.client, appname, event.id, "response");
|
|
25654
25995
|
processedResponseIds.add(responseKey);
|
|
25996
|
+
processedDMIds.add(event.id);
|
|
25655
25997
|
}
|
|
25656
25998
|
console.log("[Handshake] Received federation response from:", event.pubkey.substring(0, 8) + "...");
|
|
25657
25999
|
onResponse?.(payload, event.pubkey);
|
|
26000
|
+
} else if (payload.type === "federation_update" && payload.version === "1.0") {
|
|
26001
|
+
if (appname && client?.client) {
|
|
26002
|
+
const isDismissed = await isRequestDismissed(client.client, appname, payload.updateId);
|
|
26003
|
+
if (isDismissed) {
|
|
26004
|
+
console.log("[Handshake] Skipping dismissed update:", payload.updateId);
|
|
26005
|
+
await markDMProcessed(client.client, appname, event.id, "update");
|
|
26006
|
+
processedDMIds.add(event.id);
|
|
26007
|
+
return;
|
|
26008
|
+
}
|
|
26009
|
+
}
|
|
26010
|
+
if (appname && client?.client) {
|
|
26011
|
+
await markDMProcessed(client.client, appname, event.id, "update");
|
|
26012
|
+
processedDMIds.add(event.id);
|
|
26013
|
+
}
|
|
26014
|
+
console.log("[Handshake] Received federation update from:", event.pubkey.substring(0, 8) + "...");
|
|
26015
|
+
onUpdate?.(payload, event.pubkey);
|
|
26016
|
+
} else if (payload.type === "federation_update_response" && payload.version === "1.0") {
|
|
26017
|
+
const responseKey = `update_${payload.updateId}_${event.pubkey}`;
|
|
26018
|
+
if (processedResponseIds.has(responseKey)) {
|
|
26019
|
+
console.log("[Handshake] Skipping already processed update response:", responseKey);
|
|
26020
|
+
return;
|
|
26021
|
+
}
|
|
26022
|
+
if (appname && client?.client) {
|
|
26023
|
+
await markResponseProcessed(client.client, appname, payload.updateId, event.pubkey);
|
|
26024
|
+
await markDMProcessed(client.client, appname, event.id, "update_response");
|
|
26025
|
+
processedResponseIds.add(responseKey);
|
|
26026
|
+
processedDMIds.add(event.id);
|
|
26027
|
+
}
|
|
26028
|
+
console.log("[Handshake] Received federation update response from:", event.pubkey.substring(0, 8) + "...");
|
|
26029
|
+
onUpdateResponse?.(payload, event.pubkey);
|
|
25658
26030
|
}
|
|
25659
26031
|
} catch (error) {
|
|
25660
26032
|
}
|
|
25661
26033
|
};
|
|
25662
26034
|
let subscription = null;
|
|
25663
26035
|
const startSubscription = async () => {
|
|
25664
|
-
await
|
|
26036
|
+
await loadPersistedState();
|
|
25665
26037
|
const nostrClient = client?.client;
|
|
25666
26038
|
if (!nostrClient?.subscribe) {
|
|
25667
26039
|
console.warn("[Handshake] No NostrClient subscribe method available");
|
|
25668
26040
|
return;
|
|
25669
26041
|
}
|
|
26042
|
+
const sinceTime = lastFetchTime || 0;
|
|
26043
|
+
console.log("[Handshake] Fetching DMs since:", sinceTime ? new Date(sinceTime * 1e3).toISOString() : "beginning of time");
|
|
25670
26044
|
const filter = {
|
|
25671
26045
|
kinds: [4],
|
|
25672
26046
|
"#p": [publicKey],
|
|
25673
|
-
since:
|
|
25674
|
-
// Last 24 hours
|
|
26047
|
+
since: sinceTime
|
|
25675
26048
|
};
|
|
25676
26049
|
try {
|
|
25677
26050
|
subscription = await nostrClient.subscribe(filter, handleEvent, {});
|
|
25678
26051
|
console.log("[Handshake] Federation DM subscription started");
|
|
26052
|
+
if (appname && client?.client) {
|
|
26053
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
26054
|
+
await setLastDMFetchTime(client.client, appname, now);
|
|
26055
|
+
}
|
|
25679
26056
|
} catch (error) {
|
|
25680
26057
|
console.error("[Handshake] Failed to subscribe:", error);
|
|
25681
26058
|
}
|
|
@@ -25768,6 +26145,15 @@ async function acceptFederationRequest$1(holosphere, privateKey, params) {
|
|
|
25768
26145
|
await storeInboundCapability(holosphere.client, holosphere.config.appName, senderPubKey, cap);
|
|
25769
26146
|
}
|
|
25770
26147
|
}
|
|
26148
|
+
if (request.senderHolonId) {
|
|
26149
|
+
await registerHolon(holosphere.client, holosphere.config.appName, request.senderHolonId, senderPubKey, {
|
|
26150
|
+
alias: request.senderHolonName
|
|
26151
|
+
});
|
|
26152
|
+
console.log("[Handshake] Registered partner holon:", {
|
|
26153
|
+
holonId: request.senderHolonId,
|
|
26154
|
+
pubKey: senderPubKey?.slice(0, 12) + "..."
|
|
26155
|
+
});
|
|
26156
|
+
}
|
|
25771
26157
|
}
|
|
25772
26158
|
await holosphere.federateHolon(holonId, senderPubKey, {
|
|
25773
26159
|
lensConfig,
|
|
@@ -25877,6 +26263,15 @@ async function processFederationResponse(holosphere, response, responderPubKey,
|
|
|
25877
26263
|
alias: response.responderHolonName,
|
|
25878
26264
|
addedVia: "handshake_accepted"
|
|
25879
26265
|
});
|
|
26266
|
+
if (response.responderHolonId) {
|
|
26267
|
+
await registerHolon(holosphere.client, holosphere.config.appName, response.responderHolonId, responderPubKey, {
|
|
26268
|
+
alias: response.responderHolonName
|
|
26269
|
+
});
|
|
26270
|
+
console.log("[Handshake] Registered partner holon from response:", {
|
|
26271
|
+
holonId: response.responderHolonId,
|
|
26272
|
+
pubKey: responderPubKey?.slice(0, 12) + "..."
|
|
26273
|
+
});
|
|
26274
|
+
}
|
|
25880
26275
|
}
|
|
25881
26276
|
const receivedHolograms = {};
|
|
25882
26277
|
const responderHolonId = response.responderHolonId;
|
|
@@ -25907,103 +26302,152 @@ function isFederationRequest(payload) {
|
|
|
25907
26302
|
function isFederationResponse(payload) {
|
|
25908
26303
|
return payload?.type === "federation_response" && payload?.version === "1.0";
|
|
25909
26304
|
}
|
|
25910
|
-
|
|
25911
|
-
|
|
25912
|
-
|
|
25913
|
-
|
|
25914
|
-
|
|
25915
|
-
|
|
25916
|
-
|
|
25917
|
-
|
|
25918
|
-
|
|
25919
|
-
|
|
25920
|
-
|
|
25921
|
-
|
|
25922
|
-
|
|
25923
|
-
|
|
25924
|
-
|
|
25925
|
-
|
|
25926
|
-
|
|
26305
|
+
function createFederationUpdate({
|
|
26306
|
+
senderHolonId,
|
|
26307
|
+
senderHolonName,
|
|
26308
|
+
senderPubKey,
|
|
26309
|
+
newLensConfig,
|
|
26310
|
+
message
|
|
26311
|
+
}) {
|
|
26312
|
+
return {
|
|
26313
|
+
type: "federation_update",
|
|
26314
|
+
version: "1.0",
|
|
26315
|
+
updateId: generateNonce(),
|
|
26316
|
+
timestamp: Date.now(),
|
|
26317
|
+
senderHolonId,
|
|
26318
|
+
senderHolonName,
|
|
26319
|
+
senderNpub: hexToNpub(senderPubKey),
|
|
26320
|
+
newLensConfig,
|
|
26321
|
+
message
|
|
26322
|
+
};
|
|
25927
26323
|
}
|
|
25928
|
-
|
|
25929
|
-
|
|
25930
|
-
|
|
25931
|
-
|
|
25932
|
-
|
|
25933
|
-
|
|
25934
|
-
|
|
25935
|
-
|
|
25936
|
-
|
|
25937
|
-
|
|
25938
|
-
|
|
25939
|
-
|
|
25940
|
-
createdAt: Date.now(),
|
|
25941
|
-
updatedAt: Date.now(),
|
|
25942
|
-
createdBy: client.publicKey
|
|
26324
|
+
function createFederationUpdateResponse({
|
|
26325
|
+
updateId,
|
|
26326
|
+
status,
|
|
26327
|
+
message
|
|
26328
|
+
}) {
|
|
26329
|
+
return {
|
|
26330
|
+
type: "federation_update_response",
|
|
26331
|
+
version: "1.0",
|
|
26332
|
+
updateId,
|
|
26333
|
+
timestamp: Date.now(),
|
|
26334
|
+
status,
|
|
26335
|
+
message
|
|
25943
26336
|
};
|
|
25944
|
-
return writeGlobal(client, appname, HOLON_REGISTRY_TABLE, entry);
|
|
25945
26337
|
}
|
|
25946
|
-
async function
|
|
25947
|
-
|
|
25948
|
-
|
|
25949
|
-
|
|
25950
|
-
|
|
25951
|
-
|
|
25952
|
-
|
|
26338
|
+
async function sendFederationUpdate(client, privateKey, recipientPubKey, update2) {
|
|
26339
|
+
try {
|
|
26340
|
+
const content = JSON.stringify(update2);
|
|
26341
|
+
const encrypted = encryptNIP44(privateKey, recipientPubKey, content);
|
|
26342
|
+
const event = createDMEvent(recipientPubKey, encrypted, privateKey);
|
|
26343
|
+
if (client?.publish) {
|
|
26344
|
+
await client.publish(event);
|
|
26345
|
+
console.log("[Handshake] Federation update sent to:", recipientPubKey.substring(0, 8) + "...");
|
|
26346
|
+
return true;
|
|
26347
|
+
}
|
|
26348
|
+
return false;
|
|
26349
|
+
} catch (error) {
|
|
26350
|
+
console.error("[Handshake] Failed to send federation update:", error);
|
|
26351
|
+
return false;
|
|
25953
26352
|
}
|
|
25954
|
-
return readGlobal(client, appname, HOLON_REGISTRY_TABLE, holonId);
|
|
25955
26353
|
}
|
|
25956
|
-
async function
|
|
25957
|
-
|
|
25958
|
-
|
|
26354
|
+
async function sendFederationUpdateResponse(client, privateKey, recipientPubKey, response) {
|
|
26355
|
+
try {
|
|
26356
|
+
const content = JSON.stringify(response);
|
|
26357
|
+
const encrypted = encryptNIP44(privateKey, recipientPubKey, content);
|
|
26358
|
+
const event = createDMEvent(recipientPubKey, encrypted, privateKey);
|
|
26359
|
+
if (client?.publish) {
|
|
26360
|
+
await client.publish(event);
|
|
26361
|
+
console.log("[Handshake] Federation update response sent to:", recipientPubKey.substring(0, 8) + "...");
|
|
26362
|
+
return true;
|
|
26363
|
+
}
|
|
26364
|
+
return false;
|
|
26365
|
+
} catch (error) {
|
|
26366
|
+
console.error("[Handshake] Failed to send federation update response:", error);
|
|
26367
|
+
return false;
|
|
25959
26368
|
}
|
|
25960
|
-
const entry = await lookupHolon(client, appname, holonId);
|
|
25961
|
-
return entry?.publicKey || null;
|
|
25962
26369
|
}
|
|
25963
|
-
async function
|
|
25964
|
-
|
|
25965
|
-
|
|
26370
|
+
async function requestFederationUpdate(holosphere, privateKey, params) {
|
|
26371
|
+
const { partnerPubKey, holonId, holonName, newLensConfig, message } = params;
|
|
26372
|
+
try {
|
|
26373
|
+
const senderPubKey = getPublicKey(privateKey);
|
|
26374
|
+
const update2 = createFederationUpdate({
|
|
26375
|
+
senderHolonId: holonId,
|
|
26376
|
+
senderHolonName: holonName,
|
|
26377
|
+
senderPubKey,
|
|
26378
|
+
newLensConfig,
|
|
26379
|
+
message
|
|
26380
|
+
});
|
|
26381
|
+
const sent = await sendFederationUpdate(holosphere.client, privateKey, partnerPubKey, update2);
|
|
26382
|
+
if (sent) {
|
|
26383
|
+
return { success: true, updateId: update2.updateId };
|
|
26384
|
+
}
|
|
26385
|
+
return { success: false, error: "Failed to send update DM" };
|
|
26386
|
+
} catch (error) {
|
|
26387
|
+
return { success: false, error: error.message };
|
|
25966
26388
|
}
|
|
25967
|
-
const entry = {
|
|
25968
|
-
id: holonId,
|
|
25969
|
-
holonId,
|
|
25970
|
-
publicKey: null,
|
|
25971
|
-
_deleted: true,
|
|
25972
|
-
deletedAt: Date.now(),
|
|
25973
|
-
deletedBy: client.publicKey
|
|
25974
|
-
};
|
|
25975
|
-
return writeGlobal(client, appname, HOLON_REGISTRY_TABLE, entry);
|
|
25976
26389
|
}
|
|
25977
|
-
async function
|
|
25978
|
-
const
|
|
25979
|
-
|
|
25980
|
-
|
|
26390
|
+
async function acceptFederationUpdate(holosphere, privateKey, params) {
|
|
26391
|
+
const { updateId, senderPubKey, holonId, newLensConfig, message } = params;
|
|
26392
|
+
try {
|
|
26393
|
+
if (holosphere.federateHolon) {
|
|
26394
|
+
await holosphere.federateHolon(holonId, senderPubKey, {
|
|
26395
|
+
lensConfig: newLensConfig
|
|
26396
|
+
});
|
|
26397
|
+
}
|
|
26398
|
+
const response = createFederationUpdateResponse({
|
|
26399
|
+
updateId,
|
|
26400
|
+
status: "accepted",
|
|
26401
|
+
message
|
|
26402
|
+
});
|
|
26403
|
+
const sent = await sendFederationUpdateResponse(holosphere.client, privateKey, senderPubKey, response);
|
|
26404
|
+
return { success: sent, error: sent ? void 0 : "Failed to send response" };
|
|
26405
|
+
} catch (error) {
|
|
26406
|
+
return { success: false, error: error.message };
|
|
25981
26407
|
}
|
|
25982
|
-
const entry = {
|
|
25983
|
-
...existing,
|
|
25984
|
-
...updates,
|
|
25985
|
-
updatedAt: Date.now()
|
|
25986
|
-
};
|
|
25987
|
-
return writeGlobal(client, appname, HOLON_REGISTRY_TABLE, entry);
|
|
25988
26408
|
}
|
|
25989
|
-
async function
|
|
25990
|
-
const
|
|
25991
|
-
|
|
26409
|
+
async function rejectFederationUpdate(holosphere, privateKey, params) {
|
|
26410
|
+
const { updateId, senderPubKey, message } = params;
|
|
26411
|
+
try {
|
|
26412
|
+
const response = createFederationUpdateResponse({
|
|
26413
|
+
updateId,
|
|
26414
|
+
status: "rejected",
|
|
26415
|
+
message
|
|
26416
|
+
});
|
|
26417
|
+
const sent = await sendFederationUpdateResponse(holosphere.client, privateKey, senderPubKey, response);
|
|
26418
|
+
return { success: sent, error: sent ? void 0 : "Failed to send response" };
|
|
26419
|
+
} catch (error) {
|
|
26420
|
+
return { success: false, error: error.message };
|
|
26421
|
+
}
|
|
25992
26422
|
}
|
|
25993
|
-
|
|
25994
|
-
|
|
25995
|
-
return all.filter((e) => e.publicKey === publicKey);
|
|
26423
|
+
function isFederationUpdate(payload) {
|
|
26424
|
+
return payload?.type === "federation_update" && payload?.version === "1.0";
|
|
25996
26425
|
}
|
|
25997
|
-
|
|
26426
|
+
function isFederationUpdateResponse(payload) {
|
|
26427
|
+
return payload?.type === "federation_update_response" && payload?.version === "1.0";
|
|
26428
|
+
}
|
|
26429
|
+
const handshake = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
25998
26430
|
__proto__: null,
|
|
25999
|
-
|
|
26000
|
-
|
|
26001
|
-
|
|
26002
|
-
|
|
26003
|
-
|
|
26004
|
-
|
|
26005
|
-
|
|
26006
|
-
|
|
26431
|
+
acceptFederationRequest: acceptFederationRequest$1,
|
|
26432
|
+
acceptFederationUpdate,
|
|
26433
|
+
createFederationRequest,
|
|
26434
|
+
createFederationResponse,
|
|
26435
|
+
createFederationUpdate,
|
|
26436
|
+
createFederationUpdateResponse,
|
|
26437
|
+
initiateFederationHandshake,
|
|
26438
|
+
isFederationRequest,
|
|
26439
|
+
isFederationResponse,
|
|
26440
|
+
isFederationUpdate,
|
|
26441
|
+
isFederationUpdateResponse,
|
|
26442
|
+
processFederationResponse,
|
|
26443
|
+
rejectFederationRequest,
|
|
26444
|
+
rejectFederationUpdate,
|
|
26445
|
+
requestFederationUpdate,
|
|
26446
|
+
sendFederationRequest: sendFederationRequest$1,
|
|
26447
|
+
sendFederationResponse,
|
|
26448
|
+
sendFederationUpdate,
|
|
26449
|
+
sendFederationUpdateResponse,
|
|
26450
|
+
subscribeToFederationDMs
|
|
26007
26451
|
}, Symbol.toStringTag, { value: "Module" }));
|
|
26008
26452
|
function validateNostrEvent(event, partial = true, throwOnError = false) {
|
|
26009
26453
|
if (!event || typeof event !== "object") {
|
|
@@ -36395,7 +36839,7 @@ class ChainManager {
|
|
|
36395
36839
|
*/
|
|
36396
36840
|
async _loadEthers() {
|
|
36397
36841
|
if (!this.ethers) {
|
|
36398
|
-
const ethersModule = await import("./index-
|
|
36842
|
+
const ethersModule = await import("./index-CoAjtqsD.js");
|
|
36399
36843
|
this.ethers = ethersModule;
|
|
36400
36844
|
}
|
|
36401
36845
|
return this.ethers;
|
|
@@ -45186,7 +45630,7 @@ class ContractDeployer {
|
|
|
45186
45630
|
*/
|
|
45187
45631
|
async _loadEthers() {
|
|
45188
45632
|
if (!this.ethers) {
|
|
45189
|
-
this.ethers = await import("./index-
|
|
45633
|
+
this.ethers = await import("./index-CoAjtqsD.js");
|
|
45190
45634
|
}
|
|
45191
45635
|
return this.ethers;
|
|
45192
45636
|
}
|
|
@@ -45572,7 +46016,7 @@ class ContractOperations {
|
|
|
45572
46016
|
*/
|
|
45573
46017
|
async _loadEthers() {
|
|
45574
46018
|
if (!this.ethers) {
|
|
45575
|
-
this.ethers = await import("./index-
|
|
46019
|
+
this.ethers = await import("./index-CoAjtqsD.js");
|
|
45576
46020
|
}
|
|
45577
46021
|
return this.ethers;
|
|
45578
46022
|
}
|
|
@@ -57524,6 +57968,7 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
57524
57968
|
* @param {boolean} [options.autoPropagate=true] - Whether to propagate to federated holons
|
|
57525
57969
|
* @param {Object} [options.propagationOptions] - Options for propagation
|
|
57526
57970
|
* @param {boolean} [options.blocking=false] - If true, wait for relay confirmation before returning
|
|
57971
|
+
* @param {string} [options.signingKey] - Private key to sign with (hex format). If not provided, uses holosphere's default key.
|
|
57527
57972
|
* @returns {Promise<boolean>} True if write succeeded (or queued for optimistic writes)
|
|
57528
57973
|
* @throws {ValidationError} If holonId, lensName, or data is invalid
|
|
57529
57974
|
* @throws {AuthorizationError} If capability token is invalid
|
|
@@ -57605,7 +58050,8 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
57605
58050
|
this._log("DEBUG", "🔗 Syncing hologram write", { path, target: existingData.target });
|
|
57606
58051
|
return this._syncHologramWrite(existingData, data, path, lensName, options);
|
|
57607
58052
|
}
|
|
57608
|
-
|
|
58053
|
+
const writeOptions = options.signingKey ? { signingKey: options.signingKey } : {};
|
|
58054
|
+
await write(this.client, path, data, writeOptions);
|
|
57609
58055
|
const endTime = Date.now();
|
|
57610
58056
|
const duration = endTime - startTime;
|
|
57611
58057
|
this._metrics.writes++;
|
|
@@ -57826,6 +58272,26 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
57826
58272
|
if (!lensName) {
|
|
57827
58273
|
throw new ValidationError$1("ValidationError: lensName must be a non-empty string");
|
|
57828
58274
|
}
|
|
58275
|
+
if (dataId) {
|
|
58276
|
+
const earlyPath = buildPath(this.config.appName, holonId, lensName, dataId);
|
|
58277
|
+
if (this._deleteCache.has(earlyPath)) {
|
|
58278
|
+
this._log("DEBUG", "🗑️ EARLY CACHE: Deleted item", { path: earlyPath });
|
|
58279
|
+
return null;
|
|
58280
|
+
}
|
|
58281
|
+
const cached = this._writeCache.get(earlyPath);
|
|
58282
|
+
if (cached) {
|
|
58283
|
+
const cacheAge = Date.now() - cached.timestamp;
|
|
58284
|
+
this._log("DEBUG", "⚡ EARLY CACHE HIT: Write cache", {
|
|
58285
|
+
path: earlyPath,
|
|
58286
|
+
cacheAge: `${cacheAge}ms`
|
|
58287
|
+
});
|
|
58288
|
+
const { resolveHolograms: resolveHolograms2 = true } = options;
|
|
58289
|
+
if (resolveHolograms2 && cached.data) {
|
|
58290
|
+
return this._resolveHolograms(cached.data);
|
|
58291
|
+
}
|
|
58292
|
+
return cached.data;
|
|
58293
|
+
}
|
|
58294
|
+
}
|
|
57829
58295
|
const targetPubkey = await this._resolveHolonToPubkey(holonId);
|
|
57830
58296
|
const isOtherAuthor = targetPubkey && targetPubkey !== this.client.publicKey;
|
|
57831
58297
|
let readOptions = {};
|
|
@@ -57839,11 +58305,27 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
57839
58305
|
readOptions.authors = [targetPubkey];
|
|
57840
58306
|
}
|
|
57841
58307
|
} else if (isOtherAuthor) {
|
|
58308
|
+
this._log("DEBUG", "🔍 Looking up capability for federated author", {
|
|
58309
|
+
holonId,
|
|
58310
|
+
lensName,
|
|
58311
|
+
dataId: dataId || "*",
|
|
58312
|
+
targetPubkey: targetPubkey?.slice(0, 12) + "...",
|
|
58313
|
+
myPubkey: this.client?.publicKey?.slice(0, 12) + "..."
|
|
58314
|
+
});
|
|
57842
58315
|
const capability = await this._getCapabilityForAuthor(targetPubkey, { holonId, lensName, dataId });
|
|
57843
58316
|
if (!capability) {
|
|
57844
|
-
this._log("
|
|
58317
|
+
this._log("WARN", "❌ No capability found for federated author - returning empty", {
|
|
58318
|
+
holonId,
|
|
58319
|
+
lensName,
|
|
58320
|
+
targetPubkey: targetPubkey?.slice(0, 12) + "..."
|
|
58321
|
+
});
|
|
57845
58322
|
return dataId ? null : [];
|
|
57846
58323
|
}
|
|
58324
|
+
this._log("DEBUG", "✅ Capability found for federated author", {
|
|
58325
|
+
holonId,
|
|
58326
|
+
lensName,
|
|
58327
|
+
targetPubkey: targetPubkey?.slice(0, 12) + "..."
|
|
58328
|
+
});
|
|
57847
58329
|
readOptions.authors = [targetPubkey];
|
|
57848
58330
|
}
|
|
57849
58331
|
if (!isOtherAuthor) {
|
|
@@ -57875,7 +58357,7 @@ class HoloSphereBase extends HoloSphere$1 {
|
|
|
57875
58357
|
});
|
|
57876
58358
|
result = null;
|
|
57877
58359
|
} else {
|
|
57878
|
-
const cached =
|
|
58360
|
+
const cached = this._writeCache.get(path);
|
|
57879
58361
|
if (cached) {
|
|
57880
58362
|
const cacheAge = Date.now() - cached.timestamp;
|
|
57881
58363
|
this._log("DEBUG", "⚡ CACHE HIT: Write cache", {
|
|
@@ -59378,4 +59860,4 @@ export {
|
|
|
59378
59860
|
concatBytes as y,
|
|
59379
59861
|
dataLength as z
|
|
59380
59862
|
};
|
|
59381
|
-
//# sourceMappingURL=index-
|
|
59863
|
+
//# sourceMappingURL=index-BN_uoxQK.js.map
|