holosphere 2.0.0-alpha1 → 2.0.0-alpha4

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.
Files changed (154) hide show
  1. package/dist/2019-D2OG2idw.js +6680 -0
  2. package/dist/2019-D2OG2idw.js.map +1 -0
  3. package/dist/2019-EION3wKo.cjs +8 -0
  4. package/dist/2019-EION3wKo.cjs.map +1 -0
  5. package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
  6. package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
  7. package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
  8. package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
  9. package/dist/browser-BSniCNqO.js +3058 -0
  10. package/dist/browser-BSniCNqO.js.map +1 -0
  11. package/dist/browser-Cq59Ij19.cjs +2 -0
  12. package/dist/browser-Cq59Ij19.cjs.map +1 -0
  13. package/dist/cjs/holosphere.cjs +2 -0
  14. package/dist/cjs/holosphere.cjs.map +1 -0
  15. package/dist/esm/holosphere.js +53 -0
  16. package/dist/esm/holosphere.js.map +1 -0
  17. package/dist/index-BB_vVJgv.cjs +5 -0
  18. package/dist/index-BB_vVJgv.cjs.map +1 -0
  19. package/dist/index-CBitK71M.cjs +12 -0
  20. package/dist/index-CBitK71M.cjs.map +1 -0
  21. package/dist/index-CV0eOogK.js +37423 -0
  22. package/dist/index-CV0eOogK.js.map +1 -0
  23. package/dist/index-Cz-PLCUR.js +15104 -0
  24. package/dist/index-Cz-PLCUR.js.map +1 -0
  25. package/dist/indexeddb-storage-CRsZyB2f.cjs +2 -0
  26. package/dist/indexeddb-storage-CRsZyB2f.cjs.map +1 -0
  27. package/dist/indexeddb-storage-DZaGlY_a.js +132 -0
  28. package/dist/indexeddb-storage-DZaGlY_a.js.map +1 -0
  29. package/dist/memory-storage-BkUi6sZG.js +51 -0
  30. package/dist/memory-storage-BkUi6sZG.js.map +1 -0
  31. package/dist/memory-storage-C0DuUsdY.cjs +2 -0
  32. package/dist/memory-storage-C0DuUsdY.cjs.map +1 -0
  33. package/dist/secp256k1-0kPdAVkK.cjs +12 -0
  34. package/dist/secp256k1-0kPdAVkK.cjs.map +1 -0
  35. package/dist/secp256k1-DN4FVXcv.js +1890 -0
  36. package/dist/secp256k1-DN4FVXcv.js.map +1 -0
  37. package/docs/CONTRACTS.md +797 -0
  38. package/docs/FOSDEM_PROPOSAL.md +388 -0
  39. package/docs/LOCALFIRST.md +266 -0
  40. package/docs/contracts/api-interface.md +793 -0
  41. package/docs/data-model.md +476 -0
  42. package/docs/gun-async-usage.md +338 -0
  43. package/docs/plan.md +349 -0
  44. package/docs/quickstart.md +674 -0
  45. package/docs/research.md +362 -0
  46. package/docs/spec.md +244 -0
  47. package/docs/storage-backends.md +326 -0
  48. package/docs/tasks.md +947 -0
  49. package/examples/demo.html +47 -0
  50. package/package.json +10 -5
  51. package/src/contracts/abis/Appreciative.json +1280 -0
  52. package/src/contracts/abis/AppreciativeFactory.json +101 -0
  53. package/src/contracts/abis/Bundle.json +1435 -0
  54. package/src/contracts/abis/BundleFactory.json +106 -0
  55. package/src/contracts/abis/Holon.json +881 -0
  56. package/src/contracts/abis/Holons.json +330 -0
  57. package/src/contracts/abis/Managed.json +1262 -0
  58. package/src/contracts/abis/ManagedFactory.json +149 -0
  59. package/src/contracts/abis/Membrane.json +261 -0
  60. package/src/contracts/abis/Splitter.json +1624 -0
  61. package/src/contracts/abis/SplitterFactory.json +220 -0
  62. package/src/contracts/abis/TestToken.json +321 -0
  63. package/src/contracts/abis/Zoned.json +1461 -0
  64. package/src/contracts/abis/ZonedFactory.json +154 -0
  65. package/src/contracts/chain-manager.js +375 -0
  66. package/src/contracts/deployer.js +443 -0
  67. package/src/contracts/event-listener.js +507 -0
  68. package/src/contracts/holon-contracts.js +344 -0
  69. package/src/contracts/index.js +83 -0
  70. package/src/contracts/networks.js +224 -0
  71. package/src/contracts/operations.js +670 -0
  72. package/src/contracts/queries.js +589 -0
  73. package/src/core/holosphere.js +453 -1
  74. package/src/crypto/nostr-utils.js +263 -0
  75. package/src/federation/handshake.js +455 -0
  76. package/src/federation/hologram.js +1 -1
  77. package/src/hierarchical/upcast.js +6 -5
  78. package/src/index.js +463 -1939
  79. package/src/lib/ai-methods.js +308 -0
  80. package/src/lib/contract-methods.js +293 -0
  81. package/src/lib/errors.js +23 -0
  82. package/src/lib/federation-methods.js +238 -0
  83. package/src/lib/index.js +26 -0
  84. package/src/spatial/h3-operations.js +2 -2
  85. package/src/storage/backends/gundb-backend.js +377 -46
  86. package/src/storage/global-tables.js +28 -1
  87. package/src/storage/gun-auth.js +303 -0
  88. package/src/storage/gun-federation.js +776 -0
  89. package/src/storage/gun-references.js +198 -0
  90. package/src/storage/gun-schema.js +291 -0
  91. package/src/storage/gun-wrapper.js +347 -31
  92. package/src/storage/indexeddb-storage.js +49 -11
  93. package/src/storage/memory-storage.js +5 -0
  94. package/src/storage/nostr-async.js +45 -23
  95. package/src/storage/nostr-client.js +11 -5
  96. package/src/storage/persistent-storage.js +6 -1
  97. package/src/storage/unified-storage.js +119 -0
  98. package/src/subscriptions/manager.js +1 -1
  99. package/types/index.d.ts +133 -0
  100. package/tests/unit/ai/aggregation.test.js +0 -295
  101. package/tests/unit/ai/breakdown.test.js +0 -446
  102. package/tests/unit/ai/classifier.test.js +0 -294
  103. package/tests/unit/ai/council.test.js +0 -262
  104. package/tests/unit/ai/embeddings.test.js +0 -384
  105. package/tests/unit/ai/federation-ai.test.js +0 -344
  106. package/tests/unit/ai/h3-ai.test.js +0 -458
  107. package/tests/unit/ai/index.test.js +0 -304
  108. package/tests/unit/ai/json-ops.test.js +0 -307
  109. package/tests/unit/ai/llm-service.test.js +0 -390
  110. package/tests/unit/ai/nl-query.test.js +0 -383
  111. package/tests/unit/ai/relationships.test.js +0 -311
  112. package/tests/unit/ai/schema-extractor.test.js +0 -384
  113. package/tests/unit/ai/spatial.test.js +0 -279
  114. package/tests/unit/ai/tts.test.js +0 -279
  115. package/tests/unit/content.test.js +0 -332
  116. package/tests/unit/contract/core.test.js +0 -88
  117. package/tests/unit/contract/crypto.test.js +0 -198
  118. package/tests/unit/contract/data.test.js +0 -223
  119. package/tests/unit/contract/federation.test.js +0 -181
  120. package/tests/unit/contract/hierarchical.test.js +0 -113
  121. package/tests/unit/contract/schema.test.js +0 -114
  122. package/tests/unit/contract/social.test.js +0 -217
  123. package/tests/unit/contract/spatial.test.js +0 -110
  124. package/tests/unit/contract/subscriptions.test.js +0 -128
  125. package/tests/unit/contract/utils.test.js +0 -159
  126. package/tests/unit/core.test.js +0 -152
  127. package/tests/unit/crypto.test.js +0 -328
  128. package/tests/unit/federation.test.js +0 -234
  129. package/tests/unit/gun-async.test.js +0 -252
  130. package/tests/unit/hierarchical.test.js +0 -399
  131. package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
  132. package/tests/unit/integration/scenario-02-federation.test.js +0 -76
  133. package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
  134. package/tests/unit/integration/scenario-04-validation.test.js +0 -129
  135. package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
  136. package/tests/unit/integration/scenario-06-social.test.js +0 -135
  137. package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
  138. package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
  139. package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
  140. package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
  141. package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
  142. package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
  143. package/tests/unit/performance/benchmark.test.js +0 -85
  144. package/tests/unit/schema.test.js +0 -213
  145. package/tests/unit/spatial.test.js +0 -158
  146. package/tests/unit/storage.test.js +0 -195
  147. package/tests/unit/subscriptions.test.js +0 -328
  148. package/tests/unit/test-data-permanence-debug.js +0 -197
  149. package/tests/unit/test-data-permanence.js +0 -340
  150. package/tests/unit/test-key-persistence-fixed.js +0 -148
  151. package/tests/unit/test-key-persistence.js +0 -172
  152. package/tests/unit/test-relay-permanence.js +0 -376
  153. package/tests/unit/test-second-node.js +0 -95
  154. package/tests/unit/test-simple-write.js +0 -89
@@ -1,410 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
- import HoloSphere, { matchScope, createHologram } from '../../../src/index.js';
3
-
4
- describe('Integration: Scenario 11 - Cross-Holosphere Federation', () => {
5
- // Two distinct private keys for two separate holospheres
6
- const privateKeyA = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
7
- const privateKeyB = 'fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210';
8
-
9
- let holosphereA;
10
- let holosphereB;
11
- let publicKeyA;
12
- let publicKeyB;
13
- let testHolon;
14
-
15
- beforeEach(async () => {
16
- // Create two independent holospheres with different private keys and app namespaces
17
- // Different appNames ensure data isolation in local mode
18
- holosphereA = new HoloSphere({
19
- relays: [],
20
- appName: 'scenario-11-A',
21
- privateKey: privateKeyA,
22
- logLevel: 'ERROR'
23
- });
24
-
25
- holosphereB = new HoloSphere({
26
- relays: [],
27
- appName: 'scenario-11-B',
28
- privateKey: privateKeyB,
29
- logLevel: 'ERROR'
30
- });
31
-
32
- // Get public keys
33
- publicKeyA = holosphereA.client.publicKey;
34
- publicKeyB = holosphereB.client.publicKey;
35
-
36
- // Create a test holon (H3 cell)
37
- testHolon = await holosphereA.toHolon(37.7749, -122.4194, 9);
38
- });
39
-
40
- afterEach(async () => {
41
- if (holosphereA?.client?.close) await holosphereA.client.close();
42
- if (holosphereB?.client?.close) await holosphereB.client.close();
43
- });
44
-
45
- describe('Wildcard Scope Matching', () => {
46
- it('should match exact scope', () => {
47
- const tokenScope = { holonId: 'abc', lensName: 'quests' };
48
- const requestedScope = { holonId: 'abc', lensName: 'quests' };
49
- expect(matchScope(tokenScope, requestedScope)).toBe(true);
50
- });
51
-
52
- it('should match wildcard holonId', () => {
53
- const tokenScope = { holonId: '*', lensName: 'quests' };
54
- const requestedScope = { holonId: 'any-holon-id', lensName: 'quests' };
55
- expect(matchScope(tokenScope, requestedScope)).toBe(true);
56
- });
57
-
58
- it('should match wildcard lensName', () => {
59
- const tokenScope = { holonId: 'abc', lensName: '*' };
60
- const requestedScope = { holonId: 'abc', lensName: 'any-lens' };
61
- expect(matchScope(tokenScope, requestedScope)).toBe(true);
62
- });
63
-
64
- it('should match full wildcard scope', () => {
65
- const tokenScope = { holonId: '*', lensName: '*' };
66
- const requestedScope = { holonId: 'any-holon', lensName: 'any-lens' };
67
- expect(matchScope(tokenScope, requestedScope)).toBe(true);
68
- });
69
-
70
- it('should match item-level scope', () => {
71
- const tokenScope = { holonId: 'abc', lensName: 'quests', dataId: 'quest-001' };
72
- const requestedScope = { holonId: 'abc', lensName: 'quests', dataId: 'quest-001' };
73
- expect(matchScope(tokenScope, requestedScope)).toBe(true);
74
- });
75
-
76
- it('should match wildcard dataId', () => {
77
- const tokenScope = { holonId: 'abc', lensName: 'quests', dataId: '*' };
78
- const requestedScope = { holonId: 'abc', lensName: 'quests', dataId: 'any-id' };
79
- expect(matchScope(tokenScope, requestedScope)).toBe(true);
80
- });
81
-
82
- it('should NOT match different holonId', () => {
83
- const tokenScope = { holonId: 'abc', lensName: 'quests' };
84
- const requestedScope = { holonId: 'xyz', lensName: 'quests' };
85
- expect(matchScope(tokenScope, requestedScope)).toBe(false);
86
- });
87
-
88
- it('should NOT match different lensName', () => {
89
- const tokenScope = { holonId: 'abc', lensName: 'quests' };
90
- const requestedScope = { holonId: 'abc', lensName: 'events' };
91
- expect(matchScope(tokenScope, requestedScope)).toBe(false);
92
- });
93
-
94
- it('should NOT match different dataId when specific', () => {
95
- const tokenScope = { holonId: 'abc', lensName: 'quests', dataId: 'quest-001' };
96
- const requestedScope = { holonId: 'abc', lensName: 'quests', dataId: 'quest-002' };
97
- expect(matchScope(tokenScope, requestedScope)).toBe(false);
98
- });
99
- });
100
-
101
- describe('Federation Registry', () => {
102
- it('should add a federated partner', async () => {
103
- await holosphereA.addFederatedHolosphere(publicKeyB, {
104
- alias: 'Partner B'
105
- });
106
-
107
- const partners = await holosphereA.getFederatedHolospheres();
108
- expect(partners).toContain(publicKeyB);
109
- });
110
-
111
- it('should remove a federated partner', async () => {
112
- await holosphereA.addFederatedHolosphere(publicKeyB);
113
- await holosphereA.removeFederatedHolosphere(publicKeyB);
114
-
115
- const partners = await holosphereA.getFederatedHolospheres();
116
- expect(partners).not.toContain(publicKeyB);
117
- });
118
-
119
- it('should store inbound capabilities', async () => {
120
- // A issues capability to B
121
- const capabilityToken = await holosphereA.issueCapability(
122
- ['read'],
123
- { holonId: testHolon, lensName: 'shared' },
124
- publicKeyB,
125
- { issuerKey: privateKeyA }
126
- );
127
-
128
- // B stores the capability they received
129
- await holosphereB.addFederatedHolosphere(publicKeyA);
130
- await holosphereB.storeInboundCapability(publicKeyA, {
131
- token: capabilityToken,
132
- scope: { holonId: testHolon, lensName: 'shared' },
133
- permissions: ['read'],
134
- expires: Date.now() + 3600000
135
- });
136
-
137
- const registry = await holosphereB.getFederationRegistry();
138
- const partner = registry.federatedWith.find(p => p.pubKey === publicKeyA);
139
- expect(partner).toBeDefined();
140
- expect(partner.inboundCapabilities.length).toBeGreaterThan(0);
141
- });
142
- });
143
-
144
- describe('Capability Verification with Wildcards', () => {
145
- it('should verify wildcard capability for any holon', async () => {
146
- // Issue wildcard capability
147
- const token = await holosphereA.issueCapability(
148
- ['read'],
149
- { holonId: '*', lensName: 'events' },
150
- publicKeyB,
151
- { issuerKey: privateKeyA }
152
- );
153
-
154
- // Should be valid for any holon with 'events' lens
155
- const holon1 = await holosphereA.toHolon(40.7128, -74.0060, 9);
156
- const holon2 = await holosphereA.toHolon(51.5074, -0.1278, 9);
157
-
158
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: holon1, lensName: 'events' })).toBe(true);
159
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: holon2, lensName: 'events' })).toBe(true);
160
- // But not for different lens
161
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: holon1, lensName: 'other' })).toBe(false);
162
- });
163
-
164
- it('should verify full wildcard capability for all data', async () => {
165
- const token = await holosphereA.issueCapability(
166
- ['read', 'write'],
167
- { holonId: '*', lensName: '*' },
168
- publicKeyB,
169
- { issuerKey: privateKeyA }
170
- );
171
-
172
- const randomHolon = await holosphereA.toHolon(35.6762, 139.6503, 9);
173
-
174
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: randomHolon, lensName: 'anything' })).toBe(true);
175
- expect(await holosphereA.verifyCapability(token, 'write', { holonId: randomHolon, lensName: 'something-else' })).toBe(true);
176
- });
177
- });
178
-
179
- describe('Cross-Holosphere Hologram Creation', () => {
180
- it('should create a hologram with embedded capability', () => {
181
- const capabilityToken = 'mock-capability-token';
182
-
183
- const hologram = createHologram(
184
- testHolon, // sourceHolon
185
- 'target-holon', // targetHolon
186
- 'quests', // lensName
187
- 'quest-001', // dataId
188
- 'scenario-11', // appname
189
- {
190
- authorPubKey: publicKeyA,
191
- capability: capabilityToken
192
- }
193
- );
194
-
195
- expect(hologram.hologram).toBe(true);
196
- expect(hologram.crossHolosphere).toBe(true);
197
- expect(hologram.target.authorPubKey).toBe(publicKeyA);
198
- expect(hologram.capability).toBe(capabilityToken);
199
- expect(hologram._meta.sourcePubKey).toBe(publicKeyA);
200
- });
201
-
202
- it('should include correct target information', () => {
203
- const hologram = createHologram(
204
- testHolon,
205
- 'target-holon',
206
- 'events',
207
- 'event-001',
208
- 'my-app',
209
- { authorPubKey: publicKeyA }
210
- );
211
-
212
- expect(hologram.target.holonId).toBe(testHolon);
213
- expect(hologram.target.lensName).toBe('events');
214
- expect(hologram.target.dataId).toBe('event-001');
215
- expect(hologram.target.appname).toBe('my-app');
216
- expect(hologram.target.authorPubKey).toBe(publicKeyA);
217
- });
218
- });
219
-
220
- describe('Issue Capability for Federation', () => {
221
- it('should issue capability and track in registry', async () => {
222
- const token = await holosphereA.issueCapabilityForFederation(
223
- publicKeyB,
224
- { holonId: testHolon, lensName: 'shared' },
225
- ['read'],
226
- { expiresIn: 3600000, trackInRegistry: true }
227
- );
228
-
229
- expect(typeof token).toBe('string');
230
-
231
- const registry = await holosphereA.getFederationRegistry();
232
- const partner = registry.federatedWith.find(p => p.pubKey === publicKeyB);
233
- expect(partner).toBeDefined();
234
- expect(partner.outboundCapabilities.length).toBeGreaterThan(0);
235
- });
236
-
237
- it('should issue capability without tracking when disabled', async () => {
238
- const token = await holosphereA.issueCapabilityForFederation(
239
- publicKeyB,
240
- { holonId: testHolon, lensName: 'private' },
241
- ['read'],
242
- { expiresIn: 3600000, trackInRegistry: false }
243
- );
244
-
245
- expect(typeof token).toBe('string');
246
-
247
- // Should still be a valid token
248
- const isValid = await holosphereA.verifyCapability(
249
- token,
250
- 'read',
251
- { holonId: testHolon, lensName: 'private' }
252
- );
253
- expect(isValid).toBe(true);
254
- });
255
- });
256
-
257
- describe('Complete Cross-Holosphere Workflow', () => {
258
- it('should complete manual federation workflow', async () => {
259
- // === PHASE 1: A writes data ===
260
- const secretData = {
261
- id: 'secret-001',
262
- title: 'Secret Quest',
263
- description: 'Only visible with capability',
264
- _creator: publicKeyA
265
- };
266
- await holosphereA.write(testHolon, 'quests', secretData);
267
-
268
- // Verify A can read their own data
269
- const aData = await holosphereA.read(testHolon, 'quests', 'secret-001');
270
- expect(aData).toBeDefined();
271
- expect(aData.title).toBe('Secret Quest');
272
-
273
- // B cannot see A's data (different holosphere)
274
- const bData = await holosphereB.read(testHolon, 'quests', 'secret-001');
275
- expect(bData).toBeNull();
276
-
277
- // === PHASE 2: A issues capability to B ===
278
- const capabilityToken = await holosphereA.issueCapabilityForFederation(
279
- publicKeyB,
280
- { holonId: testHolon, lensName: 'quests' },
281
- ['read'],
282
- { expiresIn: 3600000 }
283
- );
284
-
285
- expect(typeof capabilityToken).toBe('string');
286
-
287
- // === PHASE 3: B stores the capability ===
288
- await holosphereB.addFederatedHolosphere(publicKeyA, {
289
- alias: 'Holosphere A'
290
- });
291
-
292
- await holosphereB.storeInboundCapability(publicKeyA, {
293
- token: capabilityToken,
294
- scope: { holonId: testHolon, lensName: 'quests' },
295
- permissions: ['read'],
296
- expires: Date.now() + 3600000
297
- });
298
-
299
- // === PHASE 4: Verify B has access ===
300
- const isValid = await holosphereB.verifyCapability(
301
- capabilityToken,
302
- 'read',
303
- { holonId: testHolon, lensName: 'quests' }
304
- );
305
- expect(isValid).toBe(true);
306
-
307
- // === PHASE 5: Verify capability is in B's registry ===
308
- const bRegistry = await holosphereB.getFederationRegistry();
309
- const partnerA = bRegistry.federatedWith.find(p => p.pubKey === publicKeyA);
310
- expect(partnerA).toBeDefined();
311
- expect(partnerA.inboundCapabilities.length).toBeGreaterThan(0);
312
- });
313
-
314
- it('should reject operations without valid capability', async () => {
315
- // A writes data
316
- await holosphereA.write(testHolon, 'protected', {
317
- id: 'protected-001',
318
- content: 'This is protected data'
319
- });
320
-
321
- // B adds A as partner but without capability
322
- await holosphereB.addFederatedHolosphere(publicKeyA);
323
-
324
- // B should not be able to read from A (no capability)
325
- await expect(
326
- holosphereB.readFromFederatedSource(publicKeyA, testHolon, 'protected', 'protected-001')
327
- ).rejects.toThrow('No valid capability for federated source');
328
- });
329
-
330
- it('should reject expired capabilities', async () => {
331
- // Issue already expired capability
332
- const expiredToken = await holosphereA.issueCapability(
333
- ['read'],
334
- { holonId: testHolon, lensName: 'temp' },
335
- publicKeyB,
336
- { expiresIn: -1000, issuerKey: privateKeyA } // Already expired
337
- );
338
-
339
- await holosphereB.addFederatedHolosphere(publicKeyA);
340
- await holosphereB.storeInboundCapability(publicKeyA, {
341
- token: expiredToken,
342
- scope: { holonId: testHolon, lensName: 'temp' },
343
- permissions: ['read'],
344
- expires: Date.now() - 1000 // Already expired
345
- });
346
-
347
- // Verification should fail
348
- const isValid = await holosphereB.verifyCapability(
349
- expiredToken,
350
- 'read',
351
- { holonId: testHolon, lensName: 'temp' }
352
- );
353
- expect(isValid).toBe(false);
354
- });
355
- });
356
-
357
- describe('Scope Boundary Enforcement', () => {
358
- it('should enforce holon boundary', async () => {
359
- const holon1 = await holosphereA.toHolon(40.7128, -74.0060, 9);
360
- const holon2 = await holosphereA.toHolon(51.5074, -0.1278, 9);
361
-
362
- // Issue capability only for holon1
363
- const token = await holosphereA.issueCapability(
364
- ['read'],
365
- { holonId: holon1, lensName: 'events' },
366
- publicKeyB,
367
- { issuerKey: privateKeyA }
368
- );
369
-
370
- // Valid for holon1
371
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: holon1, lensName: 'events' })).toBe(true);
372
-
373
- // Invalid for holon2
374
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: holon2, lensName: 'events' })).toBe(false);
375
- });
376
-
377
- it('should enforce lens boundary', async () => {
378
- const token = await holosphereA.issueCapability(
379
- ['read'],
380
- { holonId: testHolon, lensName: 'quests' },
381
- publicKeyB,
382
- { issuerKey: privateKeyA }
383
- );
384
-
385
- // Valid for 'quests' lens
386
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: testHolon, lensName: 'quests' })).toBe(true);
387
-
388
- // Invalid for 'events' lens
389
- expect(await holosphereA.verifyCapability(token, 'read', { holonId: testHolon, lensName: 'events' })).toBe(false);
390
- });
391
-
392
- it('should enforce permission boundary', async () => {
393
- const readOnlyToken = await holosphereA.issueCapability(
394
- ['read'],
395
- { holonId: testHolon, lensName: 'docs' },
396
- publicKeyB,
397
- { issuerKey: privateKeyA }
398
- );
399
-
400
- // Has read permission
401
- expect(await holosphereA.verifyCapability(readOnlyToken, 'read', { holonId: testHolon, lensName: 'docs' })).toBe(true);
402
-
403
- // Does NOT have write permission
404
- expect(await holosphereA.verifyCapability(readOnlyToken, 'write', { holonId: testHolon, lensName: 'docs' })).toBe(false);
405
-
406
- // Does NOT have delete permission
407
- expect(await holosphereA.verifyCapability(readOnlyToken, 'delete', { holonId: testHolon, lensName: 'docs' })).toBe(false);
408
- });
409
- });
410
- });