@hybridlabor-api/aos 4.6.5 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/agents.md +1 -0
- package/.agents/nodes.json +5 -1
- package/.agents/state.schema.json +2 -1
- package/.agents/vendor-manifest.json +50 -0
- package/.claude/agents/architect.md +4 -0
- package/.claude/agents/security-reviewer.md +1 -1
- package/.claude/hooks/memb-inject.mjs +257 -135
- package/.claude/hooks/trail-relay.mjs +18 -0
- package/.claude/settings.json +70 -0
- package/.claude/workflows/startcycle-dispatch.mjs +29 -1
- package/.opencode/agents/architect.md +4 -0
- package/.opencode/plugins/bdb-aos.js +75 -0
- package/THIRD_PARTY_NOTICES.md +48 -0
- package/bin/aos-config.mjs +3 -1
- package/bin/aos-uninstall.mjs +55 -1
- package/docs/handover/agenttrail-for-ao.md +58 -0
- package/docs/handover/deja-for-ao.md +51 -0
- package/installer.js +257 -56
- package/mcp_config.json +4 -0
- package/mcps/mcsc/README.md +24 -0
- package/mcps/mcsc/package-lock.json +1234 -0
- package/mcps/mcsc/package.json +14 -0
- package/mcps/mcsc/packages/core/bin/mcsc.js +162 -0
- package/mcps/mcsc/packages/core/rulebook.default.yaml +49 -0
- package/mcps/mcsc/packages/core/schema/rulebook.schema.json +56 -0
- package/mcps/mcsc/packages/core/src/adapters/agy.js +107 -0
- package/mcps/mcsc/packages/core/src/adapters/codex.js +56 -0
- package/mcps/mcsc/packages/core/src/adapters/native.js +14 -0
- package/mcps/mcsc/packages/core/src/adapters/opencode.js +183 -0
- package/mcps/mcsc/packages/core/src/adapters/types.js +21 -0
- package/mcps/mcsc/packages/core/src/capabilities/buildOfferTable.js +34 -0
- package/mcps/mcsc/packages/core/src/capabilities/registry.js +99 -0
- package/mcps/mcsc/packages/core/src/capabilities/types.js +24 -0
- package/mcps/mcsc/packages/core/src/detect/cache.js +47 -0
- package/mcps/mcsc/packages/core/src/detect/inventory.js +73 -0
- package/mcps/mcsc/packages/core/src/detect/probes.js +158 -0
- package/mcps/mcsc/packages/core/src/detect/types.js +26 -0
- package/mcps/mcsc/packages/core/src/rulebook/load.js +53 -0
- package/mcps/mcsc/packages/core/src/rulebook/resolve.js +227 -0
- package/mcps/mcsc/packages/core/src/rulebook/rulebook.types.js +89 -0
- package/mcps/mcsc/packages/core/src/trail.js +17 -0
- package/mcps/mcsc/packages/mcp/server.js +302 -0
- package/mcps/mcsc/server.js +2 -0
- package/package.json +3 -1
- package/skills/basic/bdbmediastorm/SKILL.md +1 -1
- package/skills/basic/godmode-ui-ux/SKILL.md +2 -2
- package/skills/basic/godmode-ui-ux/references/anti-slop-rules.md +44 -40
- package/skills/basic/godmode-ui-ux/references/taste-archetypes.md +49 -0
- package/skills/basic/startcycle/SKILL.md +7 -0
- package/skills/basic/startcycle-graph/SKILL.md +12 -0
- package/skills/basic/startcycle-graph-user/SKILL.md +3 -0
- package/skills/basic/teamwork-preview/SKILL.md +2 -0
- package/skills/bdbrainstorm/SKILL.md +1 -0
- package/skills/global_config/agenttrail/LICENSE +21 -0
- package/skills/global_config/agenttrail/SKILL.md +48 -0
- package/skills/global_config/agenttrail/bin/agenttrail.mjs +1002 -0
- package/skills/global_config/agenttrail/public/index.html +661 -0
- package/skills/global_config/aos-project-init/SKILL.md +25 -5
- package/skills/global_config/aos-project-init/scripts/aos-project-doctor.mjs +11 -0
- package/skills/global_config/aos-setup/SKILL.md +34 -1
- package/skills/global_config/aos-setup/scripts/aos-doctor.mjs +115 -1
- package/skills/global_config/archify/LICENSE +22 -0
- package/skills/global_config/archify/SKILL.md +140 -0
- package/skills/global_config/archify/THIRD_PARTY_NOTICES.md +69 -0
- package/skills/global_config/archify/assets/JetBrainsMono-OFL.txt +93 -0
- package/skills/global_config/archify/assets/template.html +14937 -0
- package/skills/global_config/archify/bin/archify.mjs +2139 -0
- package/skills/global_config/archify/bin/open-artifact.mjs +86 -0
- package/skills/global_config/archify/bin/preview.mjs +653 -0
- package/skills/global_config/archify/bin/visual-check.mjs +829 -0
- package/skills/global_config/archify/brand-marks/README.md +31 -0
- package/skills/global_config/archify/brand-marks/catalog.json +131 -0
- package/skills/global_config/archify/delta/architecture-delta.mjs +1232 -0
- package/skills/global_config/archify/examples/agent-run.lifecycle.json +60 -0
- package/skills/global_config/archify/examples/agent-tool-call.workflow.json +94 -0
- package/skills/global_config/archify/examples/async-job-roundtrip.sequence.json +61 -0
- package/skills/global_config/archify/examples/brand-aware-delivery.architecture.json +47 -0
- package/skills/global_config/archify/examples/cache-miss-request.sequence.json +82 -0
- package/skills/global_config/archify/examples/checkout-platform.base.architecture.json +31 -0
- package/skills/global_config/archify/examples/checkout-platform.head.architecture.json +31 -0
- package/skills/global_config/archify/examples/deployment-release.lifecycle.json +49 -0
- package/skills/global_config/archify/examples/event-stream.dataflow.json +57 -0
- package/skills/global_config/archify/examples/incident-response.workflow.json +64 -0
- package/skills/global_config/archify/examples/product-analytics.dataflow.json +76 -0
- package/skills/global_config/archify/examples/production-deployment.architecture.json +71 -0
- package/skills/global_config/archify/examples/release-delivery.workflow.json +62 -0
- package/skills/global_config/archify/examples/web-app.architecture.json +46 -0
- package/skills/global_config/archify/migrations/workflow-v2.mjs +279 -0
- package/skills/global_config/archify/package.json +39 -0
- package/skills/global_config/archify/recipes/scenarios.mjs +391 -0
- package/skills/global_config/archify/references/authoring-contract.md +247 -0
- package/skills/global_config/archify/references/brand-marks.md +65 -0
- package/skills/global_config/archify/references/delivery-contract.md +138 -0
- package/skills/global_config/archify/references/viewer-runtime.md +45 -0
- package/skills/global_config/archify/renderers/architecture/grid.mjs +62 -0
- package/skills/global_config/archify/renderers/architecture/render-architecture.mjs +1078 -0
- package/skills/global_config/archify/renderers/dataflow/README.md +104 -0
- package/skills/global_config/archify/renderers/dataflow/render-dataflow.mjs +483 -0
- package/skills/global_config/archify/renderers/lifecycle/README.md +115 -0
- package/skills/global_config/archify/renderers/lifecycle/render-lifecycle.mjs +561 -0
- package/skills/global_config/archify/renderers/sequence/README.md +114 -0
- package/skills/global_config/archify/renderers/sequence/render-sequence.mjs +464 -0
- package/skills/global_config/archify/renderers/shared/brand-marks.mjs +563 -0
- package/skills/global_config/archify/renderers/shared/cli.mjs +218 -0
- package/skills/global_config/archify/renderers/shared/desktop-readability.mjs +26 -0
- package/skills/global_config/archify/renderers/shared/diagnostics.mjs +160 -0
- package/skills/global_config/archify/renderers/shared/engineering-profiles.mjs +157 -0
- package/skills/global_config/archify/renderers/shared/generated-brand-marks.mjs +2003 -0
- package/skills/global_config/archify/renderers/shared/generated-validators.mjs +13 -0
- package/skills/global_config/archify/renderers/shared/geometry.mjs +1423 -0
- package/skills/global_config/archify/renderers/shared/i18n.mjs +595 -0
- package/skills/global_config/archify/renderers/shared/layout-report.mjs +40 -0
- package/skills/global_config/archify/renderers/shared/legend.mjs +217 -0
- package/skills/global_config/archify/renderers/shared/output-path.mjs +340 -0
- package/skills/global_config/archify/renderers/shared/repository-evidence.mjs +239 -0
- package/skills/global_config/archify/renderers/shared/repository-location.mjs +58 -0
- package/skills/global_config/archify/renderers/shared/text-fit.mjs +49 -0
- package/skills/global_config/archify/renderers/shared/utils.mjs +232 -0
- package/skills/global_config/archify/renderers/shared/validator.mjs +86 -0
- package/skills/global_config/archify/renderers/workflow/README.md +223 -0
- package/skills/global_config/archify/renderers/workflow/render-workflow.mjs +35 -0
- package/skills/global_config/archify/renderers/workflow/workflow-compiler.mjs +4400 -0
- package/skills/global_config/archify/renderers/workflow/workflow-migration-geometry.mjs +144 -0
- package/skills/global_config/archify/schemas/README.md +211 -0
- package/skills/global_config/archify/schemas/architecture.schema.json +178 -0
- package/skills/global_config/archify/schemas/common.schema.json +115 -0
- package/skills/global_config/archify/schemas/dataflow.schema.json +243 -0
- package/skills/global_config/archify/schemas/lifecycle.schema.json +266 -0
- package/skills/global_config/archify/schemas/sequence.schema.json +223 -0
- package/skills/global_config/archify/schemas/workflow.schema.json +428 -0
- package/skills/global_config/archify/scripts/check-render-output.mjs +916 -0
- package/skills/global_config/archify/scripts/generate-brand-marks.mjs +141 -0
- package/skills/global_config/archify/scripts/generate-validators.mjs +66 -0
- package/skills/global_config/archify/scripts/render-examples.mjs +26 -0
- package/skills/global_config/archify/skill-release.json +10 -0
- package/skills/global_config/bdb-security-audit/SKILL.md +109 -0
- package/skills/global_config/bdb-security-audit/references/audit-checklists.md +172 -0
- package/skills/global_config/bdb-security-audit/references/skylos-guide.md +139 -0
- package/skills/global_config/bdb-security-audit/references/xalgorix-bridge.md +110 -0
- package/skills/global_config/bdbdesignpro/SKILL.md +4 -4
- package/skills/global_config/bdbdesignpro/references/bdb-motion-tokens.md +52 -31
- package/skills/global_config/bdbresilience/SKILL.md +10 -0
- package/skills/global_config/brag/SKILL.md +179 -0
- package/skills/global_config/brag/assets/music/README.md +20 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.json +3846 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-1-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.json +1826 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-10-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.json +2266 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-11-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.json +2806 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-12-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.json +2796 -0
- package/skills/global_config/brag/assets/music/cues/happy-beats-business-moves-vol-9-by-ende-dot-app.music-cues.md +35 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-1-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-10-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-11-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-12-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/music/happy-beats-business-moves-vol-9-by-ende-dot-app.mp3 +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-fan-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-fan-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-place-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shove-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-shuffle.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-7.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/card-slide-8.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/cards-pack-open-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chip-lay-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chip-lay-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chip-lay-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-collide-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-handle-6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/chips-stack-6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-grab-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-grab-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-shake-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-shake-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-shake-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-throw-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-throw-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/dice-throw-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/casino/die-throw-4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_carpet_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_concrete_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_grass_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_snow_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/footstep_wood_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactBell_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGeneric_light_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactGlass_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMetal_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactMining_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlank_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_light_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPlate_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactPunch_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactSoft_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactTin_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_heavy_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_light_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_000.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/impact/impactWood_medium_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/bong_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/click_005.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/drop_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/drop_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/drop_003.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/error_005.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/error_006.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/glitch_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/glitch_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/select_008.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_001.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_002.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_004.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_005.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_006.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/interface/switch_007.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-001.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-002.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-003.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-004.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-005.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-006.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-007.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-008.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-009.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-010.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-011.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-012.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-013.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-014.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-015.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-016.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-017.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-018.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-019.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-020.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-021.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-022.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-023.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-024.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-025.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-026.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-027.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-028.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-029.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-030.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-031.wav +0 -0
- package/skills/global_config/brag/assets/sfx/keyboard/keypress-032.wav +0 -0
- package/skills/global_config/brag/assets/sfx/sfx-analysis.json +15584 -0
- package/skills/global_config/brag/assets/sfx/sfx-analysis.md +75 -0
- package/skills/global_config/brag/assets/sfx/ui/click1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/click5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/mouseclick1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/rollover5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch1.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch10.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch11.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch12.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch13.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch14.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch15.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch16.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch17.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch18.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch19.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch2.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch20.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch21.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch22.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch23.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch24.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch25.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch26.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch27.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch28.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch29.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch3.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch30.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch31.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch32.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch33.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch34.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch35.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch36.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch37.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch38.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch4.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch5.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch6.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch7.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch8.ogg +0 -0
- package/skills/global_config/brag/assets/sfx/ui/switch9.ogg +0 -0
- package/skills/global_config/brag/references/audio.md +307 -0
- package/skills/global_config/brag/references/step-1-inspect.md +133 -0
- package/skills/global_config/brag/references/step-2-plan.md +234 -0
- package/skills/global_config/brag/references/step-3-compose.md +210 -0
- package/skills/global_config/brag/references/step-4-deliver.md +168 -0
- package/skills/global_config/brag/references/tones.md +231 -0
- package/skills/global_config/brag/scripts/analyze_music_cues.py +309 -0
- package/skills/global_config/brag/scripts/pyproject.toml +14 -0
- package/skills/global_config/brag/scripts/uv.lock +819 -0
- package/skills/global_config/deja-memory/SKILL.md +42 -0
- package/skills/global_config/editable-design/LICENSE +202 -0
- package/skills/global_config/editable-design/README.md +34 -0
- package/skills/global_config/editable-design/SKILL.md +630 -0
- package/skills/global_config/editable-design/THIRD_PARTY_NOTICES.md +10 -0
- package/skills/global_config/editable-design/agents/openai.yaml +4 -0
- package/skills/global_config/editable-design/assets/editor/layer-editor.css +262 -0
- package/skills/global_config/editable-design/assets/editor/layer-editor.js +1929 -0
- package/skills/global_config/editable-design/assets/poster-starter/README.md +92 -0
- package/skills/global_config/editable-design/assets/poster-starter/assets/.gitkeep +0 -0
- package/skills/global_config/editable-design/assets/poster-starter/index.html +91 -0
- package/skills/global_config/editable-design/assets/poster-starter/poster.json +6 -0
- package/skills/global_config/editable-design/assets/poster-starter/reference/.gitkeep +1 -0
- package/skills/global_config/editable-design/assets/replay/icons/assets.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/html.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/input.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/layers.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/plan.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/reference.png +0 -0
- package/skills/global_config/editable-design/assets/replay/icons/review.png +0 -0
- package/skills/global_config/editable-design/assets/replay/index.html +59 -0
- package/skills/global_config/editable-design/assets/replay/replay-motion.js +410 -0
- package/skills/global_config/editable-design/assets/replay/replay.css +380 -0
- package/skills/global_config/editable-design/assets/replay/replay.js +374 -0
- package/skills/global_config/editable-design/font-kit/package-lock.json +115 -0
- package/skills/global_config/editable-design/font-kit/package.json +19 -0
- package/skills/global_config/editable-design/pack.sh +20 -0
- package/skills/global_config/editable-design/references/asset-architecture.md +72 -0
- package/skills/global_config/editable-design/references/editor-pitfalls.md +70 -0
- package/skills/global_config/editable-design/references/editor-runtime.md +131 -0
- package/skills/global_config/editable-design/references/font-system.md +89 -0
- package/skills/global_config/editable-design/references/imagery.md +145 -0
- package/skills/global_config/editable-design/references/layout-typography.md +116 -0
- package/skills/global_config/editable-design/references/replay-contract.md +169 -0
- package/skills/global_config/editable-design/scripts/_browser.mjs +247 -0
- package/skills/global_config/editable-design/scripts/bake.mjs +87 -0
- package/skills/global_config/editable-design/scripts/build-replay.mjs +316 -0
- package/skills/global_config/editable-design/scripts/check-contract.mjs +293 -0
- package/skills/global_config/editable-design/scripts/check-fonts.sh +252 -0
- package/skills/global_config/editable-design/scripts/check-poster.sh +70 -0
- package/skills/global_config/editable-design/scripts/doctor.sh +78 -0
- package/skills/global_config/editable-design/scripts/explode.mjs +115 -0
- package/skills/global_config/editable-design/scripts/font-kit.mjs +187 -0
- package/skills/global_config/editable-design/scripts/import-asset.sh +23 -0
- package/skills/global_config/editable-design/scripts/init-poster.sh +64 -0
- package/skills/global_config/editable-design/scripts/install-font-kit.sh +13 -0
- package/skills/global_config/editable-design/scripts/package-lock.json +334 -0
- package/skills/global_config/editable-design/scripts/package.json +14 -0
- package/skills/global_config/editable-design/scripts/remove-chroma-key.py +201 -0
- package/skills/global_config/editable-design/scripts/render-poster.sh +202 -0
- package/skills/global_config/editable-design/scripts/trace.sh +159 -0
- package/skills/global_config/editable-design/scripts/verify-replay.mjs +97 -0
- package/skills/global_config/editable-design/scripts/verify.mjs +782 -0
- package/skills/global_config/editable-design/scripts/wire-editor.mjs +104 -0
- package/skills/global_config/editable-design/tests/fixtures/small-explode/index.html +86 -0
- package/skills/global_config/plan-canvas/SKILL.md +8 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import * as simpleIcons from 'simple-icons';
|
|
7
|
+
|
|
8
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const root = path.resolve(here, '..');
|
|
10
|
+
const catalogPath = path.join(root, 'brand-marks', 'catalog.json');
|
|
11
|
+
const outputPath = path.join(root, 'renderers', 'shared', 'generated-brand-marks.mjs');
|
|
12
|
+
const catalog = JSON.parse(fs.readFileSync(catalogPath, 'utf8'));
|
|
13
|
+
const simpleIconsVersion = JSON.parse(fs.readFileSync(
|
|
14
|
+
path.join(root, 'node_modules', 'simple-icons', 'package.json'),
|
|
15
|
+
'utf8',
|
|
16
|
+
)).version;
|
|
17
|
+
const simpleBySlug = new Map(Object.values(simpleIcons)
|
|
18
|
+
.filter((icon) => icon && typeof icon === 'object' && icon.slug && icon.path)
|
|
19
|
+
.map((icon) => [icon.slug, icon]));
|
|
20
|
+
|
|
21
|
+
function normalizedList(value) {
|
|
22
|
+
return [...new Set((Array.isArray(value) ? value : [])
|
|
23
|
+
.map((item) => String(item).trim())
|
|
24
|
+
.filter(Boolean))];
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function lookupForms(value) {
|
|
28
|
+
const raw = String(value ?? '').trim().toLocaleLowerCase('en-US');
|
|
29
|
+
if (!raw) return [];
|
|
30
|
+
return [...new Set([
|
|
31
|
+
raw,
|
|
32
|
+
raw.replace(/[\s_]+/g, '-'),
|
|
33
|
+
raw.replace(/[\s_.-]+/g, ''),
|
|
34
|
+
])];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function fail(message) {
|
|
38
|
+
console.error(`brand catalog: ${message}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
if (catalog.schemaVersion !== 1 || !Array.isArray(catalog.marks) || catalog.marks.length === 0) {
|
|
43
|
+
fail('catalog.json must contain a non-empty schemaVersion 1 marks array');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const ids = new Set();
|
|
47
|
+
const lookupKeys = new Map();
|
|
48
|
+
const domains = new Map();
|
|
49
|
+
const generated = catalog.marks.map((entry, index) => {
|
|
50
|
+
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(entry.id || '')) fail(`marks[${index}] has an invalid id`);
|
|
51
|
+
if (ids.has(entry.id)) fail(`duplicate id ${entry.id}`);
|
|
52
|
+
ids.add(entry.id);
|
|
53
|
+
|
|
54
|
+
const aliases = normalizedList(entry.aliases);
|
|
55
|
+
const entryDomains = normalizedList(entry.domains).map((domain) => domain.toLowerCase());
|
|
56
|
+
for (const key of [entry.id, ...aliases]) {
|
|
57
|
+
for (const form of lookupForms(key)) {
|
|
58
|
+
if (lookupKeys.has(form) && lookupKeys.get(form) !== entry.id) {
|
|
59
|
+
fail(`lookup key ${JSON.stringify(key)} is shared by ${lookupKeys.get(form)} and ${entry.id}`);
|
|
60
|
+
}
|
|
61
|
+
lookupKeys.set(form, entry.id);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
for (const domain of entryDomains) {
|
|
65
|
+
if (domains.has(domain) && domains.get(domain) !== entry.id) {
|
|
66
|
+
fail(`domain ${domain} is shared by ${domains.get(domain)} and ${entry.id}`);
|
|
67
|
+
}
|
|
68
|
+
domains.set(domain, entry.id);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let mark;
|
|
72
|
+
if (entry.simpleIcon) {
|
|
73
|
+
const icon = simpleBySlug.get(entry.simpleIcon);
|
|
74
|
+
if (!icon) fail(`${entry.id} references missing Simple Icons slug ${entry.simpleIcon}`);
|
|
75
|
+
mark = {
|
|
76
|
+
id: entry.id,
|
|
77
|
+
title: entry.title || icon.title,
|
|
78
|
+
category: entry.category,
|
|
79
|
+
aliases,
|
|
80
|
+
domains: entryDomains,
|
|
81
|
+
viewBox: 24,
|
|
82
|
+
hex: icon.hex,
|
|
83
|
+
path: icon.path,
|
|
84
|
+
provenance: {
|
|
85
|
+
provider: 'Simple Icons',
|
|
86
|
+
providerVersion: simpleIconsVersion,
|
|
87
|
+
source: icon.source,
|
|
88
|
+
...(icon.guidelines ? { guidelines: icon.guidelines } : {}),
|
|
89
|
+
...(icon.license ? { license: icon.license } : {}),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
} else if (entry.custom) {
|
|
93
|
+
const custom = entry.custom;
|
|
94
|
+
if (!entry.title || !custom.path || !custom.source || !/^[0-9A-F]{6}$/i.test(custom.hex || '')) {
|
|
95
|
+
fail(`${entry.id} custom mark requires title, path, source, and six-digit hex`);
|
|
96
|
+
}
|
|
97
|
+
mark = {
|
|
98
|
+
id: entry.id,
|
|
99
|
+
title: entry.title,
|
|
100
|
+
category: entry.category,
|
|
101
|
+
aliases,
|
|
102
|
+
domains: entryDomains,
|
|
103
|
+
viewBox: custom.viewBox || 24,
|
|
104
|
+
hex: custom.hex.toUpperCase(),
|
|
105
|
+
path: custom.path,
|
|
106
|
+
provenance: {
|
|
107
|
+
provider: 'Official brand asset',
|
|
108
|
+
source: custom.source,
|
|
109
|
+
...(custom.guidelines ? { guidelines: custom.guidelines } : {}),
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
} else {
|
|
113
|
+
fail(`${entry.id} must provide simpleIcon or custom`);
|
|
114
|
+
}
|
|
115
|
+
if (!mark.category || !mark.title) fail(`${entry.id} is missing category or title`);
|
|
116
|
+
for (const form of lookupForms(mark.title)) {
|
|
117
|
+
if (lookupKeys.has(form) && lookupKeys.get(form) !== entry.id) {
|
|
118
|
+
fail(`title ${JSON.stringify(mark.title)} is shared by ${lookupKeys.get(form)} and ${entry.id}`);
|
|
119
|
+
}
|
|
120
|
+
lookupKeys.set(form, entry.id);
|
|
121
|
+
}
|
|
122
|
+
return mark;
|
|
123
|
+
}).sort((left, right) => left.id.localeCompare(right.id));
|
|
124
|
+
|
|
125
|
+
const banner = `// Generated by scripts/generate-brand-marks.mjs from brand-marks/catalog.json.\n// Simple Icons ${simpleIconsVersion}. Do not edit by hand.\n`;
|
|
126
|
+
const source = `${banner}export const BRAND_MARKS = Object.freeze(${JSON.stringify(generated, null, 2)});\n`;
|
|
127
|
+
|
|
128
|
+
if (process.argv.includes('--check')) {
|
|
129
|
+
const current = fs.existsSync(outputPath)
|
|
130
|
+
? fs.readFileSync(outputPath, 'utf8').replace(/\r\n?/g, '\n')
|
|
131
|
+
: '';
|
|
132
|
+
if (current !== source) {
|
|
133
|
+
console.error('generated brand marks are stale — run npm run generate:brand-marks');
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
const temporary = `${outputPath}.${process.pid}.tmp`;
|
|
138
|
+
fs.writeFileSync(temporary, source);
|
|
139
|
+
fs.renameSync(temporary, outputPath);
|
|
140
|
+
console.log(`generated ${path.relative(root, outputPath)} (${generated.length} marks)`);
|
|
141
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import Ajv2020 from 'ajv/dist/2020.js';
|
|
7
|
+
import standaloneCode from 'ajv/dist/standalone/index.js';
|
|
8
|
+
|
|
9
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
10
|
+
const root = path.resolve(__dirname, '..');
|
|
11
|
+
const schemasDir = path.join(root, 'schemas');
|
|
12
|
+
const output = path.join(root, 'renderers/shared/generated-validators.mjs');
|
|
13
|
+
const diagramTypes = ['workflow', 'sequence', 'dataflow', 'lifecycle', 'architecture'];
|
|
14
|
+
|
|
15
|
+
const ajv = new Ajv2020({
|
|
16
|
+
allErrors: true,
|
|
17
|
+
strict: true,
|
|
18
|
+
code: { source: true, esm: true },
|
|
19
|
+
});
|
|
20
|
+
ajv.addSchema(JSON.parse(fs.readFileSync(path.join(schemasDir, 'common.schema.json'), 'utf8')));
|
|
21
|
+
|
|
22
|
+
const schemaIds = {};
|
|
23
|
+
for (const type of diagramTypes) {
|
|
24
|
+
const schema = JSON.parse(fs.readFileSync(path.join(schemasDir, `${type}.schema.json`), 'utf8'));
|
|
25
|
+
ajv.addSchema(schema);
|
|
26
|
+
schemaIds[type] = schema.$id;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const banner = '// Generated by scripts/generate-validators.mjs. Do not edit by hand.\n';
|
|
30
|
+
const ajvUcs2Import = 'require("ajv/dist/runtime/ucs2length").default';
|
|
31
|
+
const inlineUcs2Length = `function ucs2length(str) {
|
|
32
|
+
const len = str.length;
|
|
33
|
+
let length = 0;
|
|
34
|
+
let pos = 0;
|
|
35
|
+
while (pos < len) {
|
|
36
|
+
length += 1;
|
|
37
|
+
const value = str.charCodeAt(pos++);
|
|
38
|
+
if (value >= 0xd800 && value <= 0xdbff && pos < len
|
|
39
|
+
&& (str.charCodeAt(pos) & 0xfc00) === 0xdc00) pos += 1;
|
|
40
|
+
}
|
|
41
|
+
return length;
|
|
42
|
+
}`;
|
|
43
|
+
let validatorCode = standaloneCode(ajv, schemaIds);
|
|
44
|
+
if (!validatorCode.includes(ajvUcs2Import)) {
|
|
45
|
+
throw new Error('AJV standalone output no longer contains the expected ucs2length helper');
|
|
46
|
+
}
|
|
47
|
+
validatorCode = validatorCode.replaceAll(ajvUcs2Import, inlineUcs2Length);
|
|
48
|
+
if (validatorCode.includes('require(')) {
|
|
49
|
+
throw new Error('AJV standalone output contains an unexpected runtime dependency');
|
|
50
|
+
}
|
|
51
|
+
const generated = `${banner}${validatorCode}\n`;
|
|
52
|
+
|
|
53
|
+
if (process.argv.includes('--check')) {
|
|
54
|
+
const current = fs.existsSync(output)
|
|
55
|
+
? fs.readFileSync(output, 'utf8').replace(/\r\n?/g, '\n')
|
|
56
|
+
: '';
|
|
57
|
+
if (current !== generated) {
|
|
58
|
+
console.error('generated validators are stale — run npm run generate:validators');
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
const temporary = `${output}.${process.pid}.tmp`;
|
|
63
|
+
fs.writeFileSync(temporary, generated);
|
|
64
|
+
fs.renameSync(temporary, output);
|
|
65
|
+
console.log(`generated ${path.relative(root, output)}`);
|
|
66
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Re-render every bundled example from its JSON IR. Installed skills keep HTML
|
|
2
|
+
// beside the JSON examples; the development script passes the golden directory.
|
|
3
|
+
|
|
4
|
+
import { execFileSync } from 'node:child_process';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const skillRoot = path.resolve(__dirname, '..');
|
|
10
|
+
const outputRoot = path.resolve(process.argv[2] || path.join(skillRoot, 'examples'));
|
|
11
|
+
|
|
12
|
+
const TARGETS = [
|
|
13
|
+
['workflow', 'agent-tool-call.workflow.json', 'workflow-agent-tool-call-rendered.html'],
|
|
14
|
+
['sequence', 'cache-miss-request.sequence.json', 'sequence-cache-miss-request.html'],
|
|
15
|
+
['dataflow', 'product-analytics.dataflow.json', 'dataflow-product-analytics.html'],
|
|
16
|
+
['lifecycle', 'agent-run.lifecycle.json', 'lifecycle-agent-run.html'],
|
|
17
|
+
['architecture', 'web-app.architecture.json', 'web-app-rendered.html'],
|
|
18
|
+
];
|
|
19
|
+
|
|
20
|
+
for (const [mode, input, output] of TARGETS) {
|
|
21
|
+
execFileSync(process.execPath, [
|
|
22
|
+
path.join(skillRoot, `renderers/${mode}/render-${mode}.mjs`),
|
|
23
|
+
path.join(skillRoot, 'examples', input),
|
|
24
|
+
path.join(outputRoot, output),
|
|
25
|
+
], { stdio: 'inherit' });
|
|
26
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"skillId": "archify",
|
|
4
|
+
"channel": "development",
|
|
5
|
+
"version": "2.17.0-dev.1",
|
|
6
|
+
"source": {
|
|
7
|
+
"repository": "https://github.com/tt-a1i/archify"
|
|
8
|
+
},
|
|
9
|
+
"updateManifestUrl": "https://tt-a1i.github.io/archify/skill-updates/archify/stable.json"
|
|
10
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bdb-security-audit
|
|
3
|
+
description: Comprehensive security auditing, diff analysis, defensive checklists, and vulnerability testing.
|
|
4
|
+
category: engineering-method
|
|
5
|
+
user-invocable: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# BDB Security Audit
|
|
9
|
+
|
|
10
|
+
Defensive security auditing for BDB projects. Use before commits, during PR review,
|
|
11
|
+
inside the Shipping quality gate, or whenever a codebase needs a structured security
|
|
12
|
+
pass. This skill is **defensive only**: it verifies, hardens, and reports. It never
|
|
13
|
+
produces attack tooling, exploit payloads, or offensive reconnaissance.
|
|
14
|
+
|
|
15
|
+
## The Three Pillars
|
|
16
|
+
|
|
17
|
+
| Pillar | What it is | When it runs |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **Skylos** | Diff and AST-level security analyzer for code changes. Catches dangerous call patterns, hardcoded credentials, and dead code that carries secrets — on staged files and PR diffs, before they land. | Pre-commit, PR review, Shipping gate |
|
|
20
|
+
| **Claude-Red Checklists** | Structured defensive audit checklists derived from red-team knowledge, inverted into verification questions. Covers OWASP Top 10, AuthN/AuthZ, injection classes, SSRF, LLM/agent security, and secret leakage. | Deep audits, new-feature review, release prep |
|
|
21
|
+
| **Xalgorix Bridge** | Decoupled connection to the `xalgorix` automated security suite. Discovered at runtime via `$PATH` or `XALGORIX_URL` — never hardcoded. Runs broader automated scans and returns findings. | Scheduled scans, pre-release sweeps, CI |
|
|
22
|
+
|
|
23
|
+
The pillars are independent. A machine may have none, one, or all three; every
|
|
24
|
+
workflow below degrades gracefully and must report "could not check" rather than
|
|
25
|
+
"checked, fine" when a tool is absent.
|
|
26
|
+
|
|
27
|
+
## When to Use
|
|
28
|
+
|
|
29
|
+
- "Audit this before I push" — run Skylos on the diff, then the relevant checklists.
|
|
30
|
+
- "Security review this PR" — `skylos diff` against the base branch, triage findings.
|
|
31
|
+
- Shipping gate step — Skylos must pass (or every finding must be dispositioned) before a release.
|
|
32
|
+
- "Is this endpoint/agent/tool safe?" — pull the matching section from `references/audit-checklists.md`.
|
|
33
|
+
- Periodic automated sweep — Xalgorix Bridge, if the suite is reachable.
|
|
34
|
+
|
|
35
|
+
## Workflow
|
|
36
|
+
|
|
37
|
+
### 1. Diff pass (always first, always cheap)
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
# Staged / uncommitted changes
|
|
41
|
+
skylos diff
|
|
42
|
+
|
|
43
|
+
# Whole tree, if no baseline exists
|
|
44
|
+
skylos scan .
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Verify the binary exists first — `command -v skylos` — and check `skylos --help`
|
|
48
|
+
for the flags your installed version supports. If skylos is absent, record
|
|
49
|
+
**"could not check"** and continue; do not silently treat the step as passed.
|
|
50
|
+
|
|
51
|
+
### 2. Checklist pass (targeted, human-driven)
|
|
52
|
+
|
|
53
|
+
Open `references/audit-checklists.md` and work only the sections the change
|
|
54
|
+
touches: touched auth code → Authentication & Session Management; new endpoint →
|
|
55
|
+
Input Validation + Infrastructure; new agent/tool surface → LLM & Agent Security.
|
|
56
|
+
Every item is phrased as a verification question. Mark each **pass / fail / not
|
|
57
|
+
applicable** — an unmarked item is not a pass.
|
|
58
|
+
|
|
59
|
+
### 3. Automated sweep (optional, decoupled)
|
|
60
|
+
|
|
61
|
+
```sh
|
|
62
|
+
# Discover the suite — never assume, never hardcode
|
|
63
|
+
command -v xalgorix || echo "not on PATH"
|
|
64
|
+
echo "${XALGORIX_URL:-not configured}"
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
If neither is present, skip and report. If present, run the scan per
|
|
68
|
+
`references/xalgorix-bridge.md` and forward findings to Reviewer/Shipping.
|
|
69
|
+
|
|
70
|
+
### 4. Report
|
|
71
|
+
|
|
72
|
+
Consolidate into one summary for Reviewer or Shipping:
|
|
73
|
+
|
|
74
|
+
- Per finding: file, line, severity, checklist or scanner origin, disposition (fix now / ticket / accepted risk).
|
|
75
|
+
- Per check: `pass`, `fail`, or `could not check` — never leave a check unreported.
|
|
76
|
+
- A gate verdict only from evidence: a passing report with two "could not check" rows is **not** a green gate.
|
|
77
|
+
|
|
78
|
+
## Commands Quick Reference
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
command -v skylos # pillar 1 present?
|
|
82
|
+
skylos diff # security scan of staged/changed code
|
|
83
|
+
skylos scan . # full-tree scan
|
|
84
|
+
skylos --help # confirm flags for your installed version
|
|
85
|
+
|
|
86
|
+
command -v xalgorix # pillar 3 on PATH?
|
|
87
|
+
echo "$XALGORIX_URL" # pillar 3 via remote endpoint?
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Guardrails
|
|
91
|
+
|
|
92
|
+
1. **Defensive posture only.** Findings describe what is wrong and how to fix it.
|
|
93
|
+
Never write or store exploit payloads, working attack strings, or recon steps —
|
|
94
|
+
not even in reports, tickets, or memory.
|
|
95
|
+
2. **No hardcoded paths.** Tools are discovered via `$PATH` or environment
|
|
96
|
+
variables (`XALGORIX_URL`). Skills, agents, and configs never contain absolute
|
|
97
|
+
machine paths.
|
|
98
|
+
3. **No secret leakage.** Audit outputs must redact credentials, tokens, and keys
|
|
99
|
+
found during scanning. Name the file and line, never the value.
|
|
100
|
+
4. **Honest gates.** "Could not check" is a distinct, reported state. Silent
|
|
101
|
+
degradation to "pass" is the defect class this skill exists to prevent.
|
|
102
|
+
5. **English only, minimal scope.** Reports state findings and fixes; they do not
|
|
103
|
+
lecture, and they do not expand scope beyond the diff or audit target.
|
|
104
|
+
|
|
105
|
+
## References
|
|
106
|
+
|
|
107
|
+
- [references/audit-checklists.md](references/audit-checklists.md) — the full defensive checklist set.
|
|
108
|
+
- [references/skylos-guide.md](references/skylos-guide.md) — installing, running, and interpreting Skylos; Shipping gate wiring.
|
|
109
|
+
- [references/xalgorix-bridge.md](references/xalgorix-bridge.md) — runtime discovery, decoupled configuration, scan reporting.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Defensive Audit Checklists
|
|
2
|
+
|
|
3
|
+
Derived from the Claude-Red body of knowledge, inverted into verification questions.
|
|
4
|
+
Every item is something an auditor **checks for presence and correctness** in the
|
|
5
|
+
defended codebase. Work only the sections the change or system under audit touches.
|
|
6
|
+
Mark each item `pass`, `fail`, or `n/a`; an unmarked item is not a pass, and a
|
|
7
|
+
section you could not verify is reported as **could not check**.
|
|
8
|
+
|
|
9
|
+
Severity guidance when a check fails:
|
|
10
|
+
|
|
11
|
+
| Severity | Meaning |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `blocking` | Exploitable by any untrusted party with the exposure the system already has. Fix before ship. |
|
|
14
|
+
| `high` | Exploitable with modest preconditions (a valid low-privilege account, a known config). Fix or ticket before ship. |
|
|
15
|
+
| `medium` | Requires special conditions or adds defense-in-depth gaps. Ticket. |
|
|
16
|
+
| `low` | Hygiene and hardening. Backlog. |
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 1. Authentication & Session Management
|
|
21
|
+
|
|
22
|
+
- [ ] Passwords are hashed with a dedicated password hash function (bcrypt, scrypt, or argon2 family) — never fast general-purpose hashes, never reversible encoding.
|
|
23
|
+
- [ ] Salt is unique per credential and generated by the hashing library itself.
|
|
24
|
+
- [ ] Password/secret comparison uses constant-time comparison functions, not `==`.
|
|
25
|
+
- [ ] Login, password reset, and MFA endpoints are rate-limited per account and per source, with exponential backoff or lockout.
|
|
26
|
+
- [ ] Authentication error messages do not reveal whether the account exists ("invalid credentials", not "unknown user").
|
|
27
|
+
- [ ] Session identifiers are regenerated on privilege change (login, password change, role elevation).
|
|
28
|
+
- [ ] Session cookies carry `Secure`, `HttpOnly`, and an appropriate `SameSite` attribute.
|
|
29
|
+
- [ ] Session lifetime and idle timeout are explicitly configured — no infinite sessions.
|
|
30
|
+
- [ ] Server-side session invalidation exists: logout actually destroys the session server-side, and "log out everywhere" is possible.
|
|
31
|
+
- [ ] Password reset tokens are single-use, short-lived, and invalidated on use or on new request.
|
|
32
|
+
- [ ] MFA, where present, is enforced server-side — client-side toggles cannot bypass it.
|
|
33
|
+
- [ ] JWTs (if used): algorithm is pinned server-side; signature, issuer, audience, and expiry are all verified; tokens are rejected after logout via a denylist or short lifetime.
|
|
34
|
+
- [ ] Service-to-service authentication uses scoped credentials (mTLS, signed tokens), not shared long-lived keys in config.
|
|
35
|
+
|
|
36
|
+
## 2. Authorization & Access Control (IDOR, BOLA)
|
|
37
|
+
|
|
38
|
+
- [ ] Every server-side handler performs its own authorization check — the client, frontend route guard, or API gateway is never the only gate.
|
|
39
|
+
- [ ] Object access resolves ownership from the **server-side session/identity**, never from a client-supplied user or account identifier alone.
|
|
40
|
+
- [ ] Sequential or guessable object identifiers (numeric IDs, slugs) are backed by an ownership/permission check, so direct object references cannot be swapped.
|
|
41
|
+
- [ ] Default authorization state is **deny**; new endpoints and new object types start inaccessible and are opened deliberately.
|
|
42
|
+
- [ ] Role/permission checks are centralized (one policy layer, middleware, or decorator) rather than re-implemented per handler.
|
|
43
|
+
- [ ] Privilege escalation paths checked: a lower-privileged role cannot invoke operations that only a higher role should reach, including via batch/bulk endpoints.
|
|
44
|
+
- [ ] Tenant isolation verified: every query that reads or writes multi-tenant data filters by tenant, including exports, search, and background jobs.
|
|
45
|
+
- [ ] Admin and internal-only endpoints are not reachable through alternate routes (old API versions, debug routers, secondary ports).
|
|
46
|
+
- [ ] File/record deletion and export operations re-check authorization at execution time, not only at link-rendering time.
|
|
47
|
+
- [ ] API responses return only fields the caller is entitled to — no over-fetching of other users' or internal fields.
|
|
48
|
+
|
|
49
|
+
## 3. Input Validation & Injection
|
|
50
|
+
|
|
51
|
+
### General
|
|
52
|
+
|
|
53
|
+
- [ ] All external input (query, body, headers, path segments, files, webhooks, message queues) is validated against an explicit schema at the trust boundary.
|
|
54
|
+
- [ ] Validation is allow-list shaped (type, length, range, format, enumeration) rather than deny-list filtering.
|
|
55
|
+
- [ ] Canonicalization happens before validation for anything that becomes a path, URL, or identifier.
|
|
56
|
+
|
|
57
|
+
### SQL injection
|
|
58
|
+
|
|
59
|
+
- [ ] Every query uses parameterized statements or a query builder/ORM binding — no string concatenation or f-string/format interpolation of user input into SQL, in **any** file, including "harmless" admin scripts.
|
|
60
|
+
- [ ] Dynamic ordering/filtering (sort column, filter name) maps through a fixed allow-list of column/field names, never through raw input.
|
|
61
|
+
- [ ] Stored procedures and raw-SQL escape hatches accept parameters, not concatenated fragments.
|
|
62
|
+
- [ ] Database accounts run with least privilege (no DDL, no cross-database access unless required).
|
|
63
|
+
|
|
64
|
+
### Command injection
|
|
65
|
+
|
|
66
|
+
- [ ] Shell invocation is avoided where a library/API call exists; when a subprocess is unavoidable, arguments are passed as an argument array — never through a single shell-parsed string.
|
|
67
|
+
- [ ] User input never reaches a shell interpreter, template engine `eval`, code `eval`, or dynamic deserialization of executable formats.
|
|
68
|
+
- [ ] Working directories and environment for spawned processes are pinned; inherited secrets are pruned from child-process environments.
|
|
69
|
+
|
|
70
|
+
### Server-Side Request Forgery (SSRF)
|
|
71
|
+
|
|
72
|
+
- [ ] Every outbound request built from user-supplied URLs validates scheme (https only, unless there is a documented exception) and resolves the host **before** connecting.
|
|
73
|
+
- [ ] Resolved addresses are checked against a deny-list: loopback, link-local, private ranges, and cloud metadata endpoints are blocked, with re-validation after every DNS resolution (DNS-rebinding defense).
|
|
74
|
+
- [ ] Redirects are followed only with re-validation of each hop, or not followed at all.
|
|
75
|
+
- [ ] Webhook and fetch-by-URL features apply the same outbound rules as direct user requests.
|
|
76
|
+
- [ ] Outbound requests run with credentials stripped — internal service tokens are never attached to requests whose target came from user input.
|
|
77
|
+
|
|
78
|
+
### Path traversal
|
|
79
|
+
|
|
80
|
+
- [ ] File paths built from user input are resolved and verified to remain inside the intended base directory (`realpath` + prefix check) — including archive members on extraction (zip-slip defense).
|
|
81
|
+
- [ ] Upload filenames are sanitized or replaced entirely (server-generated names); extension allow-lists are enforced, and uploads are stored outside any executable/web-served path.
|
|
82
|
+
- [ ] Download/export endpoints serve by internal identifier, never by client-supplied filesystem path.
|
|
83
|
+
- [ ] Symlink following is disabled or checked where the process writes into shared directories.
|
|
84
|
+
|
|
85
|
+
### Output encoding (companion to all of the above)
|
|
86
|
+
|
|
87
|
+
- [ ] Context-appropriate output encoding for HTML, attribute, JavaScript, URL, and CSS contexts — templating auto-escaping is on and not bypassed with raw/mark-safe constructs on user data.
|
|
88
|
+
- [ ] File download responses set a safe `Content-Type` and `Content-Disposition`; user-supplied data is never reflected into response headers unencoded.
|
|
89
|
+
|
|
90
|
+
## 4. LLM & Agent Security
|
|
91
|
+
|
|
92
|
+
Defends AI features (chat, copilots, autonomous agents, tool-using assistants) in the audited system.
|
|
93
|
+
|
|
94
|
+
### Prompt injection (direct)
|
|
95
|
+
|
|
96
|
+
- [ ] System instructions are separated from user content at the API level (dedicated system role/field), and user text is never concatenated into the system prompt.
|
|
97
|
+
- [ ] The model is not relied upon as the sole enforcement point: security decisions (authorization, data access, payments) are made in code, not by model output.
|
|
98
|
+
- [ ] Instructions that the model must treat as untrusted data are explicitly framed as such in the prompt design.
|
|
99
|
+
- [ ] Outputs that will be parsed (JSON, SQL, commands) come from structured/constrained generation or are schema-validated before use — free-text model output is never executed or interpolated into queries.
|
|
100
|
+
|
|
101
|
+
### Indirect injection
|
|
102
|
+
|
|
103
|
+
- [ ] Content fetched by the agent (web pages, documents, emails, tickets, repository files) is treated as untrusted input: it is quoted/delimited in prompts, never followed as instructions.
|
|
104
|
+
- [ ] Retrieved content is sanitized or summarized through a defensive pass before it can influence tool calls.
|
|
105
|
+
- [ ] Sources are labeled in context so the model (and reviewers of transcripts) can tell tool output from user intent.
|
|
106
|
+
- [ ] Agent browsing/fetch features enforce the same SSRF and URL allow-list rules as the rest of the system.
|
|
107
|
+
|
|
108
|
+
### Tool abuse
|
|
109
|
+
|
|
110
|
+
- [ ] Every tool exposed to the model declares a minimal scope (read-only vs write, which resources, which actions) and enforces it server-side.
|
|
111
|
+
- [ ] Destructive tools (delete, deploy, send, pay) require a confirmation step or policy check outside the model — model output alone can never trigger them.
|
|
112
|
+
- [ ] Tool arguments are validated with the same rigor as public API input: the model is one more untrusted client.
|
|
113
|
+
- [ ] Tool execution runs with least-privilege credentials, scoped per tool, never the operator's full identity.
|
|
114
|
+
- [ ] Loops are bounded: maximum iterations, maximum spend, maximum side effects per run; runaway agents halt safely.
|
|
115
|
+
|
|
116
|
+
### Insecure output handling
|
|
117
|
+
|
|
118
|
+
- [ ] Model output rendered in a browser is HTML-encoded like any other untrusted string (stored prompt injection → XSS is the same defect class).
|
|
119
|
+
- [ ] Model output used in code generation or config is reviewed/linted before execution; nothing is `eval`-ed.
|
|
120
|
+
- [ ] Generated SQL/commands are executed through the same parameterized/argument-array paths as above.
|
|
121
|
+
- [ ] Model transcripts and tool logs are stored with the same sensitivity rules as user data, and secrets reaching a transcript are redacted.
|
|
122
|
+
|
|
123
|
+
## 5. Secret Management & Sensitive Data Exposure
|
|
124
|
+
|
|
125
|
+
- [ ] No credentials, API keys, tokens, or connection strings in source, fixtures, seeds, tests, docs, or comments — scanners (Skylos and the platform secret scanner) run as the gate, and any finding is rotated, not just deleted (deletion does not un-leak git history).
|
|
126
|
+
- [ ] Secrets are provided at runtime via a secret manager or environment injection; `.env` files are gitignored, and only `.env.example` with placeholder values is committed.
|
|
127
|
+
- [ ] Secret values are never logged: log statements, error messages, and exception reports are audited for credential/PII leakage; verbose/debug logging cannot be enabled with secrets in scope in production.
|
|
128
|
+
- [ ] Different environments use different credentials; production secrets are not reachable from staging/dev code paths.
|
|
129
|
+
- [ ] PII is inventoried and minimized: fields collected have a purpose, storage is encrypted at rest where required, and retention/expiry is configured.
|
|
130
|
+
- [ ] Sensitive data in transit uses TLS everywhere, including internal service-to-service traffic.
|
|
131
|
+
- [ ] Client-visible payloads (API responses, error pages, source maps in production, bundled JS) do not contain internal identifiers, secrets, or debug data.
|
|
132
|
+
- [ ] Backups and exports containing sensitive data are encrypted and access-controlled like the primary store.
|
|
133
|
+
- [ ] Secret rotation is documented and tested: rotation does not require code changes or downtime, and old values are revoked after rotation.
|
|
134
|
+
- [ ] Dead code, commented-out blocks, and unused config branches that once held credentials are removed — they are the highest-signal residue an attacker greps for (this is a core Skylos target).
|
|
135
|
+
|
|
136
|
+
## 6. Infrastructure & API Security
|
|
137
|
+
|
|
138
|
+
### CORS
|
|
139
|
+
|
|
140
|
+
- [ ] CORS allow-list is explicit per origin — no wildcard origins on authenticated endpoints, no reflecting arbitrary `Origin` headers back with credentials allowed.
|
|
141
|
+
- [ ] Credentials-bearing cross-origin responses restrict `Access-Control-Allow-Origin` to enumerated trusted origins only.
|
|
142
|
+
- [ ] Preflight handling and allowed methods/headers are minimal — only what the frontend actually uses.
|
|
143
|
+
|
|
144
|
+
### Rate limiting & abuse controls
|
|
145
|
+
|
|
146
|
+
- [ ] Rate limits exist on all public endpoints, with tighter limits on auth, password reset, OTP, search, and generation endpoints (LLM endpoints also cap spend/tokens per user).
|
|
147
|
+
- [ ] Limits are enforced server-side at a shared layer (gateway, middleware, or edge), not per-instance in-memory where a second instance bypasses them.
|
|
148
|
+
- [ ] Request body size, upload size, pagination page size, and list depth are all capped.
|
|
149
|
+
- [ ] Long-running/expensive operations are queued with concurrency limits, not executed inline per request.
|
|
150
|
+
|
|
151
|
+
### Security headers & transport
|
|
152
|
+
|
|
153
|
+
- [ ] `Content-Security-Policy` set with no `unsafe-inline`/`unsafe-eval` where avoidable; `X-Content-Type-Options: nosniff`; `Referrer-Policy`; `Strict-Transport-Security` on all HTTPS responses.
|
|
154
|
+
- [ ] TLS versions and cipher configuration meet current guidance; certificates renew automatically.
|
|
155
|
+
- [ ] Framework debug modes, stack traces, and verbose error pages are disabled in production; errors return generic messages with a correlation ID logged server-side.
|
|
156
|
+
|
|
157
|
+
### API surface
|
|
158
|
+
|
|
159
|
+
- [ ] API versioning exists and deprecated versions are retired on a schedule — old versions run the current authorization code, not frozen vulnerable copies.
|
|
160
|
+
- [ ] Mass-assignment defense: request DTOs allow-list bindable fields; client JSON cannot set internal fields (role, tenant, price, owner).
|
|
161
|
+
- [ ] Error responses do not enumerate valid resources differently from invalid ones where that difference leaks account/data existence.
|
|
162
|
+
- [ ] Introspection/admin endpoints (API docs, health, metrics, actuator-style routes) are authenticated or network-restricted in production.
|
|
163
|
+
- [ ] Dependencies are pinned and scanned for known vulnerabilities on a schedule and in CI; the audit notes the last scan date and result.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Reporting Discipline
|
|
168
|
+
|
|
169
|
+
1. Record per item: `pass` / `fail` / `n/a` / `could not check` — with evidence (file:line) for every claim.
|
|
170
|
+
2. Never read back your own writes as evidence: the fact that a fix was written is not proof the check passes; re-verify after the fix.
|
|
171
|
+
3. Failures of `blocking`/`high` items stop the gate; the report goes to Reviewer/Shipping with disposition per finding.
|
|
172
|
+
4. Redact any secret values encountered — reference location, never content.
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Skylos Guide — Diff & AST Security Scanning
|
|
2
|
+
|
|
3
|
+
Skylos is pillar 1 of the BDB Security Audit skill: a static security analyzer that
|
|
4
|
+
works at the **AST level** (it parses code structure, not text) and supports
|
|
5
|
+
**diff mode**, so it can gate exactly the lines a PR or staging area touches.
|
|
6
|
+
Its role is a pre-commit and Shipping quality-gate check — the automated half of
|
|
7
|
+
`bdb-security-audit`, before the human-driven checklists run.
|
|
8
|
+
|
|
9
|
+
This guide covers installation, running, gate integration, and interpretation.
|
|
10
|
+
Command surface below reflects the two core entrypoints (`skylos scan`,
|
|
11
|
+
`skylos diff`); **always confirm flags against `skylos --help` for the installed
|
|
12
|
+
version** — do not assume flags from this document alone.
|
|
13
|
+
|
|
14
|
+
## 1. Installation
|
|
15
|
+
|
|
16
|
+
Skylos ships as a Python CLI package. Install it as an isolated tool so it does
|
|
17
|
+
not pollute project environments:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
# Preferred: isolated tool install
|
|
21
|
+
pipx install skylos
|
|
22
|
+
# or
|
|
23
|
+
uv tool install skylos
|
|
24
|
+
|
|
25
|
+
# Verify
|
|
26
|
+
command -v skylos
|
|
27
|
+
skylos --help
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If `command -v skylos` finds nothing, the pillar is **absent**: report
|
|
31
|
+
"could not check" for the scan step. Never fake a pass, and never hardcode an
|
|
32
|
+
install location into scripts or skills — install via the standard tool manager
|
|
33
|
+
so it lands on `$PATH`.
|
|
34
|
+
|
|
35
|
+
## 2. Running
|
|
36
|
+
|
|
37
|
+
### Diff mode — PRs and staged changes (primary use)
|
|
38
|
+
|
|
39
|
+
Diff mode scans only what changed, which keeps the signal high and the runtime low:
|
|
40
|
+
|
|
41
|
+
```sh
|
|
42
|
+
skylos diff # staged / uncommitted changes vs the baseline
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Typical review flow:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
git checkout feature-branch
|
|
49
|
+
skylos diff # security view of the branch's changes
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Run it before every push and as the first step of any PR security review.
|
|
53
|
+
Findings on diff mode are gate-relevant by default — the change introduced them.
|
|
54
|
+
|
|
55
|
+
### Full-tree mode — audits and baselines
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
skylos scan . # whole project, from the repo root
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Use full scans for: first-time audits, release preparation, and re-scanning after
|
|
62
|
+
a dependency or architecture change. Full scans surface legacy findings the diff
|
|
63
|
+
never touched; triage those into tickets rather than blocking the current PR on them.
|
|
64
|
+
|
|
65
|
+
### Version pinning in CI
|
|
66
|
+
|
|
67
|
+
Pin the version in CI/workflows so a scanner upgrade cannot silently change gate
|
|
68
|
+
behavior mid-release. Update the pin deliberately, review the new findings, then
|
|
69
|
+
bump.
|
|
70
|
+
|
|
71
|
+
## 3. Integration into the Shipping Quality Gate
|
|
72
|
+
|
|
73
|
+
Position Skylos as a **blocking** gate step, after lint/typecheck and before the
|
|
74
|
+
release decision:
|
|
75
|
+
|
|
76
|
+
```text
|
|
77
|
+
Build → Lint → Typecheck → [Skylos security scan] → Tests → Reviewer → Shipping
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Gate rules:
|
|
81
|
+
|
|
82
|
+
1. **Non-zero exit = gate failure.** A scanner that exits with findings must stop
|
|
83
|
+
the gate. Do not wrap the command in a way that swallows the exit code, and do
|
|
84
|
+
not `|| true` it. A discarded exit code is a swallowed failure.
|
|
85
|
+
2. **Empty output on a run that claims to have run is a failure**, not a pass —
|
|
86
|
+
the same rule as delegated CLIs: verify the finding list exists and names real
|
|
87
|
+
files, never trust a bare success status.
|
|
88
|
+
3. **Disposition every finding.** Each finding ends as `fixed`, `ticketed (link)`,
|
|
89
|
+
or `accepted risk (who accepted, why)`. An untriaged finding blocks the gate.
|
|
90
|
+
4. **"Could not check" is reported, not skipped.** If skylos is unavailable in the
|
|
91
|
+
gate environment, the gate report lists the step as `could not check` and the
|
|
92
|
+
release decision accounts for it — it must not read as green.
|
|
93
|
+
5. **Fixes re-scan.** After remediation, re-run the same scan command; the fix is
|
|
94
|
+
proven by the new scan output, not by the edit having been made.
|
|
95
|
+
|
|
96
|
+
## 4. Interpreting Findings: AST Security vs Style Lints
|
|
97
|
+
|
|
98
|
+
Skylos reads the AST, so its findings differ in kind from style-linter output.
|
|
99
|
+
Keep the two categories separate — they have different severities and different
|
|
100
|
+
dispositions:
|
|
101
|
+
|
|
102
|
+
| | Style lint | AST security finding |
|
|
103
|
+
|---|---|---|
|
|
104
|
+
| Source | Textual/format conventions | Code structure: data flow, call patterns, definitions |
|
|
105
|
+
| Examples | Naming, formatting, unused imports as a tidiness matter | Credential material in source, dangerous call patterns, dead code paths that retain secrets |
|
|
106
|
+
| Default severity | Advisory | Gate-blocking until dispositioned |
|
|
107
|
+
| Suppression | Fine, with a reason | Only via the scanner's explicit ignore mechanism **with an inline justification comment**; never by weakening lint config or filtering output |
|
|
108
|
+
|
|
109
|
+
Interpretation rules:
|
|
110
|
+
|
|
111
|
+
- **Hardcoded credential findings are always blocking.** Even test fixtures:
|
|
112
|
+
real-looking keys in tests train the habit and leak via public fixtures. Replace
|
|
113
|
+
with placeholders and rotate anything that was ever committed.
|
|
114
|
+
- **Dead-code findings are security-relevant, not cosmetic.** An unused function
|
|
115
|
+
that contains a connection string or an obsolete auth path is attack surface and
|
|
116
|
+
residue; removal is the fix, suppression is not.
|
|
117
|
+
- **Dangerous-call findings** (execution/serialization primitives reachable with
|
|
118
|
+
untrusted input) are validated against the checklist item that matches them —
|
|
119
|
+
see `references/audit-checklists.md` §3 and §4. The scanner says *where*;
|
|
120
|
+
the checklist decides *how bad, given the data flow*.
|
|
121
|
+
- **False positives:** suppress in the code at the finding site with a reason
|
|
122
|
+
(`# skylos: ignore — <why this input is trusted>`), never globally, never by
|
|
123
|
+
post-processing the report. A global filter hides tomorrow's real finding.
|
|
124
|
+
- **Findings vs the diff:** in diff mode, a finding means *this change* introduced
|
|
125
|
+
or reactivated the issue — treat it as belonging to the PR author's gate. A
|
|
126
|
+
finding that predates the branch is triaged out of the PR and ticketed.
|
|
127
|
+
|
|
128
|
+
## 5. Reporting to Reviewer/Shipping
|
|
129
|
+
|
|
130
|
+
The scan result enters the gate report as:
|
|
131
|
+
|
|
132
|
+
```text
|
|
133
|
+
Skylos: <pass | fail | could not check> (command: skylos diff, exit: N)
|
|
134
|
+
Findings:
|
|
135
|
+
- <file>:<line> — <rule/summary> — severity — disposition
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
One line per finding, every finding dispositioned, secrets redacted (name the
|
|
139
|
+
file and line, never the value).
|