@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,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**
|