ltcai 11.5.2 → 11.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (443) hide show
  1. package/README.md +93 -148
  2. package/bin/ltcai.js +234 -24
  3. package/docs/CHANGELOG.md +119 -0
  4. package/docs/COMMUNITY_AND_PLUGINS.md +1 -1
  5. package/docs/DEVELOPMENT.md +8 -6
  6. package/docs/ENTERPRISE.md +2 -1
  7. package/docs/MULTI_AGENT_RUNTIME.md +12 -5
  8. package/docs/ONBOARDING.md +1 -1
  9. package/docs/OPERATIONS.md +6 -3
  10. package/docs/REALTIME_COLLABORATION.md +1 -1
  11. package/docs/TRUST_MODEL.md +1 -1
  12. package/docs/WHY_LATTICE.md +1 -1
  13. package/docs/WORKFLOW_DESIGNER.md +3 -2
  14. package/docs/kg-schema.md +1 -1
  15. package/docs/v11.6.0_ONE_DOOR_PLAN.md +170 -0
  16. package/lattice_brain/__init__.py +42 -79
  17. package/lattice_brain/graph/__init__.py +9 -24
  18. package/lattice_brain/graph/_kg_common/__init__.py +13 -24
  19. package/lattice_brain/ingestion/__init__.py +19 -58
  20. package/lattice_brain/ingestion/pipeline.py +20 -398
  21. package/lattice_brain/multimodal/__init__.py +7 -18
  22. package/lattice_brain/multimodal/images.py +6 -264
  23. package/lattice_brain/multimodal/video.py +8 -247
  24. package/lattice_brain/runtime/__init__.py +8 -79
  25. package/lattice_brain/runtime/hooks.py +22 -584
  26. package/latticeai/__init__.py +1 -1
  27. package/latticeai/api/agent_worker_seam.py +7 -80
  28. package/latticeai/api/health.py +6 -20
  29. package/latticeai/api/local_files.py +16 -613
  30. package/latticeai/api/models.py +12 -87
  31. package/latticeai/api/search.py +17 -255
  32. package/latticeai/api/tools.py +69 -750
  33. package/latticeai/api/voice_capture.py +8 -70
  34. package/latticeai/api/worker_compute.py +842 -0
  35. package/latticeai/api/worker_seams.py +216 -0
  36. package/latticeai/app_factory.py +23 -232
  37. package/latticeai/cli/entrypoint.py +36 -249
  38. package/latticeai/core/agent_permission.py +16 -91
  39. package/latticeai/core/messages.py +89 -531
  40. package/latticeai/runtime/access_runtime.py +0 -14
  41. package/latticeai/runtime/bootstrap.py +10 -21
  42. package/latticeai/runtime/brain_runtime.py +35 -43
  43. package/latticeai/runtime/build_phases/__init__.py +21 -37
  44. package/latticeai/runtime/build_phases/features.py +99 -389
  45. package/latticeai/runtime/build_phases/foundation.py +82 -392
  46. package/latticeai/runtime/build_phases/web.py +91 -408
  47. package/latticeai/runtime/build_phases/worker_profile.py +244 -0
  48. package/latticeai/runtime/lifespan_runtime.py +7 -16
  49. package/latticeai/runtime/platform_services_runtime.py +1 -15
  50. package/latticeai/runtime/runtime_context.py +13 -130
  51. package/latticeai/runtime/security_runtime.py +10 -103
  52. package/latticeai/services/architecture_readiness.py +82 -43
  53. package/latticeai/services/model_runtime/__init__.py +2 -11
  54. package/latticeai/services/model_runtime/service.py +4 -28
  55. package/latticeai/services/p_reinforce.py +10 -261
  56. package/latticeai/services/product_readiness.py +31 -38
  57. package/latticeai/services/search_service.py +37 -795
  58. package/latticeai/services/tool_dispatch.py +30 -386
  59. package/latticeai/services/voice_capture.py +13 -107
  60. package/latticeai/tools/__init__.py +22 -49
  61. package/latticeai/tools/commands.py +0 -163
  62. package/latticeai/tools/computer.py +0 -39
  63. package/latticeai/tools/documents.py +1 -134
  64. package/latticeai/tools/filesystem.py +1 -247
  65. package/latticeai/tools/knowledge.py +1 -52
  66. package/latticeai/tools/local_files.py +0 -20
  67. package/latticeai/worker_app.py +75 -0
  68. package/package.json +2 -3
  69. package/requirements.txt +0 -5
  70. package/scripts/agent_eval.py +16 -28
  71. package/scripts/brain_quality_eval.py +20 -183
  72. package/scripts/bump_version.py +5 -5
  73. package/scripts/check_current_release_docs.mjs +7 -4
  74. package/scripts/check_openapi_drift.mjs +10 -0
  75. package/scripts/check_server_i18n.mjs +2 -18
  76. package/scripts/compose_openapi.py +377 -0
  77. package/scripts/export_openapi.py +32 -4
  78. package/scripts/gen_messages_catalog_fixture.py +302 -0
  79. package/scripts/gen_openapi_fragments.py +365 -0
  80. package/scripts/gen_redact_fixture.py +196 -0
  81. package/scripts/gen_worker_allowlist_fixture.py +115 -0
  82. package/scripts/generate_agent_parity_fixtures.py +33 -14
  83. package/scripts/openapi_route_families.json +2161 -0
  84. package/scripts/release_screen_claims.json +54 -0
  85. package/scripts/run_integration_tests.mjs +134 -29
  86. package/scripts/run_sidecar_e2e.mjs +104 -11
  87. package/scripts/wheel_smoke.py +32 -22
  88. package/src-tauri/Cargo.lock +375 -9
  89. package/src-tauri/Cargo.toml +1 -1
  90. package/src-tauri/src/backend.rs +151 -45
  91. package/src-tauri/src/main.rs +18 -18
  92. package/src-tauri/src/topology.rs +58 -88
  93. package/src-tauri/tauri.conf.json +1 -2
  94. package/static/app/asset-manifest.json +41 -41
  95. package/static/app/assets/{Act-DcQizkl1.js → Act-BPcVAbOL.js} +1 -1
  96. package/static/app/assets/AdminConsole-Bw1ATQL0.js +1 -0
  97. package/static/app/assets/{Brain-3VCSHFcn.js → Brain-CT92Kos0.js} +2 -2
  98. package/static/app/assets/{BrainHome-Qm8eaztx.js → BrainHome-CFBkt1K_.js} +1 -1
  99. package/static/app/assets/{BrainSignals-DS9BtKOW.js → BrainSignals-ReLWF2H8.js} +1 -1
  100. package/static/app/assets/Capture-BsTokYkk.js +1 -0
  101. package/static/app/assets/{Chronicle-BGvuAchH.js → Chronicle-B6f0T9id.js} +1 -1
  102. package/static/app/assets/{CommandPalette-Bqhm0Urn.js → CommandPalette-CuvjTv1u.js} +1 -1
  103. package/static/app/assets/{Library-BV6NnF0a.js → Library-BGJbG9Hd.js} +1 -1
  104. package/static/app/assets/{LivingBrain-GzenJchP.js → LivingBrain-DGYK_Jsa.js} +1 -1
  105. package/static/app/assets/{ProductFlow-DEP6-vML.js → ProductFlow-DXBC6brE.js} +1 -1
  106. package/static/app/assets/{ReviewCard-CNZ7XjWG.js → ReviewCard-HXRle3qq.js} +2 -2
  107. package/static/app/assets/System-CMHSO9qM.js +1 -0
  108. package/static/app/assets/arrow-left-BfmkskWx.js +1 -0
  109. package/static/app/assets/{bot-B_K1Tdmw.js → bot-Cn8bWRuq.js} +1 -1
  110. package/static/app/assets/{brain-DWyaV1L1.js → brain-CQJberbE.js} +1 -1
  111. package/static/app/assets/{button-aTn4s84A.js → button-Ct9f2_oT.js} +1 -1
  112. package/static/app/assets/circle-check-DruOxB-4.js +1 -0
  113. package/static/app/assets/{circle-pause-xKgeGXkT.js → circle-pause-CmzC_apg.js} +1 -1
  114. package/static/app/assets/{circle-play-DkT6tYPX.js → circle-play-D8mW2aQ7.js} +1 -1
  115. package/static/app/assets/{cpu-85xYObUC.js → cpu-DZcdd0PZ.js} +1 -1
  116. package/static/app/assets/{download-B5Fm7YXo.js → download-bv1KEPGQ.js} +1 -1
  117. package/static/app/assets/{folder-open-kk2Xa52u.js → folder-open-d-Pip5gr.js} +1 -1
  118. package/static/app/assets/{hard-drive-DkA3zBW_.js → hard-drive-D20iavUb.js} +1 -1
  119. package/static/app/assets/index-D9x-kSNy.css +2 -0
  120. package/static/app/assets/{index-BMPdTmlY.js → index-Do83hDzJ.js} +3 -3
  121. package/static/app/assets/{input-B0nRf2jO.js → input-BLXVNmj1.js} +1 -1
  122. package/static/app/assets/{link-2-Dwb4gnTc.js → link-2-BPJOFlAy.js} +1 -1
  123. package/static/app/assets/{permissionCopy-CQDUBrOZ.js → permissionCopy-ChdJd493.js} +1 -1
  124. package/static/app/assets/primitives-Cv5tbZBY.js +1 -0
  125. package/static/app/assets/search-CT9aho2j.js +1 -0
  126. package/static/app/assets/{share-2-BsrxFglO.js → share-2-YNX_NtMU.js} +1 -1
  127. package/static/app/assets/{shield-alert-5BStfp2_.js → shield-alert-DuQ3zrVL.js} +1 -1
  128. package/static/app/assets/{textarea-Cg8IUA-k.js → textarea-DqwLnli4.js} +1 -1
  129. package/static/app/assets/{useFocusTrap-CYKvE46M.js → useFocusTrap-ZVI98jaW.js} +1 -1
  130. package/static/app/assets/{useMutation-CSn9t1op.js → useMutation-CVC4qv_D.js} +1 -1
  131. package/static/app/assets/{useQuery-CY2OI2uy.js → useQuery-C7BeG4HU.js} +1 -1
  132. package/static/app/assets/{utils-Ddol2RWD.js → utils-CiFtIdZq.js} +1 -1
  133. package/static/app/assets/{workspace-BqDwOz_p.js → workspace-DQz9vIId.js} +1 -1
  134. package/static/app/index.html +4 -4
  135. package/static/sw.js +1 -1
  136. package/lattice_brain/archive.py +0 -522
  137. package/lattice_brain/context.py +0 -325
  138. package/lattice_brain/conversations.py +0 -382
  139. package/lattice_brain/core.py +0 -82
  140. package/lattice_brain/graph/_kg_contract.py +0 -249
  141. package/lattice_brain/graph/curator.py +0 -676
  142. package/lattice_brain/graph/discovery.py +0 -595
  143. package/lattice_brain/graph/discovery_index/__init__.py +0 -35
  144. package/lattice_brain/graph/discovery_index/cleanup.py +0 -182
  145. package/lattice_brain/graph/discovery_index/extract.py +0 -137
  146. package/lattice_brain/graph/discovery_index/scan.py +0 -411
  147. package/lattice_brain/graph/discovery_index/upsert.py +0 -495
  148. package/lattice_brain/graph/documents.py +0 -380
  149. package/lattice_brain/graph/fusion.py +0 -395
  150. package/lattice_brain/graph/identity.py +0 -175
  151. package/lattice_brain/graph/image_vectors.py +0 -230
  152. package/lattice_brain/graph/ingest.py +0 -829
  153. package/lattice_brain/graph/network.py +0 -205
  154. package/lattice_brain/graph/proactive.py +0 -724
  155. package/lattice_brain/graph/projection/__init__.py +0 -42
  156. package/lattice_brain/graph/projection/curation.py +0 -500
  157. package/lattice_brain/graph/projection/v2_schema.py +0 -518
  158. package/lattice_brain/graph/provenance.py +0 -524
  159. package/lattice_brain/graph/rerank.py +0 -163
  160. package/lattice_brain/graph/retrieval/__init__.py +0 -54
  161. package/lattice_brain/graph/retrieval/context.py +0 -197
  162. package/lattice_brain/graph/retrieval/graph_view.py +0 -319
  163. package/lattice_brain/graph/retrieval/hybrid.py +0 -488
  164. package/lattice_brain/graph/retrieval/maintenance.py +0 -121
  165. package/lattice_brain/graph/retrieval/signals.py +0 -95
  166. package/lattice_brain/graph/retrieval_docgen.py +0 -253
  167. package/lattice_brain/graph/retrieval_policy.py +0 -180
  168. package/lattice_brain/graph/retrieval_reads.py +0 -769
  169. package/lattice_brain/graph/retrieval_vector/__init__.py +0 -42
  170. package/lattice_brain/graph/retrieval_vector/fingerprint.py +0 -97
  171. package/lattice_brain/graph/retrieval_vector/indexing.py +0 -347
  172. package/lattice_brain/graph/retrieval_vector/search.py +0 -560
  173. package/lattice_brain/graph/retrieval_vector/status.py +0 -374
  174. package/lattice_brain/graph/schema.py +0 -792
  175. package/lattice_brain/graph/store.py +0 -268
  176. package/lattice_brain/graph/vector_index/__init__.py +0 -85
  177. package/lattice_brain/graph/vector_index/base.py +0 -167
  178. package/lattice_brain/graph/vector_index/brute_force.py +0 -110
  179. package/lattice_brain/graph/vector_index/hnsw.py +0 -290
  180. package/lattice_brain/graph/vector_index/jobs.py +0 -287
  181. package/lattice_brain/graph/vector_index/quantized.py +0 -148
  182. package/lattice_brain/graph/vector_index/selector.py +0 -161
  183. package/lattice_brain/graph/write_master.py +0 -308
  184. package/lattice_brain/ingestion/_contract.py +0 -90
  185. package/lattice_brain/ingestion/folder_scan.py +0 -57
  186. package/lattice_brain/ingestion/folders.py +0 -258
  187. package/lattice_brain/ingestion/jobs_api.py +0 -107
  188. package/lattice_brain/ingestion/routing.py +0 -295
  189. package/lattice_brain/ingestion_jobs.py +0 -380
  190. package/lattice_brain/memory.py +0 -75
  191. package/lattice_brain/portability/__init__.py +0 -90
  192. package/lattice_brain/portability/_contract.py +0 -42
  193. package/lattice_brain/portability/backups.py +0 -338
  194. package/lattice_brain/portability/bundles.py +0 -136
  195. package/lattice_brain/portability/constants.py +0 -93
  196. package/lattice_brain/portability/fsops.py +0 -138
  197. package/lattice_brain/portability/service.py +0 -41
  198. package/lattice_brain/portability/sharing.py +0 -710
  199. package/lattice_brain/quality.py +0 -543
  200. package/lattice_brain/retrieval_benchmark_fixtures.py +0 -92
  201. package/lattice_brain/runtime/agent_runtime.py +0 -859
  202. package/lattice_brain/runtime/contracts.py +0 -460
  203. package/lattice_brain/runtime/multi_agent.py +0 -942
  204. package/lattice_brain/runtime/statuses.py +0 -10
  205. package/lattice_brain/sealed_box.py +0 -240
  206. package/lattice_brain/self_model.py +0 -675
  207. package/lattice_brain/sensitivity.py +0 -94
  208. package/lattice_brain/storage/__init__.py +0 -22
  209. package/lattice_brain/storage/base.py +0 -100
  210. package/lattice_brain/storage/docker.py +0 -105
  211. package/lattice_brain/storage/factory.py +0 -31
  212. package/lattice_brain/storage/migration.py +0 -191
  213. package/lattice_brain/storage/postgres.py +0 -123
  214. package/lattice_brain/storage/sqlite.py +0 -143
  215. package/lattice_brain/synthesis.py +0 -824
  216. package/lattice_brain/workflow.py +0 -497
  217. package/latticeai/api/admin.py +0 -471
  218. package/latticeai/api/agent_registry.py +0 -105
  219. package/latticeai/api/agents.py +0 -228
  220. package/latticeai/api/auth.py +0 -383
  221. package/latticeai/api/automation_intelligence.py +0 -401
  222. package/latticeai/api/brain_intelligence.py +0 -199
  223. package/latticeai/api/browser.py +0 -493
  224. package/latticeai/api/change_proposals.py +0 -89
  225. package/latticeai/api/chat.py +0 -572
  226. package/latticeai/api/chat_agent_http.py +0 -892
  227. package/latticeai/api/chat_contracts.py +0 -73
  228. package/latticeai/api/chat_documents.py +0 -276
  229. package/latticeai/api/chat_helpers.py +0 -460
  230. package/latticeai/api/chat_history.py +0 -101
  231. package/latticeai/api/chat_hybrid.py +0 -113
  232. package/latticeai/api/chat_intents.py +0 -646
  233. package/latticeai/api/chat_stream.py +0 -216
  234. package/latticeai/api/chronicle.py +0 -63
  235. package/latticeai/api/command_center.py +0 -51
  236. package/latticeai/api/computer_use.py +0 -474
  237. package/latticeai/api/evidence_actions.py +0 -48
  238. package/latticeai/api/features.py +0 -70
  239. package/latticeai/api/funnel_metrics.py +0 -31
  240. package/latticeai/api/garden.py +0 -34
  241. package/latticeai/api/hooks.py +0 -165
  242. package/latticeai/api/index_jobs.py +0 -145
  243. package/latticeai/api/invitations.py +0 -100
  244. package/latticeai/api/knowledge_graph.py +0 -536
  245. package/latticeai/api/marketplace.py +0 -105
  246. package/latticeai/api/mcp.py +0 -482
  247. package/latticeai/api/memory.py +0 -270
  248. package/latticeai/api/network.py +0 -81
  249. package/latticeai/api/network_boundary.py +0 -225
  250. package/latticeai/api/permission_mode.py +0 -61
  251. package/latticeai/api/permissions.py +0 -436
  252. package/latticeai/api/plugins.py +0 -126
  253. package/latticeai/api/portability.py +0 -391
  254. package/latticeai/api/project_sessions.py +0 -114
  255. package/latticeai/api/realtime.py +0 -118
  256. package/latticeai/api/review_queue.py +0 -364
  257. package/latticeai/api/security_dashboard.py +0 -604
  258. package/latticeai/api/setup.py +0 -319
  259. package/latticeai/api/static_routes.py +0 -354
  260. package/latticeai/api/ui_redirects.py +0 -26
  261. package/latticeai/api/workflow_designer.py +0 -394
  262. package/latticeai/api/workspace.py +0 -856
  263. package/latticeai/api/workspace_scope.py +0 -125
  264. package/latticeai/core/agent/__init__.py +0 -93
  265. package/latticeai/core/agent/_contract.py +0 -79
  266. package/latticeai/core/agent/context.py +0 -57
  267. package/latticeai/core/agent/deps.py +0 -125
  268. package/latticeai/core/agent/execution.py +0 -622
  269. package/latticeai/core/agent/planning.py +0 -145
  270. package/latticeai/core/agent/recovery.py +0 -157
  271. package/latticeai/core/agent/runtime.py +0 -210
  272. package/latticeai/core/agent/verification.py +0 -231
  273. package/latticeai/core/agent_eval.py +0 -739
  274. package/latticeai/core/agent_helpers.py +0 -493
  275. package/latticeai/core/agent_profiles.py +0 -110
  276. package/latticeai/core/agent_prompts.py +0 -171
  277. package/latticeai/core/agent_registry.py +0 -232
  278. package/latticeai/core/agent_state.py +0 -41
  279. package/latticeai/core/agent_trace.py +0 -104
  280. package/latticeai/core/artifact_ledger.py +0 -109
  281. package/latticeai/core/audit.py +0 -260
  282. package/latticeai/core/builtin_hooks.py +0 -105
  283. package/latticeai/core/context_builder.py +0 -394
  284. package/latticeai/core/document_generator.py +0 -103
  285. package/latticeai/core/enterprise.py +0 -154
  286. package/latticeai/core/enterprise_admin.py +0 -158
  287. package/latticeai/core/file_generation/__init__.py +0 -115
  288. package/latticeai/core/file_generation/bundles.py +0 -76
  289. package/latticeai/core/file_generation/extraction.py +0 -154
  290. package/latticeai/core/file_generation/inference.py +0 -235
  291. package/latticeai/core/file_generation/orchestration.py +0 -152
  292. package/latticeai/core/file_generation/prompting.py +0 -117
  293. package/latticeai/core/file_generation/repair.py +0 -114
  294. package/latticeai/core/file_generation/sanitize.py +0 -61
  295. package/latticeai/core/file_generation/validation.py +0 -201
  296. package/latticeai/core/invitations.py +0 -132
  297. package/latticeai/core/legacy_compatibility.py +0 -243
  298. package/latticeai/core/logging_safety.py +0 -46
  299. package/latticeai/core/marketplace.py +0 -293
  300. package/latticeai/core/mcp_catalog.py +0 -452
  301. package/latticeai/core/mcp_registry.py +0 -506
  302. package/latticeai/core/network_boundary.py +0 -168
  303. package/latticeai/core/oidc.py +0 -208
  304. package/latticeai/core/plugins.py +0 -432
  305. package/latticeai/core/product_hardening.py +0 -218
  306. package/latticeai/core/project_sessions.py +0 -337
  307. package/latticeai/core/realtime.py +0 -238
  308. package/latticeai/core/run_explain.py +0 -426
  309. package/latticeai/core/run_store.py +0 -252
  310. package/latticeai/core/timezones.py +0 -80
  311. package/latticeai/core/workspace_computer_memory.py +0 -84
  312. package/latticeai/core/workspace_graph_trace.py +0 -155
  313. package/latticeai/core/workspace_indexing.py +0 -102
  314. package/latticeai/core/workspace_memory.py +0 -77
  315. package/latticeai/core/workspace_onboarding.py +0 -104
  316. package/latticeai/core/workspace_os.py +0 -978
  317. package/latticeai/core/workspace_os_constants.py +0 -126
  318. package/latticeai/core/workspace_os_state.py +0 -180
  319. package/latticeai/core/workspace_os_utils.py +0 -103
  320. package/latticeai/core/workspace_permissions.py +0 -101
  321. package/latticeai/core/workspace_plugins.py +0 -97
  322. package/latticeai/core/workspace_relationships.py +0 -99
  323. package/latticeai/core/workspace_reorganization.py +0 -335
  324. package/latticeai/core/workspace_review_items.py +0 -112
  325. package/latticeai/core/workspace_runs.py +0 -726
  326. package/latticeai/core/workspace_skills.py +0 -109
  327. package/latticeai/core/workspace_snapshots.py +0 -198
  328. package/latticeai/core/workspace_timeline.py +0 -110
  329. package/latticeai/integrations/__init__.py +0 -0
  330. package/latticeai/integrations/telegram_bot/__init__.py +0 -123
  331. package/latticeai/integrations/telegram_bot/__main__.py +0 -17
  332. package/latticeai/integrations/telegram_bot/config.py +0 -86
  333. package/latticeai/integrations/telegram_bot/dispatch.py +0 -311
  334. package/latticeai/integrations/telegram_bot/flows.py +0 -478
  335. package/latticeai/integrations/telegram_bot/helpers.py +0 -322
  336. package/latticeai/integrations/telegram_bot/screens.py +0 -394
  337. package/latticeai/runtime/audit_runtime.py +0 -76
  338. package/latticeai/runtime/automation_runtime.py +0 -81
  339. package/latticeai/runtime/chat_wiring.py +0 -141
  340. package/latticeai/runtime/context_runtime.py +0 -66
  341. package/latticeai/runtime/feature_toggle_wiring.py +0 -157
  342. package/latticeai/runtime/history_runtime.py +0 -163
  343. package/latticeai/runtime/history_writer.py +0 -138
  344. package/latticeai/runtime/hooks_runtime.py +0 -77
  345. package/latticeai/runtime/model_wiring.py +0 -68
  346. package/latticeai/runtime/namespace_runtime.py +0 -163
  347. package/latticeai/runtime/network_boundary_wiring.py +0 -117
  348. package/latticeai/runtime/network_config_runtime.py +0 -56
  349. package/latticeai/runtime/permission_mode_wiring.py +0 -112
  350. package/latticeai/runtime/persistence_runtime.py +0 -159
  351. package/latticeai/runtime/platform_runtime_wiring.py +0 -89
  352. package/latticeai/runtime/review_wiring.py +0 -42
  353. package/latticeai/runtime/router_registration.py +0 -693
  354. package/latticeai/runtime/service_singletons.py +0 -55
  355. package/latticeai/runtime/sso_config_runtime.py +0 -128
  356. package/latticeai/runtime/user_key_runtime.py +0 -106
  357. package/latticeai/runtime/web_runtime.py +0 -92
  358. package/latticeai/server_app.py +0 -51
  359. package/latticeai/services/app_context.py +0 -130
  360. package/latticeai/services/automation_execution.py +0 -266
  361. package/latticeai/services/automation_intelligence.py +0 -614
  362. package/latticeai/services/brain_automation.py +0 -191
  363. package/latticeai/services/brain_intelligence/__init__.py +0 -58
  364. package/latticeai/services/brain_intelligence/_contract.py +0 -71
  365. package/latticeai/services/brain_intelligence/consistency.py +0 -193
  366. package/latticeai/services/brain_intelligence/constants.py +0 -47
  367. package/latticeai/services/brain_intelligence/digest.py +0 -258
  368. package/latticeai/services/brain_intelligence/health.py +0 -331
  369. package/latticeai/services/brain_intelligence/proposals.py +0 -259
  370. package/latticeai/services/brain_intelligence/sampling.py +0 -84
  371. package/latticeai/services/brain_intelligence/service.py +0 -48
  372. package/latticeai/services/change_proposals.py +0 -471
  373. package/latticeai/services/chat_service.py +0 -243
  374. package/latticeai/services/chronicle.py +0 -555
  375. package/latticeai/services/cloud_egress_audit.py +0 -85
  376. package/latticeai/services/cloud_extraction.py +0 -129
  377. package/latticeai/services/cloud_streaming.py +0 -268
  378. package/latticeai/services/cloud_token_guard.py +0 -84
  379. package/latticeai/services/command_center.py +0 -548
  380. package/latticeai/services/evidence_actions.py +0 -258
  381. package/latticeai/services/feature_toggles.py +0 -502
  382. package/latticeai/services/folder_watch.py +0 -520
  383. package/latticeai/services/funnel_metrics.py +0 -307
  384. package/latticeai/services/hybrid_chat.py +0 -316
  385. package/latticeai/services/hybrid_context.py +0 -228
  386. package/latticeai/services/hybrid_policy.py +0 -129
  387. package/latticeai/services/interop_bridges.py +0 -978
  388. package/latticeai/services/local_knowledge.py +0 -465
  389. package/latticeai/services/memory_service/__init__.py +0 -52
  390. package/latticeai/services/memory_service/_contract.py +0 -100
  391. package/latticeai/services/memory_service/brief.py +0 -431
  392. package/latticeai/services/memory_service/constants.py +0 -57
  393. package/latticeai/services/memory_service/maintenance.py +0 -138
  394. package/latticeai/services/memory_service/manager.py +0 -186
  395. package/latticeai/services/memory_service/proof.py +0 -136
  396. package/latticeai/services/memory_service/recall.py +0 -225
  397. package/latticeai/services/memory_service/service.py +0 -48
  398. package/latticeai/services/memory_service/stores.py +0 -110
  399. package/latticeai/services/mode_store.py +0 -132
  400. package/latticeai/services/model_recommendation.py +0 -224
  401. package/latticeai/services/model_runtime/cloud.py +0 -87
  402. package/latticeai/services/network_boundary_service.py +0 -117
  403. package/latticeai/services/obsidian_bridge.py +0 -609
  404. package/latticeai/services/openai_compatible_adapter.py +0 -101
  405. package/latticeai/services/permission_mode_service.py +0 -122
  406. package/latticeai/services/platform_runtime.py +0 -366
  407. package/latticeai/services/review_queue.py +0 -380
  408. package/latticeai/services/router_context.py +0 -59
  409. package/latticeai/services/run_executor.py +0 -387
  410. package/latticeai/services/self_model_service.py +0 -171
  411. package/latticeai/services/setup_detection.py +0 -147
  412. package/latticeai/services/triggers.py +0 -378
  413. package/latticeai/services/upload_service.py +0 -172
  414. package/latticeai/services/workspace_service.py +0 -165
  415. package/latticeai/setup/__init__.py +0 -25
  416. package/latticeai/setup/auto_setup.py +0 -846
  417. package/latticeai/setup/demo_corpus.py +0 -98
  418. package/latticeai/setup/wizard/__init__.py +0 -126
  419. package/latticeai/setup/wizard/catalog.py +0 -175
  420. package/latticeai/setup/wizard/detect.py +0 -302
  421. package/latticeai/setup/wizard/install.py +0 -348
  422. package/latticeai/setup/wizard/paths.py +0 -165
  423. package/latticeai/setup/wizard/plans.py +0 -74
  424. package/latticeai/setup/wizard/recommend.py +0 -320
  425. package/scripts/bench_agent_smoke.py +0 -409
  426. package/scripts/bench_models.py +0 -540
  427. package/scripts/bench_vector_index.py +0 -295
  428. package/scripts/funnel_soft_gate.py +0 -192
  429. package/scripts/generate_agent_loop_fixtures.py +0 -994
  430. package/scripts/generate_rust_parity_fixtures.py +0 -908
  431. package/scripts/migrate_brain_storage.py +0 -57
  432. package/scripts/parity_fixture_corpus_context.py +0 -162
  433. package/scripts/parity_fixture_corpus_docgen.py +0 -341
  434. package/scripts/profile_kg.py +0 -355
  435. package/server.py +0 -30
  436. package/static/app/assets/AdminConsole-cf4npybT.js +0 -1
  437. package/static/app/assets/Capture-DiQ219jW.js +0 -1
  438. package/static/app/assets/System-CieofHQa.js +0 -1
  439. package/static/app/assets/arrow-left-kfsrk0mv.js +0 -1
  440. package/static/app/assets/circle-check-qqLug9nU.js +0 -1
  441. package/static/app/assets/index-DxmOfNRi.css +0 -2
  442. package/static/app/assets/primitives-SNp0LRJz.js +0 -1
  443. package/static/app/assets/search-BcHqkjoy.js +0 -1
@@ -1,10 +1,14 @@
1
- """Phases 5-8: domain singletons, the web app, services, foundation routes.
1
+ """Phases 5-6 of the AI-Worker build: domain singletons and the web shell.
2
2
 
3
- The middle of the build order. ``phase_domain`` runs before ``phase_web``
4
- because the lifespan, the static status routes and the model runtime service
5
- are all wired against the router it builds; ``phase_services`` runs after
6
- ``phase_web`` because the AppContext carries handles the web phase produces.
7
- Split out of the single ``build_phases`` module in v11.3.0.
3
+ ``phase_domain`` runs before ``phase_web`` because the lifespan and the model
4
+ runtime service are both wired against the router it builds.
5
+
6
+ WP-P1 removed the product half of both phases: the chat service, the garden,
7
+ the telegram mirror, the typed ``AppContext``, the auth/admin/security/static
8
+ routers and the workspace mount all went to ``lattice-host``. What is left is
9
+ the LLM router (the thing this process exists to run), the tool-dispatch
10
+ whitelist, and the FastAPI object with the two middlewares a proxied browser
11
+ write still passes through.
8
12
 
9
13
  Every heavy import lives *inside* a phase, never at module scope.
10
14
  """
@@ -12,25 +16,22 @@ Every heavy import lives *inside* a phase, never at module scope.
12
16
  from __future__ import annotations
13
17
 
14
18
  import logging
15
- from typing import Any, Dict, Optional
19
+ from typing import List
16
20
 
17
21
  from latticeai.runtime.runtime_context import RuntimeContext
18
22
 
19
23
 
20
24
  # ── phase 5: domain singletons (must precede the web app) ────────────────────
21
25
  def phase_domain(ctx: RuntimeContext) -> None:
22
- """The model router, the garden, and the chat service.
26
+ """The model router and the tool-dispatch policy.
23
27
 
24
- Separated from :func:`phase_services` because ``phase_web`` needs the model
25
- router: the lifespan hooks, the static status routes, and the model runtime
26
- service are all wired against it.
28
+ Separated from ``phase_web`` because the lifespan hooks and the model
29
+ runtime service are both wired against the router.
27
30
  """
28
31
  ctx.enter("domain")
29
32
 
30
33
  from lattice_brain.graph.runtime import set_llm_router
31
34
  from latticeai.models.router import LLMRouter
32
- from latticeai.services.chat_service import ChatService
33
- from latticeai.services.p_reinforce import PReinforceGardener
34
35
  from latticeai.services.tool_dispatch import configure_tool_dispatch
35
36
 
36
37
  model_router = LLMRouter()
@@ -38,290 +39,13 @@ def phase_domain(ctx: RuntimeContext) -> None:
38
39
  configure_tool_dispatch(load_users=ctx.load_users, get_user_role=ctx.get_user_role)
39
40
  ctx.set(model_router=model_router)
40
41
 
41
- # v4 garden absorption: the vault is the user-owned markdown mirror and the
42
- # brain is authoritative. Existing notes import idempotently (content-hash
43
- # dedup), and garden context queries the brain rather than rescanning.
44
- gardener = PReinforceGardener(
45
- ingestion_pipeline=ctx.INGESTION_PIPELINE if ctx.ENABLE_GRAPH else None,
46
- knowledge_graph=ctx.KNOWLEDGE_GRAPH,
47
- )
48
- if ctx.ENABLE_GRAPH:
49
- try:
50
- garden_import = gardener.import_vault()
51
- if garden_import.get("failed"):
52
- logging.warning(
53
- "garden vault import: %s notes failed to ingest",
54
- garden_import["failed"],
55
- )
56
- except Exception as exc:
57
- logging.warning("garden vault import skipped: %s", exc)
58
- ctx.set(gardener=gardener)
59
-
60
- # The chat service owns persistence and trace behaviour once its user-key
61
- # dependencies exist.
62
- ctx.set(
63
- CHAT_SERVICE=ChatService(
64
- store=ctx.WORKSPACE_OS,
65
- get_history=ctx.get_history,
66
- save_to_history=ctx.save_to_history,
67
- get_history_user=ctx.get_history_user,
68
- )
69
- )
70
-
71
-
72
- def self_model_port(workspace_graph: Any) -> Any:
73
- """The agent loop's Self-Model port (v11.2.0).
74
-
75
- 11.1.0 built ``executor_prompt_for(self_model_summary=…)`` and had nothing
76
- to pass it; this is what the composition root passes. ``summary_for_prompt``
77
- never raises and answers ``""`` for a Brain that knows nothing about its
78
- owner — which produces exactly the pre-11.2.0 prompt bytes.
79
-
80
- A module-level factory rather than a closure inside ``phase_services``
81
- because a port that cannot be called on its own cannot be tested on its own.
82
- """
83
-
84
- def _summary(*, user_email: Any = None, workspace_id: Any = None) -> str:
85
- from lattice_brain.self_model import summary_for_prompt
86
-
87
- graph = workspace_graph()
88
- if graph is None:
89
- return ""
90
- return summary_for_prompt(graph, workspace_id=workspace_id)
91
-
92
- return _summary
93
-
94
-
95
- # ── phase 6b: retrieval, agent runtime, and the typed AppContext ─────────────
96
- def phase_services(ctx: RuntimeContext) -> None:
97
- """Retrieval/context assembly, the chat agent runtime, and the AppContext.
98
-
99
- Runs after ``phase_web`` because the AppContext carries handles the web
100
- phase produces (``ui_file_response``, ``local_sysinfo``, ``graph_stats``)
101
- and the telegram mirror needs the lifespan's ``_spawn``.
102
- """
103
- ctx.enter("services")
104
-
105
- from latticeai.api.chat import build_recent_chat_context
106
- from latticeai.core.enterprise import capability_registry
107
- from latticeai.core.mcp_registry import (
108
- SKILLS_DIR,
109
- _fetch_skills_marketplace,
110
- install_skill,
111
- )
112
- from latticeai.core.workspace_os import remove_skill_directory
113
- from latticeai.runtime.chat_wiring import (
114
- build_chat_agent_runtime_from_context,
115
- maybe_build_telegram_chat_mirror,
116
- )
117
- from latticeai.runtime.context_runtime import build_context_runtime
118
- from latticeai.services.app_context import AppContext
119
- from latticeai.services.tool_dispatch import build_agent_runtime
120
- from latticeai.setup.wizard import get_recommendations, scan_environment
121
- from latticeai.tools import execute_tool, knowledge_save
122
-
123
- gardener = ctx.gardener
124
- model_router = ctx.model_router
125
-
126
- def _workspace_settings_payload() -> Dict:
127
- return {
128
- "mode": ctx.APP_MODE,
129
- "host": ctx.DEFAULT_HOST,
130
- "port": ctx.DEFAULT_PORT,
131
- "require_auth": ctx.REQUIRE_AUTH,
132
- "enable_graph": ctx.ENABLE_GRAPH,
133
- "allow_local_models": ctx.ALLOW_LOCAL_MODELS,
134
- "static_dir": str(ctx.STATIC_DIR),
135
- "data_dir": str(ctx.DATA_DIR),
136
- }
137
-
138
- def _workspace_models_payload() -> Dict:
139
- return {
140
- "current_model": ctx.model_router.current_model_id,
141
- "loaded_models": ctx.model_router.loaded_model_ids,
142
- "public_model": ctx.PUBLIC_MODEL,
143
- "local_model": ctx.LOCAL_MODEL,
144
- "local_draft_model": ctx.LOCAL_DRAFT_MODEL,
145
- }
146
-
147
- def _embedding_info() -> dict:
148
- from latticeai.core.embedding_providers import (
149
- PROVIDER_TYPES,
150
- embedding_provider_profiles,
151
- )
152
-
153
- info = ctx.EMBEDDER.as_dict()
154
- info["available_providers"] = list(PROVIDER_TYPES)
155
- info["profile"] = ctx.CONFIG.embedding_profile or ""
156
- info["profiles"] = embedding_provider_profiles()
157
- return info
158
-
159
- def _allowed_workspaces_for(user: Any) -> Any:
160
- # No-auth local mode is single-user: no scoping. With auth, reads are
161
- # scoped to the caller's memberships (legacy-global rows need an
162
- # explicit maintenance-only opt-in).
163
- if not ctx.REQUIRE_AUTH or not user:
164
- return None
165
- return ctx.PLATFORM.allowed_scopes(user)
166
-
167
- def _recent_chat_context(
168
- limit: int = 10,
169
- include_image_missing_replies: bool = True,
170
- user_email: Optional[str] = None,
171
- conversation_id: Optional[str] = None,
172
- workspace_id: Optional[str] = None,
173
- ) -> str:
174
- return build_recent_chat_context(
175
- get_history=ctx.get_history,
176
- limit=limit,
177
- include_image_missing_replies=include_image_missing_replies,
178
- user_email=user_email,
179
- conversation_id=conversation_id,
180
- workspace_id=workspace_id,
181
- )
182
-
183
- ctx.set(
184
- _workspace_settings_payload=_workspace_settings_payload,
185
- _workspace_models_payload=_workspace_models_payload,
186
- _embedding_info=_embedding_info,
187
- _allowed_workspaces_for=_allowed_workspaces_for,
188
- _recent_chat_context=_recent_chat_context,
189
- )
190
-
191
- context_runtime = build_context_runtime(
192
- graph_store=ctx._workspace_graph(),
193
- ingestion_pipeline=ctx.INGESTION_PIPELINE,
194
- memory_service=ctx.MEMORY_SERVICE,
195
- gardener=gardener,
196
- require_auth=ctx.REQUIRE_AUTH,
197
- allowed_scopes_for_user=lambda user_email: ctx.PLATFORM.allowed_scopes(
198
- user_email
199
- ),
200
- )
201
- ctx.adopt(
202
- context_runtime,
203
- "SEARCH_SERVICE",
204
- "BRAIN_MEMORY",
205
- "CONTEXT_ASSEMBLER",
206
- "ARTIFACT_LEDGER",
207
- "_scoped_hybrid_search",
208
- )
209
-
210
- # Telegram chat mirror: registered only when ENABLE_TELEGRAM is truthy, so
211
- # latticeai.api.chat never imports the 45KB telegram module.
212
- ctx.set(
213
- on_chat_message=maybe_build_telegram_chat_mirror(
214
- enable_telegram=ctx.ENABLE_TELEGRAM,
215
- spawn=ctx._spawn,
216
- )
217
- )
218
-
219
- ctx.set(
220
- CHAT_AGENT_RUNTIME=build_chat_agent_runtime_from_context(
221
- build_agent_runtime=build_agent_runtime,
222
- model_router=model_router,
223
- execute_tool=execute_tool,
224
- recent_chat_context=_recent_chat_context,
225
- clear_history=ctx.clear_history,
226
- knowledge_save=knowledge_save,
227
- audit=ctx.append_audit_event,
228
- hooks=ctx.HOOKS_REGISTRY,
229
- brain_memory=ctx.BRAIN_MEMORY,
230
- self_model_summary=self_model_port(
231
- lambda: ctx.KNOWLEDGE_GRAPH if ctx.ENABLE_GRAPH else None
232
- ),
233
- )
234
- )
235
-
236
- # One typed context object replaces the historical 25-30-kwarg wiring.
237
- ctx.set(
238
- app_context=AppContext(
239
- config=ctx.CONFIG,
240
- data_dir=ctx.DATA_DIR,
241
- static_dir=ctx.STATIC_DIR,
242
- base_dir=ctx.BASE_DIR,
243
- skills_dir=SKILLS_DIR,
244
- model_router=model_router,
245
- workspace_store=ctx.WORKSPACE_OS,
246
- workspace_service=ctx.WORKSPACE_SERVICE,
247
- knowledge_graph=ctx.KNOWLEDGE_GRAPH,
248
- local_kg_watcher=ctx.LOCAL_KG_WATCHER,
249
- chat_service=ctx.CHAT_SERVICE,
250
- context_assembler=ctx.CONTEXT_ASSEMBLER,
251
- artifact_ledger=ctx.ARTIFACT_LEDGER,
252
- brain_memory=ctx.BRAIN_MEMORY,
253
- ingestion_pipeline=ctx.INGESTION_PIPELINE if ctx.ENABLE_GRAPH else None,
254
- chat_agent_runtime=ctx.CHAT_AGENT_RUNTIME,
255
- gardener=gardener,
256
- hooks=ctx.HOOKS_REGISTRY,
257
- realtime_bus=ctx.REALTIME_BUS,
258
- capability_registry=capability_registry,
259
- require_user=ctx.require_user,
260
- require_admin=ctx.require_admin,
261
- get_current_user=ctx.get_current_user,
262
- load_users=ctx.load_users,
263
- get_user_role=ctx.get_user_role,
264
- enforce_rate_limit=ctx.enforce_rate_limit,
265
- allowed_workspaces_for=ctx._history_allowed_workspaces_for,
266
- append_audit_event=ctx.append_audit_event,
267
- get_audit_log=ctx.get_audit_log,
268
- get_history=ctx.get_history,
269
- get_history_user=ctx.get_history_user,
270
- save_to_history=ctx.save_to_history,
271
- clear_history=ctx.clear_history,
272
- clear_conversation=ctx.clear_conversation,
273
- group_history_conversations=ctx.group_history_conversations,
274
- get_conversation_messages=ctx.get_conversation_messages,
275
- conversation_title=ctx.conversation_title,
276
- enable_graph=ctx.ENABLE_GRAPH,
277
- require_graph=ctx._require_graph,
278
- workspace_graph=ctx._workspace_graph,
279
- graph_stats=ctx._graph_stats_safe,
280
- # Provider, not a value: REVIEW_QUEUE lands two phases later.
281
- review_queue=lambda: ctx.REVIEW_QUEUE,
282
- workspace_models=_workspace_models_payload,
283
- workspace_settings=_workspace_settings_payload,
284
- scan_environment=scan_environment,
285
- local_sysinfo=ctx.local_sysinfo,
286
- get_recommendations=get_recommendations,
287
- fetch_skills_marketplace=_fetch_skills_marketplace,
288
- install_skill=install_skill,
289
- remove_skill_directory=remove_skill_directory,
290
- redact_secret_text=ctx.redact_secret_text,
291
- ui_file_response=ctx.ui_file_response,
292
- public_model=ctx.PUBLIC_MODEL,
293
- local_model=ctx.LOCAL_MODEL or "",
294
- on_chat_message=ctx.on_chat_message,
295
- funnel_metrics=ctx.FUNNEL_METRICS,
296
- )
297
- )
298
- ctx.app.state.context = ctx.app_context
299
-
300
42
 
301
- # ── phase 6: web app and foundation routers ──────────────────────────────────
43
+ # ── phase 6: the web shell ───────────────────────────────────────────────────
302
44
  def phase_web(ctx: RuntimeContext) -> None:
303
- """Lifespan, the FastAPI app, model runtime service, foundation routers."""
45
+ """Lifespan, the FastAPI application object, the model runtime service."""
304
46
  ctx.enter("web")
305
47
 
306
- from latticeai.api.admin import create_admin_router
307
- from latticeai.api.auth import create_auth_router
308
- from latticeai.api.invitations import create_invitations_router
309
- from latticeai.api.security_dashboard import (
310
- create_security_router as _create_security_router,
311
- )
312
- from latticeai.api.static_routes import create_static_routes_router
313
- from latticeai.core.config import default_sso_redirect_uri
314
- from latticeai.core.policy import policy_matrix
315
- from latticeai.core.product_hardening import build_product_hardening_status
316
- from latticeai.core.security import hash_password
317
- from latticeai.core.users import ensure_user_identity
318
48
  from latticeai.runtime.lifespan_runtime import build_lifespan_runtime
319
- from latticeai.runtime.model_wiring import configure_model_runtime_from_context
320
- from latticeai.runtime.router_registration import (
321
- build_auth_admin_security_router_bundle,
322
- build_static_routes_bundle,
323
- )
324
- from latticeai.runtime.web_runtime import build_web_runtime
325
49
  from latticeai.services.model_runtime import (
326
50
  LOCAL_SERVER_PROCESSES,
327
51
  build_model_runtime,
@@ -330,7 +54,6 @@ def phase_web(ctx: RuntimeContext) -> None:
330
54
 
331
55
  lifespan_runtime = build_lifespan_runtime(
332
56
  app_mode=ctx.APP_MODE,
333
- enable_telegram=ctx.ENABLE_TELEGRAM,
334
57
  autoload_models=ctx.AUTOLOAD_MODELS,
335
58
  is_public_mode=ctx.IS_PUBLIC_MODE,
336
59
  public_model=ctx.PUBLIC_MODEL,
@@ -339,36 +62,22 @@ def phase_web(ctx: RuntimeContext) -> None:
339
62
  local_draft_model=ctx.LOCAL_DRAFT_MODEL,
340
63
  model_idle_unload_seconds=ctx.MODEL_IDLE_UNLOAD_SECONDS,
341
64
  model_router=ctx.model_router,
342
- local_kg_watcher=ctx.LOCAL_KG_WATCHER,
343
65
  local_server_processes=LOCAL_SERVER_PROCESSES,
344
66
  logger=logging,
345
67
  )
346
68
  ctx.adopt(lifespan_runtime, "_spawn", "lifespan")
347
69
 
348
- web_runtime = build_web_runtime(
349
- app_mode=ctx.APP_MODE,
350
- app_version=ctx.APP_VERSION,
351
- lifespan=ctx.lifespan,
352
- default_host=ctx.DEFAULT_HOST,
353
- default_port=ctx.DEFAULT_PORT,
354
- cors_extra_origins=ctx.CORS_EXTRA_ORIGINS,
355
- cors_allow_network=ctx.CORS_ALLOW_NETWORK,
356
- static_dir=ctx.STATIC_DIR,
357
- csrf_trusted_origins=ctx.CSRF_TRUSTED_ORIGINS,
358
- )
359
- ctx.adopt(web_runtime, "app")
70
+ ctx.set(app=build_worker_app_shell(ctx))
360
71
  ensure_agent_root()
361
72
 
362
73
  ctx.set(
363
- model_runtime_service=configure_model_runtime_from_context(
364
- build_model_runtime=build_model_runtime,
74
+ model_runtime_service=build_model_runtime(
365
75
  router=ctx.model_router,
366
76
  APP_MODE=ctx.APP_MODE,
367
77
  DEFAULT_HOST=ctx.DEFAULT_HOST,
368
78
  DEFAULT_PORT=ctx.DEFAULT_PORT,
369
79
  DATA_DIR=ctx.DATA_DIR,
370
80
  BASE_DIR=ctx.BASE_DIR,
371
- ENABLE_TELEGRAM=ctx.ENABLE_TELEGRAM,
372
81
  ENABLE_GRAPH=ctx.ENABLE_GRAPH,
373
82
  AUTOLOAD_MODELS=ctx.AUTOLOAD_MODELS,
374
83
  MODEL_IDLE_UNLOAD_SECONDS=ctx.MODEL_IDLE_UNLOAD_SECONDS,
@@ -376,7 +85,6 @@ def phase_web(ctx: RuntimeContext) -> None:
376
85
  MODEL_DOWNLOAD_TIMEOUT=ctx.MODEL_DOWNLOAD_TIMEOUT,
377
86
  ALLOW_LOCAL_MODELS=ctx.ALLOW_LOCAL_MODELS,
378
87
  REQUIRE_AUTH=ctx.REQUIRE_AUTH,
379
- INVITE_GATE_ENABLED=ctx.INVITE_GATE_ENABLED,
380
88
  ALLOW_PLAINTEXT_API_KEYS=ctx.ALLOW_PLAINTEXT_API_KEYS,
381
89
  CORS_ALLOW_NETWORK=ctx.CORS_ALLOW_NETWORK,
382
90
  PUBLIC_MODEL=ctx.PUBLIC_MODEL,
@@ -384,111 +92,86 @@ def phase_web(ctx: RuntimeContext) -> None:
384
92
  IS_PUBLIC_MODE=ctx.IS_PUBLIC_MODE,
385
93
  keyring=ctx.keyring,
386
94
  get_current_user=ctx.get_current_user,
387
- get_user_api_key=ctx.get_user_api_key,
388
95
  )
389
96
  )
390
97
 
391
- static_routes_bundle = build_static_routes_bundle(
392
- create_static_routes_router=create_static_routes_router,
393
- static_dir=ctx.STATIC_DIR,
394
- invite_gate_enabled=ctx.INVITE_GATE_ENABLED,
395
- invite_code=ctx.INVITE_CODE,
396
- invite_cookie_secret=ctx.INVITE_COOKIE_SECRET,
397
- secure_cookies=ctx.SECURE_COOKIES,
398
- app_mode=ctx.APP_MODE,
399
- model_router=ctx.model_router,
400
- require_user=ctx.require_user,
401
- )
402
- ctx.adopt(
403
- static_routes_bundle,
404
- "STATIC_ROUTES",
405
- "ui_file_response",
406
- "local_sysinfo",
407
- "invite_authorized",
408
- )
409
98
 
410
- foundation_router_bundle = build_auth_admin_security_router_bundle(
411
- create_auth_router=create_auth_router,
412
- sso_default_redirect_uri=default_sso_redirect_uri(ctx.DEFAULT_PORT),
413
- load_users=ctx.load_users,
414
- save_users=ctx.save_users,
415
- hash_password=hash_password,
416
- verify_and_migrate_password=ctx.verify_and_migrate_password,
417
- create_session=ctx.create_session,
418
- get_session_email=ctx.get_session_email,
419
- invalidate_session=ctx.invalidate_session,
420
- extract_bearer_token=ctx._extract_bearer_token,
421
- get_user_role=ctx.get_user_role,
422
- require_user=ctx.require_user,
423
- check_ip_rate_limit=ctx._check_rate_limit,
424
- client_ip=ctx._client_ip,
425
- get_sso_settings=ctx.get_sso_settings,
426
- get_sso_discovery=ctx._get_sso_discovery,
427
- public_sso_config=ctx.public_sso_config,
428
- open_registration=ctx.OPEN_REGISTRATION,
429
- session_ttl=ctx._SESSION_TTL,
430
- require_auth=ctx.REQUIRE_AUTH,
431
- secure_cookies=ctx.SECURE_COOKIES,
432
- invite_authorized=ctx.invite_authorized,
433
- ensure_identity=ensure_user_identity,
434
- create_admin_router=create_admin_router,
435
- require_admin=ctx.require_admin,
436
- get_history=ctx.get_history,
437
- get_audit_log=ctx.get_audit_log,
438
- audit_file=ctx.AUDIT_FILE,
439
- public_user=ctx.public_user,
440
- load_vpc_config=ctx.load_vpc_config,
441
- save_vpc_config=ctx.save_vpc_config,
442
- build_admin_audit_report=ctx.build_admin_audit_report,
443
- build_sensitivity_report=ctx.build_sensitivity_report,
444
- append_audit_event=ctx.append_audit_event,
445
- save_sso_config=ctx.save_sso_config,
446
- knowledge_graph=ctx.KNOWLEDGE_GRAPH,
447
- enable_graph=ctx.ENABLE_GRAPH,
448
- logger=logging,
449
- invite_code=ctx.INVITE_CODE,
450
- invite_gate_enabled=ctx.INVITE_GATE_ENABLED,
451
- default_port=ctx.DEFAULT_PORT,
452
- policy_matrix=policy_matrix,
453
- build_product_hardening_status=build_product_hardening_status,
454
- config=ctx.CONFIG,
455
- kg_portability=ctx.KG_PORTABILITY,
456
- device_identity=ctx.DEVICE_IDENTITY,
457
- create_invitations_router=create_invitations_router,
458
- invitation_store=ctx.INVITATION_STORE,
459
- workspace_service=ctx.WORKSPACE_SERVICE,
460
- user_id_for_email=ctx.user_id_for_email,
461
- create_security_router=_create_security_router,
462
- classify_sensitive_message=ctx.classify_sensitive_message,
463
- )
464
- ctx.adopt(
465
- foundation_router_bundle,
466
- "auth_router",
467
- "admin_router",
468
- "invitations_router",
469
- "security_router",
470
- "_graph_stats_safe",
471
- "_product_hardening_status",
472
- "_security_audit_events_safe",
473
- "_security_list_uploaded_files",
474
- )
99
+ def build_worker_app_shell(ctx: RuntimeContext):
100
+ """The FastAPI object plus the two middlewares a proxied write still meets.
101
+
102
+ Moved here from ``runtime/web_runtime.py`` (deleted with the router
103
+ registration it existed beside). The static mounts went with it: a worker
104
+ serves no UI, and the worker profile dropped those mounts anyway.
475
105
 
106
+ Both middlewares are load-bearing on a worker, which is not obvious:
476
107
 
477
- def phase_foundation_routes(ctx: RuntimeContext) -> None:
478
- """Mount the foundation routers once the AppContext exists."""
479
- ctx.enter("foundation_routes")
108
+ * **CORS** stays outside the CSRF guard so a rejected request still comes
109
+ back with the headers a browser needs to surface the 403 rather than an
110
+ opaque network error.
111
+ * **The CSRF origin guard** is what makes ``LATTICEAI_CSRF_TRUSTED_ORIGINS``
112
+ load-bearing for the gateway (v11.6.0 gateway integration §3): a proxied
113
+ browser write — ``POST /models/load``, ``POST /engines/pull-model``,
114
+ ``POST /tools/read_document`` — arrives carrying the browser's session
115
+ cookie *and* ``Origin: …:{gateway port}``, and without the host's
116
+ injected trust list this guard would answer 403.
117
+ """
118
+ from fastapi import FastAPI
480
119
 
481
- from latticeai.api.workspace import create_workspace_router
482
- from latticeai.runtime.router_registration import register_foundation_routers
120
+ from latticeai.core.csrf import CSRFOriginGuardMiddleware, CSRFOriginPolicy
121
+ from latticeai.core.security import host_is_loopback
483
122
 
484
- register_foundation_routers(
485
- ctx.app,
486
- static_router=ctx.STATIC_ROUTES.router,
487
- auth_router=ctx.auth_router,
488
- admin_router=ctx.admin_router,
489
- invitations_router=ctx.invitations_router,
490
- security_router=ctx.security_router,
491
- create_workspace_router=create_workspace_router,
492
- context=ctx.app_context,
123
+ app = FastAPI(
124
+ title=f"Lattice AI Server ({ctx.APP_MODE})",
125
+ version=ctx.APP_VERSION,
126
+ lifespan=ctx.lifespan,
493
127
  )
494
128
 
129
+ cors_allowed_origins = [
130
+ f"http://localhost:{ctx.DEFAULT_PORT}",
131
+ f"http://127.0.0.1:{ctx.DEFAULT_PORT}",
132
+ *ctx.CORS_EXTRA_ORIGINS,
133
+ ]
134
+ if ctx.CORS_ALLOW_NETWORK:
135
+ cors_allowed_origins = cors_allowed_origins + [
136
+ f"http://{ctx.DEFAULT_HOST}:{ctx.DEFAULT_PORT}",
137
+ f"https://{ctx.DEFAULT_HOST}:{ctx.DEFAULT_PORT}",
138
+ ]
139
+
140
+ # An origin that CORS already lets send *credentialed* cross-origin
141
+ # requests is, by that decision, trusted with the session cookie; listing
142
+ # it again here would be a second place to forget. The explicit
143
+ # LATTICEAI_CSRF_TRUSTED_ORIGINS entries are for the reverse-proxy case —
144
+ # and, since v11.6.0, for the gateway that fronts this worker.
145
+ csrf_allowed_origins: List[str] = [
146
+ *cors_allowed_origins,
147
+ *ctx.CSRF_TRUSTED_ORIGINS,
148
+ ]
149
+ csrf_policy = CSRFOriginPolicy(
150
+ trusted_origins=csrf_allowed_origins,
151
+ server_host=ctx.DEFAULT_HOST,
152
+ server_port=ctx.DEFAULT_PORT,
153
+ bind_is_loopback=host_is_loopback(ctx.DEFAULT_HOST),
154
+ )
155
+
156
+ # Registration order is stack order in reverse: the LAST middleware added
157
+ # is the OUTERMOST.
158
+ app.add_middleware(CSRFOriginGuardMiddleware, policy=csrf_policy)
159
+ _add_cors(app, cors_allowed_origins)
160
+
161
+ ctx.set(
162
+ CORS_ALLOWED_ORIGINS=cors_allowed_origins,
163
+ CSRF_ALLOWED_ORIGINS=csrf_allowed_origins,
164
+ )
165
+ return app
166
+
167
+
168
+ def _add_cors(app, origins: List[str]) -> None:
169
+ from fastapi.middleware.cors import CORSMiddleware
170
+
171
+ app.add_middleware(
172
+ CORSMiddleware,
173
+ allow_origins=origins,
174
+ allow_methods=["*"],
175
+ allow_headers=["*"],
176
+ allow_credentials=True,
177
+ )