holosphere 2.0.0-alpha1 → 2.0.0-alpha10
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/CHANGELOG.md +473 -0
- package/FEATURES.md +431 -0
- package/LICENSE +29 -166
- package/LICENSE-AGPL.md +180 -0
- package/README.md +97 -16
- package/dist/2019-D2OG2idw.js +6680 -0
- package/dist/2019-D2OG2idw.js.map +1 -0
- package/dist/2019-EION3wKo.cjs +8 -0
- package/dist/2019-EION3wKo.cjs.map +1 -0
- package/dist/_commonjsHelpers-C37NGDzP.cjs +2 -0
- package/dist/_commonjsHelpers-C37NGDzP.cjs.map +1 -0
- package/dist/_commonjsHelpers-CUmg6egw.js +7 -0
- package/dist/_commonjsHelpers-CUmg6egw.js.map +1 -0
- package/dist/browser-BSniCNqO.js +3058 -0
- package/dist/browser-BSniCNqO.js.map +1 -0
- package/dist/browser-Cq59Ij19.cjs +2 -0
- package/dist/browser-Cq59Ij19.cjs.map +1 -0
- package/dist/cdn/holosphere.min.js +55 -0
- package/dist/cdn/holosphere.min.js.map +1 -0
- package/dist/cjs/holosphere.cjs +2 -0
- package/dist/cjs/holosphere.cjs.map +1 -0
- package/dist/esm/holosphere.js +53 -0
- package/dist/esm/holosphere.js.map +1 -0
- package/dist/index-DDGt_V9o.cjs +12 -0
- package/dist/index-DDGt_V9o.cjs.map +1 -0
- package/dist/index-DJXftyvB.js +39841 -0
- package/dist/index-DJXftyvB.js.map +1 -0
- package/dist/index-DMbdcMtK.cjs +18 -0
- package/dist/index-DMbdcMtK.cjs.map +1 -0
- package/dist/index-DeZ1xz_s.js +15104 -0
- package/dist/index-DeZ1xz_s.js.map +1 -0
- package/dist/indexeddb-storage-BFt6hMeF.js +176 -0
- package/dist/indexeddb-storage-BFt6hMeF.js.map +1 -0
- package/dist/indexeddb-storage-BK5tv4Sh.cjs +2 -0
- package/dist/indexeddb-storage-BK5tv4Sh.cjs.map +1 -0
- package/dist/memory-storage-C9HuoL2E.js +91 -0
- package/dist/memory-storage-C9HuoL2E.js.map +1 -0
- package/dist/memory-storage-Dao7jfYG.cjs +2 -0
- package/dist/memory-storage-Dao7jfYG.cjs.map +1 -0
- package/dist/secp256k1-BbKzbLtD.cjs +12 -0
- package/dist/secp256k1-BbKzbLtD.cjs.map +1 -0
- package/dist/secp256k1-CreY7Pcl.js +1890 -0
- package/dist/secp256k1-CreY7Pcl.js.map +1 -0
- package/docs/CONTRACTS.md +797 -0
- package/docs/FOSDEM_PROPOSAL.md +388 -0
- package/docs/LOCALFIRST.md +266 -0
- package/docs/api/ai_aggregation.js.html +333 -0
- package/docs/api/ai_breakdown.js.html +524 -0
- package/docs/api/ai_classifier.js.html +231 -0
- package/docs/api/ai_council.js.html +246 -0
- package/docs/api/ai_embeddings.js.html +304 -0
- package/docs/api/ai_federation-ai.js.html +338 -0
- package/docs/api/ai_h3-ai.js.html +970 -0
- package/docs/api/ai_index.js.html +124 -0
- package/docs/api/ai_json-ops.js.html +241 -0
- package/docs/api/ai_llm-service.js.html +239 -0
- package/docs/api/ai_nl-query.js.html +236 -0
- package/docs/api/ai_relationships.js.html +367 -0
- package/docs/api/ai_schema-extractor.js.html +235 -0
- package/docs/api/ai_spatial.js.html +307 -0
- package/docs/api/ai_tts.js.html +214 -0
- package/docs/api/content_social-protocols.js.html +180 -0
- package/docs/api/core_holosphere.js.html +757 -0
- package/docs/api/crypto_nostr-utils.js.html +306 -0
- package/docs/api/crypto_secp256k1.js.html +267 -0
- package/docs/api/data/search.json +1 -0
- package/docs/api/federation_discovery.js.html +337 -0
- package/docs/api/federation_handshake.js.html +478 -0
- package/docs/api/federation_hologram.js.html +1053 -0
- package/docs/api/federation_registry.js.html +389 -0
- package/docs/api/fonts/Inconsolata-Regular.ttf +0 -0
- package/docs/api/fonts/OpenSans-Regular.ttf +0 -0
- package/docs/api/fonts/WorkSans-Bold.ttf +0 -0
- package/docs/api/global.html +3 -0
- package/docs/api/hierarchical_upcast.js.html +128 -0
- package/docs/api/index.html +265 -0
- package/docs/api/index.js.html +1868 -0
- package/docs/api/lib_ai-methods.js.html +660 -0
- package/docs/api/lib_contract-methods.js.html +445 -0
- package/docs/api/lib_errors.js.html +56 -0
- package/docs/api/lib_federation-methods.js.html +348 -0
- package/docs/api/lib_index.js.html +33 -0
- package/docs/api/module-ai.html +5 -0
- package/docs/api/module-ai_aggregation-SmartAggregation.html +6 -0
- package/docs/api/module-ai_aggregation.SmartAggregation.html +3 -0
- package/docs/api/module-ai_aggregation.html +3 -0
- package/docs/api/module-ai_breakdown-TaskBreakdown.html +5 -0
- package/docs/api/module-ai_breakdown.TaskBreakdown.html +3 -0
- package/docs/api/module-ai_breakdown.html +3 -0
- package/docs/api/module-ai_classifier-Classifier.html +6 -0
- package/docs/api/module-ai_classifier.Classifier.html +3 -0
- package/docs/api/module-ai_classifier.html +3 -0
- package/docs/api/module-ai_council-Council.html +6 -0
- package/docs/api/module-ai_council.Council.html +3 -0
- package/docs/api/module-ai_council.html +3 -0
- package/docs/api/module-ai_embeddings-Embeddings.html +5 -0
- package/docs/api/module-ai_embeddings.Embeddings.html +3 -0
- package/docs/api/module-ai_embeddings.html +3 -0
- package/docs/api/module-ai_federation-ai-FederationAdvisor.html +6 -0
- package/docs/api/module-ai_federation-ai.FederationAdvisor.html +3 -0
- package/docs/api/module-ai_federation-ai.html +3 -0
- package/docs/api/module-ai_h3-ai-H3AI.html +6 -0
- package/docs/api/module-ai_h3-ai.H3AI.html +3 -0
- package/docs/api/module-ai_h3-ai.html +3 -0
- package/docs/api/module-ai_json-ops-JSONOps.html +5 -0
- package/docs/api/module-ai_json-ops.JSONOps.html +3 -0
- package/docs/api/module-ai_json-ops.html +3 -0
- package/docs/api/module-ai_llm-service-LLMService.html +5 -0
- package/docs/api/module-ai_llm-service.LLMService.html +3 -0
- package/docs/api/module-ai_llm-service.html +3 -0
- package/docs/api/module-ai_nl-query-NLQuery.html +5 -0
- package/docs/api/module-ai_nl-query.NLQuery.html +3 -0
- package/docs/api/module-ai_nl-query.html +3 -0
- package/docs/api/module-ai_relationships-RelationshipDiscovery.html +6 -0
- package/docs/api/module-ai_relationships.RelationshipDiscovery.html +3 -0
- package/docs/api/module-ai_relationships.html +3 -0
- package/docs/api/module-ai_schema-extractor-SchemaExtractor.html +5 -0
- package/docs/api/module-ai_schema-extractor.SchemaExtractor.html +3 -0
- package/docs/api/module-ai_schema-extractor.html +3 -0
- package/docs/api/module-ai_spatial-SpatialAnalysis.html +6 -0
- package/docs/api/module-ai_spatial.SpatialAnalysis.html +3 -0
- package/docs/api/module-ai_spatial.html +3 -0
- package/docs/api/module-ai_tts-TTS.html +5 -0
- package/docs/api/module-ai_tts.TTS.html +3 -0
- package/docs/api/module-ai_tts.html +3 -0
- package/docs/api/module-content_social-protocols.html +3 -0
- package/docs/api/module-core_holosphere-HoloSphere.html +6 -0
- package/docs/api/module-core_holosphere.HoloSphere.html +3 -0
- package/docs/api/module-core_holosphere.html +3 -0
- package/docs/api/module-crypto_nostr-utils.html +3 -0
- package/docs/api/module-crypto_secp256k1.html +3 -0
- package/docs/api/module-federation_hologram.html +3 -0
- package/docs/api/module-hierarchical_upcast.html +3 -0
- package/docs/api/module-holosphere-HoloSphereBase.html +3 -0
- package/docs/api/module-holosphere.html +3 -0
- package/docs/api/module-lib_ai-methods.html +3 -0
- package/docs/api/module-lib_contract-methods.html +3 -0
- package/docs/api/module-lib_errors-AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors-ValidationError.html +3 -0
- package/docs/api/module-lib_errors.AuthorizationError.html +3 -0
- package/docs/api/module-lib_errors.ValidationError.html +3 -0
- package/docs/api/module-lib_errors.html +3 -0
- package/docs/api/module-lib_federation-methods.html +3 -0
- package/docs/api/module-lib_index.html +3 -0
- package/docs/api/module-schema_validator-ValidationError.html +3 -0
- package/docs/api/module-schema_validator.ValidationError.html +3 -0
- package/docs/api/module-schema_validator.html +3 -0
- package/docs/api/module-spatial_h3-operations.html +4 -0
- package/docs/api/module-storage_backend-factory.BackendFactory.html +3 -0
- package/docs/api/module-storage_backend-factory.html +3 -0
- package/docs/api/module-storage_backend-interface-StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.StorageBackend.html +3 -0
- package/docs/api/module-storage_backend-interface.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend-ActivityPubBackend.html +7 -0
- package/docs/api/module-storage_backends_activitypub-backend.ActivityPubBackend.html +3 -0
- package/docs/api/module-storage_backends_activitypub-backend.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server-ActivityPubServer.html +8 -0
- package/docs/api/module-storage_backends_activitypub_server.ActivityPubServer.html +3 -0
- package/docs/api/module-storage_backends_activitypub_server.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend-GunDBBackend.html +7 -0
- package/docs/api/module-storage_backends_gundb-backend.GunDBBackend.html +3 -0
- package/docs/api/module-storage_backends_gundb-backend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend-NostrBackend.html +8 -0
- package/docs/api/module-storage_backends_nostr-backend.NostrBackend.html +3 -0
- package/docs/api/module-storage_backends_nostr-backend.html +3 -0
- package/docs/api/module-storage_filesystem-storage-FileSystemStorage.html +5 -0
- package/docs/api/module-storage_filesystem-storage-browser-FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage-browser.html +3 -0
- package/docs/api/module-storage_filesystem-storage.FileSystemStorage.html +3 -0
- package/docs/api/module-storage_filesystem-storage.html +3 -0
- package/docs/api/module-storage_global-tables.html +3 -0
- package/docs/api/module-storage_gun-async.html +3 -0
- package/docs/api/module-storage_gun-auth-GunAuth.html +5 -0
- package/docs/api/module-storage_gun-auth.GunAuth.html +3 -0
- package/docs/api/module-storage_gun-auth.html +3 -0
- package/docs/api/module-storage_gun-federation.html +3 -0
- package/docs/api/module-storage_gun-references-GunReferenceHandler.html +5 -0
- package/docs/api/module-storage_gun-references.GunReferenceHandler.html +3 -0
- package/docs/api/module-storage_gun-references.html +3 -0
- package/docs/api/module-storage_gun-schema-GunSchemaValidator.html +5 -0
- package/docs/api/module-storage_gun-schema.GunSchemaValidator.html +3 -0
- package/docs/api/module-storage_gun-schema.html +3 -0
- package/docs/api/module-storage_gun-wrapper.html +11 -0
- package/docs/api/module-storage_indexeddb-storage-IndexedDBStorage.html +5 -0
- package/docs/api/module-storage_indexeddb-storage.IndexedDBStorage.html +3 -0
- package/docs/api/module-storage_indexeddb-storage.html +3 -0
- package/docs/api/module-storage_key-storage-simple.html +3 -0
- package/docs/api/module-storage_key-storage.html +4 -0
- package/docs/api/module-storage_memory-storage-MemoryStorage.html +5 -0
- package/docs/api/module-storage_memory-storage.MemoryStorage.html +3 -0
- package/docs/api/module-storage_memory-storage.html +3 -0
- package/docs/api/module-storage_migration-MigrationTool.html +6 -0
- package/docs/api/module-storage_migration.MigrationTool.html +3 -0
- package/docs/api/module-storage_migration.html +3 -0
- package/docs/api/module-storage_nostr-async.html +18 -0
- package/docs/api/module-storage_nostr-client-LRUCache.html +3 -0
- package/docs/api/module-storage_nostr-client-NostrClient.html +7 -0
- package/docs/api/module-storage_nostr-client.NostrClient.html +15 -0
- package/docs/api/module-storage_nostr-client.html +6 -0
- package/docs/api/module-storage_nostr-wrapper.html +3 -0
- package/docs/api/module-storage_outbox-queue-OutboxQueue.html +4 -0
- package/docs/api/module-storage_outbox-queue.OutboxQueue.html +3 -0
- package/docs/api/module-storage_outbox-queue.html +3 -0
- package/docs/api/module-storage_persistent-storage-PersistentStorage.html +3 -0
- package/docs/api/module-storage_persistent-storage.html +4 -0
- package/docs/api/module-storage_sync-service-SyncService.html +5 -0
- package/docs/api/module-storage_sync-service.SyncService.html +3 -0
- package/docs/api/module-storage_sync-service.html +3 -0
- package/docs/api/module-storage_unified-storage.html +3 -0
- package/docs/api/module-subscriptions_manager.SubscriptionRegistry.html +3 -0
- package/docs/api/module-subscriptions_manager.html +3 -0
- package/docs/api/schema_validator.js.html +113 -0
- package/docs/api/scripts/core.js +726 -0
- package/docs/api/scripts/core.min.js +23 -0
- package/docs/api/scripts/resize.js +90 -0
- package/docs/api/scripts/search.js +265 -0
- package/docs/api/scripts/search.min.js +6 -0
- package/docs/api/scripts/third-party/Apache-License-2.0.txt +202 -0
- package/docs/api/scripts/third-party/fuse.js +9 -0
- package/docs/api/scripts/third-party/hljs-line-num-original.js +369 -0
- package/docs/api/scripts/third-party/hljs-line-num.js +1 -0
- package/docs/api/scripts/third-party/hljs-original.js +5171 -0
- package/docs/api/scripts/third-party/hljs.js +1 -0
- package/docs/api/scripts/third-party/popper.js +5 -0
- package/docs/api/scripts/third-party/tippy.js +1 -0
- package/docs/api/scripts/third-party/tocbot.js +672 -0
- package/docs/api/scripts/third-party/tocbot.min.js +1 -0
- package/docs/api/spatial_h3-operations.js.html +129 -0
- package/docs/api/storage_backend-factory.js.html +133 -0
- package/docs/api/storage_backend-interface.js.html +164 -0
- package/docs/api/storage_backends_activitypub-backend.js.html +298 -0
- package/docs/api/storage_backends_activitypub_server.js.html +678 -0
- package/docs/api/storage_backends_gundb-backend.js.html +878 -0
- package/docs/api/storage_backends_nostr-backend.js.html +254 -0
- package/docs/api/storage_filesystem-storage-browser.js.html +83 -0
- package/docs/api/storage_filesystem-storage.js.html +207 -0
- package/docs/api/storage_global-tables.js.html +116 -0
- package/docs/api/storage_gun-async.js.html +344 -0
- package/docs/api/storage_gun-auth.js.html +376 -0
- package/docs/api/storage_gun-federation.js.html +788 -0
- package/docs/api/storage_gun-references.js.html +212 -0
- package/docs/api/storage_gun-schema.js.html +309 -0
- package/docs/api/storage_gun-wrapper.js.html +645 -0
- package/docs/api/storage_indexeddb-storage.js.html +224 -0
- package/docs/api/storage_key-storage-simple.js.html +102 -0
- package/docs/api/storage_key-storage.js.html +171 -0
- package/docs/api/storage_memory-storage.js.html +128 -0
- package/docs/api/storage_migration.js.html +354 -0
- package/docs/api/storage_nostr-async.js.html +1076 -0
- package/docs/api/storage_nostr-client.js.html +1598 -0
- package/docs/api/storage_nostr-wrapper.js.html +218 -0
- package/docs/api/storage_outbox-queue.js.html +248 -0
- package/docs/api/storage_persistent-storage.js.html +160 -0
- package/docs/api/storage_sync-service.js.html +201 -0
- package/docs/api/storage_unified-storage.js.html +157 -0
- package/docs/api/styles/clean-jsdoc-theme-base.css +1159 -0
- package/docs/api/styles/clean-jsdoc-theme-dark.css +412 -0
- package/docs/api/styles/clean-jsdoc-theme-light.css +482 -0
- package/docs/api/styles/clean-jsdoc-theme-scrollbar.css +30 -0
- package/docs/api/styles/clean-jsdoc-theme-without-scrollbar.min.css +1 -0
- package/docs/api/styles/clean-jsdoc-theme.min.css +1 -0
- package/docs/api/subscriptions_manager.js.html +162 -0
- package/docs/contracts/api-interface.md +793 -0
- package/docs/data-model.md +476 -0
- package/docs/gun-async-usage.md +338 -0
- package/docs/plan.md +349 -0
- package/docs/quickstart.md +674 -0
- package/docs/research.md +362 -0
- package/docs/spec.md +244 -0
- package/docs/storage-backends.md +326 -0
- package/docs/tasks.md +947 -0
- package/examples/demo.html +47 -0
- package/examples/holosphere-widget.js +1242 -0
- package/examples/widget-demo.html +274 -0
- package/examples/widget.html +703 -0
- package/jsdoc.json +26 -0
- package/package.json +25 -7
- package/src/ai/aggregation.js +13 -2
- package/src/ai/breakdown.js +12 -2
- package/src/ai/classifier.js +14 -3
- package/src/ai/council.js +22 -7
- package/src/ai/embeddings.js +37 -15
- package/src/ai/federation-ai.js +13 -2
- package/src/ai/h3-ai.js +14 -2
- package/src/ai/index.js +16 -7
- package/src/ai/json-ops.js +18 -5
- package/src/ai/llm-service.js +62 -31
- package/src/ai/nl-query.js +12 -2
- package/src/ai/relationships.js +13 -2
- package/src/ai/schema-extractor.js +24 -10
- package/src/ai/spatial.js +13 -2
- package/src/ai/tts.js +25 -8
- package/src/cdn-entry.js +22 -0
- package/src/content/social-protocols.js +34 -25
- package/src/contracts/abis/Appreciative.json +1280 -0
- package/src/contracts/abis/AppreciativeFactory.json +101 -0
- package/src/contracts/abis/Bundle.json +1438 -0
- package/src/contracts/abis/BundleFactory.json +106 -0
- package/src/contracts/abis/Holon.json +881 -0
- package/src/contracts/abis/Holons.json +330 -0
- package/src/contracts/abis/Managed.json +1262 -0
- package/src/contracts/abis/ManagedFactory.json +149 -0
- package/src/contracts/abis/Membrane.json +261 -0
- package/src/contracts/abis/Splitter.json +1624 -0
- package/src/contracts/abis/SplitterFactory.json +220 -0
- package/src/contracts/abis/TestToken.json +321 -0
- package/src/contracts/abis/Zoned.json +1461 -0
- package/src/contracts/abis/ZonedFactory.json +154 -0
- package/src/contracts/chain-manager.js +403 -0
- package/src/contracts/deployer.js +500 -0
- package/src/contracts/event-listener.js +539 -0
- package/src/contracts/holon-contracts.js +359 -0
- package/src/contracts/index.js +82 -0
- package/src/contracts/networks.js +229 -0
- package/src/contracts/operations.js +687 -0
- package/src/contracts/queries.js +638 -0
- package/src/core/holosphere.js +487 -6
- package/src/crypto/nostr-utils.js +303 -0
- package/src/crypto/secp256k1.js +7 -2
- package/src/federation/handshake.js +475 -0
- package/src/federation/hologram.js +117 -3
- package/src/hierarchical/upcast.js +40 -25
- package/src/index.js +1501 -1909
- package/src/lib/ai-methods.js +657 -0
- package/src/lib/contract-methods.js +442 -0
- package/src/lib/errors.js +53 -0
- package/src/lib/federation-methods.js +345 -0
- package/src/lib/index.js +30 -0
- package/src/schema/validator.js +22 -3
- package/src/spatial/h3-operations.js +19 -3
- package/src/storage/backend-factory.js +7 -2
- package/src/storage/backend-interface.js +21 -2
- package/src/storage/backends/activitypub/server.js +25 -3
- package/src/storage/backends/activitypub-backend.js +25 -2
- package/src/storage/backends/gundb-backend.js +692 -50
- package/src/storage/backends/nostr-backend.js +116 -1
- package/src/storage/filesystem-storage-browser.js +42 -2
- package/src/storage/filesystem-storage.js +72 -5
- package/src/storage/global-tables.js +35 -3
- package/src/storage/gun-async.js +75 -15
- package/src/storage/gun-auth.js +373 -0
- package/src/storage/gun-federation.js +785 -0
- package/src/storage/gun-references.js +209 -0
- package/src/storage/gun-schema.js +306 -0
- package/src/storage/gun-wrapper.js +475 -54
- package/src/storage/indexeddb-storage.js +112 -13
- package/src/storage/key-storage-simple.js +32 -9
- package/src/storage/key-storage.js +45 -13
- package/src/storage/memory-storage.js +68 -2
- package/src/storage/migration.js +20 -7
- package/src/storage/nostr-async.js +412 -122
- package/src/storage/nostr-client.js +749 -76
- package/src/storage/nostr-wrapper.js +6 -2
- package/src/storage/outbox-queue.js +55 -18
- package/src/storage/persistent-storage.js +62 -14
- package/src/storage/sync-service.js +51 -17
- package/src/storage/unified-storage.js +154 -0
- package/src/subscriptions/manager.js +34 -17
- package/types/index.d.ts +133 -0
- package/vite.config.cdn.js +60 -0
- package/tests/unit/ai/aggregation.test.js +0 -295
- package/tests/unit/ai/breakdown.test.js +0 -446
- package/tests/unit/ai/classifier.test.js +0 -294
- package/tests/unit/ai/council.test.js +0 -262
- package/tests/unit/ai/embeddings.test.js +0 -384
- package/tests/unit/ai/federation-ai.test.js +0 -344
- package/tests/unit/ai/h3-ai.test.js +0 -458
- package/tests/unit/ai/index.test.js +0 -304
- package/tests/unit/ai/json-ops.test.js +0 -307
- package/tests/unit/ai/llm-service.test.js +0 -390
- package/tests/unit/ai/nl-query.test.js +0 -383
- package/tests/unit/ai/relationships.test.js +0 -311
- package/tests/unit/ai/schema-extractor.test.js +0 -384
- package/tests/unit/ai/spatial.test.js +0 -279
- package/tests/unit/ai/tts.test.js +0 -279
- package/tests/unit/content.test.js +0 -332
- package/tests/unit/contract/core.test.js +0 -88
- package/tests/unit/contract/crypto.test.js +0 -198
- package/tests/unit/contract/data.test.js +0 -223
- package/tests/unit/contract/federation.test.js +0 -181
- package/tests/unit/contract/hierarchical.test.js +0 -113
- package/tests/unit/contract/schema.test.js +0 -114
- package/tests/unit/contract/social.test.js +0 -217
- package/tests/unit/contract/spatial.test.js +0 -110
- package/tests/unit/contract/subscriptions.test.js +0 -128
- package/tests/unit/contract/utils.test.js +0 -159
- package/tests/unit/core.test.js +0 -152
- package/tests/unit/crypto.test.js +0 -328
- package/tests/unit/federation.test.js +0 -234
- package/tests/unit/gun-async.test.js +0 -252
- package/tests/unit/hierarchical.test.js +0 -399
- package/tests/unit/integration/scenario-01-geographic-storage.test.js +0 -74
- package/tests/unit/integration/scenario-02-federation.test.js +0 -76
- package/tests/unit/integration/scenario-03-subscriptions.test.js +0 -102
- package/tests/unit/integration/scenario-04-validation.test.js +0 -129
- package/tests/unit/integration/scenario-05-hierarchy.test.js +0 -125
- package/tests/unit/integration/scenario-06-social.test.js +0 -135
- package/tests/unit/integration/scenario-07-persistence.test.js +0 -130
- package/tests/unit/integration/scenario-08-authorization.test.js +0 -161
- package/tests/unit/integration/scenario-09-cross-dimensional.test.js +0 -139
- package/tests/unit/integration/scenario-10-cross-holosphere-capabilities.test.js +0 -357
- package/tests/unit/integration/scenario-11-cross-holosphere-federation.test.js +0 -410
- package/tests/unit/integration/scenario-12-capability-federated-read.test.js +0 -719
- package/tests/unit/performance/benchmark.test.js +0 -85
- package/tests/unit/schema.test.js +0 -213
- package/tests/unit/spatial.test.js +0 -158
- package/tests/unit/storage.test.js +0 -195
- package/tests/unit/subscriptions.test.js +0 -328
- package/tests/unit/test-data-permanence-debug.js +0 -197
- package/tests/unit/test-data-permanence.js +0 -340
- package/tests/unit/test-key-persistence-fixed.js +0 -148
- package/tests/unit/test-key-persistence.js +0 -172
- package/tests/unit/test-relay-permanence.js +0 -376
- package/tests/unit/test-second-node.js +0 -95
- package/tests/unit/test-simple-write.js +0 -89
- /package/{cleanup-test-data.js → scripts/cleanup-test-data.js} +0 -0
- /package/{test-ai-real-api.js → scripts/test-ai-real-api.js} +0 -0
|
@@ -1,719 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import HoloSphere from '../../../src/index.js';
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Scenario 12: Capability-Based Federated Data Access
|
|
6
|
-
*
|
|
7
|
-
* This test verifies that:
|
|
8
|
-
* 1. Capability tokens work correctly for read, write, and delete operations
|
|
9
|
-
* 2. The federation registry correctly stores and retrieves capabilities
|
|
10
|
-
* 3. Capability verification works for different permission levels
|
|
11
|
-
* 4. Scope matching works correctly (holon, lens, dataId levels)
|
|
12
|
-
*
|
|
13
|
-
* Note: In test environment with MemoryStorage, we use different appNames
|
|
14
|
-
* to simulate isolation between holospheres. In production with Nostr relays,
|
|
15
|
-
* isolation is enforced by author (public key) filtering.
|
|
16
|
-
*/
|
|
17
|
-
describe('Integration: Scenario 12 - Capability-Based Federated Read', () => {
|
|
18
|
-
// Three distinct private keys for three separate holospheres
|
|
19
|
-
const privateKeyA = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef';
|
|
20
|
-
const privateKeyB = 'fedcba9876543210fedcba9876543210fedcba9876543210fedcba9876543210';
|
|
21
|
-
const privateKeyC = 'abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789';
|
|
22
|
-
|
|
23
|
-
let holosphereA;
|
|
24
|
-
let holosphereB;
|
|
25
|
-
let holosphereC;
|
|
26
|
-
let publicKeyA;
|
|
27
|
-
let publicKeyB;
|
|
28
|
-
let publicKeyC;
|
|
29
|
-
let testHolon;
|
|
30
|
-
let testHolon2;
|
|
31
|
-
|
|
32
|
-
beforeEach(async () => {
|
|
33
|
-
// Create three independent holospheres with different appNames for isolation
|
|
34
|
-
// In production with Nostr, they would use same appName but different keys
|
|
35
|
-
holosphereA = new HoloSphere({
|
|
36
|
-
relays: [],
|
|
37
|
-
appName: 'scenario-12-a',
|
|
38
|
-
privateKey: privateKeyA,
|
|
39
|
-
logLevel: 'ERROR'
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
holosphereB = new HoloSphere({
|
|
43
|
-
relays: [],
|
|
44
|
-
appName: 'scenario-12-b',
|
|
45
|
-
privateKey: privateKeyB,
|
|
46
|
-
logLevel: 'ERROR'
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
holosphereC = new HoloSphere({
|
|
50
|
-
relays: [],
|
|
51
|
-
appName: 'scenario-12-c',
|
|
52
|
-
privateKey: privateKeyC,
|
|
53
|
-
logLevel: 'ERROR'
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
// Get public keys
|
|
57
|
-
publicKeyA = holosphereA.client.publicKey;
|
|
58
|
-
publicKeyB = holosphereB.client.publicKey;
|
|
59
|
-
publicKeyC = holosphereC.client.publicKey;
|
|
60
|
-
|
|
61
|
-
// Create test holons (H3 cells)
|
|
62
|
-
testHolon = await holosphereA.toHolon(37.7749, -122.4194, 9);
|
|
63
|
-
testHolon2 = await holosphereA.toHolon(40.7128, -74.0060, 9);
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
afterEach(async () => {
|
|
67
|
-
// Clean up
|
|
68
|
-
if (holosphereA?.client?.close) await holosphereA.client.close();
|
|
69
|
-
if (holosphereB?.client?.close) await holosphereB.client.close();
|
|
70
|
-
if (holosphereC?.client?.close) await holosphereC.client.close();
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe('Capability Token Permissions', () => {
|
|
74
|
-
it('should issue and verify capability token with READ permission', async () => {
|
|
75
|
-
const token = await holosphereA.issueCapability(
|
|
76
|
-
['read'],
|
|
77
|
-
{ holonId: testHolon, lensName: 'documents' },
|
|
78
|
-
publicKeyB,
|
|
79
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
80
|
-
);
|
|
81
|
-
|
|
82
|
-
expect(typeof token).toBe('string');
|
|
83
|
-
|
|
84
|
-
// Verify read permission is granted
|
|
85
|
-
const hasRead = await holosphereB.verifyCapability(token, 'read', {
|
|
86
|
-
holonId: testHolon,
|
|
87
|
-
lensName: 'documents'
|
|
88
|
-
});
|
|
89
|
-
expect(hasRead).toBe(true);
|
|
90
|
-
|
|
91
|
-
// Verify write permission is NOT granted
|
|
92
|
-
const hasWrite = await holosphereB.verifyCapability(token, 'write', {
|
|
93
|
-
holonId: testHolon,
|
|
94
|
-
lensName: 'documents'
|
|
95
|
-
});
|
|
96
|
-
expect(hasWrite).toBe(false);
|
|
97
|
-
|
|
98
|
-
// Verify delete permission is NOT granted
|
|
99
|
-
const hasDelete = await holosphereB.verifyCapability(token, 'delete', {
|
|
100
|
-
holonId: testHolon,
|
|
101
|
-
lensName: 'documents'
|
|
102
|
-
});
|
|
103
|
-
expect(hasDelete).toBe(false);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('should issue and verify capability token with WRITE permission', async () => {
|
|
107
|
-
const token = await holosphereA.issueCapability(
|
|
108
|
-
['write'],
|
|
109
|
-
{ holonId: testHolon, lensName: 'documents' },
|
|
110
|
-
publicKeyB,
|
|
111
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
const hasWrite = await holosphereB.verifyCapability(token, 'write', {
|
|
115
|
-
holonId: testHolon,
|
|
116
|
-
lensName: 'documents'
|
|
117
|
-
});
|
|
118
|
-
expect(hasWrite).toBe(true);
|
|
119
|
-
|
|
120
|
-
const hasRead = await holosphereB.verifyCapability(token, 'read', {
|
|
121
|
-
holonId: testHolon,
|
|
122
|
-
lensName: 'documents'
|
|
123
|
-
});
|
|
124
|
-
expect(hasRead).toBe(false);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
it('should issue and verify capability token with DELETE permission', async () => {
|
|
128
|
-
const token = await holosphereA.issueCapability(
|
|
129
|
-
['delete'],
|
|
130
|
-
{ holonId: testHolon, lensName: 'documents' },
|
|
131
|
-
publicKeyB,
|
|
132
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const hasDelete = await holosphereB.verifyCapability(token, 'delete', {
|
|
136
|
-
holonId: testHolon,
|
|
137
|
-
lensName: 'documents'
|
|
138
|
-
});
|
|
139
|
-
expect(hasDelete).toBe(true);
|
|
140
|
-
|
|
141
|
-
const hasWrite = await holosphereB.verifyCapability(token, 'write', {
|
|
142
|
-
holonId: testHolon,
|
|
143
|
-
lensName: 'documents'
|
|
144
|
-
});
|
|
145
|
-
expect(hasWrite).toBe(false);
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it('should issue capability token with ALL permissions (read, write, delete)', async () => {
|
|
149
|
-
const token = await holosphereA.issueCapability(
|
|
150
|
-
['read', 'write', 'delete'],
|
|
151
|
-
{ holonId: testHolon, lensName: 'documents' },
|
|
152
|
-
publicKeyB,
|
|
153
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
154
|
-
);
|
|
155
|
-
|
|
156
|
-
const hasRead = await holosphereB.verifyCapability(token, 'read', {
|
|
157
|
-
holonId: testHolon,
|
|
158
|
-
lensName: 'documents'
|
|
159
|
-
});
|
|
160
|
-
expect(hasRead).toBe(true);
|
|
161
|
-
|
|
162
|
-
const hasWrite = await holosphereB.verifyCapability(token, 'write', {
|
|
163
|
-
holonId: testHolon,
|
|
164
|
-
lensName: 'documents'
|
|
165
|
-
});
|
|
166
|
-
expect(hasWrite).toBe(true);
|
|
167
|
-
|
|
168
|
-
const hasDelete = await holosphereB.verifyCapability(token, 'delete', {
|
|
169
|
-
holonId: testHolon,
|
|
170
|
-
lensName: 'documents'
|
|
171
|
-
});
|
|
172
|
-
expect(hasDelete).toBe(true);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
it('should reject expired capability tokens', async () => {
|
|
176
|
-
const expiredToken = await holosphereA.issueCapability(
|
|
177
|
-
['read', 'write', 'delete'],
|
|
178
|
-
{ holonId: testHolon, lensName: 'documents' },
|
|
179
|
-
publicKeyB,
|
|
180
|
-
{ expiresIn: -1000, issuerKey: privateKeyA } // Already expired
|
|
181
|
-
);
|
|
182
|
-
|
|
183
|
-
const hasRead = await holosphereB.verifyCapability(expiredToken, 'read', {
|
|
184
|
-
holonId: testHolon,
|
|
185
|
-
lensName: 'documents'
|
|
186
|
-
});
|
|
187
|
-
expect(hasRead).toBe(false);
|
|
188
|
-
|
|
189
|
-
const hasWrite = await holosphereB.verifyCapability(expiredToken, 'write', {
|
|
190
|
-
holonId: testHolon,
|
|
191
|
-
lensName: 'documents'
|
|
192
|
-
});
|
|
193
|
-
expect(hasWrite).toBe(false);
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
describe('Write Operations with Capability Tokens', () => {
|
|
198
|
-
it('should allow write operation with valid write capability token', async () => {
|
|
199
|
-
// A issues write capability to B
|
|
200
|
-
const writeToken = await holosphereA.issueCapability(
|
|
201
|
-
['write'],
|
|
202
|
-
{ holonId: testHolon, lensName: 'shared' },
|
|
203
|
-
publicKeyB,
|
|
204
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
// B writes data using the capability token
|
|
208
|
-
await holosphereB.write(testHolon, 'shared', {
|
|
209
|
-
id: 'item-from-b',
|
|
210
|
-
content: 'Written by B with capability',
|
|
211
|
-
author: publicKeyB
|
|
212
|
-
}, { capability: writeToken });
|
|
213
|
-
|
|
214
|
-
// B can read their own data
|
|
215
|
-
const data = await holosphereB.read(testHolon, 'shared', 'item-from-b');
|
|
216
|
-
expect(data).toBeDefined();
|
|
217
|
-
expect(data.content).toBe('Written by B with capability');
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
it('should reject write with invalid capability token', async () => {
|
|
221
|
-
// Create an invalid token (for wrong scope)
|
|
222
|
-
const wrongScopeToken = await holosphereA.issueCapability(
|
|
223
|
-
['write'],
|
|
224
|
-
{ holonId: testHolon, lensName: 'other-lens' },
|
|
225
|
-
publicKeyB,
|
|
226
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
// Verify token is invalid for 'shared' lens
|
|
230
|
-
const isValid = await holosphereB.verifyCapability(wrongScopeToken, 'write', {
|
|
231
|
-
holonId: testHolon,
|
|
232
|
-
lensName: 'shared'
|
|
233
|
-
});
|
|
234
|
-
expect(isValid).toBe(false);
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should reject write with read-only capability token', async () => {
|
|
238
|
-
const readOnlyToken = await holosphereA.issueCapability(
|
|
239
|
-
['read'],
|
|
240
|
-
{ holonId: testHolon, lensName: 'protected' },
|
|
241
|
-
publicKeyB,
|
|
242
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
// Verify token doesn't have write permission
|
|
246
|
-
const hasWrite = await holosphereB.verifyCapability(readOnlyToken, 'write', {
|
|
247
|
-
holonId: testHolon,
|
|
248
|
-
lensName: 'protected'
|
|
249
|
-
});
|
|
250
|
-
expect(hasWrite).toBe(false);
|
|
251
|
-
});
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
describe('Delete Operations with Capability Tokens', () => {
|
|
255
|
-
it('should allow delete operation with valid delete capability token', async () => {
|
|
256
|
-
// A writes data
|
|
257
|
-
await holosphereA.write(testHolon, 'deletable', {
|
|
258
|
-
id: 'to-delete',
|
|
259
|
-
content: 'This will be deleted'
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Verify data exists
|
|
263
|
-
const exists = await holosphereA.read(testHolon, 'deletable', 'to-delete');
|
|
264
|
-
expect(exists).toBeDefined();
|
|
265
|
-
|
|
266
|
-
// A issues delete capability to B
|
|
267
|
-
const deleteToken = await holosphereA.issueCapability(
|
|
268
|
-
['delete'],
|
|
269
|
-
{ holonId: testHolon, lensName: 'deletable' },
|
|
270
|
-
publicKeyB,
|
|
271
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
272
|
-
);
|
|
273
|
-
|
|
274
|
-
// Verify B has delete permission
|
|
275
|
-
const hasDelete = await holosphereB.verifyCapability(deleteToken, 'delete', {
|
|
276
|
-
holonId: testHolon,
|
|
277
|
-
lensName: 'deletable'
|
|
278
|
-
});
|
|
279
|
-
expect(hasDelete).toBe(true);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
it('should reject delete with write-only capability token', async () => {
|
|
283
|
-
const writeOnlyToken = await holosphereA.issueCapability(
|
|
284
|
-
['write'],
|
|
285
|
-
{ holonId: testHolon, lensName: 'no-delete' },
|
|
286
|
-
publicKeyB,
|
|
287
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
// Verify token doesn't have delete permission
|
|
291
|
-
const hasDelete = await holosphereB.verifyCapability(writeOnlyToken, 'delete', {
|
|
292
|
-
holonId: testHolon,
|
|
293
|
-
lensName: 'no-delete'
|
|
294
|
-
});
|
|
295
|
-
expect(hasDelete).toBe(false);
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
describe('Federation Registry Operations', () => {
|
|
300
|
-
it('should store and retrieve inbound capability', async () => {
|
|
301
|
-
// A issues capability to B
|
|
302
|
-
const readToken = await holosphereA.issueCapability(
|
|
303
|
-
['read'],
|
|
304
|
-
{ holonId: testHolon, lensName: 'federated-docs' },
|
|
305
|
-
publicKeyB,
|
|
306
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
307
|
-
);
|
|
308
|
-
|
|
309
|
-
// B stores the capability
|
|
310
|
-
await holosphereB.storeInboundCapability(publicKeyA, {
|
|
311
|
-
token: readToken,
|
|
312
|
-
scope: { holonId: testHolon, lensName: 'federated-docs' },
|
|
313
|
-
permissions: ['read'],
|
|
314
|
-
expires: Date.now() + 3600000
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
// B can verify the stored capability
|
|
318
|
-
const isValid = await holosphereB.verifyCapability(readToken, 'read', {
|
|
319
|
-
holonId: testHolon,
|
|
320
|
-
lensName: 'federated-docs'
|
|
321
|
-
});
|
|
322
|
-
expect(isValid).toBe(true);
|
|
323
|
-
});
|
|
324
|
-
|
|
325
|
-
it('should store capabilities from multiple partners', async () => {
|
|
326
|
-
// A issues capability to C
|
|
327
|
-
const tokenFromA = await holosphereA.issueCapability(
|
|
328
|
-
['read'],
|
|
329
|
-
{ holonId: testHolon, lensName: 'multi-partner' },
|
|
330
|
-
publicKeyC,
|
|
331
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
332
|
-
);
|
|
333
|
-
|
|
334
|
-
// B issues capability to C
|
|
335
|
-
const tokenFromB = await holosphereB.issueCapability(
|
|
336
|
-
['read', 'write'],
|
|
337
|
-
{ holonId: testHolon, lensName: 'multi-partner' },
|
|
338
|
-
publicKeyC,
|
|
339
|
-
{ expiresIn: 3600000, issuerKey: privateKeyB }
|
|
340
|
-
);
|
|
341
|
-
|
|
342
|
-
// C stores both capabilities
|
|
343
|
-
await holosphereC.storeInboundCapability(publicKeyA, {
|
|
344
|
-
token: tokenFromA,
|
|
345
|
-
scope: { holonId: testHolon, lensName: 'multi-partner' },
|
|
346
|
-
permissions: ['read'],
|
|
347
|
-
expires: Date.now() + 3600000
|
|
348
|
-
});
|
|
349
|
-
|
|
350
|
-
await holosphereC.storeInboundCapability(publicKeyB, {
|
|
351
|
-
token: tokenFromB,
|
|
352
|
-
scope: { holonId: testHolon, lensName: 'multi-partner' },
|
|
353
|
-
permissions: ['read', 'write'],
|
|
354
|
-
expires: Date.now() + 3600000
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// C can verify both capabilities
|
|
358
|
-
const validFromA = await holosphereC.verifyCapability(tokenFromA, 'read', {
|
|
359
|
-
holonId: testHolon,
|
|
360
|
-
lensName: 'multi-partner'
|
|
361
|
-
});
|
|
362
|
-
expect(validFromA).toBe(true);
|
|
363
|
-
|
|
364
|
-
const validFromB = await holosphereC.verifyCapability(tokenFromB, 'write', {
|
|
365
|
-
holonId: testHolon,
|
|
366
|
-
lensName: 'multi-partner'
|
|
367
|
-
});
|
|
368
|
-
expect(validFromB).toBe(true);
|
|
369
|
-
});
|
|
370
|
-
});
|
|
371
|
-
|
|
372
|
-
describe('Scope Matching for Capabilities', () => {
|
|
373
|
-
it('should validate capability only for correct holon scope', async () => {
|
|
374
|
-
// Token for testHolon only
|
|
375
|
-
const token = await holosphereA.issueCapability(
|
|
376
|
-
['read'],
|
|
377
|
-
{ holonId: testHolon, lensName: 'scoped' },
|
|
378
|
-
publicKeyB,
|
|
379
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
380
|
-
);
|
|
381
|
-
|
|
382
|
-
// Valid for testHolon
|
|
383
|
-
const validForHolon1 = await holosphereB.verifyCapability(token, 'read', {
|
|
384
|
-
holonId: testHolon,
|
|
385
|
-
lensName: 'scoped'
|
|
386
|
-
});
|
|
387
|
-
expect(validForHolon1).toBe(true);
|
|
388
|
-
|
|
389
|
-
// Invalid for testHolon2
|
|
390
|
-
const validForHolon2 = await holosphereB.verifyCapability(token, 'read', {
|
|
391
|
-
holonId: testHolon2,
|
|
392
|
-
lensName: 'scoped'
|
|
393
|
-
});
|
|
394
|
-
expect(validForHolon2).toBe(false);
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
it('should validate capability only for correct lens scope', async () => {
|
|
398
|
-
// Token for lens-a only
|
|
399
|
-
const token = await holosphereA.issueCapability(
|
|
400
|
-
['read'],
|
|
401
|
-
{ holonId: testHolon, lensName: 'lens-a' },
|
|
402
|
-
publicKeyB,
|
|
403
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
404
|
-
);
|
|
405
|
-
|
|
406
|
-
// Valid for lens-a
|
|
407
|
-
const validForLensA = await holosphereB.verifyCapability(token, 'read', {
|
|
408
|
-
holonId: testHolon,
|
|
409
|
-
lensName: 'lens-a'
|
|
410
|
-
});
|
|
411
|
-
expect(validForLensA).toBe(true);
|
|
412
|
-
|
|
413
|
-
// Invalid for lens-b
|
|
414
|
-
const validForLensB = await holosphereB.verifyCapability(token, 'read', {
|
|
415
|
-
holonId: testHolon,
|
|
416
|
-
lensName: 'lens-b'
|
|
417
|
-
});
|
|
418
|
-
expect(validForLensB).toBe(false);
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
it('should support wildcard holon scope (*)', async () => {
|
|
422
|
-
// Token with wildcard holon
|
|
423
|
-
const wildcardToken = await holosphereA.issueCapability(
|
|
424
|
-
['read'],
|
|
425
|
-
{ holonId: '*', lensName: 'global' },
|
|
426
|
-
publicKeyB,
|
|
427
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
428
|
-
);
|
|
429
|
-
|
|
430
|
-
// Valid for any holon
|
|
431
|
-
const validForHolon1 = await holosphereB.verifyCapability(wildcardToken, 'read', {
|
|
432
|
-
holonId: testHolon,
|
|
433
|
-
lensName: 'global'
|
|
434
|
-
});
|
|
435
|
-
expect(validForHolon1).toBe(true);
|
|
436
|
-
|
|
437
|
-
const validForHolon2 = await holosphereB.verifyCapability(wildcardToken, 'read', {
|
|
438
|
-
holonId: testHolon2,
|
|
439
|
-
lensName: 'global'
|
|
440
|
-
});
|
|
441
|
-
expect(validForHolon2).toBe(true);
|
|
442
|
-
|
|
443
|
-
// But still restricted to 'global' lens
|
|
444
|
-
const invalidForOtherLens = await holosphereB.verifyCapability(wildcardToken, 'read', {
|
|
445
|
-
holonId: testHolon,
|
|
446
|
-
lensName: 'other-lens'
|
|
447
|
-
});
|
|
448
|
-
expect(invalidForOtherLens).toBe(false);
|
|
449
|
-
});
|
|
450
|
-
|
|
451
|
-
it('should support wildcard lens scope (*)', async () => {
|
|
452
|
-
// Token with wildcard lens
|
|
453
|
-
const wildcardToken = await holosphereA.issueCapability(
|
|
454
|
-
['read'],
|
|
455
|
-
{ holonId: testHolon, lensName: '*' },
|
|
456
|
-
publicKeyB,
|
|
457
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
458
|
-
);
|
|
459
|
-
|
|
460
|
-
// Valid for any lens in testHolon
|
|
461
|
-
const validForLensA = await holosphereB.verifyCapability(wildcardToken, 'read', {
|
|
462
|
-
holonId: testHolon,
|
|
463
|
-
lensName: 'lens-a'
|
|
464
|
-
});
|
|
465
|
-
expect(validForLensA).toBe(true);
|
|
466
|
-
|
|
467
|
-
const validForLensB = await holosphereB.verifyCapability(wildcardToken, 'read', {
|
|
468
|
-
holonId: testHolon,
|
|
469
|
-
lensName: 'lens-b'
|
|
470
|
-
});
|
|
471
|
-
expect(validForLensB).toBe(true);
|
|
472
|
-
|
|
473
|
-
// But still restricted to testHolon
|
|
474
|
-
const invalidForOtherHolon = await holosphereB.verifyCapability(wildcardToken, 'read', {
|
|
475
|
-
holonId: testHolon2,
|
|
476
|
-
lensName: 'lens-a'
|
|
477
|
-
});
|
|
478
|
-
expect(invalidForOtherHolon).toBe(false);
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
it('should support full wildcard scope (*, *)', async () => {
|
|
482
|
-
// Token with full wildcard - access to all holons and lenses
|
|
483
|
-
const fullWildcardToken = await holosphereA.issueCapability(
|
|
484
|
-
['read'],
|
|
485
|
-
{ holonId: '*', lensName: '*' },
|
|
486
|
-
publicKeyB,
|
|
487
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
488
|
-
);
|
|
489
|
-
|
|
490
|
-
// Valid for any holon and lens combination
|
|
491
|
-
const valid1 = await holosphereB.verifyCapability(fullWildcardToken, 'read', {
|
|
492
|
-
holonId: testHolon,
|
|
493
|
-
lensName: 'lens-a'
|
|
494
|
-
});
|
|
495
|
-
expect(valid1).toBe(true);
|
|
496
|
-
|
|
497
|
-
const valid2 = await holosphereB.verifyCapability(fullWildcardToken, 'read', {
|
|
498
|
-
holonId: testHolon2,
|
|
499
|
-
lensName: 'lens-b'
|
|
500
|
-
});
|
|
501
|
-
expect(valid2).toBe(true);
|
|
502
|
-
});
|
|
503
|
-
|
|
504
|
-
it('should support dataId-specific scope', async () => {
|
|
505
|
-
// Token for specific item only
|
|
506
|
-
const itemToken = await holosphereA.issueCapability(
|
|
507
|
-
['read'],
|
|
508
|
-
{ holonId: testHolon, lensName: 'items', dataId: 'item-2' },
|
|
509
|
-
publicKeyB,
|
|
510
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
511
|
-
);
|
|
512
|
-
|
|
513
|
-
// Valid for item-2
|
|
514
|
-
const validForItem2 = await holosphereB.verifyCapability(itemToken, 'read', {
|
|
515
|
-
holonId: testHolon,
|
|
516
|
-
lensName: 'items',
|
|
517
|
-
dataId: 'item-2'
|
|
518
|
-
});
|
|
519
|
-
expect(validForItem2).toBe(true);
|
|
520
|
-
|
|
521
|
-
// Invalid for item-1
|
|
522
|
-
const validForItem1 = await holosphereB.verifyCapability(itemToken, 'read', {
|
|
523
|
-
holonId: testHolon,
|
|
524
|
-
lensName: 'items',
|
|
525
|
-
dataId: 'item-1'
|
|
526
|
-
});
|
|
527
|
-
expect(validForItem1).toBe(false);
|
|
528
|
-
});
|
|
529
|
-
});
|
|
530
|
-
|
|
531
|
-
describe('Complete Capability Workflow', () => {
|
|
532
|
-
it('should complete full capability workflow: issue -> verify -> use', async () => {
|
|
533
|
-
// === STEP 1: A issues full capability (read, write, delete) to B ===
|
|
534
|
-
const fullCapability = await holosphereA.issueCapability(
|
|
535
|
-
['read', 'write', 'delete'],
|
|
536
|
-
{ holonId: testHolon, lensName: 'workflow-test' },
|
|
537
|
-
publicKeyB,
|
|
538
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
539
|
-
);
|
|
540
|
-
|
|
541
|
-
expect(typeof fullCapability).toBe('string');
|
|
542
|
-
|
|
543
|
-
// === STEP 2: B stores the capability ===
|
|
544
|
-
await holosphereB.storeInboundCapability(publicKeyA, {
|
|
545
|
-
token: fullCapability,
|
|
546
|
-
scope: { holonId: testHolon, lensName: 'workflow-test' },
|
|
547
|
-
permissions: ['read', 'write', 'delete'],
|
|
548
|
-
expires: Date.now() + 3600000
|
|
549
|
-
});
|
|
550
|
-
|
|
551
|
-
// === STEP 3: B verifies all permissions ===
|
|
552
|
-
const hasRead = await holosphereB.verifyCapability(fullCapability, 'read', {
|
|
553
|
-
holonId: testHolon,
|
|
554
|
-
lensName: 'workflow-test'
|
|
555
|
-
});
|
|
556
|
-
expect(hasRead).toBe(true);
|
|
557
|
-
|
|
558
|
-
const hasWrite = await holosphereB.verifyCapability(fullCapability, 'write', {
|
|
559
|
-
holonId: testHolon,
|
|
560
|
-
lensName: 'workflow-test'
|
|
561
|
-
});
|
|
562
|
-
expect(hasWrite).toBe(true);
|
|
563
|
-
|
|
564
|
-
const hasDelete = await holosphereB.verifyCapability(fullCapability, 'delete', {
|
|
565
|
-
holonId: testHolon,
|
|
566
|
-
lensName: 'workflow-test'
|
|
567
|
-
});
|
|
568
|
-
expect(hasDelete).toBe(true);
|
|
569
|
-
|
|
570
|
-
// === STEP 4: B can write data with capability ===
|
|
571
|
-
await holosphereB.write(testHolon, 'workflow-test', {
|
|
572
|
-
id: 'b-contribution',
|
|
573
|
-
title: 'B Contribution',
|
|
574
|
-
content: 'Added by B with capability',
|
|
575
|
-
contributor: publicKeyB
|
|
576
|
-
}, { capability: fullCapability });
|
|
577
|
-
|
|
578
|
-
// Verify write worked
|
|
579
|
-
const bContrib = await holosphereB.read(testHolon, 'workflow-test', 'b-contribution');
|
|
580
|
-
expect(bContrib).toBeDefined();
|
|
581
|
-
expect(bContrib.title).toBe('B Contribution');
|
|
582
|
-
|
|
583
|
-
// === STEP 5: B deletes with capability ===
|
|
584
|
-
const deleteResult = await holosphereB.delete(testHolon, 'workflow-test', 'b-contribution', {
|
|
585
|
-
capability: fullCapability
|
|
586
|
-
});
|
|
587
|
-
expect(deleteResult).toBe(true);
|
|
588
|
-
|
|
589
|
-
// Verify deletion
|
|
590
|
-
const deleted = await holosphereB.read(testHolon, 'workflow-test', 'b-contribution');
|
|
591
|
-
expect(deleted).toBeNull();
|
|
592
|
-
});
|
|
593
|
-
|
|
594
|
-
it('should properly isolate data between holospheres (different appNames)', async () => {
|
|
595
|
-
// A writes data
|
|
596
|
-
await holosphereA.write(testHolon, 'isolated', {
|
|
597
|
-
id: 'a-data',
|
|
598
|
-
content: 'From A',
|
|
599
|
-
owner: publicKeyA
|
|
600
|
-
});
|
|
601
|
-
|
|
602
|
-
// B writes data
|
|
603
|
-
await holosphereB.write(testHolon, 'isolated', {
|
|
604
|
-
id: 'b-data',
|
|
605
|
-
content: 'From B',
|
|
606
|
-
owner: publicKeyB
|
|
607
|
-
});
|
|
608
|
-
|
|
609
|
-
// A can only see A's data
|
|
610
|
-
const aData = await holosphereA.read(testHolon, 'isolated', 'a-data');
|
|
611
|
-
expect(aData).toBeDefined();
|
|
612
|
-
expect(aData.content).toBe('From A');
|
|
613
|
-
|
|
614
|
-
const aSeesB = await holosphereA.read(testHolon, 'isolated', 'b-data');
|
|
615
|
-
expect(aSeesB).toBeNull(); // Different appName
|
|
616
|
-
|
|
617
|
-
// B can only see B's data
|
|
618
|
-
const bData = await holosphereB.read(testHolon, 'isolated', 'b-data');
|
|
619
|
-
expect(bData).toBeDefined();
|
|
620
|
-
expect(bData.content).toBe('From B');
|
|
621
|
-
|
|
622
|
-
const bSeesA = await holosphereB.read(testHolon, 'isolated', 'a-data');
|
|
623
|
-
expect(bSeesA).toBeNull(); // Different appName
|
|
624
|
-
});
|
|
625
|
-
});
|
|
626
|
-
|
|
627
|
-
describe('Capability Token Security', () => {
|
|
628
|
-
it('should not allow capability reuse for different scope', async () => {
|
|
629
|
-
const token = await holosphereA.issueCapability(
|
|
630
|
-
['read', 'write', 'delete'],
|
|
631
|
-
{ holonId: testHolon, lensName: 'specific-lens' },
|
|
632
|
-
publicKeyB,
|
|
633
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
634
|
-
);
|
|
635
|
-
|
|
636
|
-
// Token is valid for specific-lens
|
|
637
|
-
const validForSpecific = await holosphereB.verifyCapability(token, 'read', {
|
|
638
|
-
holonId: testHolon,
|
|
639
|
-
lensName: 'specific-lens'
|
|
640
|
-
});
|
|
641
|
-
expect(validForSpecific).toBe(true);
|
|
642
|
-
|
|
643
|
-
// Token is NOT valid for different-lens
|
|
644
|
-
const validForDifferent = await holosphereB.verifyCapability(token, 'read', {
|
|
645
|
-
holonId: testHolon,
|
|
646
|
-
lensName: 'different-lens'
|
|
647
|
-
});
|
|
648
|
-
expect(validForDifferent).toBe(false);
|
|
649
|
-
|
|
650
|
-
// Token is NOT valid for different holon
|
|
651
|
-
const validForDifferentHolon = await holosphereB.verifyCapability(token, 'read', {
|
|
652
|
-
holonId: testHolon2,
|
|
653
|
-
lensName: 'specific-lens'
|
|
654
|
-
});
|
|
655
|
-
expect(validForDifferentHolon).toBe(false);
|
|
656
|
-
});
|
|
657
|
-
|
|
658
|
-
it('should enforce permission restrictions', async () => {
|
|
659
|
-
// Issue read-only token
|
|
660
|
-
const readOnlyToken = await holosphereA.issueCapability(
|
|
661
|
-
['read'],
|
|
662
|
-
{ holonId: testHolon, lensName: 'read-only' },
|
|
663
|
-
publicKeyB,
|
|
664
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
665
|
-
);
|
|
666
|
-
|
|
667
|
-
// Has read
|
|
668
|
-
expect(await holosphereB.verifyCapability(readOnlyToken, 'read', {
|
|
669
|
-
holonId: testHolon,
|
|
670
|
-
lensName: 'read-only'
|
|
671
|
-
})).toBe(true);
|
|
672
|
-
|
|
673
|
-
// Does NOT have write
|
|
674
|
-
expect(await holosphereB.verifyCapability(readOnlyToken, 'write', {
|
|
675
|
-
holonId: testHolon,
|
|
676
|
-
lensName: 'read-only'
|
|
677
|
-
})).toBe(false);
|
|
678
|
-
|
|
679
|
-
// Does NOT have delete
|
|
680
|
-
expect(await holosphereB.verifyCapability(readOnlyToken, 'delete', {
|
|
681
|
-
holonId: testHolon,
|
|
682
|
-
lensName: 'read-only'
|
|
683
|
-
})).toBe(false);
|
|
684
|
-
});
|
|
685
|
-
|
|
686
|
-
it('should have unique nonce per token (replay protection)', async () => {
|
|
687
|
-
// Issue two tokens with same parameters
|
|
688
|
-
const token1 = await holosphereA.issueCapability(
|
|
689
|
-
['read'],
|
|
690
|
-
{ holonId: testHolon, lensName: 'replay-test' },
|
|
691
|
-
publicKeyB,
|
|
692
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
693
|
-
);
|
|
694
|
-
|
|
695
|
-
const token2 = await holosphereA.issueCapability(
|
|
696
|
-
['read'],
|
|
697
|
-
{ holonId: testHolon, lensName: 'replay-test' },
|
|
698
|
-
publicKeyB,
|
|
699
|
-
{ expiresIn: 3600000, issuerKey: privateKeyA }
|
|
700
|
-
);
|
|
701
|
-
|
|
702
|
-
// Tokens should be different (different nonces)
|
|
703
|
-
expect(token1).not.toBe(token2);
|
|
704
|
-
|
|
705
|
-
// But both should be valid
|
|
706
|
-
const valid1 = await holosphereB.verifyCapability(token1, 'read', {
|
|
707
|
-
holonId: testHolon,
|
|
708
|
-
lensName: 'replay-test'
|
|
709
|
-
});
|
|
710
|
-
const valid2 = await holosphereB.verifyCapability(token2, 'read', {
|
|
711
|
-
holonId: testHolon,
|
|
712
|
-
lensName: 'replay-test'
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
expect(valid1).toBe(true);
|
|
716
|
-
expect(valid2).toBe(true);
|
|
717
|
-
});
|
|
718
|
-
});
|
|
719
|
-
});
|