@hybridlabor-api/aos 4.4.1 → 4.4.2-beta.1

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 (305) hide show
  1. package/.agents/skills/firecrawl/SKILL.md +149 -0
  2. package/.agents/skills/firecrawl/rules/install.md +82 -0
  3. package/.agents/skills/firecrawl/rules/security.md +26 -0
  4. package/.agents/skills/firecrawl-agent/SKILL.md +58 -0
  5. package/.agents/skills/firecrawl-build/SKILL.md +39 -0
  6. package/.agents/skills/firecrawl-build-interact/SKILL.md +68 -0
  7. package/.agents/skills/firecrawl-build-onboarding/SKILL.md +103 -0
  8. package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
  9. package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
  10. package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
  11. package/.agents/skills/firecrawl-build-scrape/SKILL.md +69 -0
  12. package/.agents/skills/firecrawl-build-search/SKILL.md +69 -0
  13. package/.agents/skills/firecrawl-crawl/SKILL.md +59 -0
  14. package/.agents/skills/firecrawl-download/SKILL.md +70 -0
  15. package/.agents/skills/firecrawl-interact/SKILL.md +84 -0
  16. package/.agents/skills/firecrawl-map/SKILL.md +51 -0
  17. package/.agents/skills/firecrawl-scrape/SKILL.md +69 -0
  18. package/.agents/skills/firecrawl-search/SKILL.md +60 -0
  19. package/CLAUDE.md +573 -0
  20. package/README.de.md +0 -8
  21. package/README.md +0 -8
  22. package/README.pt.md +0 -8
  23. package/assets/brand/ao-ant-mark.svg +91 -0
  24. package/assets/brand/bdb-core-mark.svg +34 -0
  25. package/assets/brand/heimdall-guardian-mark.svg +16 -0
  26. package/assets/brand/memb-crystal-mark.svg +18 -0
  27. package/bin/aos-config.mjs +89 -0
  28. package/bin/aos-dashboard.mjs +608 -0
  29. package/bin/aos-uninstall.mjs +227 -0
  30. package/docs/sessions/audit-2026-09-14-silent-failures.md +114 -0
  31. package/docs/skills_table.md +0 -3
  32. package/installer.js +471 -237
  33. package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +10 -0
  34. package/mcps/after-effects-mcp/build/index.js +840 -0
  35. package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +153 -0
  36. package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +218 -0
  37. package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +71 -0
  38. package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +147 -0
  39. package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +114 -0
  40. package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +115 -0
  41. package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +192 -0
  42. package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +90 -0
  43. package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +50 -0
  44. package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +1773 -0
  45. package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +160 -0
  46. package/mcps/computer-use-mcp/dist/client.d.ts +150 -0
  47. package/mcps/computer-use-mcp/dist/client.js +136 -0
  48. package/mcps/computer-use-mcp/dist/entrypoint.d.ts +16 -0
  49. package/mcps/computer-use-mcp/dist/entrypoint.js +26 -0
  50. package/mcps/computer-use-mcp/dist/native.d.ts +212 -0
  51. package/mcps/computer-use-mcp/dist/native.js +50 -0
  52. package/mcps/computer-use-mcp/dist/server.d.ts +32 -0
  53. package/mcps/computer-use-mcp/dist/server.js +342 -0
  54. package/mcps/computer-use-mcp/dist/session.d.ts +101 -0
  55. package/mcps/computer-use-mcp/dist/session.js +2372 -0
  56. package/package.json +13 -4
  57. package/skills/global_config/aos-project-init/SKILL.md +97 -130
  58. package/skills/global_config/aos-project-init/assets/openwikiignore.template +62 -0
  59. package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +38 -1
  60. package/skills/global_config/aos-setup/SKILL.md +98 -8
  61. package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +21 -2
  62. package/skills/global_config/ask-tim/SKILL.md +2 -7
  63. package/skills/global_config/openwiki-skill/scripts/openwiki_daemon.py +65 -12
  64. package/bin/setup-saas.mjs +0 -792
  65. package/mcps/blender-mcp-server/.dockerignore +0 -19
  66. package/mcps/blender-mcp-server/.github/workflows/ci.yml +0 -67
  67. package/mcps/blender-mcp-server/.github/workflows/publish-pypi.yml +0 -54
  68. package/mcps/blender-mcp-server/CHANGELOG.md +0 -64
  69. package/mcps/blender-mcp-server/CONTRIBUTING.md +0 -107
  70. package/mcps/blender-mcp-server/Dockerfile +0 -19
  71. package/mcps/blender-mcp-server/LICENSE +0 -21
  72. package/mcps/blender-mcp-server/README.md +0 -409
  73. package/mcps/blender-mcp-server/addon/__init__.py +0 -1440
  74. package/mcps/blender-mcp-server/addon/models.py +0 -223
  75. package/mcps/blender-mcp-server/pyproject.toml +0 -120
  76. package/mcps/blender-mcp-server/scripts/blender_bridge_request.py +0 -71
  77. package/mcps/blender-mcp-server/scripts/blender_create_test_cube.py +0 -49
  78. package/mcps/blender-mcp-server/scripts/blender_scene_info.py +0 -38
  79. package/mcps/blender-mcp-server/scripts/build_addon_zip.sh +0 -29
  80. package/mcps/blender-mcp-server/scripts/demos/README.md +0 -186
  81. package/mcps/blender-mcp-server/scripts/demos/dam_break_scene.py +0 -276
  82. package/mcps/blender-mcp-server/scripts/demos/open_dam_break_gui.py +0 -33
  83. package/mcps/blender-mcp-server/scripts/demos/pipe_movement_study.py +0 -518
  84. package/mcps/blender-mcp-server/scripts/demos/pipe_pressure_failure_scene.py +0 -806
  85. package/mcps/blender-mcp-server/scripts/demos/procedural_dam_break_scene.py +0 -600
  86. package/mcps/blender-mcp-server/scripts/demos/run_dam_break.py +0 -510
  87. package/mcps/blender-mcp-server/scripts/launch_blender_gui.py +0 -41
  88. package/mcps/blender-mcp-server/scripts/library/README.md +0 -64
  89. package/mcps/blender-mcp-server/scripts/library/apply_transforms.py +0 -46
  90. package/mcps/blender-mcp-server/scripts/library/camera.py +0 -51
  91. package/mcps/blender-mcp-server/scripts/library/collections.py +0 -65
  92. package/mcps/blender-mcp-server/scripts/library/create_mesh.py +0 -41
  93. package/mcps/blender-mcp-server/scripts/library/effector.py +0 -48
  94. package/mcps/blender-mcp-server/scripts/library/fluid_domain.py +0 -80
  95. package/mcps/blender-mcp-server/scripts/library/fluid_inflow.py +0 -98
  96. package/mcps/blender-mcp-server/scripts/library/frame_range.py +0 -35
  97. package/mcps/blender-mcp-server/scripts/library/keyframes.py +0 -59
  98. package/mcps/blender-mcp-server/scripts/library/rigid_body.py +0 -52
  99. package/mcps/blender-mcp-server/scripts/library/save_blend.py +0 -40
  100. package/mcps/blender-mcp-server/scripts/server_start.sh +0 -26
  101. package/mcps/blender-mcp-server/src/blender_mcp_server/__init__.py +0 -3
  102. package/mcps/blender-mcp-server/src/blender_mcp_server/headless.py +0 -330
  103. package/mcps/blender-mcp-server/src/blender_mcp_server/server.py +0 -606
  104. package/mcps/davinci-mcp-professional/.bandit +0 -35
  105. package/mcps/davinci-mcp-professional/.claude/commands/security-review.md +0 -191
  106. package/mcps/davinci-mcp-professional/.claude/settings.json +0 -1
  107. package/mcps/davinci-mcp-professional/.editorconfig +0 -27
  108. package/mcps/davinci-mcp-professional/.gitattributes +0 -207
  109. package/mcps/davinci-mcp-professional/.github/CODEOWNERS +0 -2
  110. package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
  111. package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
  112. package/mcps/davinci-mcp-professional/.github/PULL_REQUEST_TEMPLATE.md +0 -20
  113. package/mcps/davinci-mcp-professional/.github/SECURITY.md +0 -97
  114. package/mcps/davinci-mcp-professional/.github/dependabot.yml +0 -27
  115. package/mcps/davinci-mcp-professional/.github/workflows/ci.yml +0 -39
  116. package/mcps/davinci-mcp-professional/ATTRIBUTION.md +0 -4
  117. package/mcps/davinci-mcp-professional/AUTHORS.md +0 -9
  118. package/mcps/davinci-mcp-professional/BUGS.md +0 -55
  119. package/mcps/davinci-mcp-professional/CLAUDE.md +0 -229
  120. package/mcps/davinci-mcp-professional/CONTRIBUTING.md +0 -51
  121. package/mcps/davinci-mcp-professional/COPYING.md +0 -228
  122. package/mcps/davinci-mcp-professional/Doxyfile +0 -379
  123. package/mcps/davinci-mcp-professional/README.md +0 -143
  124. package/mcps/davinci-mcp-professional/SECURITY.md +0 -40
  125. package/mcps/davinci-mcp-professional/USING.md +0 -301
  126. package/mcps/davinci-mcp-professional/VERSION.md +0 -13
  127. package/mcps/davinci-mcp-professional/build.py +0 -169
  128. package/mcps/davinci-mcp-professional/claude_desktop_config_template.json +0 -11
  129. package/mcps/davinci-mcp-professional/hooks/ci-check.sh +0 -29
  130. package/mcps/davinci-mcp-professional/hooks/pre-push +0 -46
  131. package/mcps/davinci-mcp-professional/main.py +0 -40
  132. package/mcps/davinci-mcp-professional/mcp_server.py +0 -30
  133. package/mcps/davinci-mcp-professional/pyproject.toml +0 -115
  134. package/mcps/davinci-mcp-professional/security_audit.py +0 -379
  135. package/mcps/davinci-mcp-professional/src/davinci_mcp/__init__.py +0 -19
  136. package/mcps/davinci-mcp-professional/src/davinci_mcp/cli.py +0 -138
  137. package/mcps/davinci-mcp-professional/src/davinci_mcp/resolve_client.py +0 -342
  138. package/mcps/davinci-mcp-professional/src/davinci_mcp/resources/__init__.py +0 -60
  139. package/mcps/davinci-mcp-professional/src/davinci_mcp/server.py +0 -185
  140. package/mcps/davinci-mcp-professional/src/davinci_mcp/tools/__init__.py +0 -146
  141. package/mcps/davinci-mcp-professional/src/davinci_mcp/types.py +0 -125
  142. package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/__init__.py +0 -19
  143. package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/platform.py +0 -239
  144. package/mcps/davinci-mcp-professional/test.py +0 -186
  145. package/mcps/davinci-mcp-professional/uv.lock +0 -2073
  146. package/mcps/davinci-resolve-mcp/.claude/skills/media-analysis.md +0 -44
  147. package/mcps/davinci-resolve-mcp/.clinerules +0 -17
  148. package/mcps/davinci-resolve-mcp/.cursorrules +0 -17
  149. package/mcps/davinci-resolve-mcp/.github/copilot-instructions.md +0 -17
  150. package/mcps/davinci-resolve-mcp/.github/workflows/npm-publish.yml +0 -109
  151. package/mcps/davinci-resolve-mcp/.windsurfrules +0 -17
  152. package/mcps/davinci-resolve-mcp/AGENTS.md +0 -114
  153. package/mcps/davinci-resolve-mcp/CHANGELOG.md +0 -2648
  154. package/mcps/davinci-resolve-mcp/CLAUDE.md +0 -15
  155. package/mcps/davinci-resolve-mcp/LICENSE +0 -21
  156. package/mcps/davinci-resolve-mcp/README.md +0 -173
  157. package/mcps/davinci-resolve-mcp/SECURITY.md +0 -53
  158. package/mcps/davinci-resolve-mcp/bin/davinci-resolve-mcp.mjs +0 -450
  159. package/mcps/davinci-resolve-mcp/examples/README.md +0 -53
  160. package/mcps/davinci-resolve-mcp/examples/markers/README.md +0 -81
  161. package/mcps/davinci-resolve-mcp/examples/media/README.md +0 -94
  162. package/mcps/davinci-resolve-mcp/examples/timeline/README.md +0 -98
  163. package/mcps/davinci-resolve-mcp/install.py +0 -1687
  164. package/mcps/davinci-resolve-mcp/package.json +0 -52
  165. package/mcps/davinci-resolve-mcp/release-notes/v2.22.0.md +0 -51
  166. package/mcps/davinci-resolve-mcp/release-notes/v2.23.0.md +0 -51
  167. package/mcps/davinci-resolve-mcp/release-notes/v2.23.1.md +0 -35
  168. package/mcps/davinci-resolve-mcp/release-notes/v2.24.1.md +0 -32
  169. package/mcps/davinci-resolve-mcp/scripts/audit_api_parity.py +0 -275
  170. package/mcps/davinci-resolve-mcp/scripts/audit_readwrite_symmetry.py +0 -80
  171. package/mcps/davinci-resolve-mcp/scripts/doctor.py +0 -227
  172. package/mcps/davinci-resolve-mcp/scripts/gen_api_limitations.py +0 -144
  173. package/mcps/davinci-resolve-mcp/scripts/live_media_analysis_polish_probe.py +0 -65
  174. package/mcps/davinci-resolve-mcp/scripts/measure_bridge_cost.py +0 -65
  175. package/mcps/davinci-resolve-mcp/scripts/regen_panel_screenshots.py +0 -76
  176. package/mcps/davinci-resolve-mcp/src/__init__.py +0 -3
  177. package/mcps/davinci-resolve-mcp/src/analysis_dashboard.py +0 -15505
  178. package/mcps/davinci-resolve-mcp/src/batch_cli.py +0 -540
  179. package/mcps/davinci-resolve-mcp/src/control_panel.py +0 -13
  180. package/mcps/davinci-resolve-mcp/src/granular/__init__.py +0 -17
  181. package/mcps/davinci-resolve-mcp/src/granular/common.py +0 -741
  182. package/mcps/davinci-resolve-mcp/src/granular/folder.py +0 -420
  183. package/mcps/davinci-resolve-mcp/src/granular/gallery.py +0 -306
  184. package/mcps/davinci-resolve-mcp/src/granular/graph.py +0 -309
  185. package/mcps/davinci-resolve-mcp/src/granular/media_pool.py +0 -679
  186. package/mcps/davinci-resolve-mcp/src/granular/media_pool_item.py +0 -1020
  187. package/mcps/davinci-resolve-mcp/src/granular/media_storage.py +0 -179
  188. package/mcps/davinci-resolve-mcp/src/granular/project.py +0 -1654
  189. package/mcps/davinci-resolve-mcp/src/granular/resolve_control.py +0 -538
  190. package/mcps/davinci-resolve-mcp/src/granular/timeline.py +0 -1075
  191. package/mcps/davinci-resolve-mcp/src/granular/timeline_item.py +0 -2251
  192. package/mcps/davinci-resolve-mcp/src/resolve_mcp_server.py +0 -43
  193. package/mcps/davinci-resolve-mcp/src/server.py +0 -24116
  194. package/mcps/davinci-resolve-mcp/src/utils/__init__.py +0 -3
  195. package/mcps/davinci-resolve-mcp/src/utils/actor_identity.py +0 -46
  196. package/mcps/davinci-resolve-mcp/src/utils/analysis_caps.py +0 -678
  197. package/mcps/davinci-resolve-mcp/src/utils/analysis_memory.py +0 -755
  198. package/mcps/davinci-resolve-mcp/src/utils/analysis_runs.py +0 -307
  199. package/mcps/davinci-resolve-mcp/src/utils/analysis_store.py +0 -945
  200. package/mcps/davinci-resolve-mcp/src/utils/api_truth.py +0 -525
  201. package/mcps/davinci-resolve-mcp/src/utils/app_control.py +0 -319
  202. package/mcps/davinci-resolve-mcp/src/utils/audio_fairlight_live_probe.py +0 -263
  203. package/mcps/davinci-resolve-mcp/src/utils/brain_edits.py +0 -387
  204. package/mcps/davinci-resolve-mcp/src/utils/bridge_metrics.py +0 -76
  205. package/mcps/davinci-resolve-mcp/src/utils/cdl.py +0 -20
  206. package/mcps/davinci-resolve-mcp/src/utils/clip_query.py +0 -85
  207. package/mcps/davinci-resolve-mcp/src/utils/cloud_operations.py +0 -192
  208. package/mcps/davinci-resolve-mcp/src/utils/color_grade_live_probe.py +0 -444
  209. package/mcps/davinci-resolve-mcp/src/utils/contracts.py +0 -102
  210. package/mcps/davinci-resolve-mcp/src/utils/cut_ir.py +0 -115
  211. package/mcps/davinci-resolve-mcp/src/utils/dctl_templates.py +0 -368
  212. package/mcps/davinci-resolve-mcp/src/utils/deep_vision.py +0 -643
  213. package/mcps/davinci-resolve-mcp/src/utils/destructive_hook.py +0 -606
  214. package/mcps/davinci-resolve-mcp/src/utils/edit_engine.py +0 -737
  215. package/mcps/davinci-resolve-mcp/src/utils/embeddings.py +0 -922
  216. package/mcps/davinci-resolve-mcp/src/utils/entities.py +0 -579
  217. package/mcps/davinci-resolve-mcp/src/utils/extension_authoring_live_probe.py +0 -292
  218. package/mcps/davinci-resolve-mcp/src/utils/failure_tracker.py +0 -119
  219. package/mcps/davinci-resolve-mcp/src/utils/fuse_templates.py +0 -1968
  220. package/mcps/davinci-resolve-mcp/src/utils/fusion_composition_live_probe.py +0 -284
  221. package/mcps/davinci-resolve-mcp/src/utils/fusion_group_settings.py +0 -334
  222. package/mcps/davinci-resolve-mcp/src/utils/layout_presets.py +0 -333
  223. package/mcps/davinci-resolve-mcp/src/utils/mcp_stdio.py +0 -32
  224. package/mcps/davinci-resolve-mcp/src/utils/mcp_transport.py +0 -128
  225. package/mcps/davinci-resolve-mcp/src/utils/media_analysis.py +0 -7690
  226. package/mcps/davinci-resolve-mcp/src/utils/media_analysis_jobs.py +0 -805
  227. package/mcps/davinci-resolve-mcp/src/utils/media_pool_changes.py +0 -121
  228. package/mcps/davinci-resolve-mcp/src/utils/media_pool_ingest_live_probe.py +0 -592
  229. package/mcps/davinci-resolve-mcp/src/utils/multicam.py +0 -393
  230. package/mcps/davinci-resolve-mcp/src/utils/object_inspection.py +0 -301
  231. package/mcps/davinci-resolve-mcp/src/utils/page_lock.py +0 -75
  232. package/mcps/davinci-resolve-mcp/src/utils/platform.py +0 -157
  233. package/mcps/davinci-resolve-mcp/src/utils/proc.py +0 -26
  234. package/mcps/davinci-resolve-mcp/src/utils/project_cleanup.py +0 -73
  235. package/mcps/davinci-resolve-mcp/src/utils/project_lifecycle_live_probe.py +0 -376
  236. package/mcps/davinci-resolve-mcp/src/utils/project_lint.py +0 -131
  237. package/mcps/davinci-resolve-mcp/src/utils/project_properties.py +0 -601
  238. package/mcps/davinci-resolve-mcp/src/utils/project_spec.py +0 -459
  239. package/mcps/davinci-resolve-mcp/src/utils/readback.py +0 -91
  240. package/mcps/davinci-resolve-mcp/src/utils/render_deliver_live_probe.py +0 -384
  241. package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_governance.py +0 -214
  242. package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_ledger.py +0 -244
  243. package/mcps/davinci-resolve-mcp/src/utils/resolve_busy.py +0 -171
  244. package/mcps/davinci-resolve-mcp/src/utils/resolve_connection.py +0 -77
  245. package/mcps/davinci-resolve-mcp/src/utils/review_annotation_live_probe.py +0 -352
  246. package/mcps/davinci-resolve-mcp/src/utils/script_templates.py +0 -1193
  247. package/mcps/davinci-resolve-mcp/src/utils/shot_relationships.py +0 -544
  248. package/mcps/davinci-resolve-mcp/src/utils/structural_diff.py +0 -175
  249. package/mcps/davinci-resolve-mcp/src/utils/sync_detection.py +0 -889
  250. package/mcps/davinci-resolve-mcp/src/utils/timeline_brain_db.py +0 -826
  251. package/mcps/davinci-resolve-mcp/src/utils/timeline_conform_live_probe.py +0 -280
  252. package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_live_probe.py +0 -1092
  253. package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_probe.py +0 -185
  254. package/mcps/davinci-resolve-mcp/src/utils/timeline_title_text.py +0 -87
  255. package/mcps/davinci-resolve-mcp/src/utils/timeline_versioning.py +0 -730
  256. package/mcps/davinci-resolve-mcp/src/utils/update_check.py +0 -685
  257. package/mcps/vectorworks-mcp/.dockerignore +0 -8
  258. package/mcps/vectorworks-mcp/Dockerfile +0 -28
  259. package/mcps/vectorworks-mcp/README.md +0 -156
  260. package/mcps/vectorworks-mcp/app/__init__.py +0 -2
  261. package/mcps/vectorworks-mcp/app/api.py +0 -52
  262. package/mcps/vectorworks-mcp/app/chunking.py +0 -56
  263. package/mcps/vectorworks-mcp/app/config.py +0 -29
  264. package/mcps/vectorworks-mcp/app/embeddings.py +0 -28
  265. package/mcps/vectorworks-mcp/app/indexer.py +0 -106
  266. package/mcps/vectorworks-mcp/app/main.py +0 -33
  267. package/mcps/vectorworks-mcp/app/mcp_server.py +0 -71
  268. package/mcps/vectorworks-mcp/app/search.py +0 -54
  269. package/mcps/vectorworks-mcp/app/utils.py +0 -14
  270. package/mcps/vectorworks-mcp/data/.gitkeep +0 -1
  271. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_PluginScript.htm +0 -95
  272. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_ScriptEditor.htm +0 -266
  273. package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_Scripting.htm +0 -106
  274. package/mcps/vectorworks-mcp/data/vw-app-help/VW2023_CreatingScriptedPlugins.htm +0 -327
  275. package/mcps/vectorworks-mcp/data/vw-app-help/VW2024_RunningScripts.htm +0 -116
  276. package/mcps/vectorworks-mcp/data/vw-devwiki/VS_Function_Reference_category.html +0 -2129
  277. package/mcps/vectorworks-mcp/data/vw-jp-ref/ObjectsSymbols.html +0 -2035
  278. package/mcps/vectorworks-mcp/data/vw-jp-ref/ScriptFunctionReference.html +0 -29
  279. package/mcps/vectorworks-mcp/design.md +0 -57
  280. package/mcps/vectorworks-mcp/docker-compose.yml +0 -18
  281. package/mcps/vectorworks-mcp/index/.gitkeep +0 -1
  282. package/mcps/vectorworks-mcp/index/meta.jsonl +0 -3956
  283. package/mcps/vectorworks-mcp/index/vw.faiss +0 -0
  284. package/mcps/vectorworks-mcp/requirements.txt +0 -10
  285. package/mcps/vectorworks-mcp/scripts/fetch_docs_minimal.sh +0 -84
  286. package/mcps/vectorworks-mcp/scripts/fetch_github_vectorworks.sh +0 -85
  287. package/mcps/vectorworks-mcp/templates/index.html +0 -40
  288. package/scripts/ecosystem-health-audit.js +0 -257
  289. package/skills/bdb-dev-os-skill/SKILL.md +0 -49
  290. package/skills/bdb-dev-os-skill/package.json +0 -11
  291. package/skills/bdbsaastraining/SKILL.md +0 -316
  292. package/skills/bdbsaastraining/references/exam-pool.md +0 -313
  293. package/skills/bdbsaastraining/references/interaction-modes.md +0 -94
  294. package/skills/bdbsaastraining/references/track-a-ai-agent.md +0 -111
  295. package/skills/bdbsaastraining/references/track-b-wordpress.md +0 -111
  296. package/skills/bdbsaastraining/references/track-c-mailserver.md +0 -107
  297. package/skills/bdbsaastraining/references/track-d-debian.md +0 -109
  298. package/skills/bdbsaastraining/references/track-e-custom.md +0 -83
  299. package/skills/bdbsaastraining/scripts/build_profile.py +0 -529
  300. package/skills/bdbsaastraining/scripts/generate_certificate.py +0 -161
  301. package/skills/bdbsaastraining/scripts/preflight_check.sh +0 -150
  302. package/skills/bdbsaastraining/templates/certificate_template.html +0 -508
  303. package/skills/global_config/bdb-ecosystem-health/SKILL.md +0 -68
  304. package/skills/global_config/bdbsaas-ops/SKILL.md +0 -16
  305. package/skills/global_config/bdbsaashost/SKILL.md +0 -125
@@ -1,316 +0,0 @@
1
- ---
2
- name: bdbsaastraining
3
- description: Use when onboarding or training staff on the BDB SaaS Host Engine. Guides trainees via interactive workloads (WordPress, mail, agents) through SSH 2FA, Incus, and FastMCP guardrails, culminating in a PDF certificate.
4
- category: saas-ops
5
- disable-model-invocation: true
6
- ---
7
-
8
- # 🥋 BDB SaaS Host Universal Administrator Bootcamp (`/bdbsaastraining`)
9
-
10
- Wenn dieser Skill über `/bdbsaastraining` oder eine Aufforderung zum SaaS-Host-Training aufgerufen wird, agierst du als **Lead Technical Tutor & Ausbildungs-Master** für die BDB Multi-Cloud Fleet.
11
-
12
- Der Skill ist **workload-adaptiv**: Station 0 ermittelt, *was* der Trainee tatsächlich auf der Plattform betreiben will. Daraufhin schaltest du genau **eine Trainingsspur (Track)** frei und lädst deren Detaildatei. Alle Tracks teilen dieselbe Struktur, dieselbe Punktzahl und dasselbe Zertifikat.
13
-
14
- ---
15
-
16
- ## Overview
17
- Interactive, workload-adaptive hands-on training skill for the BDB SaaS Host Engine. It guides trainees through practical engineering scenarios to master multi-cloud fleet operations.
18
-
19
- ## When to Use
20
- * **Use when** a new developer, employee, or agent needs onboarding to the BDB fleet.
21
- * **Use when** the `/bdbsaastraining` command is invoked.
22
- * **Do NOT use when** performing actual production changes; this is strictly for training.
23
-
24
- ## Core Process
25
- 1. Run Station 0 to interview the trainee and determine their target workload (e.g., WordPress, mailserver).
26
- 2. Execute the preflight check script to validate CA and SSH setups.
27
- 3. Guide the trainee step-by-step through their specific track without skipping steps.
28
- 4. Administer the final exam and generate a PDF certificate upon passing.
29
-
30
- ## Common Rationalizations
31
- | Rationalization | Reality |
32
- | :--- | :--- |
33
- | "The trainee already knows Docker, so we can skip Incus profile engineering." | Incus has different security paradigms (e.g., unprivileged containers, specific networking); skipping it creates blind spots. |
34
- | "I'll just accept their plain text answer for the exam instead of forcing a multiple-choice selection." | The exam requires strict adherence to multiple-choice formats to maintain grading integrity and track consistency. |
35
- | "The preflight check failed, but I'll let them proceed anyway to save time." | Failing CA/SSH checks means the trainee cannot securely access the cluster, blocking all subsequent hands-on steps. |
36
-
37
- ## Red Flags
38
- * Skipping Station 0 and directly providing SSH commands.
39
- * Giving the trainee the answers to the exam questions rather than letting them solve them.
40
- * Accepting a failed preflight check without enforcing the corresponding fix.
41
-
42
- ## Verification
43
- - [ ] Trainee workload track has been explicitly recorded.
44
- - [ ] Preflight script executed with exit code `0`.
45
- - [ ] Final exam scored with a minimum of 80% passing grade.
46
- - [ ] PDF certificate generated and presented to the trainee.
47
-
48
- ## 🎯 Didaktische Leitphilosophie (gilt in jedem Track)
49
-
50
- 1. **Station 0 ZUERST.** Beginne NIEMALS mit technischen Aufgaben, bevor du nicht (a) Name, LLDAP-Username und AI-Client erfasst und (b) den Ziel-Workload geklärt und einen Track festgelegt hast.
51
- 2. **Station 0.5 (Preflight) vor Station 1.** Lasse den Trainee `scripts/preflight_check.sh` ausführen. Fehlschläge werden zur *Diagnose-Übung mit Fix-Anleitung*, nicht zum stillen Abbruch.
52
- 3. **Hands-On vor Theorie.** Max. 1–2 kurze Absätze Erklärung, dann sofort ein realer Befehl mit den persönlichen Daten des Trainees zum Ausführen im Terminal / MCP-Client.
53
- 4. **Sokratische Validierung.** Warte immer, bis der Trainee den Befehl ausgeführt und den echten Output gepostet hat. Analysiere den *tatsächlichen* Output, nicht den erwarteten.
54
- 5. **Verständnisfragen.** Nach jeder praktischen Übung genau **eine** Multiple-Choice-Frage — im Interaktionsmodus des Clients (siehe `references/interaction-modes.md`). Direktes Feedback mit Begründung.
55
- 6. **State-Block.** Hänge an das Ende **jeder** Antwort den Bootcamp-Status-Block an (Format unten).
56
- 7. **Keine erfundenen Outputs oder Befehle.** Wenn ein realer Befehl anders reagiert als hier beschrieben, sage das offen und behandle die Abweichung als Lernstoff. Bekannte Gateway-Lücken sind in den Track-Dateien markiert.
57
-
58
- ---
59
-
60
- ## 🗣️ Interaktions- & Antwortmodus
61
-
62
- Lies **`references/interaction-modes.md`** und wende den Dual-Mode an:
63
-
64
- - **Claude Code** → nutze das `AskUserQuestion`-Tool für jede Auswahl (Track-Wahl, Sizing, Prüfungsfragen). „Other" (Freitext) ist immer verfügbar.
65
- - **AGY / Cursor / Claude Desktop / OpenCode / anderer Client** → textuelles A/B/C/D-Schema plus `E) etwas anderes → beschreib es`. Normalisiere Fehleingaben (`b.`, „Antwort B", „die zweite") still zur gemeinten Option.
66
-
67
- **Freitext-Regeln:**
68
- - **Station 0, Sizing-Fragen, Zwischenfragen der Stationen:** Freitext ist ausdrücklich *erwünscht* — er ist der Adaptions-Trigger (Track E, Profil-Generierung).
69
- - **Abschlussprüfung (10 Fragen):** Freitext ist *ungültig*. Bittet der Trainee bei einer Prüfungsfrage genau **einmal** um eine Auswahl aus A–D. Bleibt er bei Freitext, ist der Punkt verloren.
70
-
71
- ---
72
-
73
- ## 📋 Station 0 — Onboarding & Workload-Interview
74
-
75
- Begrüße den Trainee und erfasse in dieser Reihenfolge:
76
-
77
- **Teil A — Identität (immer offen/Freitext):**
78
- 1. Vollständiger Name (Vor- und Nachname, für das PDF-Zertifikat).
79
- 2. Zentraler LLDAP-Benutzername aus der Onboarding-E-Mail (z. B. `noah`, `sarah`, `tkd`).
80
- 3. Genutzter AI-Client (Google Antigravity, Cursor, Claude Desktop, Claude Code, OpenCode).
81
- 4. Hinweis: Onboarding-E-Mail bereithalten (CA-Fingerprint, Endpunkte, FastMCP-Token-Handshake).
82
-
83
- **Teil B — Workload (Auswahl + Freitext):**
84
-
85
- > „Was möchtest du auf der BDB SaaS Host Fleet **konkret betreiben**? Danach richte ich dein Training gezielt aus."
86
-
87
- | Option | Track | Ziel-Workload |
88
- | :-- | :-- | :-- |
89
- | **A** | `A` | **AI-Agent Sandbox** — autonome Agenten in isolierter, restricted-shell Umgebung |
90
- | **B** | `B` | **WordPress / Web-App** — öffentlich erreichbare Web-Anwendung hinter Caddy + 2FA |
91
- | **C** | `C` | **Mailserver** — Froxlor/Postfix/Dovecot Stack mit eigener Kundendomain |
92
- | **D** | `D` | **Clean Debian / Datenbank / Worker** — generischer System-Container, selbst konfiguriert |
93
- | **E** (Freitext) | `E` | **Etwas anderes** — Trainee beschreibt den Workload; du leitest Ressourcen, Pakete, Ports und Auth-Bedarf im Interview ab |
94
-
95
- Speichere intern:
96
- - `<TRAINEE_FULL_NAME>`, `<TRAINEE_USER>`, `<CLIENT_NAME>`
97
- - `<TRACK>` ∈ {A, B, C, D, E}
98
- - Bei Track E zusätzlich das Freitext-Rohziel für `scripts/build_profile.py`.
99
-
100
- **Erst wenn Track feststeht:** Lies die zugehörige Datei und folge ihr für die Stationen 2, 3 und 5:
101
-
102
- | Track | Datei |
103
- | :-- | :-- |
104
- | A | `references/track-a-ai-agent.md` |
105
- | B | `references/track-b-wordpress.md` |
106
- | C | `references/track-c-mailserver.md` |
107
- | D | `references/track-d-debian.md` |
108
- | E | `references/track-e-custom.md` |
109
-
110
- ---
111
-
112
- ## 📋 Station 0.5 — Preflight-Check
113
-
114
- Der Trainee führt auf seiner Workstation aus:
115
-
116
- ```bash
117
- bash ~/.agents/skills/bdbsaastraining/scripts/preflight_check.sh <TRAINEE_USER>
118
- ```
119
- *(Pfad an den real installierten Skill-Ort anpassen — Claude Code: `~/.claude/skills/...`, AGY: `~/.gemini/skills/...`.)*
120
-
121
- Das Skript prüft: Step-CA CLI, CA-Bootstrap + Fingerprint-Abgleich, `~/.ssh/config` Fleet-Block, FastMCP-Konfig im Client, Erreichbarkeit von `gateway.<DOMAIN>`.
122
-
123
- **Bei Fehlern:** Behandle jeden fehlgeschlagenen Check als Mini-Übung. Das Skript gibt für jeden Fehler den Fix-Befehl aus (z. B. `step ca bootstrap …`, `npm run setup:workstation`). Der Trainee führt den Fix aus und wiederholt den Check. Kein Fortschritt zu Station 1, solange Step-CA und SSH-Config nicht grün sind.
124
-
125
- **Verständnisfrage 0.5:** Warum bootstrappt `step ca bootstrap` mit einem *Fingerprint* statt blind dem TLS-Zertifikat zu vertrauen?
126
- → Lösung in `references/exam-pool.md` (`Q_PREFLIGHT`).
127
-
128
- ---
129
-
130
- ## 📚 Stationsübersicht
131
-
132
- ```mermaid
133
- flowchart TD
134
- S0["Station 0: Onboarding + Workload-Interview\n→ Track A/B/C/D/E festlegen"]
135
- S05["Station 0.5: Preflight-Check\n(preflight_check.sh, Diagnose-Übungen)"]
136
- S1["Station 1: Zero-Trust SSH 2FA\n(step ssh login, Zertifikats-Inspektion)"]
137
- S1b["Station 1b: Machine Identity (OIDC)\n(RFC 7523 private_key_jwt, Token-Claims & Refresh)"]
138
- S2["Station 2: Incus Profile Engineering\n★ TRACK-SPEZIFISCH: echtes Template inspizieren\n + eigenes Profil bauen (build_profile.py)"]
139
- S3["Station 3: Workload Deployment & Verify\n★ TRACK-SPEZIFISCH: Container starten, Dienst prüfen"]
140
- S4["Station 4: FastMCP Gateway & 4-Augen-Guardrails\n(dein Container, echte Tool-Signaturen, Approval-Dashboard)"]
141
- S5["Station 5: Routing / DNS / Auth\n★ TRACK-SPEZIFISCH: Caddy+CF proxied / DNS-Blueprint / Gateway-Route / keine"]
142
- CERT["🏆 Abschlussprüfung: 6 Kern- + 4 Track-Fragen (≥80%)\n→ PDF-Zertifikat mit Track-Vermerk"]
143
-
144
- S0 --> S05 --> S1 --> S1b --> S2 --> S3 --> S4 --> S5 --> CERT
145
- ```
146
-
147
- ---
148
-
149
- ## 🔹 Station 1 — Zero-Trust SSH 2FA Login & Zertifikats-Inspektion (alle Tracks)
150
-
151
- > Single Source of Truth für alle Auth-Fakten (Human- und Maschinen-Pfad): `~/.claude/skills/bdbsaashost/SKILL.md` §2. Diese Station lehrt den menschlichen SSH-2FA-Pfad praktisch — die Fakten selbst stehen dort, nicht hier.
152
-
153
- **Thema:** Kurzlebige, 2FA-signierte SSH-Zertifikate. Warum keine statischen `id_rsa`-Keys.
154
-
155
- **Hands-On:**
156
- 1. `step ssh login <TRAINEE_USER>` — Browser öffnet sich, Login mit LLDAP-Passwort + WebAuthn/Passkey.
157
- 2. Zertifikat inspizieren:
158
- ```bash
159
- step ssh inspect ~/.step/ssh/id_ecdsa-cert.pub
160
- ```
161
- Trainee liest aus: Gültigkeitsdauer (`Valid: … to …`, ~16 h), Principals (`<TRAINEE_USER>`), CA-Fingerprint.
162
- 3. Verbindung testen — nutze den in der **Onboarding-E-Mail** genannten SSH-Endpunkt (den obfuskierten Hostnamen oder die dort genannte IP; frag den Trainee, wenn nicht klar):
163
- ```bash
164
- ssh <TRAINEE_USER>@<SSH_ENDPOINT> "id && hostname"
165
- ```
166
-
167
- **Wenn `ssh` „no such user" oder Permission denied liefert:** Das ist echt und trackrelevant — der zentrale Unix-Account bzw. der Sudo-Eintrag wird nicht automatisch aus LLDAP erzeugt. Halte fest: der Trainee braucht einen Admin, der `useradd` + den `sudoers.d/ldap-admins`-Eintrag setzt. Notiere das als Blocker und fahre mit Station 2 im MCP-Kontext fort, falls SSH nicht verfügbar ist.
168
-
169
- **Verständnisfrage 1:** `references/exam-pool.md` → `Q_SSH_TTL`.
170
-
171
- ---
172
-
173
- ## 🔹 Station 1b — Machine Identity (OIDC) & Token-Inspektion (alle Tracks)
174
-
175
- > Single Source of Truth für alle Auth-Fakten (Human- und Maschinen-Pfad): `~/.claude/skills/bdbsaashost/SKILL.md` §2. Diese Station lehrt den maschinellen OIDC-Zugangspfad für autonome Agenten — parallel zum menschlichen SSH-2FA-Pfad.
176
-
177
- **Thema:** Asymmetrische Client-Authentifizierung (`private_key_jwt`, RFC 7523), RFC 9068 JWT Profile für OAuth 2.0 Access Tokens und fail-closed Token-Validierung am FastMCP Gateway.
178
-
179
- **Hands-On:**
180
- 1. **Machine Credential im OS Keychain prüfen:**
181
- ```bash
182
- security find-generic-password -s "bdb-saas-host-machine-key" -a "$USER"
183
- ```
184
- Der private RSA-Schlüssel (2048-bit) wird niemals im Klartext in Config-Dateien abgelegt, sondern sicher im macOS Keychain / OS Secret Store verwaltet.
185
- 2. **Client Assertion & Token-Abruf:**
186
- Ein signiertes JWT (Client Assertion, RS256) an Authelias Token-Endpunkt (`https://auth.<DOMAIN>/api/oidc/token`) senden und ein kurzlebiges Access Token abrufen:
187
- ```bash
188
- # Erfolgt im Workflow transparent via bin/setup-workstation.mjs / bin/setup-saas.mjs
189
- # Token enthält Claims: iss, sub (client_id), aud, exp, jti, client_id
190
- ```
191
- 3. **JWT Claims inspizieren:**
192
- Token dekodieren (z. B. via `python3 -m jwt <token>` oder Inspektions-Script):
193
- Trainee prüft: Gültigkeitsdauer (`exp`, 1 Stunde), `client_id` (z. B. `agent-tkd`), kein Admin-Scope.
194
- 4. **Maschinen-API Endpunkt aufrufen:**
195
- ```bash
196
- curl -s -H "Authorization: Bearer <token>" "https://api.<DOMAIN>/tools/incus_manage_instance"
197
- ```
198
- Verifizieren: Autorisierter Zugriff auf Tool-Endpunkte; Zugriff auf `/approvals/list` oder Freigabe-Endpunkte wird strikt mit HTTP 404/401 abgewiesen (M6-Isolationsgrenze).
199
- 5. **Token-Refresh & Revocation:**
200
- Trainee beobachtet: Bei `401 Unauthorized` erneuert der Client das Token einmalig transparent mit einer frischen Assertion. Ein in `queue.db` via `revoked_at` gesperrtes Credential führt sofort zu `invalid_token` (Fail-Closed).
201
-
202
- **Verständnisfrage 1b:** `references/exam-pool.md` → `Q_MACHINE_IDENTITY` & `Q_PRIVATE_KEY_JWT`.
203
-
204
- ---
205
-
206
- ## 🔹 Station 2 — Incus Profile Engineering ★ TRACK-SPEZIFISCH
207
-
208
- **Gemeinsamer Rahmen** (Details je Track in der Track-Datei):
209
-
210
- 1. **Echtes Template inspizieren.** Der Trainee öffnet das reale Profil aus dem Repo (`server-config/templates/incus/profile-*.yaml`) und liest die Struktur: `config.limits.*`, `config.cloud-init.user-data` (#cloud-config), `packages`, `runcmd`, ggf. `write_files`, `devices`.
211
- 2. **Eigenes Profil generieren.** Über das Interview + Generator:
212
- ```bash
213
- python3 ~/.agents/skills/bdbsaastraining/scripts/build_profile.py \
214
- --track <TRACK> --user <TRAINEE_USER> [weitere Interview-Flags]
215
- ```
216
- Das Skript rendert auf Basis des echten Templates ein **valides** Incus-YAML nach `~/profile-<TRACK>-<TRAINEE_USER>.yaml` und zeigt eine Erklärung jeder Zeile. Bei Track E leitet es Ressourcen/Pakete aus dem Freitext ab und warnt bei unplausiblen Werten.
217
- 3. **Profil registrieren & prüfen** (auf dem Server, sofern SSH verfügbar):
218
- ```bash
219
- sudo incus profile create <TRACK>-<TRAINEE_USER>
220
- sudo incus profile edit <TRACK>-<TRAINEE_USER> < ~/profile-<TRACK>-<TRAINEE_USER>.yaml
221
- sudo incus profile show <TRACK>-<TRAINEE_USER>
222
- ```
223
- Hinweis: `incus profile edit` erwartet KEINEN Top-Level `name:` — der Generator lässt ihn weg.
224
-
225
- **Verständnisfrage 2:** Track-Datei nennt die passende `Q_*`-ID (Netzwerk-Bridge, cloud-init, rbash, Quotas — je nach Track).
226
-
227
- ---
228
-
229
- ## 🔹 Station 3 — Workload Deployment & Verify ★ TRACK-SPEZIFISCH
230
-
231
- Gemeinsamer Rahmen:
232
- ```bash
233
- sudo incus launch images:debian/13 c-<TRACK>-<TRAINEE_USER> -p default -p <TRACK>-<TRAINEE_USER>
234
- sudo incus list
235
- sudo incus exec c-<TRACK>-<TRAINEE_USER> -- cloud-init status --wait
236
- ```
237
- Danach führt die Track-Datei durch die *workload-spezifische* Verifikation (Agent-Task / `curl localhost` / `postconf` / `systemctl` …) und die zugehörige Verständnisfrage.
238
-
239
- ---
240
-
241
- ## 🔹 Station 4 — FastMCP Gateway & 4-Augen-Guardrails (alle Tracks)
242
-
243
- > Single Source of Truth für alle Auth-Fakten (Human- und Maschinen-Pfad): `~/.claude/skills/bdbsaashost/SKILL.md` §2 — dort steht auch, ob/wann sich der Maschinen-Pfad ändert (OIDC-Umbau, `production_artifacts/00_execution_plan.md`).
244
-
245
- **Thema:** Steuerung über `https://gateway.<DOMAIN>/sse` und die realen Guardrails.
246
-
247
- **Hands-On:**
248
- 1. **MCP-Anbindung prüfen.** Wie das aktuelle Token erworben wird, steht in `~/.claude/skills/bdbsaashost/SKILL.md` §2 (Single Source of Truth — dieser Fakt ändert sich mit dem OIDC-Umbau, siehe `production_artifacts/00_execution_plan.md`). Das Token liegt clientabhängig in `~/.cursor/mcp.json`, `~/Library/Application Support/Claude/claude_desktop_config.json` oder `~/.gemini/antigravity-cli/mcp/bdb_remoteos_gateway/config.json`.
249
- 2. **Status abfragen:** im Client `remoteos_get_system_status()` aufrufen.
250
- 3. **4-Augen-Queue provozieren** — echte Signatur (Pflichtfeld `reason`, min. 5 Zeichen):
251
- ```
252
- remoteos_manage_instance(
253
- container_name="c-<TRACK>-<TRAINEE_USER>",
254
- action="delete",
255
- reason="Bootcamp Station 4 Guardrail-Demo"
256
- )
257
- ```
258
- 4. **Freigabe.** Die Freigabe läuft über das **Web-Dashboard** `https://gateway.<DOMAIN>/approvals` (Authelia 2FA → Button „Freigeben"). Es gibt **kein MCP-Tool**, das Freigaben tätigen oder listen kann — alle Approval-Tools wurden zur strikten Wahrung der M6-Grenze aus FastMCP entfernt. 4-Augen heißt: ein *anderer* Admin (Owner) gibt frei. Im Solo-Bootcamp beschreibt der Trainee den Ablauf und prüft den Status über das Dashboard oder den Carve-Out-Endpunkt `GET /api/approvals/{request_id}/status`.
259
- 5. **Guardrail-Kontext.** `99-agent-guardrails` gilt für die LDAP-Gruppe `ai_agents`, nicht für menschliche Admins. Für Agenten-Sessions ist der Weg `agent-sudo <command>` mit Auto-Approve für `ls/cat/grep/pwd/whoami` und Queue für alles andere.
260
-
261
- **Verständnisfrage 4:** `references/exam-pool.md` → `Q_GUARDRAIL_SCOPE`.
262
-
263
- > **Architektur-Hinweis (M6-Isolationsgrenze):**
264
- > - Freigaben erfolgen ausschließlich über das Web-Dashboard mit menschlicher 2FA-Session (Authelia). Sämtliche Approval-Tools im MCP-Server wurden aus Sicherheitsgründen planmäßig ausgemustert.
265
-
266
- ---
267
-
268
- ## 🔹 Station 5 — Routing / DNS / Auth ★ TRACK-SPEZIFISCH
269
-
270
- | Track | Station-5-Inhalt |
271
- | :-- | :-- |
272
- | A | Interne Gateway-Route für ein Agenten-Web-UI, `require_auth=True` (Authelia forward_auth) |
273
- | B | Öffentliche Web-Route: Caddy `forward_auth` + Cloudflare A-Record 🟠 **proxied** |
274
- | C | **DNS-Blueprint** für die Kundendomain: A/MX/SPF/DKIM/DMARC, Mail-Records ⚪ **DNS-only** |
275
- | D | Optional: interne Route ohne öffentliche Exposition, oder bewusst *keine* Route (nur `incus proxy` Device) |
276
- | E | Aus dem Interview abgeleitet (web → wie B, mail → wie C, intern → wie D) |
277
-
278
- Details, Befehle und Verständnisfrage stehen in der jeweiligen Track-Datei. Wo `/tools/add_route` nur den Stub zurückgibt, lässt der Trainee sich zusätzlich mit `remoteos_get_dns_blueprint(...)` (funktioniert real) das DNS-Paket generieren bzw. verifiziert die Caddy-Route direkt auf dem Server (`caddy validate`, `curl -I`).
279
-
280
- ---
281
-
282
- ## 🏆 Abschlussprüfung & PDF-Zertifikat
283
-
284
- **10 Fragen: 6 Kernfragen (`CORE_1` … `CORE_6`) + 4 Track-Fragen (`<TRACK>_1` … `<TRACK>_4`)** aus `references/exam-pool.md`.
285
- - Bestehensgrenze: **≥ 80 % (8/10)**.
286
- - Prüfungsmodus: A/B/C/D bzw. `AskUserQuestion` ohne „Other"-Wertung. Freitext → einmalige Bitte um Auswahl, sonst 0 Punkte für die Frage.
287
- - Stelle die Fragen einzeln, mit sofortigem Feedback + Begründung nach jeder Antwort.
288
-
289
- **Bei ≥ 8/10 — Zertifikat erzeugen:**
290
- ```bash
291
- python3 ~/.agents/skills/bdbsaastraining/scripts/generate_certificate.py \
292
- "<TRAINEE_FULL_NAME>" --score <SCORE> --track <TRACK>
293
- ```
294
- Das Skript prüft zuerst die Prerequisites (`uv`/`playwright`/Chromium) und gibt bei Fehlen eine klare Install-Anweisung statt eines Tracebacks. PDF landet unter:
295
- `production_artifacts/certificates/BDB_SaaS_Admin_Certificate_<trainee_user>.pdf`
296
-
297
- Präsentiere das Zertifikat und gratuliere.
298
-
299
- ---
300
-
301
- ## 🔄 State-Management-Engine (an JEDER Antwort)
302
-
303
- ```text
304
- ---
305
- 🎓 BDB SAAS BOOTCAMP STATUS
306
- • Trainee: <Vollständiger Name> (<TRAINEE_USER>)
307
- • Client: <CLIENT_NAME> | Modus: <AskUserQuestion | Text-A/B/C/D>
308
- • Track: <A AI-Agent | B WordPress | C Mailserver | D Clean Debian | E Custom>
309
- • Station: <z. B. Station 2 – Incus Profile Engineering>
310
- • Score: <z. B. 3/3 Zwischenfragen (100%) | Prüfung: –>
311
- • Status: <z. B. Warte auf Output von 'incus profile show'>
312
- • Resume-Token: BDB-TRN-<TRACK>-S<Station>-P<Punkte>-<TRAINEE_USER>
313
- ---
314
- ```
315
-
316
- Bei Wiederaufnahme in einem neuen Chat: Frage nach dem Resume-Token, stelle Track + Station daraus wieder her und lies die passende Track-Datei erneut.
@@ -1,313 +0,0 @@
1
- # Prüfungs- & Fragenpool
2
-
3
- **Wichtig für den Tutor:** Zeige dem Trainee IMMER nur den Fragetext und die Optionen A–D.
4
- Die Zeile `→ Richtig: X` sowie die Begründung sind NUR für dich. Zitiere diese Datei nie wörtlich im Chat.
5
-
6
- Abschlussprüfung = 6 Kernfragen (`CORE_1`–`CORE_6`) + 4 Track-Fragen (`<TRACK>_1`–`<TRACK>_4`). Bestehen ≥ 8/10.
7
-
8
- ---
9
-
10
- ## Stations-Fragen (Zwischenfragen, während der Stationen)
11
-
12
- ### Q_PREFLIGHT — Station 0.5
13
- Warum verlangt `step ca bootstrap` einen `--fingerprint` statt dem TLS-Zertifikat der CA blind zu vertrauen?
14
- - A) Der Fingerprint beschleunigt den TLS-Handshake.
15
- - B) Trust-on-first-use ohne Fingerprint wäre anfällig für einen Man-in-the-Middle beim ersten Kontakt; der Fingerprint pinnt die Root-CA kryptografisch fest.
16
- - C) `step` funktioniert technisch nicht ohne Fingerprint.
17
- - D) Der Fingerprint ist das Passwort des Trainees.
18
-
19
- → Richtig: **B**
20
- Begründung: Der Fingerprint ist ein Out-of-Band-Anker (aus der Onboarding-E-Mail). Ohne ihn müsste der Client dem ersten präsentierten CA-Zertifikat vertrauen — genau das Fenster, das ein MITM ausnutzt.
21
-
22
- ### Q_SSH_TTL — Station 1
23
- Ein Angreifer entwendet 17 Stunden nach dem letzten `step ssh login` die Datei `~/.step/ssh/id_ecdsa` vom Laptop des Trainees. Was passiert beim Login-Versuch?
24
- - A) Dauerhafter SSH-Zugriff.
25
- - B) Der Server lehnt ab: das Step-CA-Zertifikat ist nach ~16 h abgelaufen und lässt sich ohne erneute 2FA nicht verlängern.
26
- - C) Der Server verlangt das Root-Passwort.
27
- - D) Der Angreifer verlängert das Zertifikat lokal mit `step certificate sign`.
28
-
29
- → Richtig: **B**
30
- Begründung: Der private Schlüssel allein nützt nichts — gültig ist nur das *zertifikat*, und dessen TTL ist abgelaufen. Neuausstellung erzwingt Authelia-2FA.
31
-
32
- ### Q_MACHINE_IDENTITY — Station 1b
33
- Warum darf ein OIDC-Maschinen-Token (`client_credentials` / `ai_agents`) niemals die 4-Augen-Freigabe-Prüfung (`_require_admin_identity()`) am FastMCP Gateway erfüllen?
34
- - A) Weil Maschinen-Tokens keine Gültigkeitsdauer haben.
35
- - B) M6-Isolationsgrenze: Maschinen-Identitäten dürfen niemals privilegierte Aktionen selbst genehmigen; die Freigabe erfordert zwingend eine menschliche Authelia-2FA-Session.
36
- - C) Weil Authelia keine JWTs an Maschinen ausstellen kann.
37
- - D) Maschinen-Tokens dürfen nur SSH-Befehle ausführen.
38
-
39
- → Richtig: **B**
40
- Begründung: Die M6-Sicherheitsgrenze trennt strikt Anforderer (Maschine/Agent) von Freigebenden (Mensch mit WebAuthn 2FA). Ein Maschinen-Token an Freigabe-Endpunkten würde das 4-Augen-Prinzip in ein 1-Auge-System korrumpieren.
41
-
42
- ### Q_PRIVATE_KEY_JWT — Station 1b
43
- Welchen Sicherheitsvorteil bietet das RFC 7523 `private_key_jwt`-Verfahren gegenüber einem statischen Shared Secret / API-Key für Machine-to-Machine-Auth?
44
- - A) Das Token ist unbegrenzt gültig.
45
- - B) Asymmetrische Authentifizierung: Das Secret (Private Key) verlässt niemals die lokale Workstation / den OS-Keychain; an den IdP wird nur eine kurzlebige, signierte Client-Assertion übermittelt.
46
- - C) Es spart CPU-Zyklen beim TLS-Handshake.
47
- - D) Der Client benötigt keine Internetverbindung.
48
-
49
- → Richtig: **B**
50
- Begründung: Bei Shared Secrets kennt der Server das Geheimnis im Klartext; ein Leak auf Server- oder Netzwerkebene kompromittiert das Credential. Mit `private_key_jwt` wird der Private Key im lokalen Keychain geschützt und ausschließlich der öffentliche Schlüssel bei Authelia hinterlegt.
51
-
52
- ---
53
-
54
- ## Kernfragen (in JEDER Abschlussprüfung)
55
-
56
- ### CORE_1
57
- Warum werden AI-Agent-Workloads in einem Incus-System-Container statt direkt auf dem Host betrieben?
58
- - A) Der Agent läuft im Container schneller.
59
- - B) Sandbox-Isolation: kein Zugriff auf Host-Dateien (`/etc/shadow`, SSH-Keys, Sockets); CPU/RAM-Quotas verhindern, dass ein Amok-Prozess den Host lahmlegt.
60
- - C) Container brauchen kein Betriebssystem.
61
- - D) Der Agent braucht dann keine Authentifizierung.
62
-
63
- → Richtig: **B**
64
-
65
- ### CORE_2
66
- Wozu dient das Device `eth0` mit `network: incusbr0` in einem Incus-Profil?
67
- - A) Es weist dem Container eine öffentliche statische IPv4 zu.
68
- - B) `incusbr0` ist die interne Linux-Bridge: der Container bekommt eine private IP und wird über NAT sicher mit dem Host verbunden.
69
- - C) Ohne diesen Eintrag bootet Debian 13 nicht.
70
- - D) Es öffnet alle Ports ins Internet.
71
-
72
- → Richtig: **B**
73
- Hinweis: Die mitgelieferten Profile ohne eigenes `devices:` erben `eth0` aus dem `default`-Profil — das Prinzip bleibt identisch.
74
-
75
- ### CORE_3
76
- Der 4-Augen-Guardrail `99-agent-guardrails` blockiert `sudo su`. Für wen gilt das?
77
- - A) Für alle Benutzer des Servers.
78
- - B) Nur für Mitglieder der LDAP-Gruppe `ai_agents`; menschliche Admins (`admins`) haben regulär `sudo`.
79
- - C) Nur für `root`.
80
- - D) Für niemanden, es ist reine Doku.
81
-
82
- → Richtig: **B**
83
- Begründung: Die sudoers-Regeln sind `%ai_agents`-scoped. Menschliche Admins nutzen normales `sudo`, Agenten nutzen `agent-sudo` (Auto-Approve für Read-only, sonst Queue).
84
-
85
- ### CORE_4
86
- Wie erhält ein neuer Entwickler seinen FastMCP-Gateway-Token?
87
- - A) Er steht im Klartext in der Onboarding-E-Mail.
88
- - B) Über den Browser-2FA-Handshake des Workstation-Setups (`setup:workstation` / `setup-saas`): Authelia-Login → Token wird per Loopback an die CLI übergeben und in die Client-Config injiziert.
89
- - C) Er generiert ihn selbst mit `openssl rand`.
90
- - D) Der Admin schickt ihn per Chat.
91
-
92
- → Richtig: **B**
93
-
94
- ### CORE_5
95
- Ein MCP-Aufruf zum Löschen eines Prod-Containers gibt `status: "queued"` zurück. Was ist der korrekte nächste Schritt?
96
- - A) Den Aufruf sofort wiederholen, bis er durchläuft.
97
- - B) Nichts erzwingen — ein zweiter Admin (Owner) gibt die Aktion im Dashboard `gateway.<DOMAIN>/approvals` per 2FA frei; danach führt der Execution-Daemon sie aus.
98
- - C) Auf dem Server `sudo incus delete` ausführen.
99
- - D) Den Gateway-Dienst neu starten.
100
-
101
- → Richtig: **B**
102
- Begründung: 4-Augen = Trennung von Anforderer und Freigeber. Kein Retry, kein Umgehen.
103
-
104
- ### CORE_6
105
- Warum sind Mail-DNS-Records (`service_type="mail"`) in Cloudflare zwingend `⚪ DNS-only` und nicht `🟠 proxied`?
106
- - A) Aus Kostengründen.
107
- - B) Cloudflares HTTP-Proxy terminiert nur Web-Protokolle; SMTP/IMAP/POP3 würden gebrochen. Mail braucht den direkten A/MX-Record auf die echte Server-IP.
108
- - C) Weil Mailserver kein TLS können.
109
- - D) Damit der Server weniger CPU braucht.
110
-
111
- → Richtig: **B**
112
-
113
- ---
114
-
115
- ## Track A — AI-Agent Sandbox
116
-
117
- ### A_1
118
- Das reale Profil `profile-ai-agent.yaml` setzt für den User `agent` die Shell `/bin/rbash`. Was bewirkt das?
119
- - A) Schnelleres Shell-Startup.
120
- - B) Restricted Bash: kein `cd`, keine absoluten Pfade in Kommandos, kein Setzen von `PATH`/`SHELL`, keine Ausgabe-Umlenkung — der Agent bleibt in seinem Arbeitsverzeichnis eingesperrt.
121
- - C) Root-Rechte für den Agenten.
122
- - D) Deaktiviert die Bash-History.
123
-
124
- → Richtig: **B**
125
-
126
- ### A_2
127
- Der Agent im Container läuft in eine Endlosschleife und frisst RAM. Warum bleibt der Netcup-Host stabil?
128
- - A) Incus killt jeden Agenten nach 60 s.
129
- - B) `config.limits.memory` (im echten Profil 2 GiB) begrenzt den Container hart; OOM trifft nur den Container, nicht den Host.
130
- - C) Der Host hat unendlich RAM.
131
- - D) Der Agent hat gar keinen RAM-Zugriff.
132
-
133
- → Richtig: **B**
134
-
135
- ### A_3
136
- Ein Agent (Gruppe `ai_agents`) braucht auf dem Server `systemctl restart caddy`. Was passiert bei `agent-sudo systemctl restart caddy`?
137
- - A) Sofortige Ausführung, weil `systemctl` harmlos ist.
138
- - B) Der Befehl wird als HIGH-Risk klassifiziert und landet in der Approval-Queue; der Owner muss im Dashboard freigeben.
139
- - C) Ablehnung mit „command not found".
140
- - D) Der Agent bekommt eine Root-Shell.
141
-
142
- → Richtig: **B**
143
- Begründung: Auto-Approve gilt nur für `ls/cat/echo/pwd/whoami/grep` ohne Chaining-Operatoren. Alles andere → Queue. (`systemctl reload caddy` wäre über die statische Whitelist erlaubt, `restart` nicht.)
144
-
145
- ### A_4
146
- Warum wird ein neuer Agent-User via `create_lldap_user(..., group="ai_agents", owner="<admin>")` mit gesetztem `owner` angelegt?
147
- - A) `owner` ist nur Kosmetik.
148
- - B) Das Owner-Mapping (`agent_owners`) sorgt dafür, dass SSE-Approval-Pings gezielt beim verantwortlichen Admin landen statt als Broadcast.
149
- - C) Ohne `owner` kann der Agent sich nicht einloggen.
150
- - D) `owner` setzt das Agent-Passwort.
151
-
152
- → Richtig: **B**
153
-
154
- ---
155
-
156
- ## Track B — WordPress / Web-App
157
-
158
- ### B_1
159
- `profile-wordpress.yaml` installiert `nginx`, `mariadb-server`, `redis-server`, `php-fpm`. Wo werden diese Pakete definiert?
160
- - A) In `config.limits`.
161
- - B) Unter `config.cloud-init.user-data` als `#cloud-config` `packages:`-Liste; `runcmd:` legt danach DB + User an.
162
- - C) In einem separaten Dockerfile.
163
- - D) Manuell nach dem ersten Login.
164
-
165
- → Richtig: **B**
166
-
167
- ### B_2
168
- Warum steht der Cloudflare A-Record für `app.<domain>` auf `🟠 proxied`?
169
- - A) Nur so funktioniert HTTPS.
170
- - B) Der Cloudflare-Proxy liefert WAF, DDoS-Schutz und verdeckt die Origin-IP; Web-Traffic (HTTP/S) ist proxy-fähig.
171
- - C) Proxied ist billiger.
172
- - D) Damit SSH auf die Domain geht.
173
-
174
- → Richtig: **B**
175
-
176
- ### B_3
177
- Beim `curl -I https://app-<user>.<domain>` kommt `302 → https://auth.<domain>`. Warum?
178
- - A) Port 8080 ist offline.
179
- - B) `require_auth=True` erzeugt in Caddy einen `forward_auth`-Block gegen Authelia; ohne gültige 2FA-Session wird jeder Request zum SSO-Portal umgeleitet.
180
- - C) Cloudflare sperrt die Domain.
181
- - D) WordPress ist nicht installiert.
182
-
183
- → Richtig: **B**
184
-
185
- ### B_4
186
- Das Profil hat `runcmd: systemctl enable --now ... php8.2-fpm`, aber Debian 13 liefert PHP 8.4. Was ist die Konsequenz und der richtige Umgang?
187
- - A) Alles läuft, `php8.2-fpm` ist ein Alias.
188
- - B) Der `systemctl`-Aufruf schlägt fehl (Unit existiert nicht); im Training ist das eine Diagnose-Übung — im generierten Profil wird der Dienstname parametrisiert bzw. `php*-fpm` per Glob behandelt.
189
- - C) Der Container bootet gar nicht.
190
- - D) PHP muss von Hand aus dem Quellcode gebaut werden.
191
-
192
- → Richtig: **B**
193
- Begründung: Bekannter Bug im mitgelieferten Template. `build_profile.py` ersetzt den harten Versionsstring.
194
-
195
- ---
196
-
197
- ## Track C — Mailserver
198
-
199
- ### C_1
200
- `profile-mailserver-froxlor.yaml` nutzt `write_files:` für `/root/install_froxlor.sh` und ruft es in `runcmd:`. Warum nicht alles direkt in `runcmd`?
201
- - A) `runcmd` erlaubt keine mehrzeiligen Befehle.
202
- - B) `write_files` legt das Skript deterministisch mit Rechten `0755` ab; `runcmd` bleibt kurz und das Installer-Skript ist später erneut ausführbar/auditierbar.
203
- - C) Froxlor verbietet `runcmd`.
204
- - D) Aus Performancegründen.
205
-
206
- → Richtig: **B**
207
-
208
- ### C_2
209
- Welche DNS-Records generiert `remoteos_get_dns_blueprint(domain=..., service_type="mail")` mindestens?
210
- - A) Nur einen A-Record.
211
- - B) A, MX (Prio 10), SPF (`v=spf1 ...`), DKIM (`default._domainkey`), DMARC (`_dmarc`), Autodiscover.
212
- - C) Nur MX und CNAME.
213
- - D) TXT `google-site-verification`.
214
-
215
- → Richtig: **B**
216
-
217
- ### C_3
218
- Warum ist der MX/A-Record des Mailservers in Cloudflare `⚪ DNS-only`?
219
- - A) DNS-only ist schneller.
220
- - B) Der Cloudflare-Proxy kann SMTP/IMAP nicht weiterleiten; nur ein direkter Record auf die echte IP hält den Mailverkehr funktionsfähig.
221
- - C) Mailserver haben kein TLS.
222
- - D) Cloudflare verlangt Bezahlung für Mail-Proxy.
223
-
224
- → Richtig: **B**
225
-
226
- ### C_4
227
- Der Kunde bringt seine eigene Domain mit (BYOD). Was liefert das Training statt eines Cloudflare-API-Aufrufs?
228
- - A) Nichts, BYOD wird nicht unterstützt.
229
- - B) Ein RFC-konformes DNS-Blueprint, das der Kunde bei seinem eigenen DNS-Provider einträgt — die Fleet verwaltet nur ihre eigene Domain (`*.<FLEET_DOMAIN>`) per API.
230
- - C) Der Kunde muss die Domain zu Cloudflare transferieren.
231
- - D) Ein Zonefile-Download für BIND.
232
-
233
- → Richtig: **B**
234
-
235
- ---
236
-
237
- ## Track D — Clean Debian / Datenbank / Worker
238
-
239
- ### D_1
240
- Es gibt kein mitgeliefertes `profile-debian-clean.yaml`. Was lernst du in Station 2 stattdessen?
241
- - A) Dass Clean-Debian unmöglich ist.
242
- - B) Ein minimales Profil von Grund auf zu schreiben: `config.limits.cpu/memory`, ein schlankes `cloud-init.user-data` (nur die wirklich nötigen Pakete), optional ein `devices:`-Block.
243
- - C) Ein fertiges Image von Docker Hub zu ziehen.
244
- - D) Den Host direkt zu nutzen.
245
-
246
- → Richtig: **B**
247
-
248
- ### D_2
249
- Du betreibst eine PostgreSQL-Instanz im Container. Wie sicherst du sie konsistent vor einem Umzug?
250
- - A) `cp -r` des Datenverzeichnisses im laufenden Betrieb.
251
- - B) `incus snapshot create <ct> <name>` (Copy-on-Write) bzw. Container stoppen + `incus export`; für Live-Migration `incus copy <ct> <node>:<ct> --mode=push --refresh`.
252
- - C) Screenshot des `psql`-Prompts.
253
- - D) Gar nicht, Container sind unsterblich.
254
-
255
- → Richtig: **B**
256
-
257
- ### D_3
258
- Warum bekommt ein reiner Datenbank-Container in Station 5 bewusst *keine* öffentliche Caddy-Route?
259
- - A) Caddy kann kein TCP.
260
- - B) Die DB soll nur intern über `incusbr0` bzw. ein `incus proxy`-Device für die App erreichbar sein — Port 5432 gehört niemals ins öffentliche Internet.
261
- - C) Routen kosten extra.
262
- - D) PostgreSQL bringt einen eigenen Reverse-Proxy mit.
263
-
264
- → Richtig: **B**
265
-
266
- ### D_4
267
- Wie begrenzt du, dass der Worker-Container bei Lastspitzen den Host-Prozessor monopolisiert?
268
- - A) `nice` im Startskript.
269
- - B) `config.limits.cpu` (Kernanzahl) und `limits.cpu.allowance` (z. B. `50%`) im Profil — harte, vom Host durchgesetzte Grenzen.
270
- - C) Den Container manuell pausieren.
271
- - D) Gar nicht möglich.
272
-
273
- → Richtig: **B**
274
-
275
- ---
276
-
277
- ## Track E — Custom Workload
278
-
279
- ### E_1
280
- Du hast deinen Workload frei beschrieben. Woraus leitet `build_profile.py` das Profil ab?
281
- - A) Es rät zufällig.
282
- - B) Aus deinen Interview-Antworten (Basis-Muster web/mail/intern, CPU/RAM/Disk, Pakete, Ports, Auth-Bedarf) und dem am besten passenden mitgelieferten Template als Ausgangsbasis.
283
- - C) Es kopiert immer `profile-ai-agent.yaml`.
284
- - D) Es fragt ein LLM online.
285
-
286
- → Richtig: **B**
287
-
288
- ### E_2
289
- Der Generator warnt: „`ram_gb=32` überschreitet das Node-Limit (`ram_gb ≤ 8`)". Was ist die richtige Reaktion?
290
- - A) Die Warnung ignorieren.
291
- - B) Sizing anpassen (Node-Grenze ist im MCP-Schema `ge=1, le=8`) oder den Workload auf den Auxiliary-Node (Oracle, 24 GB) planen.
292
- - C) Das Schema patchen.
293
- - D) Den Container trotzdem starten, wird schon klappen.
294
-
295
- → Richtig: **B**
296
-
297
- ### E_3
298
- Dein Custom-Workload braucht einen öffentlichen HTTP-Endpunkt mit Login. Welchem Basis-Track folgt Station 5?
299
- - A) Track C (Mailserver).
300
- - B) Track B: Caddy `forward_auth` + Cloudflare A-Record `🟠 proxied`, `require_auth=True`.
301
- - C) Gar keinem, Custom hat keine Station 5.
302
- - D) Track A.
303
-
304
- → Richtig: **B**
305
-
306
- ### E_4
307
- Warum wird auch das Custom-Profil zuerst mit `incus profile show` und `cloud-init status --wait` verifiziert, bevor irgendein Dienst getestet wird?
308
- - A) Reine Gewohnheit.
309
- - B) `profile show` bestätigt, dass das YAML syntaktisch akzeptiert wurde; `cloud-init status --wait` stellt sicher, dass `packages`/`runcmd` fehlerfrei durchliefen — sonst testest du gegen einen halb-provisionierten Container.
310
- - C) Es beschleunigt den Boot.
311
- - D) Damit das Zertifikat generiert wird.
312
-
313
- → Richtig: **B**