contextsynapse 1.0.0__py3-none-any.whl

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 (776) hide show
  1. contextsynapse/__init__.py +107 -0
  2. contextsynapse/__main__.py +9 -0
  3. contextsynapse/a2a/__init__.py +28 -0
  4. contextsynapse/a2a/client.py +120 -0
  5. contextsynapse/a2a/discovery.py +128 -0
  6. contextsynapse/a2a/handlers.py +164 -0
  7. contextsynapse/a2a/models.py +246 -0
  8. contextsynapse/a2a/streaming.py +92 -0
  9. contextsynapse/a2a/task_manager.py +275 -0
  10. contextsynapse/adapters/__init__.py +98 -0
  11. contextsynapse/adapters/_base.py +298 -0
  12. contextsynapse/adapters/autogen/__init__.py +4 -0
  13. contextsynapse/adapters/autogen/tools.py +34 -0
  14. contextsynapse/adapters/crewai/__init__.py +4 -0
  15. contextsynapse/adapters/crewai/tools.py +63 -0
  16. contextsynapse/adapters/langchain/__init__.py +19 -0
  17. contextsynapse/adapters/langchain/message_history.py +17 -0
  18. contextsynapse/adapters/langchain/retriever.py +158 -0
  19. contextsynapse/adapters/langchain/tools.py +43 -0
  20. contextsynapse/adapters/langgraph/__init__.py +21 -0
  21. contextsynapse/adapters/langgraph/checkpoint.py +223 -0
  22. contextsynapse/adapters/langgraph/context_tools.py +341 -0
  23. contextsynapse/adapters/langgraph/message_history.py +138 -0
  24. contextsynapse/adapters/langgraph/tools.py +43 -0
  25. contextsynapse/adapters/llamaindex/__init__.py +4 -0
  26. contextsynapse/adapters/llamaindex/tools.py +64 -0
  27. contextsynapse/adapters/openai/__init__.py +24 -0
  28. contextsynapse/adapters/openai/tools.py +206 -0
  29. contextsynapse/adapters/pydantic_ai/__init__.py +4 -0
  30. contextsynapse/adapters/pydantic_ai/tools.py +36 -0
  31. contextsynapse/adapters/swarm/__init__.py +4 -0
  32. contextsynapse/adapters/swarm/tools.py +44 -0
  33. contextsynapse/agents/__init__.py +6 -0
  34. contextsynapse/agents/auto_capture.py +80 -0
  35. contextsynapse/agents/dispatcher.py +299 -0
  36. contextsynapse/agents/notifications.py +112 -0
  37. contextsynapse/aiql/__init__.py +71 -0
  38. contextsynapse/aiql/cache.py +341 -0
  39. contextsynapse/aiql/compiler/__init__.py +62 -0
  40. contextsynapse/aiql/compiler/optimizer.py +126 -0
  41. contextsynapse/aiql/compiler/planner.py +366 -0
  42. contextsynapse/aiql/compiler/statistics.py +235 -0
  43. contextsynapse/aiql/compiler/validator.py +425 -0
  44. contextsynapse/aiql/engine/__init__.py +11 -0
  45. contextsynapse/aiql/engine/chunk_storage.py +2584 -0
  46. contextsynapse/aiql/engine/executor.py +7737 -0
  47. contextsynapse/aiql/engine/extraction_integration.py +442 -0
  48. contextsynapse/aiql/engine/graph_builder.py +405 -0
  49. contextsynapse/aiql/engine/node_creation_from_normalized.py +691 -0
  50. contextsynapse/aiql/engine/performance_monitor.py +289 -0
  51. contextsynapse/aiql/engine/postprocessing.py +365 -0
  52. contextsynapse/aiql/engine/ray_stage_executors.py +918 -0
  53. contextsynapse/aiql/engine/redis_cache.py +106 -0
  54. contextsynapse/aiql/engine/streaming_json.py +366 -0
  55. contextsynapse/aiql/engine/streaming_parquet.py +568 -0
  56. contextsynapse/aiql/engine/streaming_ray_chunking.py +419 -0
  57. contextsynapse/aiql/grammar/__init__.py +14 -0
  58. contextsynapse/aiql/grammar/aiql_grammar.py +1822 -0
  59. contextsynapse/aiql/grammar/base.py +71 -0
  60. contextsynapse/aiql/parser/__init__.py +46 -0
  61. contextsynapse/aiql/parser/aiql_parser.py +11330 -0
  62. contextsynapse/aiql/parser/base_parser.py +47 -0
  63. contextsynapse/api/__init__.py +5 -0
  64. contextsynapse/api/a2a_router.py +233 -0
  65. contextsynapse/api/admin_router.py +140 -0
  66. contextsynapse/api/agent_worker_router.py +978 -0
  67. contextsynapse/api/algorithms_router.py +317 -0
  68. contextsynapse/api/api.py +4144 -0
  69. contextsynapse/api/audit.py +204 -0
  70. contextsynapse/api/auth.py +441 -0
  71. contextsynapse/api/auth_router.py +537 -0
  72. contextsynapse/api/billing.py +261 -0
  73. contextsynapse/api/billing_router.py +275 -0
  74. contextsynapse/api/boundary_router.py +452 -0
  75. contextsynapse/api/cognition_router.py +116 -0
  76. contextsynapse/api/connector_router.py +237 -0
  77. contextsynapse/api/context_router.py +1619 -0
  78. contextsynapse/api/dashboard_router.py +11367 -0
  79. contextsynapse/api/errors.py +183 -0
  80. contextsynapse/api/events.py +88 -0
  81. contextsynapse/api/experiment_bootstrap.py +321 -0
  82. contextsynapse/api/experiment_orchestrator.py +1078 -0
  83. contextsynapse/api/experiment_router.py +2089 -0
  84. contextsynapse/api/feature_gate.py +89 -0
  85. contextsynapse/api/federation_router.py +108 -0
  86. contextsynapse/api/integrations.py +567 -0
  87. contextsynapse/api/integrations_router.py +461 -0
  88. contextsynapse/api/intelligence_router.py +1028 -0
  89. contextsynapse/api/metering.py +155 -0
  90. contextsynapse/api/metrics.py +112 -0
  91. contextsynapse/api/models.py +38 -0
  92. contextsynapse/api/monitoring_router.py +174 -0
  93. contextsynapse/api/pipeline_router.py +1437 -0
  94. contextsynapse/api/playground_conn.py +116 -0
  95. contextsynapse/api/projects_router.py +131 -0
  96. contextsynapse/api/queries_router.py +282 -0
  97. contextsynapse/api/quota.py +95 -0
  98. contextsynapse/api/rate_limit.py +64 -0
  99. contextsynapse/api/search_router.py +261 -0
  100. contextsynapse/api/shield_router.py +447 -0
  101. contextsynapse/api/tenant_guard.py +103 -0
  102. contextsynapse/api/tenant_quotas.py +231 -0
  103. contextsynapse/api/tenants.py +305 -0
  104. contextsynapse/api/users.py +646 -0
  105. contextsynapse/api/v1.py +167 -0
  106. contextsynapse/api/vertical_builder_router.py +387 -0
  107. contextsynapse/benchmark/__init__.py +15 -0
  108. contextsynapse/benchmark/__main__.py +64 -0
  109. contextsynapse/benchmark/agents.py +338 -0
  110. contextsynapse/benchmark/live_ab.py +338 -0
  111. contextsynapse/benchmark/reporter.py +149 -0
  112. contextsynapse/benchmark/runner.py +264 -0
  113. contextsynapse/benchmark/savings.py +266 -0
  114. contextsynapse/benchmark/token_counter.py +212 -0
  115. contextsynapse/benchmark/workloads.py +289 -0
  116. contextsynapse/buffer/__init__.py +154 -0
  117. contextsynapse/buffer/base.py +257 -0
  118. contextsynapse/buffer/duckdb_buffer.py +246 -0
  119. contextsynapse/buffer/file_buffer.py +229 -0
  120. contextsynapse/buffer/lmdb_buffer.py +286 -0
  121. contextsynapse/buffer/local_buffer.py +154 -0
  122. contextsynapse/buffer/redis_buffer.py +211 -0
  123. contextsynapse/buffer/sqlite_buffer.py +266 -0
  124. contextsynapse/cache.py +2 -0
  125. contextsynapse/cli/__init__.py +40 -0
  126. contextsynapse/cli/cli.py +475 -0
  127. contextsynapse/cli/config_cli.py +177 -0
  128. contextsynapse/cli/scaffold.py +465 -0
  129. contextsynapse/cognition/__init__.py +31 -0
  130. contextsynapse/cognition/derivation.py +55 -0
  131. contextsynapse/cognition/events.py +135 -0
  132. contextsynapse/cognition/feedback.py +52 -0
  133. contextsynapse/cognition/hallucination.py +90 -0
  134. contextsynapse/cognition/invalidation.py +70 -0
  135. contextsynapse/cognition/read_tracker.py +50 -0
  136. contextsynapse/collaboration.py +2 -0
  137. contextsynapse/comparison.py +2 -0
  138. contextsynapse/config/__init__.py +10 -0
  139. contextsynapse/config/connectors/amfi_nav.yaml +18 -0
  140. contextsynapse/config/connectors/auto_sector.yaml +20 -0
  141. contextsynapse/config/connectors/banking_sector.yaml +20 -0
  142. contextsynapse/config/connectors/energy_sector.yaml +20 -0
  143. contextsynapse/config/connectors/fmcg_sector.yaml +20 -0
  144. contextsynapse/config/connectors/nsdl_fpi.yaml +9 -0
  145. contextsynapse/config/connectors/nse_price.yaml +61 -0
  146. contextsynapse/config/connectors/pharma_sector.yaml +20 -0
  147. contextsynapse/config/connectors/rbi_dbie.yaml +12 -0
  148. contextsynapse/config/context_presets/ai_research.json +25 -0
  149. contextsynapse/config/context_presets/chatgpt_conversations.json +19 -0
  150. contextsynapse/config/context_presets/claude_conversations.json +19 -0
  151. contextsynapse/config/context_presets/legal_compliance.json +21 -0
  152. contextsynapse/config/context_presets/meeting_notes.json +21 -0
  153. contextsynapse/config/context_presets/slack_engineering.json +21 -0
  154. contextsynapse/config/context_presets/tech_climate.json +24 -0
  155. contextsynapse/config/context_presets/toi_politics.json +25 -0
  156. contextsynapse/config/database_config.py +453 -0
  157. contextsynapse/config/deployment.py +221 -0
  158. contextsynapse/config/gpt_action_schema.json +164 -0
  159. contextsynapse/config/indicators/india_macro.yaml +213 -0
  160. contextsynapse/config/logging_config.py +88 -0
  161. contextsynapse/config/mode_config.py +223 -0
  162. contextsynapse/config/schemas/api_spec.yaml +48 -0
  163. contextsynapse/config/schemas/architecture_doc.yaml +51 -0
  164. contextsynapse/config/schemas/chat_history.yaml +90 -0
  165. contextsynapse/config/schemas/chatgpt_conversation.yaml +101 -0
  166. contextsynapse/config/schemas/claude_conversation.yaml +148 -0
  167. contextsynapse/config/schemas/contract.yaml +48 -0
  168. contextsynapse/config/schemas/conversation.yaml +167 -0
  169. contextsynapse/config/schemas/database.yaml +74 -0
  170. contextsynapse/config/schemas/decision.yaml +72 -0
  171. contextsynapse/config/schemas/ecommerce.yaml +56 -0
  172. contextsynapse/config/schemas/education.yaml +42 -0
  173. contextsynapse/config/schemas/healthcare.yaml +133 -0
  174. contextsynapse/config/schemas/hr_document.yaml +48 -0
  175. contextsynapse/config/schemas/invoice.yaml +40 -0
  176. contextsynapse/config/schemas/knowledge_base.yaml +75 -0
  177. contextsynapse/config/schemas/legal.yaml +42 -0
  178. contextsynapse/config/schemas/marketing_content.yaml +48 -0
  179. contextsynapse/config/schemas/meeting_notes.yaml +51 -0
  180. contextsynapse/config/schemas/news_article.yaml +61 -0
  181. contextsynapse/config/schemas/real_estate.yaml +49 -0
  182. contextsynapse/config/schemas/requirements_doc.yaml +48 -0
  183. contextsynapse/config/schemas/research_paper.yaml +56 -0
  184. contextsynapse/config/schemas/resume.yaml +49 -0
  185. contextsynapse/config/schemas/retail.yaml +42 -0
  186. contextsynapse/config/schemas/rule_meta.yaml +173 -0
  187. contextsynapse/config/schemas/rules.yaml +72 -0
  188. contextsynapse/config/schemas/screener_meta.yaml +236 -0
  189. contextsynapse/config/schemas/sdlc.yaml +103 -0
  190. contextsynapse/config/schemas/session_graph.yaml +172 -0
  191. contextsynapse/config/schemas/support_ticket.yaml +48 -0
  192. contextsynapse/config/schemas/web.yaml +64 -0
  193. contextsynapse/config/sensors/earnings_calendar.yaml +52 -0
  194. contextsynapse/config/sensors/global_risk.yaml +53 -0
  195. contextsynapse/config/sensors/government_policy.yaml +54 -0
  196. contextsynapse/config/sensors/supply_chain.yaml +50 -0
  197. contextsynapse/config/sensors/templates/behavioral.yaml +56 -0
  198. contextsynapse/config/sensors/templates/equity_sentiment.yaml +48 -0
  199. contextsynapse/config/sensors/templates/global_macro.yaml +47 -0
  200. contextsynapse/config/sensors/templates/market_data.yaml +118 -0
  201. contextsynapse/config/sensors/templates/sector_technical.yaml +47 -0
  202. contextsynapse/config/sensors/weather.yaml +52 -0
  203. contextsynapse/config/storage_strategy.py +202 -0
  204. contextsynapse/config/templates/competitive_intel.yaml +39 -0
  205. contextsynapse/config/templates/geopolitical_risk.yaml +46 -0
  206. contextsynapse/config/templates/market_analysis.yaml +58 -0
  207. contextsynapse/connectors/__init__.py +15 -0
  208. contextsynapse/connectors/api_router.py +121 -0
  209. contextsynapse/connectors/base.py +357 -0
  210. contextsynapse/connectors/financial/audio.py +170 -0
  211. contextsynapse/connectors/financial/youtube.py +272 -0
  212. contextsynapse/connectors/github.py +164 -0
  213. contextsynapse/connectors/jira.py +120 -0
  214. contextsynapse/connectors/kafka_connector.py +124 -0
  215. contextsynapse/connectors/pipeline_connector.py +747 -0
  216. contextsynapse/connectors/registry.py +116 -0
  217. contextsynapse/connectors/scheduler.py +87 -0
  218. contextsynapse/connectors/universal.py +360 -0
  219. contextsynapse/context/__init__.py +96 -0
  220. contextsynapse/context/__main__.py +4 -0
  221. contextsynapse/context/acl.py +125 -0
  222. contextsynapse/context/agent_card.py +201 -0
  223. contextsynapse/context/agent_memory.py +814 -0
  224. contextsynapse/context/agents.py +472 -0
  225. contextsynapse/context/agents_redis.py +391 -0
  226. contextsynapse/context/assembled.py +204 -0
  227. contextsynapse/context/attribution.py +113 -0
  228. contextsynapse/context/blob.py +184 -0
  229. contextsynapse/context/boundaries.py +187 -0
  230. contextsynapse/context/boundary.py +507 -0
  231. contextsynapse/context/bundle.py +155 -0
  232. contextsynapse/context/cli.py +519 -0
  233. contextsynapse/context/collaboration.py +165 -0
  234. contextsynapse/context/compiler.py +604 -0
  235. contextsynapse/context/composite.py +536 -0
  236. contextsynapse/context/compression.py +147 -0
  237. contextsynapse/context/context_manager.py +888 -0
  238. contextsynapse/context/context_schema.py +90 -0
  239. contextsynapse/context/context_schema.yaml +105 -0
  240. contextsynapse/context/context_units.py +891 -0
  241. contextsynapse/context/conversation.py +488 -0
  242. contextsynapse/context/dedup.py +207 -0
  243. contextsynapse/context/document_processor.py +698 -0
  244. contextsynapse/context/embedding_hooks.py +338 -0
  245. contextsynapse/context/execution_schema.py +274 -0
  246. contextsynapse/context/fan_out.py +138 -0
  247. contextsynapse/context/frozen.py +80 -0
  248. contextsynapse/context/gravity.py +227 -0
  249. contextsynapse/context/hub.py +1401 -0
  250. contextsynapse/context/ingest.py +391 -0
  251. contextsynapse/context/injection.py +226 -0
  252. contextsynapse/context/interaction_graphifier.py +562 -0
  253. contextsynapse/context/layers.py +574 -0
  254. contextsynapse/context/projection.py +1195 -0
  255. contextsynapse/context/promotion.py +634 -0
  256. contextsynapse/context/proof.py +131 -0
  257. contextsynapse/context/propagation.py +577 -0
  258. contextsynapse/context/pubsub.py +135 -0
  259. contextsynapse/context/quality.py +1054 -0
  260. contextsynapse/context/quality_tracker.py +270 -0
  261. contextsynapse/context/scoping.py +370 -0
  262. contextsynapse/context/seed.py +992 -0
  263. contextsynapse/context/session.py +1142 -0
  264. contextsynapse/context/session_graph.py +593 -0
  265. contextsynapse/context/session_memory.py +309 -0
  266. contextsynapse/context/session_resolver.py +111 -0
  267. contextsynapse/context/skill_learning.py +237 -0
  268. contextsynapse/context/smart_budget.py +129 -0
  269. contextsynapse/context/source_policy.py +242 -0
  270. contextsynapse/context/store_factory.py +53 -0
  271. contextsynapse/context/sync.py +648 -0
  272. contextsynapse/context/token.py +236 -0
  273. contextsynapse/context/vector_integration.py +297 -0
  274. contextsynapse/context/webhooks.py +194 -0
  275. contextsynapse/context/working_memory.py +224 -0
  276. contextsynapse/core/__init__.py +18 -0
  277. contextsynapse/core/archiver.py +237 -0
  278. contextsynapse/core/change_stream.py +282 -0
  279. contextsynapse/core/checkpoint.py +310 -0
  280. contextsynapse/core/cloud_storage.py +387 -0
  281. contextsynapse/core/context_state.py +651 -0
  282. contextsynapse/core/cron.py +324 -0
  283. contextsynapse/core/datasource.py +643 -0
  284. contextsynapse/core/db.py +289 -0
  285. contextsynapse/core/federation.py +283 -0
  286. contextsynapse/core/graph_coordinator.py +201 -0
  287. contextsynapse/core/graph_intelligence.py +388 -0
  288. contextsynapse/core/graph_structures.py +106 -0
  289. contextsynapse/core/graph_sync.py +157 -0
  290. contextsynapse/core/hybrid_graph_storage.py +2998 -0
  291. contextsynapse/core/lifecycle.py +691 -0
  292. contextsynapse/core/multiworker.py +378 -0
  293. contextsynapse/core/pruning.py +312 -0
  294. contextsynapse/core/redis_registry.py +524 -0
  295. contextsynapse/core/registry.py +1043 -0
  296. contextsynapse/core/registry_factory.py +51 -0
  297. contextsynapse/core/registry_metadata.py +294 -0
  298. contextsynapse/core/replay.py +354 -0
  299. contextsynapse/core/replication.py +339 -0
  300. contextsynapse/core/time_travel.py +260 -0
  301. contextsynapse/core/write_behind.py +152 -0
  302. contextsynapse/core/write_context.py +39 -0
  303. contextsynapse/db/__init__.py +1 -0
  304. contextsynapse/db/postgres.py +267 -0
  305. contextsynapse/db/profile.py +236 -0
  306. contextsynapse/db/rules.py +328 -0
  307. contextsynapse/demo/__init__.py +0 -0
  308. contextsynapse/demo/report.py +147 -0
  309. contextsynapse/demo/runner.py +520 -0
  310. contextsynapse/demo/scenario.py +165 -0
  311. contextsynapse/demo/session_demo.py +280 -0
  312. contextsynapse/demo/session_report.py +143 -0
  313. contextsynapse/demo/universal_runner.py +257 -0
  314. contextsynapse/engine/__init__.py +15 -0
  315. contextsynapse/engine/core.py +555 -0
  316. contextsynapse/extraction/__init__.py +69 -0
  317. contextsynapse/extraction/cli.py +274 -0
  318. contextsynapse/extraction/config.py +107 -0
  319. contextsynapse/extraction/examples/example_usage.py +118 -0
  320. contextsynapse/extraction/examples/sample_manifest.json +53 -0
  321. contextsynapse/extraction/examples/sample_normalized.json +185 -0
  322. contextsynapse/extraction/extract_engine.py +440 -0
  323. contextsynapse/extraction/extractors/__init__.py +37 -0
  324. contextsynapse/extraction/extractors/chat_export_extractor.py +189 -0
  325. contextsynapse/extraction/extractors/csv_extractor.py +83 -0
  326. contextsynapse/extraction/extractors/docx_extractor.py +129 -0
  327. contextsynapse/extraction/extractors/excel_extractor.py +152 -0
  328. contextsynapse/extraction/extractors/html_extractor.py +146 -0
  329. contextsynapse/extraction/extractors/pdf_extractor.py +635 -0
  330. contextsynapse/extraction/extractors/pdf_extractor_layoutparser.py +408 -0
  331. contextsynapse/extraction/extractors/register_extractors.py +63 -0
  332. contextsynapse/extraction/extractors/text_extractor.py +65 -0
  333. contextsynapse/extraction/extractors/txt_extractor.py +120 -0
  334. contextsynapse/extraction/extractors/website_extractor.py +246 -0
  335. contextsynapse/extraction/fact_extractor.py +236 -0
  336. contextsynapse/extraction/file_manager.py +353 -0
  337. contextsynapse/extraction/hierarchy.py +239 -0
  338. contextsynapse/extraction/id_generator.py +450 -0
  339. contextsynapse/extraction/layout_detector.py +409 -0
  340. contextsynapse/extraction/llm_entity_extractor.py +301 -0
  341. contextsynapse/extraction/normalized_store.py +480 -0
  342. contextsynapse/extraction/normalizer.py +594 -0
  343. contextsynapse/extraction/parquet_writer.py +598 -0
  344. contextsynapse/extraction/post_processors/__init__.py +40 -0
  345. contextsynapse/extraction/post_processors/column_reorganizer.py +507 -0
  346. contextsynapse/extraction/ray_normalization.py +233 -0
  347. contextsynapse/extraction/ray_runner.py +207 -0
  348. contextsynapse/extraction/redis_schema_registry.py +222 -0
  349. contextsynapse/extraction/registry.py +204 -0
  350. contextsynapse/extraction/schema_loader.py +663 -0
  351. contextsynapse/extraction/schema_registry.py +230 -0
  352. contextsynapse/extraction/semantic_normalizer.py +245 -0
  353. contextsynapse/extraction/version_manager.py +314 -0
  354. contextsynapse/gateway/__init__.py +24 -0
  355. contextsynapse/gateway/action_emitter.py +212 -0
  356. contextsynapse/gateway/cost_tracker.py +508 -0
  357. contextsynapse/gateway/gateway.py +377 -0
  358. contextsynapse/gateway/policy.py +303 -0
  359. contextsynapse/governance/__init__.py +13 -0
  360. contextsynapse/governance/layer.py +513 -0
  361. contextsynapse/ingestion/__init__.py +15 -0
  362. contextsynapse/ingestion/amplifier.py +288 -0
  363. contextsynapse/ingestion/async_ingest.py +463 -0
  364. contextsynapse/ingestion/chunker.py +303 -0
  365. contextsynapse/ingestion/chunking.py +58 -0
  366. contextsynapse/ingestion/cleaner.py +190 -0
  367. contextsynapse/ingestion/cleanse.py +252 -0
  368. contextsynapse/ingestion/connectors/__init__.py +38 -0
  369. contextsynapse/ingestion/connectors/base.py +300 -0
  370. contextsynapse/ingestion/connectors/chatgpt_memory.py +247 -0
  371. contextsynapse/ingestion/connectors/claude_memory.py +274 -0
  372. contextsynapse/ingestion/connectors/sap_ingestor.py +208 -0
  373. contextsynapse/ingestion/content_detector.py +80 -0
  374. contextsynapse/ingestion/content_monitor.py +502 -0
  375. contextsynapse/ingestion/dedup.py +106 -0
  376. contextsynapse/ingestion/feed.py +640 -0
  377. contextsynapse/ingestion/filters.py +461 -0
  378. contextsynapse/ingestion/graph_builder.py +705 -0
  379. contextsynapse/ingestion/input_classifier.py +307 -0
  380. contextsynapse/ingestion/job_manager.py +571 -0
  381. contextsynapse/ingestion/llm_extractor.py +610 -0
  382. contextsynapse/ingestion/orchestrator.py +116 -0
  383. contextsynapse/ingestion/parsers/__init__.py +19 -0
  384. contextsynapse/ingestion/parsers/graph_parser_registry.py +103 -0
  385. contextsynapse/ingestion/parsers/graphml_parser.py +141 -0
  386. contextsynapse/ingestion/parsers/jsonld_parser.py +171 -0
  387. contextsynapse/ingestion/parsers/rdf_parser.py +150 -0
  388. contextsynapse/ingestion/pipeline_context.py +228 -0
  389. contextsynapse/ingestion/pipeline_store.py +1195 -0
  390. contextsynapse/ingestion/queue.py +133 -0
  391. contextsynapse/ingestion/reprocess.py +179 -0
  392. contextsynapse/ingestion/scenario_router.py +224 -0
  393. contextsynapse/ingestion/schema_extractor.py +759 -0
  394. contextsynapse/ingestion/schema_validator.py +274 -0
  395. contextsynapse/ingestion/sdlc_ingest.py +87 -0
  396. contextsynapse/ingestion/smart_ingest.py +2451 -0
  397. contextsynapse/ingestion/source_connector.py +171 -0
  398. contextsynapse/ingestion/stage_executor.py +2095 -0
  399. contextsynapse/ingestion/stages/__init__.py +9 -0
  400. contextsynapse/ingestion/stages/tabular_to_graph.py +289 -0
  401. contextsynapse/ingestion/strategies.py +386 -0
  402. contextsynapse/ingestion/universal/__init__.py +4 -0
  403. contextsynapse/ingestion/universal/_operator_registry.py +59 -0
  404. contextsynapse/ingestion/universal/ingest_content.py +32 -0
  405. contextsynapse/ingestion/universal/operators/__init__.py +1 -0
  406. contextsynapse/ingestion/universal/operators/base.py +19 -0
  407. contextsynapse/ingestion/universal/operators/build_edges.py +75 -0
  408. contextsynapse/ingestion/universal/operators/cluster_topics.py +397 -0
  409. contextsynapse/ingestion/universal/operators/deduplicate.py +45 -0
  410. contextsynapse/ingestion/universal/operators/detect_signals.py +90 -0
  411. contextsynapse/ingestion/universal/operators/embed.py +80 -0
  412. contextsynapse/ingestion/universal/operators/extract_entities.py +253 -0
  413. contextsynapse/ingestion/universal/operators/extract_preferences.py +117 -0
  414. contextsynapse/ingestion/universal/operators/filter_content.py +69 -0
  415. contextsynapse/ingestion/universal/operators/index_bm25.py +52 -0
  416. contextsynapse/ingestion/universal/operators/infer_domains.py +69 -0
  417. contextsynapse/ingestion/universal/operators/link_cross_reference.py +210 -0
  418. contextsynapse/ingestion/universal/operators/parse_records.py +66 -0
  419. contextsynapse/ingestion/universal/operators/resolve_entities.py +261 -0
  420. contextsynapse/ingestion/universal/operators/scanners/__init__.py +16 -0
  421. contextsynapse/ingestion/universal/operators/scanners/edges.py +173 -0
  422. contextsynapse/ingestion/universal/operators/scanners/git.py +187 -0
  423. contextsynapse/ingestion/universal/operators/scanners/github.py +135 -0
  424. contextsynapse/ingestion/universal/operators/scanners/github_api.py +509 -0
  425. contextsynapse/ingestion/universal/operators/scanners/helpers.py +67 -0
  426. contextsynapse/ingestion/universal/operators/scanners/jira.py +65 -0
  427. contextsynapse/ingestion/universal/operators/scanners/llm_enrichment.py +82 -0
  428. contextsynapse/ingestion/universal/operators/scanners/repo.py +149 -0
  429. contextsynapse/ingestion/universal/operators/sdlc_scan.py +213 -0
  430. contextsynapse/ingestion/universal/operators/spec_scanner.py +149 -0
  431. contextsynapse/ingestion/universal/operators/store_documents.py +72 -0
  432. contextsynapse/ingestion/universal/operators/synthesize_cu.py +180 -0
  433. contextsynapse/ingestion/universal/operators/validate_gate.py +65 -0
  434. contextsynapse/ingestion/universal/parsers/__init__.py +5 -0
  435. contextsynapse/ingestion/universal/parsers/record_parser.py +203 -0
  436. contextsynapse/ingestion/universal/parsers/turn_parser.py +329 -0
  437. contextsynapse/ingestion/universal/shared_signals.py +161 -0
  438. contextsynapse/ingestion/universal/stage_executor.py +219 -0
  439. contextsynapse/ingestion/web_crawler.py +265 -0
  440. contextsynapse/intelligence/__init__.py +53 -0
  441. contextsynapse/intelligence/alerts.py +198 -0
  442. contextsynapse/intelligence/collector.py +655 -0
  443. contextsynapse/intelligence/comparison.py +198 -0
  444. contextsynapse/intelligence/config.py +56 -0
  445. contextsynapse/intelligence/conflict_detector.py +182 -0
  446. contextsynapse/intelligence/context_gaps.py +192 -0
  447. contextsynapse/intelligence/context_radar.py +135 -0
  448. contextsynapse/intelligence/correlation_engine.py +416 -0
  449. contextsynapse/intelligence/correlation_template.py +120 -0
  450. contextsynapse/intelligence/dedup.py +296 -0
  451. contextsynapse/intelligence/event_bus.py +91 -0
  452. contextsynapse/intelligence/feedback_loop.py +101 -0
  453. contextsynapse/intelligence/freshness.py +307 -0
  454. contextsynapse/intelligence/fundamental_feed.py +551 -0
  455. contextsynapse/intelligence/geo_data.py +170 -0
  456. contextsynapse/intelligence/geo_reference.py +112 -0
  457. contextsynapse/intelligence/graph_fusion.py +465 -0
  458. contextsynapse/intelligence/heuristics.py +176 -0
  459. contextsynapse/intelligence/impact_tracker.py +336 -0
  460. contextsynapse/intelligence/macro_indicators.py +319 -0
  461. contextsynapse/intelligence/ocr.py +104 -0
  462. contextsynapse/intelligence/persistence.py +267 -0
  463. contextsynapse/intelligence/pipeline_health.py +130 -0
  464. contextsynapse/intelligence/price_feed.py +221 -0
  465. contextsynapse/intelligence/rate_limiter.py +130 -0
  466. contextsynapse/intelligence/reactive.py +411 -0
  467. contextsynapse/intelligence/runtime_context.py +390 -0
  468. contextsynapse/intelligence/sentiment_decay.py +426 -0
  469. contextsynapse/intelligence/session.py +277 -0
  470. contextsynapse/intelligence/signal_hierarchy.py +438 -0
  471. contextsynapse/intelligence/signals.py +185 -0
  472. contextsynapse/intelligence/source_watcher.py +132 -0
  473. contextsynapse/intelligence/table_enricher.py +256 -0
  474. contextsynapse/intelligence/tagger.py +319 -0
  475. contextsynapse/intelligence/timeseries.py +209 -0
  476. contextsynapse/intelligence/tracker.py +318 -0
  477. contextsynapse/intelligence/watchdog.py +392 -0
  478. contextsynapse/intelligence/watchdog_manager.py +263 -0
  479. contextsynapse/intelligence/webhook_receiver.py +165 -0
  480. contextsynapse/intelligence/weight_learner.py +234 -0
  481. contextsynapse/llm/__init__.py +8 -0
  482. contextsynapse/llm/client.py +348 -0
  483. contextsynapse/llm/rate_limiter.py +166 -0
  484. contextsynapse/logging_config.py +2 -0
  485. contextsynapse/marketplace/__init__.py +7 -0
  486. contextsynapse/marketplace/registry.py +173 -0
  487. contextsynapse/mcp/__init__.py +11 -0
  488. contextsynapse/mcp/__main__.py +4 -0
  489. contextsynapse/mcp/auth_middleware.py +212 -0
  490. contextsynapse/mcp/connection_pool.py +128 -0
  491. contextsynapse/mcp/server.py +986 -0
  492. contextsynapse/mcp/session_context.py +67 -0
  493. contextsynapse/memory/__init__.py +34 -0
  494. contextsynapse/memory/engine.py +475 -0
  495. contextsynapse/memory/temporal.py +327 -0
  496. contextsynapse/metadata/__init__.py +12 -0
  497. contextsynapse/metadata/metadata_db.py +272 -0
  498. contextsynapse/metadata/metadata_query_tool.py +300 -0
  499. contextsynapse/metadata/metadata_tracker.py +425 -0
  500. contextsynapse/models/__init__.py +27 -0
  501. contextsynapse/models/embedding_service.py +360 -0
  502. contextsynapse/models/model_registry.py +228 -0
  503. contextsynapse/multiworker.py +2 -0
  504. contextsynapse/pipelines/__init__.py +1 -0
  505. contextsynapse/pipelines/executor.py +851 -0
  506. contextsynapse/pipelines/filters.py +189 -0
  507. contextsynapse/pipelines/models.py +176 -0
  508. contextsynapse/pipelines/scheduler.py +268 -0
  509. contextsynapse/playground/__init__.py +1 -0
  510. contextsynapse/playground/templates.py +85 -0
  511. contextsynapse/plugins/__init__.py +43 -0
  512. contextsynapse/plugins/api.py +66 -0
  513. contextsynapse/plugins/base.py +350 -0
  514. contextsynapse/plugins/domain_interface.py +508 -0
  515. contextsynapse/plugins/domain_loader.py +241 -0
  516. contextsynapse/plugins/loader.py +148 -0
  517. contextsynapse/plugins/registry.py +265 -0
  518. contextsynapse/project/__init__.py +11 -0
  519. contextsynapse/project/code_context.py +807 -0
  520. contextsynapse/project/connectors/__init__.py +4 -0
  521. contextsynapse/project/connectors/github_connector.py +113 -0
  522. contextsynapse/project/connectors/jira_connector.py +160 -0
  523. contextsynapse/project/graph.py +1023 -0
  524. contextsynapse/project/project_context.py +545 -0
  525. contextsynapse/project/scanner_registry.py +61 -0
  526. contextsynapse/project/schema_manager.py +322 -0
  527. contextsynapse/project/schemas/knowledge.yaml +59 -0
  528. contextsynapse/project/schemas/sdlc.yaml +369 -0
  529. contextsynapse/project/sdlc_schema.py +172 -0
  530. contextsynapse/project/spec_parser.py +85 -0
  531. contextsynapse/project/task_lock.py +181 -0
  532. contextsynapse/project/task_stream.py +203 -0
  533. contextsynapse/project/team_tools.py +537 -0
  534. contextsynapse/py.typed +0 -0
  535. contextsynapse/realtime/__init__.py +6 -0
  536. contextsynapse/realtime/collaboration.py +147 -0
  537. contextsynapse/rules/__init__.py +10 -0
  538. contextsynapse/rules/engine.py +116 -0
  539. contextsynapse/rules/evaluators/__init__.py +6 -0
  540. contextsynapse/rules/evaluators/aggregate.py +205 -0
  541. contextsynapse/rules/evaluators/custom.py +170 -0
  542. contextsynapse/rules/evaluators/pre_action.py +125 -0
  543. contextsynapse/rules/evaluators/temporal.py +129 -0
  544. contextsynapse/rules/loader.py +52 -0
  545. contextsynapse/rules/models.py +124 -0
  546. contextsynapse/rules/universal.py +393 -0
  547. contextsynapse/scheduler.py +229 -0
  548. contextsynapse/schema/__init__.py +42 -0
  549. contextsynapse/schema/compiler.py +252 -0
  550. contextsynapse/schema/composer.py +158 -0
  551. contextsynapse/schema/dedup.py +73 -0
  552. contextsynapse/schema/derivation.py +172 -0
  553. contextsynapse/schema/sdl.py +326 -0
  554. contextsynapse/schema/validation_gate.py +124 -0
  555. contextsynapse/sdk/__init__.py +63 -0
  556. contextsynapse/sdk/agent.py +214 -0
  557. contextsynapse/sdk/client.py +269 -0
  558. contextsynapse/sdk/exceptions.py +23 -0
  559. contextsynapse/sdk/models.py +78 -0
  560. contextsynapse/sdk/session.py +408 -0
  561. contextsynapse/sdk/tracked.py +218 -0
  562. contextsynapse/sdk/worker.py +266 -0
  563. contextsynapse/sdk/workspace_client.py +98 -0
  564. contextsynapse/sdk/ws.py +41 -0
  565. contextsynapse/search/__init__.py +20 -0
  566. contextsynapse/search/embedding_cache.py +140 -0
  567. contextsynapse/search/enhanced_search.py +152 -0
  568. contextsynapse/search/fulltext.py +130 -0
  569. contextsynapse/search/graph_search.py +634 -0
  570. contextsynapse/search/lmdb_index.py +1218 -0
  571. contextsynapse/search/nl_to_aiql.py +199 -0
  572. contextsynapse/search/rag.py +1346 -0
  573. contextsynapse/search/rag_cache.py +167 -0
  574. contextsynapse/search/reasoning_chain.py +231 -0
  575. contextsynapse/search/redis_search.py +207 -0
  576. contextsynapse/search/retrieval_quality.py +314 -0
  577. contextsynapse/search/semantic_query.py +455 -0
  578. contextsynapse/search/text_resolver.py +159 -0
  579. contextsynapse/search/whoosh_search.py +373 -0
  580. contextsynapse/security/__init__.py +17 -0
  581. contextsynapse/security/audit.py +297 -0
  582. contextsynapse/security/audit_logger.py +97 -0
  583. contextsynapse/security/audit_trail.py +270 -0
  584. contextsynapse/security/auth_unified.py +284 -0
  585. contextsynapse/security/auto_tagger.py +230 -0
  586. contextsynapse/security/data_security.py +218 -0
  587. contextsynapse/security/encryption.py +207 -0
  588. contextsynapse/security/identity.py +447 -0
  589. contextsynapse/security/jwt_identity.py +59 -0
  590. contextsynapse/security/middleware.py +336 -0
  591. contextsynapse/security/pii.py +233 -0
  592. contextsynapse/security/rbac.py +96 -0
  593. contextsynapse/security/rls.py +205 -0
  594. contextsynapse/security/sanitize.py +233 -0
  595. contextsynapse/security/scoped_encryption.py +131 -0
  596. contextsynapse/security/tenant.py +401 -0
  597. contextsynapse/shield/__init__.py +21 -0
  598. contextsynapse/shield/anomaly.py +56 -0
  599. contextsynapse/shield/permissions.py +99 -0
  600. contextsynapse/shield/profile.py +103 -0
  601. contextsynapse/shield/shield.py +108 -0
  602. contextsynapse/shield/trust_engine.py +69 -0
  603. contextsynapse/skills/__init__.py +14 -0
  604. contextsynapse/skills/engine.py +233 -0
  605. contextsynapse/skills/loader.py +59 -0
  606. contextsynapse/skills/models.py +139 -0
  607. contextsynapse/storage/__init__.py +7 -0
  608. contextsynapse/storage/cache.py +208 -0
  609. contextsynapse/storage/columnar_store_v2.py +178 -0
  610. contextsynapse/storage/csr_graph_storage.py +587 -0
  611. contextsynapse/storage/csr_store.py +388 -0
  612. contextsynapse/storage/document_store.py +491 -0
  613. contextsynapse/storage/hnsw_index.py +294 -0
  614. contextsynapse/storage/hybrid_store_v2.py +278 -0
  615. contextsynapse/storage/lmdb_graph_storage.py +366 -0
  616. contextsynapse/storage/migration.py +279 -0
  617. contextsynapse/storage/namespace_store.py +346 -0
  618. contextsynapse/storage/pure_graph_storage.py +185 -0
  619. contextsynapse/storage/redis_graph_adapter.py +186 -0
  620. contextsynapse/storage/redis_graph_storage.py +375 -0
  621. contextsynapse/storage/router/__init__.py +29 -0
  622. contextsynapse/storage/router/duckdb_store.py +398 -0
  623. contextsynapse/storage/router/factory.py +83 -0
  624. contextsynapse/storage/router/interface.py +125 -0
  625. contextsynapse/storage/router/postgres_store.py +339 -0
  626. contextsynapse/storage/router/resolver.py +192 -0
  627. contextsynapse/storage/router/router.py +300 -0
  628. contextsynapse/storage/single_file_storage.py +391 -0
  629. contextsynapse/storage/storage_manager.py +214 -0
  630. contextsynapse/storage/storage_query_optimizer.py +314 -0
  631. contextsynapse/storage/wal.py +359 -0
  632. contextsynapse/temporal/__init__.py +0 -0
  633. contextsynapse/temporal/storage.py +106 -0
  634. contextsynapse/tests/__init__.py +11 -0
  635. contextsynapse/tests/regression/__init__.py +1 -0
  636. contextsynapse/tests/regression/add_metadata.py +395 -0
  637. contextsynapse/tests/regression/add_skip_flags.py +85 -0
  638. contextsynapse/tests/regression/cases/test_basic_create_node.yaml +20 -0
  639. contextsynapse/tests/regression/cases/test_basic_select.yaml +21 -0
  640. contextsynapse/tests/regression/cases/test_blockchain_audit_trail.yaml +37 -0
  641. contextsynapse/tests/regression/cases/test_blockchain_audit_trail_filtered.yaml +39 -0
  642. contextsynapse/tests/regression/cases/test_blockchain_blocks_range.yaml +39 -0
  643. contextsynapse/tests/regression/cases/test_blockchain_get_block.yaml +35 -0
  644. contextsynapse/tests/regression/cases/test_blockchain_latest_block.yaml +35 -0
  645. contextsynapse/tests/regression/cases/test_blockchain_length.yaml +37 -0
  646. contextsynapse/tests/regression/cases/test_blockchain_merkle_root.yaml +37 -0
  647. contextsynapse/tests/regression/cases/test_blockchain_verify.yaml +35 -0
  648. contextsynapse/tests/regression/cases/test_blockchain_verify_block.yaml +35 -0
  649. contextsynapse/tests/regression/cases/test_create_edge.yaml +28 -0
  650. contextsynapse/tests/regression/cases/test_delete_edge_basic.yaml +29 -0
  651. contextsynapse/tests/regression/cases/test_delete_node_basic.yaml +29 -0
  652. contextsynapse/tests/regression/cases/test_evaluation_mrr.yaml +40 -0
  653. contextsynapse/tests/regression/cases/test_evaluation_ndcg.yaml +40 -0
  654. contextsynapse/tests/regression/cases/test_evaluation_precision.yaml +40 -0
  655. contextsynapse/tests/regression/cases/test_evaluation_recall.yaml +40 -0
  656. contextsynapse/tests/regression/cases/test_group_by_basic.yaml +56 -0
  657. contextsynapse/tests/regression/cases/test_match_node_basic.yaml +29 -0
  658. contextsynapse/tests/regression/cases/test_match_node_with_order_limit.yaml +31 -0
  659. contextsynapse/tests/regression/cases/test_namespace_switch.yaml +18 -0
  660. contextsynapse/tests/regression/cases/test_pipeline_cascaded.yaml +61 -0
  661. contextsynapse/tests/regression/cases/test_pipeline_fixed_size_chunking.yaml +48 -0
  662. contextsynapse/tests/regression/cases/test_pipeline_gpt4_chunking.yaml +54 -0
  663. contextsynapse/tests/regression/cases/test_pipeline_hybrid_indexing.yaml +57 -0
  664. contextsynapse/tests/regression/cases/test_pipeline_large_embedding.yaml +52 -0
  665. contextsynapse/tests/regression/cases/test_pipeline_paragraph_chunking.yaml +49 -0
  666. contextsynapse/tests/regression/cases/test_pipeline_recursive_chunking.yaml +47 -0
  667. contextsynapse/tests/regression/cases/test_pipeline_run_pipeline.yaml +56 -0
  668. contextsynapse/tests/regression/cases/test_pipeline_section_based_chunking.yaml +53 -0
  669. contextsynapse/tests/regression/cases/test_pipeline_semantic_chunking.yaml +51 -0
  670. contextsynapse/tests/regression/cases/test_pipeline_with_entity_extraction.yaml +57 -0
  671. contextsynapse/tests/regression/cases/test_pipeline_with_relationships.yaml +62 -0
  672. contextsynapse/tests/regression/cases/test_rag_evaluation.yaml +38 -0
  673. contextsynapse/tests/regression/cases/test_rag_graph_bfs_with_eval.yaml +48 -0
  674. contextsynapse/tests/regression/cases/test_rag_graph_centrality.yaml +40 -0
  675. contextsynapse/tests/regression/cases/test_rag_graph_centrality_eval.yaml +35 -0
  676. contextsynapse/tests/regression/cases/test_rag_graph_community.yaml +40 -0
  677. contextsynapse/tests/regression/cases/test_rag_graph_community_eval.yaml +35 -0
  678. contextsynapse/tests/regression/cases/test_rag_graph_dfs_with_eval.yaml +35 -0
  679. contextsynapse/tests/regression/cases/test_rag_graph_multi_hop_eval.yaml +35 -0
  680. contextsynapse/tests/regression/cases/test_rag_graph_path.yaml +40 -0
  681. contextsynapse/tests/regression/cases/test_rag_graph_search_basic.yaml +38 -0
  682. contextsynapse/tests/regression/cases/test_rag_graph_search_bfs.yaml +52 -0
  683. contextsynapse/tests/regression/cases/test_rag_graph_search_dfs.yaml +41 -0
  684. contextsynapse/tests/regression/cases/test_rag_graph_search_multi_hop.yaml +43 -0
  685. contextsynapse/tests/regression/cases/test_rag_graph_search_shortest_path.yaml +41 -0
  686. contextsynapse/tests/regression/cases/test_rag_graph_search_weighted.yaml +43 -0
  687. contextsynapse/tests/regression/cases/test_rag_graph_shortest_path_eval.yaml +35 -0
  688. contextsynapse/tests/regression/cases/test_rag_graph_traversal.yaml +30 -0
  689. contextsynapse/tests/regression/cases/test_rag_graph_weighted_eval.yaml +35 -0
  690. contextsynapse/tests/regression/cases/test_rag_hybrid_search.yaml +33 -0
  691. contextsynapse/tests/regression/cases/test_rag_hybrid_with_prompt_embedding.yaml +44 -0
  692. contextsynapse/tests/regression/cases/test_rag_keyword_search.yaml +32 -0
  693. contextsynapse/tests/regression/cases/test_rag_multi_hop_graph.yaml +32 -0
  694. contextsynapse/tests/regression/cases/test_rag_path_based.yaml +34 -0
  695. contextsynapse/tests/regression/cases/test_rag_profile_based.yaml +32 -0
  696. contextsynapse/tests/regression/cases/test_rag_vector_search.yaml +32 -0
  697. contextsynapse/tests/regression/cases/test_rag_weighted_graph.yaml +34 -0
  698. contextsynapse/tests/regression/cases/test_rag_weighted_hybrid.yaml +31 -0
  699. contextsynapse/tests/regression/cases/test_semantic_boundary_chunking.yaml +57 -0
  700. contextsynapse/tests/regression/cases/test_semantic_boundary_detection.yaml +33 -0
  701. contextsynapse/tests/regression/cases/test_semantic_hash_function.yaml +30 -0
  702. contextsynapse/tests/regression/cases/test_semantic_hash_with_model.yaml +31 -0
  703. contextsynapse/tests/regression/cases/test_tcs_ingestion_fixed_size.yaml +44 -0
  704. contextsynapse/tests/regression/cases/test_tcs_ingestion_recursive.yaml +46 -0
  705. contextsynapse/tests/regression/cases/test_tcs_ingestion_section.yaml +46 -0
  706. contextsynapse/tests/regression/cases/test_tcs_ingestion_semantic.yaml +44 -0
  707. contextsynapse/tests/regression/cases/test_time_travel_as_of.yaml +35 -0
  708. contextsynapse/tests/regression/cases/test_time_travel_at_commit.yaml +33 -0
  709. contextsynapse/tests/regression/cases/test_time_travel_at_timestamp.yaml +33 -0
  710. contextsynapse/tests/regression/cases/test_time_travel_for_system_time_all.yaml +37 -0
  711. contextsynapse/tests/regression/cases/test_time_travel_versions_between.yaml +39 -0
  712. contextsynapse/tests/regression/cases/test_traverse_basic.yaml +31 -0
  713. contextsynapse/tests/regression/cases/test_traverse_max_depth.yaml +34 -0
  714. contextsynapse/tests/regression/cases/test_update_edge_basic.yaml +29 -0
  715. contextsynapse/tests/regression/evaluation_metrics.py +227 -0
  716. contextsynapse/tests/regression/regression_runner.py +1081 -0
  717. contextsynapse/tests/regression/setup_regression_data.py +212 -0
  718. contextsynapse/tests/regression/test_basic_only.py +84 -0
  719. contextsynapse/tests/regression/test_namespace_creation.py +29 -0
  720. contextsynapse/tests/regression/test_single_fix.py +61 -0
  721. contextsynapse/tests/regression/test_single_query.py +20 -0
  722. contextsynapse/tests/regression/validate_test_syntax.py +179 -0
  723. contextsynapse/tests/test_advanced_features.py +347 -0
  724. contextsynapse/tests/test_aiql_summary.py +283 -0
  725. contextsynapse/tests/test_all_aiql_queries.py +948 -0
  726. contextsynapse/tests/test_all_create_queries.py +213 -0
  727. contextsynapse/tests/test_api_vs_native.py +280 -0
  728. contextsynapse/tests/test_chunking_dedup.py +199 -0
  729. contextsynapse/tests/test_connectors.py +171 -0
  730. contextsynapse/tests/test_edges_and_match.py +202 -0
  731. contextsynapse/tests/test_extraction_pipeline_integration.py +581 -0
  732. contextsynapse/tests/test_name_property.py +224 -0
  733. contextsynapse/tests/test_node_edge_metadata.py +250 -0
  734. contextsynapse/tests/test_playground_conn.py +114 -0
  735. contextsynapse/tests/test_query_cache.py +213 -0
  736. contextsynapse/tests/test_source_policy_auth.py +348 -0
  737. contextsynapse/tests/test_temporal_and_domain.py +224 -0
  738. contextsynapse/tests/test_time_travel_e2e.py +571 -0
  739. contextsynapse/tests/test_traversal_and_aggregation.py +275 -0
  740. contextsynapse/tools/__init__.py +36 -0
  741. contextsynapse/tools/a2a_tools.py +106 -0
  742. contextsynapse/tools/cognition_tools.py +118 -0
  743. contextsynapse/tools/context.py +905 -0
  744. contextsynapse/tools/formatting.py +92 -0
  745. contextsynapse/tools/gateway_tools.py +186 -0
  746. contextsynapse/tools/graph.py +1700 -0
  747. contextsynapse/tools/intelligence.py +235 -0
  748. contextsynapse/tools/memory.py +118 -0
  749. contextsynapse/tools/registry.py +373 -0
  750. contextsynapse/tools/shield_tools.py +159 -0
  751. contextsynapse/tools/tasks.py +341 -0
  752. contextsynapse/tools/workspace_tools.py +124 -0
  753. contextsynapse/utils/__init__.py +15 -0
  754. contextsynapse/utils/config_loader.py +198 -0
  755. contextsynapse/utils/env_loader.py +156 -0
  756. contextsynapse/utils/file_utils.py +288 -0
  757. contextsynapse/utils/logging_optimizer.py +119 -0
  758. contextsynapse/vector/__init__.py +30 -0
  759. contextsynapse/vector/chroma_vector_store.py +152 -0
  760. contextsynapse/vector/custom_vector_store.py +537 -0
  761. contextsynapse/vector/faiss_vector_store.py +296 -0
  762. contextsynapse/vector/qdrant_vector_store.py +163 -0
  763. contextsynapse/vector/vector_db.py +953 -0
  764. contextsynapse/vector/vector_db_manager.py +197 -0
  765. contextsynapse/workspace/__init__.py +27 -0
  766. contextsynapse/workspace/base.py +94 -0
  767. contextsynapse/workspace/git.py +228 -0
  768. contextsynapse/workspace/github.py +78 -0
  769. contextsynapse/workspace/local.py +73 -0
  770. contextsynapse/workspace/tools.py +222 -0
  771. contextsynapse-1.0.0.dist-info/METADATA +847 -0
  772. contextsynapse-1.0.0.dist-info/RECORD +776 -0
  773. contextsynapse-1.0.0.dist-info/WHEEL +5 -0
  774. contextsynapse-1.0.0.dist-info/entry_points.txt +4 -0
  775. contextsynapse-1.0.0.dist-info/licenses/LICENSE +200 -0
  776. contextsynapse-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,204 @@
1
+ """
2
+ Audit Log
3
+ =========
4
+ Immutable audit trail for admin/security actions.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import json
10
+ import logging
11
+ import time
12
+ import uuid
13
+ from dataclasses import dataclass, field
14
+ from pathlib import Path
15
+ from typing import Any, Dict, List, Optional
16
+
17
+ from contextsynapse.core.db import IS_POSTGRES, PH, connect, dict_cursor, run_ddl, row_to_dict
18
+
19
+ logger = logging.getLogger(__name__)
20
+
21
+
22
+ @dataclass
23
+ class AuditEntry:
24
+ entry_id: str
25
+ timestamp: float
26
+ user_id: str
27
+ action: str
28
+ resource_type: str
29
+ resource_id: str
30
+ details: Dict[str, Any] = field(default_factory=dict)
31
+ ip_address: str = ""
32
+
33
+ def to_dict(self) -> dict:
34
+ return {
35
+ "entry_id": self.entry_id,
36
+ "timestamp": self.timestamp,
37
+ "user_id": self.user_id,
38
+ "action": self.action,
39
+ "resource_type": self.resource_type,
40
+ "resource_id": self.resource_id,
41
+ "details": self.details,
42
+ "ip_address": self.ip_address,
43
+ }
44
+
45
+
46
+ _SCHEMA = """
47
+ CREATE TABLE IF NOT EXISTS audit_log (
48
+ entry_id TEXT PRIMARY KEY,
49
+ timestamp REAL NOT NULL,
50
+ user_id TEXT NOT NULL,
51
+ action TEXT NOT NULL,
52
+ resource_type TEXT NOT NULL DEFAULT '',
53
+ resource_id TEXT NOT NULL DEFAULT '',
54
+ details TEXT NOT NULL DEFAULT '{}',
55
+ ip_address TEXT NOT NULL DEFAULT ''
56
+ );
57
+ CREATE INDEX IF NOT EXISTS idx_audit_timestamp ON audit_log(timestamp);
58
+ CREATE INDEX IF NOT EXISTS idx_audit_action ON audit_log(action);
59
+ CREATE INDEX IF NOT EXISTS idx_audit_user ON audit_log(user_id);
60
+ """
61
+
62
+
63
+ class AuditLog:
64
+ """Append-only audit log backed by SQLite or PostgreSQL."""
65
+
66
+ def __init__(self, db_path: Optional[str] = None):
67
+ if db_path is None:
68
+ db_path = str(Path("contextcore_data") / "audit.db")
69
+ if not IS_POSTGRES:
70
+ Path(db_path).parent.mkdir(parents=True, exist_ok=True)
71
+ self._db_path = db_path
72
+ self._conn = connect(db_path)
73
+ run_ddl(self._conn, _SCHEMA)
74
+
75
+ def _exec(self, sql: str, params: tuple = ()):
76
+ cur = dict_cursor(self._conn)
77
+ cur.execute(sql, params)
78
+ return cur
79
+
80
+ def log(
81
+ self,
82
+ user_id: str,
83
+ action: str,
84
+ resource_type: str = "",
85
+ resource_id: str = "",
86
+ details: Optional[Dict[str, Any]] = None,
87
+ ip_address: str = "",
88
+ ) -> AuditEntry:
89
+ entry = AuditEntry(
90
+ entry_id=str(uuid.uuid4()),
91
+ timestamp=time.time(),
92
+ user_id=user_id,
93
+ action=action,
94
+ resource_type=resource_type,
95
+ resource_id=resource_id,
96
+ details=details or {},
97
+ ip_address=ip_address,
98
+ )
99
+ self._exec(
100
+ f"INSERT INTO audit_log "
101
+ f"(entry_id, timestamp, user_id, action, resource_type, resource_id, details, ip_address) "
102
+ f"VALUES ({PH}, {PH}, {PH}, {PH}, {PH}, {PH}, {PH}, {PH})",
103
+ (
104
+ entry.entry_id,
105
+ entry.timestamp,
106
+ entry.user_id,
107
+ entry.action,
108
+ entry.resource_type,
109
+ entry.resource_id,
110
+ json.dumps(entry.details),
111
+ entry.ip_address,
112
+ ),
113
+ )
114
+ self._conn.commit()
115
+ return entry
116
+
117
+ def query(
118
+ self,
119
+ action: Optional[str] = None,
120
+ user_id: Optional[str] = None,
121
+ resource_type: Optional[str] = None,
122
+ since: Optional[float] = None,
123
+ until: Optional[float] = None,
124
+ limit: int = 100,
125
+ offset: int = 0,
126
+ ) -> List[AuditEntry]:
127
+ clauses = []
128
+ params: list = []
129
+
130
+ if action:
131
+ clauses.append(f"action = {PH}")
132
+ params.append(action)
133
+ if user_id:
134
+ clauses.append(f"user_id = {PH}")
135
+ params.append(user_id)
136
+ if resource_type:
137
+ clauses.append(f"resource_type = {PH}")
138
+ params.append(resource_type)
139
+ if since:
140
+ clauses.append(f"timestamp >= {PH}")
141
+ params.append(since)
142
+ if until:
143
+ clauses.append(f"timestamp <= {PH}")
144
+ params.append(until)
145
+
146
+ where = f"WHERE {' AND '.join(clauses)}" if clauses else ""
147
+ sql = f"SELECT * FROM audit_log {where} ORDER BY timestamp DESC LIMIT {PH} OFFSET {PH}"
148
+ params.extend([limit, offset])
149
+
150
+ rows = self._exec(sql, tuple(params)).fetchall()
151
+
152
+ return [
153
+ AuditEntry(
154
+ entry_id=r["entry_id"],
155
+ timestamp=r["timestamp"],
156
+ user_id=r["user_id"],
157
+ action=r["action"],
158
+ resource_type=r["resource_type"],
159
+ resource_id=r["resource_id"],
160
+ details=json.loads(r["details"]) if r["details"] else {},
161
+ ip_address=r["ip_address"],
162
+ )
163
+ for r in [row_to_dict(r) for r in rows]
164
+ ]
165
+
166
+ def count(
167
+ self,
168
+ action: Optional[str] = None,
169
+ user_id: Optional[str] = None,
170
+ resource_type: Optional[str] = None,
171
+ ) -> int:
172
+ clauses = []
173
+ params: list = []
174
+ if action:
175
+ clauses.append(f"action = {PH}")
176
+ params.append(action)
177
+ if user_id:
178
+ clauses.append(f"user_id = {PH}")
179
+ params.append(user_id)
180
+ if resource_type:
181
+ clauses.append(f"resource_type = {PH}")
182
+ params.append(resource_type)
183
+
184
+ where = f"WHERE {' AND '.join(clauses)}" if clauses else ""
185
+ row = row_to_dict(self._exec(
186
+ f"SELECT COUNT(*) as cnt FROM audit_log {where}", tuple(params)
187
+ ).fetchone())
188
+ return row["cnt"] if row else 0
189
+
190
+ def export_csv(self, **filters) -> str:
191
+ """Export audit log as CSV string."""
192
+ entries = self.query(limit=10000, **filters)
193
+ lines = ["entry_id,timestamp,user_id,action,resource_type,resource_id,details,ip_address"]
194
+ for e in entries:
195
+ details_str = json.dumps(e.details).replace('"', '""')
196
+ lines.append(
197
+ f'{e.entry_id},{e.timestamp},{e.user_id},{e.action},'
198
+ f'{e.resource_type},{e.resource_id},"{details_str}",{e.ip_address}'
199
+ )
200
+ return "\n".join(lines)
201
+
202
+ def close(self):
203
+ if self._conn:
204
+ self._conn.close()
@@ -0,0 +1,441 @@
1
+ """
2
+ Authentication Middleware
3
+ =========================
4
+ Provides FastAPI dependencies for:
5
+
6
+ - ``UserAuth`` — validates ``Authorization: Bearer <jwt>`` with a user JWT.
7
+ Returns a ``UserIdentity``.
8
+ - ``TenantAuth`` — validates ``Authorization: Bearer <tenant_api_key>`` on
9
+ all data routes. Returns a ``TenantIdentity``.
10
+ - ``AgentAuth`` — validates ``Authorization: Bearer <agent_id>:<secret>`` on
11
+ ``/context/`` endpoints. Returns an ``AgentIdentity``.
12
+ - ``AdminAuth`` — validates ``X-Admin-Key`` header against the
13
+ ``AICONTEXTDB_ADMIN_KEY`` env var. Used on ``/admin/`` routes.
14
+ """
15
+
16
+ import hashlib
17
+ import hmac
18
+ import json
19
+ import logging
20
+ import os
21
+ import time
22
+ from typing import Any, Dict, Optional
23
+
24
+ from fastapi import Depends, HTTPException, Request
25
+ from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
26
+
27
+ logger = logging.getLogger(__name__)
28
+
29
+
30
+ def _get_jwt_secret() -> str:
31
+ """JWT signing secret. Falls back to AICONTEXTDB_ADMIN_KEY for compat.
32
+
33
+ Raises ``RuntimeError`` if neither env var is set, preventing the server
34
+ from starting with an insecure default.
35
+ """
36
+ secret = os.environ.get("CONTEXTSYNAPSE_JWT_SECRET") or os.environ.get("AICONTEXTDB_JWT_SECRET") or os.environ.get("CONTEXTSYNAPSE_ADMIN_KEY") or os.environ.get("AICONTEXTDB_ADMIN_KEY")
37
+ if not secret:
38
+ raise RuntimeError(
39
+ "AICONTEXTDB_JWT_SECRET (or AICONTEXTDB_ADMIN_KEY) must be set. "
40
+ "Generate one with: python -c \"import secrets; print(secrets.token_urlsafe(32))\""
41
+ )
42
+ return secret
43
+
44
+
45
+ # ======================================================================
46
+ # Lightweight JWT helpers (HMAC-SHA256, no external dependency)
47
+ # ======================================================================
48
+
49
+ def _b64url_encode(data: bytes) -> str:
50
+ import base64
51
+ return base64.urlsafe_b64encode(data).rstrip(b"=").decode()
52
+
53
+
54
+ def _b64url_decode(s: str) -> bytes:
55
+ import base64
56
+ s += "=" * (4 - len(s) % 4)
57
+ return base64.urlsafe_b64decode(s)
58
+
59
+
60
+ def create_jwt(payload: Dict[str, Any], secret: Optional[str] = None,
61
+ expires_in: int = 86400) -> str:
62
+ """Create a signed JWT with arbitrary payload."""
63
+ secret = secret or _get_jwt_secret()
64
+ payload = {**payload, "iat": int(time.time()), "exp": int(time.time()) + expires_in}
65
+ header = _b64url_encode(json.dumps({"alg": "HS256", "typ": "JWT"}).encode())
66
+ payload_b64 = _b64url_encode(json.dumps(payload).encode())
67
+ signing_input = f"{header}.{payload_b64}"
68
+ sig = hmac.new(secret.encode(), signing_input.encode(), hashlib.sha256).digest()
69
+ return f"{signing_input}.{_b64url_encode(sig)}"
70
+
71
+
72
+ def verify_jwt(token: str, secret: Optional[str] = None) -> Optional[Dict[str, Any]]:
73
+ """Verify a JWT and return the payload dict, or None if invalid/expired.
74
+
75
+ Tries JWT_SECRET first, then falls back to ADMIN_KEY if different.
76
+ """
77
+ secrets_to_try = []
78
+ if secret:
79
+ secrets_to_try.append(secret)
80
+ else:
81
+ jwt_secret = os.environ.get("CONTEXTSYNAPSE_JWT_SECRET") or os.environ.get("AICONTEXTDB_JWT_SECRET")
82
+ admin_key = os.environ.get("CONTEXTSYNAPSE_ADMIN_KEY") or os.environ.get("AICONTEXTDB_ADMIN_KEY")
83
+ if jwt_secret:
84
+ secrets_to_try.append(jwt_secret)
85
+ if admin_key and admin_key != jwt_secret:
86
+ secrets_to_try.append(admin_key)
87
+ if not secrets_to_try:
88
+ secrets_to_try.append(_get_jwt_secret())
89
+
90
+ for sec in secrets_to_try:
91
+ try:
92
+ parts = token.split(".")
93
+ if len(parts) != 3:
94
+ return None
95
+ signing_input = f"{parts[0]}.{parts[1]}"
96
+ expected_sig = hmac.new(sec.encode(), signing_input.encode(), hashlib.sha256).digest()
97
+ actual_sig = _b64url_decode(parts[2])
98
+ if hmac.compare_digest(expected_sig, actual_sig):
99
+ payload = json.loads(_b64url_decode(parts[1]))
100
+ if payload.get("exp", 0) < time.time():
101
+ return None
102
+ return payload
103
+ except Exception:
104
+ continue
105
+ return None
106
+
107
+
108
+ # Backward-compat wrappers
109
+ def create_admin_jwt(admin_key: str, expires_in: int = 86400) -> str:
110
+ """Create a signed JWT for admin dashboard sessions."""
111
+ return create_jwt({"role": "admin"}, secret=admin_key, expires_in=expires_in)
112
+
113
+
114
+ def verify_admin_jwt(token: str, admin_key: str) -> bool:
115
+ """Verify an admin JWT. Returns True if valid and not expired."""
116
+ payload = verify_jwt(token, secret=admin_key)
117
+ return payload is not None and payload.get("role") == "admin"
118
+
119
+ # Optional bearer token — allows endpoints to be called without auth header
120
+ # (registration, health) while still extracting credentials when present.
121
+ _bearer_scheme = HTTPBearer(auto_error=False)
122
+
123
+
124
+ # ======================================================================
125
+ # Tenant Auth (main API routes)
126
+ # ======================================================================
127
+
128
+ class TenantAuth:
129
+ """
130
+ FastAPI dependency that resolves a tenant from the Authorization header.
131
+
132
+ Usage::
133
+
134
+ tenant_auth = TenantAuth(tenant_registry)
135
+
136
+ @app.get("/graphs")
137
+ async def list_graphs(tenant: TenantIdentity = Depends(tenant_auth)):
138
+ ...
139
+ """
140
+
141
+ def __init__(self, tenant_registry):
142
+ self._registry = tenant_registry
143
+
144
+ async def __call__(
145
+ self,
146
+ request: Request,
147
+ credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer_scheme),
148
+ ):
149
+ if credentials is None:
150
+ raise HTTPException(
151
+ status_code=401,
152
+ detail="Authentication required. Please provide a valid API key.",
153
+ headers={"WWW-Authenticate": "Bearer realm=\"AIContextDB\""},
154
+ )
155
+
156
+ tenant = self._registry.authenticate(credentials.credentials)
157
+ if tenant is None:
158
+ raise HTTPException(status_code=403, detail="Invalid or expired API key.")
159
+
160
+ if tenant.status != "active":
161
+ raise HTTPException(status_code=403, detail="This account is currently inactive.")
162
+
163
+ # Stash on request.state so downstream middleware/routes can access it
164
+ request.state.tenant = tenant
165
+ return tenant
166
+
167
+
168
+ # ======================================================================
169
+ # Admin Auth (admin routes — uses env var AICONTEXTDB_ADMIN_KEY)
170
+ # ======================================================================
171
+
172
+ class AdminAuth:
173
+ """
174
+ FastAPI dependency that validates admin credentials via either:
175
+
176
+ 1. ``X-Admin-Key`` header (direct key match), or
177
+ 2. ``Authorization: Bearer <jwt>`` (JWT signed with admin key).
178
+
179
+ The ``AICONTEXTDB_ADMIN_KEY`` env var is the shared secret for both.
180
+ """
181
+
182
+ async def __call__(
183
+ self,
184
+ request: Request,
185
+ credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer_scheme),
186
+ ):
187
+ admin_key = os.environ.get("CONTEXTSYNAPSE_ADMIN_KEY") or os.environ.get("AICONTEXTDB_ADMIN_KEY")
188
+ if not admin_key:
189
+ raise HTTPException(
190
+ status_code=503,
191
+ detail="Admin API is not configured. Contact your administrator.",
192
+ )
193
+
194
+ # Method 1: X-Admin-Key header (CLI / scripts)
195
+ provided = request.headers.get("X-Admin-Key")
196
+ if provided and hmac.compare_digest(provided, admin_key):
197
+ return True
198
+
199
+ # Method 2: Bearer JWT (admin dashboard)
200
+ if credentials and verify_admin_jwt(credentials.credentials, admin_key):
201
+ return True
202
+
203
+ raise HTTPException(status_code=403, detail="Insufficient permissions. Admin access required.")
204
+
205
+
206
+ # ======================================================================
207
+ # Agent Auth (context routes)
208
+ # ======================================================================
209
+
210
+
211
+ class AgentAuth:
212
+ """
213
+ Dependency that resolves the current agent from the Authorization header.
214
+
215
+ Inject into router endpoints via ``Depends(agent_auth)``.
216
+ """
217
+
218
+ def __init__(self, agent_registry):
219
+ self._registry = agent_registry
220
+
221
+ async def __call__(
222
+ self,
223
+ credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer_scheme),
224
+ ):
225
+ """
226
+ Extract agent_id + api_key from the ``Authorization: Bearer <key>`` header,
227
+ validate against the AgentRegistry, and return the AgentIdentity.
228
+ """
229
+ if credentials is None:
230
+ raise HTTPException(
231
+ status_code=401,
232
+ detail="Authentication required. Please provide a valid agent API key.",
233
+ headers={"WWW-Authenticate": "Bearer realm=\"AIContextDB\""},
234
+ )
235
+
236
+ api_key = credentials.credentials
237
+
238
+ # api_key format: "<agent_id>:<secret>"
239
+ if ":" not in api_key:
240
+ raise HTTPException(
241
+ status_code=401,
242
+ detail="Invalid API key format.",
243
+ headers={"WWW-Authenticate": "Bearer realm=\"AIContextDB\""},
244
+ )
245
+
246
+ agent_id, secret = api_key.split(":", 1)
247
+
248
+ if not self._registry.authenticate(agent_id, secret):
249
+ raise HTTPException(
250
+ status_code=403,
251
+ detail="Invalid or expired API key.",
252
+ )
253
+
254
+ agent = self._registry.get(agent_id)
255
+ if agent is None:
256
+ raise HTTPException(status_code=403, detail="Agent not found.")
257
+
258
+ # Update last_seen timestamp
259
+ try:
260
+ self._registry.touch(agent_id)
261
+ except Exception:
262
+ pass # non-critical — don't fail auth over a timestamp
263
+
264
+ return agent
265
+
266
+
267
+ # ======================================================================
268
+ # User Auth (SaaS dashboard routes)
269
+ # ======================================================================
270
+
271
+ class UserAuth:
272
+ """
273
+ FastAPI dependency that validates a user JWT from the Authorization header.
274
+
275
+ Usage::
276
+
277
+ user_auth = UserAuth(user_registry)
278
+
279
+ @app.get("/dashboard/overview")
280
+ async def overview(user: UserIdentity = Depends(user_auth)):
281
+ ...
282
+ """
283
+
284
+ def __init__(self, user_registry):
285
+ self._registry = user_registry
286
+
287
+ async def __call__(
288
+ self,
289
+ request: Request,
290
+ credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer_scheme),
291
+ ):
292
+ # Accept X-Admin-Key for admin access (same as dashboard routes)
293
+ admin_key = os.environ.get("CONTEXTSYNAPSE_ADMIN_KEY") or os.environ.get("AICONTEXTDB_ADMIN_KEY")
294
+ provided = request.headers.get("X-Admin-Key")
295
+ if admin_key and provided and hmac.compare_digest(provided, admin_key):
296
+ from dataclasses import dataclass, field as _field
297
+
298
+ @dataclass
299
+ class _AdminUser:
300
+ user_id: str = "admin"
301
+ email: str = "admin@local"
302
+ display_name: str = "Admin"
303
+ status: str = "active"
304
+ role: str = "owner"
305
+ is_super_admin: bool = True
306
+ metadata: dict = _field(default_factory=dict)
307
+
308
+ request.state.user = _AdminUser()
309
+ return _AdminUser()
310
+
311
+ if credentials is None:
312
+ raise HTTPException(
313
+ status_code=401,
314
+ detail="Authentication required. Please sign in to continue.",
315
+ headers={"WWW-Authenticate": "Bearer realm=\"AIContextDB\""},
316
+ )
317
+
318
+ payload = verify_jwt(credentials.credentials)
319
+ if payload is None:
320
+ raise HTTPException(status_code=401, detail="Your session has expired. Please sign in again.")
321
+
322
+ if payload.get("type") != "user":
323
+ raise HTTPException(status_code=401, detail="Invalid authentication credentials.")
324
+
325
+ user = self._registry.get(payload.get("sub"))
326
+ if user is None:
327
+ raise HTTPException(status_code=401, detail="Account not found. Please sign up or contact support.")
328
+
329
+ if user.status != "active":
330
+ raise HTTPException(status_code=403, detail="Your account is currently inactive. Contact support for assistance.")
331
+
332
+ request.state.user = user
333
+ return user
334
+
335
+
336
+ class AdminAwareAuth(UserAuth):
337
+ """UserAuth that also accepts admin JWT and X-Admin-Key header.
338
+
339
+ Use this for endpoints that both admin and regular users need to access.
340
+ """
341
+
342
+ async def __call__(
343
+ self,
344
+ request: Request,
345
+ credentials: Optional[HTTPAuthorizationCredentials] = Depends(_bearer_scheme),
346
+ ):
347
+ import hmac as _hmac
348
+ from dataclasses import dataclass, field as _f
349
+
350
+ @dataclass
351
+ class _AdminUser:
352
+ user_id: str = "admin"
353
+ email: str = "admin@local"
354
+ display_name: str = "Admin"
355
+ status: str = "active"
356
+ role: str = "owner"
357
+ is_super_admin: bool = True
358
+ metadata: dict = _f(default_factory=dict)
359
+
360
+ admin_key = os.environ.get("CONTEXTSYNAPSE_ADMIN_KEY") or os.environ.get("AICONTEXTDB_ADMIN_KEY")
361
+
362
+ # Path 1: X-Admin-Key header
363
+ provided = request.headers.get("X-Admin-Key")
364
+ if admin_key and provided and _hmac.compare_digest(provided, admin_key):
365
+ return _AdminUser()
366
+
367
+ # Path 2: Admin JWT (from /admin/login)
368
+ if credentials and admin_key:
369
+ payload = verify_jwt(credentials.credentials, secret=admin_key)
370
+ if payload and payload.get("role") == "admin":
371
+ return _AdminUser()
372
+
373
+ # Path 3: Normal user JWT
374
+ return await super().__call__(request, credentials)
375
+
376
+
377
+ # ======================================================================
378
+ # RBAC: Role-based dependency factories
379
+ # ======================================================================
380
+
381
+ _ROLE_HIERARCHY = {
382
+ "reader": 0,
383
+ "contributor": 1,
384
+ "admin": 2,
385
+ "owner": 3,
386
+ # Legacy aliases — kept so old tokens/rows still resolve
387
+ "viewer": 0,
388
+ "member": 1,
389
+ }
390
+
391
+
392
+ def require_user_role(user_auth, user_registry, min_role: str):
393
+ """Return a FastAPI dependency that enforces a minimum tenant role.
394
+
395
+ Hierarchy: reader < contributor < admin < owner.
396
+ Super admins bypass all role checks.
397
+ """
398
+ min_level = _ROLE_HIERARCHY.get(min_role, 99)
399
+
400
+ async def _check(request: Request, user=Depends(user_auth)):
401
+ # Super admins bypass tenant role checks
402
+ if getattr(user, "is_super_admin", False):
403
+ return user
404
+ tenant_id = user_registry.get_primary_tenant_id(user.user_id)
405
+ if not tenant_id:
406
+ raise HTTPException(403, "No workspace access")
407
+ memberships = user_registry.get_user_tenants(user.user_id)
408
+ user_role = next(
409
+ (m.role for m in memberships if m.tenant_id == tenant_id), None
410
+ )
411
+ if user_role is None or _ROLE_HIERARCHY.get(user_role, -1) < min_level:
412
+ raise HTTPException(
413
+ 403,
414
+ f"Requires {min_role} role or higher (you have: {user_role or 'none'})",
415
+ )
416
+ return user
417
+
418
+ return _check
419
+
420
+
421
+ def require_agent_capability(agent_auth, *required_caps: str):
422
+ """Return a FastAPI dependency that enforces agent capabilities.
423
+
424
+ Example::
425
+
426
+ require_write = require_agent_capability(agent_auth, "read", "write")
427
+
428
+ @router.post("/data")
429
+ async def write_data(agent=Depends(require_write)):
430
+ ...
431
+ """
432
+ async def _check(agent=Depends(agent_auth)):
433
+ missing = [c for c in required_caps if c not in agent.capabilities]
434
+ if missing:
435
+ raise HTTPException(
436
+ 403,
437
+ f"Agent lacks required capabilities: {', '.join(missing)}",
438
+ )
439
+ return agent
440
+
441
+ return _check