arbora 0.1.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 (653) hide show
  1. arbora/__init__.py +29 -0
  2. arbora/_version.py +6 -0
  3. arbora/a2a/__init__.py +74 -0
  4. arbora/a2a/admission.py +67 -0
  5. arbora/a2a/application.py +498 -0
  6. arbora/a2a/approval.py +152 -0
  7. arbora/a2a/authority.py +613 -0
  8. arbora/a2a/composition.py +41 -0
  9. arbora/a2a/mcp.py +118 -0
  10. arbora/a2a/models.py +249 -0
  11. arbora/a2a/routing.py +70 -0
  12. arbora/a2a/sdk_app.py +124 -0
  13. arbora/a2a/service.py +95 -0
  14. arbora/a2a/terminal_event.py +140 -0
  15. arbora/a2a/tool_task.py +318 -0
  16. arbora/a2a/work_items.py +98 -0
  17. arbora/access/__init__.py +1 -0
  18. arbora/access/action_policy.py +1265 -0
  19. arbora/access/approval.py +53 -0
  20. arbora/access/assurance.py +247 -0
  21. arbora/access/external_policy_sync.py +754 -0
  22. arbora/access/priority.py +88 -0
  23. arbora/access/service.py +176 -0
  24. arbora/access/task_guard.py +21 -0
  25. arbora/acp/__init__.py +31 -0
  26. arbora/acp/coding_session.py +123 -0
  27. arbora/acp/session_policy.py +139 -0
  28. arbora/agent_host/__init__.py +336 -0
  29. arbora/agent_host/log_access.py +297 -0
  30. arbora/agent_host/log_replay.py +174 -0
  31. arbora/agent_host/log_routes.py +118 -0
  32. arbora/agent_host/log_runtime.py +82 -0
  33. arbora/agent_host/log_sink.py +284 -0
  34. arbora/agent_host/start_admission.py +226 -0
  35. arbora/agent_host/start_configuration.py +84 -0
  36. arbora/agent_runs.py +168 -0
  37. arbora/api/__init__.py +19 -0
  38. arbora/api/contracts/__init__.py +133 -0
  39. arbora/api/contracts/agent_control_contracts.py +294 -0
  40. arbora/api/contracts/agent_control_plane.py +505 -0
  41. arbora/api/contracts/catalog.py +388 -0
  42. arbora/api/contracts/messaging.py +42 -0
  43. arbora/api/contracts/provisioning.py +250 -0
  44. arbora/api/contracts/session.py +569 -0
  45. arbora/api/errors.py +414 -0
  46. arbora/api/evidence/__init__.py +5 -0
  47. arbora/api/evidence/bundle.py +1077 -0
  48. arbora/api/evidence/contradiction.py +353 -0
  49. arbora/api/generated/__init__.py +5 -0
  50. arbora/api/generated/descriptors.json +5946 -0
  51. arbora/api/generated/engine_errors.py +279 -0
  52. arbora/api/generated/registry.json +24709 -0
  53. arbora/api/generated/schemas/method.request.json +1 -0
  54. arbora/api/generated/schemas/result.cluster.json +1 -0
  55. arbora/api/generated/schemas/result.compute.json +1 -0
  56. arbora/api/generated/schemas/result.coordination.json +1 -0
  57. arbora/api/generated/schemas/result.graph.json +1 -0
  58. arbora/api/generated/schemas/result.ingestion.json +1 -0
  59. arbora/api/generated/schemas/result.messaging.json +1 -0
  60. arbora/api/generated/schemas/result.query.json +1 -0
  61. arbora/api/generated/schemas/result.reasoning.json +1 -0
  62. arbora/api/generated/schemas/result.security.json +1 -0
  63. arbora/api/generated/schemas/result.storage.json +1 -0
  64. arbora/api/generated/schemas/result.transactions.json +1 -0
  65. arbora/api/http/__init__.py +6 -0
  66. arbora/api/http/app.py +197 -0
  67. arbora/api/http/auth.py +230 -0
  68. arbora/api/http/openapi.py +57 -0
  69. arbora/api/http/protocol_routes.py +34 -0
  70. arbora/api/http/routes.py +139 -0
  71. arbora/api/invoke/__init__.py +13 -0
  72. arbora/api/invoke/audit.py +67 -0
  73. arbora/api/invoke/bootstrap.py +285 -0
  74. arbora/api/invoke/eg_audit.py +199 -0
  75. arbora/api/invoke/executor.py +292 -0
  76. arbora/api/invoke/pipeline.py +873 -0
  77. arbora/api/invoke/plan.py +232 -0
  78. arbora/api/invoke/steps.py +221 -0
  79. arbora/api/mcp/__init__.py +5 -0
  80. arbora/api/mcp/caller.py +125 -0
  81. arbora/api/mcp/discovery.py +166 -0
  82. arbora/api/mcp/registration.py +250 -0
  83. arbora/api/mcp/resolve.py +336 -0
  84. arbora/api/mcp/resources.py +58 -0
  85. arbora/api/mcp/serving.py +75 -0
  86. arbora/api/mcp/verbs.py +417 -0
  87. arbora/api/ops/__init__.py +8 -0
  88. arbora/api/ops/_common.py +147 -0
  89. arbora/api/ops/access.py +232 -0
  90. arbora/api/ops/agents.py +172 -0
  91. arbora/api/ops/browser.py +76 -0
  92. arbora/api/ops/capacity.py +147 -0
  93. arbora/api/ops/decide.py +82 -0
  94. arbora/api/ops/fleet.py +230 -0
  95. arbora/api/ops/fleet_deploy_watch.py +94 -0
  96. arbora/api/ops/ingest.py +177 -0
  97. arbora/api/ops/ops.py +273 -0
  98. arbora/api/ops/policy.py +71 -0
  99. arbora/api/ops/query.py +43 -0
  100. arbora/api/ops/registry_factory.py +82 -0
  101. arbora/api/ops/retrieval.py +151 -0
  102. arbora/api/ops/runs.py +163 -0
  103. arbora/api/ops/security.py +71 -0
  104. arbora/api/ops/swarm.py +70 -0
  105. arbora/api/ops/telemetry.py +70 -0
  106. arbora/api/ops/usage.py +70 -0
  107. arbora/api/ops/work.py +128 -0
  108. arbora/api/ops/write_back.py +79 -0
  109. arbora/api/ops/write_back_models.py +118 -0
  110. arbora/api/policy/__init__.py +17 -0
  111. arbora/api/policy/cache.py +46 -0
  112. arbora/api/policy/defaults.py +25 -0
  113. arbora/api/policy/domain_scopes.py +84 -0
  114. arbora/api/policy/eunomia.py +333 -0
  115. arbora/api/policy/pdp_remote.py +266 -0
  116. arbora/api/registry/__init__.py +73 -0
  117. arbora/api/registry/contract_admission.py +167 -0
  118. arbora/api/registry/digest.py +106 -0
  119. arbora/api/registry/eg_binding.py +403 -0
  120. arbora/api/registry/registry.py +110 -0
  121. arbora/api/registry/scopes.py +48 -0
  122. arbora/api/registry/spec.py +197 -0
  123. arbora/api/registry/surface_gate.py +145 -0
  124. arbora/architecture/__init__.py +1 -0
  125. arbora/architecture/boundary_census.py +153 -0
  126. arbora/architecture/capability_layers.py +88 -0
  127. arbora/browser_control/__init__.py +5 -0
  128. arbora/browser_control/browser_control_api.py +239 -0
  129. arbora/browser_control/browser_control_attendance.py +114 -0
  130. arbora/browser_control/browser_control_attendance_api.py +112 -0
  131. arbora/browser_control/browser_control_attended.py +212 -0
  132. arbora/browser_control/browser_control_binding.py +144 -0
  133. arbora/browser_control/browser_control_cancellation.py +166 -0
  134. arbora/browser_control/browser_control_channel.py +307 -0
  135. arbora/browser_control/browser_control_client.py +97 -0
  136. arbora/browser_control/browser_control_common.py +210 -0
  137. arbora/browser_control/browser_control_descriptor.py +81 -0
  138. arbora/browser_control/browser_control_dispatch.py +255 -0
  139. arbora/browser_control/browser_control_durability.py +336 -0
  140. arbora/browser_control/browser_control_lease.py +245 -0
  141. arbora/browser_control/browser_control_outcome.py +302 -0
  142. arbora/browser_control/browser_control_policy.py +159 -0
  143. arbora/browser_control/browser_control_port.py +21 -0
  144. arbora/browser_control/browser_control_provenance.py +266 -0
  145. arbora/browser_control/browser_control_registration.py +324 -0
  146. arbora/browser_control/browser_control_runtime.py +127 -0
  147. arbora/browser_control/browser_control_server.py +80 -0
  148. arbora/browser_control/browser_control_service.py +156 -0
  149. arbora/browser_control/browser_control_state.py +191 -0
  150. arbora/browser_control/browser_control_validation.py +148 -0
  151. arbora/browser_control/mcp.py +42 -0
  152. arbora/browser_control/trace_bundle.py +268 -0
  153. arbora/client/__init__.py +1 -0
  154. arbora/client/_generated_models.py +532 -0
  155. arbora/client/_schema.py +74 -0
  156. arbora/client/invoke.py +26 -0
  157. arbora/connector_runner.py +166 -0
  158. arbora/content.py +22 -0
  159. arbora/control_plane/__init__.py +7 -0
  160. arbora/control_plane/_model.py +11 -0
  161. arbora/control_plane/admission/__init__.py +6 -0
  162. arbora/control_plane/admission/models.py +57 -0
  163. arbora/control_plane/admission/service.py +69 -0
  164. arbora/control_plane/agents/__init__.py +93 -0
  165. arbora/control_plane/agents/models.py +804 -0
  166. arbora/control_plane/agents/repository.py +94 -0
  167. arbora/control_plane/agents/service.py +547 -0
  168. arbora/control_plane/connectors/__init__.py +103 -0
  169. arbora/control_plane/connectors/models.py +665 -0
  170. arbora/control_plane/connectors/repository.py +115 -0
  171. arbora/control_plane/connectors/service.py +477 -0
  172. arbora/control_plane/economics/__init__.py +104 -0
  173. arbora/control_plane/economics/models.py +1149 -0
  174. arbora/control_plane/economics/repository.py +341 -0
  175. arbora/control_plane/economics/service.py +518 -0
  176. arbora/control_plane/fleet_watch/__init__.py +26 -0
  177. arbora/control_plane/fleet_watch/service.py +86 -0
  178. arbora/control_plane/foundation/__init__.py +121 -0
  179. arbora/control_plane/foundation/models.py +829 -0
  180. arbora/control_plane/foundation/repository.py +161 -0
  181. arbora/control_plane/foundation/service.py +916 -0
  182. arbora/control_plane/migrations/__init__.py +89 -0
  183. arbora/control_plane/migrations/authority.py +918 -0
  184. arbora/control_plane/migrations/errors.py +53 -0
  185. arbora/control_plane/migrations/models.py +656 -0
  186. arbora/control_plane/policy/__init__.py +63 -0
  187. arbora/control_plane/policy/models.py +376 -0
  188. arbora/control_plane/policy/repository.py +445 -0
  189. arbora/control_plane/projection/__init__.py +95 -0
  190. arbora/control_plane/projection/authority.py +28 -0
  191. arbora/control_plane/projection/models.py +870 -0
  192. arbora/control_plane/projection/observability.py +15 -0
  193. arbora/control_plane/projection/projector.py +751 -0
  194. arbora/control_plane/projection/protocols.py +86 -0
  195. arbora/control_plane/projection/repository.py +164 -0
  196. arbora/control_plane/retrieval/__init__.py +85 -0
  197. arbora/control_plane/retrieval/errors.py +45 -0
  198. arbora/control_plane/retrieval/models.py +682 -0
  199. arbora/control_plane/retrieval/protocols.py +97 -0
  200. arbora/control_plane/retrieval/repository.py +176 -0
  201. arbora/control_plane/retrieval/service.py +321 -0
  202. arbora/control_plane/runs/__init__.py +71 -0
  203. arbora/control_plane/runs/admission.py +232 -0
  204. arbora/control_plane/runs/audit.py +134 -0
  205. arbora/control_plane/runs/capacity.py +129 -0
  206. arbora/control_plane/runs/models.py +381 -0
  207. arbora/control_plane/runs/observations.py +88 -0
  208. arbora/control_plane/sources/__init__.py +84 -0
  209. arbora/control_plane/sources/models.py +871 -0
  210. arbora/control_plane/sources/repository.py +84 -0
  211. arbora/control_plane/sources/service.py +502 -0
  212. arbora/control_plane/webui/__init__.py +102 -0
  213. arbora/control_plane/webui/errors.py +60 -0
  214. arbora/control_plane/webui/models.py +517 -0
  215. arbora/control_plane/webui/protocols.py +60 -0
  216. arbora/control_plane/webui/repository.py +559 -0
  217. arbora/control_plane/webui/service.py +442 -0
  218. arbora/control_plane/workflows/__init__.py +83 -0
  219. arbora/control_plane/workflows/domain.py +528 -0
  220. arbora/control_plane/workflows/repository.py +363 -0
  221. arbora/core/__init__.py +9 -0
  222. arbora/core/agent_config_admin.py +556 -0
  223. arbora/core/capability_contract.py +158 -0
  224. arbora/core/config_admin.py +97 -0
  225. arbora/core/event_loop.py +164 -0
  226. arbora/core/provider_materialization.py +711 -0
  227. arbora/core/providers.py +720 -0
  228. arbora/core/settings.py +1079 -0
  229. arbora/core/transport.py +224 -0
  230. arbora/deployment/__init__.py +151 -0
  231. arbora/deployment/certification_assets.py +394 -0
  232. arbora/deployment/cli.py +239 -0
  233. arbora/deployment/codex_registration.py +157 -0
  234. arbora/deployment/config_generator.py +1242 -0
  235. arbora/deployment/doctor.py +2433 -0
  236. arbora/deployment/doctor_certification.py +413 -0
  237. arbora/deployment/doctor_coverage.py +226 -0
  238. arbora/deployment/doctor_graph.py +305 -0
  239. arbora/deployment/doctor_lakehouse.py +660 -0
  240. arbora/deployment/doctor_observability.py +570 -0
  241. arbora/deployment/doctor_support.py +47 -0
  242. arbora/deployment/engine_lock.py +155 -0
  243. arbora/deployment/exit_criteria.py +69 -0
  244. arbora/deployment/file_lock.py +266 -0
  245. arbora/deployment/genesis_environments.py +1150 -0
  246. arbora/deployment/host_config.py +76 -0
  247. arbora/deployment/host_lock.py +250 -0
  248. arbora/deployment/kubernetes_first_boot.py +827 -0
  249. arbora/deployment/live_mount_guard.py +296 -0
  250. arbora/deployment/local_gates.py +83 -0
  251. arbora/deployment/preflight.py +462 -0
  252. arbora/deployment/production_ops.py +517 -0
  253. arbora/deployment/profile_guard.py +589 -0
  254. arbora/deployment/public_ingress_identity.py +208 -0
  255. arbora/deployment/release_canary.py +125 -0
  256. arbora/deployment/release_candidate.py +332 -0
  257. arbora/deployment/repo_templates.py +570 -0
  258. arbora/deployment/self_deploy.py +130 -0
  259. arbora/deployment/semantic_provisioning.py +533 -0
  260. arbora/deployment/venv_autosync.py +973 -0
  261. arbora/deployment/venv_sync.py +2918 -0
  262. arbora/deployment/venv_sync_types.py +257 -0
  263. arbora/deployment/webui_reference_model.py +101 -0
  264. arbora/ecosystem/__init__.py +12 -0
  265. arbora/ecosystem/agent_manager_dashboard.py +350 -0
  266. arbora/ecosystem/ard_federation.py +191 -0
  267. arbora/ecosystem/ard_registry.py +331 -0
  268. arbora/ecosystem/ard_signing.py +157 -0
  269. arbora/ecosystem/hook_installer.py +368 -0
  270. arbora/epistemic.py +447 -0
  271. arbora/evolution/__init__.py +5 -0
  272. arbora/evolution/wiring_sweep.py +918 -0
  273. arbora/finance/__init__.py +70 -0
  274. arbora/finance/alerts.py +79 -0
  275. arbora/finance/dca.py +104 -0
  276. arbora/finance/markets.py +116 -0
  277. arbora/finance/schedule.py +84 -0
  278. arbora/fleet/__init__.py +90 -0
  279. arbora/fleet/access_contracts.py +164 -0
  280. arbora/fleet/catalog_composition.py +86 -0
  281. arbora/fleet/catalog_items.py +316 -0
  282. arbora/fleet/catalog_reader.py +624 -0
  283. arbora/fleet/catalog_sources.py +212 -0
  284. arbora/fleet/child_resilience.py +1373 -0
  285. arbora/fleet/client_toolsets.py +175 -0
  286. arbora/fleet/connector_count_pins.py +121 -0
  287. arbora/fleet/discovery_authority.py +78 -0
  288. arbora/fleet/epistemic_adapter.py +243 -0
  289. arbora/fleet/error_budget.py +232 -0
  290. arbora/fleet/feeds.py +98 -0
  291. arbora/fleet/gateway_ops.py +511 -0
  292. arbora/fleet/health.py +548 -0
  293. arbora/fleet/local_skill_catalog.py +207 -0
  294. arbora/fleet/mcp_resource_reconciliation.py +147 -0
  295. arbora/fleet/multiplexer.py +7408 -0
  296. arbora/fleet/multiplexer_ops.py +388 -0
  297. arbora/fleet/onboarding.py +521 -0
  298. arbora/fleet/protocol_compat.py +487 -0
  299. arbora/fleet/scaling/__init__.py +26 -0
  300. arbora/fleet/scaling/_model.py +11 -0
  301. arbora/fleet/scaling/development_lane.py +200 -0
  302. arbora/fleet/scaling/resource_pool_authority.py +1149 -0
  303. arbora/fleet/scaling/resource_reservation.py +151 -0
  304. arbora/fleet/scaling/scaling_authority.py +1086 -0
  305. arbora/fleet/scaling/scaling_intent_reconciler.py +1501 -0
  306. arbora/fleet/scaling/scaling_signal_authority.py +1018 -0
  307. arbora/fleet/scaling/service_scale_units.py +1850 -0
  308. arbora/fleet/service_child.py +352 -0
  309. arbora/fleet/session_loads.py +278 -0
  310. arbora/fleet/session_notifications.py +37 -0
  311. arbora/fleet/shared_multiplexer.py +160 -0
  312. arbora/fleet/throttle_service.py +84 -0
  313. arbora/fleet_tool_call.py +100 -0
  314. arbora/gateway/__init__.py +45 -0
  315. arbora/gateway/aggregator.py +241 -0
  316. arbora/gateway/config.py +595 -0
  317. arbora/gateway/daemon.py +344 -0
  318. arbora/gateway/dashboard_api.py +407 -0
  319. arbora/gateway/enhanced_catalog_api.py +320 -0
  320. arbora/gateway/fleet.py +567 -0
  321. arbora/gateway/fleet_events.py +500 -0
  322. arbora/gateway/graph_api.py +325 -0
  323. arbora/gateway/models.py +232 -0
  324. arbora/gateway/ontology_api.py +495 -0
  325. arbora/gateway/ports.py +61 -0
  326. arbora/gateway/rate_limit.py +169 -0
  327. arbora/gateway/registry.py +206 -0
  328. arbora/gateway/registry_api.py +1682 -0
  329. arbora/gateway/remote_oauth_api.py +435 -0
  330. arbora/gateway/schema_context_api.py +81 -0
  331. arbora/gateway/schema_context_service.py +53 -0
  332. arbora/gateway/schemas/__init__.py +7 -0
  333. arbora/gateway/schemas/connector.py +67 -0
  334. arbora/gateway/schemas/graph_core.py +790 -0
  335. arbora/gateway/schemas/schema_context.py +121 -0
  336. arbora/gateway/widgets/__init__.py +5 -0
  337. arbora/gateway/widgets/ansible_tower.py +59 -0
  338. arbora/gateway/widgets/archivebox.py +46 -0
  339. arbora/gateway/widgets/aris.py +47 -0
  340. arbora/gateway/widgets/arr.py +40 -0
  341. arbora/gateway/widgets/atlassian.py +44 -0
  342. arbora/gateway/widgets/audio_transcriber.py +35 -0
  343. arbora/gateway/widgets/audiobookshelf.py +47 -0
  344. arbora/gateway/widgets/base.py +374 -0
  345. arbora/gateway/widgets/caddy.py +96 -0
  346. arbora/gateway/widgets/camunda.py +58 -0
  347. arbora/gateway/widgets/ciso_assistant.py +62 -0
  348. arbora/gateway/widgets/clarity.py +45 -0
  349. arbora/gateway/widgets/container_manager.py +52 -0
  350. arbora/gateway/widgets/data_science.py +33 -0
  351. arbora/gateway/widgets/dockerhub.py +50 -0
  352. arbora/gateway/widgets/documentdb.py +48 -0
  353. arbora/gateway/widgets/ear.py +57 -0
  354. arbora/gateway/widgets/egeria.py +54 -0
  355. arbora/gateway/widgets/emerald_exchange.py +32 -0
  356. arbora/gateway/widgets/erpnext.py +52 -0
  357. arbora/gateway/widgets/fan_manager.py +59 -0
  358. arbora/gateway/widgets/firefly_iii.py +47 -0
  359. arbora/gateway/widgets/fleet_client.py +260 -0
  360. arbora/gateway/widgets/freshrss.py +69 -0
  361. arbora/gateway/widgets/github.py +45 -0
  362. arbora/gateway/widgets/gitlab.py +74 -0
  363. arbora/gateway/widgets/google_workspace.py +29 -0
  364. arbora/gateway/widgets/gramps.py +54 -0
  365. arbora/gateway/widgets/hdhomerun.py +46 -0
  366. arbora/gateway/widgets/home_assistant.py +61 -0
  367. arbora/gateway/widgets/jellyfin.py +63 -0
  368. arbora/gateway/widgets/jena.py +42 -0
  369. arbora/gateway/widgets/kafka.py +57 -0
  370. arbora/gateway/widgets/keycloak.py +56 -0
  371. arbora/gateway/widgets/langfuse.py +59 -0
  372. arbora/gateway/widgets/leanix.py +58 -0
  373. arbora/gateway/widgets/legal_peripherals.py +30 -0
  374. arbora/gateway/widgets/lgtm.py +65 -0
  375. arbora/gateway/widgets/listmonk.py +53 -0
  376. arbora/gateway/widgets/mattermost.py +55 -0
  377. arbora/gateway/widgets/mealie.py +56 -0
  378. arbora/gateway/widgets/media_downloader.py +48 -0
  379. arbora/gateway/widgets/microsoft.py +45 -0
  380. arbora/gateway/widgets/nextcloud.py +59 -0
  381. arbora/gateway/widgets/okta.py +47 -0
  382. arbora/gateway/widgets/ollama.py +54 -0
  383. arbora/gateway/widgets/onetrust.py +46 -0
  384. arbora/gateway/widgets/openbao.py +49 -0
  385. arbora/gateway/widgets/orchestrator.py +34 -0
  386. arbora/gateway/widgets/owncast.py +48 -0
  387. arbora/gateway/widgets/paperless_ngx.py +46 -0
  388. arbora/gateway/widgets/plane.py +56 -0
  389. arbora/gateway/widgets/portainer.py +99 -0
  390. arbora/gateway/widgets/postiz.py +50 -0
  391. arbora/gateway/widgets/pulselink.py +46 -0
  392. arbora/gateway/widgets/qbittorrent.py +55 -0
  393. arbora/gateway/widgets/repository_manager.py +44 -0
  394. arbora/gateway/widgets/rom_manager.py +63 -0
  395. arbora/gateway/widgets/scholarx.py +36 -0
  396. arbora/gateway/widgets/searxng.py +49 -0
  397. arbora/gateway/widgets/sentry.py +58 -0
  398. arbora/gateway/widgets/servicenow.py +54 -0
  399. arbora/gateway/widgets/stirlingpdf.py +45 -0
  400. arbora/gateway/widgets/systems_manager.py +36 -0
  401. arbora/gateway/widgets/technitium.py +73 -0
  402. arbora/gateway/widgets/teleport.py +28 -0
  403. arbora/gateway/widgets/tunnel_manager.py +44 -0
  404. arbora/gateway/widgets/twenty.py +44 -0
  405. arbora/gateway/widgets/uptime_kuma.py +71 -0
  406. arbora/gateway/widgets/vector_db.py +64 -0
  407. arbora/gateway/widgets/wger.py +50 -0
  408. arbora/gateway/widgets/zulip.py +58 -0
  409. arbora/host_bindings.py +268 -0
  410. arbora/identity/__init__.py +28 -0
  411. arbora/identity/admin_console.py +54 -0
  412. arbora/identity/admission.py +82 -0
  413. arbora/identity/api_keys.py +54 -0
  414. arbora/identity/bootstrap.py +76 -0
  415. arbora/identity/broker.py +304 -0
  416. arbora/identity/browser.py +261 -0
  417. arbora/identity/client_entry_points.py +70 -0
  418. arbora/identity/composition.py +58 -0
  419. arbora/identity/engine.py +168 -0
  420. arbora/identity/engine_ports.py +14 -0
  421. arbora/identity/issuer.py +180 -0
  422. arbora/identity/ldap.py +140 -0
  423. arbora/identity/mail_capability.py +88 -0
  424. arbora/identity/mfa.py +77 -0
  425. arbora/identity/oidc.py +142 -0
  426. arbora/identity/ports.py +83 -0
  427. arbora/identity/saml.py +173 -0
  428. arbora/identity/scim.py +132 -0
  429. arbora/ingest/__init__.py +32 -0
  430. arbora/ingest/service.py +192 -0
  431. arbora/ingest/source_catalog.py +1002 -0
  432. arbora/mcp_server/__init__.py +15 -0
  433. arbora/mcp_server/agent_control.py +48 -0
  434. arbora/mcp_server/arbora_operations.json +1675 -0
  435. arbora/mcp_server/backing/__init__.py +20 -0
  436. arbora/mcp_server/backing/_arbora_action_manifest.py +2242 -0
  437. arbora/mcp_server/backing/action_dispatch.py +256 -0
  438. arbora/mcp_server/backing/arbora_capabilities.json +23321 -0
  439. arbora/mcp_server/backing/arbora_surface.py +294 -0
  440. arbora/mcp_server/backing/client_credentials.py +767 -0
  441. arbora/mcp_server/backing/concurrency.py +127 -0
  442. arbora/mcp_server/backing/connector_surface.py +244 -0
  443. arbora/mcp_server/backing/content_resources.py +64 -0
  444. arbora/mcp_server/backing/context_helpers.py +402 -0
  445. arbora/mcp_server/backing/delegated_auth.py +580 -0
  446. arbora/mcp_server/backing/engine_routing.py +1064 -0
  447. arbora/mcp_server/backing/engine_surface_types.py +67 -0
  448. arbora/mcp_server/backing/eunomia_principal.py +807 -0
  449. arbora/mcp_server/backing/httpx_boundary.py +157 -0
  450. arbora/mcp_server/backing/intent_contract.py +221 -0
  451. arbora/mcp_server/backing/middlewares.py +243 -0
  452. arbora/mcp_server/backing/oauth_log_hygiene.py +100 -0
  453. arbora/mcp_server/backing/ontology_types.py +30 -0
  454. arbora/mcp_server/backing/optional_tool_features.py +44 -0
  455. arbora/mcp_server/backing/remote_oauth_broker.py +1521 -0
  456. arbora/mcp_server/backing/server_factory.py +2745 -0
  457. arbora/mcp_server/backing/skill_coverage.py +553 -0
  458. arbora/mcp_server/backing/tasks_extension.py +1400 -0
  459. arbora/mcp_server/backing/tool_specs.py +349 -0
  460. arbora/mcp_server/backing/tools/__init__.py +51 -0
  461. arbora/mcp_server/backing/tools/_surface_selection.py +37 -0
  462. arbora/mcp_server/backing/tools/analysis_tools.py +2656 -0
  463. arbora/mcp_server/backing/tools/analyze_suite.py +220 -0
  464. arbora/mcp_server/backing/tools/audit_tools.py +106 -0
  465. arbora/mcp_server/backing/tools/candidate_claim_tools.py +173 -0
  466. arbora/mcp_server/backing/tools/compliance_tools.py +396 -0
  467. arbora/mcp_server/backing/tools/config_tools.py +106 -0
  468. arbora/mcp_server/backing/tools/domain_ops_tools.py +114 -0
  469. arbora/mcp_server/backing/tools/engine_surface_tools.py +3618 -0
  470. arbora/mcp_server/backing/tools/engine_tools.py +715 -0
  471. arbora/mcp_server/backing/tools/epistemic_tools.py +265 -0
  472. arbora/mcp_server/backing/tools/governance_tools.py +275 -0
  473. arbora/mcp_server/backing/tools/graph_tools.py +352 -0
  474. arbora/mcp_server/backing/tools/intent_tools.py +2821 -0
  475. arbora/mcp_server/backing/tools/mcp_apps.py +434 -0
  476. arbora/mcp_server/backing/tools/ontology_tools.py +1771 -0
  477. arbora/mcp_server/backing/tools/query_tools.py +3505 -0
  478. arbora/mcp_server/backing/tools/reach_tools.py +98 -0
  479. arbora/mcp_server/backing/tools/secret_tools.py +110 -0
  480. arbora/mcp_server/backing/tools/state_tools.py +245 -0
  481. arbora/mcp_server/backing/tools/write_ingest_tools.py +1684 -0
  482. arbora/mcp_server/backing/verbose_tools.py +808 -0
  483. arbora/mcp_server/backing/write_ingest_types.py +41 -0
  484. arbora/mcp_server/bootstrap.py +738 -0
  485. arbora/mcp_server/catalog_composition.py +127 -0
  486. arbora/mcp_server/composition.py +293 -0
  487. arbora/mcp_server/decide_wiring.py +236 -0
  488. arbora/mcp_server/effect_journal.py +244 -0
  489. arbora/mcp_server/fleet_composition.py +152 -0
  490. arbora/mcp_server/harness_host.py +125 -0
  491. arbora/mcp_server/hosted_invocation.py +58 -0
  492. arbora/mcp_server/legacy_action_mapping.py +87 -0
  493. arbora/mcp_server/operation_registry.py +107 -0
  494. arbora/mcp_server/routes.py +26 -0
  495. arbora/mcp_server/runtime.py +942 -0
  496. arbora/mcp_server/served_engine.py +304 -0
  497. arbora/mcp_server/served_invocation.py +293 -0
  498. arbora/mcp_server/server.py +409 -0
  499. arbora/messaging/__init__.py +5 -0
  500. arbora/messaging/action_dispatch.py +119 -0
  501. arbora/messaging/alert_intake.py +215 -0
  502. arbora/messaging/backends/__init__.py +21 -0
  503. arbora/messaging/backends/discord.py +344 -0
  504. arbora/messaging/backends/googlechat.py +160 -0
  505. arbora/messaging/backends/googlemeet.py +113 -0
  506. arbora/messaging/backends/imessage.py +147 -0
  507. arbora/messaging/backends/irc.py +139 -0
  508. arbora/messaging/backends/line.py +121 -0
  509. arbora/messaging/backends/matrix.py +149 -0
  510. arbora/messaging/backends/mattermost.py +440 -0
  511. arbora/messaging/backends/nextcloud.py +165 -0
  512. arbora/messaging/backends/signal.py +113 -0
  513. arbora/messaging/backends/slack.py +276 -0
  514. arbora/messaging/backends/synology.py +110 -0
  515. arbora/messaging/backends/teams.py +185 -0
  516. arbora/messaging/backends/telegram.py +475 -0
  517. arbora/messaging/backends/twitch.py +128 -0
  518. arbora/messaging/backends/voicecall.py +121 -0
  519. arbora/messaging/backends/whatsapp.py +211 -0
  520. arbora/messaging/base.py +420 -0
  521. arbora/messaging/capabilities.py +444 -0
  522. arbora/messaging/coalescer.py +101 -0
  523. arbora/messaging/commands.py +177 -0
  524. arbora/messaging/governed_send.py +46 -0
  525. arbora/messaging/host_ports.py +63 -0
  526. arbora/messaging/inbox.py +182 -0
  527. arbora/messaging/intake.py +76 -0
  528. arbora/messaging/lease.py +467 -0
  529. arbora/messaging/models.py +303 -0
  530. arbora/messaging/planner_handler.py +111 -0
  531. arbora/messaging/polling.py +171 -0
  532. arbora/messaging/reach.py +19 -0
  533. arbora/messaging/registry.py +413 -0
  534. arbora/messaging/render.py +85 -0
  535. arbora/messaging/router.py +474 -0
  536. arbora/messaging/service.py +565 -0
  537. arbora/messaging/supervision.py +122 -0
  538. arbora/messaging/transport.py +40 -0
  539. arbora/observability/__init__.py +36 -0
  540. arbora/observability/correlation.py +127 -0
  541. arbora/observability/custom_observability.py +1102 -0
  542. arbora/observability/error_detail_sink.py +151 -0
  543. arbora/observability/gateway_health.py +164 -0
  544. arbora/observability/gateway_metrics.py +1338 -0
  545. arbora/observability/health.py +348 -0
  546. arbora/observability/langfuse_exporter.py +385 -0
  547. arbora/observability/langfuse_trust.py +1246 -0
  548. arbora/observability/readiness.py +115 -0
  549. arbora/observability/runtime_health.py +750 -0
  550. arbora/observability/runtime_signals.py +593 -0
  551. arbora/observability/telemetry.py +90 -0
  552. arbora/observability/trace_ontology.py +488 -0
  553. arbora/ontology/shapes/runtime.shapes.ttl +51 -0
  554. arbora/security/__init__.py +13 -0
  555. arbora/security/actor_context.py +184 -0
  556. arbora/security/auth.py +286 -0
  557. arbora/security/config_sensitivity.py +131 -0
  558. arbora/security/conformance/__init__.py +72 -0
  559. arbora/security/conformance/surface_inventory.py +183 -0
  560. arbora/security/conformance/surface_manifest.py +363 -0
  561. arbora/security/delegation.py +459 -0
  562. arbora/security/elevation.py +266 -0
  563. arbora/security/error_surface.py +561 -0
  564. arbora/security/http_boundary.py +441 -0
  565. arbora/security/identifiers.py +120 -0
  566. arbora/security/identity.py +218 -0
  567. arbora/security/log_redaction.py +38 -0
  568. arbora/security/oidc_discovery.py +152 -0
  569. arbora/security/operation_result.py +41 -0
  570. arbora/security/prompt_injection.py +512 -0
  571. arbora/security/request_identity.py +1483 -0
  572. arbora/security/run_token.py +190 -0
  573. arbora/security/scope_registry.py +223 -0
  574. arbora/security/secrets.py +663 -0
  575. arbora/security/security_policy_middleware.py +56 -0
  576. arbora/security/settings.py +112 -0
  577. arbora/semantic_content.py +200 -0
  578. arbora/skills/__init__.py +15 -0
  579. arbora/skills/agent-utilities-source-integration/SKILL.md +181 -0
  580. arbora/skills/agent-utilities-source-integration/agents/arbora.yaml +5 -0
  581. arbora/skills/agent-utilities-source-integration/agents/openai.yaml +4 -0
  582. arbora/skills/arbora-deployment/SKILL.md +203 -0
  583. arbora/skills/arbora-deployment/agents/arbora.yaml +5 -0
  584. arbora/skills/arbora-deployment/agents/openai.yaml +4 -0
  585. arbora/skills/arbora-deployment/references/first-boot-verification.md +80 -0
  586. arbora/skills/arbora-deployment/references/fleet-and-control-plane.md +85 -0
  587. arbora/skills/arbora-deployment/references/identity-and-access.md +147 -0
  588. arbora/skills/arbora-deployment/references/secrets-and-federation.md +67 -0
  589. arbora/skills/arbora-deployment/references/telemetry.md +29 -0
  590. arbora/skills/arbora-development/SKILL.md +144 -0
  591. arbora/skills/arbora-development/references/bootstrap.md +88 -0
  592. arbora/skills/arbora-evolution/SKILL.md +542 -0
  593. arbora/skills/arbora-evolution/agents/arbora.yaml +5 -0
  594. arbora/skills/arbora-evolution/agents/openai.yaml +4 -0
  595. arbora/skills/arbora-genesis/SKILL.md +347 -0
  596. arbora/skills/arbora-genesis/agents/arbora.yaml +5 -0
  597. arbora/skills/arbora-genesis/agents/openai.yaml +4 -0
  598. arbora/skills/arbora-genesis/references/TROUBLESHOOTING.md +39 -0
  599. arbora/skills/arbora-genesis/references/bare-metal.md +45 -0
  600. arbora/skills/arbora-genesis/references/compose-and-podman.md +83 -0
  601. arbora/skills/arbora-genesis/references/data-plane-substrate.md +246 -0
  602. arbora/skills/arbora-genesis/references/deployment-contract.md +99 -0
  603. arbora/skills/arbora-genesis/references/development-workspace.md +62 -0
  604. arbora/skills/arbora-genesis/references/docker-swarm.md +63 -0
  605. arbora/skills/arbora-genesis/references/engine-identity-admission.md +218 -0
  606. arbora/skills/arbora-genesis/references/kubernetes-and-helm.md +111 -0
  607. arbora/skills/arbora-genesis/references/orchestrator-migration-cutover.md +68 -0
  608. arbora/skills/arbora-genesis/references/runtime-topology.md +90 -0
  609. arbora/skills/arbora-genesis/references/security-and-operations.md +128 -0
  610. arbora/skills/arbora-repository-development/SKILL.md +286 -0
  611. arbora/skills/autonomous-contribution/SKILL.md +42 -0
  612. arbora/skills/autonomous-contribution/agents/arbora.yaml +5 -0
  613. arbora/skills/autonomous-contribution/agents/openai.yaml +4 -0
  614. arbora/skills/core-pack.txt +15 -0
  615. arbora/skills/graph-engine-and-modalities/SKILL.md +127 -0
  616. arbora/skills/graph-engine-and-modalities/agents/arbora.yaml +37 -0
  617. arbora/skills/graph-engine-and-modalities/agents/openai.yaml +4 -0
  618. arbora/skills/graph-ingestion-and-integration/SKILL.md +191 -0
  619. arbora/skills/graph-ingestion-and-integration/agents/arbora.yaml +15 -0
  620. arbora/skills/graph-ingestion-and-integration/agents/openai.yaml +4 -0
  621. arbora/skills/graph-ingestion-and-integration/references/ingest-connector-reference.md +261 -0
  622. arbora/skills/graph-ingestion-and-integration/references/ingest_manifest.yaml +77 -0
  623. arbora/skills/graph-modeling-and-mutation/SKILL.md +136 -0
  624. arbora/skills/graph-modeling-and-mutation/agents/arbora.yaml +22 -0
  625. arbora/skills/graph-modeling-and-mutation/agents/openai.yaml +4 -0
  626. arbora/skills/graph-orchestration-and-automation/SKILL.md +128 -0
  627. arbora/skills/graph-orchestration-and-automation/agents/arbora.yaml +12 -0
  628. arbora/skills/graph-orchestration-and-automation/agents/openai.yaml +4 -0
  629. arbora/skills/graph-query-and-explanation/SKILL.md +166 -0
  630. arbora/skills/graph-query-and-explanation/agents/arbora.yaml +28 -0
  631. arbora/skills/graph-query-and-explanation/agents/openai.yaml +4 -0
  632. arbora/skills/graph-query-and-explanation/references/uql-reference.md +432 -0
  633. arbora/skills/graph-research-and-analysis/SKILL.md +160 -0
  634. arbora/skills/graph-research-and-analysis/agents/arbora.yaml +11 -0
  635. arbora/skills/graph-research-and-analysis/agents/openai.yaml +4 -0
  636. arbora/skills/graph-runtime-and-governance/SKILL.md +165 -0
  637. arbora/skills/graph-runtime-and-governance/agents/arbora.yaml +17 -0
  638. arbora/skills/graph-runtime-and-governance/agents/openai.yaml +4 -0
  639. arbora/skills/using-arbora/SKILL.md +114 -0
  640. arbora/webui_host/__init__.py +10 -0
  641. arbora/webui_host/contact_delivery.py +259 -0
  642. arbora/webui_host/contact_governance.py +282 -0
  643. arbora/webui_host/mcp_delegation.py +136 -0
  644. arbora/webui_host/package_layout_expectation.py +70 -0
  645. arbora/webui_host/voice_delegation.py +74 -0
  646. arbora/webui_host/webui_co_service.py +251 -0
  647. arbora/work_items.py +251 -0
  648. arbora-0.1.0.dist-info/METADATA +223 -0
  649. arbora-0.1.0.dist-info/RECORD +653 -0
  650. arbora-0.1.0.dist-info/WHEEL +5 -0
  651. arbora-0.1.0.dist-info/entry_points.txt +39 -0
  652. arbora-0.1.0.dist-info/licenses/LICENSE +21 -0
  653. arbora-0.1.0.dist-info/top_level.txt +1 -0
arbora/__init__.py ADDED
@@ -0,0 +1,29 @@
1
+ """Arbora: the deployable composition for the Knuckles agent platform.
2
+
3
+ RF-ADR-009 (`plans/refactor/RF-ADR-009-connector-sdk-and-arbora.md`) §2 assigns
4
+ this repository phase 5: **the deployable composition** — the MCP server, REST
5
+ gateway, control plane, fleet gateway, agent-webui hosting, and deployment
6
+ tooling. It must never own business logic that belongs to
7
+ epistemic-graph, agent-connector-sdk, or the agent-utilities agent plane.
8
+
9
+ The live package layout is:
10
+
11
+ - `arbora.mcp_server` — native MCP/REST composition and serving lifecycle.
12
+ - `arbora.fleet` — in-process MCP fleet gateway and child lifecycle.
13
+ - `arbora.gateway` — REST gateway and dashboard projections.
14
+ - `arbora.control_plane` — reconciliation and action policy.
15
+ - `arbora.webui_host` — optional Agent WebUI co-service hosting.
16
+ - `arbora.deployment` — configuration, diagnostics, canaries, and operations.
17
+
18
+ The ``arbora`` console command serves
19
+ ``arbora.mcp_server.server:mcp_server`` over stdio or authenticated
20
+ streamable HTTP. Capability limits that depend on unfinished upstream
21
+ contracts are documented in ``docs/status.md`` and fail closed; no legacy
22
+ fallback is implied by this package description.
23
+ """
24
+
25
+ from arbora._version import __version__
26
+
27
+ from . import epistemic
28
+
29
+ __all__ = ["__version__", "epistemic"]
arbora/_version.py ADDED
@@ -0,0 +1,6 @@
1
+ """Single source of truth for the installed arbora version.
2
+
3
+ Updated only by `bumpversion` (see `.bumpversion.cfg`) — never hand-edited.
4
+ """
5
+
6
+ __version__ = "0.1.0"
arbora/a2a/__init__.py ADDED
@@ -0,0 +1,74 @@
1
+ """First-party Arbora unary A2A facade."""
2
+
3
+ from .application import (
4
+ A2AAuthenticator,
5
+ AmbientA2AAuthenticator,
6
+ create_a2a_application,
7
+ create_a2a_handlers,
8
+ )
9
+ from .authority import (
10
+ A2AIdempotencyConflict,
11
+ A2ATaskAuthority,
12
+ A2ATaskNotCancelable,
13
+ WorkItemA2AAuthority,
14
+ )
15
+ from .composition import A2AComposition, compose_a2a
16
+ from .models import (
17
+ A2AAgentCard,
18
+ A2AListResult,
19
+ A2AMessage,
20
+ A2ARouteDecision,
21
+ A2ATask,
22
+ )
23
+ from .routing import A2AAssemblyUnavailable, A2ARouter, OrchestratorA2ARouter
24
+ from .sdk_app import AdmittedA2AApp, create_admitted_a2a_app
25
+ from .service import A2ACardMetadata, A2AService
26
+ from .tool_task import (
27
+ ToolTaskCarrier,
28
+ ToolTaskDispatcher,
29
+ ToolTaskRequest,
30
+ ToolTaskResult,
31
+ WorkItemFence,
32
+ run_tool_task,
33
+ )
34
+ from .work_items import (
35
+ WorkItemView,
36
+ list_work_item_views,
37
+ parse_work_item_view,
38
+ work_item_view,
39
+ )
40
+
41
+ __all__ = [
42
+ "AdmittedA2AApp",
43
+ "create_admitted_a2a_app",
44
+ "A2AAgentCard",
45
+ "A2AAssemblyUnavailable",
46
+ "A2AAuthenticator",
47
+ "A2ACardMetadata",
48
+ "A2AComposition",
49
+ "A2AIdempotencyConflict",
50
+ "A2AListResult",
51
+ "A2AMessage",
52
+ "A2ARouteDecision",
53
+ "A2ARouter",
54
+ "A2AService",
55
+ "A2ATask",
56
+ "A2ATaskAuthority",
57
+ "A2ATaskNotCancelable",
58
+ "AmbientA2AAuthenticator",
59
+ "OrchestratorA2ARouter",
60
+ "ToolTaskCarrier",
61
+ "ToolTaskDispatcher",
62
+ "ToolTaskRequest",
63
+ "ToolTaskResult",
64
+ "WorkItemA2AAuthority",
65
+ "WorkItemFence",
66
+ "WorkItemView",
67
+ "compose_a2a",
68
+ "create_a2a_application",
69
+ "create_a2a_handlers",
70
+ "list_work_item_views",
71
+ "parse_work_item_view",
72
+ "run_tool_task",
73
+ "work_item_view",
74
+ ]
@@ -0,0 +1,67 @@
1
+ """Typed context-budget tool-subset admission for the A2A door.
2
+
3
+ Owned by ``GRAPHOS-A2A-002``: admission, refusal, and provenance for the
4
+ smallest authorized tool subset that covers a selected agent graph within a
5
+ caller's context budget (see ``docs/a2a.md``, "Tool-subset assembly
6
+ status"). This fails closed today because epistemic-graph's
7
+ ``AgentAssemble`` operation returns unavailable and the signed AU
8
+ ``AgentTurnEnvelope`` carries no allowed-tool-subset field
9
+ (agent-utilities ``AU-CONTROL-R035``). Neither upstream gap is bridged with a
10
+ local heuristic, a cached prior subset, or an advisory best-effort answer.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from typing import Literal
16
+
17
+ from pydantic import Field
18
+
19
+ from .models import A2AContextBudget, _WireModel
20
+
21
+ __all__ = [
22
+ "ToolSubsetAdmissionDecision",
23
+ "ToolSubsetAdmissionRefusalReason",
24
+ "ToolSubsetAdmissionRequest",
25
+ "admit_tool_subset",
26
+ ]
27
+
28
+ ToolSubsetAdmissionRefusalReason = Literal[
29
+ "EG_ASSEMBLE_UNAVAILABLE",
30
+ "ENVELOPE_LACKS_ALLOWED_TOOL_SUBSET",
31
+ ]
32
+
33
+
34
+ class ToolSubsetAdmissionRequest(_WireModel):
35
+ """A caller's request to admit the smallest authorized tool subset."""
36
+
37
+ agent_graph_ref: str = Field(min_length=1, max_length=512)
38
+ context_budget: A2AContextBudget
39
+
40
+
41
+ class ToolSubsetAdmissionDecision(_WireModel):
42
+ """The door's admit/refuse result. Never advisory; never partial."""
43
+
44
+ admitted: bool
45
+ admitted_tools: tuple[str, ...] = Field(default=(), max_length=64)
46
+ refusal_reason: ToolSubsetAdmissionRefusalReason | None = None
47
+ provenance: str = Field(min_length=1, max_length=256)
48
+
49
+
50
+ def admit_tool_subset(
51
+ request: ToolSubsetAdmissionRequest,
52
+ ) -> ToolSubsetAdmissionDecision:
53
+ """Admit the request, or fail closed with a typed, provenanced refusal.
54
+
55
+ ``GRAPHOS-A2A-R017.1``: epistemic-graph's ``AgentAssemble`` operation
56
+ returns unavailable today, so no context-budget-bound tool subset can be
57
+ derived or cryptographically carried. This refuses closed rather than
58
+ returning an advisory, cached, or partial subset.
59
+ """
60
+
61
+ del request
62
+ return ToolSubsetAdmissionDecision(
63
+ admitted=False,
64
+ admitted_tools=(),
65
+ refusal_reason="EG_ASSEMBLE_UNAVAILABLE",
66
+ provenance="eg.AgentAssemble:unavailable",
67
+ )
@@ -0,0 +1,498 @@
1
+ """Authenticated Agent Card and JSON-RPC unary A2A transport."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable, Iterator
6
+ from contextlib import contextmanager
7
+ from secrets import token_hex
8
+ from typing import TYPE_CHECKING, Any, Protocol, runtime_checkable
9
+
10
+ from fastapi import FastAPI, Request
11
+ from fastapi.encoders import jsonable_encoder
12
+ from fastapi.responses import JSONResponse
13
+ from pydantic import BaseModel, ConfigDict, Field, ValidationError
14
+
15
+ from arbora.api.http.auth import HTTPAuthenticationError
16
+
17
+ from .authority import (
18
+ A2AIdempotencyConflict,
19
+ A2AStreamingUnavailable,
20
+ A2ATaskNotCancelable,
21
+ A2ATransitionHistoryUnavailable,
22
+ )
23
+ from .models import A2AMessage, A2AOperationInvokeParams, A2APlanConfirmParams
24
+ from .routing import A2AAssemblyUnavailable, A2AOperationBridgeUnavailable
25
+ from .service import A2AService
26
+ from .terminal_event import A2ATerminalEventUnavailable
27
+
28
+ if TYPE_CHECKING:
29
+ from arbora.api.http.auth import AmbientHTTPAuthenticator
30
+ from arbora.api.invoke.pipeline import InvokeServices
31
+ from arbora.api.invoke.steps import VerifiedCaller
32
+
33
+ __all__ = [
34
+ "A2AAuthenticator",
35
+ "AmbientA2AAuthenticator",
36
+ "create_a2a_application",
37
+ "create_a2a_handlers",
38
+ ]
39
+
40
+
41
+ @runtime_checkable
42
+ class A2AAuthenticator(Protocol):
43
+ async def authenticate(
44
+ self, request: Request, *, scope: str
45
+ ) -> VerifiedCaller | None:
46
+ """Verify authority; an injected adapter may own its dispatch binding."""
47
+
48
+
49
+ class AmbientA2AAuthenticator:
50
+ """Resolve each HTTP request through AU's verified bearer/session flow."""
51
+
52
+ async def authenticate(self, request: Request, *, scope: str) -> VerifiedCaller:
53
+ caller = await _request_caller(request)
54
+ return _require_caller_scope(caller, scope)
55
+
56
+
57
+ async def _request_caller(request: Request) -> VerifiedCaller:
58
+ from arbora.api.http.auth import (
59
+ AmbientHTTPAuthenticator,
60
+ verified_bearer_session_for_request,
61
+ )
62
+
63
+ return await AmbientHTTPAuthenticator(
64
+ session_for_request=verified_bearer_session_for_request
65
+ ).authenticate(request)
66
+
67
+
68
+ def _require_caller_scope(caller: VerifiedCaller, scope: str) -> VerifiedCaller:
69
+ if scope not in caller.effective_scopes:
70
+ raise PermissionError("Required A2A scope unavailable")
71
+ return caller
72
+
73
+
74
+ async def _refresh_unary_caller(caller: VerifiedCaller | None) -> None:
75
+ """Refuse changed authority before entering the task service's session."""
76
+ if caller is None:
77
+ return
78
+ from arbora.api.invoke.bootstrap import (
79
+ SessionRequiredError,
80
+ verify_current_from_session,
81
+ )
82
+ from arbora.api.invoke.steps import authenticate
83
+
84
+ try:
85
+ current = await verify_current_from_session(caller)
86
+ except SessionRequiredError:
87
+ raise HTTPAuthenticationError("Current A2A authority required") from None
88
+ if current != caller or authenticate(current) is not None:
89
+ raise HTTPAuthenticationError("Current A2A authority required")
90
+
91
+
92
+ @contextmanager
93
+ def _caller_session_scope(caller: VerifiedCaller | None) -> Iterator[None]:
94
+ """Bind a returned caller through legacy dispatch; never resolve a fallback."""
95
+ if caller is None:
96
+ # Explicit injected authenticators already own their admission/binding.
97
+ yield
98
+ return
99
+ from arbora.api.contracts.session import use_session
100
+ from arbora.security.actor_context import use_actor
101
+
102
+ with use_actor(caller.session.actor), use_session(caller.session):
103
+ yield
104
+
105
+
106
+ def _authentication_error(request_id: Any, error: PermissionError) -> JSONResponse:
107
+ status = 401 if isinstance(error, HTTPAuthenticationError) else 403
108
+ return _error(request_id, -32001, "A2A authority refused", status)
109
+
110
+
111
+ class _Params(BaseModel):
112
+ model_config = ConfigDict(populate_by_name=True, extra="forbid")
113
+
114
+
115
+ class _SendParams(_Params):
116
+ message: A2AMessage
117
+ context_budget_tokens: int | None = Field(
118
+ default=None, alias="contextBudgetTokens", ge=256, le=1_000_000
119
+ )
120
+
121
+
122
+ class _TaskParams(_Params):
123
+ id: str = Field(min_length=1, max_length=80)
124
+
125
+
126
+ class _GetTaskParams(_TaskParams):
127
+ include_committed_event: bool = Field(
128
+ default=False, alias="includeCommittedEvent", strict=True
129
+ )
130
+
131
+
132
+ class _ResubscribeParams(_Params):
133
+ id: str = Field(min_length=1, max_length=80)
134
+ cursor: str | None = Field(default=None, max_length=1024)
135
+
136
+
137
+ class _ListParams(_Params):
138
+ cursor: str | None = Field(default=None, max_length=1024)
139
+ limit: int = Field(default=50, ge=1, le=100)
140
+
141
+
142
+ def _error(request_id: Any, code: int, message: str, status: int = 400) -> JSONResponse:
143
+ return JSONResponse(
144
+ {
145
+ "jsonrpc": "2.0",
146
+ "id": request_id,
147
+ "error": {"code": code, "message": message},
148
+ },
149
+ status_code=status,
150
+ headers={"Cache-Control": "no-store"},
151
+ )
152
+
153
+
154
+ async def _request_envelope(
155
+ request: Request,
156
+ ) -> tuple[Any, str, dict[str, Any]] | JSONResponse:
157
+ try:
158
+ body = await request.json()
159
+ except ValueError:
160
+ return _error(None, -32700, "Parse error")
161
+ if not isinstance(body, dict) or body.get("jsonrpc") != "2.0":
162
+ request_id = body.get("id") if isinstance(body, dict) else None
163
+ return _error(request_id, -32600, "Invalid Request")
164
+ request_id = body.get("id")
165
+ method = body.get("method")
166
+ params = body.get("params")
167
+ if not isinstance(method, str) or not isinstance(params, dict):
168
+ return _error(request_id, -32602, "Invalid params")
169
+ return request_id, method, params
170
+
171
+
172
+ async def _send_message(service: A2AService, request: Request, raw_params: Any) -> Any:
173
+ send_params = _SendParams.model_validate(raw_params)
174
+ key = request.headers.get("Idempotency-Key", "")
175
+ if not key:
176
+ raise ValueError("Idempotency-Key is required")
177
+ return await service.send_message(
178
+ message=send_params.message,
179
+ idempotency_key=key,
180
+ context_budget_tokens=send_params.context_budget_tokens,
181
+ )
182
+
183
+
184
+ async def _get_task(service: A2AService, raw_params: Any, request_id: Any) -> Any:
185
+ task_params = _GetTaskParams.model_validate(raw_params)
186
+ result = await service.get_task(
187
+ task_params.id, include_committed_event=task_params.include_committed_event
188
+ )
189
+ return result or _error(request_id, -32001, "Task not found", 404)
190
+
191
+
192
+ def _resubscribe_stub(raw_params: Any) -> Any:
193
+ # Registered in the method table (GRAPHOS-A2A-R001) but fail-closed:
194
+ # durable streaming has no bounded, restart-safe event-cursor backing
195
+ # yet. Params are still validated so a malformed call is rejected as
196
+ # invalid, not treated as an unreachable method.
197
+ _ResubscribeParams.model_validate(raw_params)
198
+ raise A2AStreamingUnavailable(
199
+ "durable task streaming and resubscribe are not available yet"
200
+ )
201
+
202
+
203
+ def _op_invoke_stub(raw_params: Any) -> Any:
204
+ # Registered in the method table (GRAPHOS-A2A-R006) but fail-closed:
205
+ # the shared hosted-operation registry's invoke path is not bridged in
206
+ # yet. Params are still validated so a malformed call is rejected as
207
+ # invalid, not treated as an unreachable method.
208
+ A2AOperationInvokeParams.model_validate(raw_params)
209
+ raise A2AOperationBridgeUnavailable(
210
+ "arbora.op/invoke is not bridged to the shared operation registry yet"
211
+ )
212
+
213
+
214
+ def _plan_confirm_stub(raw_params: Any) -> Any:
215
+ # Registered in the method table (GRAPHOS-A2A-R005/R006) but
216
+ # fail-closed: the signed human approval exchange is not implemented
217
+ # end to end yet, so no approval attempt may succeed.
218
+ from .approval import verify_pending_signature
219
+
220
+ confirmation = A2APlanConfirmParams.model_validate(raw_params)
221
+ # No trusted human-key resolver or durable pending/grant authority is wired.
222
+ # A parsed payload or valid detached signature cannot supply that authority.
223
+ check = verify_pending_signature(confirmation, evidence=None)
224
+ raise A2AOperationBridgeUnavailable(
225
+ f"arbora.plan/confirm authority unavailable: {check.value}"
226
+ )
227
+
228
+
229
+ _SYNC_METHODS: dict[str, Callable[[Any], Any]] = {
230
+ "tasks/resubscribe": _resubscribe_stub,
231
+ "arbora.op/invoke": _op_invoke_stub,
232
+ "arbora.plan/confirm": _plan_confirm_stub,
233
+ }
234
+
235
+
236
+ async def _invoke_method(
237
+ service: A2AService,
238
+ request: Request,
239
+ method: str,
240
+ raw_params: dict[str, Any],
241
+ request_id: Any,
242
+ ) -> Any:
243
+ """Validate and invoke one unary method on the shared service."""
244
+ if method == "message/send":
245
+ return await _send_message(service, request, raw_params)
246
+ if method == "tasks/get":
247
+ return await _get_task(service, raw_params, request_id)
248
+ if method == "tasks/list":
249
+ list_params = _ListParams.model_validate(raw_params)
250
+ return await service.list_tasks(
251
+ cursor=list_params.cursor, limit=list_params.limit
252
+ )
253
+ if method == "tasks/cancel":
254
+ cancel_params = _TaskParams.model_validate(raw_params)
255
+ return await service.cancel_task(cancel_params.id)
256
+ sync_handler = _SYNC_METHODS.get(method)
257
+ if sync_handler is not None:
258
+ return sync_handler(raw_params)
259
+ return _error(request_id, -32601, "Method not found", 404)
260
+
261
+
262
+ _ERROR_CODES: dict[type[Exception], tuple[int, int]] = {
263
+ A2ATerminalEventUnavailable: (-32013, 503),
264
+ A2AIdempotencyConflict: (-32009, 409),
265
+ A2AAssemblyUnavailable: (-32003, 503),
266
+ A2ATaskNotCancelable: (-32002, 409),
267
+ A2AStreamingUnavailable: (-32010, 501),
268
+ A2AOperationBridgeUnavailable: (-32011, 501),
269
+ A2ATransitionHistoryUnavailable: (-32012, 501),
270
+ }
271
+
272
+
273
+ def _application_error(request_id: Any, error: Exception) -> JSONResponse:
274
+ """Translate known service failures without echoing caller input."""
275
+ mapped = _ERROR_CODES.get(type(error))
276
+ if mapped is not None:
277
+ code, status = mapped
278
+ return _error(request_id, code, str(error), status)
279
+ # Pydantic errors may echo caller text in ``input_value``. Keep the wire
280
+ # error stable and privacy-safe; details belong in local logs.
281
+ return _error(request_id, -32602, "Invalid params")
282
+
283
+
284
+ def _operation_response(
285
+ outcome: Any, *, op: str, request_id: Any, caller_id: str, digest: str
286
+ ) -> JSONResponse:
287
+ """Project shared operation outcomes without reclassifying refusals."""
288
+ from arbora.api.errors import a2a_error_status, to_envelope
289
+ from arbora.api.invoke.steps import OpError
290
+
291
+ status = 200
292
+ if outcome.code == "OK":
293
+ payload = {
294
+ "ok": True,
295
+ "result": jsonable_encoder(outcome.value),
296
+ "meta": {"registry_digest": digest, "api_version": "v1"},
297
+ }
298
+ else:
299
+ status, payload = to_envelope(
300
+ outcome,
301
+ op=op,
302
+ request_id=caller_id or token_hex(12),
303
+ registry_digest=digest,
304
+ )
305
+ body: dict[str, Any] = {"jsonrpc": "2.0", "id": request_id}
306
+ if isinstance(outcome, OpError):
307
+ code, status = a2a_error_status(outcome.code, source=outcome.source)
308
+ body["error"] = {
309
+ "code": code,
310
+ "message": payload["error"]["message"],
311
+ "data": payload,
312
+ }
313
+ else:
314
+ body["result"] = payload
315
+ return JSONResponse(body, status_code=status, headers={"Cache-Control": "no-store"})
316
+
317
+
318
+ async def _invoke_operation(
319
+ request: Request,
320
+ raw_params: dict[str, Any],
321
+ request_id: Any,
322
+ services: InvokeServices,
323
+ authenticator: AmbientHTTPAuthenticator,
324
+ ) -> JSONResponse:
325
+ from arbora.api.http.auth import HTTPAuthenticationError
326
+ from arbora.api.invoke.pipeline import invoke
327
+ from arbora.api.invoke.steps import OpError, OpResult
328
+ from arbora.api.registry import Surface
329
+
330
+ params = A2AOperationInvokeParams.model_validate(raw_params)
331
+ caller_id = ""
332
+ outcome: OpError | OpResult
333
+ try:
334
+ caller = await authenticator.authenticate(request)
335
+ except HTTPAuthenticationError:
336
+ outcome = OpError("UNAUTHENTICATED")
337
+ else:
338
+ # A plan reference cannot substitute for the missing signed A2A exchange.
339
+ if params.plan_ref is not None:
340
+ raise A2AOperationBridgeUnavailable(
341
+ "A2A plan consumption requires the signed approval exchange"
342
+ )
343
+ caller_id = caller.request_id
344
+ outcome = await invoke(
345
+ params.op,
346
+ params.params,
347
+ caller,
348
+ Surface.A2A,
349
+ services=services,
350
+ idempotency_key=params.idempotency_key,
351
+ )
352
+ return _operation_response(
353
+ outcome,
354
+ op=params.op,
355
+ request_id=request_id,
356
+ caller_id=caller_id,
357
+ digest=services.registry.digest,
358
+ )
359
+
360
+
361
+ def _validate_operation_composition(
362
+ services: InvokeServices | None,
363
+ authenticator: AmbientHTTPAuthenticator | None,
364
+ ) -> None:
365
+ if (services is None) != (authenticator is None):
366
+ raise ValueError(
367
+ "operation services and authenticator must be composed together"
368
+ )
369
+
370
+
371
+ async def _operation_request(
372
+ request: Request,
373
+ raw_params: dict[str, Any],
374
+ request_id: Any,
375
+ services: InvokeServices,
376
+ authenticator: AmbientHTTPAuthenticator,
377
+ ) -> JSONResponse:
378
+ try:
379
+ return await _invoke_operation(
380
+ request, raw_params, request_id, services, authenticator
381
+ )
382
+ except (A2AOperationBridgeUnavailable, ValidationError) as error:
383
+ return _application_error(request_id, error)
384
+
385
+
386
+ async def _unary_request(
387
+ service: A2AService,
388
+ authenticator: A2AAuthenticator,
389
+ request: Request,
390
+ method: str,
391
+ raw_params: dict[str, Any],
392
+ request_id: Any,
393
+ ) -> JSONResponse:
394
+ write_methods = {"message/send", "tasks/cancel", "arbora.plan/confirm"}
395
+ scope = "kg:write" if method in write_methods else "kg:read"
396
+ try:
397
+ caller = await authenticator.authenticate(request, scope=scope)
398
+ await _refresh_unary_caller(caller)
399
+ with _caller_session_scope(caller):
400
+ result = await _invoke_method(
401
+ service, request, method, raw_params, request_id
402
+ )
403
+ except PermissionError as error:
404
+ return _authentication_error(request_id, error)
405
+ except (
406
+ A2ATerminalEventUnavailable,
407
+ A2AIdempotencyConflict,
408
+ A2AAssemblyUnavailable,
409
+ A2AOperationBridgeUnavailable,
410
+ A2AStreamingUnavailable,
411
+ A2ATransitionHistoryUnavailable,
412
+ A2ATaskNotCancelable,
413
+ ValidationError,
414
+ TypeError,
415
+ ValueError,
416
+ ) as error:
417
+ return _application_error(request_id, error)
418
+ return _unary_response(result, request_id)
419
+
420
+
421
+ def _unary_response(result: Any, request_id: Any) -> JSONResponse:
422
+ if isinstance(result, JSONResponse):
423
+ return result
424
+ payload = result.model_dump(mode="json", by_alias=True)
425
+ return JSONResponse(
426
+ {"jsonrpc": "2.0", "id": request_id, "result": payload},
427
+ headers={"Cache-Control": "no-store"},
428
+ )
429
+
430
+
431
+ async def _agent_card_request(
432
+ service: A2AService, authenticator: A2AAuthenticator, request: Request
433
+ ) -> JSONResponse:
434
+ try:
435
+ await authenticator.authenticate(request, scope="kg:read")
436
+ except PermissionError as error:
437
+ return _authentication_error(None, error)
438
+ endpoint = str(request.url.replace(path="/a2a", query=""))
439
+ return JSONResponse(
440
+ service.agent_card(endpoint).model_dump(mode="json", by_alias=True),
441
+ headers={"Cache-Control": "no-store"},
442
+ )
443
+
444
+
445
+ def create_a2a_handlers(
446
+ *,
447
+ service: A2AService,
448
+ authenticator: A2AAuthenticator,
449
+ operation_services: InvokeServices | None = None,
450
+ operation_authenticator: AmbientHTTPAuthenticator | None = None,
451
+ ) -> tuple[Any, Any]:
452
+ """Create route handlers reusable by standalone FastAPI and FastMCP."""
453
+ if not isinstance(authenticator, A2AAuthenticator):
454
+ raise TypeError("authenticator does not implement A2AAuthenticator")
455
+ _validate_operation_composition(operation_services, operation_authenticator)
456
+
457
+ async def agent_card(request: Request) -> JSONResponse:
458
+ return await _agent_card_request(service, authenticator, request)
459
+
460
+ async def json_rpc(request: Request) -> JSONResponse:
461
+ envelope = await _request_envelope(request)
462
+ if isinstance(envelope, JSONResponse):
463
+ return envelope
464
+ request_id, method, raw_params = envelope
465
+ if method == "arbora.op/invoke" and operation_services is not None:
466
+ assert operation_authenticator is not None
467
+ return await _operation_request(
468
+ request,
469
+ raw_params,
470
+ request_id,
471
+ operation_services,
472
+ operation_authenticator,
473
+ )
474
+ return await _unary_request(
475
+ service, authenticator, request, method, raw_params, request_id
476
+ )
477
+
478
+ return agent_card, json_rpc
479
+
480
+
481
+ def create_a2a_application(
482
+ *,
483
+ service: A2AService,
484
+ authenticator: A2AAuthenticator,
485
+ operation_services: InvokeServices | None = None,
486
+ operation_authenticator: AmbientHTTPAuthenticator | None = None,
487
+ ) -> FastAPI:
488
+ metadata = service.card_metadata
489
+ app = FastAPI(title=f"{metadata.name} A2A", version=metadata.version)
490
+ card_handler, rpc_handler = create_a2a_handlers(
491
+ service=service,
492
+ authenticator=authenticator,
493
+ operation_services=operation_services,
494
+ operation_authenticator=operation_authenticator,
495
+ )
496
+ app.add_api_route("/.well-known/agent-card.json", card_handler, methods=["GET"])
497
+ app.add_api_route("/a2a", rpc_handler, methods=["POST"])
498
+ return app