@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.
- package/.agents/skills/firecrawl/SKILL.md +149 -0
- package/.agents/skills/firecrawl/rules/install.md +82 -0
- package/.agents/skills/firecrawl/rules/security.md +26 -0
- package/.agents/skills/firecrawl-agent/SKILL.md +58 -0
- package/.agents/skills/firecrawl-build/SKILL.md +39 -0
- package/.agents/skills/firecrawl-build-interact/SKILL.md +68 -0
- package/.agents/skills/firecrawl-build-onboarding/SKILL.md +103 -0
- package/.agents/skills/firecrawl-build-onboarding/references/auth-flow.md +39 -0
- package/.agents/skills/firecrawl-build-onboarding/references/project-setup.md +20 -0
- package/.agents/skills/firecrawl-build-onboarding/references/sdk-installation.md +17 -0
- package/.agents/skills/firecrawl-build-scrape/SKILL.md +69 -0
- package/.agents/skills/firecrawl-build-search/SKILL.md +69 -0
- package/.agents/skills/firecrawl-crawl/SKILL.md +59 -0
- package/.agents/skills/firecrawl-download/SKILL.md +70 -0
- package/.agents/skills/firecrawl-interact/SKILL.md +84 -0
- package/.agents/skills/firecrawl-map/SKILL.md +51 -0
- package/.agents/skills/firecrawl-scrape/SKILL.md +69 -0
- package/.agents/skills/firecrawl-search/SKILL.md +60 -0
- package/CLAUDE.md +573 -0
- package/README.de.md +0 -8
- package/README.md +0 -8
- package/README.pt.md +0 -8
- package/assets/brand/ao-ant-mark.svg +91 -0
- package/assets/brand/bdb-core-mark.svg +34 -0
- package/assets/brand/heimdall-guardian-mark.svg +16 -0
- package/assets/brand/memb-crystal-mark.svg +18 -0
- package/bin/aos-config.mjs +89 -0
- package/bin/aos-dashboard.mjs +608 -0
- package/bin/aos-uninstall.mjs +227 -0
- package/docs/sessions/audit-2026-09-14-silent-failures.md +114 -0
- package/docs/skills_table.md +0 -3
- package/installer.js +471 -237
- package/mcps/RhinoMCP/cc-plugin/.claude/settings.json +10 -0
- package/mcps/after-effects-mcp/build/index.js +840 -0
- package/mcps/after-effects-mcp/build/scripts/applyEffect.jsx +153 -0
- package/mcps/after-effects-mcp/build/scripts/applyEffectTemplate.jsx +218 -0
- package/mcps/after-effects-mcp/build/scripts/createComposition.jsx +71 -0
- package/mcps/after-effects-mcp/build/scripts/createShapeLayer.jsx +147 -0
- package/mcps/after-effects-mcp/build/scripts/createSolidLayer.jsx +114 -0
- package/mcps/after-effects-mcp/build/scripts/createTextLayer.jsx +115 -0
- package/mcps/after-effects-mcp/build/scripts/getLayerInfo.jsx +192 -0
- package/mcps/after-effects-mcp/build/scripts/getProjectInfo.jsx +90 -0
- package/mcps/after-effects-mcp/build/scripts/listCompositions.jsx +50 -0
- package/mcps/after-effects-mcp/build/scripts/mcp-bridge-auto.jsx +1773 -0
- package/mcps/after-effects-mcp/build/scripts/setLayerProperties.jsx +160 -0
- package/mcps/computer-use-mcp/dist/client.d.ts +150 -0
- package/mcps/computer-use-mcp/dist/client.js +136 -0
- package/mcps/computer-use-mcp/dist/entrypoint.d.ts +16 -0
- package/mcps/computer-use-mcp/dist/entrypoint.js +26 -0
- package/mcps/computer-use-mcp/dist/native.d.ts +212 -0
- package/mcps/computer-use-mcp/dist/native.js +50 -0
- package/mcps/computer-use-mcp/dist/server.d.ts +32 -0
- package/mcps/computer-use-mcp/dist/server.js +342 -0
- package/mcps/computer-use-mcp/dist/session.d.ts +101 -0
- package/mcps/computer-use-mcp/dist/session.js +2372 -0
- package/package.json +13 -4
- package/skills/global_config/aos-project-init/SKILL.md +97 -130
- package/skills/global_config/aos-project-init/assets/openwikiignore.template +62 -0
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +38 -1
- package/skills/global_config/aos-setup/SKILL.md +98 -8
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +21 -2
- package/skills/global_config/ask-tim/SKILL.md +2 -7
- package/skills/global_config/openwiki-skill/scripts/openwiki_daemon.py +65 -12
- package/bin/setup-saas.mjs +0 -792
- package/mcps/blender-mcp-server/.dockerignore +0 -19
- package/mcps/blender-mcp-server/.github/workflows/ci.yml +0 -67
- package/mcps/blender-mcp-server/.github/workflows/publish-pypi.yml +0 -54
- package/mcps/blender-mcp-server/CHANGELOG.md +0 -64
- package/mcps/blender-mcp-server/CONTRIBUTING.md +0 -107
- package/mcps/blender-mcp-server/Dockerfile +0 -19
- package/mcps/blender-mcp-server/LICENSE +0 -21
- package/mcps/blender-mcp-server/README.md +0 -409
- package/mcps/blender-mcp-server/addon/__init__.py +0 -1440
- package/mcps/blender-mcp-server/addon/models.py +0 -223
- package/mcps/blender-mcp-server/pyproject.toml +0 -120
- package/mcps/blender-mcp-server/scripts/blender_bridge_request.py +0 -71
- package/mcps/blender-mcp-server/scripts/blender_create_test_cube.py +0 -49
- package/mcps/blender-mcp-server/scripts/blender_scene_info.py +0 -38
- package/mcps/blender-mcp-server/scripts/build_addon_zip.sh +0 -29
- package/mcps/blender-mcp-server/scripts/demos/README.md +0 -186
- package/mcps/blender-mcp-server/scripts/demos/dam_break_scene.py +0 -276
- package/mcps/blender-mcp-server/scripts/demos/open_dam_break_gui.py +0 -33
- package/mcps/blender-mcp-server/scripts/demos/pipe_movement_study.py +0 -518
- package/mcps/blender-mcp-server/scripts/demos/pipe_pressure_failure_scene.py +0 -806
- package/mcps/blender-mcp-server/scripts/demos/procedural_dam_break_scene.py +0 -600
- package/mcps/blender-mcp-server/scripts/demos/run_dam_break.py +0 -510
- package/mcps/blender-mcp-server/scripts/launch_blender_gui.py +0 -41
- package/mcps/blender-mcp-server/scripts/library/README.md +0 -64
- package/mcps/blender-mcp-server/scripts/library/apply_transforms.py +0 -46
- package/mcps/blender-mcp-server/scripts/library/camera.py +0 -51
- package/mcps/blender-mcp-server/scripts/library/collections.py +0 -65
- package/mcps/blender-mcp-server/scripts/library/create_mesh.py +0 -41
- package/mcps/blender-mcp-server/scripts/library/effector.py +0 -48
- package/mcps/blender-mcp-server/scripts/library/fluid_domain.py +0 -80
- package/mcps/blender-mcp-server/scripts/library/fluid_inflow.py +0 -98
- package/mcps/blender-mcp-server/scripts/library/frame_range.py +0 -35
- package/mcps/blender-mcp-server/scripts/library/keyframes.py +0 -59
- package/mcps/blender-mcp-server/scripts/library/rigid_body.py +0 -52
- package/mcps/blender-mcp-server/scripts/library/save_blend.py +0 -40
- package/mcps/blender-mcp-server/scripts/server_start.sh +0 -26
- package/mcps/blender-mcp-server/src/blender_mcp_server/__init__.py +0 -3
- package/mcps/blender-mcp-server/src/blender_mcp_server/headless.py +0 -330
- package/mcps/blender-mcp-server/src/blender_mcp_server/server.py +0 -606
- package/mcps/davinci-mcp-professional/.bandit +0 -35
- package/mcps/davinci-mcp-professional/.claude/commands/security-review.md +0 -191
- package/mcps/davinci-mcp-professional/.claude/settings.json +0 -1
- package/mcps/davinci-mcp-professional/.editorconfig +0 -27
- package/mcps/davinci-mcp-professional/.gitattributes +0 -207
- package/mcps/davinci-mcp-professional/.github/CODEOWNERS +0 -2
- package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
- package/mcps/davinci-mcp-professional/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- package/mcps/davinci-mcp-professional/.github/PULL_REQUEST_TEMPLATE.md +0 -20
- package/mcps/davinci-mcp-professional/.github/SECURITY.md +0 -97
- package/mcps/davinci-mcp-professional/.github/dependabot.yml +0 -27
- package/mcps/davinci-mcp-professional/.github/workflows/ci.yml +0 -39
- package/mcps/davinci-mcp-professional/ATTRIBUTION.md +0 -4
- package/mcps/davinci-mcp-professional/AUTHORS.md +0 -9
- package/mcps/davinci-mcp-professional/BUGS.md +0 -55
- package/mcps/davinci-mcp-professional/CLAUDE.md +0 -229
- package/mcps/davinci-mcp-professional/CONTRIBUTING.md +0 -51
- package/mcps/davinci-mcp-professional/COPYING.md +0 -228
- package/mcps/davinci-mcp-professional/Doxyfile +0 -379
- package/mcps/davinci-mcp-professional/README.md +0 -143
- package/mcps/davinci-mcp-professional/SECURITY.md +0 -40
- package/mcps/davinci-mcp-professional/USING.md +0 -301
- package/mcps/davinci-mcp-professional/VERSION.md +0 -13
- package/mcps/davinci-mcp-professional/build.py +0 -169
- package/mcps/davinci-mcp-professional/claude_desktop_config_template.json +0 -11
- package/mcps/davinci-mcp-professional/hooks/ci-check.sh +0 -29
- package/mcps/davinci-mcp-professional/hooks/pre-push +0 -46
- package/mcps/davinci-mcp-professional/main.py +0 -40
- package/mcps/davinci-mcp-professional/mcp_server.py +0 -30
- package/mcps/davinci-mcp-professional/pyproject.toml +0 -115
- package/mcps/davinci-mcp-professional/security_audit.py +0 -379
- package/mcps/davinci-mcp-professional/src/davinci_mcp/__init__.py +0 -19
- package/mcps/davinci-mcp-professional/src/davinci_mcp/cli.py +0 -138
- package/mcps/davinci-mcp-professional/src/davinci_mcp/resolve_client.py +0 -342
- package/mcps/davinci-mcp-professional/src/davinci_mcp/resources/__init__.py +0 -60
- package/mcps/davinci-mcp-professional/src/davinci_mcp/server.py +0 -185
- package/mcps/davinci-mcp-professional/src/davinci_mcp/tools/__init__.py +0 -146
- package/mcps/davinci-mcp-professional/src/davinci_mcp/types.py +0 -125
- package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/__init__.py +0 -19
- package/mcps/davinci-mcp-professional/src/davinci_mcp/utils/platform.py +0 -239
- package/mcps/davinci-mcp-professional/test.py +0 -186
- package/mcps/davinci-mcp-professional/uv.lock +0 -2073
- package/mcps/davinci-resolve-mcp/.claude/skills/media-analysis.md +0 -44
- package/mcps/davinci-resolve-mcp/.clinerules +0 -17
- package/mcps/davinci-resolve-mcp/.cursorrules +0 -17
- package/mcps/davinci-resolve-mcp/.github/copilot-instructions.md +0 -17
- package/mcps/davinci-resolve-mcp/.github/workflows/npm-publish.yml +0 -109
- package/mcps/davinci-resolve-mcp/.windsurfrules +0 -17
- package/mcps/davinci-resolve-mcp/AGENTS.md +0 -114
- package/mcps/davinci-resolve-mcp/CHANGELOG.md +0 -2648
- package/mcps/davinci-resolve-mcp/CLAUDE.md +0 -15
- package/mcps/davinci-resolve-mcp/LICENSE +0 -21
- package/mcps/davinci-resolve-mcp/README.md +0 -173
- package/mcps/davinci-resolve-mcp/SECURITY.md +0 -53
- package/mcps/davinci-resolve-mcp/bin/davinci-resolve-mcp.mjs +0 -450
- package/mcps/davinci-resolve-mcp/examples/README.md +0 -53
- package/mcps/davinci-resolve-mcp/examples/markers/README.md +0 -81
- package/mcps/davinci-resolve-mcp/examples/media/README.md +0 -94
- package/mcps/davinci-resolve-mcp/examples/timeline/README.md +0 -98
- package/mcps/davinci-resolve-mcp/install.py +0 -1687
- package/mcps/davinci-resolve-mcp/package.json +0 -52
- package/mcps/davinci-resolve-mcp/release-notes/v2.22.0.md +0 -51
- package/mcps/davinci-resolve-mcp/release-notes/v2.23.0.md +0 -51
- package/mcps/davinci-resolve-mcp/release-notes/v2.23.1.md +0 -35
- package/mcps/davinci-resolve-mcp/release-notes/v2.24.1.md +0 -32
- package/mcps/davinci-resolve-mcp/scripts/audit_api_parity.py +0 -275
- package/mcps/davinci-resolve-mcp/scripts/audit_readwrite_symmetry.py +0 -80
- package/mcps/davinci-resolve-mcp/scripts/doctor.py +0 -227
- package/mcps/davinci-resolve-mcp/scripts/gen_api_limitations.py +0 -144
- package/mcps/davinci-resolve-mcp/scripts/live_media_analysis_polish_probe.py +0 -65
- package/mcps/davinci-resolve-mcp/scripts/measure_bridge_cost.py +0 -65
- package/mcps/davinci-resolve-mcp/scripts/regen_panel_screenshots.py +0 -76
- package/mcps/davinci-resolve-mcp/src/__init__.py +0 -3
- package/mcps/davinci-resolve-mcp/src/analysis_dashboard.py +0 -15505
- package/mcps/davinci-resolve-mcp/src/batch_cli.py +0 -540
- package/mcps/davinci-resolve-mcp/src/control_panel.py +0 -13
- package/mcps/davinci-resolve-mcp/src/granular/__init__.py +0 -17
- package/mcps/davinci-resolve-mcp/src/granular/common.py +0 -741
- package/mcps/davinci-resolve-mcp/src/granular/folder.py +0 -420
- package/mcps/davinci-resolve-mcp/src/granular/gallery.py +0 -306
- package/mcps/davinci-resolve-mcp/src/granular/graph.py +0 -309
- package/mcps/davinci-resolve-mcp/src/granular/media_pool.py +0 -679
- package/mcps/davinci-resolve-mcp/src/granular/media_pool_item.py +0 -1020
- package/mcps/davinci-resolve-mcp/src/granular/media_storage.py +0 -179
- package/mcps/davinci-resolve-mcp/src/granular/project.py +0 -1654
- package/mcps/davinci-resolve-mcp/src/granular/resolve_control.py +0 -538
- package/mcps/davinci-resolve-mcp/src/granular/timeline.py +0 -1075
- package/mcps/davinci-resolve-mcp/src/granular/timeline_item.py +0 -2251
- package/mcps/davinci-resolve-mcp/src/resolve_mcp_server.py +0 -43
- package/mcps/davinci-resolve-mcp/src/server.py +0 -24116
- package/mcps/davinci-resolve-mcp/src/utils/__init__.py +0 -3
- package/mcps/davinci-resolve-mcp/src/utils/actor_identity.py +0 -46
- package/mcps/davinci-resolve-mcp/src/utils/analysis_caps.py +0 -678
- package/mcps/davinci-resolve-mcp/src/utils/analysis_memory.py +0 -755
- package/mcps/davinci-resolve-mcp/src/utils/analysis_runs.py +0 -307
- package/mcps/davinci-resolve-mcp/src/utils/analysis_store.py +0 -945
- package/mcps/davinci-resolve-mcp/src/utils/api_truth.py +0 -525
- package/mcps/davinci-resolve-mcp/src/utils/app_control.py +0 -319
- package/mcps/davinci-resolve-mcp/src/utils/audio_fairlight_live_probe.py +0 -263
- package/mcps/davinci-resolve-mcp/src/utils/brain_edits.py +0 -387
- package/mcps/davinci-resolve-mcp/src/utils/bridge_metrics.py +0 -76
- package/mcps/davinci-resolve-mcp/src/utils/cdl.py +0 -20
- package/mcps/davinci-resolve-mcp/src/utils/clip_query.py +0 -85
- package/mcps/davinci-resolve-mcp/src/utils/cloud_operations.py +0 -192
- package/mcps/davinci-resolve-mcp/src/utils/color_grade_live_probe.py +0 -444
- package/mcps/davinci-resolve-mcp/src/utils/contracts.py +0 -102
- package/mcps/davinci-resolve-mcp/src/utils/cut_ir.py +0 -115
- package/mcps/davinci-resolve-mcp/src/utils/dctl_templates.py +0 -368
- package/mcps/davinci-resolve-mcp/src/utils/deep_vision.py +0 -643
- package/mcps/davinci-resolve-mcp/src/utils/destructive_hook.py +0 -606
- package/mcps/davinci-resolve-mcp/src/utils/edit_engine.py +0 -737
- package/mcps/davinci-resolve-mcp/src/utils/embeddings.py +0 -922
- package/mcps/davinci-resolve-mcp/src/utils/entities.py +0 -579
- package/mcps/davinci-resolve-mcp/src/utils/extension_authoring_live_probe.py +0 -292
- package/mcps/davinci-resolve-mcp/src/utils/failure_tracker.py +0 -119
- package/mcps/davinci-resolve-mcp/src/utils/fuse_templates.py +0 -1968
- package/mcps/davinci-resolve-mcp/src/utils/fusion_composition_live_probe.py +0 -284
- package/mcps/davinci-resolve-mcp/src/utils/fusion_group_settings.py +0 -334
- package/mcps/davinci-resolve-mcp/src/utils/layout_presets.py +0 -333
- package/mcps/davinci-resolve-mcp/src/utils/mcp_stdio.py +0 -32
- package/mcps/davinci-resolve-mcp/src/utils/mcp_transport.py +0 -128
- package/mcps/davinci-resolve-mcp/src/utils/media_analysis.py +0 -7690
- package/mcps/davinci-resolve-mcp/src/utils/media_analysis_jobs.py +0 -805
- package/mcps/davinci-resolve-mcp/src/utils/media_pool_changes.py +0 -121
- package/mcps/davinci-resolve-mcp/src/utils/media_pool_ingest_live_probe.py +0 -592
- package/mcps/davinci-resolve-mcp/src/utils/multicam.py +0 -393
- package/mcps/davinci-resolve-mcp/src/utils/object_inspection.py +0 -301
- package/mcps/davinci-resolve-mcp/src/utils/page_lock.py +0 -75
- package/mcps/davinci-resolve-mcp/src/utils/platform.py +0 -157
- package/mcps/davinci-resolve-mcp/src/utils/proc.py +0 -26
- package/mcps/davinci-resolve-mcp/src/utils/project_cleanup.py +0 -73
- package/mcps/davinci-resolve-mcp/src/utils/project_lifecycle_live_probe.py +0 -376
- package/mcps/davinci-resolve-mcp/src/utils/project_lint.py +0 -131
- package/mcps/davinci-resolve-mcp/src/utils/project_properties.py +0 -601
- package/mcps/davinci-resolve-mcp/src/utils/project_spec.py +0 -459
- package/mcps/davinci-resolve-mcp/src/utils/readback.py +0 -91
- package/mcps/davinci-resolve-mcp/src/utils/render_deliver_live_probe.py +0 -384
- package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_governance.py +0 -214
- package/mcps/davinci-resolve-mcp/src/utils/resolve_ai_ledger.py +0 -244
- package/mcps/davinci-resolve-mcp/src/utils/resolve_busy.py +0 -171
- package/mcps/davinci-resolve-mcp/src/utils/resolve_connection.py +0 -77
- package/mcps/davinci-resolve-mcp/src/utils/review_annotation_live_probe.py +0 -352
- package/mcps/davinci-resolve-mcp/src/utils/script_templates.py +0 -1193
- package/mcps/davinci-resolve-mcp/src/utils/shot_relationships.py +0 -544
- package/mcps/davinci-resolve-mcp/src/utils/structural_diff.py +0 -175
- package/mcps/davinci-resolve-mcp/src/utils/sync_detection.py +0 -889
- package/mcps/davinci-resolve-mcp/src/utils/timeline_brain_db.py +0 -826
- package/mcps/davinci-resolve-mcp/src/utils/timeline_conform_live_probe.py +0 -280
- package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_live_probe.py +0 -1092
- package/mcps/davinci-resolve-mcp/src/utils/timeline_kernel_probe.py +0 -185
- package/mcps/davinci-resolve-mcp/src/utils/timeline_title_text.py +0 -87
- package/mcps/davinci-resolve-mcp/src/utils/timeline_versioning.py +0 -730
- package/mcps/davinci-resolve-mcp/src/utils/update_check.py +0 -685
- package/mcps/vectorworks-mcp/.dockerignore +0 -8
- package/mcps/vectorworks-mcp/Dockerfile +0 -28
- package/mcps/vectorworks-mcp/README.md +0 -156
- package/mcps/vectorworks-mcp/app/__init__.py +0 -2
- package/mcps/vectorworks-mcp/app/api.py +0 -52
- package/mcps/vectorworks-mcp/app/chunking.py +0 -56
- package/mcps/vectorworks-mcp/app/config.py +0 -29
- package/mcps/vectorworks-mcp/app/embeddings.py +0 -28
- package/mcps/vectorworks-mcp/app/indexer.py +0 -106
- package/mcps/vectorworks-mcp/app/main.py +0 -33
- package/mcps/vectorworks-mcp/app/mcp_server.py +0 -71
- package/mcps/vectorworks-mcp/app/search.py +0 -54
- package/mcps/vectorworks-mcp/app/utils.py +0 -14
- package/mcps/vectorworks-mcp/data/.gitkeep +0 -1
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_PluginScript.htm +0 -95
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_ScriptEditor.htm +0 -266
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2022_Scripting.htm +0 -106
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2023_CreatingScriptedPlugins.htm +0 -327
- package/mcps/vectorworks-mcp/data/vw-app-help/VW2024_RunningScripts.htm +0 -116
- package/mcps/vectorworks-mcp/data/vw-devwiki/VS_Function_Reference_category.html +0 -2129
- package/mcps/vectorworks-mcp/data/vw-jp-ref/ObjectsSymbols.html +0 -2035
- package/mcps/vectorworks-mcp/data/vw-jp-ref/ScriptFunctionReference.html +0 -29
- package/mcps/vectorworks-mcp/design.md +0 -57
- package/mcps/vectorworks-mcp/docker-compose.yml +0 -18
- package/mcps/vectorworks-mcp/index/.gitkeep +0 -1
- package/mcps/vectorworks-mcp/index/meta.jsonl +0 -3956
- package/mcps/vectorworks-mcp/index/vw.faiss +0 -0
- package/mcps/vectorworks-mcp/requirements.txt +0 -10
- package/mcps/vectorworks-mcp/scripts/fetch_docs_minimal.sh +0 -84
- package/mcps/vectorworks-mcp/scripts/fetch_github_vectorworks.sh +0 -85
- package/mcps/vectorworks-mcp/templates/index.html +0 -40
- package/scripts/ecosystem-health-audit.js +0 -257
- package/skills/bdb-dev-os-skill/SKILL.md +0 -49
- package/skills/bdb-dev-os-skill/package.json +0 -11
- package/skills/bdbsaastraining/SKILL.md +0 -316
- package/skills/bdbsaastraining/references/exam-pool.md +0 -313
- package/skills/bdbsaastraining/references/interaction-modes.md +0 -94
- package/skills/bdbsaastraining/references/track-a-ai-agent.md +0 -111
- package/skills/bdbsaastraining/references/track-b-wordpress.md +0 -111
- package/skills/bdbsaastraining/references/track-c-mailserver.md +0 -107
- package/skills/bdbsaastraining/references/track-d-debian.md +0 -109
- package/skills/bdbsaastraining/references/track-e-custom.md +0 -83
- package/skills/bdbsaastraining/scripts/build_profile.py +0 -529
- package/skills/bdbsaastraining/scripts/generate_certificate.py +0 -161
- package/skills/bdbsaastraining/scripts/preflight_check.sh +0 -150
- package/skills/bdbsaastraining/templates/certificate_template.html +0 -508
- package/skills/global_config/bdb-ecosystem-health/SKILL.md +0 -68
- package/skills/global_config/bdbsaas-ops/SKILL.md +0 -16
- package/skills/global_config/bdbsaashost/SKILL.md +0 -125
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# Interaktionsmodi — Dual-Mode Kontrakt
|
|
2
|
-
|
|
3
|
-
Der Trainings-Skill läuft in fünf Clients. Nur **Claude Code** hat ein natives Auswahl-Tool.
|
|
4
|
-
Der Tutor erkennt den Client aus Station 0 (`<CLIENT_NAME>`) und wählt den Modus **einmal** für die gesamte Session.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## Modus 1 — Claude Code: `AskUserQuestion`
|
|
9
|
-
|
|
10
|
-
Nutze das Tool für **jede** strukturierte Auswahl:
|
|
11
|
-
- Track-Wahl (Station 0, Teil B)
|
|
12
|
-
- Sizing-/Konfig-Entscheidungen (CPU/RAM/Disk, DNS-Proxy-Modus, Auth ja/nein)
|
|
13
|
-
- alle Multiple-Choice-Verständnisfragen
|
|
14
|
-
- alle 10 Abschlussfragen
|
|
15
|
-
|
|
16
|
-
Regeln:
|
|
17
|
-
- 2–4 echte Optionen pro Frage. Die vom Skill empfohlene Option steht an Position 1 mit `(Empfohlen)` im Label.
|
|
18
|
-
- `header` ≤ 12 Zeichen (z. B. `Track`, `RAM`, `DNS-Modus`, `Frage 3`).
|
|
19
|
-
- **„Other" (Freitext) fügt das Tool automatisch hinzu** — nicht selbst als Option auflisten.
|
|
20
|
-
- `preview` einsetzen, wenn **Vergleich** der Kern ist: YAML-Profilvarianten nebeneinander, Ressourcen-Sizing, `🟠 proxied` vs `⚪ DNS-only`. NICHT bei einfachen Ja/Nein-Abzweigungen.
|
|
21
|
-
- Single-Select als Default. `multiSelect: true` nur wenn Mehrfachauswahl fachlich sinnvoll ist (z. B. „welche Zusatzpakete brauchst du?").
|
|
22
|
-
|
|
23
|
-
Auswertung:
|
|
24
|
-
- Gewählte Option → direkt weiterverarbeiten.
|
|
25
|
-
- „Other"-Freitext → siehe Freitext-Regeln unten.
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Modus 2 — AGY / Cursor / Claude Desktop / OpenCode / unbekannt: Text-Schema
|
|
30
|
-
|
|
31
|
-
Formatiere jede Auswahl als nummerierte Liste:
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
<Frage>
|
|
35
|
-
|
|
36
|
-
A) <Option 1>
|
|
37
|
-
B) <Option 2>
|
|
38
|
-
C) <Option 3>
|
|
39
|
-
D) <Option 4>
|
|
40
|
-
E) etwas anderes → beschreib es in eigenen Worten
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
- `E)` ist der Freitext-Kanal (Äquivalent zu „Other").
|
|
44
|
-
- Bei Verständnisfragen mit nur 2–4 Sachoptionen entfällt `E)` **nur in der Abschlussprüfung** (dort ist Freitext ungültig); in Stationsfragen bleibt `E)` erhalten.
|
|
45
|
-
- **Fehleingaben still normalisieren:** `b`, `b.`, `B)`, „Antwort B", „die zweite", „option 2" → alle zu `B`. Nicht belehren, einfach die gemeinte Option verarbeiten.
|
|
46
|
-
- Mehrdeutige oder leere Antwort → einmal kurz rückfragen: „Meinst du A oder C?"
|
|
47
|
-
|
|
48
|
-
---
|
|
49
|
-
|
|
50
|
-
## Freitext-Regeln (modusübergreifend)
|
|
51
|
-
|
|
52
|
-
| Kontext | Freitext erlaubt? | Verhalten |
|
|
53
|
-
| :-- | :-- | :-- |
|
|
54
|
-
| Station 0 Teil A (Name, User, Client) | ja, immer offen | direkt übernehmen |
|
|
55
|
-
| Station 0 Teil B (Workload) | **ja, erwünscht** | Freitext → **Track E**, Rohziel für `build_profile.py` merken |
|
|
56
|
-
| Sizing-/Konfig-Fragen (Station 2, Track E) | **ja, erwünscht** | Freitext parsen (Zahlen, Paketnamen, Ports); bei Lücken gezielt nachfragen |
|
|
57
|
-
| Zwischen-Verständnisfragen der Stationen 0.5–5 | ja | Freitext inhaltlich bewerten; bei „fast richtig" sokratisch nachhaken |
|
|
58
|
-
| **Abschlussprüfung (10 Fragen)** | **nein** | Freitext → **einmalig** um Auswahl A–D bitten. Bleibt Trainee bei Freitext → **0 Punkte** für die Frage, weiter zur nächsten |
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
## Mapping Workload-Auswahl → Track
|
|
63
|
-
|
|
64
|
-
| Auswahl Station 0 Teil B | Track | Track-Datei |
|
|
65
|
-
| :-- | :-- | :-- |
|
|
66
|
-
| A · AI-Agent Sandbox | `A` | `references/track-a-ai-agent.md` |
|
|
67
|
-
| B · WordPress / Web-App | `B` | `references/track-b-wordpress.md` |
|
|
68
|
-
| C · Mailserver | `C` | `references/track-c-mailserver.md` |
|
|
69
|
-
| D · Clean Debian / DB / Worker | `D` | `references/track-d-debian.md` |
|
|
70
|
-
| „Other" / E · Freitext | `E` | `references/track-e-custom.md` |
|
|
71
|
-
|
|
72
|
-
Track E kann nach dem Interview auf einen konkreten Basis-Track „andocken" (web-artig → B-Muster, mail-artig → C-Muster, intern → D-Muster). Die Track-E-Datei steuert das.
|
|
73
|
-
|
|
74
|
-
---
|
|
75
|
-
|
|
76
|
-
## Beispiel — Track-Wahl in beiden Modi
|
|
77
|
-
|
|
78
|
-
**Claude Code (`AskUserQuestion`):**
|
|
79
|
-
- question: „Was möchtest du auf der BDB SaaS Host Fleet konkret betreiben?"
|
|
80
|
-
- header: `Workload`
|
|
81
|
-
- options: `AI-Agent Sandbox` / `WordPress / Web-App` / `Mailserver` / `Clean Debian / DB / Worker`
|
|
82
|
-
- (Tool ergänzt „Other" automatisch → Track E)
|
|
83
|
-
- optional `preview` je Option: 4–6 Zeilen, was der Track lehrt + Basis-Template
|
|
84
|
-
|
|
85
|
-
**Text-Modus:**
|
|
86
|
-
```
|
|
87
|
-
Was möchtest du auf der BDB SaaS Host Fleet konkret betreiben?
|
|
88
|
-
|
|
89
|
-
A) AI-Agent Sandbox – autonome Agenten, restricted shell, agent-sudo
|
|
90
|
-
B) WordPress / Web-App – öffentlich, Caddy + Authelia 2FA, Cloudflare proxied
|
|
91
|
-
C) Mailserver – Froxlor/Postfix/Dovecot, eigene Kundendomain, DNS-Blueprint
|
|
92
|
-
D) Clean Debian – generischer Container, Datenbank/Worker, selbst konfiguriert
|
|
93
|
-
E) etwas anderes → beschreib deinen Workload in eigenen Worten
|
|
94
|
-
```
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Track A — AI-Agent Sandbox
|
|
2
|
-
|
|
3
|
-
**Ziel-Workload:** autonome AI-Agenten in isolierter, restricted-shell Umgebung.
|
|
4
|
-
**Basis-Template (real):** `server-config/templates/incus/profile-ai-agent.yaml`
|
|
5
|
-
**Container-Name im Training:** `c-A-<TRAINEE_USER>` · **Profil-Name:** `A-<TRAINEE_USER>`
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Station 2 — Incus Profile Engineering (Track A)
|
|
10
|
-
|
|
11
|
-
### 2.1 Echtes Template inspizieren
|
|
12
|
-
Der Trainee öffnet `profile-ai-agent.yaml` und liest laut vor, was er sieht. Erwartete Struktur:
|
|
13
|
-
- `config.limits.cpu: "2"`, `config.limits.memory: 2GiB` — harte Quotas.
|
|
14
|
-
- `config.cloud-init.user-data` (**nicht** `user.user-data`) mit `#cloud-config`.
|
|
15
|
-
- `packages:` nodejs, npm, python3, python3-venv, python3-pip, git, build-essential.
|
|
16
|
-
- `users:` — ein User `agent` mit **`shell: /bin/rbash`** und einer einzigen sudo-Regel (`systemctl --no-pager status *`).
|
|
17
|
-
- `write_files:` — eine `README.txt` im Home des Agenten.
|
|
18
|
-
- **kein `devices:`** → `eth0`/`root` kommen aus dem `default`-Profil.
|
|
19
|
-
|
|
20
|
-
Frage zum Verständnis (nicht Prüfung): „Was kann der User `agent` mit `/bin/rbash` NICHT?" → kein `cd`, keine absoluten Pfade, kein `>`-Redirect, kein Ändern von `PATH`.
|
|
21
|
-
|
|
22
|
-
### 2.2 Eigenes Profil generieren
|
|
23
|
-
Interview (per `AskUserQuestion` / Text):
|
|
24
|
-
- RAM: 1 / 2 / 4 GiB (Default 2, Node-Limit ≤ 8)
|
|
25
|
-
- CPU: 1 / 2 (Default 2)
|
|
26
|
-
- Zusatz-Runtime: „nur Python" / „nur Node" / „beides" (Default beides)
|
|
27
|
-
- Agent-Framework vorinstallieren? `fastmcp` via pip / `@modelcontextprotocol/sdk` via npm / nichts
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
python3 ~/.agents/skills/bdbsaastraining/scripts/build_profile.py \
|
|
31
|
-
--track A --user <TRAINEE_USER> \
|
|
32
|
-
--ram 2 --cpu 2 --runtime both --agent-framework fastmcp
|
|
33
|
-
```
|
|
34
|
-
Output: `~/profile-A-<TRAINEE_USER>.yaml` + zeilenweise Erklärung.
|
|
35
|
-
Der Generator behält `shell: /bin/rbash` bei (Kernkonzept) und ergänzt bei `--agent-framework fastmcp` einen `runcmd`-Schritt `python3 -m venv /home/agent/venv && /home/agent/venv/bin/pip install fastmcp` (statt es dem Trainee später als `ModuleNotFoundError` zu überlassen).
|
|
36
|
-
|
|
37
|
-
### 2.3 Registrieren & prüfen
|
|
38
|
-
```bash
|
|
39
|
-
sudo incus profile create A-<TRAINEE_USER>
|
|
40
|
-
sudo incus profile edit A-<TRAINEE_USER> < ~/profile-A-<TRAINEE_USER>.yaml
|
|
41
|
-
sudo incus profile show A-<TRAINEE_USER>
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Verständnisfrage 2 → `exam-pool.md` → `CORE_2`** (incusbr0 / Bridge).
|
|
45
|
-
|
|
46
|
-
---
|
|
47
|
-
|
|
48
|
-
## Station 3 — Deployment & Agent-Task (Track A)
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
sudo incus launch images:debian/13 c-A-<TRAINEE_USER> -p default -p A-<TRAINEE_USER>
|
|
52
|
-
sudo incus list
|
|
53
|
-
sudo incus exec c-A-<TRAINEE_USER> -- cloud-init status --wait
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
### 3.1 In die Sandbox als unprivilegierter Agent
|
|
57
|
-
```bash
|
|
58
|
-
sudo incus exec c-A-<TRAINEE_USER> -- su - agent
|
|
59
|
-
# Erwartung: rbash-Prompt. Test:
|
|
60
|
-
cd /tmp # -> rbash: cd: restricted
|
|
61
|
-
```
|
|
62
|
-
> Falls der Trainee den User `agentrunner` erwartet (aus altem Skill-Stand): den gibt es NICHT. Der reale User heißt `agent`.
|
|
63
|
-
|
|
64
|
-
### 3.2 Realer Agent-Task — MCP-Tool im Container bauen
|
|
65
|
-
```bash
|
|
66
|
-
# als agent, im Home:
|
|
67
|
-
cat > build_mcp.py <<'PY'
|
|
68
|
-
from fastmcp import FastMCP
|
|
69
|
-
mcp = FastMCP("demo-agent-service")
|
|
70
|
-
|
|
71
|
-
@mcp.tool()
|
|
72
|
-
def analyze_lead(email: str, company: str) -> dict:
|
|
73
|
-
return {"status": "analyzed", "email": email, "company": company, "score": 95}
|
|
74
|
-
|
|
75
|
-
if __name__ == "__main__":
|
|
76
|
-
mcp.run(transport="stdio")
|
|
77
|
-
PY
|
|
78
|
-
/home/agent/venv/bin/python build_mcp.py --help 2>&1 | head
|
|
79
|
-
```
|
|
80
|
-
Didaktik: Selbst wenn das Skript crasht oder eine Endlosschleife baut — der Host ist durch die 2-GiB-Quota + Incus-Sandbox unberührt.
|
|
81
|
-
|
|
82
|
-
**Verständnisfrage 3 → `exam-pool.md` → `CORE_1`** (Sandbox-Vorteil).
|
|
83
|
-
|
|
84
|
-
---
|
|
85
|
-
|
|
86
|
-
## Station 4 — FastMCP & Guardrails (Track A-Fokus)
|
|
87
|
-
|
|
88
|
-
Zusätzlich zum gemeinsamen Station-4-Ablauf (siehe `SKILL.md`):
|
|
89
|
-
- Der Trainee ruft `create_lldap_user(username="agent-demo-<TRAINEE_USER>", group="ai_agents", owner="<TRAINEE_USER>")` auf und beobachtet die Antwort (`status: "success"`, Hinweis auf Background-Worker).
|
|
90
|
-
- Erklärung `agent-sudo`: auf einer Agent-SSH-Session ist `sudo` gesperrt; der Agent nutzt `agent-sudo <cmd>`. `agent-sudo ls /etc` → Auto-Approve. `agent-sudo systemctl restart caddy` → Queue.
|
|
91
|
-
|
|
92
|
-
**Track-Fragen für die Prüfung:** `A_1`, `A_2`, `A_3`, `A_4`.
|
|
93
|
-
|
|
94
|
-
---
|
|
95
|
-
|
|
96
|
-
## Station 5 — Interne Gateway-Route (Track A)
|
|
97
|
-
|
|
98
|
-
Der Agent exponiert ein kleines Web-UI (z. B. Port 8000) — **nur** hinter Authelia, nie roh öffentlich:
|
|
99
|
-
```
|
|
100
|
-
remoteos_add_route(
|
|
101
|
-
domain="agent-<TRAINEE_USER>.<DOMAIN>",
|
|
102
|
-
upstream_port=8000,
|
|
103
|
-
require_auth=True,
|
|
104
|
-
target_node="netcup",
|
|
105
|
-
service_type="web",
|
|
106
|
-
sync_cloudflare=True
|
|
107
|
-
)
|
|
108
|
-
```
|
|
109
|
-
> **Gateway-Lücke:** `/tools/add_route` ist am Remote-Gateway ein Stub. Der Trainee verifiziert daher zusätzlich direkt auf dem Server: `sudo caddy validate --config /etc/caddy/Caddyfile` und prüft, ob ein `forward_auth`-Block für die Domain existiert. Alternativ Konzept erklären: ohne 2FA-Session → 302 auf `auth.<DOMAIN>`.
|
|
110
|
-
|
|
111
|
-
**Verständnisfrage 5 → `exam-pool.md` → `A_3`** (agent-sudo Klassifikation) — oder als Prüfungsfrage aufheben und hier `CORE_5` (Queue-Verhalten) stellen.
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Track B — WordPress / Web-App
|
|
2
|
-
|
|
3
|
-
**Ziel-Workload:** öffentlich erreichbare Web-Anwendung hinter Caddy + Authelia 2FA.
|
|
4
|
-
**Basis-Template (real):** `server-config/templates/incus/profile-wordpress.yaml`
|
|
5
|
-
**Container:** `c-B-<TRAINEE_USER>` · **Profil:** `B-<TRAINEE_USER>`
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Station 2 — Incus Profile Engineering (Track B)
|
|
10
|
-
|
|
11
|
-
### 2.1 Echtes Template inspizieren
|
|
12
|
-
`profile-wordpress.yaml`:
|
|
13
|
-
- `config.limits.cpu: "2"`, `config.limits.memory: 4GiB`.
|
|
14
|
-
- `config.cloud-init.user-data` → `#cloud-config` mit `package_update: true`, `package_upgrade: true`.
|
|
15
|
-
- `packages:` nginx, mariadb-server, redis-server, php-fpm, php-mysql, php-redis, php-curl, php-gd, php-xml, php-mbstring, certbot.
|
|
16
|
-
- `runcmd:` — erzeugt DB `wp` + User `wp` mit Zufallspasswort (`openssl rand -hex 16` → `/root/.wp-db-credentials`, `chmod 0600`), dann `systemctl enable --now nginx mariadb redis-server php8.2-fpm`.
|
|
17
|
-
- **kein `devices:`** → aus `default`.
|
|
18
|
-
|
|
19
|
-
**Bekannter Bug (Diagnose-Übung):** `php8.2-fpm` ist hart kodiert. Debian 13 (trixie) liefert PHP 8.4 → die Unit `php8.2-fpm` existiert nicht, der `systemctl`-Aufruf schlägt fehl. Der Generator ersetzt das durch die real installierte Version (`php-fpm` Meta-Paket → Dienst per `systemctl enable --now $(systemctl list-units 'php*-fpm*' ...)` bzw. parametrisiert `php8.4-fpm`).
|
|
20
|
-
|
|
21
|
-
### 2.2 Eigenes Profil generieren
|
|
22
|
-
Interview:
|
|
23
|
-
- RAM: 2 / 4 GiB (Default 4, Node-Limit ≤ 8)
|
|
24
|
-
- Disk-Quota: 20 / 40 / 60 GiB (Default 40)
|
|
25
|
-
- DB-Engine: MariaDB (Default) / PostgreSQL
|
|
26
|
-
- Object-Cache Redis: ja (Default) / nein
|
|
27
|
-
- WordPress automatisch per `wp-cli` installieren? ja / nein (nur Stack)
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
python3 ~/.agents/skills/bdbsaastraining/scripts/build_profile.py \
|
|
31
|
-
--track B --user <TRAINEE_USER> \
|
|
32
|
-
--ram 4 --disk 40 --db mariadb --redis yes --wpcli yes
|
|
33
|
-
```
|
|
34
|
-
Output: `~/profile-B-<TRAINEE_USER>.yaml`. Der Generator fixt den `php8.2-fpm`-Bug und fügt bei `--wpcli yes` einen `runcmd`-Schritt für `wp core download && wp config create ...` hinzu.
|
|
35
|
-
|
|
36
|
-
### 2.3 Registrieren & prüfen
|
|
37
|
-
```bash
|
|
38
|
-
sudo incus profile create B-<TRAINEE_USER>
|
|
39
|
-
sudo incus profile edit B-<TRAINEE_USER> < ~/profile-B-<TRAINEE_USER>.yaml
|
|
40
|
-
sudo incus profile show B-<TRAINEE_USER>
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
**Verständnisfrage 2 → `exam-pool.md` → `B_1`** (packages in cloud-init).
|
|
44
|
-
|
|
45
|
-
---
|
|
46
|
-
|
|
47
|
-
## Station 3 — Deployment & Verify (Track B)
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
sudo incus launch images:debian/13 c-B-<TRAINEE_USER> -p default -p B-<TRAINEE_USER>
|
|
51
|
-
sudo incus exec c-B-<TRAINEE_USER> -- cloud-init status --wait
|
|
52
|
-
sudo incus exec c-B-<TRAINEE_USER> -- systemctl --failed
|
|
53
|
-
```
|
|
54
|
-
Verifikation:
|
|
55
|
-
```bash
|
|
56
|
-
CT_IP=$(sudo incus list c-B-<TRAINEE_USER> -c4 --format csv | cut -d' ' -f1)
|
|
57
|
-
curl -sI "http://$CT_IP/" | head -1 # -> HTTP/1.1 200 / 301 (nginx lebt)
|
|
58
|
-
sudo incus exec c-B-<TRAINEE_USER> -- cat /root/.wp-db-credentials
|
|
59
|
-
```
|
|
60
|
-
Wenn `systemctl --failed` `php8.2-fpm` zeigt → Diagnose-Übung: `systemctl list-units 'php*'`, richtigen Dienstnamen finden, im generierten Profil ist es bereits gefixt (Trainee vergleicht).
|
|
61
|
-
|
|
62
|
-
**Verständnisfrage 3 → `exam-pool.md` → `B_4`** (php-Version-Bug).
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## Station 4 — FastMCP & Guardrails
|
|
67
|
-
|
|
68
|
-
Gemeinsamer Ablauf (`SKILL.md`). Track-B-Betonung: `remoteos_create_instance` würde für einen echten Kunden so aussehen —
|
|
69
|
-
```
|
|
70
|
-
remoteos_create_instance(
|
|
71
|
-
client_name="kunde-mueller",
|
|
72
|
-
domain="shop.kunde-mueller.de",
|
|
73
|
-
template="wordpress",
|
|
74
|
-
environment="staging1",
|
|
75
|
-
target_node="netcup",
|
|
76
|
-
cpu_cores=2, ram_gb=4, disk_gb=40
|
|
77
|
-
)
|
|
78
|
-
```
|
|
79
|
-
`staging1` → sofort, `environment="production"` → 4-Augen-Queue (siehe `classify_risk`).
|
|
80
|
-
|
|
81
|
-
**Track-Fragen:** `B_1`, `B_2`, `B_3`, `B_4`.
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## Station 5 — Öffentliche Web-Route (Track B)
|
|
86
|
-
|
|
87
|
-
```
|
|
88
|
-
remoteos_add_route(
|
|
89
|
-
domain="app-<TRAINEE_USER>.<DOMAIN>",
|
|
90
|
-
upstream_port=80,
|
|
91
|
-
require_auth=True,
|
|
92
|
-
target_node="netcup",
|
|
93
|
-
service_type="web",
|
|
94
|
-
sync_cloudflare=True
|
|
95
|
-
)
|
|
96
|
-
```
|
|
97
|
-
Erwartetes Verhalten (Konzept, da `/tools/add_route` Stub):
|
|
98
|
-
- Caddy bekommt `forward_auth 127.0.0.1:9091 { uri /api/authz/forward-auth ... }` + `reverse_proxy` auf die Container-IP.
|
|
99
|
-
- Cloudflare A-Record `app-<TRAINEE_USER>` → Netcup-IP, **`🟠 proxied`** (`service_type="web"` ⇒ `proxied: true`).
|
|
100
|
-
|
|
101
|
-
Verifikation auf dem Server:
|
|
102
|
-
```bash
|
|
103
|
-
sudo caddy validate --config /etc/caddy/Caddyfile
|
|
104
|
-
curl -sI https://app-<TRAINEE_USER>.<DOMAIN> | grep -Ei 'location|http/' # -> 302 auth.<DOMAIN>
|
|
105
|
-
```
|
|
106
|
-
DNS-Blueprint für eine echte Kundendomain zusätzlich:
|
|
107
|
-
```
|
|
108
|
-
remoteos_get_dns_blueprint(domain="kunde-mueller.de", service_type="web")
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**Verständnisfrage 5 → `exam-pool.md` → `B_2`** (proxied-Modus) oder `B_3` (forward_auth 302).
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
# Track C — Mailserver (Froxlor / Postfix / Dovecot)
|
|
2
|
-
|
|
3
|
-
**Ziel-Workload:** Kunden-Mailserver mit eigener Domain.
|
|
4
|
-
**Basis-Template (real):** `server-config/templates/incus/profile-mailserver-froxlor.yaml`
|
|
5
|
-
**Container:** `c-C-<TRAINEE_USER>` · **Profil:** `C-<TRAINEE_USER>`
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Station 2 — Incus Profile Engineering (Track C)
|
|
10
|
-
|
|
11
|
-
### 2.1 Echtes Template inspizieren
|
|
12
|
-
`profile-mailserver-froxlor.yaml`:
|
|
13
|
-
- **Top-Level `name:` UND `description:`** (dieses Template hat beides — anders als die anderen).
|
|
14
|
-
- `config.limits.cpu: "2"`, `config.limits.memory: 4GiB`.
|
|
15
|
-
- `config.cloud-init.user-data` → `packages:` postfix, dovecot-imapd, dovecot-pop3d, mariadb-server, php-fpm, php-mysql, php-cli, certbot, nginx, curl, gnupg.
|
|
16
|
-
- `write_files:` — `/root/install_froxlor.sh` (Rechte `0755`), setzt die offizielle Froxlor-Debian-Repo + Key ein, `apt-get install froxlor`.
|
|
17
|
-
- `runcmd:` — `[ "/bin/bash", "/root/install_froxlor.sh" ]`.
|
|
18
|
-
|
|
19
|
-
> Für `incus profile edit` **muss der Top-Level `name:` raus** (bzw. exakt gleich dem CLI-Profilnamen). Der Generator entfernt ihn.
|
|
20
|
-
> `php8.2-fpm` im `install_froxlor.sh` ist wie bei Track B versionsabhängig — Diagnose-Übung, im Generat gefixt.
|
|
21
|
-
|
|
22
|
-
### 2.2 Eigenes Profil generieren
|
|
23
|
-
Interview:
|
|
24
|
-
- Kundendomain (Freitext, z. B. `kunde-mueller.de`) — Pflicht für Station 5
|
|
25
|
-
- Anzahl Postfächer: 5 / 10 / 20 (beeinflusst Disk-Empfehlung)
|
|
26
|
-
- POP3 zusätzlich zu IMAP? ja / nein (Default nur IMAP)
|
|
27
|
-
- Webmail (Roundcube) mit ausliefern? ja / nein
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
python3 ~/.agents/skills/bdbsaastraining/scripts/build_profile.py \
|
|
31
|
-
--track C --user <TRAINEE_USER> \
|
|
32
|
-
--customer-domain kunde-mueller.de --mailboxes 10 --pop3 no --webmail yes
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### 2.3 Registrieren & prüfen
|
|
36
|
-
```bash
|
|
37
|
-
sudo incus profile create C-<TRAINEE_USER>
|
|
38
|
-
sudo incus profile edit C-<TRAINEE_USER> < ~/profile-C-<TRAINEE_USER>.yaml
|
|
39
|
-
sudo incus profile show C-<TRAINEE_USER>
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
**Verständnisfrage 2 → `exam-pool.md` → `C_1`** (write_files vs runcmd).
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## Station 3 — Deployment & Verify (Track C)
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
sudo incus launch images:debian/13 c-C-<TRAINEE_USER> -p default -p C-<TRAINEE_USER>
|
|
50
|
-
sudo incus exec c-C-<TRAINEE_USER> -- cloud-init status --wait
|
|
51
|
-
```
|
|
52
|
-
Verifikation:
|
|
53
|
-
```bash
|
|
54
|
-
sudo incus exec c-C-<TRAINEE_USER> -- postconf mail_version
|
|
55
|
-
sudo incus exec c-C-<TRAINEE_USER> -- systemctl is-active postfix dovecot
|
|
56
|
-
sudo incus exec c-C-<TRAINEE_USER> -- ss -tlnp | grep -E ':25|:143|:993'
|
|
57
|
-
sudo incus exec c-C-<TRAINEE_USER> -- ls -la /var/www/froxlor 2>/dev/null || echo "froxlor install noch nicht fertig"
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
**Verständnisfrage 3 → `exam-pool.md` → `CORE_6`** (Mail nie proxied).
|
|
61
|
-
|
|
62
|
-
---
|
|
63
|
-
|
|
64
|
-
## Station 4 — FastMCP & Guardrails
|
|
65
|
-
|
|
66
|
-
Gemeinsamer Ablauf. Track-C-Betonung — echter Provisioning-Call für einen Mail-Kunden:
|
|
67
|
-
```
|
|
68
|
-
remoteos_create_instance(
|
|
69
|
-
client_name="kunde-mueller",
|
|
70
|
-
domain="mail.kunde-mueller.de",
|
|
71
|
-
template="froxlor-mail",
|
|
72
|
-
environment="staging1",
|
|
73
|
-
target_node="netcup"
|
|
74
|
-
)
|
|
75
|
-
```
|
|
76
|
-
Antwort enthält bei einer externen Kundendomain (nicht die Fleet-Domain) **kein** Cloudflare-Sync, sondern ein `dns_blueprint`-Feld (Mailserver-Variante).
|
|
77
|
-
|
|
78
|
-
**Track-Fragen:** `C_1`, `C_2`, `C_3`, `C_4`.
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
## Station 5 — DNS-Blueprint für die Kundendomain (Track C)
|
|
83
|
-
|
|
84
|
-
```
|
|
85
|
-
remoteos_get_dns_blueprint(
|
|
86
|
-
domain="<CUSTOMER_DOMAIN>",
|
|
87
|
-
service_type="mail",
|
|
88
|
-
target_node="netcup"
|
|
89
|
-
)
|
|
90
|
-
```
|
|
91
|
-
Der Trainee liest das generierte Paket und ordnet jeden Record zu:
|
|
92
|
-
- **A** `mail.<domain>` → Netcup-IP, **⚪ DNS-only**
|
|
93
|
-
- **MX** `<domain>` → `mail.<domain>` Prio 10
|
|
94
|
-
- **TXT SPF** `v=spf1 a mx ~all` (o. ä.)
|
|
95
|
-
- **TXT DKIM** `default._domainkey.<domain>` (öffentlicher Key aus dem Container)
|
|
96
|
-
- **TXT DMARC** `_dmarc.<domain>` `v=DMARC1; p=quarantine; ...`
|
|
97
|
-
- **CNAME** `autodiscover` / `autoconfig`
|
|
98
|
-
|
|
99
|
-
Wichtig: Die Fleet verwaltet nur ihre eigene Domain (`*.<FLEET_DOMAIN>`) per Cloudflare-API. Für **BYOD-Kundendomains** trägt der Kunde diese Records bei **seinem eigenen** DNS-Provider ein — deshalb Blueprint statt API-Call.
|
|
100
|
-
|
|
101
|
-
DKIM-Key aus dem Container holen:
|
|
102
|
-
```bash
|
|
103
|
-
sudo incus exec c-C-<TRAINEE_USER> -- cat /etc/dkimkeys/<domain>/default.txt 2>/dev/null || \
|
|
104
|
-
sudo incus exec c-C-<TRAINEE_USER> -- opendkim-genkey --help
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Verständnisfrage 5 → `exam-pool.md` → `C_4`** (BYOD Blueprint).
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
# Track D — Clean Debian / Datenbank / Worker
|
|
2
|
-
|
|
3
|
-
**Ziel-Workload:** generischer System-Container (PostgreSQL, Redis, BullMQ-Worker, Cron-Jobs …), selbst konfiguriert.
|
|
4
|
-
**Basis-Template:** KEINES — es gibt kein `profile-debian-clean.yaml`. Station 2 = Profil von Grund auf.
|
|
5
|
-
**Container:** `c-D-<TRAINEE_USER>` · **Profil:** `D-<TRAINEE_USER>`
|
|
6
|
-
|
|
7
|
-
> Hinweis: Das MCP-Schema kennt `template="debian-clean"`, aber `incus_client.create_from_profile` erwartet ein Incus-Profil dieses Namens auf dem Host — das existiert nicht. Deshalb geht Track D bewusst den manuellen `incus profile create/edit`-Weg. Das ist der eigentliche Lernwert: „Custom Profile Engineering".
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Station 2 — Incus Profile von Grund auf (Track D)
|
|
12
|
-
|
|
13
|
-
### 2.1 Vergleichsbasis
|
|
14
|
-
Der Trainee öffnet EIN mitgeliefertes Template (z. B. `profile-ai-agent.yaml`) nur als Formvorlage und markiert, was für einen minimalen DB-Container **weg** kann (nodejs, npm, build-essential, rbash-User).
|
|
15
|
-
|
|
16
|
-
### 2.2 Interview → minimales Profil
|
|
17
|
-
- Workload-Art: PostgreSQL / Redis / Node-Worker (BullMQ) / „nur Debian, ich installiere selbst"
|
|
18
|
-
- RAM: 1 / 2 / 4 GiB (Node-Limit ≤ 8)
|
|
19
|
-
- CPU-Kerne: 1 / 2 · CPU-Deckel: `limits.cpu.allowance` 50% / 100%
|
|
20
|
-
- Disk-Quota: 10 / 20 / 30 GiB
|
|
21
|
-
- Persistenter Datenpfad als eigenes `devices:`-Disk (empfohlen für DB): ja / nein
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
python3 ~/.agents/skills/bdbsaastraining/scripts/build_profile.py \
|
|
25
|
-
--track D --user <TRAINEE_USER> \
|
|
26
|
-
--workload postgres --ram 2 --cpu 2 --cpu-allowance 50 --disk 20 --data-device yes
|
|
27
|
-
```
|
|
28
|
-
Ergebnis-Skelett (illustrativ, real generiert der Generator):
|
|
29
|
-
```yaml
|
|
30
|
-
config:
|
|
31
|
-
limits.cpu: "2"
|
|
32
|
-
limits.cpu.allowance: 50%
|
|
33
|
-
limits.memory: 2GiB
|
|
34
|
-
cloud-init.user-data: |
|
|
35
|
-
#cloud-config
|
|
36
|
-
package_update: true
|
|
37
|
-
packages: [postgresql, postgresql-client]
|
|
38
|
-
runcmd:
|
|
39
|
-
- systemctl enable --now postgresql
|
|
40
|
-
description: "RC Cloud Clean Debian — postgres (D-<TRAINEE_USER>)"
|
|
41
|
-
devices:
|
|
42
|
-
data:
|
|
43
|
-
type: disk
|
|
44
|
-
pool: default
|
|
45
|
-
source: ""
|
|
46
|
-
path: /var/lib/postgresql
|
|
47
|
-
size: 20GiB
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### 2.3 Registrieren & prüfen
|
|
51
|
-
```bash
|
|
52
|
-
sudo incus profile create D-<TRAINEE_USER>
|
|
53
|
-
sudo incus profile edit D-<TRAINEE_USER> < ~/profile-D-<TRAINEE_USER>.yaml
|
|
54
|
-
sudo incus profile show D-<TRAINEE_USER>
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**Verständnisfrage 2 → `exam-pool.md` → `D_1`** (Profil von Grund auf) oder `D_4` (limits.cpu.allowance).
|
|
58
|
-
|
|
59
|
-
---
|
|
60
|
-
|
|
61
|
-
## Station 3 — Deployment & Verify (Track D)
|
|
62
|
-
|
|
63
|
-
```bash
|
|
64
|
-
sudo incus launch images:debian/13 c-D-<TRAINEE_USER> -p default -p D-<TRAINEE_USER>
|
|
65
|
-
sudo incus exec c-D-<TRAINEE_USER> -- cloud-init status --wait
|
|
66
|
-
```
|
|
67
|
-
Verifikation je nach Workload:
|
|
68
|
-
```bash
|
|
69
|
-
# postgres:
|
|
70
|
-
sudo incus exec c-D-<TRAINEE_USER> -- sudo -u postgres psql -c "SELECT version();"
|
|
71
|
-
# redis:
|
|
72
|
-
sudo incus exec c-D-<TRAINEE_USER> -- redis-cli ping
|
|
73
|
-
# quota-check:
|
|
74
|
-
sudo incus config show c-D-<TRAINEE_USER> | grep -E 'limits|size'
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
**Verständnisfrage 3 → `exam-pool.md` → `D_2`** (Snapshot/Migration).
|
|
78
|
-
|
|
79
|
-
---
|
|
80
|
-
|
|
81
|
-
## Station 4 — FastMCP & Guardrails
|
|
82
|
-
|
|
83
|
-
Gemeinsamer Ablauf. Track-D-Betonung: Lifecycle über MCP —
|
|
84
|
-
```
|
|
85
|
-
remoteos_manage_instance(container_name="c-D-<TRAINEE_USER>", action="stop", reason="Bootcamp D Lifecycle-Test")
|
|
86
|
-
remoteos_manage_instance(container_name="c-D-<TRAINEE_USER>", action="start", reason="Bootcamp D Lifecycle-Test")
|
|
87
|
-
```
|
|
88
|
-
`start`/`stop` → sofort (`RiskLevel.STAGING`). `restart`/`delete` → Queue.
|
|
89
|
-
|
|
90
|
-
**Track-Fragen:** `D_1`, `D_2`, `D_3`, `D_4`.
|
|
91
|
-
|
|
92
|
-
---
|
|
93
|
-
|
|
94
|
-
## Station 5 — Bewusst KEINE öffentliche Route (Track D)
|
|
95
|
-
|
|
96
|
-
Ein DB/Worker-Container gehört **nicht** ins öffentliche Internet. Zwei Optionen:
|
|
97
|
-
|
|
98
|
-
**Option 1 — nur intern über die Bridge:** Die App im selben Netz erreicht die DB über die Container-IP auf `incusbr0`. Nichts weiter zu tun.
|
|
99
|
-
|
|
100
|
-
**Option 2 — gezieltes Port-Forwarding zum Host (kein Caddy, kein DNS):**
|
|
101
|
-
```bash
|
|
102
|
-
sudo incus config device add c-D-<TRAINEE_USER> pg proxy \
|
|
103
|
-
listen=tcp:127.0.0.1:15432 connect=tcp:127.0.0.1:5432
|
|
104
|
-
```
|
|
105
|
-
→ DB nur auf `127.0.0.1:15432` des Hosts, erreichbar für lokale Prozesse / SSH-Tunnel, nie extern.
|
|
106
|
-
|
|
107
|
-
Wenn der Trainee doch eine Admin-Weboberfläche (pgAdmin) exponieren will → wie Track B, aber `require_auth=True` ist Pflicht und Cloudflare `🟠 proxied`.
|
|
108
|
-
|
|
109
|
-
**Verständnisfrage 5 → `exam-pool.md` → `D_3`** (keine öffentliche Route für DB).
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# Track E — Custom Workload (frei beschrieben)
|
|
2
|
-
|
|
3
|
-
**Auslöser:** Der Trainee hat in Station 0 „Other" / `E)` gewählt und seinen Workload in eigenen Worten beschrieben.
|
|
4
|
-
**Ziel:** Aus dem Freitext ein reales, valides Incus-Profil ableiten und das Training an den passenden Basis-Track andocken.
|
|
5
|
-
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
## E.0 — Interview (nach dem Freitext)
|
|
9
|
-
|
|
10
|
-
Frage strukturiert nach, was im Freitext fehlt. Nutze `AskUserQuestion` / Text-Schema:
|
|
11
|
-
|
|
12
|
-
1. **Grundcharakter** → bestimmt das Basis-Muster:
|
|
13
|
-
- „öffentlich per HTTP(S) erreichbar, mit Login" → **B-Muster** (Caddy + Authelia + Cloudflare proxied)
|
|
14
|
-
- „E-Mail / SMTP / IMAP" → **C-Muster** (DNS-Blueprint, DNS-only)
|
|
15
|
-
- „nur intern / Datenbank / Worker / Batch" → **D-Muster** (keine öffentliche Route)
|
|
16
|
-
- „autonome Agenten / Code-Ausführung" → **A-Muster** (rbash, ai_agents, agent-sudo)
|
|
17
|
-
2. **Ressourcen:** RAM (1–8 GiB), CPU (1–2), CPU-Deckel (50/100 %), Disk (10–60 GiB)
|
|
18
|
-
3. **Pakete:** welche Dienste/Runtimes? (Freitext-Liste, Generator validiert gegen Debian-13-Paketnamen und warnt bei Unbekanntem)
|
|
19
|
-
4. **Ports:** welche TCP-Ports lauscht der Dienst? intern / öffentlich?
|
|
20
|
-
5. **Auth:** braucht der öffentliche Endpunkt Authelia-2FA? (Default: ja, wenn öffentlich)
|
|
21
|
-
6. **Persistenz:** eigener Daten-`devices:`-Block? (Default ja bei DB-artigen Workloads)
|
|
22
|
-
|
|
23
|
-
Speichere: `<E_BASE>` ∈ {A, B, C, D}.
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
|
-
## E.1 — Profil generieren
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
python3 ~/.agents/skills/bdbsaastraining/scripts/build_profile.py \
|
|
31
|
-
--track E --user <TRAINEE_USER> \
|
|
32
|
-
--base <E_BASE> \
|
|
33
|
-
--ram <N> --cpu <N> --cpu-allowance <50|100> --disk <N> \
|
|
34
|
-
--packages "pkg1,pkg2,pkg3" \
|
|
35
|
-
--ports "8000/public,9000/internal" \
|
|
36
|
-
--auth <yes|no> --data-device <yes|no> \
|
|
37
|
-
--describe "<originaler Freitext des Trainees>"
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Der Generator:
|
|
41
|
-
- nimmt das `<E_BASE>`-Template als Ausgangsbasis (bzw. ein Minimal-Skelett bei `--base D`),
|
|
42
|
-
- ersetzt `packages:` durch die validierte Liste,
|
|
43
|
-
- setzt `limits.*` aus den Sizing-Antworten,
|
|
44
|
-
- **warnt** (nicht abbricht) bei: `ram > 8`, `disk > 100`, unbekannten Paketnamen, öffentlichem Port ohne `--auth yes`,
|
|
45
|
-
- entfernt Top-Level `name:`,
|
|
46
|
-
- schreibt `~/profile-E-<TRAINEE_USER>.yaml` + zeilenweise Erklärung + Liste aller Warnungen.
|
|
47
|
-
|
|
48
|
-
Bei `ram > 8`: Hinweis, dass der Primary-Node (`ram_gb ≤ 8` im MCP-Schema) das nicht trägt → Workload auf Auxiliary-Node (Oracle, 24 GB) planen.
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## E.2 — Station 2 / 3 / 5 nach Basis-Muster
|
|
53
|
-
|
|
54
|
-
Ab hier folgst du der Datei des Basis-Tracks `<E_BASE>` für Struktur und Befehle, aber mit den Custom-Werten:
|
|
55
|
-
|
|
56
|
-
| `<E_BASE>` | Station 2/3 wie | Station 5 wie |
|
|
57
|
-
| :-- | :-- | :-- |
|
|
58
|
-
| A | `track-a-ai-agent.md` (rbash-User, Sandbox-Task) | interne Gateway-Route, `require_auth=True` |
|
|
59
|
-
| B | `track-b-wordpress.md` (Stack-Verify per `curl`) | öffentliche Route, Caddy forward_auth, CF `🟠 proxied` |
|
|
60
|
-
| C | `track-c-mailserver.md` (`postconf`, Ports) | `remoteos_get_dns_blueprint(service_type="mail")`, `⚪ DNS-only` |
|
|
61
|
-
| D | `track-d-debian.md` (minimal, Quotas, Snapshot) | keine öffentliche Route / `incus proxy` Device |
|
|
62
|
-
|
|
63
|
-
Container-Name: `c-E-<TRAINEE_USER>` · Profil: `E-<TRAINEE_USER>`.
|
|
64
|
-
|
|
65
|
-
Verifikation immer zuerst:
|
|
66
|
-
```bash
|
|
67
|
-
sudo incus profile show E-<TRAINEE_USER>
|
|
68
|
-
sudo incus launch images:debian/13 c-E-<TRAINEE_USER> -p default -p E-<TRAINEE_USER>
|
|
69
|
-
sudo incus exec c-E-<TRAINEE_USER> -- cloud-init status --wait
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
---
|
|
73
|
-
|
|
74
|
-
## E.3 — Station 4 (gemeinsam)
|
|
75
|
-
|
|
76
|
-
Wie in `SKILL.md`, mit `container_name="c-E-<TRAINEE_USER>"` und Pflichtfeld `reason`.
|
|
77
|
-
|
|
78
|
-
---
|
|
79
|
-
|
|
80
|
-
## Prüfung — Track E
|
|
81
|
-
|
|
82
|
-
**Track-Fragen:** `E_1`, `E_2`, `E_3`, `E_4` (aus `exam-pool.md`).
|
|
83
|
-
Zusätzlich: Wenn `<E_BASE>` z. B. `B` war, darf der Tutor bis zu 2 der 4 Track-Fragen durch passende `B_*`-Fragen ersetzen, damit die Prüfung zum tatsächlich Gelernten passt. Immer 6 Kern + 4 Track = 10.
|