holosphere 2.0.0-alpha10 → 2.0.0-alpha12
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-D2OG2idw.js → 2019-DQdDE6DG.js} +2 -2
- package/dist/{2019-D2OG2idw.js.map → 2019-DQdDE6DG.js.map} +1 -1
- package/dist/{2019-EION3wKo.cjs → 2019-Ew-DTDlI.cjs} +2 -2
- package/dist/{2019-EION3wKo.cjs.map → 2019-Ew-DTDlI.cjs.map} +1 -1
- package/dist/{browser-BSniCNqO.js → browser-CckFyRI9.js} +2 -2
- package/dist/{browser-BSniCNqO.js.map → browser-CckFyRI9.js.map} +1 -1
- package/dist/browser-D2qtVhH5.cjs +2 -0
- package/dist/{browser-Cq59Ij19.cjs.map → browser-D2qtVhH5.cjs.map} +1 -1
- package/dist/cjs/holosphere.cjs +1 -1
- package/dist/esm/holosphere.js +67 -50
- package/dist/index-9sqetkAn.cjs +29 -0
- package/dist/index-9sqetkAn.cjs.map +1 -0
- package/dist/index-C0ITDyFo.cjs +13 -0
- package/dist/index-C0ITDyFo.cjs.map +1 -0
- package/dist/{index-DeZ1xz_s.js → index-DrYM1LOY.js} +2 -2
- package/dist/{index-DeZ1xz_s.js.map → index-DrYM1LOY.js.map} +1 -1
- package/dist/{index-DJXftyvB.js → index-TDDyakLc.js} +20345 -805
- package/dist/index-TDDyakLc.js.map +1 -0
- package/dist/{index-DDGt_V9o.cjs → index-kyf1sjaC.cjs} +3 -3
- package/dist/{index-DDGt_V9o.cjs.map → index-kyf1sjaC.cjs.map} +1 -1
- package/dist/index-lbSQUoRz.js +11663 -0
- package/dist/index-lbSQUoRz.js.map +1 -0
- package/dist/{indexeddb-storage-BFt6hMeF.js → indexeddb-storage-CXhjqwhA.js} +2 -2
- package/dist/{indexeddb-storage-BFt6hMeF.js.map → indexeddb-storage-CXhjqwhA.js.map} +1 -1
- package/dist/{indexeddb-storage-BK5tv4Sh.cjs → indexeddb-storage-DFESDYIj.cjs} +2 -2
- package/dist/{indexeddb-storage-BK5tv4Sh.cjs.map → indexeddb-storage-DFESDYIj.cjs.map} +1 -1
- package/dist/{memory-storage-Dao7jfYG.cjs → memory-storage-D1tc1bjk.cjs} +2 -2
- package/dist/{memory-storage-Dao7jfYG.cjs.map → memory-storage-D1tc1bjk.cjs.map} +1 -1
- package/dist/{memory-storage-C9HuoL2E.js → memory-storage-DkewsdcM.js} +2 -2
- package/dist/{memory-storage-C9HuoL2E.js.map → memory-storage-DkewsdcM.js.map} +1 -1
- package/docs/FEDERATION.md +474 -0
- package/package.json +3 -1
- package/src/crypto/nostr-utils.js +7 -0
- package/src/crypto/secp256k1.js +46 -29
- package/src/federation/capabilities.js +162 -0
- package/src/federation/card-storage.js +304 -0
- package/src/federation/handshake.js +204 -7
- package/src/federation/hologram.js +167 -58
- package/src/federation/holon-registry.js +166 -0
- package/src/federation/index.js +68 -0
- package/src/federation/registry.js +110 -2
- package/src/federation/request-card.js +373 -0
- package/src/hierarchical/upcast.js +19 -3
- package/src/index.js +224 -95
- package/src/lib/federation-methods.js +527 -5
- package/src/storage/nostr-async.js +2 -2
- package/src/storage/nostr-client.js +370 -155
- package/src/storage/nostr-wrapper.js +1 -1
- package/dist/_commonjsHelpers-C37NGDzP.cjs +0 -2
- package/dist/_commonjsHelpers-C37NGDzP.cjs.map +0 -1
- package/dist/_commonjsHelpers-CUmg6egw.js +0 -7
- package/dist/_commonjsHelpers-CUmg6egw.js.map +0 -1
- package/dist/browser-Cq59Ij19.cjs +0 -2
- package/dist/cdn/holosphere.min.js +0 -55
- package/dist/cdn/holosphere.min.js.map +0 -1
- package/dist/index-DJXftyvB.js.map +0 -1
- package/dist/index-DMbdcMtK.cjs +0 -18
- package/dist/index-DMbdcMtK.cjs.map +0 -1
- package/dist/secp256k1-BbKzbLtD.cjs +0 -12
- package/dist/secp256k1-BbKzbLtD.cjs.map +0 -1
- package/dist/secp256k1-CreY7Pcl.js +0 -1890
- package/dist/secp256k1-CreY7Pcl.js.map +0 -1
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Federation Request Card Configuration
|
|
3
|
+
*
|
|
4
|
+
* Provides a card-based configuration system for federation requests.
|
|
5
|
+
* After inputting a public key, displays a card with all available lenses
|
|
6
|
+
* that can be configured for the federation request.
|
|
7
|
+
*
|
|
8
|
+
* @module federation/request-card
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { issueCapabilitiesForLenses } from './capabilities.js';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @typedef {Object} LensConfig
|
|
15
|
+
* @property {string} name - Lens name
|
|
16
|
+
* @property {boolean} enabled - Whether lens is enabled for federation
|
|
17
|
+
* @property {string} direction - 'inbound', 'outbound', or 'bidirectional'
|
|
18
|
+
* @property {string[]} permissions - Permissions to grant ('read', 'write')
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @typedef {Object} FederationCardConfig
|
|
23
|
+
* @property {string} partnerPubKey - Partner's public key
|
|
24
|
+
* @property {string} partnerName - Partner's display name (optional)
|
|
25
|
+
* @property {string} holonId - Local holon ID
|
|
26
|
+
* @property {string} holonName - Local holon display name
|
|
27
|
+
* @property {LensConfig[]} lenses - Lens configurations
|
|
28
|
+
* @property {string} message - Optional message to partner
|
|
29
|
+
* @property {number} createdAt - Card creation timestamp
|
|
30
|
+
* @property {string} status - 'pending', 'sent', 'accepted', 'rejected', 'dismissed'
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @typedef {Object} CardDisplayOptions
|
|
35
|
+
* @property {number} initialLensCount - Number of lenses to show initially (default: 3)
|
|
36
|
+
* @property {boolean} expanded - Whether card is expanded to show all lenses
|
|
37
|
+
* @property {boolean} showPermissions - Whether to show permission toggles
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
// Default number of lenses to show before "Show more" button
|
|
41
|
+
const DEFAULT_INITIAL_LENS_COUNT = 3;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Create a federation request card configuration
|
|
45
|
+
* @param {Object} params - Card parameters
|
|
46
|
+
* @param {string} params.partnerPubKey - Partner's public key
|
|
47
|
+
* @param {string} params.partnerName - Partner's display name
|
|
48
|
+
* @param {string} params.holonId - Local holon ID
|
|
49
|
+
* @param {string} params.holonName - Local holon display name
|
|
50
|
+
* @param {string[]} params.availableLenses - All available lens names
|
|
51
|
+
* @param {Object} params.defaultConfig - Default lens configuration
|
|
52
|
+
* @returns {FederationCardConfig} Card configuration
|
|
53
|
+
*/
|
|
54
|
+
export function createFederationCard({
|
|
55
|
+
partnerPubKey,
|
|
56
|
+
partnerName = null,
|
|
57
|
+
holonId,
|
|
58
|
+
holonName,
|
|
59
|
+
availableLenses = [],
|
|
60
|
+
defaultConfig = {},
|
|
61
|
+
}) {
|
|
62
|
+
const {
|
|
63
|
+
defaultDirection = 'bidirectional',
|
|
64
|
+
defaultPermissions = ['read'],
|
|
65
|
+
enabledByDefault = true,
|
|
66
|
+
} = defaultConfig;
|
|
67
|
+
|
|
68
|
+
// Create lens configurations for all available lenses
|
|
69
|
+
const lenses = availableLenses.map(name => ({
|
|
70
|
+
name,
|
|
71
|
+
enabled: enabledByDefault,
|
|
72
|
+
direction: defaultDirection,
|
|
73
|
+
permissions: [...defaultPermissions],
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
id: `fedcard_${partnerPubKey.substring(0, 8)}_${Date.now()}`,
|
|
78
|
+
partnerPubKey,
|
|
79
|
+
partnerName,
|
|
80
|
+
holonId,
|
|
81
|
+
holonName,
|
|
82
|
+
lenses,
|
|
83
|
+
message: '',
|
|
84
|
+
createdAt: Date.now(),
|
|
85
|
+
status: 'pending',
|
|
86
|
+
expanded: false,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Update a lens configuration in a card
|
|
92
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
93
|
+
* @param {string} lensName - Lens name to update
|
|
94
|
+
* @param {Partial<LensConfig>} updates - Updates to apply
|
|
95
|
+
* @returns {FederationCardConfig} Updated card
|
|
96
|
+
*/
|
|
97
|
+
export function updateLensConfig(card, lensName, updates) {
|
|
98
|
+
const lensIndex = card.lenses.findIndex(l => l.name === lensName);
|
|
99
|
+
if (lensIndex === -1) return card;
|
|
100
|
+
|
|
101
|
+
const updatedLenses = [...card.lenses];
|
|
102
|
+
updatedLenses[lensIndex] = {
|
|
103
|
+
...updatedLenses[lensIndex],
|
|
104
|
+
...updates,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
return {
|
|
108
|
+
...card,
|
|
109
|
+
lenses: updatedLenses,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Toggle a lens enabled/disabled state
|
|
115
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
116
|
+
* @param {string} lensName - Lens name to toggle
|
|
117
|
+
* @returns {FederationCardConfig} Updated card
|
|
118
|
+
*/
|
|
119
|
+
export function toggleLens(card, lensName) {
|
|
120
|
+
const lens = card.lenses.find(l => l.name === lensName);
|
|
121
|
+
if (!lens) return card;
|
|
122
|
+
|
|
123
|
+
return updateLensConfig(card, lensName, { enabled: !lens.enabled });
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Enable all lenses in a card
|
|
128
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
129
|
+
* @returns {FederationCardConfig} Updated card
|
|
130
|
+
*/
|
|
131
|
+
export function enableAllLenses(card) {
|
|
132
|
+
return {
|
|
133
|
+
...card,
|
|
134
|
+
lenses: card.lenses.map(l => ({ ...l, enabled: true })),
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Disable all lenses in a card
|
|
140
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
141
|
+
* @returns {FederationCardConfig} Updated card
|
|
142
|
+
*/
|
|
143
|
+
export function disableAllLenses(card) {
|
|
144
|
+
return {
|
|
145
|
+
...card,
|
|
146
|
+
lenses: card.lenses.map(l => ({ ...l, enabled: false })),
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Toggle card expansion to show all lenses
|
|
152
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
153
|
+
* @returns {FederationCardConfig} Updated card
|
|
154
|
+
*/
|
|
155
|
+
export function toggleCardExpansion(card) {
|
|
156
|
+
return {
|
|
157
|
+
...card,
|
|
158
|
+
expanded: !card.expanded,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get lenses to display based on expansion state
|
|
164
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
165
|
+
* @param {number} initialCount - Number of lenses to show when collapsed
|
|
166
|
+
* @returns {Object} { visibleLenses, hiddenCount, isExpanded }
|
|
167
|
+
*/
|
|
168
|
+
export function getVisibleLenses(card, initialCount = DEFAULT_INITIAL_LENS_COUNT) {
|
|
169
|
+
const allLenses = card.lenses;
|
|
170
|
+
const isExpanded = card.expanded;
|
|
171
|
+
|
|
172
|
+
if (isExpanded || allLenses.length <= initialCount) {
|
|
173
|
+
return {
|
|
174
|
+
visibleLenses: allLenses,
|
|
175
|
+
hiddenCount: 0,
|
|
176
|
+
isExpanded: true,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
visibleLenses: allLenses.slice(0, initialCount),
|
|
182
|
+
hiddenCount: allLenses.length - initialCount,
|
|
183
|
+
isExpanded: false,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Get enabled lenses from a card
|
|
189
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
190
|
+
* @returns {LensConfig[]} Enabled lenses
|
|
191
|
+
*/
|
|
192
|
+
export function getEnabledLenses(card) {
|
|
193
|
+
return card.lenses.filter(l => l.enabled);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get lens configuration for handshake (inbound/outbound arrays)
|
|
198
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
199
|
+
* @returns {Object} { inbound: string[], outbound: string[] }
|
|
200
|
+
*/
|
|
201
|
+
export function getLensConfigForHandshake(card) {
|
|
202
|
+
const inbound = [];
|
|
203
|
+
const outbound = [];
|
|
204
|
+
|
|
205
|
+
for (const lens of card.lenses) {
|
|
206
|
+
if (!lens.enabled) continue;
|
|
207
|
+
|
|
208
|
+
if (lens.direction === 'inbound' || lens.direction === 'bidirectional') {
|
|
209
|
+
inbound.push(lens.name);
|
|
210
|
+
}
|
|
211
|
+
if (lens.direction === 'outbound' || lens.direction === 'bidirectional') {
|
|
212
|
+
outbound.push(lens.name);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return { inbound, outbound };
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Update card status
|
|
221
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
222
|
+
* @param {string} status - New status
|
|
223
|
+
* @returns {FederationCardConfig} Updated card
|
|
224
|
+
*/
|
|
225
|
+
export function updateCardStatus(card, status) {
|
|
226
|
+
return {
|
|
227
|
+
...card,
|
|
228
|
+
status,
|
|
229
|
+
updatedAt: Date.now(),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/**
|
|
234
|
+
* Dismiss a card (mark as dismissed so it doesn't reappear)
|
|
235
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
236
|
+
* @returns {FederationCardConfig} Updated card with dismissed status
|
|
237
|
+
*/
|
|
238
|
+
export function dismissCard(card) {
|
|
239
|
+
return updateCardStatus(card, 'dismissed');
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Check if a card should be displayed
|
|
244
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
245
|
+
* @returns {boolean} True if card should be displayed
|
|
246
|
+
*/
|
|
247
|
+
export function shouldDisplayCard(card) {
|
|
248
|
+
return card.status !== 'dismissed' && card.status !== 'rejected';
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Convert card configuration to handshake request params
|
|
253
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
254
|
+
* @returns {Object} Params for initiateFederationHandshake
|
|
255
|
+
*/
|
|
256
|
+
export function cardToHandshakeParams(card) {
|
|
257
|
+
const lensConfig = getLensConfigForHandshake(card);
|
|
258
|
+
|
|
259
|
+
return {
|
|
260
|
+
partnerPubKey: card.partnerPubKey,
|
|
261
|
+
holonId: card.holonId,
|
|
262
|
+
holonName: card.holonName,
|
|
263
|
+
lensConfig,
|
|
264
|
+
message: card.message,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Generate capabilities for a card's outbound lenses
|
|
270
|
+
* @param {Object} client - NostrClient instance
|
|
271
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
272
|
+
* @returns {Promise<Object[]>} Array of capability info objects
|
|
273
|
+
*/
|
|
274
|
+
export async function generateCapabilitiesForCard(client, card) {
|
|
275
|
+
const { outbound } = getLensConfigForHandshake(card);
|
|
276
|
+
|
|
277
|
+
if (outbound.length === 0) {
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return issueCapabilitiesForLenses(
|
|
282
|
+
client,
|
|
283
|
+
card.holonId,
|
|
284
|
+
outbound,
|
|
285
|
+
card.partnerPubKey,
|
|
286
|
+
{ permissions: ['read'] }
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Render card as a simple text representation (for CLI/logs)
|
|
292
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
293
|
+
* @param {CardDisplayOptions} options - Display options
|
|
294
|
+
* @returns {string} Text representation
|
|
295
|
+
*/
|
|
296
|
+
export function renderCardAsText(card, options = {}) {
|
|
297
|
+
const { initialLensCount = DEFAULT_INITIAL_LENS_COUNT } = options;
|
|
298
|
+
const { visibleLenses, hiddenCount, isExpanded } = getVisibleLenses(card, initialLensCount);
|
|
299
|
+
const { inbound, outbound } = getLensConfigForHandshake(card);
|
|
300
|
+
|
|
301
|
+
const lines = [
|
|
302
|
+
`┌─────────────────────────────────────────────────────┐`,
|
|
303
|
+
`│ Federation Request │`,
|
|
304
|
+
`├─────────────────────────────────────────────────────┤`,
|
|
305
|
+
`│ Partner: ${(card.partnerName || card.partnerPubKey.substring(0, 16) + '...').padEnd(40)}│`,
|
|
306
|
+
`│ Status: ${card.status.padEnd(40)}│`,
|
|
307
|
+
`├─────────────────────────────────────────────────────┤`,
|
|
308
|
+
`│ Lenses: │`,
|
|
309
|
+
];
|
|
310
|
+
|
|
311
|
+
for (const lens of visibleLenses) {
|
|
312
|
+
const status = lens.enabled ? '✓' : '○';
|
|
313
|
+
const dir = lens.direction === 'bidirectional' ? '↔' :
|
|
314
|
+
lens.direction === 'inbound' ? '←' : '→';
|
|
315
|
+
lines.push(`│ ${status} ${lens.name.padEnd(20)} ${dir.padEnd(22)}│`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (hiddenCount > 0) {
|
|
319
|
+
lines.push(`│ ... and ${hiddenCount} more lenses (click to expand) │`);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
lines.push(`├─────────────────────────────────────────────────────┤`);
|
|
323
|
+
lines.push(`│ Sharing: ${outbound.length} lenses | Receiving: ${inbound.length} lenses`.padEnd(52) + `│`);
|
|
324
|
+
lines.push(`└─────────────────────────────────────────────────────┘`);
|
|
325
|
+
|
|
326
|
+
return lines.join('\n');
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Serialize card for storage
|
|
331
|
+
* @param {FederationCardConfig} card - Card configuration
|
|
332
|
+
* @returns {Object} Serialized card
|
|
333
|
+
*/
|
|
334
|
+
export function serializeCard(card) {
|
|
335
|
+
return {
|
|
336
|
+
...card,
|
|
337
|
+
serializedAt: Date.now(),
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* Deserialize card from storage
|
|
343
|
+
* @param {Object} data - Serialized card data
|
|
344
|
+
* @returns {FederationCardConfig} Card configuration
|
|
345
|
+
*/
|
|
346
|
+
export function deserializeCard(data) {
|
|
347
|
+
return {
|
|
348
|
+
...data,
|
|
349
|
+
expanded: data.expanded || false,
|
|
350
|
+
lenses: data.lenses || [],
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export default {
|
|
355
|
+
createFederationCard,
|
|
356
|
+
updateLensConfig,
|
|
357
|
+
toggleLens,
|
|
358
|
+
enableAllLenses,
|
|
359
|
+
disableAllLenses,
|
|
360
|
+
toggleCardExpansion,
|
|
361
|
+
getVisibleLenses,
|
|
362
|
+
getEnabledLenses,
|
|
363
|
+
getLensConfigForHandshake,
|
|
364
|
+
updateCardStatus,
|
|
365
|
+
dismissCard,
|
|
366
|
+
shouldDisplayCard,
|
|
367
|
+
cardToHandshakeParams,
|
|
368
|
+
generateCapabilitiesForCard,
|
|
369
|
+
renderCardAsText,
|
|
370
|
+
serializeCard,
|
|
371
|
+
deserializeCard,
|
|
372
|
+
DEFAULT_INITIAL_LENS_COUNT,
|
|
373
|
+
};
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Hierarchical aggregation (upcast) operations for propagating data to parent holons.
|
|
3
3
|
* Implements upcast operations (FR-025 to FR-027) for H3-based geographic hierarchies.
|
|
4
|
+
*
|
|
5
|
+
* UNIFIED MODEL: Uses createHologramWithCapability for consistent capability-based federation.
|
|
6
|
+
*
|
|
4
7
|
* @module hierarchical/upcast
|
|
5
8
|
*/
|
|
6
9
|
|
|
7
10
|
import { getParents, isValidH3 } from '../spatial/h3-operations.js';
|
|
8
|
-
import {
|
|
11
|
+
import { createHologramWithCapability } from '../federation/hologram.js';
|
|
9
12
|
import { write } from '../storage/unified-storage.js';
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -50,6 +53,7 @@ export async function upcast(hs, holonId, lensName, dataId, options = {}) {
|
|
|
50
53
|
|
|
51
54
|
/**
|
|
52
55
|
* Propagate data to a parent holon by creating a hologram reference.
|
|
56
|
+
* UNIFIED MODEL: Uses createHologramWithCapability for consistent capability-based federation.
|
|
53
57
|
* @private
|
|
54
58
|
* @param {Object} client - Nostr client instance
|
|
55
59
|
* @param {string} appname - Application name
|
|
@@ -69,8 +73,20 @@ async function propagateToParent(
|
|
|
69
73
|
dataId,
|
|
70
74
|
operation
|
|
71
75
|
) {
|
|
72
|
-
// Create hologram
|
|
73
|
-
const hologram =
|
|
76
|
+
// UNIFIED MODEL: Create hologram with capability
|
|
77
|
+
const hologram = await createHologramWithCapability(
|
|
78
|
+
client,
|
|
79
|
+
sourceHolon,
|
|
80
|
+
parentHolon,
|
|
81
|
+
lensName,
|
|
82
|
+
dataId,
|
|
83
|
+
appname,
|
|
84
|
+
{
|
|
85
|
+
// Use client's public key as source author (self-federation for upcast)
|
|
86
|
+
sourceAuthorPubKey: client.publicKey,
|
|
87
|
+
permissions: ['read'],
|
|
88
|
+
}
|
|
89
|
+
);
|
|
74
90
|
|
|
75
91
|
// Add operation metadata
|
|
76
92
|
hologram._meta.operation = operation;
|