society-protocol 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (271) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/adapters.d.ts +101 -0
  4. package/dist/adapters.d.ts.map +1 -0
  5. package/dist/adapters.js +764 -0
  6. package/dist/adapters.js.map +1 -0
  7. package/dist/agents-md.d.ts +59 -0
  8. package/dist/agents-md.d.ts.map +1 -0
  9. package/dist/agents-md.js +204 -0
  10. package/dist/agents-md.js.map +1 -0
  11. package/dist/autoconfig.d.ts +137 -0
  12. package/dist/autoconfig.d.ts.map +1 -0
  13. package/dist/autoconfig.js +452 -0
  14. package/dist/autoconfig.js.map +1 -0
  15. package/dist/bootstrap.d.ts +68 -0
  16. package/dist/bootstrap.d.ts.map +1 -0
  17. package/dist/bootstrap.js +304 -0
  18. package/dist/bootstrap.js.map +1 -0
  19. package/dist/bridges/a2a-bridge.d.ts +156 -0
  20. package/dist/bridges/a2a-bridge.d.ts.map +1 -0
  21. package/dist/bridges/a2a-bridge.js +337 -0
  22. package/dist/bridges/a2a-bridge.js.map +1 -0
  23. package/dist/bridges/mcp-bridge.d.ts +87 -0
  24. package/dist/bridges/mcp-bridge.d.ts.map +1 -0
  25. package/dist/bridges/mcp-bridge.js +332 -0
  26. package/dist/bridges/mcp-bridge.js.map +1 -0
  27. package/dist/cache.d.ts +130 -0
  28. package/dist/cache.d.ts.map +1 -0
  29. package/dist/cache.js +257 -0
  30. package/dist/cache.js.map +1 -0
  31. package/dist/capsules.d.ts +23 -0
  32. package/dist/capsules.d.ts.map +1 -0
  33. package/dist/capsules.js +75 -0
  34. package/dist/capsules.js.map +1 -0
  35. package/dist/cli/commands.d.ts +8 -0
  36. package/dist/cli/commands.d.ts.map +1 -0
  37. package/dist/cli/commands.js +263 -0
  38. package/dist/cli/commands.js.map +1 -0
  39. package/dist/coc.d.ts +121 -0
  40. package/dist/coc.d.ts.map +1 -0
  41. package/dist/coc.js +629 -0
  42. package/dist/coc.js.map +1 -0
  43. package/dist/coc.test.d.ts +2 -0
  44. package/dist/coc.test.d.ts.map +1 -0
  45. package/dist/coc.test.js +80 -0
  46. package/dist/coc.test.js.map +1 -0
  47. package/dist/compression.d.ts +125 -0
  48. package/dist/compression.d.ts.map +1 -0
  49. package/dist/compression.js +573 -0
  50. package/dist/compression.js.map +1 -0
  51. package/dist/cot-stream.d.ts +220 -0
  52. package/dist/cot-stream.d.ts.map +1 -0
  53. package/dist/cot-stream.js +673 -0
  54. package/dist/cot-stream.js.map +1 -0
  55. package/dist/crypto-wasm.d.ts +100 -0
  56. package/dist/crypto-wasm.d.ts.map +1 -0
  57. package/dist/crypto-wasm.js +229 -0
  58. package/dist/crypto-wasm.js.map +1 -0
  59. package/dist/federation.d.ts +200 -0
  60. package/dist/federation.d.ts.map +1 -0
  61. package/dist/federation.js +691 -0
  62. package/dist/federation.js.map +1 -0
  63. package/dist/federation.test.d.ts +2 -0
  64. package/dist/federation.test.d.ts.map +1 -0
  65. package/dist/federation.test.js +71 -0
  66. package/dist/federation.test.js.map +1 -0
  67. package/dist/gateway/capability-router.d.ts +77 -0
  68. package/dist/gateway/capability-router.d.ts.map +1 -0
  69. package/dist/gateway/capability-router.js +222 -0
  70. package/dist/gateway/capability-router.js.map +1 -0
  71. package/dist/gateway/demand-spawner.d.ts +155 -0
  72. package/dist/gateway/demand-spawner.d.ts.map +1 -0
  73. package/dist/gateway/demand-spawner.js +426 -0
  74. package/dist/gateway/demand-spawner.js.map +1 -0
  75. package/dist/identity.d.ts +46 -0
  76. package/dist/identity.d.ts.map +1 -0
  77. package/dist/identity.js +102 -0
  78. package/dist/identity.js.map +1 -0
  79. package/dist/identity.test.d.ts +2 -0
  80. package/dist/identity.test.d.ts.map +1 -0
  81. package/dist/identity.test.js +45 -0
  82. package/dist/identity.test.js.map +1 -0
  83. package/dist/index.d.ts +36 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +1572 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/integration.d.ts +210 -0
  88. package/dist/integration.d.ts.map +1 -0
  89. package/dist/integration.js +1105 -0
  90. package/dist/integration.js.map +1 -0
  91. package/dist/integration.test.d.ts +2 -0
  92. package/dist/integration.test.d.ts.map +1 -0
  93. package/dist/integration.test.js +155 -0
  94. package/dist/integration.test.js.map +1 -0
  95. package/dist/knowledge.d.ts +219 -0
  96. package/dist/knowledge.d.ts.map +1 -0
  97. package/dist/knowledge.js +543 -0
  98. package/dist/knowledge.js.map +1 -0
  99. package/dist/knowledge.test.d.ts +2 -0
  100. package/dist/knowledge.test.d.ts.map +1 -0
  101. package/dist/knowledge.test.js +72 -0
  102. package/dist/knowledge.test.js.map +1 -0
  103. package/dist/latent-space.d.ts +178 -0
  104. package/dist/latent-space.d.ts.map +1 -0
  105. package/dist/latent-space.js +385 -0
  106. package/dist/latent-space.js.map +1 -0
  107. package/dist/lib.d.ts +30 -0
  108. package/dist/lib.d.ts.map +1 -0
  109. package/dist/lib.js +30 -0
  110. package/dist/lib.js.map +1 -0
  111. package/dist/mcp/server.d.ts +74 -0
  112. package/dist/mcp/server.d.ts.map +1 -0
  113. package/dist/mcp/server.js +1392 -0
  114. package/dist/mcp/server.js.map +1 -0
  115. package/dist/metrics.d.ts +98 -0
  116. package/dist/metrics.d.ts.map +1 -0
  117. package/dist/metrics.js +222 -0
  118. package/dist/metrics.js.map +1 -0
  119. package/dist/p2p.d.ts +87 -0
  120. package/dist/p2p.d.ts.map +1 -0
  121. package/dist/p2p.js +606 -0
  122. package/dist/p2p.js.map +1 -0
  123. package/dist/persona/capabilities.d.ts +17 -0
  124. package/dist/persona/capabilities.d.ts.map +1 -0
  125. package/dist/persona/capabilities.js +224 -0
  126. package/dist/persona/capabilities.js.map +1 -0
  127. package/dist/persona/domains.d.ts +22 -0
  128. package/dist/persona/domains.d.ts.map +1 -0
  129. package/dist/persona/domains.js +176 -0
  130. package/dist/persona/domains.js.map +1 -0
  131. package/dist/persona/embeddings.d.ts +40 -0
  132. package/dist/persona/embeddings.d.ts.map +1 -0
  133. package/dist/persona/embeddings.js +265 -0
  134. package/dist/persona/embeddings.js.map +1 -0
  135. package/dist/persona/engine.d.ts +79 -0
  136. package/dist/persona/engine.d.ts.map +1 -0
  137. package/dist/persona/engine.js +1087 -0
  138. package/dist/persona/engine.js.map +1 -0
  139. package/dist/persona/index.d.ts +11 -0
  140. package/dist/persona/index.d.ts.map +1 -0
  141. package/dist/persona/index.js +11 -0
  142. package/dist/persona/index.js.map +1 -0
  143. package/dist/persona/lifecycle.d.ts +17 -0
  144. package/dist/persona/lifecycle.d.ts.map +1 -0
  145. package/dist/persona/lifecycle.js +36 -0
  146. package/dist/persona/lifecycle.js.map +1 -0
  147. package/dist/persona/retrieval.d.ts +6 -0
  148. package/dist/persona/retrieval.d.ts.map +1 -0
  149. package/dist/persona/retrieval.js +122 -0
  150. package/dist/persona/retrieval.js.map +1 -0
  151. package/dist/persona/sync.d.ts +15 -0
  152. package/dist/persona/sync.d.ts.map +1 -0
  153. package/dist/persona/sync.js +92 -0
  154. package/dist/persona/sync.js.map +1 -0
  155. package/dist/persona/types.d.ts +283 -0
  156. package/dist/persona/types.d.ts.map +1 -0
  157. package/dist/persona/types.js +2 -0
  158. package/dist/persona/types.js.map +1 -0
  159. package/dist/persona/zkp/engine.d.ts +26 -0
  160. package/dist/persona/zkp/engine.d.ts.map +1 -0
  161. package/dist/persona/zkp/engine.js +370 -0
  162. package/dist/persona/zkp/engine.js.map +1 -0
  163. package/dist/persona/zkp/types.d.ts +39 -0
  164. package/dist/persona/zkp/types.d.ts.map +1 -0
  165. package/dist/persona/zkp/types.js +2 -0
  166. package/dist/persona/zkp/types.js.map +1 -0
  167. package/dist/planner.d.ts +114 -0
  168. package/dist/planner.d.ts.map +1 -0
  169. package/dist/planner.js +522 -0
  170. package/dist/planner.js.map +1 -0
  171. package/dist/proactive/checkpoints.d.ts +9 -0
  172. package/dist/proactive/checkpoints.d.ts.map +1 -0
  173. package/dist/proactive/checkpoints.js +20 -0
  174. package/dist/proactive/checkpoints.js.map +1 -0
  175. package/dist/proactive/engine.d.ts +59 -0
  176. package/dist/proactive/engine.d.ts.map +1 -0
  177. package/dist/proactive/engine.js +406 -0
  178. package/dist/proactive/engine.js.map +1 -0
  179. package/dist/proactive/scheduler.d.ts +11 -0
  180. package/dist/proactive/scheduler.d.ts.map +1 -0
  181. package/dist/proactive/scheduler.js +45 -0
  182. package/dist/proactive/scheduler.js.map +1 -0
  183. package/dist/proactive/swarm-controller.d.ts +189 -0
  184. package/dist/proactive/swarm-controller.d.ts.map +1 -0
  185. package/dist/proactive/swarm-controller.js +477 -0
  186. package/dist/proactive/swarm-controller.js.map +1 -0
  187. package/dist/proactive/swarm-registry.d.ts +13 -0
  188. package/dist/proactive/swarm-registry.d.ts.map +1 -0
  189. package/dist/proactive/swarm-registry.js +122 -0
  190. package/dist/proactive/swarm-registry.js.map +1 -0
  191. package/dist/proactive/types.d.ts +145 -0
  192. package/dist/proactive/types.d.ts.map +1 -0
  193. package/dist/proactive/types.js +25 -0
  194. package/dist/proactive/types.js.map +1 -0
  195. package/dist/registry.d.ts +35 -0
  196. package/dist/registry.d.ts.map +1 -0
  197. package/dist/registry.js +88 -0
  198. package/dist/registry.js.map +1 -0
  199. package/dist/reputation.d.ts +123 -0
  200. package/dist/reputation.d.ts.map +1 -0
  201. package/dist/reputation.js +366 -0
  202. package/dist/reputation.js.map +1 -0
  203. package/dist/reputation.test.d.ts +5 -0
  204. package/dist/reputation.test.d.ts.map +1 -0
  205. package/dist/reputation.test.js +265 -0
  206. package/dist/reputation.test.js.map +1 -0
  207. package/dist/rooms.d.ts +96 -0
  208. package/dist/rooms.d.ts.map +1 -0
  209. package/dist/rooms.js +410 -0
  210. package/dist/rooms.js.map +1 -0
  211. package/dist/sdk/client.d.ts +290 -0
  212. package/dist/sdk/client.d.ts.map +1 -0
  213. package/dist/sdk/client.js +1287 -0
  214. package/dist/sdk/client.js.map +1 -0
  215. package/dist/sdk/index.d.ts +32 -0
  216. package/dist/sdk/index.d.ts.map +1 -0
  217. package/dist/sdk/index.js +70 -0
  218. package/dist/sdk/index.js.map +1 -0
  219. package/dist/security.d.ts +230 -0
  220. package/dist/security.d.ts.map +1 -0
  221. package/dist/security.js +652 -0
  222. package/dist/security.js.map +1 -0
  223. package/dist/skills/engine.d.ts +262 -0
  224. package/dist/skills/engine.d.ts.map +1 -0
  225. package/dist/skills/engine.js +788 -0
  226. package/dist/skills/engine.js.map +1 -0
  227. package/dist/skills/engine.test.d.ts +2 -0
  228. package/dist/skills/engine.test.d.ts.map +1 -0
  229. package/dist/skills/engine.test.js +134 -0
  230. package/dist/skills/engine.test.js.map +1 -0
  231. package/dist/skills/parser.d.ts +129 -0
  232. package/dist/skills/parser.d.ts.map +1 -0
  233. package/dist/skills/parser.js +318 -0
  234. package/dist/skills/parser.js.map +1 -0
  235. package/dist/social.d.ts +149 -0
  236. package/dist/social.d.ts.map +1 -0
  237. package/dist/social.js +401 -0
  238. package/dist/social.js.map +1 -0
  239. package/dist/storage-optimized.d.ts +116 -0
  240. package/dist/storage-optimized.d.ts.map +1 -0
  241. package/dist/storage-optimized.js +264 -0
  242. package/dist/storage-optimized.js.map +1 -0
  243. package/dist/storage.d.ts +584 -0
  244. package/dist/storage.d.ts.map +1 -0
  245. package/dist/storage.js +2703 -0
  246. package/dist/storage.js.map +1 -0
  247. package/dist/storage.test.d.ts +2 -0
  248. package/dist/storage.test.d.ts.map +1 -0
  249. package/dist/storage.test.js +78 -0
  250. package/dist/storage.test.js.map +1 -0
  251. package/dist/swp.d.ts +443 -0
  252. package/dist/swp.d.ts.map +1 -0
  253. package/dist/swp.js +223 -0
  254. package/dist/swp.js.map +1 -0
  255. package/dist/swp.test.d.ts +5 -0
  256. package/dist/swp.test.d.ts.map +1 -0
  257. package/dist/swp.test.js +127 -0
  258. package/dist/swp.test.js.map +1 -0
  259. package/dist/templates.d.ts +25 -0
  260. package/dist/templates.d.ts.map +1 -0
  261. package/dist/templates.js +1048 -0
  262. package/dist/templates.js.map +1 -0
  263. package/dist/test-e2e.d.ts +14 -0
  264. package/dist/test-e2e.d.ts.map +1 -0
  265. package/dist/test-e2e.js +266 -0
  266. package/dist/test-e2e.js.map +1 -0
  267. package/dist/workers/research-worker.d.ts +19 -0
  268. package/dist/workers/research-worker.d.ts.map +1 -0
  269. package/dist/workers/research-worker.js +141 -0
  270. package/dist/workers/research-worker.js.map +1 -0
  271. package/package.json +110 -0
@@ -0,0 +1,1105 @@
1
+ /**
2
+ * Society Protocol - Module Integration Layer v1.0
3
+ *
4
+ * Integrações entre módulos:
5
+ * - Federation ↔ Rooms (salas pertencem a federações)
6
+ * - Knowledge ↔ CoC (CoCs geram knowledge automaticamente)
7
+ * - Skills ↔ Runtime (execução multi-runtime)
8
+ * - Security ↔ All (segurança em todos os pontos)
9
+ */
10
+ import { EventEmitter } from 'events';
11
+ import { ulid } from 'ulid';
12
+ // ─── Integration Engine ──────────────────────────────────────────
13
+ class IntegrationEngine extends EventEmitter {
14
+ storage;
15
+ identity;
16
+ federationEngine;
17
+ roomManager;
18
+ knowledgePool;
19
+ cocEngine;
20
+ skillsEngine;
21
+ securityManager;
22
+ config;
23
+ federationRooms = new Map(); // federationId -> rooms
24
+ cocKnowledgeBindings = new Map();
25
+ meshBridges = new Map();
26
+ bridgeRateLimits = new Map();
27
+ personaVault;
28
+ personaHooksBound = false;
29
+ cotStream;
30
+ cotHooksBound = false;
31
+ constructor(storage, identity, federationEngine, roomManager, knowledgePool, cocEngine, skillsEngine, securityManager, config) {
32
+ super();
33
+ this.storage = storage;
34
+ this.identity = identity;
35
+ this.federationEngine = federationEngine;
36
+ this.roomManager = roomManager;
37
+ this.knowledgePool = knowledgePool;
38
+ this.cocEngine = cocEngine;
39
+ this.skillsEngine = skillsEngine;
40
+ this.securityManager = securityManager;
41
+ this.config = {
42
+ autoIndexCoC: true,
43
+ autoCreateKnowledgeSpace: true,
44
+ enforceFederationACLs: true,
45
+ autoCompressMessages: true,
46
+ maxKnowledgeCardSize: 10000,
47
+ ...config
48
+ };
49
+ this.loadFromStorage();
50
+ this.setupHooks();
51
+ }
52
+ attachPersonaVault(engine) {
53
+ this.personaVault = engine;
54
+ if (this.personaHooksBound)
55
+ return;
56
+ this.personaHooksBound = true;
57
+ const publishDelta = async (operations, vaultId) => {
58
+ const resolvedVaultId = vaultId || this.storage.getPersonaVaults?.(this.identity.did)?.[0]?.id;
59
+ if (!resolvedVaultId)
60
+ return;
61
+ const delta = this.personaVault.buildSyncDelta({
62
+ vaultId: resolvedVaultId,
63
+ operations,
64
+ });
65
+ const rooms = this.roomManager.getJoinedRooms?.() || [];
66
+ await Promise.all(rooms.map((roomId) => this.roomManager.sendMessage(roomId, delta, 'persona.sync.delta')));
67
+ };
68
+ engine.on('persona:memory:added', (node) => {
69
+ publishDelta([{ type: 'node_upsert', payload: node }], node.vaultId).catch(() => { });
70
+ });
71
+ engine.on('persona:memory:updated', (node) => {
72
+ publishDelta([{ type: 'node_upsert', payload: node }], node.vaultId).catch(() => { });
73
+ });
74
+ engine.on('persona:memory:deleted', (evt) => {
75
+ publishDelta([{ type: 'node_delete', payload: { nodeId: evt.nodeId } }], evt.vaultId).catch(() => { });
76
+ });
77
+ engine.on('persona:edge:upserted', (edge) => {
78
+ publishDelta([{ type: 'edge_upsert', payload: edge }], edge.vaultId).catch(() => { });
79
+ });
80
+ engine.on('persona:capability:revoked', (evt) => {
81
+ publishDelta([{ type: 'capability_revoke', payload: { tokenId: evt.tokenId, reason: evt.reason } }]).catch(() => { });
82
+ });
83
+ engine.on('persona:capability:attenuated', (cap) => {
84
+ publishDelta([{ type: 'capability_attenuate', payload: { tokenId: cap.parentTokenId, caveatsPatch: cap.caveats } }], cap.vaultId).catch(() => { });
85
+ });
86
+ engine.on('persona:claim:issued', (claim) => {
87
+ publishDelta([{ type: 'claim_upsert', payload: claim }], claim.vaultId).catch(() => { });
88
+ });
89
+ engine.on('persona:claim:revoked', (evt) => {
90
+ publishDelta([{ type: 'claim_revoke', payload: { claimId: evt.claimId } }]).catch(() => { });
91
+ });
92
+ engine.on('persona:zkp:generated', (proof) => {
93
+ publishDelta([{ type: 'zkp_proof_upsert', payload: proof }], proof.vaultId).catch(() => { });
94
+ });
95
+ }
96
+ /**
97
+ * Attach CoT Stream Engine for insight→knowledge auto-indexing
98
+ * and CoC step→stream correlation.
99
+ */
100
+ attachCotStream(engine) {
101
+ this.cotStream = engine;
102
+ if (this.cotHooksBound)
103
+ return;
104
+ this.cotHooksBound = true;
105
+ // Hook: CoT insight with high confidence → auto-create knowledge card
106
+ engine.on('insight:received', async (_streamId, insight) => {
107
+ if (this.config.autoIndexCoC && insight.confidence >= 0.7) {
108
+ this.emit('cot:insight:indexed', insight);
109
+ }
110
+ });
111
+ // Hook: CoT stream ended → index summary as knowledge
112
+ engine.on('stream:ended', async (streamId, status, summary) => {
113
+ if (status === 'completed' && this.config.autoIndexCoC) {
114
+ const stream = engine.getStream(streamId);
115
+ if (stream?.chain_id) {
116
+ this.emit('cot:stream:completed', streamId, summary);
117
+ }
118
+ }
119
+ });
120
+ // Hook: CoC step unlocked → notify CoT engine for potential auto-stream
121
+ this.cocEngine.on('step:unlocked', (chainId, stepId, step) => {
122
+ this.emit('cot:step:available', chainId, stepId, step);
123
+ });
124
+ }
125
+ // ═══════════════════════════════════════════════════════════════
126
+ // FEDERATION ↔ ROOMS INTEGRATION
127
+ // ═══════════════════════════════════════════════════════════════
128
+ /**
129
+ * Criar room vinculada a uma federação
130
+ */
131
+ async createFederatedRoom(roomId, name, federationId, options) {
132
+ // Verificar se federação existe
133
+ const federation = this.federationEngine.getFederation(federationId);
134
+ if (!federation) {
135
+ throw new Error(`Federation ${federationId} not found`);
136
+ }
137
+ // Verificar permissão de criar room na federação
138
+ const canCreate = this.federationEngine.checkPolicy(federation, 'room:create', this.identity.did);
139
+ if (!canCreate.allowed) {
140
+ throw new Error(`Cannot create room: ${canCreate.reason}`);
141
+ }
142
+ // Criar room no RoomManager (se não existir)
143
+ // Note: RoomManager.createRoom só aceita name, então criamos via storage
144
+ this.storage.createRoom(roomId, name, this.identity.did);
145
+ this.storage.addRoomMember(roomId, this.identity.did, this.identity.displayName);
146
+ // Criar vínculo federation-room
147
+ const federationRoom = {
148
+ roomId,
149
+ federationId,
150
+ policies: federation.policies.map(p => p.id),
151
+ requiresInvitation: options?.requireInvitation ?? federation.settings.requireInvitation,
152
+ memberCount: 0
153
+ };
154
+ if (!this.federationRooms.has(federationId)) {
155
+ this.federationRooms.set(federationId, []);
156
+ }
157
+ this.federationRooms.get(federationId).push(federationRoom);
158
+ this.storage.saveFederationRoom?.(federationId, roomId, federationRoom);
159
+ // Criar knowledge space para a room se configurado
160
+ let knowledgeSpace;
161
+ if (this.config.autoCreateKnowledgeSpace) {
162
+ knowledgeSpace = await this.knowledgePool.createSpace(`${name} Knowledge`, `Shared knowledge for ${name}`, 'team', federation.visibility === 'public' ? 'public' : 'federation');
163
+ }
164
+ // Emitir evento
165
+ this.emit('federation:room:created', { roomId, federationId, knowledgeSpace });
166
+ return {
167
+ room: { room_id: roomId, name },
168
+ federationRoom
169
+ };
170
+ }
171
+ /**
172
+ * Verificar se usuário pode entrar na room (ACL da federação)
173
+ */
174
+ async canJoinRoom(roomId, did) {
175
+ // Encontrar federação da room
176
+ const federationRoom = this.findFederationForRoom(roomId);
177
+ if (!federationRoom) {
178
+ // Room não está em nenhuma federação - livre
179
+ return { allowed: true };
180
+ }
181
+ const federation = this.federationEngine.getFederation(federationRoom.federationId);
182
+ if (!federation) {
183
+ return { allowed: false, reason: 'Federation not found' };
184
+ }
185
+ // Verificar se já é membro da federação
186
+ const isMember = federation.members.has(did);
187
+ if (!isMember) {
188
+ // Verificar se pode entrar na federação
189
+ if (federationRoom.requiresInvitation) {
190
+ return {
191
+ allowed: false,
192
+ reason: 'Invitation required to join federation',
193
+ requiresInvite: true
194
+ };
195
+ }
196
+ // Tentar juntar à federação primeiro
197
+ try {
198
+ await this.federationEngine.joinFederation(federationRoom.federationId, did, 'Unknown' // Nome será atualizado depois
199
+ );
200
+ }
201
+ catch (err) {
202
+ return { allowed: false, reason: err.message };
203
+ }
204
+ }
205
+ // Verificar políticas específicas da room
206
+ const checkResult = this.federationEngine.checkPolicy(federation, 'room:join', did);
207
+ return {
208
+ allowed: checkResult.allowed,
209
+ reason: checkResult.reason
210
+ };
211
+ }
212
+ /**
213
+ * Listar rooms de uma federação
214
+ */
215
+ getFederationRooms(federationId) {
216
+ return this.federationRooms.get(federationId) || [];
217
+ }
218
+ /**
219
+ * Obter federação de uma room
220
+ */
221
+ findFederationForRoom(roomId) {
222
+ for (const rooms of this.federationRooms.values()) {
223
+ const room = rooms.find(r => r.roomId === roomId);
224
+ if (room)
225
+ return room;
226
+ }
227
+ return undefined;
228
+ }
229
+ // ═══════════════════════════════════════════════════════════════
230
+ // FEDERATION MESH (Peering + Bridge + Sync)
231
+ // ═══════════════════════════════════════════════════════════════
232
+ async openMeshBridge(peeringId, localRoomId, remoteRoomId, rules) {
233
+ const peering = this.federationEngine.getPeering(peeringId);
234
+ if (!peering) {
235
+ throw new Error(`Peering ${peeringId} not found`);
236
+ }
237
+ if (peering.status !== 'active') {
238
+ throw new Error(`Peering ${peeringId} is not active`);
239
+ }
240
+ const now = Date.now();
241
+ const bridge = {
242
+ id: `bridge_${ulid()}`,
243
+ peeringId,
244
+ localFederationId: peering.sourceFederationId,
245
+ localRoomId,
246
+ remoteRoomId,
247
+ rules: this.mergeBridgeRules(peering.policy, rules),
248
+ status: 'active',
249
+ eventsIn: 0,
250
+ eventsOut: 0,
251
+ createdAt: now,
252
+ updatedAt: now
253
+ };
254
+ this.meshBridges.set(bridge.id, bridge);
255
+ this.persistMeshBridge(bridge);
256
+ this.emit('mesh:bridge:opened', bridge);
257
+ return bridge;
258
+ }
259
+ async closeMeshBridge(bridgeId) {
260
+ const bridge = this.meshBridges.get(bridgeId);
261
+ if (!bridge) {
262
+ throw new Error(`Bridge ${bridgeId} not found`);
263
+ }
264
+ bridge.status = 'closed';
265
+ bridge.updatedAt = Date.now();
266
+ this.meshBridges.set(bridge.id, bridge);
267
+ this.persistMeshBridge(bridge);
268
+ this.storage.updateFederationBridgeStatus?.(bridge.id, 'closed', bridge.lastSyncAt);
269
+ this.emit('mesh:bridge:closed', bridge);
270
+ }
271
+ listMeshBridges(federationId, status) {
272
+ return Array.from(this.meshBridges.values())
273
+ .filter((bridge) => {
274
+ if (federationId && bridge.localFederationId !== federationId)
275
+ return false;
276
+ if (status && bridge.status !== status)
277
+ return false;
278
+ return true;
279
+ })
280
+ .sort((a, b) => b.updatedAt - a.updatedAt);
281
+ }
282
+ async publishMeshEvent(bridgeId, envelope) {
283
+ const bridge = this.meshBridges.get(bridgeId);
284
+ if (!bridge) {
285
+ return { delivered: false, reason: `Bridge ${bridgeId} not found` };
286
+ }
287
+ if (bridge.status !== 'active') {
288
+ return { delivered: false, reason: `Bridge ${bridgeId} is not active` };
289
+ }
290
+ const peering = this.federationEngine.getPeering(bridge.peeringId);
291
+ if (!peering || peering.status !== 'active') {
292
+ await this.closeMeshBridge(bridgeId);
293
+ return { delivered: false, reason: `Peering ${bridge.peeringId} is not active` };
294
+ }
295
+ if (envelope.room !== bridge.localRoomId) {
296
+ return { delivered: false, reason: 'Envelope room does not match bridge local room' };
297
+ }
298
+ if (!this.isMessageTypeAllowed(bridge.rules.allowedTypes, envelope.t)) {
299
+ this.storage.appendFederationSyncLog?.({
300
+ bridgeId: bridge.id,
301
+ envelopeId: envelope.id,
302
+ direction: 'out',
303
+ messageType: envelope.t,
304
+ fromFederationId: bridge.localFederationId,
305
+ toFederationId: peering.targetFederationDid,
306
+ status: 'rejected',
307
+ error: `type ${envelope.t} blocked by mesh policy`,
308
+ ts: Date.now()
309
+ });
310
+ return { delivered: false, reason: `Message type ${envelope.t} blocked by mesh policy` };
311
+ }
312
+ if (!this.consumeBridgeRateLimit(bridge)) {
313
+ return { delivered: false, reason: `Rate limit exceeded for bridge ${bridge.id}` };
314
+ }
315
+ if (this.storage.hasFederationSyncLog?.(bridge.id, envelope.id, 'out')) {
316
+ return { delivered: false, reason: 'Duplicate envelope blocked by sync log' };
317
+ }
318
+ const outboundEnvelope = this.applyPrivacyMode(envelope, bridge.rules.privacyMode);
319
+ const payload = {
320
+ bridge_id: bridge.id,
321
+ peering_id: bridge.peeringId,
322
+ source_federation_id: bridge.localFederationId,
323
+ target_federation_did: peering.targetFederationDid,
324
+ direction: 'out',
325
+ cursor: envelope.id,
326
+ envelope: outboundEnvelope
327
+ };
328
+ try {
329
+ await this.roomManager.sendMessage(bridge.remoteRoomId, payload, 'federation.bridge.sync');
330
+ const now = Date.now();
331
+ bridge.eventsOut += 1;
332
+ bridge.lastSyncAt = now;
333
+ bridge.updatedAt = now;
334
+ this.meshBridges.set(bridge.id, bridge);
335
+ this.persistMeshBridge(bridge);
336
+ this.storage.incrementFederationBridgeCounters?.(bridge.id, 'out', 1, now);
337
+ this.storage.saveFederationSyncCursor?.({
338
+ bridgeId: bridge.id,
339
+ direction: 'out',
340
+ cursorId: envelope.id,
341
+ updatedAt: now
342
+ });
343
+ this.storage.appendFederationSyncLog?.({
344
+ bridgeId: bridge.id,
345
+ envelopeId: envelope.id,
346
+ direction: 'out',
347
+ messageType: envelope.t,
348
+ fromFederationId: bridge.localFederationId,
349
+ toFederationId: peering.targetFederationDid,
350
+ status: 'processed',
351
+ ts: now
352
+ });
353
+ this.emit('mesh:event:published', {
354
+ bridgeId: bridge.id,
355
+ envelopeId: envelope.id,
356
+ messageType: envelope.t
357
+ });
358
+ return { delivered: true };
359
+ }
360
+ catch (error) {
361
+ const message = error instanceof Error ? error.message : String(error);
362
+ this.storage.appendFederationSyncLog?.({
363
+ bridgeId: bridge.id,
364
+ envelopeId: envelope.id,
365
+ direction: 'out',
366
+ messageType: envelope.t,
367
+ fromFederationId: bridge.localFederationId,
368
+ toFederationId: peering.targetFederationDid,
369
+ status: 'failed',
370
+ error: message,
371
+ ts: Date.now()
372
+ });
373
+ return { delivered: false, reason: message };
374
+ }
375
+ }
376
+ getMeshStats(federationId) {
377
+ if (this.storage.getFederationMeshStats) {
378
+ return this.storage.getFederationMeshStats(federationId);
379
+ }
380
+ const bridges = this.listMeshBridges(federationId);
381
+ let eventsIn = 0;
382
+ let eventsOut = 0;
383
+ let lastSyncAt;
384
+ for (const bridge of bridges) {
385
+ eventsIn += bridge.eventsIn;
386
+ eventsOut += bridge.eventsOut;
387
+ if (bridge.lastSyncAt && (!lastSyncAt || bridge.lastSyncAt > lastSyncAt)) {
388
+ lastSyncAt = bridge.lastSyncAt;
389
+ }
390
+ }
391
+ return {
392
+ bridgeCount: bridges.length,
393
+ activeBridges: bridges.filter((bridge) => bridge.status === 'active').length,
394
+ eventsIn,
395
+ eventsOut,
396
+ lastSyncAt
397
+ };
398
+ }
399
+ // ═══════════════════════════════════════════════════════════════
400
+ // KNOWLEDGE ↔ CoC INTEGRATION
401
+ // ═══════════════════════════════════════════════════════════════
402
+ /**
403
+ * Criar CoC vinculado a knowledge space
404
+ */
405
+ async createCoCWithKnowledge(roomId, goal, options) {
406
+ // Criar CoC
407
+ const chainId = await this.cocEngine.openChain(roomId, goal, { templateId: options?.template });
408
+ // Criar ou usar knowledge space
409
+ let knowledgeSpaceId = options?.knowledgeSpaceId;
410
+ if (!knowledgeSpaceId && this.config.autoCreateKnowledgeSpace) {
411
+ const space = await this.knowledgePool.createSpace(`CoC: ${goal.slice(0, 50)}`, `Knowledge generated from CoC ${chainId}`, 'team', 'room');
412
+ knowledgeSpaceId = space.id;
413
+ }
414
+ // Criar binding
415
+ if (knowledgeSpaceId && (options?.autoIndex ?? this.config.autoIndexCoC)) {
416
+ const binding = {
417
+ cocId: chainId,
418
+ knowledgeSpaceId,
419
+ autoIndexSteps: true,
420
+ indexArtifacts: true,
421
+ indexDecisions: true
422
+ };
423
+ this.cocKnowledgeBindings.set(chainId, binding);
424
+ // Salvar no storage
425
+ this.storage.saveCoCKnowledgeBinding?.(binding);
426
+ }
427
+ this.emit('coc:knowledge:linked', { chainId, knowledgeSpaceId });
428
+ return { chainId, binding: this.cocKnowledgeBindings.get(chainId) };
429
+ }
430
+ /**
431
+ * Indexar step do CoC como knowledge card
432
+ */
433
+ async indexStepAsKnowledge(chainId, stepId) {
434
+ const binding = this.cocKnowledgeBindings.get(chainId);
435
+ if (!binding || !binding.autoIndexSteps) {
436
+ return undefined;
437
+ }
438
+ // Obter step do CoC
439
+ const step = this.cocEngine.getStep(stepId);
440
+ if (!step)
441
+ return undefined;
442
+ // Determinar tipo de knowledge
443
+ let knowledgeType = 'insight';
444
+ if (step.kind === 'decision')
445
+ knowledgeType = 'decision';
446
+ else if (step.kind === 'synthesis')
447
+ knowledgeType = 'document';
448
+ else if (step.kind === 'task')
449
+ knowledgeType = 'code';
450
+ // Criar knowledge card
451
+ const card = await this.knowledgePool.createCard(binding.knowledgeSpaceId, knowledgeType, step.title, step.result_memo || 'No content', {
452
+ tags: ['coc-generated', step.kind, `chain-${chainId}`],
453
+ source: {
454
+ type: 'coc',
455
+ id: chainId,
456
+ context: `Step ${stepId} in CoC ${chainId}`
457
+ },
458
+ privacy: 'federation'
459
+ });
460
+ // Indexar artifacts se configurado
461
+ if (binding.indexArtifacts && step.artifacts) {
462
+ for (const artifactId of step.artifacts) {
463
+ await this.linkArtifactToKnowledge(artifactId, card.id);
464
+ }
465
+ }
466
+ this.emit('coc:step:indexed', { chainId, stepId, cardId: card.id });
467
+ return card;
468
+ }
469
+ /**
470
+ * Indexar decisão do CoC
471
+ */
472
+ async indexDecision(chainId, decision, rationale) {
473
+ const binding = this.cocKnowledgeBindings.get(chainId);
474
+ if (!binding || !binding.indexDecisions) {
475
+ return undefined;
476
+ }
477
+ const card = await this.knowledgePool.createCard(binding.knowledgeSpaceId, 'decision', `Decision: ${decision.slice(0, 100)}`, rationale, {
478
+ tags: ['coc-decision', `chain-${chainId}`],
479
+ source: { type: 'coc', id: chainId },
480
+ privacy: 'federation'
481
+ });
482
+ return card;
483
+ }
484
+ /**
485
+ * Linkar artifact a knowledge card
486
+ */
487
+ async linkArtifactToKnowledge(artifactId, knowledgeCardId) {
488
+ // Criar link no knowledge graph
489
+ await this.knowledgePool.linkCards(knowledgeCardId, artifactId, // Artifact como pseudo-card
490
+ 'depends-on', 0.9);
491
+ }
492
+ /**
493
+ * Query knowledge relacionado a CoC
494
+ */
495
+ async queryKnowledgeForCoC(chainId, query) {
496
+ const binding = this.cocKnowledgeBindings.get(chainId);
497
+ if (!binding) {
498
+ // Buscar em todos os spaces
499
+ return this.knowledgePool.queryCards({ query });
500
+ }
501
+ return this.knowledgePool.queryCards({
502
+ spaceId: binding.knowledgeSpaceId,
503
+ query
504
+ });
505
+ }
506
+ /**
507
+ * Obter contexto de conhecimento para CoC
508
+ */
509
+ async getKnowledgeContextForCoC(chainId) {
510
+ const binding = this.cocKnowledgeBindings.get(chainId);
511
+ if (!binding)
512
+ return '';
513
+ // Obter collective unconscious do space
514
+ const cu = this.knowledgePool.getCollectiveUnconscious(binding.knowledgeSpaceId);
515
+ if (!cu)
516
+ return '';
517
+ return this.knowledgePool.getSharedContext(binding.knowledgeSpaceId);
518
+ }
519
+ // ═══════════════════════════════════════════════════════════════
520
+ // SKILLS ↔ RUNTIME INTEGRATION
521
+ // ═══════════════════════════════════════════════════════════════
522
+ /**
523
+ * Executar skill com acesso a todos os módulos
524
+ */
525
+ async executeIntegratedSkill(skillId, inputs, context) {
526
+ // Criar contexto de segurança
527
+ const securityContext = {
528
+ identity: this.identity,
529
+ permissions: [], // Será preenchido baseado na skill
530
+ sessionId: `session_${Date.now()}`,
531
+ mfaVerified: false,
532
+ reputation: 0,
533
+ trustTier: 'bronze'
534
+ };
535
+ // Verificar permissões
536
+ const resource = `skill:${skillId}`;
537
+ const allowed = await this.securityManager.checkAccess(securityContext, resource, 'execute');
538
+ if (!allowed) {
539
+ throw new Error('Permission denied to execute skill');
540
+ }
541
+ // Enriquecer inputs com contexto
542
+ const enrichedInputs = await this.enrichSkillInputs(inputs, context);
543
+ // Executar skill
544
+ const result = await this.skillsEngine.executeSkill(skillId, enrichedInputs, context ? {
545
+ room: context.roomId,
546
+ federation: context.federationId
547
+ } : undefined);
548
+ // Auditar
549
+ await this.securityManager.audit.log({
550
+ type: 'action',
551
+ severity: 'info',
552
+ actor: this.identity.did,
553
+ resource,
554
+ action: 'execute',
555
+ result: result.status === 'completed' ? 'success' : 'failure',
556
+ details: { skillId, inputs: Object.keys(inputs) }
557
+ });
558
+ return result;
559
+ }
560
+ /**
561
+ * Enriquecer inputs de skill com contexto do sistema
562
+ */
563
+ async enrichSkillInputs(inputs, context) {
564
+ const enriched = { ...inputs };
565
+ // Adicionar contexto compartilhado se room especificada
566
+ if (context?.roomId && inputs.use_shared_context !== false) {
567
+ const federationRoom = this.findFederationForRoom(context.roomId);
568
+ if (federationRoom) {
569
+ const knowledgeContext = await this.knowledgePool.getSharedContext(federationRoom.roomId);
570
+ enriched._sharedContext = knowledgeContext;
571
+ }
572
+ }
573
+ // Adicionar info da federação
574
+ if (context?.federationId) {
575
+ const federation = this.federationEngine.getFederation(context.federationId);
576
+ if (federation) {
577
+ enriched._federation = {
578
+ name: federation.name,
579
+ policies: federation.policies.map(p => p.name)
580
+ };
581
+ }
582
+ }
583
+ return enriched;
584
+ }
585
+ // ═══════════════════════════════════════════════════════════════
586
+ // SECURITY INTEGRATION (todos os módulos)
587
+ // ═══════════════════════════════════════════════════════════════
588
+ /**
589
+ * Processar envelope com segurança completa
590
+ */
591
+ async processSecureEnvelope(envelope) {
592
+ // 1. Verificar ameaças
593
+ const threatCheck = this.securityManager.threats.analyzeEnvelope(envelope);
594
+ if (threatCheck.threat && threatCheck.severity === 'critical') {
595
+ return { allowed: false, reason: 'Threat detected' };
596
+ }
597
+ // 2. Verificar ACL da federação/room
598
+ if (this.config.enforceFederationACLs) {
599
+ const federationRoom = this.findFederationForRoom(envelope.room);
600
+ if (federationRoom) {
601
+ const federation = this.federationEngine.getFederation(federationRoom.federationId);
602
+ if (federation) {
603
+ const check = this.federationEngine.checkPolicy(federation, 'message:send', envelope.from.did);
604
+ if (!check.allowed) {
605
+ return { allowed: false, reason: check.reason };
606
+ }
607
+ }
608
+ }
609
+ }
610
+ // 3. Processar com security manager
611
+ return this.securityManager.processIncoming(envelope);
612
+ }
613
+ /**
614
+ * Comprimir mensagem se configurado
615
+ */
616
+ async compressMessageIfNeeded(data) {
617
+ if (!this.config.autoCompressMessages || data.length < 1024) {
618
+ return { data, compressed: false };
619
+ }
620
+ // Usar compressor do módulo de compression
621
+ const { MessageCompressor } = await import('./compression.js');
622
+ const compressor = new MessageCompressor({ algorithm: 'zstd' });
623
+ const compressed = await compressor.compress(data);
624
+ const stats = compressor.getCompressionStats(data.length, compressed.length);
625
+ if (stats.savingsPercent > 20) {
626
+ return { data: compressed, compressed: true, algorithm: 'zstd' };
627
+ }
628
+ return { data, compressed: false };
629
+ }
630
+ // ═══════════════════════════════════════════════════════════════
631
+ // HOOKS SETUP
632
+ // ═══════════════════════════════════════════════════════════════
633
+ setupHooks() {
634
+ // Hook: CoC step completed → Indexar como knowledge
635
+ this.cocEngine.on('step:submitted', async (chainId, stepId) => {
636
+ if (this.config.autoIndexCoC) {
637
+ try {
638
+ await this.indexStepAsKnowledge(chainId, stepId);
639
+ }
640
+ catch (err) {
641
+ console.error('Failed to index step:', err);
642
+ }
643
+ }
644
+ });
645
+ // Hook: CoC completed → Indexar decisões
646
+ this.cocEngine.on('chain:completed', async (chainId) => {
647
+ const binding = this.cocKnowledgeBindings.get(chainId);
648
+ if (binding?.indexDecisions) {
649
+ const chain = this.cocEngine.getChain(chainId);
650
+ if (chain?.final_report) {
651
+ await this.indexDecision(chainId, 'CoC Completed', chain.final_report);
652
+ }
653
+ }
654
+ });
655
+ // Hook: Knowledge criado → Notificar room
656
+ this.knowledgePool.on('card:created', async (card) => {
657
+ // Notificar room se o card for público/federation
658
+ if (card.privacy !== 'private') {
659
+ this.emit('knowledge:shared', card);
660
+ }
661
+ });
662
+ // Hook: Federation member joined → Adicionar às rooms
663
+ this.federationEngine.on('federation:member:joined', async (federationId, member) => {
664
+ const rooms = this.getFederationRooms(federationId);
665
+ for (const room of rooms) {
666
+ if (!room.requiresInvitation) {
667
+ this.storage.addRoomMember(room.roomId, member.did, member.displayName);
668
+ }
669
+ }
670
+ });
671
+ // Hook: Mesh federation events routed by RoomManager
672
+ this.roomManager.on('federation:event', async (_roomId, envelope) => {
673
+ try {
674
+ await this.handleMeshEnvelope(envelope);
675
+ }
676
+ catch (err) {
677
+ console.warn('[integration] Failed to handle mesh envelope:', err.message);
678
+ }
679
+ });
680
+ this.roomManager.on('persona:event', async (roomId, envelope) => {
681
+ try {
682
+ await this.handlePersonaEnvelope(roomId, envelope);
683
+ }
684
+ catch (err) {
685
+ console.warn('[integration] Failed to handle persona envelope:', err.message);
686
+ }
687
+ });
688
+ }
689
+ // ═══════════════════════════════════════════════════════════════
690
+ // UTILS
691
+ // ═══════════════════════════════════════════════════════════════
692
+ loadFromStorage() {
693
+ // Federation rooms
694
+ const federations = this.storage.getFederations?.() || [];
695
+ for (const federation of federations) {
696
+ const rooms = this.storage.getFederationRooms?.(federation.id) || [];
697
+ if (rooms.length > 0) {
698
+ this.federationRooms.set(federation.id, rooms);
699
+ }
700
+ }
701
+ // CoC knowledge bindings
702
+ try {
703
+ const bindings = this.storage.query('SELECT coc_id, knowledge_space_id, auto_index_steps, index_artifacts, index_decisions FROM coc_knowledge_bindings');
704
+ for (const row of bindings) {
705
+ this.cocKnowledgeBindings.set(row.coc_id, {
706
+ cocId: row.coc_id,
707
+ knowledgeSpaceId: row.knowledge_space_id,
708
+ autoIndexSteps: !!row.auto_index_steps,
709
+ indexArtifacts: !!row.index_artifacts,
710
+ indexDecisions: !!row.index_decisions
711
+ });
712
+ }
713
+ }
714
+ catch {
715
+ // Optional table may not exist in early schemas
716
+ }
717
+ // Mesh bridges
718
+ const bridges = this.storage.listFederationBridges?.() || [];
719
+ for (const row of bridges) {
720
+ const bridge = {
721
+ id: row.bridgeId,
722
+ peeringId: row.peeringId,
723
+ localFederationId: row.localFederationId,
724
+ localRoomId: row.localRoomId,
725
+ remoteRoomId: row.remoteRoomId,
726
+ rules: this.mergeBridgeRules(undefined, row.rules),
727
+ status: row.status,
728
+ eventsIn: row.eventsIn,
729
+ eventsOut: row.eventsOut,
730
+ createdAt: row.createdAt,
731
+ updatedAt: row.updatedAt,
732
+ lastSyncAt: row.lastSyncAt
733
+ };
734
+ this.meshBridges.set(bridge.id, bridge);
735
+ }
736
+ }
737
+ persistMeshBridge(bridge) {
738
+ this.storage.saveFederationBridge?.({
739
+ bridgeId: bridge.id,
740
+ peeringId: bridge.peeringId,
741
+ localFederationId: bridge.localFederationId,
742
+ localRoomId: bridge.localRoomId,
743
+ remoteRoomId: bridge.remoteRoomId,
744
+ rules: bridge.rules,
745
+ status: bridge.status,
746
+ eventsIn: bridge.eventsIn,
747
+ eventsOut: bridge.eventsOut,
748
+ lastSyncAt: bridge.lastSyncAt,
749
+ createdAt: bridge.createdAt,
750
+ updatedAt: bridge.updatedAt
751
+ });
752
+ }
753
+ mergeBridgeRules(policy, rules) {
754
+ const allowedTypes = rules?.allowedTypes?.length
755
+ ? rules.allowedTypes
756
+ : policy?.allowedTypes?.length
757
+ ? policy.allowedTypes
758
+ : ['chat.msg', 'coc.open', 'coc.plan', 'coc.submit', 'federation.bridge.sync', 'persona.sync.delta', 'persona.capability.revoke'];
759
+ const maxRatePerMinute = Number(rules?.maxRatePerMinute ?? policy?.maxRatePerMinute ?? 200);
760
+ return {
761
+ allowedTypes,
762
+ maxRatePerMinute: Number.isFinite(maxRatePerMinute) && maxRatePerMinute > 0
763
+ ? Math.floor(maxRatePerMinute)
764
+ : 200,
765
+ privacyMode: rules?.privacyMode || policy?.privacyMode || 'summary'
766
+ };
767
+ }
768
+ isMessageTypeAllowed(allowed, messageType) {
769
+ return allowed.some((pattern) => this.matchesMessageTypePattern(pattern, messageType));
770
+ }
771
+ matchesMessageTypePattern(pattern, messageType) {
772
+ if (pattern === '*')
773
+ return true;
774
+ if (pattern.endsWith('*')) {
775
+ return messageType.startsWith(pattern.slice(0, -1));
776
+ }
777
+ return pattern === messageType;
778
+ }
779
+ consumeBridgeRateLimit(bridge) {
780
+ const now = Date.now();
781
+ const current = this.bridgeRateLimits.get(bridge.id);
782
+ if (!current || now - current.windowStartedAt >= 60_000) {
783
+ this.bridgeRateLimits.set(bridge.id, { windowStartedAt: now, count: 1 });
784
+ return true;
785
+ }
786
+ if (current.count >= bridge.rules.maxRatePerMinute) {
787
+ return false;
788
+ }
789
+ current.count += 1;
790
+ this.bridgeRateLimits.set(bridge.id, current);
791
+ return true;
792
+ }
793
+ applyPrivacyMode(envelope, mode) {
794
+ if (mode === 'full') {
795
+ return envelope;
796
+ }
797
+ if (mode === 'metadata-only') {
798
+ return {
799
+ ...envelope,
800
+ body: {
801
+ redacted: true,
802
+ original_type: envelope.t,
803
+ original_id: envelope.id,
804
+ original_ts: envelope.ts
805
+ }
806
+ };
807
+ }
808
+ const body = envelope.body;
809
+ if (envelope.t === 'chat.msg') {
810
+ const text = typeof body.text === 'string' ? body.text : '';
811
+ return {
812
+ ...envelope,
813
+ body: {
814
+ summary: text.length > 180 ? `${text.slice(0, 180)}...` : text,
815
+ has_attachments: Array.isArray(body.attachments) && body.attachments.length > 0
816
+ }
817
+ };
818
+ }
819
+ if (envelope.t.startsWith('coc.')) {
820
+ return {
821
+ ...envelope,
822
+ body: {
823
+ chain_id: body.chain_id,
824
+ step_id: body.step_id,
825
+ status: body.status,
826
+ kind: body.kind
827
+ }
828
+ };
829
+ }
830
+ return envelope;
831
+ }
832
+ async handleMeshEnvelope(envelope) {
833
+ if (envelope.t === 'federation.peer.revoke') {
834
+ const body = envelope.body;
835
+ if (body.peering_id) {
836
+ for (const bridge of this.meshBridges.values()) {
837
+ if (bridge.peeringId === body.peering_id && bridge.status === 'active') {
838
+ await this.closeMeshBridge(bridge.id);
839
+ }
840
+ }
841
+ }
842
+ return;
843
+ }
844
+ if (envelope.t !== 'federation.bridge.sync') {
845
+ return;
846
+ }
847
+ const body = envelope.body;
848
+ if (!body.bridge_id) {
849
+ return;
850
+ }
851
+ const bridge = this.meshBridges.get(body.bridge_id);
852
+ if (!bridge || bridge.status !== 'active') {
853
+ return;
854
+ }
855
+ const innerEnvelope = body.envelope || envelope;
856
+ const envelopeId = innerEnvelope.id || body.cursor || envelope.id;
857
+ const messageType = innerEnvelope.t || 'federation.bridge.sync';
858
+ if (this.storage.hasFederationSyncLog?.(bridge.id, envelopeId, 'in')) {
859
+ return;
860
+ }
861
+ if (!this.isMessageTypeAllowed(bridge.rules.allowedTypes, messageType)) {
862
+ this.storage.appendFederationSyncLog?.({
863
+ bridgeId: bridge.id,
864
+ envelopeId,
865
+ direction: 'in',
866
+ messageType,
867
+ fromFederationId: body.source_federation_id,
868
+ toFederationId: bridge.localFederationId,
869
+ status: 'rejected',
870
+ error: `type ${messageType} blocked by mesh policy`,
871
+ ts: Date.now()
872
+ });
873
+ return;
874
+ }
875
+ const now = Date.now();
876
+ bridge.eventsIn += 1;
877
+ bridge.lastSyncAt = now;
878
+ bridge.updatedAt = now;
879
+ this.meshBridges.set(bridge.id, bridge);
880
+ this.persistMeshBridge(bridge);
881
+ this.storage.incrementFederationBridgeCounters?.(bridge.id, 'in', 1, now);
882
+ this.storage.saveFederationSyncCursor?.({
883
+ bridgeId: bridge.id,
884
+ direction: 'in',
885
+ cursorId: envelopeId,
886
+ updatedAt: now
887
+ });
888
+ this.storage.appendFederationSyncLog?.({
889
+ bridgeId: bridge.id,
890
+ envelopeId,
891
+ direction: 'in',
892
+ messageType,
893
+ fromFederationId: body.source_federation_id,
894
+ toFederationId: bridge.localFederationId,
895
+ status: 'processed',
896
+ ts: now
897
+ });
898
+ this.emit('mesh:event:received', {
899
+ bridgeId: bridge.id,
900
+ envelope: innerEnvelope,
901
+ messageType
902
+ });
903
+ }
904
+ async handlePersonaEnvelope(roomId, envelope) {
905
+ if (!this.personaVault)
906
+ return;
907
+ if (envelope.t === 'persona.sync.delta') {
908
+ const body = envelope.body;
909
+ const result = await this.personaVault.applySyncDelta(body);
910
+ this.emit('persona:sync:applied', {
911
+ roomId,
912
+ deltaId: body.id,
913
+ applied: result.applied,
914
+ ignored: result.ignored
915
+ });
916
+ await this.roomManager.sendMessage(roomId, {
917
+ delta_id: body.id,
918
+ vault_id: body.vaultId,
919
+ applied: result.applied,
920
+ ignored: result.ignored,
921
+ cursor: result.cursor,
922
+ need_snapshot: result.applied === 0 && result.ignored > 0
923
+ }, 'persona.sync.ack');
924
+ return;
925
+ }
926
+ if (envelope.t === 'persona.preference.update') {
927
+ const body = envelope.body;
928
+ const fallbackVaultId = this.storage.getPersonaVaults?.(this.identity.did)?.[0]?.id;
929
+ const vaultId = body.vault_id || body.vaultId || fallbackVaultId;
930
+ if (!vaultId)
931
+ return;
932
+ const node = body.node ||
933
+ (body.key
934
+ ? {
935
+ id: body.node_id || `pref_${envelope.id}`,
936
+ vaultId,
937
+ domain: body.domain || 'preferences',
938
+ type: 'preference',
939
+ title: body.key,
940
+ content: JSON.stringify(body.value),
941
+ tags: body.tags || ['preference'],
942
+ confidence: body.confidence ?? 0.9,
943
+ source: { type: 'sync', actorDid: envelope.from.did },
944
+ metadata: { key: body.key, value: body.value },
945
+ createdAt: envelope.ts,
946
+ updatedAt: envelope.ts,
947
+ }
948
+ : undefined);
949
+ if (!node)
950
+ return;
951
+ await this.personaVault.applySyncDelta({
952
+ id: `delta_${envelope.id}`,
953
+ vaultId,
954
+ fromDid: envelope.from.did,
955
+ operations: [{ type: 'node_upsert', payload: node }],
956
+ vectorClock: { [envelope.from.did]: 1 },
957
+ createdAt: envelope.ts,
958
+ });
959
+ return;
960
+ }
961
+ if (envelope.t === 'persona.sync.ack') {
962
+ const body = envelope.body;
963
+ if (body.need_snapshot && body.vault_id) {
964
+ const snapshot = await this.personaVault.exportSubgraph({
965
+ vaultId: body.vault_id,
966
+ includeNeighbors: true,
967
+ });
968
+ const delta = this.personaVault.buildSyncDelta({
969
+ vaultId: snapshot.vaultId,
970
+ operations: snapshot.nodes.map((node) => ({
971
+ type: 'node_upsert',
972
+ payload: node,
973
+ })),
974
+ cursor: body.cursor,
975
+ });
976
+ await this.roomManager.sendMessage(roomId, delta, 'persona.sync.delta');
977
+ }
978
+ return;
979
+ }
980
+ if (envelope.t === 'persona.capability.revoke') {
981
+ const body = envelope.body;
982
+ if (body.token_id) {
983
+ await this.personaVault.revokeCapability(body.token_id, body.reason || 'remote-revoke');
984
+ }
985
+ return;
986
+ }
987
+ if (envelope.t === 'persona.capability.attenuate') {
988
+ const body = envelope.body;
989
+ if (body.token_id) {
990
+ await this.personaVault.attenuateCapability({
991
+ tokenId: body.token_id,
992
+ caveatsPatch: (body.caveats_patch || {}),
993
+ });
994
+ }
995
+ return;
996
+ }
997
+ if (envelope.t === 'persona.memory.upsert') {
998
+ const body = envelope.body;
999
+ await this.personaVault.applySyncDelta({
1000
+ id: `delta_${envelope.id}`,
1001
+ vaultId: body.vaultId,
1002
+ fromDid: envelope.from.did,
1003
+ operations: [{ type: 'node_upsert', payload: body.node }],
1004
+ vectorClock: body.vectorClock || { [envelope.from.did]: 1 },
1005
+ createdAt: envelope.ts,
1006
+ });
1007
+ return;
1008
+ }
1009
+ if (envelope.t === 'persona.claim.upsert') {
1010
+ const body = envelope.body;
1011
+ await this.personaVault.applySyncDelta({
1012
+ id: `delta_${envelope.id}`,
1013
+ vaultId: body.vaultId,
1014
+ fromDid: envelope.from.did,
1015
+ operations: [{ type: 'claim_upsert', payload: body.claim }],
1016
+ vectorClock: body.vectorClock || { [envelope.from.did]: 1 },
1017
+ createdAt: envelope.ts,
1018
+ });
1019
+ return;
1020
+ }
1021
+ if (envelope.t === 'persona.claim.revoke') {
1022
+ const body = envelope.body;
1023
+ await this.personaVault.applySyncDelta({
1024
+ id: `delta_${envelope.id}`,
1025
+ vaultId: body.vaultId,
1026
+ fromDid: envelope.from.did,
1027
+ operations: [{ type: 'claim_revoke', payload: { claimId: body.claimId } }],
1028
+ vectorClock: body.vectorClock || { [envelope.from.did]: 1 },
1029
+ createdAt: envelope.ts,
1030
+ });
1031
+ return;
1032
+ }
1033
+ if (envelope.t === 'persona.zkp.proof') {
1034
+ const body = envelope.body;
1035
+ await this.personaVault.applySyncDelta({
1036
+ id: `delta_${envelope.id}`,
1037
+ vaultId: body.vaultId,
1038
+ fromDid: envelope.from.did,
1039
+ operations: [{ type: 'zkp_proof_upsert', payload: body.proof }],
1040
+ vectorClock: body.vectorClock || { [envelope.from.did]: 1 },
1041
+ createdAt: envelope.ts,
1042
+ });
1043
+ return;
1044
+ }
1045
+ if (envelope.t === 'persona.edge.upsert') {
1046
+ const body = envelope.body;
1047
+ await this.personaVault.applySyncDelta({
1048
+ id: `delta_${envelope.id}`,
1049
+ vaultId: body.vaultId,
1050
+ fromDid: envelope.from.did,
1051
+ operations: [{ type: 'edge_upsert', payload: body.edge }],
1052
+ vectorClock: body.vectorClock || { [envelope.from.did]: 1 },
1053
+ createdAt: envelope.ts,
1054
+ });
1055
+ return;
1056
+ }
1057
+ if (envelope.t === 'persona.memory.delete') {
1058
+ const body = envelope.body;
1059
+ await this.personaVault.applySyncDelta({
1060
+ id: `delta_${envelope.id}`,
1061
+ vaultId: body.vaultId,
1062
+ fromDid: envelope.from.did,
1063
+ operations: [{ type: 'node_delete', payload: { nodeId: body.nodeId } }],
1064
+ vectorClock: body.vectorClock || { [envelope.from.did]: 1 },
1065
+ createdAt: envelope.ts,
1066
+ });
1067
+ return;
1068
+ }
1069
+ }
1070
+ /**
1071
+ * Obter estatísticas de integração
1072
+ */
1073
+ getStats() {
1074
+ let totalRooms = 0;
1075
+ for (const rooms of this.federationRooms.values()) {
1076
+ totalRooms += rooms.length;
1077
+ }
1078
+ return {
1079
+ federationRooms: totalRooms,
1080
+ cocKnowledgeBindings: this.cocKnowledgeBindings.size,
1081
+ indexedSteps: 0 // TODO: contar do storage
1082
+ };
1083
+ }
1084
+ }
1085
+ // ═══════════════════════════════════════════════════════════════
1086
+ // DECORATORS (para facilitar uso)
1087
+ // ═══════════════════════════════════════════════════════════════
1088
+ /**
1089
+ * Decorator: Aplicar ACL da federação em método
1090
+ */
1091
+ export function requireFederationPermission(resource, action) {
1092
+ return function (target, propertyKey, descriptor) {
1093
+ const originalMethod = descriptor.value;
1094
+ descriptor.value = async function (...args) {
1095
+ // Verificação de permissão seria feita aqui
1096
+ // usando o integrationEngine da instância
1097
+ return originalMethod.apply(this, args);
1098
+ };
1099
+ return descriptor;
1100
+ };
1101
+ }
1102
+ // Types already exported via 'export interface'
1103
+ export { IntegrationEngine };
1104
+ export default IntegrationEngine;
1105
+ //# sourceMappingURL=integration.js.map