From 808a8f07ba86a87b212f4eccbeda0fb7afe4c996 Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 10:56:01 -0500 Subject: [PATCH 1/7] docs(plans): added plan docs for developing the release bundle and its contents --- .ai/plans/bundle-contents.md | 328 +++ .ai/plans/checklists/gap-analysis.md | 173 ++ .../checklists/implementation-tracking.md | 248 +++ .ai/plans/checklists/testing-validation.md | 183 ++ .../bundle-contents-phase-00-manual-setup.md | 283 +++ .../bundle-contents-phase-01-foundation.md | 1843 +++++++++++++++++ ...undle-contents-phase-02-build-pipelines.md | 125 ++ .../bundle-contents-phase-03-code-quality.md | 721 +++++++ .../bundle-contents-phase-04-testing-unit.md | 131 ++ ...ndle-contents-phase-05-testing-property.md | 136 ++ ...e-contents-phase-06-testing-integration.md | 153 ++ .../bundle-contents-phase-07-testing-e2e.md | 167 ++ ...e-contents-phase-08-testing-performance.md | 137 ++ ...ndle-contents-phase-09-testing-coverage.md | 186 ++ ...contents-phase-10-testing-quality-gates.md | 148 ++ ...-contents-phase-11-testing-mcp-protocol.md | 164 ++ ...-contents-phase-12-testing-mock-harness.md | 173 ++ .../bundle-contents-phase-13-testing-chaos.md | 153 ++ ...contents-phase-14-security-dependencies.md | 279 +++ ...dle-contents-phase-15-security-licenses.md | 360 ++++ .../bundle-contents-phase-16-security-sast.md | 155 ++ ...ndle-contents-phase-17-security-secrets.md | 146 ++ ...undle-contents-phase-18-security-memory.md | 166 ++ ...ndle-contents-phase-19-security-fuzzing.md | 192 ++ ...bundle-contents-phase-20-security-taint.md | 172 ++ ...e-contents-phase-21-security-containers.md | 784 +++++++ ...e-contents-phase-22-security-compliance.md | 337 +++ ...undle-contents-phase-22a-policy-library.md | 807 ++++++++ ...-contents-phase-23-security-attestation.md | 406 ++++ ...le-contents-phase-24-release-versioning.md | 478 +++++ ...le-contents-phase-25-release-containers.md | 161 ++ ...ndle-contents-phase-26-release-packages.md | 188 ++ .../bundle-contents-phase-27-release-helm.md | 362 ++++ ...dle-contents-phase-28-automation-issues.md | 716 +++++++ ...tents-phase-29-automation-notifications.md | 196 ++ ...bundle-contents-phase-30-automation-mcp.md | 779 +++++++ .ai/plans/references/mcp-testing-taxonomy.md | 401 ++++ .ai/plans/references/quick-start.md | 266 +++ 38 files changed, 12803 insertions(+) create mode 100644 .ai/plans/bundle-contents.md create mode 100644 .ai/plans/checklists/gap-analysis.md create mode 100644 .ai/plans/checklists/implementation-tracking.md create mode 100644 .ai/plans/checklists/testing-validation.md create mode 100644 .ai/plans/phases/bundle-contents-phase-00-manual-setup.md create mode 100644 .ai/plans/phases/bundle-contents-phase-01-foundation.md create mode 100644 .ai/plans/phases/bundle-contents-phase-02-build-pipelines.md create mode 100644 .ai/plans/phases/bundle-contents-phase-03-code-quality.md create mode 100644 .ai/plans/phases/bundle-contents-phase-04-testing-unit.md create mode 100644 .ai/plans/phases/bundle-contents-phase-05-testing-property.md create mode 100644 .ai/plans/phases/bundle-contents-phase-06-testing-integration.md create mode 100644 .ai/plans/phases/bundle-contents-phase-07-testing-e2e.md create mode 100644 .ai/plans/phases/bundle-contents-phase-08-testing-performance.md create mode 100644 .ai/plans/phases/bundle-contents-phase-09-testing-coverage.md create mode 100644 .ai/plans/phases/bundle-contents-phase-10-testing-quality-gates.md create mode 100644 .ai/plans/phases/bundle-contents-phase-11-testing-mcp-protocol.md create mode 100644 .ai/plans/phases/bundle-contents-phase-12-testing-mock-harness.md create mode 100644 .ai/plans/phases/bundle-contents-phase-13-testing-chaos.md create mode 100644 .ai/plans/phases/bundle-contents-phase-14-security-dependencies.md create mode 100644 .ai/plans/phases/bundle-contents-phase-15-security-licenses.md create mode 100644 .ai/plans/phases/bundle-contents-phase-16-security-sast.md create mode 100644 .ai/plans/phases/bundle-contents-phase-17-security-secrets.md create mode 100644 .ai/plans/phases/bundle-contents-phase-18-security-memory.md create mode 100644 .ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md create mode 100644 .ai/plans/phases/bundle-contents-phase-20-security-taint.md create mode 100644 .ai/plans/phases/bundle-contents-phase-21-security-containers.md create mode 100644 .ai/plans/phases/bundle-contents-phase-22-security-compliance.md create mode 100644 .ai/plans/phases/bundle-contents-phase-22a-policy-library.md create mode 100644 .ai/plans/phases/bundle-contents-phase-23-security-attestation.md create mode 100644 .ai/plans/phases/bundle-contents-phase-24-release-versioning.md create mode 100644 .ai/plans/phases/bundle-contents-phase-25-release-containers.md create mode 100644 .ai/plans/phases/bundle-contents-phase-26-release-packages.md create mode 100644 .ai/plans/phases/bundle-contents-phase-27-release-helm.md create mode 100644 .ai/plans/phases/bundle-contents-phase-28-automation-issues.md create mode 100644 .ai/plans/phases/bundle-contents-phase-29-automation-notifications.md create mode 100644 .ai/plans/phases/bundle-contents-phase-30-automation-mcp.md create mode 100644 .ai/plans/references/mcp-testing-taxonomy.md create mode 100644 .ai/plans/references/quick-start.md diff --git a/.ai/plans/bundle-contents.md b/.ai/plans/bundle-contents.md new file mode 100644 index 0000000..e7350b5 --- /dev/null +++ b/.ai/plans/bundle-contents.md @@ -0,0 +1,328 @@ +--- +id: a8f2e4c1-3b9d-4e7f-8a6b-9c0d1e2f3a4b +title: "Bundle Expansion Overview" +status: active +created: 2025-12-05 +type: overview +--- + +# Bundle Expansion Overview + +## Purpose + +Expand the MCP template bundle to include comprehensive CI/CD workflows, templates, and configurations for multi-language projects with a focus on security, compliance, and automation. + +--- + +## Important Context + +> **This plan produces a versioned release artifact (bundle) for onboarding new repositories to "MCP Server Development" standards.** + +### Scope Clarification + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLANNING CONTEXT │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ DEFAULT: Template Development │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ All phases develop TEMPLATES, CONFIGS, and WORKFLOWS intended for │ +│ packaging into a versioned bundle. These artifacts are NOT directly │ +│ applied to the aRustyDev/mcp repository. │ +│ │ +│ Target: Unknown future repositories that will consume this bundle │ +│ │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ │ +│ EXCEPTION: aRustyDev/mcp Configuration │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Tasks explicitly marked with [MCP-REPO] are intended for direct │ +│ configuration of the aRustyDev/mcp repository itself. │ +│ │ +│ Example: "## [MCP-REPO] Configure branch protection" │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Bundle Output + +When implemented, this plan produces: + +| Artifact | Description | +|----------|-------------| +| `mcp-bundle-v{X.Y.Z}.tar.gz` | Versioned release archive | +| `MANIFEST.md` | Bundle contents and installation guide | +| `justfile` | Automated setup commands | +| `AGENT.md` | AI agent instructions for target repo | + +### Bundle Consumer Workflow + +``` +1. Download bundle release +2. Extract to target repository root +3. Run `just setup` for automated configuration +4. Complete Phase 00 manual steps +5. Customize templates as needed +``` + +### Tagging Convention + +- Template tasks: No special tag (default) +- aRustyDev/mcp tasks: `[MCP-REPO]` prefix in section header + +--- + +## Phase Gate: Justfile Review + +> **REQUIRED**: Before beginning ANY phase, conduct a justfile review conversation with the user. + +### Purpose + +This quality gate prevents the justfile from diverging or spiraling out of control during development. Each phase may add, modify, or refine justfile recipes, and regular review ensures coherent evolution. + +### Gate Process + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE GATE: JUSTFILE REVIEW │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ BEFORE starting Phase N: │ +│ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 1. JUSTFILE STATE REVIEW │ │ +│ │ ├── Present current justfile structure │ │ +│ │ ├── List all recipes and their purposes │ │ +│ │ ├── Identify recipes added in previous phases │ │ +│ │ └── Flag any complexity concerns │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 2. WORKFLOW COMPARISON │ │ +│ │ ├── Expected workflow (from plan) │ │ +│ │ ├── Current workflow (as implemented) │ │ +│ │ ├── Identify gaps or divergences │ │ +│ │ └── Discuss any scope changes │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 3. PHASE N PLANNING │ │ +│ │ ├── What justfile changes does Phase N require? │ │ +│ │ ├── What new recipes will be added? │ │ +│ │ ├── What existing recipes need modification? │ │ +│ │ └── How will this integrate with existing workflow? │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 4. USER APPROVAL │ │ +│ │ ├── User confirms understanding of current state │ │ +│ │ ├── User approves planned justfile changes │ │ +│ │ └── User provides any additional context or constraints │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 5. PROCEED WITH PHASE │ │ +│ │ └── Begin phase implementation │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Review Conversation Template + +When initiating a phase, start with: + +```markdown +## Phase N Gate: Justfile Review + +### Current Justfile State + +**Recipes implemented:** +- `just init ` - Main entry point (Phase 01) +- `just configure` - Interactive setup (Phase 01) +- ... [list all recipes] + +**Recent changes (Phase N-1):** +- Added: [recipes] +- Modified: [recipes] +- Removed: [recipes] + +### Workflow Comparison + +**Expected (from plan):** +[Describe what the plan says the workflow should be] + +**Current (as implemented):** +[Describe what the justfile actually does] + +**Divergences:** +- [List any differences] + +### Phase N Impact + +**Planned justfile changes:** +- [New recipes to add] +- [Existing recipes to modify] + +**Questions for user:** +1. [Any decisions needed] +2. [Any clarifications required] + +--- + +**Ready to proceed?** Please review and confirm. +``` + +### What to Review + +| Aspect | Questions to Address | +|--------|---------------------| +| **Complexity** | Is the justfile growing too complex? Should we split into modules? | +| **Consistency** | Are naming conventions consistent? Are patterns reusable? | +| **Dependencies** | Are external tool dependencies reasonable? | +| **Error Handling** | Do recipes fail gracefully with helpful messages? | +| **Documentation** | Are recipes self-documenting? Is help text adequate? | +| **Testing** | Have new recipes been tested? | +| **Integration** | Do new recipes integrate cleanly with existing ones? | + +### Gate Exceptions + +The gate may be abbreviated (not skipped) for: + +- **Minor phases** with no justfile impact (still mention "no justfile changes expected") +- **Hotfix phases** where urgency is documented +- **Documentation-only phases** (Phase 00) + +Even in these cases, briefly confirm: "Phase N has no expected justfile changes. Proceed?" + +--- + +## Phase Summary + +| # | Phase | Focus | Status | +|---|-------|-------|--------| +| 00 | Manual Setup | Wiki init, secrets, branch protection, local setup | pending | +| 01 | Foundation | Templates, Labels, Core Configs, AGENT.md | pending | +| 02 | Build Pipelines | Container, Rust, Python, Node builds | pending | +| 03 | Code Quality | Linting workflows for all languages | pending | +| 04 | Testing - Unit | Language-specific unit test workflows | pending | +| 05 | Testing - Property | Property-based testing (proptest, Hypothesis) | pending | +| 06 | Testing - Integration | Cross-component integration tests | pending | +| 07 | Testing - E2E | End-to-end test workflows | pending | +| 08 | Testing - Performance | Benchmark and performance regression | pending | +| 09 | Testing - Coverage | Code coverage collection and reporting | pending | +| 10 | Testing - Quality Gates | Coverage thresholds and gates | pending | +| 11 | Testing - MCP Protocol | MCP-specific protocol conformance | pending | +| 12 | Testing - Mock Harness | Mock infrastructure and fixtures | pending | +| 13 | Testing - Chaos | Resilience and chaos engineering | pending | +| 14 | Security - Dependencies | Dependency scanning (4-layer Rust) | pending | +| 15 | Security - Licenses | License compliance and SBOM | pending | +| 16 | Security - SAST | Static analysis (Semgrep, CodeQL) | pending | +| 17 | Security - Secrets | Secret scanning (Gitleaks, TruffleHog) | pending | +| 18 | Security - Memory | Memory safety (Miri, sanitizers) | pending | +| 19 | Security - Fuzzing | Fuzz testing for all languages | pending | +| 20 | Security - Taint | Data flow and taint analysis | pending | +| 21 | Security - Containers | Container image scanning | pending | +| 22 | Security - Compliance | CIS, PCI-DSS, HIPAA checklists | pending | +| 22a | Policy Library | OPA/Rego policy CI/CD, shared library | pending | +| 23 | Security - Attestation | SLSA, SBOM, cosign signing | pending | +| 24 | Release - Versioning | Semantic release, changelog | pending | +| 25 | Release - Containers | Container publishing (GHCR, Docker Hub) | pending | +| 26 | Release - Packages | Package publishing (crates.io, PyPI, npm) | pending | +| 27 | Release - Helm | Helm chart workflows | pending | +| 28 | Automation - Issues | Issue/PR automation, labeling | pending | +| 29 | Automation - Notifications | Slack, Discord webhooks | pending | +| 30 | Automation - MCP | MCP evaluation and discovery | pending | + +--- + +## Bundle Structure + +``` +bundles/ +├── .github/ +│ ├── ISSUE_TEMPLATE/ # Issue templates (Phase 01) +│ ├── workflows/ # GitHub Actions workflows (Phases 02-30) +│ ├── labels.yml # Label definitions (Phase 01) +│ ├── labeler.yml # Path-based labeler (Phase 28) +│ └── dependabot.yml # Dependency updates (Phase 14) +├── policies/ # OPA/Rego policy library (Phase 22a) +│ ├── container/ # Container security policies (Phase 21) +│ ├── compliance/ # CIS, PCI-DSS policies (Phase 22) +│ ├── license/ # License enforcement policies (Phase 15) +│ ├── lib/ # Shared utility functions +│ ├── data/ # External data (allowlists, etc.) +│ ├── tests/ # Policy unit tests +│ └── .manifest # Bundle version and metadata +├── configs/ +│ ├── mcp/ # MCP client configurations (Phase 01) +│ │ ├── project/ # Project-local configs (enabled by default) +│ │ │ ├── servers.json # Common dev servers +│ │ │ └── servers-*.json # Language-specific servers +│ │ └── global/ # Global config templates (manual install) +│ │ ├── common-servers.json +│ │ └── install.sh +│ ├── .releaserc.json # Semantic release (Phase 24) +│ ├── codecov.yml # Coverage config (Phase 09) +│ ├── .gitleaks.toml # Secret scanning (Phase 17) +│ └── ... # Tool configurations +├── docs/ +│ └── ... # Documentation +├── justfile # Setup automation +├── MANIFEST.md # Bundle contents +└── AGENT.md # AI agent instructions (Phase 01) +``` + +--- + +## Related Documents + +### Checklists +- [Gap Analysis](checklists/gap-analysis.md) - Capability gaps and action items +- [Implementation Tracking](checklists/implementation-tracking.md) - Task completion status +- [Testing Validation](checklists/testing-validation.md) - Final validation checklist + +### References +- [MCP Testing Taxonomy](references/mcp-testing-taxonomy.md) - Comprehensive MCP test specifications +- [Quick Start Guide](references/quick-start.md) - Developer onboarding + +### ADRs +- [Frontmatter Standard](../docs/adr/frontmatter-standard.md) - YAML frontmatter specification for plan documents +- [Dependency Scanning Strategy](../docs/adr/dependency-scanning-strategy.md) - 4-layer Rust defense model + +### Strategies +- [AI Context Strategy](../docs/strategies/ai-context.md) - AGENT.md and AI agent behavioral guidance +- [Policy-as-Code Strategy](../docs/strategies/policy-as-code.md) - OPA/Rego unified policy library +- [Tagging and Versioning Strategy](../docs/strategies/tagging-and-versioning.md) - Version source of truth and release coordination + +--- + +## Success Criteria + +- [ ] All workflows pass `actionlint` validation +- [ ] Bundle extracts correctly to target repo +- [ ] `just setup` works on empty repo +- [ ] Each workflow runs without errors +- [ ] SARIF uploads to GitHub Security tab +- [ ] Selective installation supported +- [ ] Documentation complete and accurate + +--- + +## File Estimates by Phase Category + +| Category | Phases | Est. Files | +|----------|--------|------------| +| Foundation | 01 | ~48 | +| Build & Quality | 02-03 | ~13 | +| Testing | 04-13 | ~50 | +| Security | 14-22, 22a, 23 | ~65 | +| Release | 24-27 | ~20 | +| Automation | 28-30 | ~11 | + +**Total Estimated: ~207 workflow/config/policy files** + +*Notes:* +- *Foundation includes +9 MCP client config files (5 project-local, 4 global)* +- *Security includes +15 OPA/Rego policy files from Phase 22a policy library* diff --git a/.ai/plans/checklists/gap-analysis.md b/.ai/plans/checklists/gap-analysis.md new file mode 100644 index 0000000..e1e01f7 --- /dev/null +++ b/.ai/plans/checklists/gap-analysis.md @@ -0,0 +1,173 @@ +--- +id: 4e593fba-d836-4aa6-9a27-d833df63e90f +title: "Gap Analysis" +type: checklist +--- + +# Gap Analysis Checklist + +## Purpose + +Use this checklist after implementing all phases to identify missing capabilities and areas for improvement. + +--- + +## 1. Language Coverage Matrix + +| Feature | Rust | Python | JS | TS | Go | Container | +|---------|------|--------|----|----|----|-----------| +| Build | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Lint | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Test | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Coverage | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Security Scan | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Dependency Check | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | +| Publish | [ ] | [ ] | [ ] | [ ] | [ ] | [ ] | + +### Identified Gaps + +- [ ] **Go support**: No Go-specific workflows yet +- [ ] **Ruby support**: Not included +- [ ] **Java/JVM support**: Not included +- [ ] **C/C++ support**: Not included + +--- + +## 2. Security Defense in Depth + +> **Reference**: See [ADR: Dependency Scanning Strategy](../../docs/adr/dependency-scanning-strategy.md) + +| Layer | Tools | Status | +|-------|-------|--------| +| Source Code | CodeQL, Semgrep | [ ] | +| Dependencies | Dependabot, cargo-audit, pip-audit | [ ] | +| Secrets | Gitleaks, TruffleHog | [ ] | +| Container Image | Trivy, Grype, Scout | [ ] | +| Runtime (optional) | Falco, Sysdig | [ ] | +| Supply Chain | SLSA, SBOM, Sigstore | [ ] | + +### Rust Supply Chain (4-Layer Defense-in-Depth) + +| Layer | Tool | Purpose | Status | +|-------|------|---------|--------| +| 1 | cargo-audit | Known CVEs (RustSec) | [ ] | +| 2 | cargo-deny | Policy enforcement (licenses, bans) | [ ] | +| 3 | cargo-vet | Audit trail verification | [ ] | +| 4 | cargo-crev | Community trust reviews | [ ] | + +### Identified Gaps + +- [ ] **CodeQL/Semgrep**: Not included in current plan +- [ ] **Runtime security**: Not addressed (out of scope for CI) +- [ ] **Supply chain attacks**: SLSA level needs verification +- [x] **Rust supply chain**: Addressed via 4-layer defense (ADR approved) + +--- + +## 3. Compliance Coverage + +| Framework | Container | Code | CI/CD | Docs | +|-----------|-----------|------|-------|------| +| CIS Benchmarks | [ ] | [ ] | [ ] | [ ] | +| PCI-DSS | [ ] | [ ] | [ ] | [ ] | +| HIPAA | [ ] | [ ] | [ ] | [ ] | +| SOC 2 | [ ] | [ ] | [ ] | [ ] | +| NIST | [ ] | [ ] | [ ] | [ ] | +| FedRAMP | [ ] | [ ] | [ ] | [ ] | + +### Identified Gaps + +- [ ] **NIST frameworks**: Not included +- [ ] **FedRAMP**: Not included +- [ ] **ISO 27001**: Not included +- [ ] **Compliance documentation templates**: Missing + +--- + +## 4. Automation Completeness + +| Task | Automated | Manual | Not Needed | +|------|-----------|--------|------------| +| Code review assignment | [ ] | [ ] | [ ] | +| Label management | [ ] | [ ] | [ ] | +| Stale issue cleanup | [ ] | [ ] | [ ] | +| Dependency updates | [ ] | [ ] | [ ] | +| Release notes | [ ] | [ ] | [ ] | +| Version bumping | [ ] | [ ] | [ ] | +| Changelog generation | [ ] | [ ] | [ ] | +| Security alerts | [ ] | [ ] | [ ] | +| Performance alerts | [ ] | [ ] | [ ] | + +### Identified Gaps + +- [ ] **Performance monitoring**: No performance regression detection +- [ ] **Benchmark tracking**: No benchmark history + +--- + +## 5. Integration Points + +| Integration | Covered | Priority | +|-------------|---------|----------| +| GitHub Security Tab | [ ] | High | +| GitHub Packages | [ ] | High | +| GitHub Pages | [ ] | Medium | +| GitHub Projects | [ ] | Medium | +| Codecov | [ ] | Medium | +| Slack | [ ] | Low | +| Discord | [ ] | Low | +| Jira | [ ] | Low | +| Linear | [ ] | Low | + +### Identified Gaps + +- [ ] **Jira integration**: Not included +- [ ] **Linear integration**: Not included +- [ ] **PagerDuty/OpsGenie**: Not included + +--- + +## 6. MCP-Specific Gaps + +| Feature | Status | Priority | +|---------|--------|----------| +| MCP server validation | [ ] | High | +| Tool schema validation | [ ] | High | +| Resource testing | [ ] | High | +| Transport testing | [ ] | Medium | +| SDK compatibility | [ ] | Medium | +| Performance benchmarks | [ ] | Low | + +--- + +## Action Items + +### High Priority + +1. [ ] Add CodeQL/Semgrep for code scanning +2. [ ] Complete MCP-specific validation +3. [ ] Add Go language support +4. [ ] Create reference implementation repo + +### Medium Priority + +5. [ ] Add Terraform/K8s workflows +6. [ ] Add performance benchmarking +7. [ ] Create central configuration system +8. [ ] Add API documentation linting + +### Low Priority + +9. [ ] Add Jira/Linear integrations +10. [ ] Create video tutorials +11. [ ] Add accessibility checks +12. [ ] Add additional compliance frameworks + +--- + +## Review Schedule + +- [ ] Weekly: Check implementation progress +- [ ] After each phase: Update this checklist +- [ ] Before release: Full gap review +- [ ] Quarterly: Re-evaluate priorities diff --git a/.ai/plans/checklists/implementation-tracking.md b/.ai/plans/checklists/implementation-tracking.md new file mode 100644 index 0000000..0d3dd03 --- /dev/null +++ b/.ai/plans/checklists/implementation-tracking.md @@ -0,0 +1,248 @@ +--- +id: 674b3bcb-ee95-496e-ac24-4d144685f05b +title: "Implementation Tracking" +type: checklist +--- + +# Implementation Tracking + +## Progress Overview + +| Phase | Status | Progress | +|-------|--------|----------| +| 01. Foundation | Not Started | 0/34 | +| 02. Build Pipelines | Not Started | 0/5 | +| 03. Code Quality | Not Started | 0/8 | +| 04. Testing - Unit | Not Started | 0/7 | +| 05. Testing - Property | Not Started | 0/3 | +| 06. Testing - Integration | Not Started | 0/4 | +| 07. Testing - E2E | Not Started | 0/4 | +| 08. Testing - Performance | Not Started | 0/3 | +| 09. Testing - Coverage | Not Started | 0/5 | +| 10. Testing - Quality Gates | Not Started | 0/4 | +| 11. Testing - MCP Protocol | Not Started | 0/6 | +| 12. Testing - Mock Harness | Not Started | 0/8 | +| 13. Testing - Chaos | Not Started | 0/4 | +| 14. Security - Dependencies | Not Started | 0/6 | +| 15. Security - Licenses | Not Started | 0/5 | +| 16. Security - SAST | Not Started | 0/8 | +| 17. Security - Secrets | Not Started | 0/5 | +| 18. Security - Memory | Not Started | 0/6 | +| 19. Security - Fuzzing | Not Started | 0/9 | +| 20. Security - Taint | Not Started | 0/4 | +| 21. Security - Containers | Not Started | 0/6 | +| 22. Security - Compliance | Not Started | 0/4 | +| 23. Security - Attestation | Not Started | 0/4 | +| 24. Release - Versioning | Not Started | 0/4 | +| 25. Release - Containers | Not Started | 0/3 | +| 26. Release - Packages | Not Started | 0/5 | +| 27. Release - Helm | Not Started | 0/10 | +| 28. Automation - Issues | Not Started | 0/6 | +| 29. Automation - Notifications | Not Started | 0/2 | +| 30. Automation - MCP | Not Started | 0/2 | + +--- + +## Phase 01: Foundation + +### Issue Templates +- [ ] bug-report.yml +- [ ] feature-request.yml +- [ ] security-vulnerability.yml +- [ ] documentation.yml +- [ ] question.yml +- [ ] config.yml + +### Rust Rewrite Templates +- [x] rust-rewrite.yml +- [x] code-analysis.yml + +### Rust Transport Templates +- [x] rust-transport-stdio.yml +- [x] rust-transport-sse.yml +- [x] rust-transport-http.yml +- [x] rust-transport-websocket.yml +- [x] rust-transport-ipc.yml +- [x] rust-transport-grpc.yml + +### MCP Templates +- [x] mcp-tool-documentation.yml +- [x] mcp-tool-implementation.yml +- [x] repo-llm-txt.yml +- [x] mcp-transport-security.yml +- [x] mcp-transport-authentication.yml +- [x] mcp-server-observability.yml +- [x] mcp-testing-unit.yml +- [x] mcp-testing-e2e.yml +- [x] mcp-testing-integration.yml +- [x] mcp-testing-cases.yml +- [x] containerization.yml +- [x] library-extension.yml + +### Core Configs +- [ ] pull_request_template.md +- [ ] labels.yml (extended) +- [ ] dependabot.yml +- [ ] SECURITY.md +- [ ] AGENT.md + +--- + +## Phase 02-03: Build & Quality + +### Build Workflows +- [ ] build-container.yml +- [ ] build-mdbook.yml +- [ ] build-rust.yml +- [ ] build-python.yml +- [ ] build-node.yml + +### Lint Workflows +- [ ] lint-container.yml +- [ ] lint-rust.yml +- [ ] lint-python.yml +- [ ] lint-javascript.yml +- [ ] lint-typescript.yml +- [ ] lint-markdown.yml +- [ ] lint-yaml.yml +- [ ] lint-shell.yml + +--- + +## Phase 04-13: Testing + +### Unit & Core +- [ ] test-rust.yml +- [ ] test-python.yml +- [ ] test-javascript.yml +- [ ] test-typescript.yml +- [ ] test-container.yml +- [ ] test-mdbook.yml +- [ ] test-integration.yml + +### Extended Testing +- [ ] test-property.yml +- [ ] test-benchmark.yml +- [ ] test-smoke.yml +- [ ] test-regression.yml +- [ ] test-chaos.yml + +### Coverage +- [ ] coverage.yml +- [ ] configs/codecov.yml +- [ ] configs/.codeclimate.yml +- [ ] mutation-testing.yml +- [ ] quality-gate.yml + +### MCP Testing +- [ ] test-mcp-protocol.yml +- [ ] test-mcp-tools.yml +- [ ] test-mcp-resources.yml +- [ ] test-mcp-transport.yml +- [ ] test-mcp-security.yml +- [ ] test-mcp-performance.yml + +### Mock Harness +- [ ] docker-compose.mocks.yml +- [ ] mock-mcp-server/ +- [ ] mcp-test-client/ +- [ ] VCR infrastructure + +--- + +## Phase 14-23: Security + +### Dependency Scanning +- [ ] dependency-review.yml +- [ ] deps-rust.yml +- [ ] deps-python.yml +- [ ] deps-node.yml +- [ ] deps-container.yml +- [ ] security-rust.yml (4-layer) + +### License & SBOM +- [ ] security-license.yml +- [ ] reuse-lint.yml +- [ ] attestation-sbom.yml + +### Static Analysis +- [ ] security-sast.yml +- [ ] security-sast-rust.yml +- [ ] security-sast-python.yml +- [ ] security-sast-go.yml + +### Secrets +- [ ] secret-scan-precommit.yml +- [ ] secret-scan-ci.yml +- [ ] .gitleaks.toml + +### Memory & Fuzzing +- [ ] security-memory-rust.yml +- [ ] security-fuzz-rust.yml +- [ ] security-fuzz-python.yml +- [ ] security-fuzz-api.yml + +### Container & Compliance +- [ ] security-container.yml +- [ ] compliance-cis.yml +- [ ] attestation-slsa.yml +- [ ] attestation-sign.yml + +--- + +## Phase 24-27: Release + +### Versioning +- [ ] semantic-release.yml +- [ ] .releaserc.json +- [ ] release-drafter.yml + +### Publishing +- [ ] publish-container.yml +- [ ] publish-rust.yml +- [ ] publish-python.yml +- [ ] publish-node.yml +- [ ] deploy-docs.yml + +### Helm +- [ ] lint-helm.yml +- [ ] test-helm.yml +- [ ] release-helm.yml +- [ ] publish-helm-oci.yml + +--- + +## Phase 28-30: Automation + +### Issue/PR Automation +- [ ] label-sync.yml +- [ ] stale-issues.yml +- [ ] stale-prs.yml +- [ ] triage.yml +- [ ] welcome.yml +- [ ] auto-assign.yml + +### Notifications +- [ ] notify-slack.yml +- [ ] notify-discord.yml + +### MCP Automation +- [ ] mcp-eval.yml +- [ ] mcp-discovery.yml + +--- + +## Blockers & Issues + +| Issue | Phase | Status | Resolution | +|-------|-------|--------|------------| +| - | - | - | - | + +--- + +## Session Log + +### Session 1: [DATE] +- Started: +- Completed: +- Notes: diff --git a/.ai/plans/checklists/testing-validation.md b/.ai/plans/checklists/testing-validation.md new file mode 100644 index 0000000..1abba4a --- /dev/null +++ b/.ai/plans/checklists/testing-validation.md @@ -0,0 +1,183 @@ +--- +id: 52545f6d-de4f-421f-8444-3f8d683c3ad0 +title: "Testing Validation" +type: checklist +--- + +# Testing Validation Checklist + +## Purpose + +Final validation checklist to verify the bundle is ready for release. + +--- + +## 1. Workflow Validation + +### Syntax & Structure +- [ ] All workflows pass `actionlint` validation +- [ ] All workflows pass `yamllint` validation +- [ ] No hardcoded secrets in workflow files +- [ ] All workflow names are unique +- [ ] All job names are descriptive + +### Permissions +- [ ] Minimum required permissions specified +- [ ] `contents: read` is default where applicable +- [ ] Write permissions explicitly justified +- [ ] GITHUB_TOKEN permissions documented + +### Triggers +- [ ] Appropriate triggers for each workflow type +- [ ] Path filters working correctly +- [ ] Branch filters correct +- [ ] workflow_dispatch enabled for debugging + +--- + +## 2. Bundle Installation + +### Fresh Install +- [ ] `just setup` works on empty repository +- [ ] `just setup-remote` works via API +- [ ] All files extracted to correct locations +- [ ] No file permission issues + +### Selective Install +- [ ] Individual workflow installation works +- [ ] Category-based installation works +- [ ] Conflict detection works +- [ ] Upgrade path documented + +### Configuration +- [ ] All configs have sensible defaults +- [ ] Override mechanism documented +- [ ] Environment variables documented +- [ ] Secrets list is complete + +--- + +## 3. Workflow Execution + +### Build Workflows +- [ ] build-container.yml runs successfully +- [ ] build-rust.yml runs successfully +- [ ] build-python.yml runs successfully +- [ ] build-node.yml runs successfully +- [ ] Caching works correctly + +### Lint Workflows +- [ ] lint-container.yml produces SARIF +- [ ] lint-rust.yml catches violations +- [ ] lint-python.yml catches violations +- [ ] All linters have config files + +### Test Workflows +- [ ] test-rust.yml reports coverage +- [ ] test-python.yml reports coverage +- [ ] Integration tests pass +- [ ] E2E tests pass + +### Security Workflows +- [ ] SARIF uploads to Security tab +- [ ] Secret scanning works +- [ ] Dependency review blocks PRs +- [ ] Container scanning works + +### Release Workflows +- [ ] Semantic release works +- [ ] Container publishing works +- [ ] Package publishing works +- [ ] Changelog generation works + +--- + +## 4. Integration Points + +### GitHub Features +- [ ] Security tab shows findings +- [ ] Dependabot creates PRs +- [ ] Labels sync correctly +- [ ] Projects automation works + +### External Services +- [ ] Codecov receives reports +- [ ] Slack notifications work (if configured) +- [ ] Docker Hub publishing works +- [ ] crates.io publishing works + +--- + +## 5. Documentation + +### Completeness +- [ ] All workflows documented in MANIFEST.md +- [ ] All secrets documented +- [ ] All configurations documented +- [ ] Troubleshooting guide exists + +### Accuracy +- [ ] Examples work as written +- [ ] Links are not broken +- [ ] Version numbers are current +- [ ] Screenshots are current + +--- + +## 6. MCP-Specific Validation + +### Protocol Conformance +- [ ] JSON-RPC 2.0 tests pass +- [ ] MCP protocol version tests pass +- [ ] Schema validation tests pass + +### Functional Testing +- [ ] Tool discovery tests pass +- [ ] Tool invocation tests pass +- [ ] Resource tests pass +- [ ] Transport tests pass + +### Security Testing +- [ ] Input validation tests pass +- [ ] Fuzzing produces no crashes +- [ ] Rate limiting works + +--- + +## 7. Performance Validation + +### Workflow Efficiency +- [ ] Average workflow time < 5 min +- [ ] Cache hit rate > 80% +- [ ] Parallel jobs maximized +- [ ] Redundant runs minimized + +### Resource Usage +- [ ] No workflow exceeds timeout +- [ ] Artifact sizes reasonable +- [ ] Log output manageable + +--- + +## 8. Final Sign-off + +### Pre-release +- [ ] All blockers resolved +- [ ] All high-priority gaps addressed +- [ ] README updated +- [ ] CHANGELOG updated +- [ ] Version bumped + +### Release +- [ ] Tag created +- [ ] Release notes generated +- [ ] Artifacts attached +- [ ] Announcement prepared + +--- + +## Validation Log + +| Date | Validator | Result | Notes | +|------|-----------|--------|-------| +| - | - | - | - | diff --git a/.ai/plans/phases/bundle-contents-phase-00-manual-setup.md b/.ai/plans/phases/bundle-contents-phase-00-manual-setup.md new file mode 100644 index 0000000..3e2a17a --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-00-manual-setup.md @@ -0,0 +1,283 @@ +--- +id: 6daf1a38-745e-41f8-abf4-90757b4b1a8a +title: "Phase 00: Manual Setup" +status: pending +depends_on: [] # First phase - no dependencies +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - wiki-documentation-strategy-adr # ADR in ../docs/adr/ +issues: [] +gate: + required: true + justfile_changes: none # This phase is manual, no justfile changes + review_focus: + - Confirm bundle download location + - Verify justfile prerequisites (gh, op CLIs) + - Discuss workspace directory preferences +--- + +# Phase 00: Manual Setup + +> **⚠️ GATE REQUIRED**: Before starting this phase, complete the [Justfile Review Gate](../bundle-contents.md#phase-gate-justfile-review) conversation with user. + +## 0. Phase Gate: Justfile Review + +### Pre-Phase Checklist + +- [ ] Confirmed Phase 00 has no justfile changes (manual-only phase) +- [ ] Verified user understands prerequisite tools (gh CLI, op CLI) +- [ ] Discussed workspace directory preferences +- [ ] User approved proceeding with manual setup + +### Phase 00 Justfile Impact + +**No justfile changes in this phase.** Phase 00 captures manual actions that must be performed before the bundle's justfile can be used effectively. + +However, this phase establishes the **prerequisites** for justfile execution: + +| Prerequisite | Purpose | Validation | +|--------------|---------|------------| +| `gh` CLI | GitHub API operations | `gh auth status` | +| `op` CLI | 1Password credential storage | `op account list` | +| Wiki initialized | Documentation storage | Manual via GitHub UI | +| Secrets configured | Workflow authentication | Manual via GitHub UI | + +--- + +## 1. Purpose + +This phase captures **manual actions** that must be performed by the user after downloading/applying the bundle. These steps cannot be automated due to GitHub limitations, security requirements, or one-time setup needs. + +**This phase should be completed BEFORE proceeding with Phase 01.** + +--- + +## 2. Manual Actions Checklist + +### 2.1 Repository Wiki Setup + +**Why Manual**: GitHub wikis cannot be programmatically initialized - the first page must be created via the web UI. + +- [ ] Navigate to repository → Wiki tab +- [ ] Click "Create the first page" +- [ ] Create `Home.md` with initial content (template below) +- [ ] Verify wiki is accessible at `https://github.com///wiki` + +#### Home.md Template + +```markdown +# Project Wiki + +Welcome to the project wiki. This wiki serves as the central documentation hub for: + +- **AI Agents**: LLMs.txt and context for AI-assisted development +- **ADRs**: Architecture Decision Records +- **Guides**: Tool guides, setup instructions, workflows +- **References**: API docs, protocol specs, configuration references + +## Quick Links + +- [LLMs.txt](LLMs.txt) - AI agent context file +- [ADRs](ADRs) - Architecture decisions +- [Setup Guide](Setup-Guide) - Getting started + +## For AI Agents + +This wiki is accessible via: +- **Context7**: Point to `https://github.com///wiki` +- **GitMCP**: Use `https://gitmcp.io//.wiki` +- **Raw Access**: `https://raw.githubusercontent.com/wiki///.md` + +--- + +*This wiki is automatically synced from the repository. See [Wiki Sync Workflow](../.github/workflows/wiki-sync.yml).* +``` + +### 2.2 GitHub Repository Settings + +**Why Manual**: Repository settings require admin access and cannot be configured via workflow files. + +- [ ] **Enable Wiki**: Settings → Features → Wikis (check) +- [ ] **Branch Protection**: Settings → Branches → Add rule for `main` + - [ ] Require pull request reviews + - [ ] Require status checks to pass + - [ ] Require signed commits (optional) +- [ ] **Actions Permissions**: Settings → Actions → General + - [ ] Allow GitHub Actions to create and approve pull requests + - [ ] Set workflow permissions to "Read and write permissions" +- [ ] **Merge Queue** (optional, for high PR volume): Settings → General → Pull Requests + - [ ] Enable "Require branches to be up to date before merging" + - [ ] Enable "Require merge queue" + - Benefits: Automatic rebasing, batched CI runs, guaranteed main stability + +### 2.3 Secrets Configuration + +**Why Manual**: Secrets must be added via GitHub UI for security. + +| Secret | Required For | How to Obtain | +|--------|--------------|---------------| +| `CARGO_REGISTRY_TOKEN` | crates.io publishing | [crates.io/settings/tokens](https://crates.io/settings/tokens) | +| `NPM_TOKEN` | npm publishing | [npmjs.com/settings/tokens](https://www.npmjs.com/settings/tokens) | +| `PYPI_API_TOKEN` | PyPI publishing | [pypi.org/manage/account](https://pypi.org/manage/account/) | +| `SLACK_BOT_TOKEN` | Slack notifications | Slack App settings | +| `DISCORD_WEBHOOK` | Discord notifications | Discord server settings | +| `CODECOV_TOKEN` | Coverage reports | [codecov.io](https://codecov.io) | + +- [ ] Add required secrets: Settings → Secrets and variables → Actions + +### 2.4 GitHub App Installations + +**Why Manual**: App installations require OAuth authorization. + +- [ ] **pre-commit.ci**: Install from [pre-commit.ci](https://pre-commit.ci) +- [ ] **Codecov**: Install from [GitHub Marketplace](https://github.com/marketplace/codecov) +- [ ] **Dependabot**: Enable via Settings → Code security and analysis + +### 2.5 Local Development Setup + +**Why Manual**: Local environment varies per developer. + +```bash +# Install pre-commit hooks +pip install pre-commit +pre-commit install +pre-commit install --hook-type commit-msg + +# Install Cocogitto (commit linting) +cargo install cocogitto + +# Install commitlint (optional, for detailed validation) +npm install -g @commitlint/cli @commitlint/config-conventional + +# Verify setup +pre-commit run --all-files +cog check +``` + +- [ ] Document local setup in CONTRIBUTING.md + +### 2.6 Wiki Initial Pages + +After wiki is initialized, create these pages: + +| Page | Purpose | +|------|---------| +| `Home.md` | Landing page (created in 2.1) | +| `LLMs.txt` | AI agent context - brief version | +| `LLMs-Full.txt` | AI agent context - comprehensive | +| `ADRs.md` | Index of architecture decisions | +| `Setup-Guide.md` | Getting started guide | +| `_Sidebar.md` | Custom navigation sidebar | + +- [ ] Create initial wiki pages using template below + +#### _Sidebar.md Template + +```markdown +**Navigation** + +- [[Home]] +- [[Setup Guide]] +- [[Contributing]] + +**For AI Agents** + +- [[LLMs.txt]] +- [[LLMs Full]] + +**Architecture** + +- [[ADRs]] + +**References** + +- [[Tool Guides]] +- [[API Reference]] +``` + +--- + +## 3. Post-Setup Verification + +After completing manual setup: + +- [ ] Wiki accessible and has Home page +- [ ] Branch protection rules active +- [ ] Required secrets configured +- [ ] pre-commit.ci app installed +- [ ] Local pre-commit hooks working +- [ ] `cog check` passes locally + +--- + +## 4. Automation for Wiki Sync + +Once wiki is initialized, this workflow can sync docs automatically: + +```yaml +# .github/workflows/wiki-sync.yml +name: Sync Docs to Wiki + +on: + push: + branches: [main] + paths: + - 'docs/**' + - '.ai/docs/**' + workflow_dispatch: + +jobs: + sync: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + path: repo + + - name: Checkout wiki + uses: actions/checkout@v4 + with: + repository: ${{ github.repository }}.wiki + path: wiki + + - name: Sync documentation + run: | + # Sync ADRs + mkdir -p wiki/ADRs + cp -r repo/.ai/docs/adr/*.md wiki/ADRs/ + + # Sync other docs + cp -r repo/docs/*.md wiki/ 2>/dev/null || true + + # Generate ADR index + echo "# Architecture Decision Records" > wiki/ADRs.md + echo "" >> wiki/ADRs.md + for f in wiki/ADRs/*.md; do + name=$(basename "$f" .md) + title=$(grep -m1 "^title:" "$f" | cut -d: -f2- | xargs) + echo "- [[$name|$title]]" >> wiki/ADRs.md + done + + - name: Commit and push + run: | + cd wiki + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add . + git diff --quiet && git diff --staged --quiet || git commit -m "docs: sync from main repo" + git push +``` + +--- + +## 5. Review & Validation + +- [ ] All manual actions completed +- [ ] Wiki sync workflow added to bundle +- [ ] Documentation updated with manual steps +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-01-foundation.md b/.ai/plans/phases/bundle-contents-phase-01-foundation.md new file mode 100644 index 0000000..07d25f5 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-01-foundation.md @@ -0,0 +1,1843 @@ +--- +id: 367b75a1-dd7d-4d34-9bf9-6aaab692c2ee +title: "Phase 01: Foundation" +status: pending +depends_on: + - 6daf1a38-745e-41f8-abf4-90757b4b1a8a # phase-00 (manual setup) +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +gate: + required: true + justfile_changes: major # none | minor | major + review_focus: + - Initial justfile structure and core recipes + - Configuration options (language, clone method, AI agent) + - 1Password integration approach + - Expected init workflow +--- + +# Phase 01: Foundation + +> **⚠️ GATE REQUIRED**: Before starting this phase, complete the [Justfile Review Gate](../bundle-contents.md#phase-gate-justfile-review) conversation with user. + +## 0. Phase Gate: Justfile Review + +### Pre-Phase Checklist + +- [ ] Reviewed current justfile state with user +- [ ] Compared expected vs current workflow +- [ ] Discussed Phase 01 justfile changes +- [ ] User approved planned changes +- [ ] Gate conversation documented + +### Phase 01 Justfile Impact + +This phase establishes the **foundational justfile structure**. Major changes: + +| Recipe | Status | Purpose | +|--------|--------|---------| +| `init ` | **New** | Main entry point for project setup | +| `test-readiness ` | **New** | Verify setup is complete | +| `configure` | **New** | Interactive configuration wizard | +| `_preflight` | **New** | Validate prerequisites | +| `_setup-repos` | **New** | Fork and create from template | +| `_clone-repos` | **New** | Clone repositories locally | +| `_setup-1password` | **New** | Create vault and store credentials | +| `_create-issues` | **New** | Create setup milestone and issues | +| `_apply-bundle` | **New** | Copy bundle files to repo | +| `_apply-mcp-config` | **New** | Configure MCP client servers | +| `_finalize` | **New** | Install hooks, display summary | +| `show-config` | **New** | Display current configuration | +| `check` | **New** | Validate prerequisites | +| `list-templates` | **New** | Show available language templates | +| `list-agents` | **New** | Show supported AI agents | +| `help` | **New** | Display usage help | + +### Questions for Gate Review + +1. Is the `~/mcp-workspace//` directory structure acceptable? +2. Should 1Password vault naming use a different convention? +3. Are the language template repos (`aRustyDev/tmpl-*`) correct? +4. Any additional AI agents to support? + +--- + +## 1. Current State Assessment + +- [ ] Review existing issue templates in bundle +- [ ] Check for existing labels.yml +- [ ] Verify PR template exists +- [ ] Check for AGENT.md +- [ ] Review dependabot.yml if present + +### Existing Assets + +- Rust transport templates (6 files) - completed +- MCP testing templates (4 files) - completed +- MCP implementation templates (3 files) - completed +- Container/library templates (2 files) - completed + +### Gaps Identified + +- [ ] General issue templates (bug, feature, security, docs, question) +- [ ] Issue template config.yml +- [ ] Extended labels.yml +- [ ] Comprehensive PR template +- [ ] AGENT.md with git workflow +- [ ] SECURITY.md + +--- + +## 2. Contextual Goal + +Establish the foundational templates and configurations that all other phases build upon. This includes standardized issue templates for bug reports, feature requests, security vulnerabilities, and documentation; a comprehensive PR template with testing checklists; extended label definitions covering all workflow categories; and AGENT.md providing AI agent instructions for consistent development practices. + +### Success Criteria + +- [ ] All 5 general issue templates created +- [ ] Issue template config.yml configured +- [ ] PR template with comprehensive sections +- [ ] labels.yml with 100+ labels across all categories +- [ ] AGENT.md with git workflow documentation +- [ ] dependabot.yml for multi-ecosystem support + +### Out of Scope + +- Workflow files (Phase 02+) +- Security scanning configurations (Phase 14+) +- Release configurations (Phase 24+) + +--- + +## 3. Implementation + +### 3.1 Issue Templates + +Create `.github/ISSUE_TEMPLATE/` directory with: + +| File | Purpose | +|------|---------| +| `bug-report.yml` | Standard bug reporting with severity, reproduction steps | +| `feature-request.yml` | Feature proposals with problem statement | +| `security-vulnerability.yml` | Private security reports with CVSS | +| `documentation.yml` | Docs improvements and corrections | +| `question.yml` | General usage questions | +| `config.yml` | Template chooser with contact links | + +### 3.2 PR Template + +Create `.github/pull_request_template.md` with sections: +- Summary +- Related Issues +- Changes +- Type of Change (checkboxes) +- Testing (checkboxes) +- Screenshots +- Checklist + +### 3.3 Labels + +Extend `.github/labels.yml` with categories: +- Type labels (bug, feature, docs, question, security) +- Priority labels (P0-P4) +- Status labels (triage, blocked, in-progress, review-needed) +- Size labels (XS, S, M, L, XL) +- Language labels (rust, python, javascript, typescript, go) +- Workflow labels (ci, cd, security, compliance) + +### 3.4 AGENT.md + +Create `AGENT.md` with: +- Git workflow (hierarchical branch strategy) +- Conventional commits specification +- Signed-off-by requirements +- Coding standards per language + +#### Git Workflow - Branch Strategy + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ BRANCH HIERARCHY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ main ───────────────────────────────────────────────────────────────────── │ +│ │ │ +│ ├── feature/- # Human-created feature branches │ +│ │ │ +│ ├── fix/- # Human-created bug fix branches │ +│ │ │ +│ ├── refactor/- # Human-created refactor branches │ +│ │ │ +│ ├── docs/- # Human-created documentation │ +│ │ │ +│ ├── pr/ # CI-created PR validation branches │ +│ │ │ +│ └── deps// # CI-created dependency updates │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ + +Branch Prefix Legend: + feature/* | fix/* | refactor/* | docs/* → Human-created (developer workflow) + pr/* → CI-created (PR validation only) + deps/* → CI-created (Dependabot/Renovate) +``` + +#### Branch Creation Rules + +| Prefix | Creator | Purpose | Merge Target | +|--------|---------|---------|--------------| +| `feature/` | Human | New functionality | `main` | +| `fix/` | Human | Bug fixes | `main` | +| `refactor/` | Human | Code improvements | `main` | +| `docs/` | Human | Documentation | `main` | +| `pr/` | CI only | PR validation/testing | Never merged directly | +| `deps/` | CI only | Dependency updates | `main` (auto-merge eligible) | + +#### deps/* Branch Specification + +**Format**: `deps//` + +**Examples**: +- `deps/tokio/1.35.0` +- `deps/serde/1.0.195` +- `deps/actions-checkout/v4` + +**Creation**: Only by authorized CI processes: +- Dependabot +- Renovate Bot +- Custom dependency update workflows + +**Behavior**: +- Treated equivalently to `pr/*` for CI validation +- Eligible for auto-merge based on update type (see Phase 28) +- Protected from human direct push +- Auto-deleted after merge + +**Branch Protection Rules**: +```yaml +# Example branch protection for deps/* +deps/**: + required_status_checks: + strict: true + contexts: + - "CI / build" + - "CI / test" + - "Security / audit" + restrictions: + apps: + - dependabot + - renovate +``` + +#### Commit Strategy + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ COMMIT STRATEGY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHILOSOPHY: Atomic, Traceable, Reversible │ +│ │ +│ Each commit should: │ +│ • Represent ONE logical change (atomic) │ +│ • Be linked to an issue or PR (traceable) │ +│ • Be independently revertable (reversible) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Conventional Commits Format**: +``` +(): + +[optional body] + +[optional footer(s)] +``` + +**Types** (in order of precedence for changelogs): +| Type | Description | Changelog Section | +|------|-------------|-------------------| +| `feat` | New feature | Features | +| `fix` | Bug fix | Bug Fixes | +| `perf` | Performance improvement | Performance | +| `refactor` | Code change that neither fixes nor adds | (hidden) | +| `docs` | Documentation only | Documentation | +| `style` | Formatting, whitespace | (hidden) | +| `test` | Adding/updating tests | (hidden) | +| `build` | Build system changes | (hidden) | +| `ci` | CI configuration | (hidden) | +| `chore` | Maintenance tasks | (hidden) | + +**Scope Guidelines**: +- Use the affected module, component, or area +- Examples: `auth`, `api`, `cli`, `transport`, `mcp-protocol` +- For cross-cutting changes: `core`, `all`, or omit scope + +**Breaking Changes**: +``` +feat(api)!: change response format for tools endpoint + +BREAKING CHANGE: The tools endpoint now returns an array instead of an object. +Migration: Update client code to iterate over array response. +``` + +**Issue Linking**: +``` +fix(transport): handle connection timeout gracefully + +Properly catch and retry on ETIMEDOUT errors during +WebSocket handshake. Adds exponential backoff with +configurable max retries. + +Fixes #123 +``` + +**When to Commit**: +| Scenario | Commit Strategy | +|----------|-----------------| +| TDD Red phase | Commit failing test: `test(scope): add failing test for X` | +| TDD Green phase | Commit with test: `feat/fix(scope): implement X` | +| TDD Refactor phase | Commit refactor: `refactor(scope): extract/simplify X` | +| Pre-commit hook fails | Fix issues, then commit (don't skip hooks) | +| Large feature | Break into multiple atomic commits | + +**Commit Message Body**: +- **What**: What changed (the diff shows this, be concise) +- **Why**: Why this change was necessary (context) +- **Side effects**: Any behavioral changes to note + +**Trailers**: +``` +Signed-off-by: Name # Required (DCO) +Co-authored-by: Name # For pair programming +Reviewed-by: Name # Post-review attribution +Fixes: #123 # Issue auto-close +Refs: #456, #789 # Related issues (no auto-close) +``` + +#### PR Workflow + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PR LIFECYCLE │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ +│ │ Draft │ -> │ Ready │ -> │ Review │ -> │ Merge │ │ +│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ +│ │ │ │ │ │ +│ │ │ │ │ │ +│ Work in Request Address Squash & │ +│ progress review feedback merge │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**PR States**: +| State | Label | Description | +|-------|-------|-------------| +| Draft | `status:draft` | Work in progress, CI runs but no review | +| Ready | `status:ready-for-review` | Complete, requesting review | +| Changes Requested | `status:changes-requested` | Reviewer requested changes | +| Approved | `status:approved` | Ready for merge | +| Blocked | `status:blocked` | Cannot proceed (dependency, discussion) | + +**Merge Strategy**: +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ MERGE STRATEGY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ DEFAULT: Squash and Merge │ +│ ────────────────────────────────────────────────────────────────────────── │ +│ • Combines all PR commits into single commit on main │ +│ • PR title becomes commit message │ +│ • Keeps main branch history clean │ +│ • Individual commits preserved in PR for archaeology │ +│ │ +│ EXCEPTION: Rebase and Merge │ +│ ────────────────────────────────────────────────────────────────────────── │ +│ Use when each commit is meaningful and atomic: │ +│ • Multi-part features with distinct commits │ +│ • Commits from different authors (preserve attribution) │ +│ • When explicitly requested in PR description │ +│ │ +│ NEVER: Merge Commit │ +│ ────────────────────────────────────────────────────────────────────────── │ +│ Creates noise in history. Disabled at repository level. │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Review Requirements**: +- Minimum 1 approving review for standard changes +- Minimum 2 approving reviews for: + - Security-related changes + - Breaking changes + - Changes to CI/CD pipelines + - Changes to authentication/authorization +- CODEOWNERS automatically requested based on paths + +**CI Gates Before Merge**: +| Gate | Required | Description | +|------|----------|-------------| +| Build | Yes | Must compile/build successfully | +| Unit Tests | Yes | All tests must pass | +| Lint | Yes | No lint errors (warnings allowed) | +| Security Scan | Yes | No high/critical vulnerabilities | +| Coverage | No | Informational, not blocking | +| Integration Tests | Depends | Required for API changes | + +#### Planning Strategy + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLANNING METHODOLOGY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ APPROACH: Iterative Decomposition │ +│ │ +│ 1. Understand → 2. Decompose → 3. Sequence → 4. Execute → 5. Validate │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Phase 1: Understand** +- Read the issue/requirement completely +- Identify acceptance criteria +- Ask clarifying questions BEFORE starting +- State your understanding back to confirm + +**Phase 2: Decompose** +``` +Feature Request + │ + ├── What existing code is affected? + │ └── Read and understand existing patterns + │ + ├── What new code is needed? + │ └── List new files/functions/modules + │ + ├── What tests are needed? + │ └── Unit, integration, edge cases + │ + └── What documentation updates? + └── README, API docs, comments +``` + +**Phase 3: Sequence** +Order tasks by: +1. **Dependencies**: What must exist first? +2. **Risk**: What has highest uncertainty? (do early) +3. **Value**: What delivers most value? (prioritize) + +**Task Size Guidelines**: +| Size | Description | Commits | +|------|-------------|---------| +| XS | Single function change | 1 | +| S | Single file, multiple functions | 1-2 | +| M | Multiple files, one module | 2-5 | +| L | Multiple modules | 5-10 | +| XL | Should be broken down | Split into multiple PRs | + +**Risk Identification**: +Before starting, identify: +- **Technical risks**: Unknown APIs, complex algorithms +- **Integration risks**: Breaking changes, dependencies +- **Security risks**: Auth, input validation, secrets +- **Performance risks**: Large data, N+1 queries + +**When to Stop and Ask**: +- Ambiguous requirements +- Multiple valid approaches (need decision) +- Scope creep detected +- Blocked by external dependency +- Estimated effort exceeds original scope + +#### Debugging Strategy + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ DEBUGGING METHODOLOGY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ APPROACH: Scientific Method │ +│ │ +│ 1. Reproduce → 2. Isolate → 3. Hypothesize → 4. Test → 5. Fix → 6. Verify │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**Phase 1: Reproduce** +- Get exact steps to reproduce +- Identify environment (OS, versions, config) +- Create minimal reproduction case +- Document reproduction steps in issue + +**Phase 2: Isolate** +``` +Is the bug in...? + │ + ├── This repository's code? + │ └── git bisect to find introducing commit + │ + ├── A dependency? + │ └── Check dependency changelogs, update/pin + │ + ├── Configuration? + │ └── Compare working vs broken configs + │ + └── Environment? + └── Test in clean environment +``` + +**Phase 3: Hypothesize** +Before changing code: +1. State your hypothesis: "I believe X causes Y because Z" +2. Predict what fixing X will change +3. Identify how to verify the fix + +**Phase 4: Test Hypothesis** +``` +# Good: Targeted test +Add a failing test that demonstrates the bug +Run test → Confirm it fails for the right reason + +# Bad: Shotgun debugging +Change random things hoping it works +``` + +**Phase 5: Fix** +- Fix the root cause, not symptoms +- Keep the fix minimal and focused +- Don't refactor unrelated code in bug fix + +**Phase 6: Verify** +- [ ] Failing test now passes +- [ ] All other tests still pass +- [ ] Manual verification in original context +- [ ] No regression in related functionality + +**Git Bisect Workflow**: +```bash +# Start bisect +git bisect start + +# Mark current (broken) as bad +git bisect bad + +# Mark known good commit +git bisect good v1.2.0 + +# Git checks out middle commit - test it +# If broken: +git bisect bad +# If working: +git bisect good + +# Repeat until found +# Git outputs: " is the first bad commit" + +# Clean up +git bisect reset +``` + +**Log Analysis**: +| Log Level | When to Use | +|-----------|-------------| +| ERROR | Start here - what failed? | +| WARN | Look for preceding warnings | +| INFO | Trace the request flow | +| DEBUG | Enable for detailed state | +| TRACE | Last resort, very verbose | + +**Common Debugging Patterns**: + +| Pattern | Approach | +|---------|----------| +| Works locally, fails in CI | Environment diff, check secrets/config | +| Intermittent failure | Race condition, timing, resource exhaustion | +| Works in test, fails in prod | Config, scale, data differences | +| Regression after update | git bisect, check changelogs | +| Performance degradation | Profile, check N+1, memory leaks | + +**Documentation Requirements for Bug Fixes**: +Every bug fix commit/PR should include: +- Root cause analysis +- How it was found +- Why the fix works +- How to prevent similar bugs + +### 3.5 Core Configs + +- Update `SECURITY.md` with vulnerability reporting process +- Create `dependabot.yml` for cargo, npm, pip, actions + +### 3.6 justfile - Bundle Orchestration + +The justfile is the primary entry point for the bundle. It orchestrates the complete setup workflow from initial fork through configured repository. + +#### 3.6.1 Configuration Variables + +```just +# justfile - MCP Bundle Orchestration +# ==================================== + +# Configuration (can be overridden via environment or .env file) +set dotenv-load := true + +# ───────────────────────────────────────────────────────────────── +# REQUIRED CONFIGURATION +# ───────────────────────────────────────────────────────────────── + +# Git username (auto-detected if not set) +git_username := `git config user.name 2>/dev/null || echo ""` + +# GitHub username (auto-detected if not set) +github_username := `gh api user -q .login 2>/dev/null || echo ""` + +# ───────────────────────────────────────────────────────────────── +# OPTIONAL CONFIGURATION (with defaults) +# ───────────────────────────────────────────────────────────────── + +# Language preference: rust | golang | typescript | python +language := env_var_or_default("MCP_LANGUAGE", "rust") + +# Clone method: ssh | https +clone_method := env_var_or_default("MCP_CLONE_METHOD", "https") + +# AI Agent preference: zed | claude | copilot | codex | gemini | cursor | windsurf | vscode +ai_agent := env_var_or_default("MCP_AI_AGENT", "claude") + +# 1Password vault name prefix +op_vault_prefix := env_var_or_default("MCP_OP_VAULT_PREFIX", "mcp") + +# Template repositories by language +tmpl_rust := "aRustyDev/tmpl-rust" +tmpl_golang := "aRustyDev/tmpl-golang" +tmpl_typescript := "aRustyDev/tmpl-typescript" +tmpl_python := "aRustyDev/tmpl-python" + +# ───────────────────────────────────────────────────────────────── +# DERIVED VALUES +# ───────────────────────────────────────────────────────────────── + +# Select template based on language +template := if language == "rust" { tmpl_rust } else { + if language == "golang" { tmpl_golang } else { + if language == "typescript" { tmpl_typescript } else { + if language == "python" { tmpl_python } else { tmpl_rust } + } + } +} +``` + +#### 3.6.2 Workflow Overview + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ BUNDLE INIT WORKFLOW │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ User runs: just init / │ +│ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 1. PREFLIGHT CHECKS │ │ +│ │ ├── Verify gh CLI authenticated │ │ +│ │ ├── Verify op CLI authenticated │ │ +│ │ ├── Check if fork already exists │ │ +│ │ ├── Check if repo already exists for language │ │ +│ │ └── Validate configuration │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 2. REPOSITORY SETUP │ │ +│ │ ├── Fork target → /fork- │ │ +│ │ ├── Create from template → / │ │ +│ │ └── Configure repository settings │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 3. LOCAL CLONE │ │ +│ │ ├── Clone fork (ssh or https based on config) │ │ +│ │ ├── Clone new repo (ssh or https based on config) │ │ +│ │ └── Set up remotes │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 4. 1PASSWORD SETUP │ │ +│ │ ├── Create vault: - │ │ +│ │ ├── Store GitHub token │ │ +│ │ ├── Store SSH keys (if applicable) │ │ +│ │ └── Store any required API keys │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 5. ISSUE CREATION │ │ +│ │ ├── Create setup milestone │ │ +│ │ ├── Create issues for each bundle phase │ │ +│ │ └── Link issues to milestone │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 6. BUNDLE APPLICATION │ │ +│ │ ├── Copy bundle files to new repo │ │ +│ │ ├── Configure based on language/agent preferences │ │ +│ │ ├── Create surgical commits per phase │ │ +│ │ └── Update issues as progress occurs │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────────────────────────────────────────────────────┐ │ +│ │ 7. FINALIZATION │ │ +│ │ ├── Configure AI agent files (.cursor/, .zed/, etc.) │ │ +│ │ ├── Run pre-commit install │ │ +│ │ ├── Close setup issues/milestone │ │ +│ │ └── Display summary and next steps │ │ +│ └──────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +#### 3.6.3 Core Recipes + +```just +# ───────────────────────────────────────────────────────────────── +# MAIN ENTRY POINT +# ───────────────────────────────────────────────────────────────── + +# Initialize a new MCP server project +# Usage: just init / +init target: + @echo "🚀 Initializing MCP project from {{target}}" + @just _preflight "{{target}}" + @just _setup-repos "{{target}}" + @just _clone-repos "{{target}}" + @just _setup-1password "{{target}}" + @just _create-issues "{{target}}" + @just _apply-bundle "{{target}}" + @just _finalize "{{target}}" + @echo "✅ Project initialized successfully!" + @just _show-summary "{{target}}" + +# Interactive configuration wizard +configure: + @echo "🔧 MCP Bundle Configuration Wizard" + @echo "" + @echo "Current settings:" + @echo " Language: {{language}}" + @echo " Clone method: {{clone_method}}" + @echo " AI Agent: {{ai_agent}}" + @echo "" + @just _select-language + @just _select-clone-method + @just _select-ai-agent + @echo "" + @echo "Configuration saved to .env" + +# ───────────────────────────────────────────────────────────────── +# CONFIGURATION SELECTION +# ───────────────────────────────────────────────────────────────── + +# Select language preference +_select-language: + #!/usr/bin/env bash + set -euo pipefail + echo "Select language:" + echo " 1) rust (default)" + echo " 2) golang" + echo " 3) typescript" + echo " 4) python" + read -p "Choice [1-4]: " choice + case "$choice" in + 1|"") lang="rust" ;; + 2) lang="golang" ;; + 3) lang="typescript" ;; + 4) lang="python" ;; + *) echo "Invalid choice"; exit 1 ;; + esac + echo "MCP_LANGUAGE=$lang" >> .env + echo "Selected: $lang" + +# Select clone method +_select-clone-method: + #!/usr/bin/env bash + set -euo pipefail + echo "Select clone method:" + echo " 1) https (default)" + echo " 2) ssh" + read -p "Choice [1-2]: " choice + case "$choice" in + 1|"") method="https" ;; + 2) method="ssh" ;; + *) echo "Invalid choice"; exit 1 ;; + esac + echo "MCP_CLONE_METHOD=$method" >> .env + echo "Selected: $method" + +# Select AI agent preference +_select-ai-agent: + #!/usr/bin/env bash + set -euo pipefail + echo "Select AI agent preference:" + echo " 1) claude (default)" + echo " 2) cursor" + echo " 3) copilot" + echo " 4) zed" + echo " 5) windsurf" + echo " 6) vscode" + echo " 7) codex" + echo " 8) gemini" + read -p "Choice [1-8]: " choice + case "$choice" in + 1|"") agent="claude" ;; + 2) agent="cursor" ;; + 3) agent="copilot" ;; + 4) agent="zed" ;; + 5) agent="windsurf" ;; + 6) agent="vscode" ;; + 7) agent="codex" ;; + 8) agent="gemini" ;; + *) echo "Invalid choice"; exit 1 ;; + esac + echo "MCP_AI_AGENT=$agent" >> .env + echo "Selected: $agent" + +# ───────────────────────────────────────────────────────────────── +# PREFLIGHT CHECKS +# ───────────────────────────────────────────────────────────────── + +_preflight target: + #!/usr/bin/env bash + set -euo pipefail + echo "📋 Running preflight checks..." + + # Parse target + target_owner=$(echo "{{target}}" | cut -d'/' -f1) + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + + # Check gh CLI + if ! command -v gh &> /dev/null; then + echo "❌ gh CLI not found. Install: https://cli.github.com/" + exit 1 + fi + + if ! gh auth status &> /dev/null; then + echo "❌ gh CLI not authenticated. Run: gh auth login" + exit 1 + fi + echo "✓ gh CLI authenticated" + + # Check op CLI + if ! command -v op &> /dev/null; then + echo "❌ 1Password CLI not found. Install: https://1password.com/downloads/command-line/" + exit 1 + fi + + if ! op account list &> /dev/null; then + echo "❌ 1Password CLI not authenticated. Run: eval $(op signin)" + exit 1 + fi + echo "✓ 1Password CLI authenticated" + + # Check if fork already exists + fork_name="fork-${target_repo}" + if gh repo view "{{github_username}}/${fork_name}" &> /dev/null; then + echo "⚠️ Fork already exists: {{github_username}}/${fork_name}" + read -p "Continue anyway? [y/N]: " confirm + [[ "$confirm" =~ ^[Yy]$ ]] || exit 1 + else + echo "✓ Fork does not exist yet" + fi + + # Check if repo already exists for this language + if gh repo view "{{github_username}}/${target_repo}" &> /dev/null; then + echo "⚠️ Repository already exists: {{github_username}}/${target_repo}" + read -p "Continue anyway? [y/N]: " confirm + [[ "$confirm" =~ ^[Yy]$ ]] || exit 1 + else + echo "✓ Target repository does not exist yet" + fi + + echo "✅ Preflight checks passed" + +# ───────────────────────────────────────────────────────────────── +# REPOSITORY SETUP +# ───────────────────────────────────────────────────────────────── + +_setup-repos target: + #!/usr/bin/env bash + set -euo pipefail + echo "🔧 Setting up repositories..." + + target_owner=$(echo "{{target}}" | cut -d'/' -f1) + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + fork_name="fork-${target_repo}" + + # Fork target repository + echo "Forking {{target}} → {{github_username}}/${fork_name}..." + gh repo fork "{{target}}" --clone=false --fork-name="${fork_name}" || { + echo "Fork may already exist, continuing..." + } + + # Create from template + echo "Creating {{github_username}}/${target_repo} from {{template}}..." + gh repo create "{{github_username}}/${target_repo}" \ + --template="{{template}}" \ + --private \ + --description="MCP Server: ${target_repo}" || { + echo "Repository may already exist, continuing..." + } + + # Configure repository settings + echo "Configuring repository settings..." + gh repo edit "{{github_username}}/${target_repo}" \ + --enable-issues \ + --enable-wiki \ + --enable-projects \ + --delete-branch-on-merge \ + --enable-auto-merge || true + + echo "✅ Repositories configured" + +# ───────────────────────────────────────────────────────────────── +# LOCAL CLONE +# ───────────────────────────────────────────────────────────────── + +_clone-repos target: + #!/usr/bin/env bash + set -euo pipefail + echo "📥 Cloning repositories locally..." + + target_owner=$(echo "{{target}}" | cut -d'/' -f1) + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + fork_name="fork-${target_repo}" + + # Determine clone URL format + if [[ "{{clone_method}}" == "ssh" ]]; then + fork_url="git@github.com:{{github_username}}/${fork_name}.git" + repo_url="git@github.com:{{github_username}}/${target_repo}.git" + upstream_url="git@github.com:${target_owner}/${target_repo}.git" + else + fork_url="https://github.com/{{github_username}}/${fork_name}.git" + repo_url="https://github.com/{{github_username}}/${target_repo}.git" + upstream_url="https://github.com/${target_owner}/${target_repo}.git" + fi + + # Create workspace directory + workspace="${HOME}/mcp-workspace/${target_repo}" + mkdir -p "${workspace}" + cd "${workspace}" + + # Clone fork + if [[ ! -d "${fork_name}" ]]; then + echo "Cloning fork..." + git clone "${fork_url}" "${fork_name}" + cd "${fork_name}" + git remote add upstream "${upstream_url}" + cd .. + else + echo "Fork already cloned" + fi + + # Clone new repo + if [[ ! -d "${target_repo}" ]]; then + echo "Cloning new repository..." + git clone "${repo_url}" "${target_repo}" + else + echo "Repository already cloned" + fi + + echo "✅ Repositories cloned to ${workspace}" + +# ───────────────────────────────────────────────────────────────── +# 1PASSWORD SETUP +# ───────────────────────────────────────────────────────────────── + +_setup-1password target: + #!/usr/bin/env bash + set -euo pipefail + echo "🔐 Setting up 1Password vault..." + + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + vault_name="{{op_vault_prefix}}-${target_repo}" + + # Create vault if it doesn't exist + if ! op vault get "${vault_name}" &> /dev/null; then + echo "Creating vault: ${vault_name}" + op vault create "${vault_name}" --description "MCP Server: ${target_repo}" + else + echo "Vault already exists: ${vault_name}" + fi + + # Store GitHub token (if not already stored) + if ! op item get "github-token" --vault="${vault_name}" &> /dev/null; then + echo "Storing GitHub token..." + gh_token=$(gh auth token) + op item create \ + --category=api_credential \ + --title="github-token" \ + --vault="${vault_name}" \ + "credential=${gh_token}" \ + "hostname=github.com" \ + "type=pat" + fi + + # Store repository URLs + op item create \ + --category=secure_note \ + --title="repository-info" \ + --vault="${vault_name}" \ + "fork_repo={{github_username}}/fork-${target_repo}" \ + "main_repo={{github_username}}/${target_repo}" \ + "upstream={{target}}" \ + "language={{language}}" \ + "ai_agent={{ai_agent}}" 2>/dev/null || true + + echo "✅ 1Password vault configured: ${vault_name}" + +# ───────────────────────────────────────────────────────────────── +# ISSUE CREATION +# ───────────────────────────────────────────────────────────────── + +_create-issues target: + #!/usr/bin/env bash + set -euo pipefail + echo "📝 Creating setup issues..." + + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + repo="{{github_username}}/${target_repo}" + + # Create milestone + milestone_url=$(gh api repos/${repo}/milestones \ + -f title="Initial Setup" \ + -f description="Bundle configuration and repository setup" \ + -f state="open" \ + --jq '.number' 2>/dev/null) || milestone_url="" + + # Create issues for each phase + phases=( + "Phase 00: Manual Setup|Complete manual configuration steps (wiki, secrets, branch protection)" + "Phase 01: Foundation|Add issue templates, PR template, labels, AGENT.md" + "Phase 02: Build Pipelines|Configure build workflows for {{language}}" + "Phase 03: Code Quality|Set up linting and formatting" + "Phase 14: Security - Dependencies|Configure dependency scanning" + "Phase 24: Release - Versioning|Set up semantic release" + ) + + for phase in "${phases[@]}"; do + title=$(echo "$phase" | cut -d'|' -f1) + body=$(echo "$phase" | cut -d'|' -f2) + + gh issue create \ + --repo="${repo}" \ + --title="${title}" \ + --body="${body} + +--- +*Created by MCP Bundle init*" \ + --label="setup" \ + ${milestone_url:+--milestone="${milestone_url}"} || true + done + + echo "✅ Setup issues created" + +# ───────────────────────────────────────────────────────────────── +# BUNDLE APPLICATION +# ───────────────────────────────────────────────────────────────── + +_apply-bundle target: + #!/usr/bin/env bash + set -euo pipefail + echo "📦 Applying bundle to repository..." + + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + workspace="${HOME}/mcp-workspace/${target_repo}/${target_repo}" + bundle_dir="$(pwd)" + + cd "${workspace}" + + # Copy and configure based on language + echo "Copying bundle files..." + + # Phase 01: Foundation files + mkdir -p .github/ISSUE_TEMPLATE + cp -r "${bundle_dir}/.github/ISSUE_TEMPLATE/"* .github/ISSUE_TEMPLATE/ 2>/dev/null || true + cp "${bundle_dir}/.github/pull_request_template.md" .github/ 2>/dev/null || true + cp "${bundle_dir}/.github/labels.yml" .github/ 2>/dev/null || true + cp "${bundle_dir}/AGENT.md" . 2>/dev/null || true + + git add . + git commit -m "chore(setup): add Phase 01 foundation files + +- Issue templates +- PR template +- Labels configuration +- AGENT.md + +Part of: Phase 01: Foundation" || true + + # Language-specific configuration + case "{{language}}" in + rust) + just _apply-rust-config + ;; + golang) + just _apply-golang-config + ;; + typescript) + just _apply-typescript-config + ;; + python) + just _apply-python-config + ;; + esac + + # AI Agent configuration + just _apply-agent-config + + # Push changes + git push origin main + + echo "✅ Bundle applied" + +# Language-specific configurations +_apply-rust-config: + #!/usr/bin/env bash + echo "Applying Rust-specific configuration..." + # Copy Rust-specific workflows + # cargo deny, cargo audit, etc. + +_apply-golang-config: + #!/usr/bin/env bash + echo "Applying Go-specific configuration..." + # Copy Go-specific workflows + +_apply-typescript-config: + #!/usr/bin/env bash + echo "Applying TypeScript-specific configuration..." + # Copy TypeScript/Node-specific workflows + +_apply-python-config: + #!/usr/bin/env bash + echo "Applying Python-specific configuration..." + # Copy Python-specific workflows + +# ───────────────────────────────────────────────────────────────── +# AI AGENT CONFIGURATION +# ───────────────────────────────────────────────────────────────── + +_apply-agent-config: + #!/usr/bin/env bash + set -euo pipefail + echo "Configuring AI agent: {{ai_agent}}..." + + case "{{ai_agent}}" in + claude) + mkdir -p .claude + # Copy Claude Code configuration + ;; + cursor) + mkdir -p .cursor + # Copy Cursor configuration + ;; + copilot) + mkdir -p .github + # Copy GitHub Copilot configuration + ;; + zed) + mkdir -p .zed + # Copy Zed configuration + ;; + windsurf) + mkdir -p .windsurf + # Copy Windsurf configuration + ;; + vscode) + mkdir -p .vscode + # Copy VS Code configuration + ;; + codex) + # Copy Codex configuration + ;; + gemini) + # Copy Gemini configuration + ;; + esac + + git add . 2>/dev/null || true + git commit -m "chore(setup): configure {{ai_agent}} AI agent" 2>/dev/null || true + +# ───────────────────────────────────────────────────────────────── +# FINALIZATION +# ───────────────────────────────────────────────────────────────── + +_finalize target: + #!/usr/bin/env bash + set -euo pipefail + echo "🏁 Finalizing setup..." + + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + workspace="${HOME}/mcp-workspace/${target_repo}/${target_repo}" + + cd "${workspace}" + + # Install pre-commit hooks + if command -v pre-commit &> /dev/null; then + pre-commit install + pre-commit install --hook-type commit-msg + fi + + # Install cocogitto (if Rust toolchain available) + if command -v cargo &> /dev/null; then + cargo install cocogitto 2>/dev/null || true + fi + + echo "✅ Setup finalized" + +_show-summary target: + #!/usr/bin/env bash + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + workspace="${HOME}/mcp-workspace/${target_repo}" + + echo "" + echo "═══════════════════════════════════════════════════════════════" + echo " MCP PROJECT INITIALIZED" + echo "═══════════════════════════════════════════════════════════════" + echo "" + echo "📁 Workspace: ${workspace}" + echo "🔀 Fork: {{github_username}}/fork-${target_repo}" + echo "📦 Repository: {{github_username}}/${target_repo}" + echo "🔐 1Password: {{op_vault_prefix}}-${target_repo}" + echo "" + echo "Configuration:" + echo " Language: {{language}}" + echo " Clone method: {{clone_method}}" + echo " AI Agent: {{ai_agent}}" + echo "" + echo "Next steps:" + echo " 1. cd ${workspace}/${target_repo}" + echo " 2. Review created issues: gh issue list" + echo " 3. Complete Phase 00 manual steps" + echo " 4. Start development!" + echo "" + echo "═══════════════════════════════════════════════════════════════" + +# ───────────────────────────────────────────────────────────────── +# VERIFICATION RECIPES +# ───────────────────────────────────────────────────────────────── + +# Test repository readiness - verify setup is complete +# Usage: just test-readiness / +test-readiness target: + #!/usr/bin/env bash + set -euo pipefail + + target_owner=$(echo "{{target}}" | cut -d'/' -f1) + target_repo=$(echo "{{target}}" | cut -d'/' -f2) + fork_name="fork-${target_repo}" + repo="{{github_username}}/${target_repo}" + vault_name="{{op_vault_prefix}}-${target_repo}" + workspace="${HOME}/mcp-workspace/${target_repo}/${target_repo}" + + echo "═══════════════════════════════════════════════════════════════" + echo " MCP PROJECT READINESS CHECK" + echo "═══════════════════════════════════════════════════════════════" + echo "" + + passed=0 + failed=0 + warnings=0 + + # Helper functions + check_pass() { echo " ✅ $1"; ((passed++)); } + check_fail() { echo " ❌ $1"; ((failed++)); } + check_warn() { echo " ⚠️ $1"; ((warnings++)); } + section() { echo ""; echo "▶ $1"; echo " ────────────────────────────────────────"; } + + # ───────────────────────────────────────────────────────────── + section "Remote Repositories" + # ───────────────────────────────────────────────────────────── + + # Check main repo exists + if gh repo view "${repo}" &> /dev/null; then + check_pass "Repository exists: ${repo}" + else + check_fail "Repository not found: ${repo}" + fi + + # Check fork exists + if gh repo view "{{github_username}}/${fork_name}" &> /dev/null; then + check_pass "Fork exists: {{github_username}}/${fork_name}" + else + check_fail "Fork not found: {{github_username}}/${fork_name}" + fi + + # Check upstream accessible + if gh repo view "{{target}}" &> /dev/null; then + check_pass "Upstream accessible: {{target}}" + else + check_warn "Upstream not accessible: {{target}}" + fi + + # ───────────────────────────────────────────────────────────── + section "Repository Settings" + # ───────────────────────────────────────────────────────────── + + # Check wiki enabled + wiki_enabled=$(gh repo view "${repo}" --json hasWikiEnabled -q '.hasWikiEnabled' 2>/dev/null || echo "false") + if [[ "$wiki_enabled" == "true" ]]; then + check_pass "Wiki enabled" + # Check if wiki has content (Home page exists) + if curl -sf "https://github.com/${repo}/wiki" | grep -q "Home" 2>/dev/null; then + check_pass "Wiki initialized (Home page exists)" + else + check_warn "Wiki enabled but may not be initialized (Phase 00 manual step)" + fi + else + check_fail "Wiki not enabled" + fi + + # Check issues enabled + issues_enabled=$(gh repo view "${repo}" --json hasIssuesEnabled -q '.hasIssuesEnabled' 2>/dev/null || echo "false") + if [[ "$issues_enabled" == "true" ]]; then + check_pass "Issues enabled" + else + check_fail "Issues not enabled" + fi + + # Check branch protection (requires admin access) + if gh api "repos/${repo}/branches/main/protection" &> /dev/null; then + check_pass "Branch protection configured on main" + else + check_warn "Branch protection not configured (Phase 00 manual step)" + fi + + # ───────────────────────────────────────────────────────────── + section "Required Files (Remote)" + # ───────────────────────────────────────────────────────────── + + # Check AGENT.md + if gh api "repos/${repo}/contents/AGENT.md" &> /dev/null; then + check_pass "AGENT.md present" + else + check_fail "AGENT.md missing" + fi + + # Check PR template + if gh api "repos/${repo}/contents/.github/pull_request_template.md" &> /dev/null; then + check_pass "PR template present" + else + check_fail "PR template missing" + fi + + # Check issue templates directory + if gh api "repos/${repo}/contents/.github/ISSUE_TEMPLATE" &> /dev/null; then + template_count=$(gh api "repos/${repo}/contents/.github/ISSUE_TEMPLATE" --jq 'length' 2>/dev/null || echo "0") + if [[ "$template_count" -ge 5 ]]; then + check_pass "Issue templates present (${template_count} files)" + else + check_warn "Issue templates incomplete (${template_count}/5+ expected)" + fi + else + check_fail "Issue templates directory missing" + fi + + # Check labels.yml + if gh api "repos/${repo}/contents/.github/labels.yml" &> /dev/null; then + check_pass "labels.yml present" + else + check_warn "labels.yml missing (labels may be applied directly)" + fi + + # Check MCP configs + if gh api "repos/${repo}/contents/.mcp/servers.json" &> /dev/null; then + check_pass "MCP project config present (.mcp/servers.json)" + else + check_fail "MCP project config missing" + fi + + # ───────────────────────────────────────────────────────────── + section "Local Workspace" + # ───────────────────────────────────────────────────────────── + + if [[ -d "${workspace}" ]]; then + check_pass "Local workspace exists: ${workspace}" + + # Check git repo + if [[ -d "${workspace}/.git" ]]; then + check_pass "Git repository initialized" + + # Check remotes + cd "${workspace}" + if git remote get-url origin &> /dev/null; then + check_pass "Git remote 'origin' configured" + else + check_fail "Git remote 'origin' not configured" + fi + + # Check pre-commit hooks + if [[ -f ".git/hooks/pre-commit" ]]; then + check_pass "pre-commit hook installed" + else + check_warn "pre-commit hook not installed" + fi + + if [[ -f ".git/hooks/commit-msg" ]]; then + check_pass "commit-msg hook installed" + else + check_warn "commit-msg hook not installed" + fi + else + check_fail "Not a git repository" + fi + + # Check local files + if [[ -f "${workspace}/AGENT.md" ]]; then + check_pass "AGENT.md present locally" + else + check_fail "AGENT.md missing locally" + fi + + if [[ -f "${workspace}/.mcp/servers.json" ]]; then + check_pass "MCP config present locally" + else + check_fail "MCP config missing locally" + fi + + else + check_fail "Local workspace not found: ${workspace}" + fi + + # ───────────────────────────────────────────────────────────── + section "1Password Vault" + # ───────────────────────────────────────────────────────────── + + if command -v op &> /dev/null; then + if op vault get "${vault_name}" &> /dev/null; then + check_pass "1Password vault exists: ${vault_name}" + + # Check for github token + if op item get "github-token" --vault="${vault_name}" &> /dev/null; then + check_pass "GitHub token stored in vault" + else + check_warn "GitHub token not found in vault" + fi + + # Check for repo info + if op item get "repository-info" --vault="${vault_name}" &> /dev/null; then + check_pass "Repository info stored in vault" + else + check_warn "Repository info not found in vault" + fi + else + check_fail "1Password vault not found: ${vault_name}" + fi + else + check_warn "1Password CLI not installed - skipping vault checks" + fi + + # ───────────────────────────────────────────────────────────── + section "Local Development Tools" + # ───────────────────────────────────────────────────────────── + + # Check pre-commit + if command -v pre-commit &> /dev/null; then + check_pass "pre-commit installed" + else + check_warn "pre-commit not installed" + fi + + # Check cocogitto + if command -v cog &> /dev/null; then + check_pass "cocogitto (cog) installed" + else + check_warn "cocogitto not installed" + fi + + # Check gh CLI + if command -v gh &> /dev/null; then + if gh auth status &> /dev/null; then + check_pass "gh CLI installed and authenticated" + else + check_warn "gh CLI installed but not authenticated" + fi + else + check_fail "gh CLI not installed" + fi + + # Check jq (for MCP config merging) + if command -v jq &> /dev/null; then + check_pass "jq installed" + else + check_warn "jq not installed (MCP config merging may be limited)" + fi + + # ───────────────────────────────────────────────────────────── + section "GitHub Labels" + # ───────────────────────────────────────────────────────────── + + label_count=$(gh label list --repo "${repo}" --json name --jq 'length' 2>/dev/null || echo "0") + if [[ "$label_count" -ge 50 ]]; then + check_pass "Labels configured (${label_count} labels)" + elif [[ "$label_count" -ge 10 ]]; then + check_warn "Some labels configured (${label_count} labels, expected 50+)" + else + check_fail "Labels not configured (${label_count} labels)" + fi + + # ───────────────────────────────────────────────────────────── + section "Setup Issues" + # ───────────────────────────────────────────────────────────── + + setup_issues=$(gh issue list --repo "${repo}" --label "setup" --json number --jq 'length' 2>/dev/null || echo "0") + if [[ "$setup_issues" -gt 0 ]]; then + check_pass "Setup issues created (${setup_issues} issues)" + else + check_warn "No setup issues found" + fi + + # ───────────────────────────────────────────────────────────── + # Summary + # ───────────────────────────────────────────────────────────── + echo "" + echo "═══════════════════════════════════════════════════════════════" + echo " SUMMARY" + echo "═══════════════════════════════════════════════════════════════" + echo "" + echo " ✅ Passed: ${passed}" + echo " ❌ Failed: ${failed}" + echo " ⚠️ Warnings: ${warnings}" + echo "" + + if [[ "$failed" -eq 0 ]]; then + if [[ "$warnings" -eq 0 ]]; then + echo " 🎉 Repository is FULLY READY for development!" + else + echo " ✓ Repository is READY (review warnings for optional improvements)" + fi + exit 0 + else + echo " ⛔ Repository has FAILED checks - review above for details" + echo "" + echo " Common fixes:" + echo " - Complete Phase 00 manual steps (wiki, branch protection, secrets)" + echo " - Re-run: just init {{target}}" + echo " - Check: just show-config" + exit 1 + fi + +# ───────────────────────────────────────────────────────────────── +# UTILITY RECIPES +# ───────────────────────────────────────────────────────────────── + +# Show current configuration +show-config: + @echo "Current MCP Bundle Configuration:" + @echo " Language: {{language}}" + @echo " Clone method: {{clone_method}}" + @echo " AI Agent: {{ai_agent}}" + @echo " Template: {{template}}" + @echo " GitHub user: {{github_username}}" + +# Validate prerequisites +check: + @just _preflight "test/test" + +# Clean up .env file +clean-config: + @rm -f .env + @echo "Configuration cleared" + +# List available templates +list-templates: + @echo "Available templates by language:" + @echo " rust: {{tmpl_rust}}" + @echo " golang: {{tmpl_golang}}" + @echo " typescript: {{tmpl_typescript}}" + @echo " python: {{tmpl_python}}" + +# List supported AI agents +list-agents: + @echo "Supported AI agents:" + @echo " - claude (Claude Code / Anthropic)" + @echo " - cursor (Cursor IDE)" + @echo " - copilot (GitHub Copilot)" + @echo " - zed (Zed Editor)" + @echo " - windsurf (Windsurf)" + @echo " - vscode (VS Code)" + @echo " - codex (OpenAI Codex)" + @echo " - gemini (Google Gemini)" + +# Help +help: + @echo "MCP Bundle - Project Initialization Tool" + @echo "" + @echo "Usage:" + @echo " just init / Initialize new MCP project" + @echo " just test-readiness / Verify setup is complete" + @echo " just configure Interactive configuration wizard" + @echo " just show-config Show current configuration" + @echo " just check Validate prerequisites" + @echo "" + @echo "Configuration:" + @echo " Set via environment variables or .env file:" + @echo " MCP_LANGUAGE=rust|golang|typescript|python" + @echo " MCP_CLONE_METHOD=https|ssh" + @echo " MCP_AI_AGENT=claude|cursor|copilot|zed|windsurf|vscode|codex|gemini" + @echo "" + @echo "Example:" + @echo " just configure" + @echo " just init modelcontextprotocol/servers" + @echo " just test-readiness modelcontextprotocol/servers" +``` + +#### 3.6.4 AI Agent Configuration Files + +Each AI agent requires specific configuration files: + +| Agent | Config Directory | Key Files | +|-------|-----------------|-----------| +| Claude | `.claude/` | `settings.json`, `CLAUDE.md` | +| Cursor | `.cursor/` | `settings.json`, `rules/` | +| Copilot | `.github/` | `copilot-instructions.md` | +| Zed | `.zed/` | `settings.json` | +| Windsurf | `.windsurf/` | `rules.md` | +| VS Code | `.vscode/` | `settings.json`, `extensions.json` | +| Codex | `.codex/` | `config.json` | +| Gemini | `.gemini/` | `context.md` | + +#### 3.6.5 1Password Integration + +The justfile leverages 1Password CLI for secure credential management: + +```bash +# Vault structure +mcp-/ +├── github-token # GitHub PAT +├── repository-info # Repo metadata (secure note) +├── npm-token # If TypeScript (optional) +├── cargo-token # If Rust (optional) +├── pypi-token # If Python (optional) +└── secrets/ # Project-specific secrets +``` + +### 3.7 MCP Client Configurations + +The bundle includes MCP client configurations (mcp.json) for AI-assisted MCP server development. Both **global** (system-wide) and **project-local** (repository-specific) configurations are provided. + +#### 3.7.1 Configuration Strategy + +| Type | Location | Enabled by Default | Purpose | +|------|----------|-------------------|---------| +| Project-local | `.mcp/servers.json` | **Yes** | Development servers for this repo | +| Global template | `configs/mcp/global/` | No | System-wide server configs (copy to system location) | + +> **Default Behavior**: Only project-local configs are active after bundle application. Global configs are provided as templates that users can manually install to their system config location. + +#### 3.7.2 Project-Local Configuration + +**File**: `.mcp/servers.json` + +```json +{ + "$schema": "https://modelcontextprotocol.io/schemas/mcp-servers.json", + "mcpServers": { + "filesystem": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-filesystem", "."], + "description": "Read-only access to project files" + }, + "git": { + "command": "uvx", + "args": ["mcp-server-git", "--repository", "."], + "description": "Git operations for development workflow" + }, + "fetch": { + "command": "uvx", + "args": ["mcp-server-fetch"], + "description": "HTTP requests for API testing" + }, + "sequential-thinking": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-sequential-thinking"], + "description": "Step-by-step reasoning for complex debugging" + } + } +} +``` + +#### 3.7.3 Global Configuration Templates + +**Directory**: `configs/mcp/global/` + +Provided as templates - users copy to their system config location: + +| Platform | Config Location | +|----------|-----------------| +| macOS (Claude Desktop) | `~/Library/Application Support/Claude/claude_desktop_config.json` | +| Linux (Claude Desktop) | `~/.config/claude/claude_desktop_config.json` | +| Windows (Claude Desktop) | `%APPDATA%\Claude\claude_desktop_config.json` | + +**File**: `configs/mcp/global/common-servers.json` + +```json +{ + "$schema": "https://modelcontextprotocol.io/schemas/mcp-servers.json", + "mcpServers": { + "context7": { + "command": "npx", + "args": ["-y", "@upstash/context7-mcp"], + "description": "Documentation lookup for libraries and frameworks", + "disabled": false + }, + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_PERSONAL_ACCESS_TOKEN": "" + }, + "description": "GitHub API operations", + "disabled": true + }, + "memory": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-memory"], + "description": "Persistent memory across sessions", + "disabled": true + }, + "brave-search": { + "command": "npx", + "args": ["-y", "@anthropic/mcp-server-brave-search"], + "env": { + "BRAVE_API_KEY": "" + }, + "description": "Web search via Brave", + "disabled": true + }, + "puppeteer": { + "command": "npx", + "args": ["-y", "@anthropic/mcp-server-puppeteer"], + "description": "Browser automation for testing", + "disabled": true + } + } +} +``` + +#### 3.7.4 Language-Specific Development Servers + +Additional servers based on language selection: + +**Rust** (`.mcp/servers-rust.json`): +```json +{ + "mcpServers": { + "rust-analyzer": { + "command": "mcp-server-rust-analyzer", + "description": "Rust language server integration", + "disabled": true + } + } +} +``` + +**TypeScript** (`.mcp/servers-typescript.json`): +```json +{ + "mcpServers": { + "typescript": { + "command": "npx", + "args": ["-y", "mcp-server-typescript"], + "description": "TypeScript language features", + "disabled": true + } + } +} +``` + +**Python** (`.mcp/servers-python.json`): +```json +{ + "mcpServers": { + "python": { + "command": "uvx", + "args": ["mcp-server-python"], + "description": "Python language features", + "disabled": true + } + } +} +``` + +#### 3.7.5 Integration with justfile + +The `_apply-agent-config` recipe merges MCP configs based on language and agent: + +```just +# Apply MCP client configurations +_apply-mcp-config: + #!/usr/bin/env bash + set -euo pipefail + echo "Configuring MCP client servers..." + + # Copy project-local config (always enabled) + mkdir -p .mcp + cp "${bundle_dir}/configs/mcp/project/servers.json" .mcp/ + + # Merge language-specific servers if available + lang_config="${bundle_dir}/configs/mcp/project/servers-{{language}}.json" + if [[ -f "$lang_config" ]]; then + # Merge using jq (if available) or simple concatenation + if command -v jq &> /dev/null; then + jq -s '.[0] * .[1]' .mcp/servers.json "$lang_config" > .mcp/servers.tmp + mv .mcp/servers.tmp .mcp/servers.json + fi + fi + + # Inform user about global configs + echo "" + echo "📋 Global MCP server templates available in: configs/mcp/global/" + echo " Copy to your system config location to enable globally." +``` + +#### 3.7.6 Bundle Structure (MCP Configs) + +``` +configs/ +└── mcp/ + ├── project/ # Project-local configs (enabled by default) + │ ├── servers.json # Common development servers + │ ├── servers-rust.json # Rust-specific servers + │ ├── servers-typescript.json # TypeScript-specific servers + │ ├── servers-python.json # Python-specific servers + │ └── servers-golang.json # Go-specific servers + └── global/ # Global config templates (manual install) + ├── common-servers.json # Commonly useful servers + ├── README.md # Installation instructions + └── install.sh # Optional install helper script +``` + +--- + +## 4. Review & Validation + +- [ ] All templates pass YAML validation +- [ ] Labels are unique (no duplicates) +- [ ] PR template renders correctly on GitHub +- [ ] AGENT.md is comprehensive and clear +- [ ] justfile recipes work end-to-end +- [ ] justfile supports all language options +- [ ] justfile supports all AI agent options +- [ ] 1Password vault creation works +- [ ] Issue creation works correctly +- [ ] MCP project-local configs valid JSON +- [ ] MCP global config templates valid JSON +- [ ] MCP config merge works with jq +- [ ] Language-specific MCP servers disabled by default +- [ ] test-readiness recipe runs without errors +- [ ] test-readiness detects missing Phase 00 items as warnings +- [ ] test-readiness exits non-zero on critical failures +- [ ] No scope creep into workflow files +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-02-build-pipelines.md b/.ai/plans/phases/bundle-contents-phase-02-build-pipelines.md new file mode 100644 index 0000000..c0c0a11 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-02-build-pipelines.md @@ -0,0 +1,125 @@ +--- +id: 173e85b4-ff31-4f5f-bc87-f09a8067a75b +title: "Phase 02: Build Pipelines" +status: pending +depends_on: + - 367b75a1-dd7d-4d34-9bf9-6aaab692c2ee # phase-01 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 02: Build Pipelines + +## 1. Current State Assessment + +- [ ] Check for existing build workflows +- [ ] Review caching strategies in place +- [ ] Identify supported language versions +- [ ] Check for matrix build configurations + +### Existing Assets + +None - build workflows not yet created. + +### Gaps Identified + +- [ ] Container build workflow (multi-arch) +- [ ] Rust build workflow (stable, beta, nightly) +- [ ] Python build workflow (3.10, 3.11, 3.12) +- [ ] Node build workflow (18, 20, 22) +- [ ] mdBook build workflow + +--- + +## 2. Contextual Goal + +Create standardized build workflows for all supported languages and platforms. Each workflow should include proper caching, matrix builds across supported versions, artifact uploads, and path-based triggering to avoid unnecessary builds. The container workflow must support multi-architecture builds (amd64, arm64) using buildx. + +### Success Criteria + +- [ ] All 5 build workflows created and validated +- [ ] Caching configured for each language +- [ ] Matrix builds cover all supported versions +- [ ] Path filters prevent unnecessary runs +- [ ] Artifacts uploaded with appropriate retention + +### Out of Scope + +- Linting (Phase 03) +- Testing (Phase 04+) +- Publishing (Phase 25-26) + +--- + +## 3. Implementation + +### 3.1 build-container.yml + +```yaml +# Features: +# - Multi-arch builds (linux/amd64, linux/arm64) +# - Layer caching via GHA cache +# - Metadata extraction for tags +# - SBOM and provenance generation +# - Push only on non-PR events +``` + +Key steps: +- Setup QEMU for multi-arch +- Setup Docker Buildx +- Login to GHCR (non-PR only) +- Extract metadata for tags +- Build and push with caching + +### 3.2 build-rust.yml + +```yaml +# Features: +# - Matrix: stable, beta, nightly on ubuntu/macos/windows +# - cargo caching via Swatinem/rust-cache +# - Format check on stable only +# - Release build on stable only +# - Minimal versions check +``` + +### 3.3 build-python.yml + +```yaml +# Features: +# - Matrix: Python 3.10, 3.11, 3.12 on ubuntu/macos/windows +# - pip caching +# - Build wheel and sdist +# - Artifact upload +``` + +### 3.4 build-node.yml + +```yaml +# Features: +# - Matrix: Node 18, 20, 22 +# - Auto-detect package manager (npm/pnpm/yarn) +# - Appropriate caching per manager +# - Build and artifact upload +``` + +### 3.5 build-mdbook.yml + +```yaml +# Features: +# - Build mdBook documentation +# - Install common plugins (mermaid, toc, linkcheck) +# - Link validation +# - Artifact upload +``` + +--- + +## 4. Review & Validation + +- [ ] All workflows pass `actionlint` +- [ ] Path filters work correctly +- [ ] Caching provides measurable speedup +- [ ] Matrix covers all supported versions +- [ ] Artifacts are correctly named and uploaded +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-03-code-quality.md b/.ai/plans/phases/bundle-contents-phase-03-code-quality.md new file mode 100644 index 0000000..7fcbcd0 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-03-code-quality.md @@ -0,0 +1,721 @@ +--- +id: e813a7bc-3a3e-4171-94c8-6bf0b363eb62 +title: "Phase 03: Code Quality" +status: pending +depends_on: + - 173e85b4-ff31-4f5f-bc87-f09a8067a75b # phase-02 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - linting-strategy-adr # ADR in ../docs/adr/ +issues: [] +--- + +# Phase 03: Code Quality + +## 1. Current State Assessment + +- [ ] Check for existing lint workflows +- [ ] Review language-specific linting tools used +- [ ] Identify SARIF upload capability +- [ ] Check for config files (clippy.toml, ruff.toml, etc.) + +### Existing Assets + +None - lint workflows not yet created. + +### Gaps Identified + +#### Language-Specific Linting +- [ ] Container lint (hadolint, dockle) +- [ ] Rust lint (clippy, rustfmt) +- [ ] Python lint (ruff, black, mypy) +- [ ] JavaScript lint (eslint, prettier) +- [ ] TypeScript lint (eslint, prettier, tsc) +- [ ] Go lint (golangci-lint) + +#### Configuration/Data File Linting +- [ ] Markdown lint (markdownlint) +- [ ] YAML lint (yamllint) +- [ ] Shell lint (shellcheck, shfmt) +- [ ] TOML lint (taplo) +- [ ] JSON lint (check-json, prettier) +- [ ] EditorConfig check (editorconfig-checker) + +#### Quality Assurance +- [ ] Spellcheck (typos-cli or cspell) +- [ ] Actions lint (actionlint) + +#### Commit Linting (Hybrid Approach) +- [ ] Cocogitto (cog.toml) - custom types, changelog, versioning +- [ ] commitlint (.commitlintrc.js) - header/body/footer validation +- [ ] lint-commits.yml workflow + +#### Pre-commit Integration +- [ ] .pre-commit-config.yaml +- [ ] pre-commit.ci configuration + +--- + +## 2. Contextual Goal + +Establish comprehensive code quality checks using a hybrid approach: pre-commit hooks for fast local feedback, pre-commit.ci for PR enforcement with auto-fixes, and individual GitHub workflows for SARIF output and extended analysis. Cover all file types including source code, configuration files, and documentation. Enforce conventional commits and spelling consistency. + +### Success Criteria + +- [ ] All language-specific lint workflows created (6 languages) +- [ ] All config file lint workflows created (TOML, JSON, YAML, Markdown) +- [ ] Pre-commit.yaml with unified local hooks +- [ ] pre-commit.ci integrated for auto-fixes +- [ ] SARIF output where supported +- [ ] Spellcheck catches typos in docs/comments +- [ ] Commit linting with hybrid Cocogitto + commitlint +- [ ] Custom commit types/scopes configurable +- [ ] Header/body/footer validation rules enforced +- [ ] Actions validated with actionlint + +### Out of Scope + +- Security-specific analysis (Phase 16 SAST) +- Test execution (Phase 04+) +- Helm chart linting (Phase 27) + +--- + +## 3. Implementation + +### 3.0 Linting Strategy (Hybrid Approach) + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ LINTING STRATEGY │ +├─────────────────────────────────────────────────────────────────────────┤ +│ Layer 1: LOCAL PRE-COMMIT (Fast Feedback) │ +│ • Format checks, fast lints, spelling, commit messages │ +│ • Runs: Every commit locally │ +├─────────────────────────────────────────────────────────────────────────┤ +│ Layer 2: PRE-COMMIT.CI (PR Enforcement) │ +│ • Same hooks as local, auto-fixes via commit │ +│ • Runs: Every PR │ +├─────────────────────────────────────────────────────────────────────────┤ +│ Layer 3: INDIVIDUAL WORKFLOWS (SARIF + Extended Analysis) │ +│ • SARIF → Security tab, type checking, slow/comprehensive checks │ +│ • Runs: Push to main, PR, scheduled │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +### 3.1 Pre-commit Configuration + +```yaml +# .pre-commit-config.yaml +ci: + autofix_prs: true + autofix_commit_msg: 'style: auto-fix by pre-commit.ci' + autoupdate_schedule: weekly + skip: [cargo-clippy] # Too slow for CI, run in workflow + +repos: + # General hooks + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.5.0 + hooks: + - id: check-toml + - id: check-json + - id: check-yaml + args: [--unsafe] # Allow custom tags + - id: end-of-file-fixer + - id: trailing-whitespace + - id: mixed-line-ending + - id: check-merge-conflict + + # Spelling + - repo: https://github.com/crate-ci/typos + rev: v1.16.0 + hooks: + - id: typos + + # Commit messages - Hybrid: Cocogitto (types/scopes) + commitlint (validation) + - repo: local + hooks: + - id: cocogitto + name: cocogitto (conventional commits check) + entry: cog check --from-latest-tag + language: system + stages: [commit-msg] + pass_filenames: false + + - id: commitlint + name: commitlint (header/body/footer validation) + entry: npx --no -- commitlint --edit + language: system + stages: [commit-msg] + pass_filenames: false + + # GitHub Actions + - repo: https://github.com/rhysd/actionlint + rev: v1.6.26 + hooks: + - id: actionlint + + # TOML + - repo: https://github.com/tamasfe/taplo + rev: 0.8.1 + hooks: + - id: taplo + + # Markdown + - repo: https://github.com/igorshubovych/markdownlint-cli + rev: v0.37.0 + hooks: + - id: markdownlint-fix + + # Shell + - repo: https://github.com/shellcheck-py/shellcheck-py + rev: v0.9.0.6 + hooks: + - id: shellcheck + + - repo: https://github.com/scop/pre-commit-shfmt + rev: v3.7.0-4 + hooks: + - id: shfmt + + # Rust + - repo: local + hooks: + - id: cargo-fmt + name: cargo fmt + entry: cargo fmt --all -- + language: system + types: [rust] + pass_filenames: false + + # Python + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.1.6 + hooks: + - id: ruff + args: [--fix] + - id: ruff-format + + # JavaScript/TypeScript + - repo: https://github.com/pre-commit/mirrors-eslint + rev: v8.54.0 + hooks: + - id: eslint + types: [javascript, typescript] + additional_dependencies: + - eslint-config-prettier + + - repo: https://github.com/pre-commit/mirrors-prettier + rev: v3.1.0 + hooks: + - id: prettier + types_or: [javascript, typescript, json, yaml, markdown] + + # EditorConfig + - repo: https://github.com/editorconfig-checker/editorconfig-checker.python + rev: 2.7.3 + hooks: + - id: editorconfig-checker +``` + +### 3.2 lint-container.yml + +Tools: +- **hadolint**: Dockerfile best practices (SARIF output) +- **dockle**: CIS benchmarks for images + +### 3.3 lint-rust.yml + +Jobs: +- **clippy**: Linting with `-D warnings` (SARIF via clippy-sarif) +- **rustfmt**: Format checking + +### 3.4 lint-python.yml + +Tools: +- **ruff**: Fast linting + formatting (SARIF output) +- **mypy**: Type checking + +### 3.5 lint-javascript.yml + +Tools: +- **eslint**: JS linting with security plugins (SARIF output) +- **prettier**: Format checking + +### 3.6 lint-typescript.yml + +Tools: +- **eslint**: TS linting (SARIF output) +- **prettier**: Format checking +- **tsc**: Type checking (--noEmit) + +### 3.7 lint-go.yml + +Tools: +- **golangci-lint**: Comprehensive Go linting (SARIF output) +- **gofmt**: Format checking + +### 3.8 lint-config.yml (Unified Config Linting) + +```yaml +name: Lint Config Files + +on: + push: + paths: + - '**/*.toml' + - '**/*.json' + - '**/*.yaml' + - '**/*.yml' + - '**/*.md' + - '.github/workflows/**' + pull_request: + paths: + - '**/*.toml' + - '**/*.json' + - '**/*.yaml' + - '**/*.yml' + - '**/*.md' + - '.github/workflows/**' + +jobs: + toml: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: tamasfe/taplo-action@v0.3.1 + with: + arguments: check + + yaml: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: yamllint + uses: ibiqlik/action-yamllint@v3 + + markdown: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: DavidAnson/markdownlint-cli2-action@v14 + + actionlint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: reviewdog/action-actionlint@v1 +``` + +### 3.9 lint-shell.yml + +Tools: +- **shellcheck**: Shell script linting (SARIF output) +- **shfmt**: Shell script formatting + +### 3.10 lint-spelling.yml + +```yaml +name: Spellcheck + +on: + push: + paths: + - '**/*.md' + - '**/*.rs' + - '**/*.py' + - '**/*.ts' + - '**/*.js' + pull_request: + +jobs: + typos: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: crate-ci/typos@master + with: + config: .typos.toml +``` + +### 3.11 Commit Linting (Hybrid Strategy) + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ COMMIT LINTING STRATEGY │ +├─────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ COCOGITTO (Rust) │ │ +│ │ Purpose: Custom types, scopes, changelog, versioning │ │ +│ │ Config: cog.toml │ │ +│ │ Commands: cog commit, cog check, cog bump, cog changelog │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ + │ +│ ┌─────────────────────────────────────────────────────────────────┐ │ +│ │ COMMITLINT (JavaScript) │ │ +│ │ Purpose: Header/body/footer validation, length limits │ │ +│ │ Config: .commitlintrc.js │ │ +│ │ Hooks: commit-msg via pre-commit │ │ +│ └─────────────────────────────────────────────────────────────────┘ │ +│ │ +│ Why both? │ +│ • Cocogitto: Best for custom types + automatic changelog/versioning │ +│ • commitlint: Best for detailed message validation rules │ +│ │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +#### 3.11.1 cog.toml (Cocogitto Configuration) + +```toml +# cog.toml - Cocogitto configuration for conventional commits + +# ───────────────────────────────────────────────────────────────────────────── +# CUSTOM COMMIT TYPES +# ───────────────────────────────────────────────────────────────────────────── +# Standard types + custom additions for MCP development + +[commit_types] +# Standard conventional commits +feat = { changelog_title = "✨ Features", order = 1, bump_minor = true } +fix = { changelog_title = "🐛 Bug Fixes", order = 2, bump_patch = true } +docs = { changelog_title = "📚 Documentation", order = 6 } +style = { changelog_title = "💄 Styling", order = 8 } +refactor = { changelog_title = "♻️ Refactoring", order = 7 } +perf = { changelog_title = "⚡ Performance", order = 3, bump_patch = true } +test = { changelog_title = "🧪 Tests", order = 9 } +build = { changelog_title = "📦 Build", order = 10 } +ci = { changelog_title = "👷 CI/CD", order = 11 } +chore = { changelog_title = "🔧 Chores", omit_from_changelog = true } +revert = { changelog_title = "⏪ Reverts", order = 5, bump_patch = true } + +# Custom types for this project +hotfix = { changelog_title = "🚑 Hotfixes", order = 0, bump_patch = true } +security = { changelog_title = "🔒 Security", order = 0, bump_patch = true } +deps = { changelog_title = "📦 Dependencies", order = 4, bump_patch = true } +wip = { omit_from_changelog = true } +release = { changelog_title = "🚀 Releases", omit_from_changelog = true } + +# ───────────────────────────────────────────────────────────────────────────── +# SCOPES (Optional - for validation and autocomplete) +# ───────────────────────────────────────────────────────────────────────────── +# Define allowed scopes for your project + +[scopes] +# Core components +core = "Core functionality" +api = "API layer" +cli = "Command-line interface" +config = "Configuration" + +# MCP-specific scopes +mcp = "MCP protocol" +transport = "Transport layer (stdio, sse, http)" +tools = "MCP tools" +resources = "MCP resources" +prompts = "MCP prompts" + +# Infrastructure +ci = "CI/CD pipelines" +docker = "Container configuration" +deps = "Dependencies" +docs = "Documentation" + +# ───────────────────────────────────────────────────────────────────────────── +# CHANGELOG CONFIGURATION +# ───────────────────────────────────────────────────────────────────────────── + +[changelog] +path = "CHANGELOG.md" +template = "remote" +remote = "github.com" +owner = "your-org" +repository = "your-repo" + +# Author mappings (git email → display name) +authors = [ + { username = "your-username", signature = "Your Name" }, +] + +# ───────────────────────────────────────────────────────────────────────────── +# VERSION BUMPING HOOKS +# ───────────────────────────────────────────────────────────────────────────── + +pre_bump_hooks = [ + "cargo fmt --check", + "cargo clippy -- -D warnings", + "cargo test --all-features", +] + +post_bump_hooks = [ + "cargo build --release", + "git push", + "git push origin {{version}}", +] + +# ───────────────────────────────────────────────────────────────────────────── +# MONOREPO SUPPORT (Optional) +# ───────────────────────────────────────────────────────────────────────────── + +# [packages.my-crate] +# path = "crates/my-crate" +# changelog_path = "crates/my-crate/CHANGELOG.md" +# include = ["crates/my-crate/**"] +# ignore = ["crates/my-crate/tests/**"] +``` + +#### 3.11.2 .commitlintrc.js (commitlint Configuration) + +```javascript +// .commitlintrc.js - Detailed commit message validation + +module.exports = { + extends: ['@commitlint/config-conventional'], + + // ───────────────────────────────────────────────────────────────────────── + // CUSTOM RULES + // ───────────────────────────────────────────────────────────────────────── + // Rule format: [level, applicable, value] + // Level: 0 = disable, 1 = warning, 2 = error + // Applicable: 'always' | 'never' + + rules: { + // ───────────────────────────────────────────────────────────────────── + // TYPE RULES (must match cog.toml types) + // ───────────────────────────────────────────────────────────────────── + 'type-enum': [2, 'always', [ + // Standard types + 'feat', 'fix', 'docs', 'style', 'refactor', + 'perf', 'test', 'build', 'ci', 'chore', 'revert', + // Custom types (must match cog.toml) + 'hotfix', 'security', 'deps', 'wip', 'release', + ]], + 'type-case': [2, 'always', 'lower-case'], + 'type-empty': [2, 'never'], + + // ───────────────────────────────────────────────────────────────────── + // SCOPE RULES (must match cog.toml scopes) + // ───────────────────────────────────────────────────────────────────── + 'scope-enum': [2, 'always', [ + // Core + 'core', 'api', 'cli', 'config', + // MCP-specific + 'mcp', 'transport', 'tools', 'resources', 'prompts', + // Infrastructure + 'ci', 'docker', 'deps', 'docs', + ]], + 'scope-case': [2, 'always', 'lower-case'], + 'scope-empty': [1, 'never'], // Warning if no scope (not error) + + // ───────────────────────────────────────────────────────────────────── + // HEADER RULES (type(scope): subject) + // ───────────────────────────────────────────────────────────────────── + 'header-max-length': [2, 'always', 72], + 'header-min-length': [2, 'always', 10], + 'header-full-stop': [2, 'never', '.'], + 'header-trim': [2, 'always'], + + // ───────────────────────────────────────────────────────────────────── + // SUBJECT RULES + // ───────────────────────────────────────────────────────────────────── + 'subject-case': [2, 'never', [ + 'sentence-case', + 'start-case', + 'pascal-case', + 'upper-case', + ]], + 'subject-empty': [2, 'never'], + 'subject-full-stop': [2, 'never', '.'], + + // ───────────────────────────────────────────────────────────────────── + // BODY RULES + // ───────────────────────────────────────────────────────────────────── + 'body-leading-blank': [2, 'always'], + 'body-max-line-length': [2, 'always', 100], + 'body-min-length': [0, 'always', 0], // Optional body + + // ───────────────────────────────────────────────────────────────────── + // FOOTER RULES + // ───────────────────────────────────────────────────────────────────── + 'footer-leading-blank': [2, 'always'], + 'footer-max-line-length': [2, 'always', 100], + + // ───────────────────────────────────────────────────────────────────── + // SPECIAL RULES + // ───────────────────────────────────────────────────────────────────── + // Signed-off-by trailer (optional, set to 2 to require) + 'signed-off-by': [0, 'always', 'Signed-off-by:'], + + // References (issue/PR links) - warning if missing + 'references-empty': [1, 'never'], + + // Breaking changes must have both ! and BREAKING CHANGE footer + // (or neither - XNOR behavior) + // 'breaking-change-exclamation-mark': [2, 'always'], + }, + + // ───────────────────────────────────────────────────────────────────────── + // HELP URL + // ───────────────────────────────────────────────────────────────────────── + helpUrl: 'https://www.conventionalcommits.org/en/v1.0.0/', +}; +``` + +#### 3.11.3 lint-commits.yml (Commit Validation Workflow) + +```yaml +name: Lint Commits + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + # ───────────────────────────────────────────────────────────────────────── + # COCOGITTO: Validate commit types and generate changelog preview + # ───────────────────────────────────────────────────────────────────────── + cocogitto: + name: Cocogitto Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 # Full history for commit range + + - name: Install Cocogitto + run: | + curl -sSL https://github.com/cocogitto/cocogitto/releases/latest/download/cocogitto-x86_64-unknown-linux-gnu.tar.gz | tar xz + sudo mv cog /usr/local/bin/ + + - name: Validate commits + run: | + # Check all commits in PR against conventional commits spec + cog check --from-latest-tag || cog check + + - name: Preview changelog + if: success() + run: | + echo "## Changelog Preview" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + cog changelog --at HEAD >> $GITHUB_STEP_SUMMARY || echo "No changelog entries" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + + # ───────────────────────────────────────────────────────────────────────── + # COMMITLINT: Detailed message validation + # ───────────────────────────────────────────────────────────────────────── + commitlint: + name: Commitlint Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install commitlint + run: | + npm install --save-dev @commitlint/cli @commitlint/config-conventional + + - name: Validate commit messages + run: | + npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose + + # ───────────────────────────────────────────────────────────────────────── + # PR TITLE CHECK (for squash merges) + # ───────────────────────────────────────────────────────────────────────── + pr-title: + name: PR Title Check + runs-on: ubuntu-latest + steps: + - uses: amannn/action-semantic-pull-request@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + types: | + feat + fix + docs + style + refactor + perf + test + build + ci + chore + revert + hotfix + security + deps + wip + release + scopes: | + core + api + cli + config + mcp + transport + tools + resources + prompts + ci + docker + deps + docs + requireScope: false + subjectPattern: ^[a-z].+$ + subjectPatternError: | + Subject must start with lowercase letter. + Example: "feat(mcp): add new transport layer" +``` + +### 3.12 Configuration Files + +| File | Purpose | +|------|---------| +| `.pre-commit-config.yaml` | Pre-commit hook definitions | +| `.typos.toml` | Spelling exceptions | +| `.markdownlint.json` | Markdown rules | +| `.yamllint.yml` | YAML rules | +| `.shellcheckrc` | Shellcheck rules | +| `.editorconfig` | Editor settings | +| `taplo.toml` | TOML formatting | +| `cog.toml` | Cocogitto - custom types, changelog, versioning | +| `.commitlintrc.js` | commitlint - header/body/footer validation | +| `clippy.toml` | Clippy configuration | +| `rustfmt.toml` | Rust formatting | +| `ruff.toml` | Python linting/formatting | +| `.eslintrc.js` | JS/TS linting | +| `.prettierrc` | JS/TS/JSON/YAML formatting | +| `.golangci.yml` | Go linting | + +--- + +## 4. Review & Validation + +- [ ] Pre-commit hooks run locally without errors +- [ ] pre-commit.ci auto-fixes PRs correctly +- [ ] All workflows pass `actionlint` +- [ ] SARIF uploads to Security tab +- [ ] Path filters work correctly +- [ ] Spelling catches real typos, no false positives +- [ ] Config files are sensible defaults +- [ ] Implementation tracking checklist updated + +### Commit Linting Validation + +- [ ] Cocogitto installed and `cog check` works locally +- [ ] commitlint installed and validates commits +- [ ] Custom types accepted (hotfix, security, deps, wip, release) +- [ ] Custom scopes accepted (mcp, transport, tools, resources, prompts) +- [ ] Header length enforced (max 72 chars) +- [ ] Body/footer rules validated (blank lines, line length) +- [ ] PR title validation catches malformed titles +- [ ] Changelog preview generated in PR summary +- [ ] Types/scopes synchronized between cog.toml, .commitlintrc.js, and lint-commits.yml diff --git a/.ai/plans/phases/bundle-contents-phase-04-testing-unit.md b/.ai/plans/phases/bundle-contents-phase-04-testing-unit.md new file mode 100644 index 0000000..b4a50cc --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-04-testing-unit.md @@ -0,0 +1,131 @@ +--- +id: 0b9c78f2-4273-4522-a4db-7a172e80481c +title: "Phase 04: Testing - Unit" +status: pending +depends_on: + - e813a7bc-3a3e-4171-94c8-6bf0b363eb62 # phase-03 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 04: Testing - Unit + +## 1. Current State Assessment + +- [ ] Check for existing test workflows +- [ ] Review test frameworks used per language +- [ ] Identify coverage collection methods +- [ ] Check for test configuration files + +### Existing Assets + +None - test workflows not yet created. + +### Gaps Identified + +- [ ] Rust unit tests (cargo test, nextest) +- [ ] Python unit tests (pytest) +- [ ] JavaScript unit tests (jest/vitest) +- [ ] TypeScript unit tests (jest/vitest) +- [ ] Container structure tests +- [ ] mdBook link/spell tests + +--- + +## 2. Contextual Goal + +Create unit test workflows for all supported languages with coverage collection. Each workflow should run tests in parallel where possible, generate coverage reports compatible with Codecov, and provide clear failure messages. Use modern test runners (nextest for Rust, vitest for TS) for better performance and output. + +### Success Criteria + +- [ ] All unit test workflows created +- [ ] Coverage reports generated in lcov format +- [ ] Test results clearly visible in PR checks +- [ ] Parallel test execution where supported +- [ ] Appropriate timeout limits set + +### Out of Scope + +- Coverage reporting to Codecov (Phase 09) +- Integration tests (Phase 06) +- E2E tests (Phase 07) + +--- + +## 3. Implementation + +### 3.1 test-rust.yml + +```yaml +# Framework: cargo test + cargo-nextest +# Coverage: cargo-llvm-cov +# Features: +# - Matrix across stable/beta/nightly +# - nextest for parallel execution +# - Coverage in lcov format +# - Doc tests included +``` + +### 3.2 test-python.yml + +```yaml +# Framework: pytest +# Coverage: coverage.py / pytest-cov +# Features: +# - Matrix across Python versions +# - pytest-xdist for parallel +# - Coverage in lcov/xml format +# - JUnit XML for test results +``` + +### 3.3 test-javascript.yml + +```yaml +# Framework: jest or vitest (auto-detect) +# Coverage: c8 / istanbul +# Features: +# - Matrix across Node versions +# - Coverage in lcov format +# - JUnit XML for test results +``` + +### 3.4 test-typescript.yml + +```yaml +# Framework: vitest (preferred) or jest +# Coverage: c8 / istanbul +# Features: +# - Type checking before tests +# - Coverage in lcov format +# - Source maps for accurate coverage +``` + +### 3.5 test-container.yml + +```yaml +# Framework: container-structure-test +# Features: +# - Validate container structure +# - Check for expected files/commands +# - Verify metadata labels +``` + +### 3.6 test-mdbook.yml + +```yaml +# Tools: +# - mdbook-linkcheck for broken links +# - aspell or cspell for spell check +``` + +--- + +## 4. Review & Validation + +- [ ] All workflows pass `actionlint` +- [ ] Tests execute and pass on sample code +- [ ] Coverage reports are generated +- [ ] Parallel execution provides speedup +- [ ] Timeouts are appropriate +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-05-testing-property.md b/.ai/plans/phases/bundle-contents-phase-05-testing-property.md new file mode 100644 index 0000000..58ffc90 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-05-testing-property.md @@ -0,0 +1,136 @@ +--- +id: 63b65361-73ac-48b5-a614-931d6cb36022 +title: "Phase 05: Testing - Property-Based" +status: pending +depends_on: + - 0b9c78f2-4273-4522-a4db-7a172e80481c # phase-04 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 05: Testing - Property-Based + +## 1. Current State Assessment + +- [ ] Check for existing property-based test setups +- [ ] Review proptest/hypothesis usage in projects +- [ ] Identify shrinking and seed management + +### Existing Assets + +None - property testing not yet configured. + +### Gaps Identified + +- [ ] Rust property tests (proptest) +- [ ] Python property tests (Hypothesis) +- [ ] TypeScript property tests (fast-check) + +--- + +## 2. Contextual Goal + +Add property-based testing capabilities to discover edge cases that unit tests miss. Property-based tests generate random inputs based on specifications and verify invariants hold. Failed cases are automatically shrunk to minimal reproducible examples. This complements unit testing by exploring the input space more thoroughly. + +### Success Criteria + +- [ ] Property test workflow created +- [ ] Supports Rust (proptest), Python (Hypothesis), TypeScript (fast-check) +- [ ] Seed values logged for reproduction +- [ ] Shrunk failing cases reported clearly +- [ ] Reasonable iteration counts (default 100-1000) + +### Out of Scope + +- Fuzzing (Phase 19) - different purpose, longer running +- Integration property tests + +--- + +## 3. Implementation + +### 3.1 test-property.yml + +```yaml +name: Property Tests + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '0 6 * * 1' # Weekly deep run + workflow_dispatch: + inputs: + iterations: + description: 'Number of test cases' + default: '1000' + +jobs: + rust-property: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + - name: Run proptest + env: + PROPTEST_CASES: ${{ inputs.iterations || '256' }} + run: cargo test --features proptest + + python-property: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: 'pip' + - run: pip install hypothesis pytest + - name: Run Hypothesis + env: + HYPOTHESIS_PROFILE: ${{ github.event_name == 'schedule' && 'ci-extended' || 'ci' }} + run: pytest -v --hypothesis-show-statistics + + typescript-property: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + - run: npm ci + - name: Run fast-check + run: npm run test:property +``` + +### 3.2 Configuration Files + +**conftest.py** (Hypothesis profiles): +```python +from hypothesis import settings, Verbosity + +settings.register_profile("ci", max_examples=100) +settings.register_profile("ci-extended", max_examples=1000) +settings.load_profile("ci") +``` + +**proptest.toml**: +```toml +[proptest] +cases = 256 +max_shrink_iters = 10000 +``` + +--- + +## 4. Review & Validation + +- [ ] All property tests run successfully +- [ ] Seed values are logged +- [ ] Shrinking produces minimal examples +- [ ] Weekly extended runs complete in reasonable time +- [ ] No flaky tests due to randomness +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-06-testing-integration.md b/.ai/plans/phases/bundle-contents-phase-06-testing-integration.md new file mode 100644 index 0000000..ad2cdad --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-06-testing-integration.md @@ -0,0 +1,153 @@ +--- +id: 13d034f0-2e8a-4c35-8daa-5731b1982835 +title: "Phase 06: Testing - Integration" +status: pending +depends_on: + - 63b65361-73ac-48b5-a614-931d6cb36022 # phase-05 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 06: Testing - Integration + +## 1. Current State Assessment + +- [ ] Check for existing integration test setups +- [ ] Review docker-compose configurations +- [ ] Identify external service dependencies +- [ ] Check for test database setups + +### Existing Assets + +None - integration testing not yet configured. + +### Gaps Identified + +- [ ] Integration test workflow +- [ ] docker-compose.test.yml for services +- [ ] Database fixtures and migrations +- [ ] External API mocking + +--- + +## 2. Contextual Goal + +Create integration test workflows that verify components work together correctly. This includes testing database interactions, API endpoints, message queues, and service-to-service communication. Tests run in isolated containers with dedicated test databases and mock external services. + +### Success Criteria + +- [ ] Integration test workflow created +- [ ] docker-compose setup for test services +- [ ] Database seeding/teardown automated +- [ ] External services properly mocked +- [ ] Tests isolated from production data + +### Out of Scope + +- E2E tests with real services (Phase 07) +- MCP protocol tests (Phase 11) +- Chaos testing (Phase 13) + +--- + +## 3. Implementation + +### 3.1 test-integration.yml + +```yaml +name: Integration Tests + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + integration: + runs-on: ubuntu-latest + + services: + postgres: + image: postgres:16 + env: + POSTGRES_USER: test + POSTGRES_PASSWORD: test + POSTGRES_DB: testdb + ports: + - 5432:5432 + options: >- + --health-cmd pg_isready + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + redis: + image: redis:7 + ports: + - 6379:6379 + options: >- + --health-cmd "redis-cli ping" + --health-interval 10s + --health-timeout 5s + --health-retries 5 + + steps: + - uses: actions/checkout@v4 + + - name: Setup test environment + run: | + # Run migrations, seed data, etc. + + - name: Run integration tests + env: + DATABASE_URL: postgres://test:test@localhost:5432/testdb + REDIS_URL: redis://localhost:6379 + run: | + # Language-specific test command +``` + +### 3.2 docker-compose.test.yml + +```yaml +version: '3.8' + +services: + app: + build: + context: . + target: test + depends_on: + - postgres + - redis + environment: + - DATABASE_URL=postgres://test:test@postgres:5432/testdb + - REDIS_URL=redis://redis:6379 + + postgres: + image: postgres:16 + environment: + POSTGRES_USER: test + POSTGRES_PASSWORD: test + POSTGRES_DB: testdb + + redis: + image: redis:7 +``` + +### 3.3 Test Database Management + +- Use transactions for test isolation +- Reset sequences between tests +- Separate test fixtures from production seeds + +--- + +## 4. Review & Validation + +- [ ] Services start correctly in CI +- [ ] Tests pass with isolated databases +- [ ] No race conditions between parallel tests +- [ ] Cleanup runs even on test failure +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-07-testing-e2e.md b/.ai/plans/phases/bundle-contents-phase-07-testing-e2e.md new file mode 100644 index 0000000..7c470a2 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-07-testing-e2e.md @@ -0,0 +1,167 @@ +--- +id: 4888cfdd-f46d-475a-949b-b37fac3a12a7 +title: "Phase 07: Testing - E2E" +status: pending +depends_on: + - 13d034f0-2e8a-4c35-8daa-5731b1982835 # phase-06 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 07: Testing - E2E + +## 1. Current State Assessment + +- [ ] Check for existing E2E test frameworks +- [ ] Review browser automation setup (if applicable) +- [ ] Identify API testing requirements +- [ ] Check for contract testing setup + +### Existing Assets + +None - E2E testing not yet configured. + +### Gaps Identified + +- [ ] E2E test workflow +- [ ] API contract testing (Pact) +- [ ] Smoke test workflow +- [ ] Regression test workflow + +--- + +## 2. Contextual Goal + +Create end-to-end test workflows that verify the complete system works as expected from a user perspective. This includes API testing against deployed services, contract testing between services, smoke tests for critical paths, and regression tests to prevent feature breakage. + +### Success Criteria + +- [ ] E2E workflow for API testing created +- [ ] Contract testing with Pact or similar +- [ ] Smoke tests for critical user journeys +- [ ] Regression test suite maintained +- [ ] Test reports with screenshots/artifacts + +### Out of Scope + +- Performance testing (Phase 08) +- Browser automation for web apps (project-specific) + +--- + +## 3. Implementation + +### 3.1 test-e2e.yml + +```yaml +name: E2E Tests + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + e2e: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Build application + run: docker compose build + + - name: Start services + run: docker compose up -d + + - name: Wait for services + run: | + # Health check endpoints + + - name: Run E2E tests + run: | + # E2E test runner + + - name: Upload artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-results + path: | + test-results/ + screenshots/ + + - name: Stop services + if: always() + run: docker compose down -v +``` + +### 3.2 test-smoke.yml + +```yaml +name: Smoke Tests + +on: + deployment: + workflow_dispatch: + inputs: + environment: + description: 'Environment to test' + required: true + default: 'staging' + +jobs: + smoke: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Run smoke tests + run: | + # Critical path verification + # - Health endpoints + # - Authentication + # - Core functionality +``` + +### 3.3 test-contract.yml + +```yaml +name: Contract Tests + +on: + push: + branches: [main] + pull_request: + +jobs: + pact: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Generate contracts + run: | + # Consumer contract generation + + - name: Verify contracts + run: | + # Provider verification + + - name: Publish contracts + if: github.ref == 'refs/heads/main' + run: | + # Publish to Pact Broker +``` + +--- + +## 4. Review & Validation + +- [ ] E2E tests pass on clean deployment +- [ ] Smoke tests cover critical paths +- [ ] Contract tests prevent breaking changes +- [ ] Artifacts useful for debugging failures +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-08-testing-performance.md b/.ai/plans/phases/bundle-contents-phase-08-testing-performance.md new file mode 100644 index 0000000..f2c127b --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-08-testing-performance.md @@ -0,0 +1,137 @@ +--- +id: 8c8e095d-23b8-4ff4-8da7-b2bddd233181 +title: "Phase 08: Testing - Performance" +status: pending +depends_on: + - 4888cfdd-f46d-475a-949b-b37fac3a12a7 # phase-07 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 08: Testing - Performance + +## 1. Current State Assessment + +- [ ] Check for existing benchmark setups +- [ ] Review criterion/pytest-benchmark usage +- [ ] Identify performance-critical paths +- [ ] Check for regression detection + +### Existing Assets + +None - performance testing not yet configured. + +### Gaps Identified + +- [ ] Benchmark workflow +- [ ] Regression detection system +- [ ] Historical tracking +- [ ] Load testing capability + +--- + +## 2. Contextual Goal + +Create performance testing workflows that establish baselines and detect regressions. Benchmarks should run on consistent hardware, track results over time, and alert when performance degrades beyond thresholds. Focus on micro-benchmarks for critical code paths and macro-benchmarks for API endpoints. + +### Success Criteria + +- [ ] Benchmark workflow created +- [ ] Results stored and tracked over time +- [ ] Regression detection with configurable threshold +- [ ] PR comments with performance impact +- [ ] Consistent benchmark environment + +### Out of Scope + +- Load testing at scale (requires dedicated infrastructure) +- Profiling for optimization (development task) + +--- + +## 3. Implementation + +### 3.1 test-benchmark.yml + +```yaml +name: Benchmarks + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + rust-bench: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + - uses: Swatinem/rust-cache@v2 + + - name: Run benchmarks + run: cargo bench --all-features -- --save-baseline pr + + - name: Compare with main + if: github.event_name == 'pull_request' + run: | + git fetch origin main + git checkout origin/main + cargo bench --all-features -- --save-baseline main + git checkout - + cargo bench --all-features -- --baseline main --compare pr + + python-bench: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: 'pip' + + - run: pip install pytest pytest-benchmark + + - name: Run benchmarks + run: pytest --benchmark-only --benchmark-json=output.json + + - name: Store results + uses: benchmark-action/github-action-benchmark@v1 + with: + tool: 'pytest' + output-file-path: output.json + github-token: ${{ secrets.GITHUB_TOKEN }} + auto-push: true + alert-threshold: '150%' + comment-on-alert: true +``` + +### 3.2 Benchmark Categories + +| Category | Tools | Purpose | +|----------|-------|---------| +| Micro | criterion, pytest-benchmark | Function-level timing | +| API | wrk, hey | Endpoint throughput | +| Memory | heaptrack, memray | Memory profiling | +| Startup | hyperfine | Cold start timing | + +### 3.3 Regression Detection + +- Store baseline on main branch +- Compare PR benchmarks against baseline +- Alert if regression > 10% (configurable) +- Comment on PR with results + +--- + +## 4. Review & Validation + +- [ ] Benchmarks produce consistent results +- [ ] Regression detection catches 10%+ slowdowns +- [ ] Historical data accessible +- [ ] PR comments are informative +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-09-testing-coverage.md b/.ai/plans/phases/bundle-contents-phase-09-testing-coverage.md new file mode 100644 index 0000000..09e0257 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-09-testing-coverage.md @@ -0,0 +1,186 @@ +--- +id: f074da4e-abd9-476f-8e6c-a5cfc970d37c +title: "Phase 09: Testing - Coverage" +status: pending +depends_on: + - 8c8e095d-23b8-4ff4-8da7-b2bddd233181 # phase-08 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 09: Testing - Coverage + +## 1. Current State Assessment + +- [ ] Check for existing coverage collection +- [ ] Review Codecov/Coveralls integration +- [ ] Identify coverage gaps in test workflows +- [ ] Check for coverage configuration files + +### Existing Assets + +Unit test workflows exist but coverage not uploaded. + +### Gaps Identified + +- [ ] Unified coverage workflow +- [ ] Codecov configuration +- [ ] Coverage merge across languages +- [ ] Documentation coverage + +--- + +## 2. Contextual Goal + +Establish comprehensive code coverage reporting that aggregates results from all test workflows. Coverage reports should be uploaded to Codecov for tracking trends, with PR comments showing coverage changes. Include line, branch, and function coverage metrics, with documentation coverage for public APIs. + +### Success Criteria + +- [ ] Coverage workflow collecting from all languages +- [ ] Codecov integration with PR comments +- [ ] Coverage trends visible over time +- [ ] Documentation coverage tracked +- [ ] Coverage badge for README + +### Out of Scope + +- Quality gates based on coverage (Phase 10) +- Mutation testing (separate concern) + +--- + +## 3. Implementation + +### 3.1 coverage.yml + +```yaml +name: Coverage + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + rust-coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + components: llvm-tools-preview + + - uses: Swatinem/rust-cache@v2 + + - name: Install cargo-llvm-cov + uses: taiki-e/install-action@cargo-llvm-cov + + - name: Collect coverage + run: cargo llvm-cov --all-features --lcov --output-path lcov.info + + - name: Upload to Codecov + uses: codecov/codecov-action@v4 + with: + files: lcov.info + flags: rust + token: ${{ secrets.CODECOV_TOKEN }} + + python-coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + cache: 'pip' + + - run: pip install pytest coverage + + - name: Collect coverage + run: | + coverage run -m pytest + coverage lcov -o coverage.lcov + + - name: Upload to Codecov + uses: codecov/codecov-action@v4 + with: + files: coverage.lcov + flags: python + token: ${{ secrets.CODECOV_TOKEN }} + + typescript-coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: 'npm' + + - run: npm ci + + - name: Collect coverage + run: npm run test:coverage + + - name: Upload to Codecov + uses: codecov/codecov-action@v4 + with: + files: coverage/lcov.info + flags: typescript + token: ${{ secrets.CODECOV_TOKEN }} +``` + +### 3.2 codecov.yml + +```yaml +# configs/codecov.yml +coverage: + status: + project: + default: + target: auto + threshold: 1% + patch: + default: + target: 80% + +comment: + layout: "reach,diff,flags,files" + behavior: default + require_changes: true + +flags: + rust: + paths: + - src/ + carryforward: true + python: + paths: + - "**/*.py" + carryforward: true + typescript: + paths: + - "**/*.ts" + carryforward: true +``` + +### 3.3 Documentation Coverage + +- **Rust**: `cargo doc --document-private-items` +- **Python**: `interrogate` for docstring coverage +- **TypeScript**: `typedoc` coverage report + +--- + +## 4. Review & Validation + +- [ ] All languages upload coverage +- [ ] Codecov comments appear on PRs +- [ ] Coverage trends visible in dashboard +- [ ] Flags correctly separate languages +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-10-testing-quality-gates.md b/.ai/plans/phases/bundle-contents-phase-10-testing-quality-gates.md new file mode 100644 index 0000000..ce6d463 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-10-testing-quality-gates.md @@ -0,0 +1,148 @@ +--- +id: 903f0911-039e-4917-8605-cb0e33519d75 +title: "Phase 10: Testing - Quality Gates" +status: pending +depends_on: + - f074da4e-abd9-476f-8e6c-a5cfc970d37c # phase-09 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 10: Testing - Quality Gates + +## 1. Current State Assessment + +- [ ] Check for existing quality gate enforcement +- [ ] Review coverage thresholds +- [ ] Identify blocking vs warning conditions +- [ ] Check for Code Climate integration + +### Existing Assets + +Coverage collection exists but no gates enforced. + +### Gaps Identified + +- [ ] Quality gate workflow +- [ ] Coverage threshold enforcement +- [ ] Mutation testing +- [ ] Type coverage enforcement + +--- + +## 2. Contextual Goal + +Establish quality gates that block merges when code quality drops below acceptable thresholds. This includes minimum coverage requirements, type coverage for typed languages, and optionally mutation testing to verify test effectiveness. Gates should be configurable per project with sensible defaults. + +### Success Criteria + +- [ ] Quality gate workflow blocks on threshold failures +- [ ] Coverage thresholds configurable (default 70%) +- [ ] Mutation testing integrated (optional) +- [ ] Type coverage checked for Python/TypeScript +- [ ] Clear failure messages for blocked PRs + +### Out of Scope + +- SAST (Phase 16) +- Security gates (Phase 14+) + +--- + +## 3. Implementation + +### 3.1 quality-gate.yml + +```yaml +name: Quality Gates + +on: + pull_request: + workflow_dispatch: + +jobs: + coverage-gate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Check coverage + uses: codecov/codecov-action@v4 + with: + fail_ci_if_error: true + token: ${{ secrets.CODECOV_TOKEN }} + + - name: Verify thresholds + run: | + # Check that coverage meets minimum + # Exit 1 if below threshold + + mutation-testing: + runs-on: ubuntu-latest + if: contains(github.event.pull_request.labels.*.name, 'mutation-test') + steps: + - uses: actions/checkout@v4 + + - name: Run cargo-mutants + run: | + cargo install cargo-mutants + cargo mutants --timeout 300 + + - name: Upload results + uses: actions/upload-artifact@v4 + with: + name: mutation-report + path: mutants.out/ + + type-coverage: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Python type coverage + run: | + pip install mypy + mypy --html-report typecov . + # Check coverage percentage + + - name: TypeScript type coverage + run: | + npx type-coverage --at-least 90 +``` + +### 3.2 Threshold Configuration + +```yaml +# .github/quality-gates.yml +coverage: + minimum: 70 + patch_minimum: 80 + +mutation: + enabled: false # Opt-in via label + timeout: 300 + +type_coverage: + python: 80 + typescript: 90 +``` + +### 3.3 Gate Enforcement + +| Gate | Default | Blocks Merge | +|------|---------|--------------| +| Line coverage | 70% | Yes | +| Patch coverage | 80% | Yes | +| Mutation score | 60% | No (opt-in) | +| Type coverage | 80% | Warning | + +--- + +## 4. Review & Validation + +- [ ] Gates block PRs below thresholds +- [ ] Thresholds are configurable +- [ ] Mutation testing runs on demand +- [ ] Type coverage reported accurately +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-11-testing-mcp-protocol.md b/.ai/plans/phases/bundle-contents-phase-11-testing-mcp-protocol.md new file mode 100644 index 0000000..f87c2a8 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-11-testing-mcp-protocol.md @@ -0,0 +1,164 @@ +--- +id: cbf0ef37-c0c8-45f7-afe3-b89c274b4566 +title: "Phase 11: Testing - MCP Protocol" +status: pending +depends_on: + - 903f0911-039e-4917-8605-cb0e33519d75 # phase-10 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - 6d0e0e40-1c80-4d57-aef2-e2da53cdd416 # mcp-testing-taxonomy +issues: [] +--- + +# Phase 11: Testing - MCP Protocol + +## 1. Current State Assessment + +- [ ] Review MCP testing taxonomy reference +- [ ] Check for existing MCP test infrastructure +- [ ] Identify protocol version requirements +- [ ] Check for transport-specific tests + +### Existing Assets + +- MCP Testing Taxonomy reference document +- MCP testing issue templates (created in Phase 01) + +### Gaps Identified + +- [ ] MCP protocol conformance workflow +- [ ] JSON-RPC 2.0 compliance tests +- [ ] Transport-specific test workflows +- [ ] MCP test fixtures + +--- + +## 2. Contextual Goal + +Create MCP-specific test workflows that verify protocol conformance, functional correctness, and transport compatibility. Tests should cover JSON-RPC 2.0 compliance, MCP initialization sequence, capability negotiation, tool/resource/prompt operations, and all supported transports (stdio, SSE, HTTP, WebSocket). + +### Success Criteria + +- [ ] Protocol conformance tests implemented +- [ ] All JSON-RPC error codes verified +- [ ] Transport tests for stdio, SSE, HTTP, WS +- [ ] Tool/resource/prompt functional tests +- [ ] Test fixtures for common scenarios + +### Out of Scope + +- MCP security testing (covered in Phase 19 fuzzing) +- MCP performance benchmarks (Phase 08) +- Mock harness implementation (Phase 12) + +--- + +## 3. Implementation + +### 3.1 test-mcp-protocol.yml + +```yaml +name: MCP Protocol Conformance + +on: + push: + branches: [main] + paths: + - 'src/**' + - 'tests/mcp/**' + pull_request: + workflow_dispatch: + +jobs: + jsonrpc-compliance: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build MCP server + run: cargo build --release + + - name: Run JSON-RPC compliance tests + run: | + cargo test --test jsonrpc_compliance + + mcp-initialization: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Test initialization sequence + run: | + # Test MCP-INIT-001 through MCP-INIT-006 + cargo test --test mcp_init + + capability-negotiation: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Test capability negotiation + run: | + # Test MCP-CAP-001 through MCP-CAP-005 + cargo test --test mcp_capabilities +``` + +### 3.2 test-mcp-transport.yml + +```yaml +name: MCP Transport Tests + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + stdio: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Test stdio transport + run: cargo test --test transport_stdio + + sse: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Test SSE transport + run: cargo test --test transport_sse + + http: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Test HTTP transport + run: cargo test --test transport_http + + websocket: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Test WebSocket transport + run: cargo test --test transport_ws +``` + +### 3.3 Test Fixtures + +Create `tests/fixtures/` with: +- `valid_initialize.json` - Valid initialization request +- `error_codes.json` - All JSON-RPC error codes +- `tool_responses.json` - Sample tool responses +- `resource_templates.json` - Resource template examples + +--- + +## 4. Review & Validation + +- [ ] All protocol tests pass +- [ ] Transport tests cover all modes +- [ ] Fixtures are comprehensive +- [ ] Error handling verified +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-12-testing-mock-harness.md b/.ai/plans/phases/bundle-contents-phase-12-testing-mock-harness.md new file mode 100644 index 0000000..f62b98c --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-12-testing-mock-harness.md @@ -0,0 +1,173 @@ +--- +id: 6ab50022-3628-416e-8651-e6ca3ac3d940 +title: "Phase 12: Testing - Mock Harness" +status: pending +depends_on: + - cbf0ef37-c0c8-45f7-afe3-b89c274b4566 # phase-11 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 12: Testing - Mock Harness + +## 1. Current State Assessment + +- [ ] Check for existing mock infrastructure +- [ ] Review WireMock/mockserver usage +- [ ] Identify VCR/cassette recording needs +- [ ] Check for factory pattern implementations + +### Existing Assets + +None - mock infrastructure not yet created. + +### Gaps Identified + +- [ ] docker-compose.mocks.yml +- [ ] WireMock mappings +- [ ] Mock MCP server +- [ ] Factory patterns per language +- [ ] VCR/cassette infrastructure +- [ ] Mock harness workflow + +--- + +## 2. Contextual Goal + +Build comprehensive mock infrastructure for testing services in isolation. This includes HTTP mocking with WireMock, a mock MCP server for client testing, data factories for generating test fixtures, and VCR-style recording for external API interactions. The harness should be reusable across test types and languages. + +### Success Criteria + +- [ ] docker-compose.mocks.yml with all mock services +- [ ] Mock MCP server functional +- [ ] Factories implemented for Python, TS, Rust +- [ ] VCR recording infrastructure working +- [ ] Workflow to spin up mock environment + +### Out of Scope + +- Chaos injection (Phase 13) +- Production-like load testing + +--- + +## 3. Implementation + +### 3.1 docker-compose.mocks.yml + +```yaml +version: '3.8' + +services: + wiremock: + image: wiremock/wiremock:latest + ports: + - "8080:8080" + volumes: + - ./wiremock:/home/wiremock + + mock-mcp-server: + build: + context: ./mock-mcp-server + ports: + - "3000:3000" + environment: + - MCP_DELAY_MS=0 + - MCP_ERROR_RATE=0 + + mockserver: + image: mockserver/mockserver:latest + ports: + - "1080:1080" +``` + +### 3.2 Mock MCP Server + +```rust +// mock-mcp-server/src/main.rs +struct MockConfig { + tools: Vec, + resources: Vec, + delay_ms: u64, + error_rate: f32, + custom_responses: HashMap, +} +``` + +### 3.3 Factory Patterns + +**Python (factory_boy)**: +```python +class ToolFactory(factory.Factory): + class Meta: + model = Tool + + name = factory.Faker('word') + description = factory.Faker('sentence') +``` + +**TypeScript (fishery)**: +```typescript +export const toolFactory = Factory.define(() => ({ + name: faker.word.noun(), + description: faker.lorem.sentence(), +})); +``` + +**Rust (fake)**: +```rust +impl Dummy for Tool { + fn dummy_with_rng(_: &Faker, rng: &mut R) -> Self { + Tool { + name: Word().fake_with_rng(rng), + description: Sentence(3..5).fake_with_rng(rng), + } + } +} +``` + +### 3.4 VCR Infrastructure + +| Language | Library | Format | +|----------|---------|--------| +| Python | vcrpy | YAML cassettes | +| TypeScript | nock | JSON recordings | +| Rust | rvcr | JSON cassettes | + +### 3.5 mock-harness.yml + +```yaml +name: Mock Harness + +on: + workflow_call: + workflow_dispatch: + +jobs: + start-mocks: + runs-on: ubuntu-latest + outputs: + wiremock-url: http://localhost:8080 + mcp-url: http://localhost:3000 + + steps: + - uses: actions/checkout@v4 + + - name: Start mock services + run: docker compose -f docker-compose.mocks.yml up -d + + - name: Wait for services + run: | + # Health checks +``` + +--- + +## 4. Review & Validation + +- [ ] All mock services start correctly +- [ ] Mock MCP server responds to requests +- [ ] Factories generate valid data +- [ ] VCR recording and playback works +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-13-testing-chaos.md b/.ai/plans/phases/bundle-contents-phase-13-testing-chaos.md new file mode 100644 index 0000000..640bc89 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-13-testing-chaos.md @@ -0,0 +1,153 @@ +--- +id: 0738234f-77e5-4b0e-ae25-2b41eab9ba61 +title: "Phase 13: Testing - Chaos" +status: pending +depends_on: + - 6ab50022-3628-416e-8651-e6ca3ac3d940 # phase-12 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 13: Testing - Chaos + +## 1. Current State Assessment + +- [ ] Check for existing resilience tests +- [ ] Review error handling coverage +- [ ] Identify fault injection points +- [ ] Check for timeout handling tests + +### Existing Assets + +Mock harness from Phase 12 can inject delays and errors. + +### Gaps Identified + +- [ ] Chaos test workflow +- [ ] Network fault injection +- [ ] Resource exhaustion tests +- [ ] Dependency failure tests + +--- + +## 2. Contextual Goal + +Create chaos engineering tests that verify system behavior under failure conditions. This includes network latency injection, packet loss simulation, service unavailability, resource exhaustion, and cascading failure scenarios. Tests should verify graceful degradation and proper error propagation. + +### Success Criteria + +- [ ] Chaos test workflow created +- [ ] Network faults injectable (latency, loss) +- [ ] Service failures handled gracefully +- [ ] Resource limits verified +- [ ] Recovery behavior documented + +### Out of Scope + +- Production chaos engineering (requires separate infrastructure) +- Full chaos mesh deployment + +--- + +## 3. Implementation + +### 3.1 test-chaos.yml + +```yaml +name: Chaos Tests + +on: + schedule: + - cron: '0 4 * * 1' # Weekly Monday 4am + workflow_dispatch: + inputs: + scenario: + description: 'Chaos scenario' + default: 'all' + type: choice + options: + - all + - network + - resource + - dependency + +jobs: + network-chaos: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup network chaos + run: | + # Use tc (traffic control) for network simulation + sudo tc qdisc add dev eth0 root netem delay 100ms 20ms + + - name: Run tests with latency + run: cargo test --test chaos_network + + - name: Cleanup + if: always() + run: sudo tc qdisc del dev eth0 root + + resource-chaos: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Memory pressure test + run: | + # Limit memory available to test process + systemd-run --scope -p MemoryMax=256M cargo test --test chaos_memory + + - name: CPU throttle test + run: | + # Limit CPU for test process + cargo test --test chaos_cpu + + dependency-chaos: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Start services with fault injection + run: | + docker compose -f docker-compose.mocks.yml up -d + # Configure mock to fail randomly + + - name: Run tests + run: cargo test --test chaos_deps + + - name: Cleanup + if: always() + run: docker compose -f docker-compose.mocks.yml down -v +``` + +### 3.2 Chaos Scenarios + +| Scenario | Tool/Method | Verification | +|----------|-------------|--------------| +| Latency | tc netem | Response within timeout | +| Packet loss | tc netem | Retries work | +| Service down | Stop container | Error returned, no hang | +| OOM | cgroups | Graceful degradation | +| Slow response | Mock delay | Timeout handling | + +### 3.3 Expected Behaviors + +| Failure | Expected Behavior | +|---------|------------------| +| Network timeout | Return error within configured timeout | +| Service unavailable | Return error, don't retry forever | +| Memory exhaustion | Graceful shutdown, no data corruption | +| Partial failure | Other operations continue working | + +--- + +## 4. Review & Validation + +- [ ] All chaos scenarios run successfully +- [ ] System recovers from injected faults +- [ ] No cascading failures +- [ ] Error messages are helpful +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-14-security-dependencies.md b/.ai/plans/phases/bundle-contents-phase-14-security-dependencies.md new file mode 100644 index 0000000..b884b52 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-14-security-dependencies.md @@ -0,0 +1,279 @@ +--- +id: 56738219-8f07-4634-9592-5a461b36ee18 +title: "Phase 14: Security - Dependencies" +status: pending +depends_on: + - 0738234f-77e5-4b0e-ae25-2b41eab9ba61 # phase-13 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking + - 4e593fba-d836-4aa6-9a27-d833df63e90f # gap-analysis +references: + - dependency-scanning-strategy-adr # ADR in ../docs/adr/ +issues: [] +--- + +# Phase 14: Security - Dependencies + +## 1. Current State Assessment + +- [ ] Review ADR: Dependency Scanning Strategy +- [ ] Check for existing dependency scanning +- [ ] Identify dependency ecosystems used +- [ ] Check for dependabot configuration + +### Existing Assets + +- ADR: Dependency Scanning Strategy (approved) +- dependabot.yml template (Phase 01) + +### Gaps Identified + +- [ ] dependency-review.yml (PR gate) +- [ ] deps-rust.yml (Rust freshness) +- [ ] deps-python.yml (Python freshness) +- [ ] deps-node.yml (Node freshness) +- [ ] deps-container.yml (Base image freshness) +- [ ] security-rust.yml (4-layer defense) + +--- + +## 2. Contextual Goal + +Implement comprehensive dependency security scanning following the approved ADR. For Rust, this means implementing the 4-layer defense-in-depth strategy: cargo-audit (CVEs), cargo-deny (policies), cargo-vet (audits), and cargo-crev (community trust). For other ecosystems, implement appropriate scanning tools. Include both PR-blocking security gates and scheduled freshness reports. + +### Success Criteria + +- [ ] dependency-review.yml blocks vulnerable PRs +- [ ] Rust 4-layer defense fully implemented +- [ ] Python pip-audit integrated +- [ ] Node npm-audit integrated +- [ ] Container base image freshness tracked + +### Out of Scope + +- License compliance (Phase 15) +- SAST source scanning (Phase 16) + +--- + +## 3. Implementation + +### 3.1 dependency-review.yml + +```yaml +name: Dependency Review + +on: + pull_request: + +permissions: + contents: read + pull-requests: write + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Dependency Review + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: high + deny-licenses: GPL-3.0, AGPL-3.0 + allow-ghsas: false +``` + +### 3.2 security-rust.yml (4-Layer Defense) + +```yaml +name: Rust Security + +on: + push: + branches: [main] + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + pull_request: + paths: + - '**/Cargo.toml' + - '**/Cargo.lock' + schedule: + - cron: '0 6 * * *' + +jobs: + # Layer 1: Known Vulnerabilities + cargo-audit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: rustsec/audit-check@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + # Layer 2: Policy Enforcement + cargo-deny: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: EmbarkStudios/cargo-deny-action@v1 + + # Layer 3: Audit Trail + cargo-vet: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo install cargo-vet + - run: cargo vet + + # Layer 4: Community Trust + cargo-crev: + runs-on: ubuntu-latest + if: github.event_name == 'schedule' + steps: + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + - run: cargo install cargo-crev + - run: cargo crev verify +``` + +### 3.3 Configuration Files + +#### deny.toml (cargo-deny) + +```toml +[graph] +targets = [] +all-features = true + +[advisories] +db-path = "~/.cargo/advisory-db" +vulnerability = "deny" +unmaintained = "warn" +yanked = "deny" +notice = "warn" + +[licenses] +confidence-threshold = 0.93 +allow = [ + "MIT", + "Apache-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "Zlib", + "CC0-1.0", + "Unlicense", +] +exceptions = [ + { allow = ["MPL-2.0"], crate = "webpki-roots" }, + { allow = ["Unicode-DFS-2016"], crate = "unicode-ident" }, +] + +[licenses.private] +ignore = true + +[bans] +multiple-versions = "warn" +wildcards = "deny" +highlight = "all" +deny = [ + { crate = "openssl-sys", use-instead = "rustls" }, + { crate = "openssl", use-instead = "rustls" }, +] +skip = [] +skip-tree = [] + +[sources] +unknown-registry = "deny" +unknown-git = "deny" +allow-registry = ["https://github.com/rust-lang/crates.io-index"] +``` + +#### supply-chain/config.toml (cargo-vet) + +```toml +[cargo-vet] +version = "0.10" + +[imports.mozilla] +url = "https://raw.githubusercontent.com/AliRn-dev/AliRn-dev/main/AliRn-dev" + +[imports.embark] +url = "https://raw.githubusercontent.com/AliRn-dev/AliRn-dev/main/AliRn-dev" + +[imports.bytecode-alliance] +url = "https://raw.githubusercontent.com/AliRn-dev/AliRn-dev/main/AliRn-dev" + +[policy.example-crate] +audit-as-crates-io = true + +[criteria.crypto-reviewed] +description = "Cryptographic code has been reviewed for correctness" +implies = ["safe-to-deploy"] +``` + +### 3.4 Pre-commit Hook Setup + +```yaml +# .pre-commit-config.yaml +repos: + - repo: local + hooks: + - id: cargo-audit + name: cargo-audit + entry: cargo audit + language: system + types: [rust] + pass_filenames: false +``` + +### 3.5 Developer Workflow Commands + +```bash +# Install all tools +cargo install cargo-audit --features=fix +cargo install cargo-deny +cargo install cargo-vet +cargo install cargo-crev + +# Initialize configurations +cargo deny init # Creates deny.toml +cargo vet init # Creates supply-chain/ +cargo crev id new # Creates reviewer identity + +# Before adding a new dependency +cargo crev crate search # Check community reviews +cargo vet suggest # See if already audited + +# After reviewing a crate +cargo crev crate review # Publish your review +cargo vet certify # Record your audit + +# Regular maintenance +cargo audit # Quick vuln check +cargo deny check # Full policy check +cargo vet # Verify all audited +cargo crev repo publish # Share your reviews +``` + +### 3.6 deps-*.yml Freshness Reports + +For each ecosystem, create scheduled workflows that report outdated dependencies without blocking: + +- `deps-rust.yml`: cargo-outdated +- `deps-python.yml`: pip-check, pip-audit +- `deps-node.yml`: npm outdated, npm audit +- `deps-container.yml`: Check base image for updates + +--- + +## 4. Review & Validation + +- [ ] Dependency review blocks vulnerable PRs +- [ ] All 4 Rust security layers functional +- [ ] Freshness reports run on schedule +- [ ] SARIF output to Security tab where supported +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-15-security-licenses.md b/.ai/plans/phases/bundle-contents-phase-15-security-licenses.md new file mode 100644 index 0000000..0f94845 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-15-security-licenses.md @@ -0,0 +1,360 @@ +--- +id: 998f42c0-584d-4dcb-8b02-07116f0f03e3 +title: "Phase 15: Security - Licenses" +status: pending +depends_on: + - 56738219-8f07-4634-9592-5a461b36ee18 # phase-14 + - e9f0a1b2-c3d4-5e6f-7a8b-9c0d1e2f3a4b # phase-22a (policy library) +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - ../../docs/strategies/policy-as-code.md # Unified policy strategy +issues: [] +--- + +# Phase 15: Security - Licenses + +## 1. Current State Assessment + +- [ ] Check for existing license scanning +- [ ] Review allowed/denied license lists +- [ ] Identify SBOM requirements +- [ ] Check for REUSE compliance + +### Existing Assets + +cargo-deny (Phase 14) includes license checking for Rust. + +### Gaps Identified + +- [ ] security-license.yml (ScanCode) +- [ ] reuse-lint.yml (REUSE compliance) +- [ ] License policy configuration +- [ ] SBOM generation integration + +--- + +## 2. Contextual Goal + +Establish comprehensive license compliance checking across all dependencies. This includes scanning dependencies for license information using ScanCode, enforcing project-level compliance with REUSE, maintaining allowed/denied license lists, and correlating license data with SBOMs for complete visibility. + +### Success Criteria + +- [ ] ScanCode scans all dependencies +- [ ] REUSE compliance verified +- [ ] Allowed/denied license policy enforced +- [ ] License compatibility matrix documented +- [ ] SBOM contains license information + +### Out of Scope + +- SBOM generation (Phase 23 Attestation) +- Legal review of licenses + +--- + +## 3. Implementation + +### 3.1 security-license.yml + +```yaml +name: License Compliance + +on: + push: + branches: [main] + paths: + - '**/Cargo.toml' + - '**/package.json' + - '**/pyproject.toml' + - '**/requirements*.txt' + pull_request: + schedule: + - cron: '0 5 * * 1' # Weekly + +jobs: + scancode: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup ScanCode + run: | + pip install scancode-toolkit + + - name: Scan licenses + run: | + scancode --license --license-text --json-pp licenses.json . + + - name: Check for denied licenses + run: | + # Parse licenses.json and check against policy + + - name: Upload results + uses: actions/upload-artifact@v4 + with: + name: license-scan + path: licenses.json +``` + +### 3.2 reuse-lint.yml + +```yaml +name: REUSE Compliance + +on: + push: + branches: [main] + pull_request: + +jobs: + reuse: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: REUSE Compliance Check + uses: fsfe/reuse-action@v3 +``` + +### 3.3 License Policy + +> **Policy Source**: License data is centralized in the unified policy library (Phase 22a). +> See [Policy-as-Code Strategy](../../docs/strategies/policy-as-code.md) for policy patterns. + +#### 3.3.1 Native Tool Configuration (cargo-deny) + +Rust-specific license checking remains in `deny.toml` (Phase 14) due to deep Cargo integration. + +#### 3.3.2 Unified License Policies (in policies/license/) + +For cross-language license enforcement and reporting, use OPA/Rego policies with shared data. + +**File**: `policies/license/enforcement.rego` + +```rego +# METADATA +# title: License Enforcement +# description: Enforce allowed/denied license policy across all languages +# custom: +# phase: 15 + +package mcp.license.enforcement + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +import data.mcp.allowed_licenses +import data.mcp.denied_licenses +import data.mcp.require_review + +# Deny packages with denied licenses +deny contains msg if { + some pkg in input.packages + pkg.license in denied_licenses + msg := sprintf("Denied license '%s' found in package '%s'", [pkg.license, pkg.name]) +} + +# Warn on licenses requiring review +warn contains msg if { + some pkg in input.packages + pkg.license in require_review + msg := sprintf("License '%s' in package '%s' requires legal review", [pkg.license, pkg.name]) +} + +# Warn on unknown licenses +warn contains msg if { + some pkg in input.packages + not pkg.license in allowed_licenses + not pkg.license in denied_licenses + not pkg.license in require_review + msg := sprintf("Unknown license '%s' in package '%s' - please classify", [pkg.license, pkg.name]) +} +``` + +**File**: `policies/license/compatibility.rego` + +```rego +# METADATA +# title: License Compatibility +# description: Check license compatibility for distribution +# custom: +# phase: 15 + +package mcp.license.compatibility + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +# Define compatibility matrix +# MIT is compatible with: MIT, BSD, Apache-2.0, MPL-2.0 +mit_compatible := {"MIT", "BSD-2-Clause", "BSD-3-Clause", "Apache-2.0", "MPL-2.0", "ISC", "Zlib"} + +# Apache-2.0 is NOT compatible with GPL-2.0 (one-way) +apache_incompatible := {"GPL-2.0-only", "GPL-2.0-or-later"} + +deny contains msg if { + input.project_license == "Apache-2.0" + some pkg in input.packages + pkg.license in apache_incompatible + msg := sprintf("Apache-2.0 project cannot include GPL-2.0 package '%s'", [pkg.name]) +} + +warn contains msg if { + input.project_license == "MIT" + some pkg in input.packages + not pkg.license in mit_compatible + msg := sprintf("License '%s' in '%s' may have compatibility issues with MIT", [pkg.license, pkg.name]) +} +``` + +#### 3.3.3 External Data Files + +License lists are stored in `policies/data/` for easy updates without policy changes. + +**File**: `policies/data/allowed_licenses.json` +(See Phase 22a for full content) + +```json +{ + "mcp": { + "allowed_licenses": [ + "MIT", "Apache-2.0", "BSD-2-Clause", "BSD-3-Clause", + "ISC", "MPL-2.0", "Zlib", "Unlicense", "CC0-1.0", "0BSD" + ] + } +} +``` + +**File**: `policies/data/denied_licenses.json` + +```json +{ + "mcp": { + "denied_licenses": [ + "GPL-3.0-only", "GPL-3.0-or-later", + "AGPL-3.0-only", "AGPL-3.0-or-later", + "SSPL-1.0", "BSL-1.1", "Elastic-2.0" + ], + "require_review": [ + "GPL-2.0-only", "GPL-2.0-or-later", + "LGPL-2.1-only", "LGPL-3.0-only", + "EPL-2.0", "CDDL-1.0" + ] + } +} +``` + +#### 3.3.4 Unified License Workflow + +```yaml +# .github/workflows/license-policy.yml +name: Unified License Policy + +on: + pull_request: + paths: + - '**/Cargo.toml' + - '**/package.json' + - '**/pyproject.toml' + - 'policies/license/**' + - 'policies/data/*licenses*.json' + +jobs: + license-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup tools + run: | + pip install scancode-toolkit + curl -L https://github.com/open-policy-agent/conftest/releases/latest/download/conftest_Linux_x86_64.tar.gz | tar xz + sudo mv conftest /usr/local/bin/ + + - name: Scan licenses + run: | + scancode --license --json-pp licenses.json . + + - name: Transform to policy input + run: | + # Transform ScanCode output to OPA input format + jq '{ + project_license: "MIT", + packages: [.files[] | select(.licenses) | { + name: .path, + license: .licenses[0].spdx_license_key + }] + }' licenses.json > license-input.json + + - name: Check license policy + run: | + conftest test license-input.json \ + --policy policies/license/ \ + --data policies/data/ \ + --output github +``` + +#### 3.3.5 License Policy Tests + +**File**: `policies/tests/license_test.rego` + +```rego +package mcp.license_test + +import data.mcp.license.enforcement +import data.mcp.license.compatibility + +# Test enforcement +test_deny_gpl3 if { + result := enforcement.deny with input as { + "packages": [{"name": "bad-pkg", "license": "GPL-3.0-only"}] + } with data.mcp.denied_licenses as ["GPL-3.0-only"] + count(result) == 1 +} + +test_allow_mit if { + result := enforcement.deny with input as { + "packages": [{"name": "good-pkg", "license": "MIT"}] + } with data.mcp.denied_licenses as ["GPL-3.0-only"] + count(result) == 0 +} + +test_warn_unknown if { + result := enforcement.warn with input as { + "packages": [{"name": "unknown-pkg", "license": "UNKNOWN-1.0"}] + } with data.mcp.allowed_licenses as ["MIT"] + with data.mcp.denied_licenses as ["GPL-3.0-only"] + with data.mcp.require_review as [] + count(result) == 1 +} + +# Test compatibility +test_apache_gpl2_incompatible if { + result := compatibility.deny with input as { + "project_license": "Apache-2.0", + "packages": [{"name": "gpl-pkg", "license": "GPL-2.0-only"}] + } + count(result) == 1 +} +``` + +### 3.4 License Compatibility Matrix + +| Your License | Compatible With | +|--------------|-----------------| +| MIT | MIT, BSD, Apache-2.0, MPL-2.0 | +| Apache-2.0 | MIT, BSD, Apache-2.0 | +| MPL-2.0 | MIT, BSD, Apache-2.0, MPL-2.0 | + +--- + +## 4. Review & Validation + +- [ ] ScanCode detects all licenses +- [ ] REUSE compliance passes +- [ ] Policy blocks denied licenses +- [ ] Compatibility matrix is accurate +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-16-security-sast.md b/.ai/plans/phases/bundle-contents-phase-16-security-sast.md new file mode 100644 index 0000000..2c5f22c --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-16-security-sast.md @@ -0,0 +1,155 @@ +--- +id: 4690fa44-71ef-4f5d-84f4-943c8c50a34b +title: "Phase 16: Security - SAST" +status: pending +depends_on: + - 998f42c0-584d-4dcb-8b02-07116f0f03e3 # phase-15 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 16: Security - SAST + +## 1. Current State Assessment + +- [ ] Check for existing SAST configuration +- [ ] Review CodeQL setup if present +- [ ] Identify Semgrep rules in use +- [ ] Check for language-specific security lints + +### Existing Assets + +Clippy security lints (Phase 03) provide some Rust coverage. + +### Gaps Identified + +- [ ] security-sast.yml (unified SAST) +- [ ] Semgrep custom rules +- [ ] CodeQL query packs +- [ ] SARIF aggregation +- [ ] Language-specific SAST workflows + +--- + +## 2. Contextual Goal + +Implement comprehensive static application security testing using Semgrep and CodeQL. Create custom rules for MCP-specific patterns, aggregate SARIF results to GitHub Security tab, and provide language-specific security analysis for Rust, Python, Go, and JavaScript. Focus on vulnerability detection without generating excessive false positives. + +### Success Criteria + +- [ ] Unified SAST workflow with Semgrep + CodeQL +- [ ] MCP-specific Semgrep rules created +- [ ] SARIF results appear in Security tab +- [ ] False positive rate acceptable +- [ ] Custom query packs for each language + +### Out of Scope + +- DAST (runtime testing) +- Fuzzing (Phase 19) + +--- + +## 3. Implementation + +### 3.1 security-sast.yml + +```yaml +name: SAST + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '0 5 * * *' + +jobs: + semgrep: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Semgrep Scan + uses: returntocorp/semgrep-action@v1 + with: + config: >- + p/security-audit + p/rust + p/python + p/javascript + .semgrep/ + generateSarif: true + + - name: Upload SARIF + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: semgrep.sarif + + codeql: + runs-on: ubuntu-latest + permissions: + security-events: write + + strategy: + matrix: + language: [python, javascript] + + steps: + - uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + queries: security-extended + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform Analysis + uses: github/codeql-action/analyze@v3 +``` + +### 3.2 MCP-Specific Semgrep Rules + +```yaml +# .semgrep/mcp-security.yml +rules: + - id: mcp-path-traversal + patterns: + - pattern: | + resources/read($URI) + - metavariable-regex: + metavariable: $URI + regex: '.*\.\./.*' + message: Potential path traversal in resource URI + severity: ERROR + + - id: mcp-command-injection + patterns: + - pattern: | + subprocess.run($CMD, shell=True) + - pattern-inside: | + def $TOOL(...): + ... + message: Command injection risk in MCP tool + severity: ERROR +``` + +### 3.3 Language-Specific Workflows + +- `security-sast-rust.yml`: Clippy security lints + cargo-geiger +- `security-sast-python.yml`: Bandit + Pylint security +- `security-sast-go.yml`: gosec + staticcheck + +--- + +## 4. Review & Validation + +- [ ] All SAST tools run without errors +- [ ] SARIF uploads to Security tab +- [ ] Custom MCP rules detect issues +- [ ] False positive rate < 10% +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-17-security-secrets.md b/.ai/plans/phases/bundle-contents-phase-17-security-secrets.md new file mode 100644 index 0000000..bf43f42 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-17-security-secrets.md @@ -0,0 +1,146 @@ +--- +id: 9837e690-439f-42cb-811f-dbcff58a6af9 +title: "Phase 17: Security - Secrets" +status: pending +depends_on: + - 4690fa44-71ef-4f5d-84f4-943c8c50a34b # phase-16 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 17: Security - Secrets + +## 1. Current State Assessment + +- [ ] Check for existing secret scanning +- [ ] Review pre-commit hooks for secrets +- [ ] Identify secret patterns to detect +- [ ] Check for GitHub secret scanning + +### Existing Assets + +GitHub built-in secret scanning (if enabled on repo). + +### Gaps Identified + +- [ ] secret-scan-precommit.yml (Gitleaks hook) +- [ ] secret-scan-ci.yml (TruffleHog PR gate) +- [ ] secret-scan-audit.yml (GitGuardian audit) +- [ ] .gitleaks.toml configuration +- [ ] Pre-commit hook configuration + +--- + +## 2. Contextual Goal + +Implement defense-in-depth secret scanning with three layers: Gitleaks at pre-commit to catch secrets before commit, TruffleHog in CI to block PRs with secrets, and GitGuardian for post-approval audit and historical scanning. Configure custom patterns for organization-specific secret formats. + +### Success Criteria + +- [ ] Pre-commit hook catches secrets locally +- [ ] CI gate blocks PRs with secrets +- [ ] Audit scanning runs on schedule +- [ ] Custom patterns for org secrets configured +- [ ] False positives minimized with allowlist + +### Out of Scope + +- Secret rotation (operations task) +- Vault integration (deployment config) + +--- + +## 3. Implementation + +### 3.1 Defense-in-Depth Layers + +| Layer | Tool | When | Purpose | +|-------|------|------|---------| +| 1 | Gitleaks | Pre-commit | Block before commit | +| 2 | TruffleHog | PR gate | Block before merge | +| 3 | GitGuardian | Scheduled | Historical audit | + +### 3.2 secret-scan-precommit.yml + +```yaml +name: Pre-commit Secret Scan + +on: + pull_request: + +jobs: + gitleaks: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Gitleaks + uses: gitleaks/gitleaks-action@v2 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### 3.3 secret-scan-ci.yml + +```yaml +name: Secret Scan CI + +on: + pull_request: + +jobs: + trufflehog: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: TruffleHog + uses: trufflesecurity/trufflehog@main + with: + extra_args: --only-verified +``` + +### 3.4 .gitleaks.toml + +```toml +[extend] +useDefault = true + +[[rules]] +id = "org-api-key" +description = "Organization API Key" +regex = '''org_[a-zA-Z0-9]{32}''' +secretGroup = 0 + +[allowlist] +paths = [ + '''\.gitleaks\.toml$''', + '''test/.*fixtures.*''', +] +``` + +### 3.5 Pre-commit Hook + +```yaml +# .pre-commit-config.yaml addition +repos: + - repo: https://github.com/gitleaks/gitleaks + rev: v8.18.0 + hooks: + - id: gitleaks +``` + +--- + +## 4. Review & Validation + +- [ ] Pre-commit hook blocks test secrets +- [ ] CI gate detects secrets in PRs +- [ ] Audit runs on schedule +- [ ] Allowlist prevents false positives +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-18-security-memory.md b/.ai/plans/phases/bundle-contents-phase-18-security-memory.md new file mode 100644 index 0000000..61da76f --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-18-security-memory.md @@ -0,0 +1,166 @@ +--- +id: c8643976-ddd4-4753-b307-b5b4db81b068 +title: "Phase 18: Security - Memory" +status: pending +depends_on: + - 9837e690-439f-42cb-811f-dbcff58a6af9 # phase-17 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 18: Security - Memory + +## 1. Current State Assessment + +- [ ] Check for existing Miri usage +- [ ] Review sanitizer configuration +- [ ] Identify unsafe code blocks +- [ ] Check for Valgrind usage + +### Existing Assets + +None - memory safety analysis not yet configured. + +### Gaps Identified + +- [ ] security-memory-rust.yml (Miri + sanitizers) +- [ ] cargo-careful integration +- [ ] RUSTFLAGS sanitizer matrix +- [ ] security-memory-native.yml (ASan/MSan/TSan) +- [ ] Valgrind workflow + +--- + +## 2. Contextual Goal + +Implement comprehensive memory safety analysis for Rust and native code. Use Miri for detecting undefined behavior in Rust, sanitizers (AddressSanitizer, MemorySanitizer, ThreadSanitizer) for runtime detection, cargo-careful for extra-strict checking, and Valgrind for native code profiling. + +### Success Criteria + +- [ ] Miri runs on all Rust tests +- [ ] Sanitizer matrix covers ASan, MSan, TSan +- [ ] cargo-careful checks pass +- [ ] Memory issues reported clearly +- [ ] No false positives in safe code + +### Out of Scope + +- Performance optimization +- Memory profiling for non-Rust code + +--- + +## 3. Implementation + +### 3.1 security-memory-rust.yml + +```yaml +name: Rust Memory Safety + +on: + push: + branches: [main] + paths: + - '**.rs' + - 'Cargo.toml' + pull_request: + paths: + - '**.rs' + schedule: + - cron: '0 4 * * 1' # Weekly + +jobs: + miri: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@nightly + with: + components: miri + + - uses: Swatinem/rust-cache@v2 + + - name: Run Miri + run: cargo miri test + env: + MIRIFLAGS: -Zmiri-disable-isolation + + sanitizers: + runs-on: ubuntu-latest + strategy: + matrix: + sanitizer: [address, memory, thread] + + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@nightly + + - name: Run with ${{ matrix.sanitizer }} sanitizer + run: cargo test + env: + RUSTFLAGS: -Zsanitizer=${{ matrix.sanitizer }} + RUSTDOCFLAGS: -Zsanitizer=${{ matrix.sanitizer }} + + cargo-careful: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@nightly + + - run: cargo install cargo-careful + + - name: Run cargo-careful + run: cargo careful test +``` + +### 3.2 Sanitizer Matrix + +| Sanitizer | Detects | +|-----------|---------| +| AddressSanitizer | Buffer overflows, use-after-free | +| MemorySanitizer | Uninitialized reads | +| ThreadSanitizer | Data races, deadlocks | +| LeakSanitizer | Memory leaks | + +### 3.3 security-memory-native.yml + +For native code (C/C++ FFI): + +```yaml +name: Native Memory Safety + +on: + push: + branches: [main] + paths: + - '**.c' + - '**.cpp' + schedule: + - cron: '0 4 * * 1' + +jobs: + valgrind: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Valgrind + run: sudo apt-get install -y valgrind + + - name: Run Valgrind + run: valgrind --error-exitcode=1 ./target/release/binary +``` + +--- + +## 4. Review & Validation + +- [ ] Miri detects UB in test code +- [ ] Sanitizers run without crashes +- [ ] No false positives in clean code +- [ ] Clear error reporting +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md b/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md new file mode 100644 index 0000000..9d3b8cc --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md @@ -0,0 +1,192 @@ +--- +id: b3db6c9b-ec1e-4298-b8f5-2149afcd5050 +title: "Phase 19: Security - Fuzzing" +status: pending +depends_on: + - c8643976-ddd4-4753-b307-b5b4db81b068 # phase-18 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 19: Security - Fuzzing + +## 1. Current State Assessment + +- [ ] Check for existing fuzz targets +- [ ] Review cargo-fuzz configuration +- [ ] Identify fuzzing corpus location +- [ ] Check for OSS-Fuzz integration + +### Existing Assets + +None - fuzzing not yet configured. + +### Gaps Identified + +- [ ] security-fuzz-rust.yml (cargo-fuzz + AFL++) +- [ ] security-fuzz-python.yml (Atheris + Hypothesis) +- [ ] security-fuzz-go.yml (go-fuzz) +- [ ] security-fuzz-api.yml (Schemathesis) +- [ ] MCP protocol fuzzer +- [ ] Fuzz corpus management +- [ ] Crash triage workflow + +--- + +## 2. Contextual Goal + +Implement comprehensive fuzzing for discovering edge cases and security vulnerabilities. Create language-specific fuzz targets, an MCP protocol fuzzer, and API fuzzers. Manage corpus storage for regression testing, automate crash triage, and integrate with OSS-Fuzz for continuous fuzzing. + +### Success Criteria + +- [ ] Fuzz targets for each language +- [ ] MCP protocol fuzzer operational +- [ ] API fuzzing with Schemathesis +- [ ] Corpus stored and versioned +- [ ] Crash triage automated + +### Out of Scope + +- OSS-Fuzz setup (requires separate process) +- Long-running fuzzing campaigns + +--- + +## 3. Implementation + +### 3.1 security-fuzz-rust.yml + +```yaml +name: Rust Fuzzing + +on: + schedule: + - cron: '0 3 * * *' # Daily + workflow_dispatch: + inputs: + duration: + description: 'Fuzzing duration (seconds)' + default: '300' + +jobs: + cargo-fuzz: + runs-on: ubuntu-latest + strategy: + matrix: + target: [parse_json, parse_request, tool_call] + + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@nightly + + - run: cargo install cargo-fuzz + + - name: Restore corpus + uses: actions/cache@v4 + with: + path: fuzz/corpus/${{ matrix.target }} + key: fuzz-corpus-${{ matrix.target }}-${{ github.sha }} + restore-keys: fuzz-corpus-${{ matrix.target }}- + + - name: Run fuzzer + run: | + cargo fuzz run ${{ matrix.target }} -- \ + -max_total_time=${{ inputs.duration || 300 }} + continue-on-error: true + + - name: Upload crashes + if: always() + uses: actions/upload-artifact@v4 + with: + name: crashes-${{ matrix.target }} + path: fuzz/artifacts/${{ matrix.target }} + if-no-files-found: ignore +``` + +### 3.2 security-fuzz-api.yml + +```yaml +name: API Fuzzing + +on: + schedule: + - cron: '0 4 * * 1' + workflow_dispatch: + +jobs: + schemathesis: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Start API server + run: docker compose up -d + + - name: Run Schemathesis + run: | + pip install schemathesis + schemathesis run http://localhost:8080/openapi.json \ + --stateful=links \ + --checks all \ + --report schemathesis-report.json + + - name: Upload report + uses: actions/upload-artifact@v4 + with: + name: schemathesis-report + path: schemathesis-report.json +``` + +### 3.3 MCP Protocol Fuzzer + +```rust +// fuzz/fuzz_targets/mcp_protocol.rs +#![no_main] +use libfuzzer_sys::fuzz_target; + +fuzz_target!(|data: &[u8]| { + if let Ok(s) = std::str::from_utf8(data) { + // Try to parse as JSON-RPC request + let _ = serde_json::from_str::(s); + } +}); +``` + +### 3.4 Crash Triage + +```yaml +name: Triage Crashes + +on: + workflow_run: + workflows: ["Rust Fuzzing"] + types: [completed] + +jobs: + triage: + runs-on: ubuntu-latest + if: ${{ github.event.workflow_run.conclusion == 'failure' }} + steps: + - name: Download crashes + uses: actions/download-artifact@v4 + + - name: Deduplicate crashes + run: | + # Hash-based deduplication + + - name: Create issues + run: | + # Auto-create issues for new crashes +``` + +--- + +## 4. Review & Validation + +- [ ] All fuzz targets run successfully +- [ ] Crashes are captured and triaged +- [ ] Corpus grows over time +- [ ] No crashes in stable code +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-20-security-taint.md b/.ai/plans/phases/bundle-contents-phase-20-security-taint.md new file mode 100644 index 0000000..00fd8dd --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-20-security-taint.md @@ -0,0 +1,172 @@ +--- +id: 0e96d833-2d1f-4d8a-b7d3-3711ea49f320 +title: "Phase 20: Security - Taint" +status: pending +depends_on: + - b3db6c9b-ec1e-4298-b8f5-2149afcd5050 # phase-19 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 20: Security - Taint + +## 1. Current State Assessment + +- [ ] Check for existing data flow analysis +- [ ] Review CodeQL taint tracking usage +- [ ] Identify MCP-specific data flows +- [ ] Check for Pysa configuration + +### Existing Assets + +CodeQL (Phase 16) provides some taint tracking. + +### Gaps Identified + +- [ ] security-taint.yml (CodeQL data flow) +- [ ] Semgrep taint rules for MCP +- [ ] Pysa configuration for Python +- [ ] Custom source/sink definitions + +--- + +## 2. Contextual Goal + +Implement taint analysis to track data flow from untrusted sources to sensitive sinks. This is critical for MCP servers where tool inputs flow to system operations. Define MCP-specific sources (tool arguments, resource URIs) and sinks (file operations, command execution) to detect injection vulnerabilities. + +### Success Criteria + +- [ ] CodeQL taint queries functional +- [ ] Semgrep taint rules for MCP +- [ ] Pysa configured for Python servers +- [ ] Custom sources/sinks documented +- [ ] No false negatives on known patterns + +### Out of Scope + +- Runtime taint tracking (RASP) +- Full formal verification + +--- + +## 3. Implementation + +### 3.1 security-taint.yml + +```yaml +name: Taint Analysis + +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '0 5 * * 1' + +jobs: + codeql-taint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: python + queries: security-and-quality + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Analyze + uses: github/codeql-action/analyze@v3 + + semgrep-taint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Semgrep Taint + uses: returntocorp/semgrep-action@v1 + with: + config: .semgrep/taint-rules.yml +``` + +### 3.2 MCP Taint Rules + +```yaml +# .semgrep/taint-rules.yml +rules: + - id: mcp-taint-tool-to-file + mode: taint + message: Untrusted tool input flows to file operation + severity: ERROR + languages: [python] + pattern-sources: + - patterns: + - pattern: $ARGS["$KEY"] + - pattern-inside: | + def $TOOL(..., $ARGS: dict, ...): + ... + pattern-sinks: + - pattern: open($PATH, ...) + - pattern: os.path.join(..., $PATH, ...) + + - id: mcp-taint-resource-to-command + mode: taint + message: Resource URI flows to command execution + severity: ERROR + languages: [python] + pattern-sources: + - pattern: $URI + pattern-inside: | + def read_resource($URI, ...): + ... + pattern-sinks: + - pattern: subprocess.run($CMD, ...) + - pattern: os.system($CMD) +``` + +### 3.3 MCP Sources and Sinks + +| Category | Sources | Sinks | +|----------|---------|-------| +| Tools | `arguments` dict, `name` param | File ops, subprocess, DB | +| Resources | `uri` param, template vars | File read, network fetch | +| Prompts | `arguments` dict | Any output | + +### 3.4 Pysa Configuration + +```python +# .pyre/taint.config +{ + "sources": [ + {"name": "MCPToolInput", "comment": "Tool arguments from client"}, + {"name": "MCPResourceURI", "comment": "Resource URI from client"} + ], + "sinks": [ + {"name": "FileSystem", "comment": "File system operations"}, + {"name": "CommandExecution", "comment": "Shell/subprocess"} + ], + "features": [], + "rules": [ + { + "name": "MCP Injection", + "code": 1001, + "sources": ["MCPToolInput", "MCPResourceURI"], + "sinks": ["FileSystem", "CommandExecution"] + } + ] +} +``` + +--- + +## 4. Review & Validation + +- [ ] Taint analysis detects known vulnerabilities +- [ ] Custom rules cover MCP patterns +- [ ] No false negatives on test cases +- [ ] Sources and sinks are complete +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-21-security-containers.md b/.ai/plans/phases/bundle-contents-phase-21-security-containers.md new file mode 100644 index 0000000..37d7a14 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-21-security-containers.md @@ -0,0 +1,784 @@ +--- +id: 6330d055-1bfd-46ec-9458-f006fff1e9b9 +title: "Phase 21: Security - Containers" +status: pending +depends_on: + - 0e96d833-2d1f-4d8a-b7d3-3711ea49f320 # phase-20 + - e9f0a1b2-c3d4-5e6f-7a8b-9c0d1e2f3a4b # phase-22a (policy library) +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - container-scanning-strategy-adr # ADR for Grype-only decision + - ../../docs/strategies/policy-as-code.md # Unified policy strategy +issues: [] +--- + +# Phase 21: Security - Containers + +## 1. Current State Assessment + +- [ ] Check for existing container scanning +- [ ] Review Dockerfile hardening practices +- [ ] Identify base image policies +- [ ] Check for runtime security configs + +### Existing Assets + +- Hadolint (Phase 03) lints Dockerfiles +- Container structure tests (Phase 04) + +### Gaps Identified + +- [ ] security-container.yml (Grype + Docker Bench) +- [ ] base-image-policy.yml (with scratch support) +- [ ] runtime-config-validation.yml (OPA/Conftest) +- [ ] image-size-check.yml +- [ ] Seccomp profile templates +- [ ] Container hardening checklist + +--- + +## 2. Contextual Goal + +Implement comprehensive container security scanning and hardening using SRP-compliant tooling. Use Grype exclusively for CVE scanning (not Trivy, which violates SRP by bundling multiple capabilities). Enforce base image policies including scratch images, verify CIS benchmarks with Docker Bench, validate runtime configs with OPA/Conftest, and enforce image size limits. + +### Tool Selection Rationale + +> **Decision**: Use Grype instead of Trivy for vulnerability scanning. +> +> **Rationale**: Trivy violates Single Responsibility Principle by combining CVE scanning, secret detection, misconfiguration scanning, IaC scanning, and license scanning into one tool. We prefer specialized tools: +> +> | Capability | Tool | Phase | +> |------------|------|-------| +> | CVE Scanning | **Grype** | 21 | +> | SBOM Generation | Syft | 23 | +> | Secret Scanning | Gitleaks | 17 | +> | Misconfiguration | Conftest/OPA | 21 | +> | License Scanning | cargo-deny, Syft | 15 | +> +> **Trade-offs**: +> - Grype v6 includes CISA KEV and EPSS data (Trivy doesn't) +> - Grype has fewer false positives (prioritizes GitHub Advisory over CPE) +> - Losing: Arch, AlmaLinux, Rocky Linux, Photon OS coverage (acceptable for MCP servers) +> - Losing: Go Vulnerability Database integration (add govulncheck separately if needed) + +### Success Criteria + +- [ ] Container scanning with Grype (CISA KEV + EPSS enabled) +- [ ] Base image allowlist enforced (including scratch) +- [ ] Docker Bench compliance checked +- [ ] Runtime configs validated with Conftest +- [ ] Image size limits enforced +- [ ] Seccomp profiles provided +- [ ] Non-root enforcement verified + +### Out of Scope + +- Kubernetes-specific security (deployment configs) +- Runtime monitoring (Falco) +- Trivy (replaced by specialized tools per SRP) + +--- + +## 3. Implementation + +### 3.1 security-container.yml + +```yaml +name: Container Security + +on: + push: + branches: [main] + paths: + - 'Dockerfile*' + - 'docker/**' + pull_request: + paths: + - 'Dockerfile*' + - 'docker/**' + schedule: + - cron: '0 6 * * *' + +env: + IMAGE_NAME: app + IMAGE_TAG: test + # Grype v6 settings + GRYPE_DB_AUTO_UPDATE: true + GRYPE_DB_VALIDATE_AGE: true + +jobs: + grype: + name: Vulnerability Scan (Grype) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build image + run: docker build -t ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} . + + - name: Scan with Grype + uses: anchore/scan-action@v4 + id: scan + with: + image: ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} + fail-build: true + severity-cutoff: high + output-format: sarif + # v6 features: include KEV and EPSS data + add-cpes-if-none: false # Reduce false positives + + - name: Upload SARIF to GitHub Security + uses: github/codeql-action/upload-sarif@v3 + if: always() + with: + sarif_file: ${{ steps.scan.outputs.sarif }} + + - name: Check for CISA KEV matches + run: | + # Grype v6 outputs KEV matches - fail if any found + if grep -q '"kev":true' ${{ steps.scan.outputs.json }} 2>/dev/null; then + echo "::error::Image contains vulnerabilities in CISA Known Exploited Vulnerabilities catalog" + exit 1 + fi + + docker-bench: + name: CIS Benchmark (Docker Bench) + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build image + run: docker build -t ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} . + + - name: Run Docker Bench + run: | + docker run --rm --net host --pid host --userns host --cap-add audit_control \ + -v /var/lib:/var/lib:ro \ + -v /var/run/docker.sock:/var/run/docker.sock:ro \ + -v /etc:/etc:ro \ + -v "$(pwd)":/workspace:ro \ + docker/docker-bench-security \ + -c container_images \ + -i ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} \ + -l /workspace/docker-bench-results.log + + - name: Check critical failures + run: | + if grep -E "\[WARN\].*4\.[0-9]+" docker-bench-results.log; then + echo "::warning::Docker Bench found container image warnings" + fi + # Fail on critical container image checks + if grep -E "\[WARN\].*4\.(1|2|3|6)" docker-bench-results.log; then + echo "::error::Critical Docker Bench failures detected" + exit 1 + fi + + - name: Upload results + uses: actions/upload-artifact@v4 + if: always() + with: + name: docker-bench-results + path: docker-bench-results.log + + image-size: + name: Image Size Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build image + run: docker build -t ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} . + + - name: Check image size + run: | + SIZE_BYTES=$(docker image inspect ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} --format='{{.Size}}') + SIZE_MB=$((SIZE_BYTES / 1024 / 1024)) + + echo "Image size: ${SIZE_MB}MB" + + # Configurable thresholds + WARN_THRESHOLD=${IMAGE_SIZE_WARN_MB:-100} + FAIL_THRESHOLD=${IMAGE_SIZE_FAIL_MB:-500} + + if [ "$SIZE_MB" -gt "$FAIL_THRESHOLD" ]; then + echo "::error::Image size ${SIZE_MB}MB exceeds maximum allowed ${FAIL_THRESHOLD}MB" + exit 1 + elif [ "$SIZE_MB" -gt "$WARN_THRESHOLD" ]; then + echo "::warning::Image size ${SIZE_MB}MB exceeds recommended ${WARN_THRESHOLD}MB" + else + echo "::notice::Image size ${SIZE_MB}MB is within acceptable limits" + fi + + - name: Analyze layers + run: | + echo "## Layer Analysis" >> $GITHUB_STEP_SUMMARY + docker history ${{ env.IMAGE_NAME }}:${{ env.IMAGE_TAG }} --no-trunc --format "table {{.Size}}\t{{.CreatedBy}}" >> $GITHUB_STEP_SUMMARY +``` + +### 3.2 base-image-policy.yml + +```yaml +name: Base Image Policy + +on: + pull_request: + paths: + - 'Dockerfile*' + - '**/Dockerfile*' + +jobs: + check-base-image: + name: Verify Base Image Allowlist + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Find all Dockerfiles + id: find + run: | + FILES=$(find . -name 'Dockerfile*' -type f | tr '\n' ' ') + echo "files=$FILES" >> $GITHUB_OUTPUT + + - name: Check base images + run: | + # Allowlist patterns (regex) + # - scratch: Empty base for static binaries (Go, Rust) + # - distroless: Google's minimal images + # - chainguard: Hardened, SLSA-attested images + # - alpine: Small, security-focused (use with caution) + # - debian-slim: When alpine musl is incompatible + ALLOWLIST=( + "^scratch$" + "^gcr\.io/distroless/" + "^cgr\.dev/chainguard/" + "^docker\.io/library/alpine:" + "^alpine:" + "^debian:.*-slim$" + "^docker\.io/library/debian:.*-slim$" + "^rust:.*-alpine" + "^golang:.*-alpine" + "^python:.*-slim" + "^node:.*-alpine" + ) + + FAILED=0 + + for dockerfile in ${{ steps.find.outputs.files }}; do + echo "Checking: $dockerfile" + + # Extract all FROM instructions (handle multi-stage builds) + BASES=$(grep -E '^FROM' "$dockerfile" | awk '{print $2}' | grep -v '^\$' || true) + + for base in $BASES; do + # Skip build stage references (e.g., "FROM builder AS runtime") + if echo "$base" | grep -qE '^[a-z]+$' && ! echo "$base" | grep -qE '^(scratch|alpine|debian|ubuntu|centos|fedora)$'; then + echo " Skipping build stage reference: $base" + continue + fi + + ALLOWED=0 + for pattern in "${ALLOWLIST[@]}"; do + if echo "$base" | grep -qE "$pattern"; then + ALLOWED=1 + echo " ✅ $base (matches: $pattern)" + break + fi + done + + if [ "$ALLOWED" -eq 0 ]; then + echo " ❌ $base (not in allowlist)" + FAILED=1 + fi + done + done + + if [ "$FAILED" -eq 1 ]; then + echo "" + echo "::error::One or more base images are not in the allowlist" + echo "" + echo "Allowed base images:" + for pattern in "${ALLOWLIST[@]}"; do + echo " - $pattern" + done + exit 1 + fi + + echo "::notice::All base images are approved" +``` + +### 3.3 runtime-config-validation.yml + +> **Policy Source**: This workflow uses policies from the unified policy library (Phase 22a). +> See [Policy-as-Code Strategy](../../docs/strategies/policy-as-code.md) for policy patterns. + +```yaml +name: Runtime Config Validation + +on: + pull_request: + paths: + - 'docker-compose*.yml' + - 'docker-compose*.yaml' + - 'compose*.yml' + - 'compose*.yaml' + - '.docker/**' + - 'policies/container/**' # Re-validate on policy changes + +jobs: + conftest: + name: Validate with Conftest/OPA + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Conftest + uses: instrumenta/conftest-action@master + with: + version: latest + + - name: Find compose files + id: find + run: | + FILES=$(find . -name 'docker-compose*.yml' -o -name 'docker-compose*.yaml' -o -name 'compose*.yml' -o -name 'compose*.yaml' | tr '\n' ' ') + echo "files=$FILES" >> $GITHUB_OUTPUT + + - name: Validate compose files + run: | + for file in ${{ steps.find.outputs.files }}; do + echo "Validating: $file" + conftest test "$file" \ + --policy policies/container/ \ + --data policies/data/ \ + --output github \ + --all-namespaces + done + + - name: Generate validation report + if: always() + run: | + echo "## Container Config Validation" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Policies from: \`policies/container/\`" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "See [Policy-as-Code Strategy](docs/strategies/policy-as-code.md) for details." >> $GITHUB_STEP_SUMMARY +``` + +### 3.3.1 Container Policies (in policies/container/) + +> **Note**: These policies are implemented in the unified policy library (Phase 22a). +> This section documents the policies this phase contributes to the library. + +**File**: `policies/container/privileged.rego` + +```rego +# METADATA +# title: No Privileged Containers +# description: Containers must not run in privileged mode +# custom: +# severity: high +# phase: 21 + +package mcp.container.privileged + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +deny contains msg if { + some name, service in input.services + service.privileged == true + msg := sprintf("Service '%s' must not run in privileged mode", [name]) +} +``` + +**File**: `policies/container/root_user.rego` + +```rego +# METADATA +# title: No Root User +# description: Containers must not run as root +# custom: +# severity: high +# phase: 21 + +package mcp.container.root_user + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +deny contains msg if { + some name, service in input.services + service.user == "root" + msg := sprintf("Service '%s' must not run as root user", [name]) +} + +deny contains msg if { + some name, service in input.services + service.user == "0" + msg := sprintf("Service '%s' must not run as UID 0", [name]) +} + +warn contains msg if { + some name, service in input.services + not service.user + msg := sprintf("Service '%s' has no user specified (will run as root)", [name]) +} +``` + +**File**: `policies/container/networking.rego` + +```rego +# METADATA +# title: Network Isolation +# description: Containers must not use host networking +# custom: +# severity: high +# phase: 21 + +package mcp.container.networking + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +deny contains msg if { + some name, service in input.services + service.network_mode == "host" + msg := sprintf("Service '%s' must not use host networking", [name]) +} + +deny contains msg if { + some name, service in input.services + service.pid == "host" + msg := sprintf("Service '%s' must not use host PID namespace", [name]) +} +``` + +**File**: `policies/container/capabilities.rego` + +```rego +# METADATA +# title: Capability Restrictions +# description: Containers must not have dangerous capabilities +# custom: +# severity: high +# phase: 21 + +package mcp.container.capabilities + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +import data.mcp.dangerous_capabilities + +deny contains msg if { + some name, service in input.services + some cap in service.cap_add + cap in dangerous_capabilities + msg := sprintf("Service '%s' has dangerous capability: %s", [name, cap]) +} +``` + +**File**: `policies/container/resources.rego` + +```rego +# METADATA +# title: Resource Limits +# description: Containers should have resource limits defined +# custom: +# severity: medium +# phase: 21 + +package mcp.container.resources + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +warn contains msg if { + some name, service in input.services + not service.deploy.resources.limits + not service.mem_limit + msg := sprintf("Service '%s' has no memory limits defined", [name]) +} + +warn contains msg if { + some name, service in input.services + not service.read_only + msg := sprintf("Service '%s' does not have read-only root filesystem", [name]) +} +``` + +**File**: `policies/container/volumes.rego` + +```rego +# METADATA +# title: Volume Restrictions +# description: Containers must not mount dangerous volumes +# custom: +# severity: critical +# phase: 21 + +package mcp.container.volumes + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +deny contains msg if { + some name, service in input.services + some volume in service.volumes + contains(volume, "docker.sock") + msg := sprintf("Service '%s' mounts Docker socket - security risk", [name]) +} +``` + +### 3.3.2 Container Policy Tests + +**File**: `policies/tests/container_test.rego` + +```rego +package mcp.container_test + +import data.mcp.container.privileged +import data.mcp.container.root_user +import data.mcp.container.networking + +# Privileged tests +test_deny_privileged if { + result := privileged.deny with input as { + "services": {"web": {"privileged": true}} + } + count(result) == 1 +} + +test_allow_non_privileged if { + result := privileged.deny with input as { + "services": {"web": {"privileged": false}} + } + count(result) == 0 +} + +# Root user tests +test_deny_root_user if { + result := root_user.deny with input as { + "services": {"web": {"user": "root"}} + } + count(result) == 1 +} + +test_deny_uid_zero if { + result := root_user.deny with input as { + "services": {"web": {"user": "0"}} + } + count(result) == 1 +} + +test_warn_no_user if { + result := root_user.warn with input as { + "services": {"web": {"image": "nginx"}} + } + count(result) == 1 +} + +# Networking tests +test_deny_host_network if { + result := networking.deny with input as { + "services": {"web": {"network_mode": "host"}} + } + count(result) == 1 +} + +test_deny_host_pid if { + result := networking.deny with input as { + "services": {"web": {"pid": "host"}} + } + count(result) == 1 +} +``` + +### 3.4 Seccomp Profile + +**File**: `configs/security/seccomp-default.json` + +```json +{ + "defaultAction": "SCMP_ACT_ERRNO", + "defaultErrnoRet": 1, + "archMap": [ + { + "architecture": "SCMP_ARCH_X86_64", + "subArchitectures": ["SCMP_ARCH_X86", "SCMP_ARCH_X32"] + }, + { + "architecture": "SCMP_ARCH_AARCH64", + "subArchitectures": ["SCMP_ARCH_ARM"] + } + ], + "syscalls": [ + { + "names": [ + "accept", "accept4", "access", "arch_prctl", "bind", "brk", + "capget", "capset", "chdir", "chmod", "chown", "clock_gettime", + "clone", "close", "connect", "dup", "dup2", "dup3", "epoll_create", + "epoll_create1", "epoll_ctl", "epoll_pwait", "epoll_wait", "execve", + "exit", "exit_group", "faccessat", "fadvise64", "fallocate", "fchmod", + "fchown", "fcntl", "fdatasync", "flock", "fork", "fstat", "fstatfs", + "fsync", "ftruncate", "futex", "getcwd", "getdents", "getdents64", + "getegid", "geteuid", "getgid", "getgroups", "getpeername", "getpgid", + "getpgrp", "getpid", "getppid", "getpriority", "getrandom", "getresgid", + "getresuid", "getrlimit", "getrusage", "getsid", "getsockname", + "getsockopt", "gettid", "gettimeofday", "getuid", "inotify_add_watch", + "inotify_init", "inotify_init1", "inotify_rm_watch", "ioctl", "kill", + "lchown", "link", "linkat", "listen", "lseek", "lstat", "madvise", + "memfd_create", "mkdir", "mkdirat", "mknod", "mknodat", "mlock", + "mlock2", "mlockall", "mmap", "mprotect", "mremap", "msync", "munlock", + "munlockall", "munmap", "nanosleep", "newfstatat", "open", "openat", + "pause", "pipe", "pipe2", "poll", "ppoll", "prctl", "pread64", + "preadv", "preadv2", "prlimit64", "pselect6", "pwrite64", "pwritev", + "pwritev2", "read", "readahead", "readlink", "readlinkat", "readv", + "recvfrom", "recvmmsg", "recvmsg", "rename", "renameat", "renameat2", + "restart_syscall", "rmdir", "rt_sigaction", "rt_sigpending", + "rt_sigprocmask", "rt_sigqueueinfo", "rt_sigreturn", "rt_sigsuspend", + "rt_sigtimedwait", "rt_tgsigqueueinfo", "sched_getaffinity", + "sched_getparam", "sched_getscheduler", "sched_get_priority_max", + "sched_get_priority_min", "sched_setaffinity", "sched_yield", "select", + "sendfile", "sendmmsg", "sendmsg", "sendto", "setfsgid", "setfsuid", + "setgid", "setgroups", "setitimer", "setpgid", "setpriority", + "setregid", "setresgid", "setresuid", "setreuid", "setsid", + "setsockopt", "set_robust_list", "set_tid_address", "setuid", "shutdown", + "sigaltstack", "socket", "socketpair", "splice", "stat", "statfs", + "statx", "symlink", "symlinkat", "sync", "sync_file_range", "tee", + "tgkill", "time", "timer_create", "timer_delete", "timerfd_create", + "timerfd_gettime", "timerfd_settime", "timer_getoverrun", "timer_gettime", + "timer_settime", "times", "tkill", "truncate", "umask", "uname", + "unlink", "unlinkat", "utime", "utimensat", "utimes", "vfork", "wait4", + "waitid", "write", "writev" + ], + "action": "SCMP_ACT_ALLOW" + } + ] +} +``` + +### 3.5 Container Hardening Checklist + +#### Build-Time Hardening + +- [ ] Non-root user defined (`USER` directive) +- [ ] Multi-stage build used (smaller final image) +- [ ] No secrets in build args or layers +- [ ] `.dockerignore` excludes sensitive files +- [ ] Specific version tags used (not `:latest`) +- [ ] Base image from allowlist +- [ ] `HEALTHCHECK` defined + +#### Runtime Hardening + +- [ ] Read-only root filesystem (`read_only: true`) +- [ ] No privileged mode (`privileged: false`) +- [ ] Minimal capabilities (`cap_drop: [ALL]`) +- [ ] No host networking (`network_mode` not `host`) +- [ ] No host PID namespace (`pid` not `host`) +- [ ] Memory limits set (`mem_limit`) +- [ ] CPU limits set (`cpus`) +- [ ] Seccomp profile applied +- [ ] No Docker socket mount + +--- + +## 4. Review & Validation + +- [ ] Grype detects known vulnerabilities with CISA KEV flagging +- [ ] Base image policy blocks non-allowed images +- [ ] Base image policy allows `scratch` for static binaries +- [ ] Docker Bench passes critical checks (4.1, 4.2, 4.3, 4.6) +- [ ] Conftest validates compose files against OPA policies +- [ ] Image size check enforces thresholds +- [ ] Seccomp profiles don't break functionality +- [ ] Implementation tracking checklist updated + +--- + +## 5. Vulnerability Prioritization Strategy + +With Grype v6, we have multiple signals for prioritizing vulnerabilities: + +### 5.1 Priority Matrix + +| Signal | Source | Weight | Action | +|--------|--------|--------|--------| +| CISA KEV | Known exploited | **Critical** | Block deployment immediately | +| EPSS > 0.5 | Exploit prediction | High | Fix within 24 hours | +| CVSS >= 9.0 | Severity score | High | Fix within 7 days | +| CVSS >= 7.0 | Severity score | Medium | Fix within 30 days | +| CVSS < 7.0 | Severity score | Low | Track and plan | + +### 5.2 Prioritization Workflow + +```yaml +# Add to security-container.yml after Grype scan +- name: Prioritize vulnerabilities + run: | + # Parse Grype JSON output + RESULTS="${{ steps.scan.outputs.json }}" + + # Count by priority + KEV_COUNT=$(jq '[.matches[] | select(.vulnerability.kev == true)] | length' "$RESULTS") + HIGH_EPSS=$(jq '[.matches[] | select(.vulnerability.epss > 0.5)] | length' "$RESULTS") + CRITICAL=$(jq '[.matches[] | select(.vulnerability.severity == "Critical")] | length' "$RESULTS") + + echo "## Vulnerability Summary" >> $GITHUB_STEP_SUMMARY + echo "| Priority | Count | Action |" >> $GITHUB_STEP_SUMMARY + echo "|----------|-------|--------|" >> $GITHUB_STEP_SUMMARY + echo "| CISA KEV (Active Exploit) | $KEV_COUNT | 🔴 Block |" >> $GITHUB_STEP_SUMMARY + echo "| High EPSS (>50%) | $HIGH_EPSS | 🟠 24h fix |" >> $GITHUB_STEP_SUMMARY + echo "| Critical CVSS | $CRITICAL | 🟡 7d fix |" >> $GITHUB_STEP_SUMMARY + + # Fail if any KEV vulnerabilities found + if [ "$KEV_COUNT" -gt 0 ]; then + echo "::error::Found $KEV_COUNT vulnerabilities in CISA KEV catalog" + exit 1 + fi + + # Warn on high EPSS + if [ "$HIGH_EPSS" -gt 0 ]; then + echo "::warning::Found $HIGH_EPSS vulnerabilities with high exploit probability (EPSS > 50%)" + fi +``` + +### 5.3 Why Not Multi-Scanner Reconciliation? + +> **Previous approach**: Run both Grype and Trivy, reconcile conflicting results. +> +> **Current approach**: Single scanner (Grype) with multiple priority signals. +> +> **Rationale**: +> - Multi-scanner creates noise without clear prioritization +> - False positive reconciliation is complex and error-prone +> - Grype v6 provides sufficient signal diversity (KEV, EPSS, CVSS, vendor severity) +> - SRP: One tool for CVE scanning, multiple signals for prioritization +> +> If additional coverage is needed for specific ecosystems (Go stdlib, Arch Linux), add **targeted tools** rather than another general scanner. + +--- + +## 6. Data Source Coverage Note + +> **Note**: By choosing Grype over Trivy, we accept reduced coverage for: +> +> | OS/Source | Status | Mitigation | +> |-----------|--------|------------| +> | Arch Linux | Not covered | Not used for MCP servers | +> | AlmaLinux | Not covered | Use RHEL/CentOS base instead | +> | Rocky Linux | Not covered | Use RHEL/CentOS base instead | +> | Photon OS | Not covered | Not used for MCP servers | +> | Go stdlib vulns | Partial | Add `govulncheck` in Phase 04 if needed | +> +> **Gained capabilities in Grype v6**: +> - CISA Known Exploited Vulnerabilities (KEV) flagging +> - EPSS (Exploit Prediction Scoring System) risk scores +> - Reduced false positives via GitHub Advisory prioritization diff --git a/.ai/plans/phases/bundle-contents-phase-22-security-compliance.md b/.ai/plans/phases/bundle-contents-phase-22-security-compliance.md new file mode 100644 index 0000000..12cb663 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-22-security-compliance.md @@ -0,0 +1,337 @@ +--- +id: b357c053-9d64-4efa-a06f-34bdd138271e +title: "Phase 22: Security - Compliance" +status: pending +depends_on: + - 6330d055-1bfd-46ec-9458-f006fff1e9b9 # phase-21 + - e9f0a1b2-c3d4-5e6f-7a8b-9c0d1e2f3a4b # phase-22a (policy library) +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking + - 4e593fba-d836-4aa6-9a27-d833df63e90f # gap-analysis +references: + - ../../docs/strategies/policy-as-code.md # Unified policy strategy +issues: [] +--- + +# Phase 22: Security - Compliance + +## 1. Current State Assessment + +- [ ] Check for existing compliance workflows +- [ ] Review CIS benchmark coverage +- [ ] Identify compliance requirements +- [ ] Check for OPA/Conftest usage + +### Existing Assets + +Docker Bench (Phase 21) covers CIS for containers. + +### Gaps Identified + +- [ ] compliance-cis.yml (CIS benchmarks) +- [ ] compliance-pci.yml (PCI-DSS) +- [ ] compliance-hipaa.yml (HIPAA) +- [ ] OPA/Rego policy library +- [ ] Compliance documentation templates + +--- + +## 2. Contextual Goal + +Establish compliance checking workflows for common frameworks. Implement CIS benchmarks for infrastructure, PCI-DSS checklists for payment handling, and HIPAA checklists for health data. Use OPA/Rego for policy-as-code enforcement. Generate compliance evidence documentation automatically. + +### Success Criteria + +- [ ] CIS benchmark workflow functional +- [ ] PCI-DSS checklist automation +- [ ] HIPAA checklist automation +- [ ] OPA policies reusable +- [ ] Evidence documentation generated + +### Out of Scope + +- Full compliance audits (requires human review) +- SOC 2 / ISO 27001 (future phases) + +--- + +## 3. Implementation + +### 3.1 compliance-cis.yml + +```yaml +name: CIS Compliance + +on: + schedule: + - cron: '0 6 * * 1' + workflow_dispatch: + +jobs: + docker-cis: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Docker CIS Benchmark + run: | + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \ + docker/docker-bench-security + + - name: Parse results + run: | + # Convert to machine-readable format + + kubernetes-cis: + runs-on: ubuntu-latest + if: false # Enable when K8s is used + steps: + - name: Install kube-bench + run: | + curl -L https://github.com/aquasecurity/kube-bench/releases/download/v0.7.0/kube-bench_0.7.0_linux_amd64.tar.gz | tar xz + + - name: Run kube-bench + run: ./kube-bench run --targets node +``` + +### 3.2 Compliance Policies (in policies/compliance/) + +> **Policy Source**: These policies are part of the unified policy library (Phase 22a). +> See [Policy-as-Code Strategy](../../docs/strategies/policy-as-code.md) for policy patterns. + +This phase contributes the following policies to the library: + +**File**: `policies/compliance/cis/docker.rego` + +```rego +# METADATA +# title: CIS Docker Benchmark Policies +# description: Policy checks aligned with CIS Docker Benchmark +# custom: +# framework: CIS +# version: "1.5.0" +# phase: 22 + +package mcp.compliance.cis.docker + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +# CIS 4.1 - Ensure a user for the container has been created +deny contains msg if { + input.User == "root" + msg := "CIS 4.1: Container must not run as root" +} + +deny contains msg if { + input.User == "" + msg := "CIS 4.1: Container must specify a non-root user" +} + +# CIS 4.2 - Ensure that containers use only trusted base images +# (Implemented in Phase 21 base-image-policy.yml) + +# CIS 4.6 - Ensure that HEALTHCHECK instructions have been added +warn contains msg if { + not input.Healthcheck + msg := "CIS 4.6: Container should have HEALTHCHECK instruction" +} + +# CIS 5.2 - Ensure SELinux security options are set +warn contains msg if { + not input.SecurityOpt + msg := "CIS 5.2: Container should have security options defined" +} + +# CIS 5.4 - Ensure that privileged containers are not used +deny contains msg if { + input.Privileged == true + msg := "CIS 5.4: Container must not be privileged" +} + +# CIS 5.12 - Ensure that the container's root filesystem is mounted as read only +warn contains msg if { + input.ReadOnlyRootFilesystem != true + msg := "CIS 5.12: Container should have read-only root filesystem" +} + +# CIS 5.25 - Ensure that the container is restricted from acquiring additional privileges +deny contains msg if { + not no_new_privileges(input) + msg := "CIS 5.25: Container should not acquire additional privileges" +} + +no_new_privileges(config) if { + some opt in config.SecurityOpt + opt == "no-new-privileges:true" +} + +no_new_privileges(config) if { + config.SecurityOpt == null +} +``` + +**File**: `policies/compliance/pci_dss.rego` + +```rego +# METADATA +# title: PCI-DSS Compliance Checks +# description: Policy checks for PCI-DSS requirements +# custom: +# framework: PCI-DSS +# version: "4.0" +# phase: 22 + +package mcp.compliance.pci_dss + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +# PCI-DSS 2.2.1 - Configuration standards +deny contains msg if { + input.Privileged == true + msg := "PCI-DSS 2.2.1: Privileged containers violate configuration standards" +} + +# PCI-DSS 8.3.1 - Strong authentication +warn contains msg if { + some env in input.Env + contains(env, "PASSWORD=") + msg := "PCI-DSS 8.3.1: Passwords should not be in environment variables" +} + +# PCI-DSS 10.2 - Audit logging +warn contains msg if { + not has_logging_config(input) + msg := "PCI-DSS 10.2: Container should have logging configuration" +} + +has_logging_config(config) if { + config.LogConfig +} + +has_logging_config(config) if { + config.Labels["logging"] +} +``` + +### 3.3 conftest-compliance.yml + +```yaml +name: Compliance Policy Check + +on: + pull_request: + paths: + - 'Dockerfile*' + - 'docker/**' + - 'policies/compliance/**' + schedule: + - cron: '0 6 * * 1' # Weekly compliance check + +jobs: + conftest: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup Conftest + uses: instrumenta/conftest-action@master + with: + version: latest + + - name: Parse Dockerfile to JSON + run: | + # Use dockerfile-json or hadolint --format json + docker run --rm -i hadolint/hadolint hadolint --format json - < Dockerfile > dockerfile.json || true + + - name: Run compliance checks + run: | + conftest test dockerfile.json \ + --policy policies/compliance/ \ + --data policies/data/ \ + --output github \ + --all-namespaces + + - name: Generate compliance report + if: always() + run: | + echo "## Compliance Check Results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "### Frameworks Checked" >> $GITHUB_STEP_SUMMARY + echo "- CIS Docker Benchmark v1.5.0" >> $GITHUB_STEP_SUMMARY + echo "- PCI-DSS v4.0 (container requirements)" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "See [Policy-as-Code Strategy](docs/strategies/policy-as-code.md) for details." >> $GITHUB_STEP_SUMMARY +``` + +### 3.3.1 Compliance Policy Tests + +**File**: `policies/tests/compliance_test.rego` + +```rego +package mcp.compliance_test + +import data.mcp.compliance.cis.docker as cis +import data.mcp.compliance.pci_dss as pci + +# CIS Docker tests +test_cis_deny_root_user if { + result := cis.deny with input as {"User": "root"} + count(result) == 1 +} + +test_cis_deny_empty_user if { + result := cis.deny with input as {"User": ""} + count(result) == 1 +} + +test_cis_allow_nonroot_user if { + result := cis.deny with input as {"User": "1000:1000"} + count(result) == 0 +} + +test_cis_deny_privileged if { + result := cis.deny with input as {"Privileged": true} + count(result) == 1 +} + +test_cis_warn_no_healthcheck if { + result := cis.warn with input as {"User": "app"} + some msg in result + contains(msg, "HEALTHCHECK") +} + +# PCI-DSS tests +test_pci_deny_privileged if { + result := pci.deny with input as {"Privileged": true} + count(result) == 1 +} + +test_pci_warn_password_env if { + result := pci.warn with input as { + "Env": ["APP_NAME=test", "PASSWORD=secret123"] + } + count(result) >= 1 +} +``` + +### 3.4 Compliance Documentation + +Generate evidence reports: +- Scan timestamps +- Tool versions +- Pass/fail status +- Remediation notes + +--- + +## 4. Review & Validation + +- [ ] CIS benchmarks run on schedule +- [ ] OPA policies enforce standards +- [ ] Evidence documentation generated +- [ ] No false positives +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-22a-policy-library.md b/.ai/plans/phases/bundle-contents-phase-22a-policy-library.md new file mode 100644 index 0000000..e9fef4d --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-22a-policy-library.md @@ -0,0 +1,807 @@ +--- +id: e9f0a1b2-c3d4-5e6f-7a8b-9c0d1e2f3a4b +title: "Phase 22a: Policy Library" +status: pending +depends_on: + - 56738219-8f07-4634-9592-5a461b36ee18 # phase-14 (cargo-deny as reference) +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 22a: Policy Library + +## 1. Current State Assessment + +- [ ] Review existing inline policies in Phase 21, 22 +- [ ] Identify all policy domains needed +- [ ] Check for OPA/Conftest installation patterns +- [ ] Review policy-as-code.md strategy document + +### Existing Assets + +- Inline Rego policies in Phase 21 (container runtime validation) +- Inline Rego policies in Phase 22 (compliance) +- cargo-deny TOML policies (Phase 14) +- License YAML policies (Phase 15) + +### Gaps Identified + +- [ ] Unified policy directory structure +- [ ] Policy testing workflow +- [ ] Policy formatting/linting +- [ ] Policy bundle building +- [ ] Policy versioning +- [ ] Shared policy library functions +- [ ] External data management +- [ ] Policy documentation generation + +--- + +## 2. Contextual Goal + +Establish a centralized, tested, and versioned OPA policy library that serves as the foundation for all policy-as-code enforcement across the bundle. This phase creates the CI/CD infrastructure for policy development and provides reusable policies for Phases 21, 22, and beyond. + +> **Reference**: See [Policy-as-Code Strategy](../../docs/strategies/policy-as-code.md) for architectural decisions and patterns. + +### Success Criteria + +- [ ] Policy directory structure created per strategy +- [ ] `opa fmt` enforced in CI +- [ ] `opa check` validates syntax +- [ ] `opa test` runs with >90% coverage +- [ ] Policy bundle built and versioned +- [ ] Conftest integration documented +- [ ] Shared library functions available +- [ ] External data loading works + +### Out of Scope + +- Domain-specific policies (handled by Phases 21, 22, 15) +- Native tool policies (cargo-deny, eslint) +- Policy enforcement in other workflows (they reference this) + +--- + +## 3. Implementation + +### 3.1 Policy Directory Structure + +Create the unified policy structure in the bundle: + +``` +bundles/ +├── policies/ +│ ├── container/ +│ │ └── .gitkeep +│ ├── kubernetes/ +│ │ └── .gitkeep +│ ├── compliance/ +│ │ ├── cis/ +│ │ │ └── .gitkeep +│ │ └── .gitkeep +│ ├── license/ +│ │ └── .gitkeep +│ ├── workflow/ +│ │ └── .gitkeep +│ ├── lib/ +│ │ ├── utils.rego +│ │ └── semver.rego +│ ├── data/ +│ │ ├── allowed_licenses.json +│ │ ├── denied_licenses.json +│ │ ├── allowed_base_images.json +│ │ └── dangerous_capabilities.json +│ ├── tests/ +│ │ ├── lib_test.rego +│ │ └── testdata/ +│ │ └── .gitkeep +│ ├── .manifest +│ └── README.md +``` + +### 3.2 Shared Library Functions + +**File**: `policies/lib/utils.rego` + +```rego +# METADATA +# title: MCP Policy Utilities +# description: Shared utility functions for MCP policies +# entrypoint: false +# scope: package + +package mcp.lib.utils + +import future.keywords.if +import future.keywords.in + +# Check if value exists in array +array_contains(arr, val) if { + val in arr +} + +# Get value with default +get_default(obj, key, default_value) := obj[key] if { + obj[key] +} else := default_value + +# Check if string starts with prefix +has_prefix(str, prefix) if { + startswith(str, prefix) +} + +# Check if string ends with suffix +has_suffix(str, suffix) if { + endswith(str, suffix) +} + +# Check if any element in array matches predicate +any_match(arr, predicate) if { + some elem in arr + predicate(elem) +} + +# Normalize image name (remove tag) +normalize_image(image) := name if { + contains(image, ":") + name := split(image, ":")[0] +} else := image + +# Check if image is in allowed list (prefix match) +image_allowed(image, allowed_list) if { + normalized := normalize_image(image) + some allowed in allowed_list + has_prefix(normalized, allowed) +} +``` + +**File**: `policies/lib/semver.rego` + +```rego +# METADATA +# title: Semantic Version Utilities +# description: Parse and compare semantic versions +# entrypoint: false +# scope: package + +package mcp.lib.semver + +import future.keywords.if + +# Parse semver string to object +# Input: "1.2.3" or "v1.2.3" +# Output: {"major": 1, "minor": 2, "patch": 3} +parse(version) := result if { + clean := trim_prefix(version, "v") + parts := split(clean, ".") + count(parts) >= 3 + result := { + "major": to_number(parts[0]), + "minor": to_number(parts[1]), + "patch": to_number(split(parts[2], "-")[0]), + } +} + +# Compare two versions +# Returns: -1 (a < b), 0 (a == b), 1 (a > b) +compare(a, b) := -1 if { + pa := parse(a) + pb := parse(b) + pa.major < pb.major +} + +compare(a, b) := 1 if { + pa := parse(a) + pb := parse(b) + pa.major > pb.major +} + +compare(a, b) := -1 if { + pa := parse(a) + pb := parse(b) + pa.major == pb.major + pa.minor < pb.minor +} + +compare(a, b) := 1 if { + pa := parse(a) + pb := parse(b) + pa.major == pb.major + pa.minor > pb.minor +} + +compare(a, b) := -1 if { + pa := parse(a) + pb := parse(b) + pa.major == pb.major + pa.minor == pb.minor + pa.patch < pb.patch +} + +compare(a, b) := 1 if { + pa := parse(a) + pb := parse(b) + pa.major == pb.major + pa.minor == pb.minor + pa.patch > pb.patch +} + +compare(a, b) := 0 if { + pa := parse(a) + pb := parse(b) + pa.major == pb.major + pa.minor == pb.minor + pa.patch == pb.patch +} + +# Check if version meets minimum +meets_minimum(version, minimum) if { + compare(version, minimum) >= 0 +} +``` + +### 3.3 Library Tests + +**File**: `policies/tests/lib_test.rego` + +```rego +package mcp.lib.utils_test + +import data.mcp.lib.utils +import data.mcp.lib.semver + +# Test array_contains +test_array_contains_found if { + utils.array_contains(["a", "b", "c"], "b") +} + +test_array_contains_not_found if { + not utils.array_contains(["a", "b", "c"], "d") +} + +# Test get_default +test_get_default_exists if { + result := utils.get_default({"key": "value"}, "key", "default") + result == "value" +} + +test_get_default_missing if { + result := utils.get_default({"key": "value"}, "other", "default") + result == "default" +} + +# Test normalize_image +test_normalize_image_with_tag if { + result := utils.normalize_image("nginx:1.25") + result == "nginx" +} + +test_normalize_image_without_tag if { + result := utils.normalize_image("nginx") + result == "nginx" +} + +# Test image_allowed +test_image_allowed_exact if { + utils.image_allowed("alpine:3.18", ["alpine", "nginx"]) +} + +test_image_allowed_prefix if { + utils.image_allowed("gcr.io/distroless/static:latest", ["gcr.io/distroless/"]) +} + +test_image_not_allowed if { + not utils.image_allowed("ubuntu:22.04", ["alpine", "nginx"]) +} + +# Test semver parse +test_semver_parse if { + result := semver.parse("1.2.3") + result.major == 1 + result.minor == 2 + result.patch == 3 +} + +test_semver_parse_with_v if { + result := semver.parse("v1.2.3") + result.major == 1 +} + +# Test semver compare +test_semver_compare_less if { + semver.compare("1.0.0", "2.0.0") == -1 +} + +test_semver_compare_greater if { + semver.compare("2.0.0", "1.0.0") == 1 +} + +test_semver_compare_equal if { + semver.compare("1.2.3", "1.2.3") == 0 +} + +test_semver_meets_minimum if { + semver.meets_minimum("1.5.0", "1.0.0") +} + +test_semver_below_minimum if { + not semver.meets_minimum("0.9.0", "1.0.0") +} +``` + +### 3.4 External Data Files + +**File**: `policies/data/allowed_licenses.json` + +```json +{ + "mcp": { + "allowed_licenses": [ + "MIT", + "Apache-2.0", + "BSD-2-Clause", + "BSD-3-Clause", + "ISC", + "MPL-2.0", + "Zlib", + "Unlicense", + "CC0-1.0", + "0BSD" + ] + } +} +``` + +**File**: `policies/data/denied_licenses.json` + +```json +{ + "mcp": { + "denied_licenses": [ + "GPL-3.0-only", + "GPL-3.0-or-later", + "AGPL-3.0-only", + "AGPL-3.0-or-later", + "SSPL-1.0", + "BSL-1.1", + "Elastic-2.0" + ], + "require_review": [ + "GPL-2.0-only", + "GPL-2.0-or-later", + "LGPL-2.1-only", + "LGPL-3.0-only", + "EPL-2.0", + "CDDL-1.0" + ] + } +} +``` + +**File**: `policies/data/allowed_base_images.json` + +```json +{ + "mcp": { + "allowed_base_images": [ + "scratch", + "gcr.io/distroless/static", + "gcr.io/distroless/base", + "gcr.io/distroless/cc", + "cgr.dev/chainguard/static", + "cgr.dev/chainguard/busybox", + "alpine", + "docker.io/library/alpine" + ] + } +} +``` + +**File**: `policies/data/dangerous_capabilities.json` + +```json +{ + "mcp": { + "dangerous_capabilities": [ + "ALL", + "SYS_ADMIN", + "NET_ADMIN", + "SYS_PTRACE", + "SYS_RAWIO", + "SYS_MODULE", + "DAC_READ_SEARCH", + "NET_RAW" + ], + "warn_capabilities": [ + "SYS_CHROOT", + "SETUID", + "SETGID", + "MKNOD" + ] + } +} +``` + +### 3.5 Bundle Manifest + +**File**: `policies/.manifest` + +```json +{ + "revision": "0.1.0", + "roots": ["mcp"], + "metadata": { + "bundle_type": "mcp-policies", + "created_by": "mcp-bundle", + "min_opa_version": "0.60.0" + } +} +``` + +### 3.6 Policy Library CI Workflow + +**File**: `.github/workflows/policy-library.yml` + +```yaml +name: Policy Library CI + +on: + push: + branches: [main] + paths: + - 'policies/**' + - '.github/workflows/policy-library.yml' + pull_request: + paths: + - 'policies/**' + - '.github/workflows/policy-library.yml' + workflow_dispatch: + inputs: + release: + description: 'Create release bundle' + required: false + type: boolean + default: false + +permissions: + contents: write + +env: + OPA_VERSION: '0.60.0' + CONFTEST_VERSION: '0.45.0' + +jobs: + validate: + name: Validate Policies + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Setup OPA + uses: open-policy-agent/setup-opa@v2 + with: + version: ${{ env.OPA_VERSION }} + + - name: Check formatting + run: | + echo "## Policy Format Check" >> $GITHUB_STEP_SUMMARY + if ! opa fmt --diff --fail policies/; then + echo "::error::Policy files are not formatted. Run 'opa fmt -w policies/' to fix." + echo "❌ Format check failed" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + echo "✅ All policies properly formatted" >> $GITHUB_STEP_SUMMARY + + - name: Check syntax + run: | + echo "## Policy Syntax Check" >> $GITHUB_STEP_SUMMARY + if ! opa check policies/; then + echo "::error::Policy syntax errors found" + echo "❌ Syntax check failed" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + echo "✅ All policies have valid syntax" >> $GITHUB_STEP_SUMMARY + + - name: Validate bundle structure + run: | + echo "## Bundle Structure" >> $GITHUB_STEP_SUMMARY + echo "Checking required directories and files..." + + required_dirs=("policies/lib" "policies/data" "policies/tests") + for dir in "${required_dirs[@]}"; do + if [[ -d "$dir" ]]; then + echo "✅ $dir exists" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Missing required directory: $dir" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + done + + if [[ -f "policies/.manifest" ]]; then + echo "✅ .manifest exists" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Missing .manifest file" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + test: + name: Test Policies + runs-on: ubuntu-latest + needs: validate + steps: + - uses: actions/checkout@v4 + + - name: Setup OPA + uses: open-policy-agent/setup-opa@v2 + with: + version: ${{ env.OPA_VERSION }} + + - name: Run policy tests + run: | + echo "## Policy Tests" >> $GITHUB_STEP_SUMMARY + opa test policies/ -v --format=pretty 2>&1 | tee test-output.txt + + # Count results + passed=$(grep -c "PASS" test-output.txt || echo "0") + failed=$(grep -c "FAIL" test-output.txt || echo "0") + + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Result | Count |" >> $GITHUB_STEP_SUMMARY + echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Passed | $passed |" >> $GITHUB_STEP_SUMMARY + echo "| Failed | $failed |" >> $GITHUB_STEP_SUMMARY + + if [[ "$failed" -gt 0 ]]; then + echo "::error::$failed policy tests failed" + exit 1 + fi + + - name: Check test coverage + run: | + echo "## Test Coverage" >> $GITHUB_STEP_SUMMARY + opa test policies/ --coverage --format=json > coverage.json + + # Extract coverage percentage + coverage=$(jq '.coverage' coverage.json) + echo "Coverage: ${coverage}%" >> $GITHUB_STEP_SUMMARY + + # Fail if below threshold + threshold=80 + if (( $(echo "$coverage < $threshold" | bc -l) )); then + echo "::warning::Test coverage ($coverage%) is below threshold ($threshold%)" + fi + + - name: Upload coverage + uses: actions/upload-artifact@v4 + with: + name: policy-coverage + path: coverage.json + + integration: + name: Integration Test + runs-on: ubuntu-latest + needs: test + steps: + - uses: actions/checkout@v4 + + - name: Setup Conftest + run: | + curl -L https://github.com/open-policy-agent/conftest/releases/download/v${{ env.CONFTEST_VERSION }}/conftest_${{ env.CONFTEST_VERSION }}_Linux_x86_64.tar.gz | tar xz + sudo mv conftest /usr/local/bin/ + + - name: Test with sample files + run: | + echo "## Integration Tests" >> $GITHUB_STEP_SUMMARY + + # Create test compose file + cat > test-compose.yml << 'EOF' + version: "3.8" + services: + web: + image: nginx:alpine + user: "1000:1000" + EOF + + # Run conftest with policies + echo "Testing valid compose file..." >> $GITHUB_STEP_SUMMARY + if conftest test test-compose.yml --policy policies/ --data policies/data/ 2>&1; then + echo "✅ Valid compose passed" >> $GITHUB_STEP_SUMMARY + else + echo "❌ Valid compose should pass" >> $GITHUB_STEP_SUMMARY + exit 1 + fi + + - name: Test policy violations + run: | + # Create invalid compose file + cat > invalid-compose.yml << 'EOF' + version: "3.8" + services: + web: + image: nginx:alpine + privileged: true + user: root + EOF + + # Should fail with violations + echo "Testing invalid compose file..." >> $GITHUB_STEP_SUMMARY + if conftest test invalid-compose.yml --policy policies/container/ --data policies/data/ 2>&1; then + echo "⚠️ Invalid compose should have violations (no container policies yet)" >> $GITHUB_STEP_SUMMARY + else + echo "✅ Invalid compose correctly rejected" >> $GITHUB_STEP_SUMMARY + fi + + build: + name: Build Bundle + runs-on: ubuntu-latest + needs: [test, integration] + if: github.ref == 'refs/heads/main' || github.event.inputs.release == 'true' + steps: + - uses: actions/checkout@v4 + + - name: Setup OPA + uses: open-policy-agent/setup-opa@v2 + with: + version: ${{ env.OPA_VERSION }} + + - name: Extract version + id: version + run: | + version=$(jq -r '.revision' policies/.manifest) + echo "version=$version" >> $GITHUB_OUTPUT + echo "Policy bundle version: $version" + + - name: Build policy bundle + run: | + mkdir -p dist + opa build \ + --bundle policies/ \ + --output dist/mcp-policies-v${{ steps.version.outputs.version }}.tar.gz \ + --revision "${{ steps.version.outputs.version }}" + + # Also create latest symlink + cp dist/mcp-policies-v${{ steps.version.outputs.version }}.tar.gz dist/mcp-policies-latest.tar.gz + + - name: Inspect bundle + run: | + echo "## Bundle Info" >> $GITHUB_STEP_SUMMARY + opa inspect dist/mcp-policies-v${{ steps.version.outputs.version }}.tar.gz >> $GITHUB_STEP_SUMMARY + + - name: Upload bundle artifact + uses: actions/upload-artifact@v4 + with: + name: policy-bundle + path: dist/ + + - name: Create release + if: github.event.inputs.release == 'true' + uses: softprops/action-gh-release@v1 + with: + tag_name: policies-v${{ steps.version.outputs.version }} + name: Policy Bundle v${{ steps.version.outputs.version }} + files: | + dist/mcp-policies-v${{ steps.version.outputs.version }}.tar.gz + body: | + ## MCP Policy Bundle v${{ steps.version.outputs.version }} + + ### Installation + + ```bash + # Download + curl -L -o policies.tar.gz \ + https://github.com/${{ github.repository }}/releases/download/policies-v${{ steps.version.outputs.version }}/mcp-policies-v${{ steps.version.outputs.version }}.tar.gz + + # Extract + tar -xzf policies.tar.gz -C policies/ + + # Use with Conftest + conftest test docker-compose.yml --policy policies/ + ``` + + ### Included Policies + + See [policy-as-code.md](docs/strategies/policy-as-code.md) for documentation. +``` + +### 3.7 Policy README + +**File**: `policies/README.md` + +```markdown +# MCP Policy Library + +Centralized OPA/Rego policy library for the MCP bundle. + +## Quick Start + +```bash +# Validate policies +opa check policies/ + +# Format policies +opa fmt -w policies/ + +# Run tests +opa test policies/ -v + +# Use with Conftest +conftest test docker-compose.yml --policy policies/ --data policies/data/ +``` + +## Structure + +| Directory | Purpose | +|-----------|---------| +| `container/` | Docker/Compose security policies | +| `kubernetes/` | K8s manifest policies | +| `compliance/` | CIS, PCI-DSS, HIPAA | +| `license/` | License compliance | +| `workflow/` | GitHub Actions policies | +| `lib/` | Shared utility functions | +| `data/` | External data (allowlists, etc.) | +| `tests/` | Policy unit tests | + +## Writing Policies + +See [Policy-as-Code Strategy](../docs/strategies/policy-as-code.md) for: +- Package naming conventions +- Metadata requirements +- Testing patterns +- Data-driven policies + +## Bundle Version + +Current version: See `.manifest` + +## Related + +- Phase 21: Container Security (uses container policies) +- Phase 22: Compliance (uses compliance policies) +- Phase 15: License (uses license policies) +``` + +--- + +## 4. Review & Validation + +- [ ] Policy directory structure matches strategy document +- [ ] Shared library functions implemented and tested +- [ ] External data files created with correct structure +- [ ] CI workflow validates format, syntax, tests +- [ ] Bundle builds successfully +- [ ] Conftest integration works +- [ ] >80% test coverage achieved +- [ ] README documentation complete +- [ ] policy-as-code.md strategy updated if needed +- [ ] Implementation tracking checklist updated + +--- + +## 5. Phase Dependencies + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 22a DEPENDENCY GRAPH │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Phase 22a: Policy Library │ +│ │ │ +│ ┌───────────────┼───────────────┐ │ +│ │ │ │ │ +│ ▼ ▼ ▼ │ +│ Phase 21 Phase 22 Phase 15 │ +│ Containers Compliance Licenses │ +│ (uses container (uses CIS, (uses license │ +│ policies) PCI policies) policies) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +This phase provides: +- Shared library functions (`mcp.lib.*`) +- External data files (`policies/data/`) +- CI/CD infrastructure for policy validation +- Bundle building and versioning + +Consuming phases add domain-specific policies to the appropriate directories. diff --git a/.ai/plans/phases/bundle-contents-phase-23-security-attestation.md b/.ai/plans/phases/bundle-contents-phase-23-security-attestation.md new file mode 100644 index 0000000..a0fd3bf --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-23-security-attestation.md @@ -0,0 +1,406 @@ +--- +id: dfeca409-20f3-46f0-94d3-c8e1c8f6fb19 +title: "Phase 23: Security - Attestation" +status: pending +depends_on: + - b357c053-9d64-4efa-a06f-34bdd138271e # phase-22 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 23: Security - Attestation + +## 1. Current State Assessment + +- [ ] Check for existing SBOM generation +- [ ] Review signing infrastructure +- [ ] Identify SLSA level requirements +- [ ] Check for cosign usage + +### Existing Assets + +Container builds (Phase 02) include SBOM and provenance flags. + +### Gaps Identified + +- [ ] attestation-sbom.yml (Syft) +- [ ] attestation-slsa.yml (SLSA provenance) +- [ ] attestation-sign.yml (cosign sign) +- [ ] attestation-verify.yml (cosign verify) +- [ ] SBOM output formats (SPDX, CycloneDX) + +--- + +## 2. Contextual Goal + +Implement software supply chain security through attestations. Generate SBOMs with Syft in SPDX and CycloneDX formats, create SLSA provenance attestations, and sign artifacts with cosign using keyless signing. Integrate with GitHub native attestations for container images. + +### Success Criteria + +- [ ] SBOMs generated for all artifacts +- [ ] SLSA provenance at Level 2+ +- [ ] Artifacts signed with cosign +- [ ] Attestations verifiable +- [ ] GitHub attestations utilized + +### Out of Scope + +- SLSA Level 3+ (requires isolated builds) +- Key management infrastructure + +--- + +## 3. Implementation + +### 3.1 attestation-sbom.yml + +```yaml +name: Generate SBOM + +on: + release: + types: [published] + workflow_dispatch: + +jobs: + sbom: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install Syft + uses: anchore/sbom-action/download-syft@v0 + + - name: Generate SPDX SBOM + run: syft . -o spdx-json=sbom-spdx.json + + - name: Generate CycloneDX SBOM + run: syft . -o cyclonedx-json=sbom-cyclonedx.json + + - name: Upload SBOMs + uses: actions/upload-artifact@v4 + with: + name: sbom + path: sbom-*.json + + - name: Attach to release + if: github.event_name == 'release' + uses: softprops/action-gh-release@v1 + with: + files: | + sbom-spdx.json + sbom-cyclonedx.json +``` + +### 3.2 attestation-slsa.yml + +```yaml +name: SLSA Provenance + +on: + release: + types: [published] + +jobs: + provenance: + permissions: + actions: read + id-token: write + contents: write + attestations: write + + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0 + with: + base64-subjects: "${{ needs.build.outputs.digests }}" + upload-assets: true +``` + +### 3.3 attestation-sign.yml + +```yaml +name: Sign Artifacts + +on: + release: + types: [published] + +jobs: + sign: + runs-on: ubuntu-latest + permissions: + id-token: write + packages: write + attestations: write + + steps: + - uses: actions/checkout@v4 + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Sign container + run: | + cosign sign --yes ghcr.io/${{ github.repository }}:${{ github.ref_name }} + + - name: Attest SBOM + run: | + cosign attest --yes --predicate sbom-spdx.json \ + --type spdxjson ghcr.io/${{ github.repository }}:${{ github.ref_name }} +``` + +### 3.4 attestation-verify.yml + +```yaml +name: Verify Artifacts + +on: + # Run on deployment to verify before release + workflow_call: + inputs: + image: + description: 'Image to verify (e.g., ghcr.io/owner/repo:tag)' + required: true + type: string + require-sbom: + description: 'Require SBOM attestation' + required: false + type: boolean + default: true + require-provenance: + description: 'Require SLSA provenance' + required: false + type: boolean + default: true + + # Manual verification + workflow_dispatch: + inputs: + image: + description: 'Image to verify (e.g., ghcr.io/owner/repo:tag)' + required: true + type: string + + # Verify on pull (consumption verification) + pull_request: + paths: + - 'docker-compose*.yml' + - 'compose*.yml' + - '**/deployment*.yml' + +jobs: + verify-signature: + name: Verify Image Signature + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Install cosign + uses: sigstore/cosign-installer@v3 + + - name: Determine image to verify + id: image + run: | + if [ -n "${{ inputs.image }}" ]; then + echo "ref=${{ inputs.image }}" >> $GITHUB_OUTPUT + else + # Extract from compose file or use default + echo "ref=ghcr.io/${{ github.repository }}:latest" >> $GITHUB_OUTPUT + fi + + - name: Verify signature (keyless) + run: | + echo "Verifying signature for: ${{ steps.image.outputs.ref }}" + + # Keyless verification using Sigstore + # This verifies the image was signed by a trusted identity + cosign verify \ + --certificate-identity-regexp="https://github.com/${{ github.repository_owner }}/.*" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ + ${{ steps.image.outputs.ref }} + + echo "::notice::Signature verification passed" + + - name: Verify SBOM attestation + if: inputs.require-sbom != false + run: | + echo "Verifying SBOM attestation for: ${{ steps.image.outputs.ref }}" + + # Verify SBOM attestation exists and is valid + cosign verify-attestation \ + --type spdxjson \ + --certificate-identity-regexp="https://github.com/${{ github.repository_owner }}/.*" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ + ${{ steps.image.outputs.ref }} + + echo "::notice::SBOM attestation verification passed" + + - name: Verify SLSA provenance + if: inputs.require-provenance != false + run: | + echo "Verifying SLSA provenance for: ${{ steps.image.outputs.ref }}" + + # Verify SLSA provenance attestation + cosign verify-attestation \ + --type slsaprovenance \ + --certificate-identity-regexp="https://github.com/${{ github.repository_owner }}/.*" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ + ${{ steps.image.outputs.ref }} || { + # Try GitHub native attestation format + echo "Trying GitHub attestation format..." + cosign verify-attestation \ + --type https://slsa.dev/provenance/v1 \ + --certificate-identity-regexp="https://github.com/${{ github.repository_owner }}/.*" \ + --certificate-oidc-issuer="https://token.actions.githubusercontent.com" \ + ${{ steps.image.outputs.ref }} + } + + echo "::notice::SLSA provenance verification passed" + + - name: Extract and display SBOM + if: always() + run: | + echo "## SBOM Contents" >> $GITHUB_STEP_SUMMARY + + # Download and display SBOM + cosign download attestation \ + --predicate-type spdxjson \ + ${{ steps.image.outputs.ref }} 2>/dev/null | \ + jq -r '.payload' | base64 -d | jq '.predicate' > sbom.json || true + + if [ -f sbom.json ]; then + echo '```json' >> $GITHUB_STEP_SUMMARY + jq '.packages | length' sbom.json | xargs -I {} echo "Package count: {}" >> $GITHUB_STEP_SUMMARY + echo '```' >> $GITHUB_STEP_SUMMARY + fi + + verify-github-attestations: + name: Verify GitHub Native Attestations + runs-on: ubuntu-latest + steps: + - name: Install GitHub CLI attestation extension + run: gh extension install github/gh-attestation || true + + - name: Determine image to verify + id: image + run: | + if [ -n "${{ inputs.image }}" ]; then + echo "ref=${{ inputs.image }}" >> $GITHUB_OUTPUT + else + echo "ref=ghcr.io/${{ github.repository }}:latest" >> $GITHUB_OUTPUT + fi + + - name: Verify with GitHub attestations + env: + GH_TOKEN: ${{ github.token }} + run: | + echo "Verifying GitHub attestations for: ${{ steps.image.outputs.ref }}" + + # Use GitHub's native attestation verification + gh attestation verify \ + oci://${{ steps.image.outputs.ref }} \ + --owner ${{ github.repository_owner }} || { + echo "::warning::GitHub attestation verification failed or not found" + exit 0 # Don't fail - may not have GitHub attestations + } + + echo "::notice::GitHub attestation verification passed" + + verify-summary: + name: Verification Summary + needs: [verify-signature, verify-github-attestations] + runs-on: ubuntu-latest + if: always() + steps: + - name: Generate summary + run: | + echo "## Verification Summary" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY + echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY + + if [ "${{ needs.verify-signature.result }}" == "success" ]; then + echo "| Cosign Signature | ✅ Passed |" >> $GITHUB_STEP_SUMMARY + else + echo "| Cosign Signature | ❌ Failed |" >> $GITHUB_STEP_SUMMARY + fi + + if [ "${{ needs.verify-github-attestations.result }}" == "success" ]; then + echo "| GitHub Attestations | ✅ Passed |" >> $GITHUB_STEP_SUMMARY + else + echo "| GitHub Attestations | ⚠️ Not found or failed |" >> $GITHUB_STEP_SUMMARY + fi +``` + +### 3.5 GitHub Native Attestations + +```yaml +# In container build workflow +- name: Attest + uses: actions/attest-build-provenance@v1 + with: + subject-name: ghcr.io/${{ github.repository }} + subject-digest: ${{ steps.build.outputs.digest }} + push-to-registry: true +``` + +### 3.6 Verification in Deployment Pipeline + +Example of integrating verification into deployment: + +```yaml +# deploy.yml +name: Deploy + +on: + workflow_dispatch: + inputs: + environment: + description: 'Target environment' + required: true + type: choice + options: + - staging + - production + +jobs: + verify: + name: Verify Artifacts + uses: ./.github/workflows/attestation-verify.yml + with: + image: ghcr.io/${{ github.repository }}:${{ github.sha }} + require-sbom: true + require-provenance: true + + deploy: + name: Deploy to ${{ inputs.environment }} + needs: verify + runs-on: ubuntu-latest + environment: ${{ inputs.environment }} + steps: + - name: Deploy verified image + run: | + echo "Deploying verified image to ${{ inputs.environment }}" + # Deployment steps here... +``` + +--- + +## 4. Review & Validation + +- [ ] SBOMs contain all dependencies +- [ ] SLSA provenance verifiable +- [ ] Signatures verify with `cosign verify` +- [ ] SBOM attestations verify with `cosign verify-attestation` +- [ ] Provenance attestations verify with `cosign verify-attestation` +- [ ] GitHub attestations visible in repository +- [ ] GitHub attestations verify with `gh attestation verify` +- [ ] Verification workflow integrates into deployment pipeline +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-24-release-versioning.md b/.ai/plans/phases/bundle-contents-phase-24-release-versioning.md new file mode 100644 index 0000000..7b8a2d7 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-24-release-versioning.md @@ -0,0 +1,478 @@ +--- +id: 0b4c7d81-ee56-43dd-b14d-9af8a7a8759c +title: "Phase 24: Release - Versioning" +status: pending +depends_on: + - dfeca409-20f3-46f0-94d3-c8e1c8f6fb19 # phase-23 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 24: Release - Versioning + +## 1. Current State Assessment + +- [ ] Check for existing versioning strategy +- [ ] Review semantic-release configuration +- [ ] Identify changelog generation +- [ ] Check for release drafter usage + +### Existing Assets + +Conventional commits (Phase 01) enable automated versioning. + +### Gaps Identified + +- [ ] semantic-release.yml workflow +- [ ] .releaserc.json configuration +- [ ] scripts/update-versions.sh (manifest updater) +- [ ] release-drafter.yml workflow (PR categorization only) +- [ ] .github/release-drafter.yml config (version resolution disabled) +- [ ] version-check.yml (drift detection) + +--- + +## 2. Contextual Goal + +Implement automated semantic versioning based on conventional commits. Use semantic-release to determine version bumps, generate changelogs, create GitHub releases, tag releases, **and update all package manifest files**. The git tag is the single source of truth for versioning. + +### Version Source of Truth + +> **IMPORTANT**: The git tag created by semantic-release is the single source of truth. +> +> All package manifests (Cargo.toml, package.json, pyproject.toml, Chart.yaml) +> are updated by semantic-release to match the git tag version. +> +> ``` +> semantic-release determines version from commits +> │ +> ├── Creates Git Tag: v1.3.0 +> ├── Creates GitHub Release: v1.3.0 +> ├── Updates CHANGELOG.md +> └── Updates ALL package manifests: +> ├── Cargo.toml +> ├── package.json +> ├── pyproject.toml +> └── charts/*/Chart.yaml (appVersion) +> ``` +> +> **Do not manually edit version numbers in manifest files.** + +### Success Criteria + +- [ ] Automatic version bumping from commits +- [ ] Changelog generated from commit messages +- [ ] GitHub releases created automatically +- [ ] **All package manifests updated to match git tag** +- [ ] **Version consistency validated in CI** +- [ ] Breaking changes trigger major bumps +- [ ] Prerelease branches supported (optional) + +### Out of Scope + +- Package publishing (Phase 26) +- Container tagging (Phase 25) + +--- + +## 3. Implementation + +### 3.1 semantic-release.yml + +```yaml +name: Semantic Release + +on: + push: + branches: [main] + workflow_dispatch: + +permissions: + contents: write + issues: write + pull-requests: write + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + persist-credentials: false + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Install semantic-release + run: npm install -g semantic-release @semantic-release/changelog @semantic-release/git + + - name: Run semantic-release + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: npx semantic-release +``` + +### 3.2 .releaserc.json + +```json +{ + "branches": [ + "main", + { "name": "beta", "prerelease": true }, + { "name": "alpha", "prerelease": true } + ], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + [ + "@semantic-release/changelog", + { + "changelogFile": "CHANGELOG.md" + } + ], + [ + "@semantic-release/exec", + { + "prepareCmd": "scripts/update-versions.sh ${nextRelease.version}" + } + ], + [ + "@semantic-release/git", + { + "assets": [ + "CHANGELOG.md", + "Cargo.toml", + "Cargo.lock", + "package.json", + "package-lock.json", + "pyproject.toml", + "charts/*/Chart.yaml" + ], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + } + ], + "@semantic-release/github" + ] +} +``` + +### 3.3 scripts/update-versions.sh + +Version update script called by semantic-release: + +```bash +#!/usr/bin/env bash +# scripts/update-versions.sh +# Updates all package manifests to the specified version +set -euo pipefail + +VERSION="${1:-}" +if [ -z "$VERSION" ]; then + echo "Usage: $0 " + exit 1 +fi + +echo "Updating versions to: $VERSION" + +# Rust: Cargo.toml +if [ -f "Cargo.toml" ]; then + echo " → Cargo.toml" + sed -i.bak "s/^version = \".*\"/version = \"$VERSION\"/" Cargo.toml + rm -f Cargo.toml.bak + # Update Cargo.lock if it exists + if [ -f "Cargo.lock" ]; then + cargo update --workspace 2>/dev/null || true + fi +fi + +# Node: package.json +if [ -f "package.json" ]; then + echo " → package.json" + # Use npm version to properly update package.json and package-lock.json + npm version "$VERSION" --no-git-tag-version --allow-same-version 2>/dev/null || \ + sed -i.bak "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" package.json + rm -f package.json.bak +fi + +# Python: pyproject.toml +if [ -f "pyproject.toml" ]; then + echo " → pyproject.toml" + sed -i.bak "s/^version = \".*\"/version = \"$VERSION\"/" pyproject.toml + rm -f pyproject.toml.bak +fi + +# Helm: Chart.yaml (update appVersion, not version) +# Chart version can be managed independently or synced +for chart in charts/*/Chart.yaml; do + if [ -f "$chart" ]; then + echo " → $chart (appVersion)" + sed -i.bak "s/^appVersion:.*/appVersion: \"$VERSION\"/" "$chart" + rm -f "${chart}.bak" + fi +done + +echo "Version update complete: $VERSION" +``` + +### 3.4 release-drafter.yml (Optional - PR Labeling Only) + +> **Note**: release-drafter is configured for **PR categorization only**, not version resolution. +> Version determination is handled exclusively by semantic-release from commit messages. +> +> **Why?** release-drafter resolves versions from PR labels, while semantic-release +> resolves from commit messages. Using both for versioning causes conflicts. + +```yaml +name: Release Drafter + +on: + pull_request: + types: [opened, reopened, synchronize, labeled, unlabeled] + +permissions: + contents: read + pull-requests: write + +jobs: + update_release_draft: + runs-on: ubuntu-latest + steps: + - uses: release-drafter/release-drafter@v5 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### 3.5 .github/release-drafter.yml + +```yaml +# NOTE: Version resolution DISABLED - semantic-release is the source of truth +# release-drafter is used only for PR categorization and draft notes + +name-template: 'v$RESOLVED_VERSION' +tag-template: 'v$RESOLVED_VERSION' + +categories: + - title: 'Breaking Changes' + labels: + - 'breaking' + - title: 'Features' + labels: + - 'type:feature' + - 'enhancement' + - title: 'Bug Fixes' + labels: + - 'type:bug' + - 'bugfix' + - title: 'Security' + labels: + - 'security' + - title: 'Documentation' + labels: + - 'type:docs' + - 'documentation' + - title: 'Maintenance' + labels: + - 'chore' + - 'dependencies' + +# VERSION RESOLUTION DISABLED +# semantic-release determines version from commit messages, not PR labels +# Uncommenting this would cause conflicts with semantic-release +# +# version-resolver: +# major: +# labels: +# - 'breaking' +# minor: +# labels: +# - 'type:feature' +# patch: +# labels: +# - 'type:bug' +# default: patch + +template: | + ## Changes + + $CHANGES + + ## Contributors + + $CONTRIBUTORS + + --- + *Note: Final version determined by semantic-release from commit messages.* +``` + +### 3.6 version-check.yml + +Validates version consistency across all package manifests: + +```yaml +name: Version Consistency Check + +on: + pull_request: + push: + branches: [main] + paths: + - 'Cargo.toml' + - 'package.json' + - 'pyproject.toml' + - 'charts/*/Chart.yaml' + +jobs: + check-versions: + name: Validate Version Consistency + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Extract versions from manifests + id: versions + run: | + # Extract version from each manifest (if exists) + CARGO_VER="N/A" + PKG_VER="N/A" + PY_VER="N/A" + CHART_APP_VER="N/A" + + if [ -f "Cargo.toml" ]; then + CARGO_VER=$(grep -m1 '^version' Cargo.toml | sed 's/.*"\(.*\)".*/\1/' || echo "N/A") + fi + + if [ -f "package.json" ]; then + PKG_VER=$(jq -r '.version // "N/A"' package.json 2>/dev/null || echo "N/A") + fi + + if [ -f "pyproject.toml" ]; then + PY_VER=$(grep -m1 '^version' pyproject.toml | sed 's/.*"\(.*\)".*/\1/' || echo "N/A") + fi + + # Get appVersion from first Chart.yaml found + CHART_FILE=$(find charts -name 'Chart.yaml' -type f 2>/dev/null | head -1) + if [ -n "$CHART_FILE" ]; then + CHART_APP_VER=$(grep -m1 '^appVersion:' "$CHART_FILE" | sed 's/.*: *"\{0,1\}\([^"]*\)"\{0,1\}/\1/' || echo "N/A") + fi + + echo "cargo=$CARGO_VER" >> $GITHUB_OUTPUT + echo "npm=$PKG_VER" >> $GITHUB_OUTPUT + echo "python=$PY_VER" >> $GITHUB_OUTPUT + echo "helm=$CHART_APP_VER" >> $GITHUB_OUTPUT + + - name: Generate version report + run: | + echo "## Version Consistency Report" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Manifest | Version |" >> $GITHUB_STEP_SUMMARY + echo "|----------|---------|" >> $GITHUB_STEP_SUMMARY + echo "| Cargo.toml | \`${{ steps.versions.outputs.cargo }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| package.json | \`${{ steps.versions.outputs.npm }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| pyproject.toml | \`${{ steps.versions.outputs.python }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Chart.yaml (appVersion) | \`${{ steps.versions.outputs.helm }}\` |" >> $GITHUB_STEP_SUMMARY + + - name: Check for version drift + run: | + # Collect all non-N/A versions + VERSIONS="" + for v in "${{ steps.versions.outputs.cargo }}" \ + "${{ steps.versions.outputs.npm }}" \ + "${{ steps.versions.outputs.python }}" \ + "${{ steps.versions.outputs.helm }}"; do + if [ "$v" != "N/A" ]; then + VERSIONS="$VERSIONS $v" + fi + done + + # Count unique versions + UNIQUE=$(echo $VERSIONS | tr ' ' '\n' | sort -u | grep -v '^$' | wc -l) + + if [ "$UNIQUE" -gt 1 ]; then + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ⚠️ Version Drift Detected" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "Multiple different versions found across manifests." >> $GITHUB_STEP_SUMMARY + echo "This may indicate:" >> $GITHUB_STEP_SUMMARY + echo "- Manual version edit (should use semantic-release)" >> $GITHUB_STEP_SUMMARY + echo "- Failed release process" >> $GITHUB_STEP_SUMMARY + echo "- Missing manifest update in scripts/update-versions.sh" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "::warning::Version mismatch detected: $(echo $VERSIONS | tr ' ' '\n' | sort -u | tr '\n' ' ')" + + # Fail on main branch, warn on PRs + if [ "${{ github.ref }}" == "refs/heads/main" ]; then + echo "::error::Version drift on main branch - this should not happen" + exit 1 + fi + else + echo "" >> $GITHUB_STEP_SUMMARY + echo "### ✅ Versions Consistent" >> $GITHUB_STEP_SUMMARY + if [ -n "$(echo $VERSIONS | xargs)" ]; then + echo "All manifests report version: \`$(echo $VERSIONS | awk '{print $1}')\`" >> $GITHUB_STEP_SUMMARY + fi + fi +``` + +--- + +## 4. Review & Validation + +- [ ] Version bumps correctly from commits +- [ ] Changelog includes all changes +- [ ] GitHub releases created +- [ ] **All package manifests updated by semantic-release** +- [ ] **scripts/update-versions.sh handles all manifest types** +- [ ] **version-check.yml detects drift correctly** +- [ ] Release notes are readable +- [ ] Prerelease branches work (beta, alpha) +- [ ] release-drafter categorizes PRs without version resolution +- [ ] Implementation tracking checklist updated + +--- + +## 5. Terminology Clarification + +| Term | Definition | Created By | +|------|------------|------------| +| **Version** | Semantic version number (1.2.3) | Determined by semantic-release | +| **Git Tag** | Immutable pointer to commit (`v1.2.3`) | semantic-release via `@semantic-release/github` | +| **GitHub Release** | GitHub feature wrapping git tag | semantic-release via `@semantic-release/github` | +| **Package Version** | Version in manifest file | `scripts/update-versions.sh` | +| **Container Tag** | Label on container image | `docker/metadata-action` (Phase 25) | +| **Chart Version** | Version in `Chart.yaml` | Independent (chart lifecycle) | +| **Chart appVersion** | App version in `Chart.yaml` | `scripts/update-versions.sh` | + +### Version Flow + +``` +Commit to main + │ + ▼ +semantic-release analyzes commits + │ + ├── Determines next version: 1.3.0 + │ + ├── Runs: scripts/update-versions.sh 1.3.0 + │ ├── Updates Cargo.toml + │ ├── Updates package.json + │ ├── Updates pyproject.toml + │ └── Updates Chart.yaml appVersion + │ + ├── Commits: "chore(release): 1.3.0 [skip ci]" + │ + ├── Creates git tag: v1.3.0 + │ + └── Creates GitHub Release: v1.3.0 + │ + ▼ + Triggers Phase 25/26/27 workflows + │ + ├── publish-container.yml → tags from git ref + ├── publish-rust.yml → reads Cargo.toml (now 1.3.0) + ├── publish-python.yml → reads pyproject.toml (now 1.3.0) + ├── publish-node.yml → reads package.json (now 1.3.0) + └── publish-helm-oci.yml → reads Chart.yaml +``` diff --git a/.ai/plans/phases/bundle-contents-phase-25-release-containers.md b/.ai/plans/phases/bundle-contents-phase-25-release-containers.md new file mode 100644 index 0000000..8976e7e --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-25-release-containers.md @@ -0,0 +1,161 @@ +--- +id: b0116cbd-58d7-4a2e-8720-9d3860ad9232 +title: "Phase 25: Release - Containers" +status: pending +depends_on: + - 0b4c7d81-ee56-43dd-b14d-9af8a7a8759c # phase-24 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 25: Release - Containers + +## 1. Current State Assessment + +- [ ] Check for existing container publishing +- [ ] Review registry configuration +- [ ] Identify tag strategies +- [ ] Check for multi-arch publishing + +### Existing Assets + +- Container build workflow (Phase 02) +- Container signing (Phase 23) + +### Gaps Identified + +- [ ] publish-container.yml (release publishing) +- [ ] Multi-registry support (GHCR + Docker Hub) +- [ ] Tag strategy configuration + +--- + +## 2. Contextual Goal + +Implement container publishing workflows that publish release images to GHCR and optionally Docker Hub. Tags should follow semantic versioning with additional tags for latest, major version, and SHA. Include attestations and SBOM from Phase 23. + +### Success Criteria + +- [ ] Publish to GHCR on release +- [ ] Optional Docker Hub publishing +- [ ] Semantic version tags applied +- [ ] Multi-arch images published +- [ ] Attestations attached + +### Out of Scope + +- Development/preview images (covered in Phase 02) +- Helm chart publishing (Phase 27) + +--- + +## 3. Implementation + +### 3.1 publish-container.yml + +```yaml +name: Publish Container + +on: + release: + types: [published] + workflow_dispatch: + inputs: + tag: + description: 'Image tag' + required: true + +env: + REGISTRY_GHCR: ghcr.io + REGISTRY_DOCKER: docker.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + id-token: write + attestations: write + + steps: + - uses: actions/checkout@v4 + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY_GHCR }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Login to Docker Hub + if: secrets.DOCKERHUB_TOKEN != '' + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Extract metadata + id: meta + uses: docker/metadata-action@v5 + with: + images: | + ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }} + ${{ env.REGISTRY_DOCKER }}/${{ env.IMAGE_NAME }} + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=semver,pattern={{major}} + type=sha + + - name: Build and push + id: build + uses: docker/build-push-action@v6 + with: + context: . + platforms: linux/amd64,linux/arm64 + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + provenance: true + sbom: true + + - name: Attest + uses: actions/attest-build-provenance@v1 + with: + subject-name: ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }} + subject-digest: ${{ steps.build.outputs.digest }} + push-to-registry: true + + - name: Sign with cosign + run: | + cosign sign --yes ${{ env.REGISTRY_GHCR }}/${{ env.IMAGE_NAME }}@${{ steps.build.outputs.digest }} +``` + +### 3.2 Tag Strategy + +| Event | Tags Applied | +|-------|--------------| +| Release v1.2.3 | `1.2.3`, `1.2`, `1`, `latest` | +| Release v2.0.0 | `2.0.0`, `2.0`, `2`, `latest` | +| Manual dispatch | Custom tag input | + +--- + +## 4. Review & Validation + +- [ ] Images publish to GHCR +- [ ] Docker Hub optional and working +- [ ] All expected tags present +- [ ] Multi-arch images functional +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-26-release-packages.md b/.ai/plans/phases/bundle-contents-phase-26-release-packages.md new file mode 100644 index 0000000..8f20126 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-26-release-packages.md @@ -0,0 +1,188 @@ +--- +id: 045fa19d-a65d-4fca-b6e0-2a813af692a8 +title: "Phase 26: Release - Packages" +status: pending +depends_on: + - b0116cbd-58d7-4a2e-8720-9d3860ad9232 # phase-25 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 26: Release - Packages + +## 1. Current State Assessment + +- [ ] Check for existing package publishing +- [ ] Review registry tokens configuration +- [ ] Identify package ecosystems used +- [ ] Check for dry-run testing + +### Existing Assets + +Build workflows (Phase 02) create publishable artifacts. + +### Gaps Identified + +- [ ] publish-rust.yml (crates.io) +- [ ] publish-python.yml (PyPI) +- [ ] publish-node.yml (npm) +- [ ] deploy-docs.yml (documentation) + +--- + +## 2. Contextual Goal + +Implement package publishing workflows for all supported ecosystems. Publish Rust crates to crates.io, Python packages to PyPI, and Node packages to npm. Include documentation deployment to GitHub Pages or Cloudflare. Ensure packages are signed and include provenance. + +### Success Criteria + +- [ ] crates.io publishing works +- [ ] PyPI publishing works +- [ ] npm publishing works +- [ ] Documentation deployed +- [ ] Dry-run on PRs + +### Out of Scope + +- Private registries +- Monorepo package coordination + +--- + +## 3. Implementation + +### 3.1 publish-rust.yml + +```yaml +name: Publish to crates.io + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + + - name: Publish + run: cargo publish + env: + CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} +``` + +### 3.2 publish-python.yml + +```yaml +name: Publish to PyPI + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write # For trusted publishing + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Build package + run: | + pip install build + python -m build + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 +``` + +### 3.3 publish-node.yml + +```yaml +name: Publish to npm + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + id-token: write # For npm provenance + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 20 + registry-url: 'https://registry.npmjs.org' + + - run: npm ci + + - run: npm publish --provenance --access public + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} +``` + +### 3.4 deploy-docs.yml + +```yaml +name: Deploy Documentation + +on: + release: + types: [published] + workflow_dispatch: + +jobs: + deploy: + runs-on: ubuntu-latest + permissions: + pages: write + id-token: write + + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: + - uses: actions/checkout@v4 + + - name: Build docs + run: | + # mdBook, rustdoc, etc. + + - name: Setup Pages + uses: actions/configure-pages@v4 + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: 'book/' + + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 +``` + +--- + +## 4. Review & Validation + +- [ ] crates.io publish succeeds +- [ ] PyPI publish succeeds +- [ ] npm publish succeeds +- [ ] Documentation deploys +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-27-release-helm.md b/.ai/plans/phases/bundle-contents-phase-27-release-helm.md new file mode 100644 index 0000000..2e41392 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-27-release-helm.md @@ -0,0 +1,362 @@ +--- +id: 10252d3a-1d19-4bf7-ad39-e4288ac6a3e2 +title: "Phase 27: Release - Helm" +status: pending +depends_on: + - 045fa19d-a65d-4fca-b6e0-2a813af692a8 # phase-26 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 27: Release - Helm + +## 1. Current State Assessment + +- [ ] Check for existing Helm chart infrastructure +- [ ] Review chart template patterns +- [ ] Identify chart repository strategy +- [ ] Check for OCI registry support + +### Existing Assets + +None - Helm infrastructure not yet created. + +### Gaps Identified + +- [ ] lint-helm.yml +- [ ] test-helm.yml +- [ ] release-helm.yml +- [ ] publish-helm-oci.yml +- [ ] Chart templates for MCP servers + +--- + +## 2. Contextual Goal + +Implement Helm chart infrastructure using a centralized chart repository pattern. Create workflows for linting, testing with kind, releasing with chart-releaser, and publishing to OCI registries. Provide chart templates optimized for MCP server deployment. + +### Chart Version vs App Version + +> **Important**: Helm charts have two version fields with different purposes: +> +> | Field | Purpose | Updated By | Example | +> |-------|---------|------------|---------| +> | `version` | Chart version (chart changes) | Developer/chart-releaser | `0.1.5` | +> | `appVersion` | Application version (code changes) | semantic-release (Phase 24) | `1.3.0` | +> +> **Strategy**: The chart `version` is managed independently (can release chart updates +> without app changes). The `appVersion` is synced with git tags by `scripts/update-versions.sh`. + +### Success Criteria + +- [ ] Helm lint workflow functional +- [ ] Chart testing with kind works +- [ ] chart-releaser publishes to gh-pages +- [ ] OCI registry publishing works +- [ ] **appVersion synced with semantic-release** +- [ ] **Chart release triggered on GitHub release (not push)** +- [ ] MCP chart template provided + +### Out of Scope + +- Kubernetes deployment automation +- Helm operator/Flux integration + +--- + +## 3. Implementation + +### 3.1 lint-helm.yml + +```yaml +name: Lint Helm Charts + +on: + push: + paths: + - 'charts/**' + pull_request: + paths: + - 'charts/**' + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Lint charts + run: ct lint --config .github/ct.yaml +``` + +### 3.2 test-helm.yml + +```yaml +name: Test Helm Charts + +on: + push: + paths: + - 'charts/**' + pull_request: + paths: + - 'charts/**' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Set up Helm + uses: azure/setup-helm@v4 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Create kind cluster + uses: helm/kind-action@v1 + + - name: Test charts + run: ct install --config .github/ct.yaml +``` + +### 3.3 release-helm.yml + +> **Note**: This workflow triggers on GitHub release (created by semantic-release in Phase 24), +> ensuring chart releases are synchronized with application releases. The `appVersion` in +> Chart.yaml is already updated by `scripts/update-versions.sh` before the release is created. + +```yaml +name: Release Helm Charts + +on: + # Trigger on GitHub release - synced with semantic-release (Phase 24) + release: + types: [published] + + # Also allow chart-only releases via manual trigger + workflow_dispatch: + inputs: + bump_chart_version: + description: 'Bump chart version (patch/minor/major)' + required: false + type: choice + options: + - patch + - minor + - major + +jobs: + release: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Configure Git + run: | + git config user.name "$GITHUB_ACTOR" + git config user.email "$GITHUB_ACTOR@users.noreply.github.com" + + - name: Set up Helm + uses: azure/setup-helm@v4 + + - name: Bump chart version (manual only) + if: github.event_name == 'workflow_dispatch' && inputs.bump_chart_version != '' + run: | + for chart in charts/*/Chart.yaml; do + if [ -f "$chart" ]; then + echo "Bumping $chart version (${{ inputs.bump_chart_version }})" + + # Extract current version + CURRENT=$(grep '^version:' "$chart" | awk '{print $2}') + IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT" + + case "${{ inputs.bump_chart_version }}" in + major) MAJOR=$((MAJOR + 1)); MINOR=0; PATCH=0 ;; + minor) MINOR=$((MINOR + 1)); PATCH=0 ;; + patch) PATCH=$((PATCH + 1)) ;; + esac + + NEW_VERSION="$MAJOR.$MINOR.$PATCH" + sed -i "s/^version:.*/version: $NEW_VERSION/" "$chart" + echo " $CURRENT → $NEW_VERSION" + fi + done + + git add charts/*/Chart.yaml + git commit -m "chore(helm): bump chart version [skip ci]" + git push + + - name: Run chart-releaser + uses: helm/chart-releaser-action@v1 + env: + CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" + + - name: Generate release summary + run: | + echo "## Helm Chart Release" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + for chart in charts/*/Chart.yaml; do + if [ -f "$chart" ]; then + NAME=$(grep '^name:' "$chart" | awk '{print $2}') + VERSION=$(grep '^version:' "$chart" | awk '{print $2}') + APP_VERSION=$(grep '^appVersion:' "$chart" | awk '{print $2}' | tr -d '"') + echo "| Chart | Version | App Version |" >> $GITHUB_STEP_SUMMARY + echo "|-------|---------|-------------|" >> $GITHUB_STEP_SUMMARY + echo "| $NAME | $VERSION | $APP_VERSION |" >> $GITHUB_STEP_SUMMARY + fi + done +``` + +### 3.4 publish-helm-oci.yml + +```yaml +name: Publish Helm OCI + +on: + release: + types: [published] + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + packages: write + + steps: + - uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + + - name: Login to GHCR + run: | + echo "${{ secrets.GITHUB_TOKEN }}" | \ + helm registry login ghcr.io -u ${{ github.actor }} --password-stdin + + - name: Package and push + run: | + helm package charts/mcp-server + helm push mcp-server-*.tgz oci://ghcr.io/${{ github.repository }}/charts +``` + +### 3.5 MCP Server Chart Template + +```yaml +# charts/mcp-server/Chart.yaml +apiVersion: v2 +name: mcp-server +description: A Helm chart for MCP server deployment +type: application + +# Chart version - managed independently, bumped via workflow_dispatch +# or when chart templates change +version: 0.1.0 + +# App version - synced with git tags by scripts/update-versions.sh (Phase 24) +# DO NOT manually edit - updated automatically by semantic-release +appVersion: "0.1.0" + +maintainers: + - name: maintainer + email: maintainer@example.com +``` + +```yaml +# charts/mcp-server/values.yaml +replicaCount: 1 + +image: + repository: ghcr.io/org/mcp-server + # Default to appVersion from Chart.yaml if not specified + # This ensures the container tag matches the release version + tag: "" + pullPolicy: IfNotPresent + +transport: + type: stdio # stdio, sse, http, websocket + port: 3000 + +securityContext: + runAsNonRoot: true + runAsUser: 1000 + readOnlyRootFilesystem: true + +resources: + limits: + memory: 256Mi + requests: + cpu: 100m + memory: 128Mi +``` + +```yaml +# charts/mcp-server/templates/deployment.yaml (excerpt) +# Shows how appVersion is used for image tag +containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} +``` + +--- + +## 4. Review & Validation + +- [ ] Helm lint passes +- [ ] Chart installs in kind cluster +- [ ] chart-releaser creates releases on GitHub release +- [ ] **appVersion matches git tag after semantic-release** +- [ ] **chart version is independent and bump-able via workflow_dispatch** +- [ ] OCI registry contains charts +- [ ] Image tag defaults to appVersion in deployment template +- [ ] Implementation tracking checklist updated + +--- + +## 5. Versioning Integration with Phase 24 + +This phase integrates with Phase 24 (Release - Versioning) for consistent versioning: + +``` +Phase 24: semantic-release + │ + ├── Creates git tag: v1.3.0 + │ + └── scripts/update-versions.sh 1.3.0 + │ + └── Updates charts/*/Chart.yaml appVersion: "1.3.0" + │ + ▼ +Phase 27: release-helm.yml (triggered by release) + │ + ├── chart-releaser packages chart + │ └── Chart includes appVersion: "1.3.0" + │ + └── publish-helm-oci.yml pushes to OCI + └── oci://ghcr.io/org/repo/charts/mcp-server:0.1.5 + (chart version 0.1.5, app version 1.3.0) +``` + +**Key Points**: +- `version` in Chart.yaml = chart lifecycle (template changes) +- `appVersion` in Chart.yaml = application lifecycle (synced with git tags) +- Both workflows trigger on `release: [published]` for consistency +- Manual `workflow_dispatch` allows chart-only releases when needed diff --git a/.ai/plans/phases/bundle-contents-phase-28-automation-issues.md b/.ai/plans/phases/bundle-contents-phase-28-automation-issues.md new file mode 100644 index 0000000..caba124 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-28-automation-issues.md @@ -0,0 +1,716 @@ +--- +id: e587174a-70dc-412e-8c17-07637ada8ca4 +title: "Phase 28: Automation - Issues" +status: pending +depends_on: + - 10252d3a-1d19-4bf7-ad39-e4288ac6a3e2 # phase-27 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +gate: + required: true + justfile_changes: minor + review_focus: + - Issue automation integration with justfile init + - Label sync workflow triggering + - Dependabot auto-merge behavior +--- + +# Phase 28: Automation - Issues + +> **⚠️ GATE REQUIRED**: Before starting this phase, complete the [Justfile Review Gate](../bundle-contents.md#phase-gate-justfile-review) conversation with user. + +## 0. Phase Gate: Justfile Review + +### Pre-Phase Checklist + +- [ ] Reviewed current justfile state (Phases 01-27 accumulated) +- [ ] Compared expected vs current workflow +- [ ] Discussed Phase 28 justfile changes +- [ ] User approved planned changes +- [ ] Gate conversation documented + +### Phase 28 Justfile Impact + +Minor changes - primarily workflow files, but some justfile recipes may be added: + +| Recipe | Status | Purpose | +|--------|--------|---------| +| `sync-labels` | **New** | Trigger label sync workflow | +| `stale-check` | **New** | Run stale issue check manually | + +### Integration Points + +- `_create-issues` recipe should align with auto-labeling rules +- Issue templates should match triage workflow expectations +- Dependabot config integrates with auto-merge workflow + +--- + +## 1. Current State Assessment + +- [ ] Check for existing issue automation +- [ ] Review labeler configuration +- [ ] Identify stale issue handling +- [ ] Check for triage workflows + +### Existing Assets + +- Labels defined (Phase 01) +- Issue templates (Phase 01) + +### Gaps Identified + +- [ ] label-sync.yml (sync labels from config) +- [ ] stale-issues.yml (mark stale issues) +- [ ] stale-prs.yml (mark stale PRs) +- [ ] triage.yml (auto-label new issues) +- [ ] welcome.yml (welcome contributors) +- [ ] auto-assign.yml (assign reviewers) +- [ ] auto-update-branch.yml (rebase PRs when main changes) +- [ ] dependabot-auto-merge.yml (auto-merge safe updates) +- [ ] deps-major-validation.yml (comprehensive testing for major updates) + +--- + +## 2. Contextual Goal + +Implement comprehensive issue and PR automation to reduce maintainer burden. Auto-label issues based on content, mark stale items for follow-up, welcome new contributors, and automatically assign reviewers based on code ownership. + +### Success Criteria + +- [ ] Labels sync from configuration +- [ ] Stale issues/PRs marked automatically +- [ ] New issues auto-labeled +- [ ] First-time contributors welcomed +- [ ] Reviewers assigned automatically +- [ ] Open PRs auto-rebased when main changes +- [ ] Major dependency updates trigger comprehensive validation +- [ ] Dependabot patch updates auto-merged + +### Out of Scope + +- Project board automation (GitHub native) +- Complex workflow routing +- Merge queue (requires repo settings, see Phase 00) + +--- + +## 3. Implementation + +### 3.1 label-sync.yml + +```yaml +name: Sync Labels + +on: + push: + branches: [main] + paths: + - '.github/labels.yml' + workflow_dispatch: + +jobs: + sync: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Sync labels + uses: EndBug/label-sync@v2 + with: + config-file: .github/labels.yml + delete-other-labels: true +``` + +### 3.2 stale-issues.yml + +```yaml +name: Stale Issues + +on: + schedule: + - cron: '0 6 * * *' + workflow_dispatch: + +jobs: + stale: + runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + + steps: + - uses: actions/stale@v9 + with: + stale-issue-message: > + This issue has been automatically marked as stale due to inactivity. + It will be closed in 7 days if no further activity occurs. + stale-pr-message: > + This PR has been automatically marked as stale due to inactivity. + It will be closed in 14 days if no further activity occurs. + stale-issue-label: 'stale' + stale-pr-label: 'stale' + days-before-stale: 30 + days-before-close: 7 + days-before-pr-close: 14 + exempt-issue-labels: 'pinned,security' + exempt-pr-labels: 'pinned' +``` + +### 3.3 triage.yml + +```yaml +name: Issue Triage + +on: + issues: + types: [opened] + +jobs: + triage: + runs-on: ubuntu-latest + permissions: + issues: write + + steps: + - uses: actions/github-script@v7 + with: + script: | + const issue = context.payload.issue; + const labels = []; + + // Auto-label based on title/body keywords + if (issue.title.toLowerCase().includes('bug') || + issue.body?.toLowerCase().includes('steps to reproduce')) { + labels.push('type:bug'); + } + + if (issue.title.toLowerCase().includes('feature') || + issue.body?.toLowerCase().includes('feature request')) { + labels.push('type:feature'); + } + + if (labels.length > 0) { + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: labels + }); + } + + // Add triage label + await github.rest.issues.addLabels({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + labels: ['status:triage'] + }); +``` + +### 3.4 welcome.yml + +```yaml +name: Welcome + +on: + issues: + types: [opened] + pull_request_target: + types: [opened] + +jobs: + welcome: + runs-on: ubuntu-latest + steps: + - uses: actions/first-interaction@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + issue-message: | + Thanks for opening your first issue! We appreciate your contribution. + A maintainer will review this shortly. + pr-message: | + Thanks for your first contribution! We'll review this PR soon. + Please ensure all CI checks pass. +``` + +### 3.5 auto-assign.yml + +```yaml +name: Auto Assign + +on: + pull_request: + types: [opened, ready_for_review] + +jobs: + assign: + runs-on: ubuntu-latest + permissions: + pull-requests: write + + steps: + - uses: kentaro-m/auto-assign-action@v1 + with: + configuration-path: '.github/auto-assign.yml' +``` + +### 3.6 auto-update-branch.yml + +Auto-rebase open PRs when the base branch (main) is updated. This is particularly useful when dependency updates merge before feature PRs. + +```yaml +name: Auto Update Branch + +on: + push: + branches: [main] + workflow_dispatch: + inputs: + pr_number: + description: 'Specific PR number to update (optional)' + required: false + +permissions: + contents: write + pull-requests: write + +jobs: + update-branches: + runs-on: ubuntu-latest + steps: + - name: Update PR branches + uses: actions/github-script@v7 + with: + script: | + const prNumber = context.payload.inputs?.pr_number; + + // Get open PRs + let prs; + if (prNumber) { + // Update specific PR + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: parseInt(prNumber) + }); + prs = [pr]; + } else { + // Get all open PRs targeting main + const { data: allPrs } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + base: 'main', + sort: 'updated', + direction: 'desc' + }); + prs = allPrs; + } + + for (const pr of prs) { + // Skip draft PRs + if (pr.draft) { + console.log(`Skipping draft PR #${pr.number}`); + continue; + } + + // Skip PRs with conflicts (can't auto-update) + if (pr.mergeable === false) { + console.log(`Skipping PR #${pr.number} - has conflicts`); + continue; + } + + // Skip PRs that are already up to date + if (pr.mergeable_state === 'clean' || pr.mergeable_state === 'unstable') { + console.log(`PR #${pr.number} is already up to date`); + continue; + } + + try { + // Update the branch + await github.rest.pulls.updateBranch({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number, + expected_head_sha: pr.head.sha + }); + console.log(`Updated PR #${pr.number}: ${pr.title}`); + + // Add comment + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + body: '🔄 Branch automatically updated with latest changes from `main`.' + }); + } catch (error) { + console.log(`Failed to update PR #${pr.number}: ${error.message}`); + } + } +``` + +**Alternative: Label-Based Trigger** + +For more control, only update PRs with a specific label: + +```yaml +name: Auto Update Branch (Label-Based) + +on: + push: + branches: [main] + +jobs: + update-labeled-prs: + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + + steps: + - name: Update PRs with auto-update label + uses: actions/github-script@v7 + with: + script: | + const { data: prs } = await github.rest.pulls.list({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'open', + base: 'main' + }); + + for (const pr of prs) { + // Only update PRs with 'auto-update' label + const hasLabel = pr.labels.some(l => l.name === 'auto-update'); + if (!hasLabel) continue; + + try { + await github.rest.pulls.updateBranch({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: pr.number + }); + console.log(`Updated PR #${pr.number}`); + } catch (error) { + console.log(`Failed: ${error.message}`); + } + } +``` + +### 3.7 dependabot-auto-merge.yml + +Auto-merge Dependabot PRs for patch/minor updates after CI passes: + +```yaml +name: Dependabot Auto-Merge + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: write + pull-requests: write + +jobs: + auto-merge: + runs-on: ubuntu-latest + if: github.actor == 'dependabot[bot]' + + steps: + - name: Fetch Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Auto-merge patch updates + if: steps.metadata.outputs.update-type == 'version-update:semver-patch' + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Auto-merge minor updates (dev dependencies only) + if: | + steps.metadata.outputs.update-type == 'version-update:semver-minor' && + steps.metadata.outputs.dependency-type == 'direct:development' + run: gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Label major updates for review + if: steps.metadata.outputs.update-type == 'version-update:semver-major' + run: gh pr edit "$PR_URL" --add-label "needs:review,breaking-change" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +### 3.8 deps-major-validation.yml + +Comprehensive testing for major dependency updates. Runs extended test suites to identify breaking changes before manual review. **Does NOT auto-merge.** + +```yaml +name: Major Dependency Validation + +on: + pull_request: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + checks: write + +jobs: + # Gate: Only run for Dependabot major updates + check-trigger: + runs-on: ubuntu-latest + if: github.actor == 'dependabot[bot]' + outputs: + is-major: ${{ steps.metadata.outputs.update-type == 'version-update:semver-major' }} + dependency: ${{ steps.metadata.outputs.dependency-names }} + ecosystem: ${{ steps.metadata.outputs.package-ecosystem }} + steps: + - name: Fetch Dependabot metadata + id: metadata + uses: dependabot/fetch-metadata@v2 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + + # Full test matrix for major updates + validation: + needs: check-trigger + if: needs.check-trigger.outputs.is-major == 'true' + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + test-type: [unit, integration, e2e, property] + steps: + - uses: actions/checkout@v4 + + - name: Setup test environment + uses: ./.github/actions/setup-test-env + with: + test-type: ${{ matrix.test-type }} + + - name: Run ${{ matrix.test-type }} tests + id: tests + run: | + # Dispatch to appropriate test runner + case "${{ matrix.test-type }}" in + unit) just test-unit ;; + integration) just test-integration ;; + e2e) just test-e2e ;; + property) just test-property ;; + esac + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: test-results-${{ matrix.test-type }} + path: target/test-results/ + + # Breaking change detection + breaking-changes: + needs: check-trigger + if: needs.check-trigger.outputs.is-major == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Detect breaking changes (Rust) + if: needs.check-trigger.outputs.ecosystem == 'cargo' + run: | + cargo install cargo-semver-checks + cargo semver-checks check-release 2>&1 | tee breaking-changes.txt || true + + - name: Detect breaking changes (Node) + if: needs.check-trigger.outputs.ecosystem == 'npm' + run: | + npx publint 2>&1 | tee breaking-changes.txt || true + + - name: Upload breaking change report + uses: actions/upload-artifact@v4 + with: + name: breaking-changes + path: breaking-changes.txt + + # Benchmark comparison + performance: + needs: check-trigger + if: needs.check-trigger.outputs.is-major == 'true' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/checkout@v4 + with: + ref: main + path: baseline + + - name: Run baseline benchmarks + run: | + cd baseline + just bench --save-baseline main + + - name: Run PR benchmarks + run: | + just bench --baseline main --save-baseline pr + + - name: Generate comparison + id: bench + run: | + just bench-compare main pr > bench-comparison.md + echo "has-regression=$(grep -q 'REGRESSION' bench-comparison.md && echo 'true' || echo 'false')" >> $GITHUB_OUTPUT + + - name: Upload benchmark comparison + uses: actions/upload-artifact@v4 + with: + name: benchmark-comparison + path: bench-comparison.md + + # Summary report + report: + needs: [check-trigger, validation, breaking-changes, performance] + if: always() && needs.check-trigger.outputs.is-major == 'true' + runs-on: ubuntu-latest + permissions: + pull-requests: write + steps: + - uses: actions/download-artifact@v4 + with: + merge-multiple: true + + - name: Generate validation report + id: report + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + + const dependency = '${{ needs.check-trigger.outputs.dependency }}'; + const validationResult = '${{ needs.validation.result }}'; + const breakingResult = '${{ needs.breaking-changes.result }}'; + const perfResult = '${{ needs.performance.result }}'; + + let breakingChanges = ''; + try { + breakingChanges = fs.readFileSync('breaking-changes.txt', 'utf8'); + } catch (e) { + breakingChanges = 'No breaking changes detected or analysis not available.'; + } + + let benchComparison = ''; + try { + benchComparison = fs.readFileSync('bench-comparison.md', 'utf8'); + } catch (e) { + benchComparison = 'Benchmark comparison not available.'; + } + + const allPassed = validationResult === 'success' && + breakingResult === 'success' && + perfResult === 'success'; + + const statusEmoji = allPassed ? '✅' : '⚠️'; + + const body = `## ${statusEmoji} Major Dependency Update Validation + +**Dependency**: \`${dependency}\` +**Update Type**: Major (semver-major) + +### Test Results + +| Test Suite | Status | +|------------|--------| +| Unit Tests | ${validationResult === 'success' ? '✅ Passed' : '❌ Failed'} | +| Integration Tests | ${validationResult === 'success' ? '✅ Passed' : '❌ Failed'} | +| E2E Tests | ${validationResult === 'success' ? '✅ Passed' : '❌ Failed'} | +| Property Tests | ${validationResult === 'success' ? '✅ Passed' : '❌ Failed'} | + +### Breaking Changes Detection + +\`\`\` +${breakingChanges.substring(0, 2000)} +\`\`\` + +### Performance Comparison + +${benchComparison.substring(0, 2000)} + +--- + +⚠️ **This is a MAJOR version update. Manual review required.** + +**Checklist for reviewer:** +- [ ] Breaking changes have been evaluated +- [ ] Migration path documented (if needed) +- [ ] Performance impact acceptable +- [ ] All tests passing or failures explained +- [ ] Downstream consumers notified (if public API affected) +`; + + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: body + }); + + - name: Add validation label + run: | + if [ "${{ needs.validation.result }}" == "success" ]; then + gh pr edit "${{ github.event.pull_request.number }}" --add-label "validated" + else + gh pr edit "${{ github.event.pull_request.number }}" --add-label "validation-failed" + fi + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} +``` + +**Key differences from auto-merge workflow:** +- Runs comprehensive test matrix (unit, integration, e2e, property) +- Detects API breaking changes (cargo-semver-checks, publint) +- Compares benchmarks against baseline +- Posts detailed validation report +- **Never auto-merges** - requires human approval +- Adds `validated` or `validation-failed` label + +### 3.9 Merge Queue Configuration (Manual) + +For repositories with high PR volume, enable GitHub's native Merge Queue: + +**Settings → General → Pull Requests:** +- [ ] Enable "Require branches to be up to date before merging" +- [ ] Enable "Require merge queue" + +**Merge Queue Benefits:** +- Automatic rebasing before merge +- Batched CI runs (efficiency) +- Guaranteed main branch stability +- No race conditions between PRs + +> **Note**: Merge Queue requires repository admin access. Add to Phase 00 manual setup checklist. + +--- + +## 4. Review & Validation + +- [ ] Labels sync correctly +- [ ] Stale workflow runs on schedule +- [ ] Auto-labeling accurate +- [ ] Welcome messages appropriate +- [ ] Auto-update rebases PRs when main changes +- [ ] Dependabot patch updates auto-merge after CI +- [ ] Dependabot major updates labeled for review +- [ ] Major updates trigger comprehensive validation +- [ ] Validation report posted to PR with checklist +- [ ] Merge Queue configured (if high PR volume) +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-29-automation-notifications.md b/.ai/plans/phases/bundle-contents-phase-29-automation-notifications.md new file mode 100644 index 0000000..9944516 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-29-automation-notifications.md @@ -0,0 +1,196 @@ +--- +id: 48214b5a-d97d-4805-80bb-fabe5c73df00 +title: "Phase 29: Automation - Notifications" +status: pending +depends_on: + - e587174a-70dc-412e-8c17-07637ada8ca4 # phase-28 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +issues: [] +--- + +# Phase 29: Automation - Notifications + +## 1. Current State Assessment + +- [ ] Check for existing notification setup +- [ ] Review webhook configurations +- [ ] Identify notification triggers +- [ ] Check for secret management + +### Existing Assets + +None - notifications not yet configured. + +### Gaps Identified + +- [ ] notify-slack.yml +- [ ] notify-discord.yml + +--- + +## 2. Contextual Goal + +Implement notification workflows for Slack and Discord to keep teams informed of releases, security issues, and CI failures. Notifications should be configurable with different channels for different event types. + +### Success Criteria + +- [ ] Slack notifications on releases +- [ ] Discord notifications on releases +- [ ] Security alerts routed correctly +- [ ] CI failure notifications +- [ ] Secrets properly managed + +### Out of Scope + +- PagerDuty/OpsGenie integration +- Email notifications + +--- + +## 3. Implementation + +### 3.1 notify-slack.yml + +```yaml +name: Notify Slack + +on: + release: + types: [published] + workflow_run: + workflows: ["CI"] + types: [completed] + workflow_dispatch: + inputs: + message: + description: 'Custom message' + required: true + +jobs: + notify-release: + if: github.event_name == 'release' + runs-on: ubuntu-latest + steps: + - name: Notify Slack + uses: slackapi/slack-github-action@v1 + with: + channel-id: 'releases' + payload: | + { + "blocks": [ + { + "type": "header", + "text": { + "type": "plain_text", + "text": "New Release: ${{ github.event.release.tag_name }}" + } + }, + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "${{ github.event.release.body }}" + } + }, + { + "type": "actions", + "elements": [ + { + "type": "button", + "text": {"type": "plain_text", "text": "View Release"}, + "url": "${{ github.event.release.html_url }}" + } + ] + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} + + notify-failure: + if: github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'failure' + runs-on: ubuntu-latest + steps: + - name: Notify Slack + uses: slackapi/slack-github-action@v1 + with: + channel-id: 'ci-alerts' + payload: | + { + "text": "CI Failed: ${{ github.event.workflow_run.name }}", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "*CI Failure*\nWorkflow: ${{ github.event.workflow_run.name }}\nBranch: ${{ github.event.workflow_run.head_branch }}" + } + } + ] + } + env: + SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }} +``` + +### 3.2 notify-discord.yml + +```yaml +name: Notify Discord + +on: + release: + types: [published] + workflow_dispatch: + inputs: + message: + description: 'Custom message' + required: true + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Notify Discord + uses: sarisia/actions-status-discord@v1 + if: github.event_name == 'release' + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + title: "New Release: ${{ github.event.release.tag_name }}" + description: ${{ github.event.release.body }} + url: ${{ github.event.release.html_url }} + color: 0x00ff00 + + - name: Custom notification + if: github.event_name == 'workflow_dispatch' + uses: sarisia/actions-status-discord@v1 + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + title: "Announcement" + description: ${{ inputs.message }} +``` + +### 3.3 Required Secrets + +| Secret | Purpose | +|--------|---------| +| `SLACK_BOT_TOKEN` | Slack API token | +| `DISCORD_WEBHOOK` | Discord webhook URL | + +### 3.4 Channel Routing + +| Event | Slack Channel | Discord Channel | +|-------|---------------|-----------------| +| Release | #releases | releases | +| CI Failure | #ci-alerts | ci-alerts | +| Security | #security | security | + +--- + +## 4. Review & Validation + +- [ ] Slack notifications work +- [ ] Discord notifications work +- [ ] Messages format correctly +- [ ] Secrets are secured +- [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-30-automation-mcp.md b/.ai/plans/phases/bundle-contents-phase-30-automation-mcp.md new file mode 100644 index 0000000..d445656 --- /dev/null +++ b/.ai/plans/phases/bundle-contents-phase-30-automation-mcp.md @@ -0,0 +1,779 @@ +--- +id: 66d2f055-ea20-46b5-8905-f7acd89c06c5 +title: "Phase 30: Automation - MCP" +status: pending +depends_on: + - 48214b5a-d97d-4805-80bb-fabe5c73df00 # phase-29 +checklists: + - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking + - 52545f6d-de4f-421f-8444-3f8d683c3ad0 # testing-validation +issues: [] +--- + +# Phase 30: Automation - MCP + +## 1. Current State Assessment + +- [ ] Check for existing MCP automation +- [ ] Review ecosystem discovery tools +- [ ] Identify evaluation frameworks +- [ ] Check for MCP server registry + +### Existing Assets + +- MCP testing taxonomy (references/) +- MCP protocol tests (Phase 11) + +### Gaps Identified + +- [ ] mcp-eval.yml (server evaluation) +- [ ] mcp-discovery.yml (ecosystem scanning with category-based search) +- [ ] discovery-config.yml (configurable search criteria) +- [ ] known-servers.yml (registry of known/evaluated servers) + +--- + +## 2. Contextual Goal + +Implement MCP-specific automation workflows for evaluating MCP server implementations and discovering ecosystem resources. The evaluation workflow runs comprehensive tests against MCP servers using the taxonomy defined in references. The discovery workflow scans for new MCP servers and tools in the ecosystem. + +### Success Criteria + +- [ ] MCP evaluation workflow functional +- [ ] Evaluation reports generated +- [ ] Ecosystem discovery runs on schedule (weekly) +- [ ] Search criteria configurable per category +- [ ] Known servers tracked to avoid duplicates +- [ ] New discoveries create issues automatically +- [ ] Results published to repository +- [ ] Badges/scores visible + +### Out of Scope + +- Running third-party MCP servers +- Maintaining a public registry +- Manual server evaluation (human task) + +--- + +## 3. Implementation + +### 3.1 mcp-eval.yml + +```yaml +name: MCP Server Evaluation + +on: + push: + branches: [main] + paths: + - 'src/**' + pull_request: + schedule: + - cron: '0 6 * * 1' # Weekly + workflow_dispatch: + inputs: + server: + description: 'Server to evaluate (default: local)' + default: 'local' + +jobs: + evaluate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build server + run: cargo build --release + + - name: Run protocol conformance + run: | + cargo test --test mcp_conformance -- --format json > conformance.json + + - name: Run functional tests + run: | + cargo test --test mcp_functional -- --format json > functional.json + + - name: Run performance benchmarks + run: | + cargo bench -- --format json > performance.json + + - name: Generate evaluation report + run: | + python scripts/generate-eval-report.py \ + --conformance conformance.json \ + --functional functional.json \ + --performance performance.json \ + --output evaluation-report.md + + - name: Upload report + uses: actions/upload-artifact@v4 + with: + name: mcp-evaluation + path: evaluation-report.md + + - name: Update README badge + if: github.ref == 'refs/heads/main' + run: | + # Calculate score and update badge + + compare: + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + needs: evaluate + steps: + - name: Compare with baseline + run: | + # Compare PR results with main branch baseline +``` + +### 3.2 discovery-config.yml + +Configuration file defining search criteria for MCP server discovery: + +```yaml +# .github/mcp/discovery-config.yml +version: 1 + +# How often to run discovery (cron expressions per category) +schedule: + default: "0 6 * * 1" # Weekly on Monday 6AM + +# Search sources +sources: + - name: github + type: code-search + enabled: true + - name: npm + type: package-registry + enabled: true + - name: pypi + type: package-registry + enabled: true + - name: crates + type: package-registry + enabled: true + +# Discovery categories with search criteria +categories: + database: + description: "Database and data storage MCP servers" + priority: high + search_terms: + - "mcp server postgresql" + - "mcp server mysql" + - "mcp server mongodb" + - "mcp server redis" + - "mcp server sqlite" + - "mcp-server database" + - "model context protocol database" + github_topics: + - mcp-server + - model-context-protocol + file_patterns: + - "**/mcp.json" + - "**/mcp-server.json" + exclude_terms: + - "archived" + - "deprecated" + - "unmaintained" + labels: + - "mcp:database" + - "type:discovery" + + ai-tools: + description: "AI/ML integration MCP servers" + priority: high + search_terms: + - "mcp server openai" + - "mcp server anthropic" + - "mcp server llm" + - "mcp server embedding" + - "mcp-server ai" + labels: + - "mcp:ai-tools" + - "type:discovery" + + dev-tools: + description: "Developer tooling MCP servers" + priority: medium + search_terms: + - "mcp server git" + - "mcp server github" + - "mcp server docker" + - "mcp server kubernetes" + - "mcp server terraform" + - "mcp-server devops" + labels: + - "mcp:dev-tools" + - "type:discovery" + + file-storage: + description: "File and cloud storage MCP servers" + priority: medium + search_terms: + - "mcp server s3" + - "mcp server gcs" + - "mcp server azure blob" + - "mcp server filesystem" + - "mcp-server storage" + labels: + - "mcp:file-storage" + - "type:discovery" + + communication: + description: "Communication and messaging MCP servers" + priority: low + search_terms: + - "mcp server slack" + - "mcp server discord" + - "mcp server email" + - "mcp server webhook" + labels: + - "mcp:communication" + - "type:discovery" + +# Minimum quality thresholds +quality_filters: + github: + min_stars: 5 + min_commits: 10 + max_days_since_update: 180 + require_license: true + require_readme: true + npm: + min_weekly_downloads: 100 + pypi: + min_downloads: 500 + crates: + min_downloads: 100 + +# Issue template for discoveries +issue_template: | + ## MCP Server Discovery + + **Category**: {{ category }} + **Source**: {{ source }} + **Discovered**: {{ discovered_at }} + + ### Server Details + + | Field | Value | + |-------|-------| + | Name | {{ name }} | + | Repository | {{ repository_url }} | + | Package | {{ package_url }} | + | Stars | {{ stars }} | + | Last Updated | {{ last_updated }} | + | License | {{ license }} | + + ### Description + + {{ description }} + + ### Evaluation Checklist + + - [ ] Review README and documentation + - [ ] Check MCP protocol compliance + - [ ] Verify security practices + - [ ] Test basic functionality + - [ ] Assess maintenance status + - [ ] Document integration requirements + + --- + *Auto-generated by MCP Discovery workflow* +``` + +### 3.3 known-servers.yml + +Registry of known MCP servers to avoid duplicate discoveries: + +```yaml +# .github/mcp/known-servers.yml +version: 1 + +# Known servers organized by category +servers: + database: + - id: "github:modelcontextprotocol/servers/postgres" + name: "Official PostgreSQL Server" + status: evaluated + added: "2024-01-15" + + - id: "github:modelcontextprotocol/servers/sqlite" + name: "Official SQLite Server" + status: evaluated + added: "2024-01-15" + + ai-tools: + - id: "github:anthropics/claude-code" + name: "Claude Code" + status: internal + added: "2024-01-01" + + dev-tools: + - id: "github:modelcontextprotocol/servers/github" + name: "Official GitHub Server" + status: evaluated + added: "2024-01-15" + + - id: "github:modelcontextprotocol/servers/git" + name: "Official Git Server" + status: evaluated + added: "2024-01-15" + + file-storage: + - id: "github:modelcontextprotocol/servers/filesystem" + name: "Official Filesystem Server" + status: evaluated + added: "2024-01-15" + +# Servers to explicitly ignore (forks, deprecated, etc.) +ignored: + - id: "github:*/mcp-server-template" + reason: "Template repository" + + - id: "github:*/awesome-mcp*" + reason: "Awesome list, not a server" + +# Status values: +# - evaluated: Fully evaluated and documented +# - pending: Discovered, awaiting evaluation +# - rejected: Evaluated and rejected +# - internal: Internal/first-party server +# - ignored: Explicitly ignored +``` + +### 3.4 mcp-discovery.yml + +Main discovery workflow with category-based search, filtering, and auto-issue creation: + +```yaml +name: MCP Server Discovery + +on: + schedule: + - cron: '0 6 * * 1' # Weekly on Monday 6AM UTC + workflow_dispatch: + inputs: + category: + description: 'Category to search (or "all")' + required: false + default: 'all' + type: choice + options: + - all + - database + - ai-tools + - dev-tools + - file-storage + - communication + dry_run: + description: 'Dry run (no issue creation)' + required: false + default: false + type: boolean + +permissions: + contents: write + issues: write + +jobs: + discover: + runs-on: ubuntu-latest + outputs: + discoveries: ${{ steps.filter.outputs.new_discoveries }} + new_count: ${{ steps.filter.outputs.new_count }} + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Install dependencies + run: npm install js-yaml + + - name: Load configuration + id: config + run: | + echo "config<> $GITHUB_OUTPUT + cat .github/mcp/discovery-config.yml >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Load known servers + id: known + run: | + echo "known<> $GITHUB_OUTPUT + cat .github/mcp/known-servers.yml >> $GITHUB_OUTPUT + echo "EOF" >> $GITHUB_OUTPUT + + - name: Search for MCP servers + id: search + uses: actions/github-script@v7 + env: + CATEGORY: ${{ inputs.category || 'all' }} + CONFIG: ${{ steps.config.outputs.config }} + with: + script: | + const yaml = require('js-yaml'); + const config = yaml.load(process.env.CONFIG); + const targetCategory = process.env.CATEGORY; + + const discoveries = []; + + // Determine which categories to search + const categories = targetCategory === 'all' + ? Object.keys(config.categories) + : [targetCategory]; + + for (const categoryName of categories) { + const category = config.categories[categoryName]; + if (!category) continue; + + console.log(`\n=== Searching category: ${categoryName} ===`); + + // Search GitHub + for (const term of category.search_terms || []) { + try { + const query = `${term} in:readme,name,description`; + console.log(`Searching: ${query}`); + + const { data: results } = await github.rest.search.repos({ + q: query, + sort: 'stars', + order: 'desc', + per_page: 20 + }); + + for (const repo of results.items) { + // Apply quality filters + const filters = config.quality_filters.github; + if (repo.stargazers_count < filters.min_stars) continue; + if (repo.archived) continue; + + const daysSinceUpdate = Math.floor( + (Date.now() - new Date(repo.updated_at)) / (1000 * 60 * 60 * 24) + ); + if (daysSinceUpdate > filters.max_days_since_update) continue; + if (filters.require_license && !repo.license) continue; + + discoveries.push({ + id: `github:${repo.full_name}`, + category: categoryName, + source: 'github', + name: repo.name, + full_name: repo.full_name, + description: repo.description || '', + repository_url: repo.html_url, + package_url: null, + stars: repo.stargazers_count, + forks: repo.forks_count, + last_updated: repo.updated_at, + license: repo.license?.spdx_id || 'Unknown', + topics: repo.topics || [], + labels: category.labels || [] + }); + } + + // Rate limiting pause + await new Promise(r => setTimeout(r, 1000)); + } catch (error) { + console.log(`Search error for "${term}": ${error.message}`); + } + } + } + + // Deduplicate by ID + const unique = [...new Map(discoveries.map(d => [d.id, d])).values()]; + console.log(`\nTotal discoveries: ${unique.length}`); + + core.setOutput('discoveries', JSON.stringify(unique)); + return unique; + + - name: Filter known servers + id: filter + uses: actions/github-script@v7 + env: + DISCOVERIES: ${{ steps.search.outputs.discoveries }} + KNOWN: ${{ steps.known.outputs.known }} + with: + script: | + const yaml = require('js-yaml'); + const discoveries = JSON.parse(process.env.DISCOVERIES); + const known = yaml.load(process.env.KNOWN); + + // Build set of known IDs + const knownIds = new Set(); + + // Add all known servers + for (const category of Object.values(known.servers || {})) { + for (const server of category) { + knownIds.add(server.id); + } + } + + // Add ignored patterns + const ignoredPatterns = (known.ignored || []).map(i => { + const pattern = i.id.replace(/\*/g, '.*'); + return new RegExp(`^${pattern}$`); + }); + + // Filter discoveries + const newDiscoveries = discoveries.filter(d => { + // Check exact match + if (knownIds.has(d.id)) { + console.log(`Skipping known: ${d.id}`); + return false; + } + + // Check ignored patterns + for (const pattern of ignoredPatterns) { + if (pattern.test(d.id)) { + console.log(`Skipping ignored: ${d.id}`); + return false; + } + } + + return true; + }); + + console.log(`\nNew discoveries: ${newDiscoveries.length}`); + + core.setOutput('new_discoveries', JSON.stringify(newDiscoveries)); + core.setOutput('new_count', newDiscoveries.length); + return newDiscoveries; + + create-issues: + needs: discover + if: needs.discover.outputs.new_count > 0 && inputs.dry_run != true + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: Create discovery issues + uses: actions/github-script@v7 + env: + DISCOVERIES: ${{ needs.discover.outputs.discoveries }} + with: + script: | + const discoveries = JSON.parse(process.env.DISCOVERIES); + + for (const d of discoveries) { + // Check for existing issue + const { data: issues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'all', + labels: 'type:discovery', + per_page: 100 + }); + + const exists = issues.some(issue => + issue.body && issue.body.includes(d.id) + ); + + if (exists) { + console.log(`Issue already exists for: ${d.id}`); + continue; + } + + const body = `## MCP Server Discovery + +**Category**: ${d.category} +**Source**: ${d.source} +**Discovered**: ${new Date().toISOString().split('T')[0]} + +### Server Details + +| Field | Value | +|-------|-------| +| Name | ${d.name} | +| Repository | ${d.repository_url} | +| Package | ${d.package_url || 'N/A'} | +| Stars | ${d.stars} | +| Last Updated | ${d.last_updated.split('T')[0]} | +| License | ${d.license} | + +### Description + +${d.description || '_No description provided_'} + +### Evaluation Checklist + +- [ ] Review README and documentation +- [ ] Check MCP protocol compliance +- [ ] Verify security practices +- [ ] Test basic functionality +- [ ] Assess maintenance status +- [ ] Document integration requirements + +--- +**Server ID**: \`${d.id}\` +*Auto-generated by MCP Discovery workflow*`; + + const { data: issue } = await github.rest.issues.create({ + owner: context.repo.owner, + repo: context.repo.repo, + title: `[MCP Discovery] ${d.name}`, + body: body, + labels: d.labels + }); + + console.log(`Created issue #${issue.number}: ${issue.title}`); + + // Rate limit pause + await new Promise(r => setTimeout(r, 2000)); + } + + update-known: + needs: [discover, create-issues] + if: always() && needs.discover.outputs.new_count > 0 && inputs.dry_run != true + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - uses: actions/checkout@v4 + with: + ref: main + + - name: Update known-servers.yml + uses: actions/github-script@v7 + env: + DISCOVERIES: ${{ needs.discover.outputs.discoveries }} + with: + script: | + const fs = require('fs'); + const yaml = require('js-yaml'); + + const discoveries = JSON.parse(process.env.DISCOVERIES); + const knownPath = '.github/mcp/known-servers.yml'; + const known = yaml.load(fs.readFileSync(knownPath, 'utf8')); + + // Add new discoveries as pending + for (const d of discoveries) { + if (!known.servers[d.category]) { + known.servers[d.category] = []; + } + + // Check if already exists + const exists = known.servers[d.category].some(s => s.id === d.id); + if (!exists) { + known.servers[d.category].push({ + id: d.id, + name: d.name, + status: 'pending', + added: new Date().toISOString().split('T')[0] + }); + } + } + + fs.writeFileSync(knownPath, yaml.dump(known, { lineWidth: -1 })); + + - name: Commit updates + run: | + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git add .github/mcp/known-servers.yml + git diff --quiet --staged || git commit -m "chore(mcp): update known servers from discovery + + Added ${{ needs.discover.outputs.new_count }} new server(s) as pending. + + [skip ci]" + git push + + summary: + needs: [discover, create-issues, update-known] + if: always() + runs-on: ubuntu-latest + + steps: + - name: Generate summary + uses: actions/github-script@v7 + with: + script: | + const newCount = parseInt('${{ needs.discover.outputs.new_count }}') || 0; + const dryRun = '${{ inputs.dry_run }}' === 'true'; + + let summary = `## MCP Discovery Summary\n\n`; + summary += `| Metric | Value |\n`; + summary += `|--------|-------|\n`; + summary += `| New Discoveries | ${newCount} |\n`; + summary += `| Dry Run | ${dryRun ? 'Yes' : 'No'} |\n`; + summary += `| Issues Created | ${dryRun ? 'N/A' : newCount} |\n`; + + if (newCount > 0) { + const discoveries = JSON.parse('${{ needs.discover.outputs.discoveries }}'); + summary += `\n### Discoveries by Category\n\n`; + + const byCategory = {}; + for (const d of discoveries) { + byCategory[d.category] = (byCategory[d.category] || 0) + 1; + } + + for (const [cat, count] of Object.entries(byCategory)) { + summary += `- **${cat}**: ${count}\n`; + } + } + + await core.summary.addRaw(summary).write(); +``` + +### 3.5 Evaluation Metrics + +| Category | Metrics | Weight | +|----------|---------|--------| +| Protocol Conformance | JSON-RPC, MCP init, capabilities | 40% | +| Functional | Tools, resources, prompts | 30% | +| Performance | Latency p50/p95/p99, throughput | 20% | +| Security | Input validation, fuzzing survival | 10% | + +### 3.6 Discovery Sources + +| Source | Search Method | +|--------|---------------| +| GitHub | Topic search, code search, readme search | +| npm | Keyword search (mcp-server, model-context-protocol) | +| PyPI | Classifier/keyword search | +| crates.io | Keyword search | + +### 3.7 Discovery Categories + +| Category | Priority | Example Search Terms | +|----------|----------|---------------------| +| `database` | High | postgresql, mysql, mongodb, redis, sqlite | +| `ai-tools` | High | openai, anthropic, llm, embedding | +| `dev-tools` | Medium | git, github, docker, kubernetes, terraform | +| `file-storage` | Medium | s3, gcs, azure blob, filesystem | +| `communication` | Low | slack, discord, email, webhook | + +--- + +## 4. Review & Validation + +- [ ] Evaluation produces meaningful scores +- [ ] Discovery config loads correctly +- [ ] Category-based search works +- [ ] Known servers filtered correctly +- [ ] Quality filters applied (stars, license, update date) +- [ ] New discoveries create issues automatically +- [ ] known-servers.yml updated after discovery +- [ ] Dry run mode prevents issue creation +- [ ] Reports are readable +- [ ] Automation runs on schedule (weekly) +- [ ] Implementation tracking checklist updated + +--- + +## Final Notes + +This phase completes the Bundle Expansion plan. After implementing all 30 phases: + +1. Run the Testing Validation checklist +2. Update the Gap Analysis checklist +3. Create a release with the complete bundle +4. Publish documentation diff --git a/.ai/plans/references/mcp-testing-taxonomy.md b/.ai/plans/references/mcp-testing-taxonomy.md new file mode 100644 index 0000000..cb6d069 --- /dev/null +++ b/.ai/plans/references/mcp-testing-taxonomy.md @@ -0,0 +1,401 @@ +--- +id: 6d0e0e40-1c80-4d57-aef2-e2da53cdd416 +title: "MCP Testing Taxonomy" +type: reference +--- + +# MCP Server Testing Taxonomy + +## Overview + +Comprehensive testing strategy for Model Context Protocol (MCP) servers covering protocol conformance, functional correctness, security, performance, and reliability. + +--- + +## 1. Protocol Conformance Testing + +### 1.1 JSON-RPC 2.0 Compliance + +| Test ID | Test Case | Input | Expected | +|---------|-----------|-------|----------| +| JSONRPC-001 | Valid request format | `{"jsonrpc":"2.0","id":1,"method":"..."}` | Accepted | +| JSONRPC-002 | Missing jsonrpc field | `{"id":1,"method":"..."}` | Error -32600 | +| JSONRPC-003 | Invalid jsonrpc version | `{"jsonrpc":"1.0",...}` | Error -32600 | +| JSONRPC-004 | Null id for notification | `{"jsonrpc":"2.0","method":"..."}` | No response | +| JSONRPC-005 | String id handling | `{"id":"abc",...}` | Response with same id | +| JSONRPC-006 | Batch requests | `[{...},{...}]` | Batch response | +| JSONRPC-007 | Empty batch | `[]` | Error -32600 | + +#### Error Code Verification + +| Code | Meaning | When to Return | +|------|---------|----------------| +| -32700 | Parse error | Invalid JSON | +| -32600 | Invalid request | Malformed request object | +| -32601 | Method not found | Unknown method | +| -32602 | Invalid params | Wrong arguments | +| -32603 | Internal error | Server error | +| -32000 to -32099 | Server error | Implementation-defined | + +### 1.2 MCP Protocol Compliance + +#### Initialization Sequence + +``` +┌─────────┐ ┌─────────┐ +│ Client │ │ Server │ +└────┬────┘ └────┬────┘ + │ │ + │──── initialize ─────────────>│ + │ │ + │<─── initialize result ───────│ + │ │ + │──── initialized ────────────>│ + │ │ + │ (ready for requests) │ +``` + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| MCP-INIT-001 | Valid initialize request | Success with capabilities | +| MCP-INIT-002 | Missing clientInfo | Error or default handling | +| MCP-INIT-003 | Unsupported protocol version | Error with supported versions | +| MCP-INIT-004 | Request before initialize | Error -32002 (not initialized) | +| MCP-INIT-005 | Double initialize | Error or idempotent | +| MCP-INIT-006 | initialized notification | No response, ready state | + +### 1.3 Schema Validation + +```yaml +validation_targets: + requests: + - initialize params match InitializeRequest schema + - tools/call params match CallToolRequest schema + - resources/read params match ReadResourceRequest schema + + responses: + - initialize result matches InitializeResult schema + - tools/list result matches ListToolsResult schema + - Content objects have required type field + + error_objects: + - Required: code (integer), message (string) + - Optional: data (any) +``` + +--- + +## 2. Functional Testing + +### 2.1 Tool Testing + +#### Tool Discovery (tools/list) + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| TOOL-LIST-001 | List all tools | Array of tool definitions | +| TOOL-LIST-002 | Empty tools list | Empty array (not error) | +| TOOL-LIST-003 | Tool metadata complete | name, description, inputSchema present | +| TOOL-LIST-004 | inputSchema is valid JSON Schema | Parseable schema | +| TOOL-LIST-005 | Pagination (cursor) | Correct page handling | + +#### Tool Invocation (tools/call) + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| TOOL-CALL-001 | Valid tool call | Success with content | +| TOOL-CALL-002 | Unknown tool name | Error -32601 or MCP error | +| TOOL-CALL-003 | Missing required argument | Error -32602 | +| TOOL-CALL-004 | Wrong argument type | Error -32602 | +| TOOL-CALL-005 | Extra arguments | Ignored or error (per policy) | +| TOOL-CALL-006 | Empty arguments object | Valid if no required params | +| TOOL-CALL-007 | Null argument value | Per schema (nullable?) | + +### 2.2 Resource Testing + +#### Resource Discovery (resources/list) + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| RES-LIST-001 | List all resources | Array of resource definitions | +| RES-LIST-002 | Resource metadata | uri, name, mimeType present | +| RES-LIST-003 | URI scheme handling | file://, http://, custom:// | +| RES-LIST-004 | Pagination | Cursor-based pagination works | + +#### Resource Reading (resources/read) + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| RES-READ-001 | Valid URI | Contents returned | +| RES-READ-002 | Unknown URI | Error -32002 | +| RES-READ-003 | Text resource | text field populated | +| RES-READ-004 | Binary resource | blob field (base64) | +| RES-READ-005 | Large resource | Chunking or streaming | + +### 2.3 Prompt Testing + +#### Prompt Discovery (prompts/list) + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| PROMPT-LIST-001 | List all prompts | Array of prompt definitions | +| PROMPT-LIST-002 | Prompt metadata | name, description, arguments | +| PROMPT-LIST-003 | Required vs optional args | Clearly marked | + +--- + +## 3. Transport Testing + +### 3.1 stdio Transport + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| STDIO-001 | Line-delimited JSON | Each message on one line | +| STDIO-002 | Large message buffering | No truncation | +| STDIO-003 | UTF-8 encoding | Correct handling | +| STDIO-004 | EOF handling | Graceful shutdown | +| STDIO-005 | stderr for logging | Doesn't pollute stdout | + +### 3.2 HTTP/SSE Transport + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| SSE-001 | Event stream format | `data: {...}\n\n` | +| SSE-002 | Event type field | Correct event types | +| SSE-003 | Keep-alive | Connection stays open | +| SSE-004 | Reconnection | Client can reconnect | +| SSE-005 | CORS headers | Proper cross-origin support | + +### 3.3 WebSocket Transport + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| WS-001 | Connection establishment | Successful handshake | +| WS-002 | Message framing | Text frames, JSON content | +| WS-003 | Ping/pong | Keep-alive works | +| WS-004 | Close handling | Clean disconnect | +| WS-005 | Reconnection | State recovery | + +--- + +## 4. Security Testing + +### 4.1 Input Validation + +| Test ID | Test Case | Attack Vector | Expected | +|---------|-----------|---------------|----------| +| SEC-INP-001 | Path traversal | `../../../etc/passwd` | Blocked | +| SEC-INP-002 | Command injection | `; rm -rf /` | Sanitized | +| SEC-INP-003 | SQL injection | `' OR 1=1 --` | Escaped | +| SEC-INP-004 | XSS in output | `` | Escaped | +| SEC-INP-005 | XXE injection | External entity | Blocked | +| SEC-INP-006 | SSRF | `http://169.254.169.254/` | Blocked | + +### 4.2 Rate Limiting + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| SEC-RATE-001 | Normal usage | Allowed | +| SEC-RATE-002 | Exceed limit | 429 or error response | +| SEC-RATE-003 | Rate limit reset | Access restored after window | + +### 4.3 Fuzzing Targets + +```yaml +fuzzing_targets: + json_parsing: + tool: cargo-fuzz / atheris / jazzer + inputs: + - Malformed JSON + - Deeply nested objects + - Very long strings + - Invalid UTF-8 + + protocol_messages: + inputs: + - Random method names + - Random params structures + - Edge case values + + tool_arguments: + inputs: + - Generated per inputSchema + - Boundary values + - Type confusion +``` + +--- + +## 5. Performance Testing + +### 5.1 Latency Benchmarks + +| Metric | Target | Measurement | +|--------|--------|-------------| +| p50 latency | < 50ms | Median response time | +| p95 latency | < 200ms | 95th percentile | +| p99 latency | < 500ms | 99th percentile | +| Cold start | < 2s | First request after start | + +### 5.2 Throughput Benchmarks + +| Scenario | Target | Duration | +|----------|--------|----------| +| Sustained load | 100 req/s | 10 minutes | +| Peak load | 500 req/s | 1 minute | +| Burst | 1000 req/s | 10 seconds | + +### 5.3 Resource Usage + +| Metric | Idle | Under Load | Limit | +|--------|------|------------|-------| +| Memory | < 50MB | < 200MB | 512MB | +| CPU | < 1% | < 50% | 80% | +| Connections | 0 | < 100 | 1000 | + +--- + +## 6. Reliability Testing + +### 6.1 Error Handling + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| REL-ERR-001 | Tool throws exception | JSON-RPC error response | +| REL-ERR-002 | Resource not found | Proper error code | +| REL-ERR-003 | Network timeout | Error, not hang | +| REL-ERR-004 | Partial failure | Other tools still work | + +### 6.2 Graceful Shutdown + +| Test ID | Test Case | Expected | +|---------|-----------|----------| +| REL-SHUT-001 | SIGTERM | Pending requests complete | +| REL-SHUT-002 | SIGINT | Clean shutdown | +| REL-SHUT-003 | Shutdown timeout | Force terminate | + +### 6.3 Chaos Testing + +```yaml +chaos_scenarios: + network: + - Latency injection (100-500ms) + - Packet loss (1-10%) + - Connection reset + - DNS failure + + resource: + - CPU stress (90%) + - Memory pressure (80%) + - Disk full + - File descriptor exhaustion + + dependency: + - External API down + - Database unavailable + - Slow responses +``` + +--- + +## 7. Test Infrastructure + +### 7.1 Mock Harness Components + +``` +┌─────────────────────────────────────────────────────────────┐ +│ Test Execution │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌─────────────────────┼─────────────────────┐ + ▼ ▼ ▼ +┌───────────────┐ ┌───────────────┐ ┌───────────────┐ +│ Mock Servers │ │ Fixtures │ │ Recorders │ +│ - WireMock │ │ - Factories │ │ - VCR │ +│ - mockserver │ │ - Snapshots │ │ - Cassettes │ +│ - Prism │ │ - Seeds │ │ - Replay │ +└───────────────┘ └───────────────┘ └───────────────┘ +``` + +### 7.2 Test Data Factories + +| Language | Library | Usage | +|----------|---------|-------| +| Python | factory_boy | `UserFactory.build()` | +| TypeScript | fishery | `userFactory.build()` | +| Rust | fake | `Faker.fake::()` | + +--- + +## 8. Test Tooling by Language + +### 8.1 Rust + +```yaml +testing: + unit: cargo test + integration: cargo test --test '*' + coverage: cargo-llvm-cov, grcov + benchmarks: criterion + property: proptest + fuzzing: cargo-fuzz + mutation: cargo-mutants +``` + +### 8.2 Python + +```yaml +testing: + unit: pytest + integration: pytest-asyncio + coverage: coverage.py + benchmarks: pytest-benchmark + property: hypothesis + fuzzing: atheris + mutation: mutmut +``` + +### 8.3 TypeScript + +```yaml +testing: + unit: vitest, jest + integration: vitest + coverage: c8, istanbul + benchmarks: tinybench + property: fast-check + mutation: stryker +``` + +--- + +## 9. CI/CD Integration + +### 9.1 Quality Gates + +| Gate | Threshold | Enforcement | +|------|-----------|-------------| +| Unit test pass | 100% | Block merge | +| Coverage | > 70% | Block merge | +| Integration pass | 100% | Block merge | +| Security issues | 0 critical | Block merge | +| Performance regression | < 10% | Warning | + +--- + +## 10. External Resources + +### Evaluation Platforms + +- https://www.mcpevals.io/ +- https://www.mcpevals.ai/ +- https://mcp.scorecard.io/mcp + +### Testing Guides + +- https://mcpcat.io/guides/writing-unit-tests-mcp-servers/ +- https://testomat.io/blog/mcp-server-testing-tools/ + +### Benchmarks + +- https://deepwiki.com/modelscope/MCPBench/3.3-metrics-and-results diff --git a/.ai/plans/references/quick-start.md b/.ai/plans/references/quick-start.md new file mode 100644 index 0000000..5ab43ff --- /dev/null +++ b/.ai/plans/references/quick-start.md @@ -0,0 +1,266 @@ +--- +id: 0093b808-3915-460a-aed9-e60ea13f32e7 +title: "Quick Start Guide" +type: reference +--- + +# Bundle Expansion Quick Start Guide + +## Getting Started + +### Prerequisites + +1. Clone the repository: + ```bash + git clone https://github.com/aRustyDev/mcp.git + cd mcp + ``` + +2. Install tools: + ```bash + # Just (task runner) + brew install just # or cargo install just + + # Validation tools + brew install actionlint yamllint + ``` + +### Directory Structure + +``` +bundles/ +├── .github/ +│ ├── ISSUE_TEMPLATE/ # Issue templates +│ ├── workflows/ # GitHub Actions workflows +│ ├── labels.yml # Label definitions +│ ├── labeler.yml # Path-based labeler config +│ └── dependabot.yml # Dependency updates +├── configs/ +│ ├── .releaserc.json # Semantic release config +│ ├── codecov.yml # Coverage config +│ └── .gitleaks.toml # Secret scanning config +├── docs/ +│ └── ... # Documentation +├── justfile # Setup automation +└── MANIFEST.md # Bundle contents +``` + +--- + +## Development Workflow + +### 1. Create Placeholder Workflow + +```bash +# Create new workflow file +touch bundles/.github/workflows/my-workflow.yml +``` + +```yaml +# bundles/.github/workflows/my-workflow.yml +name: My Workflow + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + placeholder: + runs-on: ubuntu-latest + steps: + - name: Placeholder + run: echo "TODO: Implement" +``` + +### 2. Validate Workflow + +```bash +# Check syntax +actionlint bundles/.github/workflows/my-workflow.yml + +# Check YAML +yamllint bundles/.github/workflows/my-workflow.yml +``` + +### 3. Implement Workflow + +Use the phase guides for reference: +- Phase 01: Foundation - Templates, labels +- Phases 02-03: Build, lint +- Phases 04-13: Testing +- Phases 14-23: Security +- Phases 24-27: Release +- Phases 28-30: Automation + +### 4. Test Locally (optional) + +```bash +# Use act to test workflows locally +brew install act +act -j my-job-name +``` + +### 5. Update Tracking + +Update `checklists/implementation-tracking.md`: +```markdown +- [x] `my-workflow.yml` - Description +``` + +--- + +## Common Patterns + +### Path-Filtered Workflow + +```yaml +on: + push: + paths: + - 'src/**' + - 'Cargo.toml' + pull_request: + paths: + - 'src/**' +``` + +### Matrix Build + +```yaml +jobs: + build: + strategy: + matrix: + os: [ubuntu-latest, macos-latest] + version: ['3.10', '3.11', '3.12'] + runs-on: ${{ matrix.os }} +``` + +### Reusable Workflow + +```yaml +# In the bundle +on: + workflow_call: + inputs: + version: + type: string + default: 'latest' + +# In consuming repo +jobs: + call: + uses: aRustyDev/mcp/.github/workflows/reusable.yml@main + with: + version: '1.0.0' +``` + +### SARIF Upload (Security) + +```yaml +- name: Upload SARIF + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: results.sarif +``` + +### Caching + +```yaml +# Rust +- uses: Swatinem/rust-cache@v2 + +# Python +- uses: actions/setup-python@v5 + with: + cache: 'pip' + +# Node +- uses: actions/setup-node@v4 + with: + cache: 'npm' +``` + +--- + +## Workflow Categories + +### By Trigger + +| Trigger | Use Case | Example | +|---------|----------|---------| +| `push` | Main branch changes | Build, test | +| `pull_request` | PR validation | Lint, test | +| `schedule` | Periodic tasks | Security scan | +| `release` | Publishing | Deploy | +| `workflow_dispatch` | Manual runs | Debug | + +### By Purpose + +| Category | Workflows | +|----------|-----------| +| Build | build-*.yml | +| Lint | lint-*.yml | +| Test | test-*.yml | +| Security | security-*.yml, secret-scan.yml | +| Publish | publish-*.yml | +| Automation | stale-*.yml, triage.yml, welcome.yml | + +--- + +## Secrets Required + +| Secret | Workflows | Required For | +|--------|-----------|--------------| +| `GITHUB_TOKEN` | All | Built-in | +| `DOCKERHUB_USERNAME` | publish-container | Docker Hub | +| `DOCKERHUB_TOKEN` | publish-container | Docker Hub | +| `CARGO_REGISTRY_TOKEN` | publish-rust | crates.io | +| `NPM_TOKEN` | publish-node | npm | +| `SLACK_BOT_TOKEN` | notify-slack | Slack | +| `DISCORD_WEBHOOK` | notify-discord | Discord | +| `SNYK_TOKEN` | security-* | Snyk (optional) | +| `CLOUDFLARE_API_TOKEN` | publish-mdbook | Cloudflare | +| `OP_SVC_TOKEN` | Any | 1Password | + +--- + +## Validation Checklist + +Before committing: + +- [ ] `actionlint` passes +- [ ] `yamllint` passes +- [ ] File is in correct directory +- [ ] Permissions are correct +- [ ] Secrets are documented +- [ ] Tracking doc updated + +--- + +## Commands + +```bash +# Validate all workflows +just validate-workflows + +# Build bundle locally +just build-bundle + +# Test bundle installation +just test-bundle /tmp/test-repo + +# Update tracking +just update-tracking +``` + +--- + +## Resources + +- [GitHub Actions Docs](https://docs.github.com/en/actions) +- [Awesome Actions](https://github.com/sdras/awesome-actions) +- [actionlint](https://github.com/rhysd/actionlint) +- [act - Local Testing](https://github.com/nektos/act) From 89787bdb58411db1600603909583108747a0a8a5 Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:28:58 -0500 Subject: [PATCH 2/7] planning(bundle-contents): added plan docs for SAST --- .ai/docs/strategies/sarif-strategy.md | 741 ++++++++++++++++++ .ai/docs/strategies/sast-strategy.md | 533 +++++++++++++ .ai/plans/bundle-contents.md | 30 +- .../bundle-contents-phase-03-code-quality.md | 43 + .../bundle-contents-phase-16-security-sast.md | 501 ++++++++++-- ...undle-contents-phase-18-security-memory.md | 61 ++ ...ndle-contents-phase-19-security-fuzzing.md | 84 ++ ...bundle-contents-phase-20-security-taint.md | 496 +++++++++++- 8 files changed, 2391 insertions(+), 98 deletions(-) create mode 100644 .ai/docs/strategies/sarif-strategy.md create mode 100644 .ai/docs/strategies/sast-strategy.md diff --git a/.ai/docs/strategies/sarif-strategy.md b/.ai/docs/strategies/sarif-strategy.md new file mode 100644 index 0000000..7c8abae --- /dev/null +++ b/.ai/docs/strategies/sarif-strategy.md @@ -0,0 +1,741 @@ +--- +id: a9b8c7d6-e5f4-3a2b-1c0d-9e8f7a6b5c4d +title: "SARIF Strategy" +status: active +created: 2025-12-05 +type: strategy +related: + - sast-strategy.md + - policy-as-code.md +phases: + - 03 # Code Quality (SARIF output) + - 14 # Dependency Scanning + - 16 # Security - SAST + - 17 # Security - Secrets + - 18 # Security - Memory + - 19 # Security - Fuzzing + - 20 # Security - Taint + - 21 # Security - Containers +--- + +# SARIF Strategy + +## 1. Overview + +SARIF (Static Analysis Results Interchange Format) is the standard format for representing static analysis results. This strategy defines how to aggregate, deduplicate, enrich, and act on SARIF output from multiple security tools. + +### Goals + +1. **Unified View**: All findings in GitHub Security tab +2. **Deduplication**: No duplicate alerts from overlapping tools +3. **Enrichment**: Consistent metadata across tools +4. **Gating**: Automated merge blocking based on findings +5. **Tracking**: Trend analysis and metrics + +--- + +## 2. SARIF Fundamentals + +### Format Structure + +```json +{ + "$schema": "https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "semgrep", + "version": "1.50.0", + "rules": [...] + } + }, + "results": [ + { + "ruleId": "mcp-path-traversal", + "level": "error", + "message": { "text": "..." }, + "locations": [...], + "fingerprints": {...} + } + ] + } + ] +} +``` + +### Key Fields + +| Field | Purpose | Usage | +|-------|---------|-------| +| `ruleId` | Unique rule identifier | Deduplication, suppression | +| `level` | Severity (error/warning/note) | Gating decisions | +| `fingerprint` | Stable identifier for finding | Baseline comparison | +| `locations` | Code location | Developer navigation | +| `properties` | Custom metadata | Enrichment | + +--- + +## 3. Tool SARIF Support + +### Tools with Native SARIF Output + +| Tool | Phase | SARIF Support | Notes | +|------|-------|---------------|-------| +| Semgrep | 16, 20 | Native | `--sarif` flag | +| CodeQL | 16, 20 | Native | GitHub Actions default | +| Trivy | 14, 21 | Native | `--format sarif` | +| Gitleaks | 17 | Native | `--report-format sarif` | +| Hadolint | 03 | Native | `--format sarif` | +| Clippy | 03, 16 | Via converter | `clippy-sarif` | +| Bandit | 16 | Native | `--format sarif` | +| gosec | 16 | Native | `-fmt sarif` | +| ESLint | 03, 16 | Via plugin | `@microsoft/eslint-formatter-sarif` | +| Shellcheck | 03 | Via converter | `shellcheck-sarif` | +| Checkov | 21 | Native | `--output sarif` | + +### Tools Requiring SARIF Conversion + +```yaml +# Converters used in workflows +converters: + clippy-sarif: "https://github.com/psastras/sarif-rs" + cargo-audit-sarif: "https://github.com/pvillela/cargo-audit-sarif" + shellcheck-sarif: "https://github.com/aegistudio/shellcheck-sarif" + mypy-sarif: "Custom script" + pylint-sarif: "Custom script" +``` + +--- + +## 4. SARIF Workflow Architecture + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ SARIF PIPELINE │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ +│ │ Semgrep │ │ CodeQL │ │ Trivy │ │ Bandit │ │ Clippy │ │ +│ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ +│ │ │ │ │ │ │ +│ │ *.sarif files │ │ │ │ +│ └───────────┼───────────┼───────────┼───────────┘ │ +│ ↓ ↓ ↓ │ +│ ┌─────────────────────────────────┐ │ +│ │ SARIF MERGE │ │ +│ │ (sarif-multitool merge) │ │ +│ └───────────────┬─────────────────┘ │ +│ ↓ │ +│ ┌─────────────────────────────────┐ │ +│ │ DEDUPLICATION │ │ +│ │ (fingerprint-based) │ │ +│ └───────────────┬─────────────────┘ │ +│ ↓ │ +│ ┌─────────────────────────────────┐ │ +│ │ ENRICHMENT │ │ +│ │ (add CWE, CVSS, metadata) │ │ +│ └───────────────┬─────────────────┘ │ +│ ↓ │ +│ ┌─────────────────────────────────┐ │ +│ │ BASELINE COMPARISON │ │ +│ │ (identify new findings) │ │ +│ └───────────────┬─────────────────┘ │ +│ ↓ │ +│ ┌──────────────────────┼──────────────────────┐ │ +│ ↓ ↓ ↓ │ +│ ┌─────────┐ ┌─────────────┐ ┌──────────┐ │ +│ │ GitHub │ │ Quality │ │ Report │ │ +│ │Security │ │ Gate │ │Generator │ │ +│ │ Tab │ │ Decision │ │ │ │ +│ └─────────┘ └─────────────┘ └──────────┘ │ +│ │ │ +│ ┌─────────┴─────────┐ │ +│ ↓ ↓ │ +│ [PASS] [FAIL] │ +│ Continue PR Block Merge │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## 5. SARIF Aggregation + +### Merge Workflow + +```yaml +# .github/workflows/sarif-aggregate.yml +name: SARIF Aggregation + +on: + workflow_call: + inputs: + sarif_files: + description: 'Glob pattern for SARIF files' + type: string + default: '**/*.sarif' + +jobs: + aggregate: + runs-on: ubuntu-latest + steps: + - name: Download all SARIF artifacts + uses: actions/download-artifact@v4 + with: + pattern: sarif-* + path: sarif-results/ + merge-multiple: true + + - name: Setup SARIF tools + run: | + npm install -g @microsoft/sarif-multitool + + - name: Merge SARIF files + run: | + sarif-multitool merge sarif-results/*.sarif \ + --output-file merged.sarif \ + --force + + - name: Validate merged SARIF + run: | + sarif-multitool validate merged.sarif + + - name: Upload merged SARIF + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: merged.sarif + category: security-scan + + - name: Store for gating + uses: actions/upload-artifact@v4 + with: + name: merged-sarif + path: merged.sarif +``` + +### Tool-Specific SARIF Jobs + +Each tool uploads its own SARIF as an artifact: + +```yaml +# Example: Semgrep SARIF output +- name: Semgrep Scan + run: | + semgrep scan --config auto --sarif --output semgrep.sarif + +- name: Upload Semgrep SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-semgrep + path: semgrep.sarif +``` + +--- + +## 6. Deduplication Strategy + +### Deduplication Levels + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ DEDUPLICATION HIERARCHY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ LEVEL 1: SAME TOOL, SAME FILE, SAME LINE │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Method: Exact match on file path + line number + ruleId │ +│ Action: Keep single instance │ +│ │ +│ LEVEL 2: SAME FILE, SAME LINE, DIFFERENT TOOLS │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Method: Match on file path + line range overlap + CWE mapping │ +│ Action: Keep finding from PRIMARY tool, reference others │ +│ │ +│ LEVEL 3: SAME VULNERABILITY CLASS, DIFFERENT LOCATIONS │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Method: Pattern-based grouping (same CWE, same function) │ +│ Action: Group into single alert with multiple locations │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Tool Priority for Duplicates + +When multiple tools detect the same issue, keep the finding from: + +| Priority | Tool | Reason | +|----------|------|--------| +| 1 | CodeQL | Deepest analysis, best explanations | +| 2 | Semgrep | Good context, customizable | +| 3 | Language-specific (Bandit, gosec) | Domain expertise | +| 4 | Generic linters | Broadest but shallowest | + +### Deduplication Script + +```python +#!/usr/bin/env python3 +# scripts/sarif-dedup.py + +import json +import sys +from collections import defaultdict + +def fingerprint_result(result): + """Generate stable fingerprint for deduplication.""" + location = result.get('locations', [{}])[0] + physical = location.get('physicalLocation', {}) + artifact = physical.get('artifactLocation', {}).get('uri', '') + region = physical.get('region', {}) + + return f"{artifact}:{region.get('startLine', 0)}:{result.get('ruleId', '')}" + +def deduplicate_sarif(sarif_data): + """Deduplicate results across all runs.""" + seen = {} + + for run in sarif_data.get('runs', []): + tool_name = run.get('tool', {}).get('driver', {}).get('name', 'unknown') + deduped_results = [] + + for result in run.get('results', []): + fp = fingerprint_result(result) + + if fp not in seen: + seen[fp] = (tool_name, result) + deduped_results.append(result) + else: + # Add reference to duplicate + result.setdefault('properties', {})['duplicateOf'] = { + 'tool': seen[fp][0], + 'ruleId': seen[fp][1].get('ruleId') + } + + run['results'] = deduped_results + + return sarif_data + +if __name__ == '__main__': + sarif = json.load(sys.stdin) + deduped = deduplicate_sarif(sarif) + json.dump(deduped, sys.stdout, indent=2) +``` + +--- + +## 7. SARIF Enrichment + +### Enrichment Fields + +Add consistent metadata to all findings: + +```yaml +enrichment: + # CWE mapping + cwe: + source: rule metadata or manual mapping + format: "CWE-XXX" + + # CVSS score (if applicable) + cvss: + source: NVD or manual assessment + version: "3.1" + + # OWASP Top 10 + owasp: + source: rule metadata + format: "A01:2021" + + # Custom MCP metadata + mcp: + component: tools|resources|prompts|transport + severity_override: based on MCP context +``` + +### Enrichment Workflow + +```yaml +- name: Enrich SARIF + run: | + python scripts/sarif-enrich.py \ + --input merged.sarif \ + --output enriched.sarif \ + --cwe-mapping configs/sast/cwe-mapping.yaml \ + --severity-overrides configs/sast/severity-overrides.yaml +``` + +### CWE Mapping File + +```yaml +# configs/sast/cwe-mapping.yaml +rules: + # Semgrep rules + mcp-path-traversal: + cwe: CWE-22 + owasp: "A01:2021" + + mcp-command-injection: + cwe: CWE-78 + owasp: "A03:2021" + + # Bandit rules + B102: + cwe: CWE-78 + owasp: "A03:2021" + + B301: + cwe: CWE-502 + owasp: "A08:2021" +``` + +--- + +## 8. Baseline Management + +### Baseline Files + +``` +.sast-baseline/ +├── main.sarif # Baseline for main branch +├── baseline.json # Fingerprint index +└── history/ + └── 2025-01-01.sarif # Historical baselines +``` + +### Baseline Comparison Workflow + +```yaml +- name: Compare against baseline + run: | + python scripts/sarif-baseline.py \ + --current merged.sarif \ + --baseline .sast-baseline/main.sarif \ + --output new-findings.sarif \ + --stats baseline-stats.json + +- name: Report new findings only + if: hashFiles('new-findings.sarif') != '' + run: | + echo "## New Security Findings" >> $GITHUB_STEP_SUMMARY + python scripts/sarif-summary.py new-findings.sarif >> $GITHUB_STEP_SUMMARY +``` + +### Baseline Update Process + +```yaml +# On merge to main +- name: Update baseline + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + cp merged.sarif .sast-baseline/main.sarif + + # Archive historical baseline + DATE=$(date +%Y-%m-%d) + cp merged.sarif ".sast-baseline/history/${DATE}.sarif" + + git add .sast-baseline/ + git commit -m "chore: update SAST baseline" + git push +``` + +--- + +## 9. Quality Gate Implementation + +### Gate Decision Logic + +```python +#!/usr/bin/env python3 +# scripts/sarif-gate.py + +import json +import sys + +def evaluate_gate(sarif_data, config): + """Evaluate quality gate based on SARIF findings.""" + + blocking_findings = [] + warning_findings = [] + + for run in sarif_data.get('runs', []): + for result in run.get('results', []): + level = result.get('level', 'warning') + rule_id = result.get('ruleId', '') + + # Check CWE-based blocking + cwe = result.get('properties', {}).get('cwe', '') + if cwe in config['critical_cwes']: + blocking_findings.append(result) + continue + + # Check level-based blocking + if level == 'error': + blocking_findings.append(result) + elif level == 'warning': + warning_findings.append(result) + + return { + 'pass': len(blocking_findings) == 0, + 'blocking': blocking_findings, + 'warnings': warning_findings, + 'summary': { + 'blocking_count': len(blocking_findings), + 'warning_count': len(warning_findings) + } + } + +if __name__ == '__main__': + sarif = json.load(open(sys.argv[1])) + config = json.load(open(sys.argv[2])) + + result = evaluate_gate(sarif, config) + + print(json.dumps(result, indent=2)) + sys.exit(0 if result['pass'] else 1) +``` + +### Gate Configuration + +```yaml +# configs/sast/gate-config.yaml +pr_gate: + # Block on these severity levels + blocking_levels: + - error + + # Block on these CWEs regardless of level + critical_cwes: + - CWE-78 # Command Injection + - CWE-89 # SQL Injection + - CWE-94 # Code Injection + - CWE-22 # Path Traversal (for MCP) + + # Minimum confidence to block + min_confidence: high + + # Only consider new findings (vs baseline) + new_findings_only: true + +main_gate: + blocking_levels: + - error + - warning + + critical_cwes: + - CWE-78 + - CWE-89 + - CWE-94 + - CWE-22 + - CWE-502 # Deserialization + + min_confidence: medium + new_findings_only: false +``` + +### Gate Workflow + +```yaml +# .github/workflows/sarif-gate.yml +name: Security Gate + +on: + workflow_call: + +jobs: + gate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Download merged SARIF + uses: actions/download-artifact@v4 + with: + name: merged-sarif + + - name: Evaluate gate + id: gate + run: | + python scripts/sarif-gate.py \ + merged.sarif \ + configs/sast/gate-config.yaml \ + > gate-result.json + + PASS=$(jq -r '.pass' gate-result.json) + echo "pass=$PASS" >> $GITHUB_OUTPUT + + if [ "$PASS" = "false" ]; then + echo "## Security Gate Failed" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + jq -r '.blocking[] | "- **\(.ruleId)**: \(.message.text)"' gate-result.json >> $GITHUB_STEP_SUMMARY + fi + + - name: Fail if blocking findings + if: steps.gate.outputs.pass == 'false' + run: exit 1 +``` + +--- + +## 10. GitHub Security Integration + +### Upload Strategy + +```yaml +# Single upload for merged results +- name: Upload to GitHub Security + uses: github/codeql-action/upload-sarif@v3 + with: + sarif_file: merged.sarif + category: mcp-security-scan + wait-for-processing: true +``` + +### Categories + +Use categories to organize findings: + +| Category | Tools | Purpose | +|----------|-------|---------| +| `sast-pattern` | Semgrep, linters | Pattern-based findings | +| `sast-dataflow` | CodeQL, Pysa | Dataflow findings | +| `dependency` | Trivy, cargo-audit | Dependency vulnerabilities | +| `secrets` | Gitleaks | Secret detection | +| `container` | Trivy, Checkov | Container security | + +### Alert Dismissal + +Configure default dismissal reasons: + +```yaml +# .github/security-advisories.yml +dismissal_reasons: + false_positive: "Finding is incorrect" + wont_fix: "Accepted risk, documented in issue" + used_in_tests: "Only used in test code" + mitigated: "Mitigated by other controls" +``` + +--- + +## 11. Reporting + +### PR Summary Report + +```yaml +- name: Generate PR summary + run: | + python scripts/sarif-report.py \ + --sarif merged.sarif \ + --format github-summary \ + >> $GITHUB_STEP_SUMMARY +``` + +### Summary Format + +```markdown +## Security Scan Results + +### Summary +| Severity | Count | Status | +|----------|-------|--------| +| Critical | 0 | :white_check_mark: | +| High | 2 | :x: Blocking | +| Medium | 5 | :warning: | +| Low | 12 | :information_source: | + +### Blocking Findings (2) + +#### 1. Command Injection in tool handler +- **Rule**: mcp-command-injection +- **File**: `src/tools/shell.py:45` +- **CWE**: CWE-78 + +
+Details + +Tool arguments flow to subprocess without sanitization. + +```python +subprocess.run(args["command"], shell=True) # Line 45 +``` + +**Remediation**: Use `shlex.split()` and avoid `shell=True`. +
+ +### Warnings (5) +[Collapsed by default...] +``` + +### Trend Report + +Weekly trend report for security dashboard: + +```yaml +# .github/workflows/security-report.yml +name: Weekly Security Report + +on: + schedule: + - cron: '0 9 * * 1' # Monday 9 AM + +jobs: + report: + runs-on: ubuntu-latest + steps: + - name: Generate trend report + run: | + python scripts/sarif-trend.py \ + --baseline-dir .sast-baseline/history/ \ + --output trend-report.md + + - name: Post to Slack/Discord + uses: slackapi/slack-github-action@v1 + with: + payload-file-path: trend-report.json +``` + +--- + +## 12. Tooling Reference + +### sarif-multitool Commands + +```bash +# Merge multiple SARIF files +sarif-multitool merge a.sarif b.sarif --output merged.sarif + +# Validate SARIF format +sarif-multitool validate merged.sarif + +# Convert formats +sarif-multitool convert --input result.json --output result.sarif --tool semgrep + +# Query SARIF +sarif-multitool query --expression "runs[*].results[?level=='error']" merged.sarif +``` + +### jq Queries for SARIF + +```bash +# Count findings by severity +jq '[.runs[].results[].level] | group_by(.) | map({key: .[0], count: length})' merged.sarif + +# List all rule IDs +jq '[.runs[].results[].ruleId] | unique' merged.sarif + +# Get findings for specific file +jq '.runs[].results[] | select(.locations[0].physicalLocation.artifactLocation.uri | contains("handler.py"))' merged.sarif + +# Extract fingerprints +jq '.runs[].results[] | {ruleId, fingerprint: .fingerprints}' merged.sarif +``` + +--- + +## 13. Related Documents + +- [SAST Strategy](sast-strategy.md) - Tool selection and phase boundaries +- [Policy-as-Code Strategy](policy-as-code.md) - OPA/Rego policy enforcement +- Phase 16: Pattern-based SAST implementation +- Phase 20: Dataflow analysis implementation diff --git a/.ai/docs/strategies/sast-strategy.md b/.ai/docs/strategies/sast-strategy.md new file mode 100644 index 0000000..f194777 --- /dev/null +++ b/.ai/docs/strategies/sast-strategy.md @@ -0,0 +1,533 @@ +--- +id: f1a2b3c4-d5e6-7f8a-9b0c-1d2e3f4a5b6c +title: "SAST Strategy" +status: active +created: 2025-12-05 +type: strategy +related: + - sarif-strategy.md + - policy-as-code.md +phases: + - 03 # Code Quality + - 16 # Security - SAST + - 18 # Security - Memory + - 19 # Security - Fuzzing + - 20 # Security - Taint +--- + +# SAST Strategy + +## 1. Overview + +This document defines the Static Application Security Testing (SAST) strategy for the MCP bundle. It establishes tool responsibilities, phase boundaries, severity mappings, and quality gates to ensure comprehensive security coverage without duplicate findings or unclear ownership. + +### Goals + +1. **Clear Ownership**: Each tool has defined responsibilities +2. **No Duplication**: Findings deduplicated across tools +3. **Fast Feedback**: Quick PR checks with deep scheduled analysis +4. **MCP Focus**: Custom rules for MCP-specific vulnerabilities +5. **Actionable Results**: Low false positive rate, clear remediation + +--- + +## 2. Tool Selection Philosophy + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ TOOL SELECTION CRITERIA │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PRIMARY SELECTION FACTORS │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ 1. Language Coverage - Does it support our language stack? │ +│ 2. Analysis Depth - Pattern vs semantic vs dataflow? │ +│ 3. Customizability - Can we write MCP-specific rules? │ +│ 4. SARIF Output - Can results go to GitHub Security tab? │ +│ 5. Speed - Fast enough for PR checks? │ +│ │ +│ SECONDARY FACTORS │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ 6. False Positive Rate - Acceptable noise level? │ +│ 7. Community Rules - Existing rule packs available? │ +│ 8. CI Integration - GitHub Actions support? │ +│ 9. Cost - Free tier sufficient? │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Selected Tools + +| Tool | Role | Strengths | Limitations | +|------|------|-----------|-------------| +| **Semgrep** | Pattern SAST | Fast, custom rules, multi-language | Limited dataflow (Pro only) | +| **CodeQL** | Semantic SAST | Deep analysis, dataflow, GitHub native | Slower, build required | +| **Clippy** | Rust SAST | Deep Rust knowledge, unsafe detection | Rust only | +| **Bandit** | Python SAST | Python-specific patterns | Pattern-only | +| **gosec** | Go SAST | Go-specific patterns | Pattern-only | +| **cargo-geiger** | Unsafe audit | Counts unsafe code | Rust only | +| **Pysa** | Python taint | Facebook-grade taint analysis | Complex setup | +| **Miri** | Rust memory | Undefined behavior detection | Slow, nightly only | + +--- + +## 3. Phase Boundaries + +Clear separation of concerns between phases prevents duplicate work and unclear ownership. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE RESPONSIBILITIES │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHASE 03: CODE QUALITY │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Focus: Style, formatting, complexity, non-security lints │ +│ Tools: Linters in "quality" mode (not security) │ +│ NOT: Security vulnerabilities, unsafe code │ +│ │ +│ Examples: │ +│ ✓ clippy::complexity, clippy::style │ +│ ✓ ruff format checking, import sorting │ +│ ✓ eslint style rules │ +│ ✗ clippy::suspicious (→ Phase 16) │ +│ ✗ bandit security checks (→ Phase 16) │ +│ │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHASE 16: PATTERN SAST │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Focus: Pattern-based security detection, fast PR feedback │ +│ Tools: Semgrep patterns, security lints, cargo-geiger │ +│ NOT: Dataflow analysis, deep semantic analysis │ +│ │ +│ Examples: │ +│ ✓ Semgrep security-audit ruleset │ +│ ✓ clippy::suspicious, clippy::correctness │ +│ ✓ bandit, gosec pattern detection │ +│ ✓ MCP-specific Semgrep patterns │ +│ ✗ CodeQL dataflow queries (→ Phase 20) │ +│ ✗ Pysa taint tracking (→ Phase 20) │ +│ │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHASE 18: MEMORY SAFETY │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Focus: Runtime memory safety, undefined behavior │ +│ Tools: Miri, sanitizers (ASan, MSan, TSan), Valgrind │ +│ NOT: Pattern detection, static analysis │ +│ │ +│ Examples: │ +│ ✓ Miri undefined behavior detection │ +│ ✓ AddressSanitizer buffer overflow detection │ +│ ✓ ThreadSanitizer race condition detection │ +│ ✗ Static unsafe code counting (→ Phase 16 cargo-geiger) │ +│ │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHASE 19: FUZZING │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Focus: Dynamic input fuzzing, crash discovery │ +│ Tools: cargo-fuzz, AFL++, Schemathesis, Atheris │ +│ NOT: Static analysis, deterministic testing │ +│ │ +│ Examples: │ +│ ✓ Protocol parser fuzzing │ +│ ✓ API endpoint fuzzing │ +│ ✓ MCP JSON-RPC message fuzzing │ +│ ✗ Static vulnerability detection (→ Phases 16, 20) │ +│ │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHASE 20: DATAFLOW/TAINT ANALYSIS │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Focus: Data flow tracking, source-to-sink analysis │ +│ Tools: CodeQL dataflow, Semgrep taint mode, Pysa │ +│ NOT: Pattern matching, memory safety │ +│ │ +│ Examples: │ +│ ✓ CodeQL taint tracking queries │ +│ ✓ MCP tool input → file operation tracking │ +│ ✓ Pysa source/sink definitions │ +│ ✗ Simple pattern matching (→ Phase 16) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Phase Execution Order + +``` +Code Quality (03) → Pattern SAST (16) → Memory (18) → Fuzzing (19) → Taint (20) + ↓ ↓ ↓ ↓ ↓ + Style/Lint Patterns Runtime Dynamic Dataflow + (Every PR) (Every PR) (Weekly) (Daily) (Weekly) +``` + +--- + +## 4. Tool Responsibility Matrix + +### By Vulnerability Class + +| Vulnerability | Primary Tool | Secondary Tool | Phase | +|---------------|--------------|----------------|-------| +| SQL Injection | CodeQL | Semgrep | 20, 16 | +| Command Injection | Semgrep | CodeQL | 16, 20 | +| Path Traversal | Semgrep | CodeQL | 16, 20 | +| XSS | Semgrep | CodeQL | 16, 20 | +| SSRF | CodeQL | Semgrep | 20, 16 | +| Unsafe Deserialization | Bandit/Semgrep | CodeQL | 16, 20 | +| Hardcoded Secrets | Gitleaks | Semgrep | 17, 16 | +| Buffer Overflow | Miri/Sanitizers | - | 18 | +| Use After Free | Miri/Sanitizers | - | 18 | +| Data Races | ThreadSanitizer | - | 18 | +| Unsafe Rust | cargo-geiger | Clippy | 16 | +| MCP Tool Injection | Semgrep MCP rules | CodeQL | 16, 20 | + +### By Language + +| Language | Phase 16 (Pattern) | Phase 20 (Dataflow) | Phase 18 (Memory) | +|----------|-------------------|---------------------|-------------------| +| Rust | Clippy, cargo-geiger, Semgrep | CodeQL* | Miri, sanitizers | +| Python | Bandit, Semgrep | CodeQL, Pysa | - | +| Go | gosec, Semgrep | CodeQL | - | +| JavaScript | ESLint security, Semgrep | CodeQL | - | +| TypeScript | ESLint security, Semgrep | CodeQL | - | + +*CodeQL Rust support is limited; rely primarily on Clippy + Miri. + +--- + +## 5. MCP-Specific Security Rules + +All MCP-specific rules are centralized in `configs/semgrep/rules/mcp/`. + +### Rule Categories + +``` +configs/semgrep/rules/mcp/ +├── injection/ +│ ├── path-traversal.yaml # Resource URI path injection +│ ├── command-injection.yaml # Tool → subprocess flows +│ └── sql-injection.yaml # Tool → database flows +├── protocol/ +│ ├── json-rpc-validation.yaml # JSON-RPC message validation +│ ├── capability-check.yaml # Missing capability enforcement +│ └── transport-security.yaml # Transport layer issues +├── taint/ +│ ├── tool-sources.yaml # Tool argument sources +│ ├── resource-sources.yaml # Resource URI sources +│ └── dangerous-sinks.yaml # File, subprocess, network sinks +└── mcp-all.yaml # Aggregates all MCP rules +``` + +### Rule Ownership + +| Rule Category | Created In | Used By | +|---------------|------------|---------| +| `injection/` | Phase 16 | Phase 16, 20 | +| `protocol/` | Phase 16 | Phase 16, 19 | +| `taint/` | Phase 20 | Phase 20 | + +### Example MCP Rule Structure + +```yaml +# configs/semgrep/rules/mcp/injection/path-traversal.yaml +rules: + - id: mcp-path-traversal-resource + message: | + Resource URI contains path traversal sequence. + MCP resource handlers must validate URIs before filesystem access. + severity: ERROR + languages: [python, javascript, typescript] + metadata: + category: security + subcategory: path-traversal + cwe: CWE-22 + owasp: A01:2021 + mcp-component: resources + confidence: HIGH + likelihood: HIGH + impact: HIGH + references: + - https://spec.modelcontextprotocol.io/specification/server/resources/ + patterns: + - pattern-either: + - pattern: | + def read_resource($URI, ...): + ... + open($PATH, ...) + - pattern: | + async def read_resource($URI, ...): + ... + open($PATH, ...) + - metavariable-regex: + metavariable: $PATH + regex: '.*\.\./.*' +``` + +--- + +## 6. Severity Mapping + +Unified severity across all tools for consistent gating. + +### Severity Levels + +| Level | Description | Gate Action | +|-------|-------------|-------------| +| **CRITICAL** | Exploitable, high impact | Block merge | +| **HIGH** | Likely exploitable | Block merge | +| **MEDIUM** | Potential vulnerability | Warning | +| **LOW** | Best practice violation | Info only | +| **INFO** | Informational finding | Info only | + +### Tool-to-Unified Mapping + +| Tool | Tool Severity | Unified Severity | +|------|---------------|------------------| +| Semgrep | ERROR | CRITICAL/HIGH | +| Semgrep | WARNING | MEDIUM | +| Semgrep | INFO | LOW | +| CodeQL | error | CRITICAL/HIGH | +| CodeQL | warning | MEDIUM | +| CodeQL | note | LOW | +| Clippy | deny | HIGH | +| Clippy | warn | MEDIUM | +| Clippy | allow | INFO | +| Bandit | HIGH | HIGH | +| Bandit | MEDIUM | MEDIUM | +| Bandit | LOW | LOW | + +### CWE-Based Severity Override + +Certain CWEs always map to specific severities regardless of tool confidence: + +```yaml +# configs/sast/severity-overrides.yaml +critical_cwes: + - CWE-78 # OS Command Injection + - CWE-89 # SQL Injection + - CWE-94 # Code Injection + - CWE-502 # Deserialization of Untrusted Data + +high_cwes: + - CWE-22 # Path Traversal + - CWE-79 # XSS + - CWE-918 # SSRF + - CWE-434 # Unrestricted Upload +``` + +--- + +## 7. Quality Gates + +### PR Gate (Fast) + +Runs on every PR, must complete in < 5 minutes. + +```yaml +pr_gate: + tools: + - semgrep (p/security-audit + MCP rules) + - clippy --deny warnings (security categories only) + - bandit (high confidence only) + + blocking: + - severity >= HIGH + - any CRITICAL/HIGH CWE + + warning: + - severity == MEDIUM + + timeout: 5m +``` + +### Main Branch Gate (Thorough) + +Runs on push to main, can take longer. + +```yaml +main_gate: + tools: + - semgrep (full ruleset) + - codeql (security-extended) + - cargo-geiger + - pysa (if Python) + + blocking: + - severity >= MEDIUM with HIGH confidence + - new findings only (baseline comparison) + + timeout: 30m +``` + +### Scheduled Deep Scan + +Runs weekly, comprehensive analysis. + +```yaml +scheduled_scan: + tools: + - codeql (security-and-quality) + - semgrep (all rules including experimental) + - miri + - sanitizers + + actions: + - create_issues_for_high_severity + - update_security_dashboard + - generate_trend_report + + schedule: "0 5 * * 1" # Weekly Monday 5AM +``` + +--- + +## 8. Baseline and Suppression Management + +### Baseline Strategy + +New findings only approach for existing codebases. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ BASELINE WORKFLOW │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. INITIAL BASELINE │ +│ └── Run full scan on main branch │ +│ └── Store results as baseline in .sast-baseline/ │ +│ │ +│ 2. PR COMPARISON │ +│ └── Run scan on PR branch │ +│ └── Compare against baseline │ +│ └── Report NEW findings only │ +│ │ +│ 3. BASELINE UPDATE │ +│ └── After merge to main, update baseline │ +│ └── Track baseline drift over time │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Suppression Files + +``` +.semgrepignore # Semgrep path exclusions +.codeql/ # CodeQL configuration + └── queries/ + └── excludes.qll # CodeQL query exclusions +configs/sast/ + └── suppressions.yaml # Unified suppression list +``` + +### Suppression Format + +```yaml +# configs/sast/suppressions.yaml +suppressions: + - id: mcp-path-traversal-resource + file: src/legacy/old_handler.py + reason: "Legacy code, tracked in issue #123" + expires: 2025-03-01 + approved_by: security-team + + - id: bandit-B101 + file: tests/** + reason: "Assert statements acceptable in tests" + expires: never +``` + +### Suppression Review Process + +1. All suppressions require `approved_by` field +2. Suppressions with `expires` are auto-removed after date +3. Monthly review of all suppressions +4. Suppressions tracked in security dashboard + +--- + +## 9. Workflow Integration + +### Unified SAST Workflow + +See [SARIF Strategy](sarif-strategy.md) for result aggregation. + +```yaml +# .github/workflows/sast.yml (simplified) +name: SAST + +on: + pull_request: + push: + branches: [main] + +jobs: + # Fast pattern checks + semgrep: + uses: ./.github/workflows/sast-semgrep.yml + + # Language-specific security lints + security-lints: + uses: ./.github/workflows/sast-lints.yml + + # Deep analysis (main only) + codeql: + if: github.ref == 'refs/heads/main' + uses: ./.github/workflows/sast-codeql.yml + + # Aggregate and gate + gate: + needs: [semgrep, security-lints] + uses: ./.github/workflows/sarif-gate.yml +``` + +--- + +## 10. Metrics and Reporting + +### Key Metrics + +| Metric | Target | Measured By | +|--------|--------|-------------| +| False Positive Rate | < 10% | Manual review sampling | +| Mean Time to Fix (MTTF) | < 7 days for HIGH | Issue tracking | +| Coverage | 100% of languages | Tool matrix | +| Scan Time (PR) | < 5 minutes | Workflow duration | +| Baseline Drift | < 5% monthly | Baseline comparison | + +### Dashboard Requirements + +- Findings by severity over time +- Findings by vulnerability class +- Tool effectiveness comparison +- Fix rate trends +- Coverage gaps + +--- + +## 11. Migration Guide + +### From No SAST + +1. Implement Phase 16 (Pattern SAST) first +2. Create baseline from initial scan +3. Enable PR blocking for HIGH/CRITICAL only +4. Gradually add Phase 20 (Dataflow) + +### From Existing Tools + +1. Map existing tools to phase responsibilities +2. Consolidate overlapping rules +3. Migrate to unified SARIF workflow +4. Update suppression format + +--- + +## 12. Related Documents + +- [SARIF Strategy](sarif-strategy.md) - Result aggregation and gating +- [Policy-as-Code Strategy](policy-as-code.md) - OPA/Rego policy enforcement +- Phase 16: Pattern-based SAST implementation +- Phase 20: Dataflow analysis implementation diff --git a/.ai/plans/bundle-contents.md b/.ai/plans/bundle-contents.md index e7350b5..258d1a1 100644 --- a/.ai/plans/bundle-contents.md +++ b/.ai/plans/bundle-contents.md @@ -263,10 +263,33 @@ bundles/ │ │ └── global/ # Global config templates (manual install) │ │ ├── common-servers.json │ │ └── install.sh +│ ├── semgrep/ # Semgrep configurations (Phases 16, 20) +│ │ └── rules/ +│ │ └── mcp/ # MCP-specific security rules +│ │ ├── injection/ # Pattern-based injection rules (Phase 16) +│ │ ├── protocol/ # Protocol validation rules (Phase 16) +│ │ └── taint/ # Taint tracking rules (Phase 20) +│ ├── sast/ # SAST configuration (Phases 16, 20) +│ │ ├── gate-config.yaml # Quality gate thresholds +│ │ ├── suppressions.yaml # Finding suppressions +│ │ ├── severity-overrides.yaml # CWE severity mapping +│ │ └── cwe-mapping.yaml # Rule-to-CWE mapping │ ├── .releaserc.json # Semantic release (Phase 24) │ ├── codecov.yml # Coverage config (Phase 09) │ ├── .gitleaks.toml # Secret scanning (Phase 17) │ └── ... # Tool configurations +├── .codeql/ # CodeQL configuration (Phase 20) +│ ├── codeql-config.yml # Query configuration +│ └── queries/ +│ └── mcp/ # Custom MCP dataflow queries +├── scripts/ # Utility scripts (various phases) +│ ├── sarif-dedup.py # SARIF deduplication (Phase 16, 20) +│ ├── sarif-gate.py # Quality gate evaluation (Phase 16) +│ ├── sarif-baseline.py # Baseline comparison (Phase 16) +│ ├── sarif-report.py # Report generation (Phase 16) +│ ├── miri-to-sarif.py # Miri SARIF converter (Phase 18) +│ ├── fuzz-crashes-to-sarif.py # Fuzz crash SARIF converter (Phase 19) +│ └── pysa-to-sarif.py # Pysa SARIF converter (Phase 20) ├── docs/ │ └── ... # Documentation ├── justfile # Setup automation @@ -294,6 +317,8 @@ bundles/ ### Strategies - [AI Context Strategy](../docs/strategies/ai-context.md) - AGENT.md and AI agent behavioral guidance - [Policy-as-Code Strategy](../docs/strategies/policy-as-code.md) - OPA/Rego unified policy library +- [SAST Strategy](../docs/strategies/sast-strategy.md) - Static analysis tool selection, phase boundaries, and quality gates +- [SARIF Strategy](../docs/strategies/sarif-strategy.md) - SARIF aggregation, deduplication, and GitHub Security integration - [Tagging and Versioning Strategy](../docs/strategies/tagging-and-versioning.md) - Version source of truth and release coordination --- @@ -321,8 +346,11 @@ bundles/ | Release | 24-27 | ~20 | | Automation | 28-30 | ~11 | -**Total Estimated: ~207 workflow/config/policy files** +**Total Estimated: ~230 workflow/config/policy files** *Notes:* - *Foundation includes +9 MCP client config files (5 project-local, 4 global)* - *Security includes +15 OPA/Rego policy files from Phase 22a policy library* +- *Security includes +15 Semgrep rules for MCP patterns and taint tracking (Phases 16, 20)* +- *Security includes +7 SARIF utility scripts and +4 SAST configuration files* +- *Security includes +3 CodeQL custom queries for MCP (Phase 20)* diff --git a/.ai/plans/phases/bundle-contents-phase-03-code-quality.md b/.ai/plans/phases/bundle-contents-phase-03-code-quality.md index 7fcbcd0..46d4242 100644 --- a/.ai/plans/phases/bundle-contents-phase-03-code-quality.md +++ b/.ai/plans/phases/bundle-contents-phase-03-code-quality.md @@ -8,6 +8,8 @@ checklists: - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking references: - linting-strategy-adr # ADR in ../docs/adr/ + - ../../docs/strategies/sast-strategy.md # Phase boundaries + - ../../docs/strategies/sarif-strategy.md # SARIF aggregation issues: [] --- @@ -80,6 +82,47 @@ Establish comprehensive code quality checks using a hybrid approach: pre-commit - Test execution (Phase 04+) - Helm chart linting (Phase 27) +### Phase Boundary with SAST (Phase 16) + +> **See**: [SAST Strategy](../../docs/strategies/sast-strategy.md) for detailed phase boundaries. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 03 vs PHASE 16 BOUNDARY │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ PHASE 03: CODE QUALITY (This Phase) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✓ clippy::complexity, clippy::style, clippy::perf │ +│ ✓ ruff formatting, import sorting, line length │ +│ ✓ eslint style rules, prettier formatting │ +│ ✓ golangci-lint style linters │ +│ ✓ Config file validation (TOML, YAML, JSON) │ +│ ✓ Spelling, commit messages, actionlint │ +│ │ +│ PHASE 16: SECURITY SAST (Defer To) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✗ clippy::suspicious, clippy::correctness (security implications) │ +│ ✗ cargo-geiger (unsafe code audit) │ +│ ✗ bandit, gosec (security scanners) │ +│ ✗ eslint-plugin-security │ +│ ✗ Semgrep security rulesets │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### SARIF Output Strategy + +> **See**: [SARIF Strategy](../../docs/strategies/sarif-strategy.md) for aggregation details. + +Tools in this phase that support SARIF output: +- hadolint (Dockerfile linting) +- clippy (via clippy-sarif converter) +- shellcheck (via shellcheck-sarif converter) +- eslint (via @microsoft/eslint-formatter-sarif) + +SARIF files from this phase are uploaded as artifacts for aggregation in the unified security pipeline. + --- ## 3. Implementation diff --git a/.ai/plans/phases/bundle-contents-phase-16-security-sast.md b/.ai/plans/phases/bundle-contents-phase-16-security-sast.md index 2c5f22c..5c85e19 100644 --- a/.ai/plans/phases/bundle-contents-phase-16-security-sast.md +++ b/.ai/plans/phases/bundle-contents-phase-16-security-sast.md @@ -6,6 +6,9 @@ depends_on: - 998f42c0-584d-4dcb-8b02-07116f0f03e3 # phase-15 checklists: - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - ../../docs/strategies/sast-strategy.md # SAST tool selection and boundaries + - ../../docs/strategies/sarif-strategy.md # SARIF aggregation issues: [] --- @@ -20,43 +23,78 @@ issues: [] ### Existing Assets -Clippy security lints (Phase 03) provide some Rust coverage. +Clippy quality lints (Phase 03) provide style checking; security lints move here. ### Gaps Identified -- [ ] security-sast.yml (unified SAST) -- [ ] Semgrep custom rules -- [ ] CodeQL query packs -- [ ] SARIF aggregation -- [ ] Language-specific SAST workflows +- [ ] security-sast.yml (unified pattern SAST) +- [ ] security-sast-rust.yml (Rust-specific) +- [ ] security-sast-python.yml (Python-specific) +- [ ] security-sast-go.yml (Go-specific) +- [ ] MCP-specific Semgrep rules (in configs/semgrep/rules/mcp/) +- [ ] SARIF aggregation workflow +- [ ] Baseline management --- ## 2. Contextual Goal -Implement comprehensive static application security testing using Semgrep and CodeQL. Create custom rules for MCP-specific patterns, aggregate SARIF results to GitHub Security tab, and provide language-specific security analysis for Rust, Python, Go, and JavaScript. Focus on vulnerability detection without generating excessive false positives. +Implement **pattern-based** static application security testing using Semgrep and language-specific tools. This phase focuses on fast, deterministic pattern matching suitable for PR checks. Deep dataflow analysis is deferred to Phase 20. + +> **See**: [SAST Strategy](../../docs/strategies/sast-strategy.md) for tool selection rationale and phase boundaries. ### Success Criteria -- [ ] Unified SAST workflow with Semgrep + CodeQL +- [ ] Unified SAST workflow with Semgrep +- [ ] Language-specific security lint workflows - [ ] MCP-specific Semgrep rules created -- [ ] SARIF results appear in Security tab -- [ ] False positive rate acceptable -- [ ] Custom query packs for each language +- [ ] SARIF results aggregated and uploaded +- [ ] PR gate blocks on HIGH/CRITICAL findings +- [ ] False positive rate < 10% ### Out of Scope -- DAST (runtime testing) +- Dataflow/taint analysis (Phase 20) +- Memory safety analysis (Phase 18) - Fuzzing (Phase 19) +- DAST/runtime testing + +### Phase Boundary + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 16 RESPONSIBILITIES │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ IN SCOPE (Pattern-Based SAST) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✓ Semgrep security-audit ruleset │ +│ ✓ Semgrep custom MCP patterns │ +│ ✓ clippy::suspicious, clippy::correctness │ +│ ✓ cargo-geiger (unsafe code audit) │ +│ ✓ bandit (Python patterns) │ +│ ✓ gosec (Go patterns) │ +│ ✓ eslint-plugin-security │ +│ │ +│ OUT OF SCOPE (Deferred to Other Phases) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✗ CodeQL dataflow queries → Phase 20 │ +│ ✗ Semgrep taint mode → Phase 20 │ +│ ✗ Pysa taint tracking → Phase 20 │ +│ ✗ Miri/sanitizers → Phase 18 │ +│ ✗ Fuzzing → Phase 19 │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` --- ## 3. Implementation -### 3.1 security-sast.yml +### 3.1 security-sast.yml (Unified Pattern SAST) ```yaml -name: SAST +name: Pattern SAST on: push: @@ -67,6 +105,7 @@ on: jobs: semgrep: + name: Semgrep Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -76,80 +115,430 @@ jobs: with: config: >- p/security-audit - p/rust - p/python - p/javascript - .semgrep/ + p/secrets + p/owasp-top-ten + configs/semgrep/rules/mcp/ generateSarif: true - - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v3 + - name: Upload Semgrep SARIF + uses: actions/upload-artifact@v4 with: - sarif_file: semgrep.sarif + name: sarif-semgrep + path: semgrep.sarif + + # Aggregate SARIF from all jobs + aggregate: + needs: [semgrep] + uses: ./.github/workflows/sarif-aggregate.yml + + # Quality gate + gate: + needs: [aggregate] + uses: ./.github/workflows/sarif-gate.yml + with: + gate_config: pr # or 'main' for push to main +``` + +### 3.2 security-sast-rust.yml + +```yaml +name: Rust Security SAST + +on: + push: + branches: [main] + paths: ['**.rs', 'Cargo.toml', 'Cargo.lock'] + pull_request: + paths: ['**.rs', 'Cargo.toml', 'Cargo.lock'] - codeql: +jobs: + clippy-security: + name: Clippy Security Lints runs-on: ubuntu-latest - permissions: - security-events: write + steps: + - uses: actions/checkout@v4 + + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy + + - uses: Swatinem/rust-cache@v2 + + - name: Clippy Security Analysis + run: | + cargo clippy --all-targets --all-features -- \ + -D clippy::suspicious \ + -D clippy::correctness \ + -W clippy::nursery \ + 2>&1 | tee clippy-output.txt - strategy: - matrix: - language: [python, javascript] + - name: Convert to SARIF + run: | + cargo install clippy-sarif sarif-fmt + cat clippy-output.txt | clippy-sarif > clippy.sarif + - name: Upload Clippy SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-clippy + path: clippy.sarif + + cargo-geiger: + name: Unsafe Code Audit + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + - uses: dtolnay/rust-toolchain@stable + + - name: Install cargo-geiger + run: cargo install cargo-geiger + + - name: Run cargo-geiger + run: | + cargo geiger --all-features --output-format Json > geiger.json + + - name: Check unsafe thresholds + run: | + # Parse geiger.json and check thresholds + UNSAFE_COUNT=$(jq '.packages[].unsafety.used.functions.unsafe' geiger.json | grep -v null | paste -sd+ | bc) + echo "Total unsafe functions: $UNSAFE_COUNT" + + if [ "$UNSAFE_COUNT" -gt "${UNSAFE_THRESHOLD:-10}" ]; then + echo "::warning::Unsafe function count ($UNSAFE_COUNT) exceeds threshold" + fi + + - name: Upload geiger report + uses: actions/upload-artifact@v4 + with: + name: cargo-geiger-report + path: geiger.json +``` + +### 3.3 security-sast-python.yml + +```yaml +name: Python Security SAST + +on: + push: + branches: [main] + paths: ['**.py', 'pyproject.toml', 'requirements*.txt'] + pull_request: + paths: ['**.py', 'pyproject.toml', 'requirements*.txt'] + +jobs: + bandit: + name: Bandit Security Scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Bandit + run: pip install bandit[sarif] + + - name: Run Bandit + run: | + bandit -r . \ + --format sarif \ + --output bandit.sarif \ + --severity-level medium \ + --confidence-level medium \ + --exclude '**/tests/**,**/test_*.py' \ + || true + + - name: Upload Bandit SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-bandit + path: bandit.sarif + + pylint-security: + name: Pylint Security Checks + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 with: - languages: ${{ matrix.language }} - queries: security-extended + python-version: '3.11' + + - name: Install dependencies + run: pip install pylint pylint-sarif - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + - name: Run Pylint security checks + run: | + pylint --load-plugins=pylint.extensions.security \ + --disable=all \ + --enable=security \ + --output-format=sarif \ + **/*.py > pylint-security.sarif || true - - name: Perform Analysis - uses: github/codeql-action/analyze@v3 + - name: Upload Pylint SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-pylint-security + path: pylint-security.sarif ``` -### 3.2 MCP-Specific Semgrep Rules +### 3.4 security-sast-go.yml + +```yaml +name: Go Security SAST + +on: + push: + branches: [main] + paths: ['**.go', 'go.mod', 'go.sum'] + pull_request: + paths: ['**.go', 'go.mod', 'go.sum'] + +jobs: + gosec: + name: gosec Security Scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-go@v5 + with: + go-version: stable + + - name: Run gosec + uses: securego/gosec@master + with: + args: -fmt sarif -out gosec.sarif ./... + + - name: Upload gosec SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-gosec + path: gosec.sarif +``` + +### 3.5 MCP-Specific Semgrep Rules + +> **Rule Location**: `configs/semgrep/rules/mcp/` + +All MCP-specific rules are centralized for maintainability. See [SAST Strategy](../../docs/strategies/sast-strategy.md) for rule organization. + +#### 3.5.1 Directory Structure + +``` +configs/semgrep/rules/mcp/ +├── mcp-all.yaml # Aggregates all MCP rules +├── injection/ +│ ├── path-traversal.yaml # Resource URI path injection +│ ├── command-injection.yaml # Tool → subprocess flows +│ └── sql-injection.yaml # Tool → database flows +├── protocol/ +│ ├── json-rpc-validation.yaml +│ ├── capability-check.yaml +│ └── transport-security.yaml +└── README.md # Rule documentation +``` + +#### 3.5.2 injection/path-traversal.yaml ```yaml -# .semgrep/mcp-security.yml rules: - - id: mcp-path-traversal + - id: mcp-path-traversal-resource + message: | + Potential path traversal in MCP resource handler. + Resource URIs from clients must be validated before filesystem access. + + Remediation: + - Use os.path.realpath() and verify path is within allowed directory + - Use pathlib.Path.resolve() and check with is_relative_to() + severity: ERROR + languages: [python] + metadata: + category: security + subcategory: path-traversal + cwe: CWE-22 + owasp: "A01:2021" + mcp-component: resources + confidence: HIGH + likelihood: HIGH + impact: HIGH patterns: - - pattern: | - resources/read($URI) - - metavariable-regex: - metavariable: $URI - regex: '.*\.\./.*' - message: Potential path traversal in resource URI + - pattern-either: + - pattern: | + def $FUNC($URI, ...): + ... + open($PATH, ...) + - pattern: | + async def $FUNC($URI, ...): + ... + open($PATH, ...) + - pattern-not-inside: | + if $CHECK: + ... + - metavariable-pattern: + metavariable: $PATH + pattern-either: + - pattern: $URI + - pattern: f"...{$URI}..." + - pattern: $X + $URI + - pattern: os.path.join(..., $URI, ...) + + - id: mcp-path-traversal-dotdot + message: | + Path contains traversal sequence '../'. + Validate and normalize paths before use. severity: ERROR + languages: [python, javascript, typescript] + metadata: + cwe: CWE-22 + mcp-component: resources + pattern-regex: '\.\.\/' +``` + +#### 3.5.3 injection/command-injection.yaml - - id: mcp-command-injection +```yaml +rules: + - id: mcp-command-injection-shell + message: | + MCP tool handler passes input to shell command. + Never use shell=True with untrusted input. + + Remediation: + - Use subprocess.run() with shell=False and argument list + - Use shlex.split() for argument parsing + - Validate input against allowlist + severity: ERROR + languages: [python] + metadata: + category: security + subcategory: command-injection + cwe: CWE-78 + owasp: "A03:2021" + mcp-component: tools + confidence: HIGH patterns: - - pattern: | - subprocess.run($CMD, shell=True) + - pattern-either: + - pattern: subprocess.run($CMD, shell=True, ...) + - pattern: subprocess.call($CMD, shell=True, ...) + - pattern: subprocess.Popen($CMD, shell=True, ...) + - pattern: os.system($CMD) + - pattern: os.popen($CMD) - pattern-inside: | def $TOOL(...): ... - message: Command injection risk in MCP tool + - pattern-not-inside: | + $CMD = "..." # Literal string only + + - id: mcp-command-injection-format + message: | + User input formatted into command string. + Use argument lists instead of string formatting. severity: ERROR + languages: [python] + metadata: + cwe: CWE-78 + mcp-component: tools + patterns: + - pattern-either: + - pattern: subprocess.run(f"...$ARG...", ...) + - pattern: subprocess.run("...%s..." % $ARG, ...) + - pattern: subprocess.run("...{}...".format($ARG), ...) +``` + +#### 3.5.4 protocol/capability-check.yaml + +```yaml +rules: + - id: mcp-missing-capability-check + message: | + MCP handler does not check client capabilities before using feature. + Always verify capabilities before using optional features. + severity: WARNING + languages: [python] + metadata: + category: security + subcategory: authorization + cwe: CWE-862 + mcp-component: protocol + patterns: + - pattern: | + def $HANDLER(...): + ... + $CLIENT.send_progress(...) + - pattern-not-inside: | + if $CAPABILITIES.experimental.progress: + ... +``` + +### 3.6 SARIF Aggregation + +> **See**: [SARIF Strategy](../../docs/strategies/sarif-strategy.md) for detailed aggregation workflow. + +This phase contributes SARIF files that are merged with outputs from other security phases: + +| Source | SARIF Artifact Name | Tool | +|--------|---------------------|------| +| security-sast.yml | sarif-semgrep | Semgrep | +| security-sast-rust.yml | sarif-clippy | Clippy | +| security-sast-python.yml | sarif-bandit | Bandit | +| security-sast-go.yml | sarif-gosec | gosec | + +### 3.7 Quality Gate Configuration + +```yaml +# configs/sast/gate-config.yaml (Phase 16 contribution) +pr_gate: + blocking_levels: + - error + + # Block on these CWEs regardless of confidence + critical_cwes: + - CWE-78 # Command Injection + - CWE-22 # Path Traversal + - CWE-94 # Code Injection + + # MCP-specific rule blocking + blocking_rules: + - mcp-command-injection-shell + - mcp-path-traversal-resource + + min_confidence: high + new_findings_only: true + timeout: 5m ``` -### 3.3 Language-Specific Workflows +### 3.8 Baseline Management -- `security-sast-rust.yml`: Clippy security lints + cargo-geiger -- `security-sast-python.yml`: Bandit + Pylint security -- `security-sast-go.yml`: gosec + staticcheck +```yaml +# configs/sast/suppressions.yaml (Phase 16 contribution) +suppressions: + # Example: Known issue tracked elsewhere + - id: mcp-path-traversal-resource + file: src/legacy/file_handler.py + reason: "Legacy code, migration tracked in #456" + expires: 2025-06-01 + approved_by: security-team + + # Example: Test code exclusion + - id: mcp-command-injection-shell + file: tests/** + reason: "Test fixtures intentionally trigger warnings" + expires: never +``` --- ## 4. Review & Validation -- [ ] All SAST tools run without errors -- [ ] SARIF uploads to Security tab -- [ ] Custom MCP rules detect issues -- [ ] False positive rate < 10% +- [ ] Semgrep scans complete in < 3 minutes +- [ ] Language-specific workflows trigger on correct paths +- [ ] SARIF uploads appear in GitHub Security tab +- [ ] MCP rules detect test vulnerabilities +- [ ] False positive rate acceptable (< 10%) +- [ ] Gate blocks on HIGH/CRITICAL findings +- [ ] Baseline comparison works for PRs - [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-18-security-memory.md b/.ai/plans/phases/bundle-contents-phase-18-security-memory.md index 61da76f..a1f5f1e 100644 --- a/.ai/plans/phases/bundle-contents-phase-18-security-memory.md +++ b/.ai/plans/phases/bundle-contents-phase-18-security-memory.md @@ -6,6 +6,9 @@ depends_on: - 9837e690-439f-42cb-811f-dbcff58a6af9 # phase-17 checklists: - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - ../../docs/strategies/sast-strategy.md # Phase boundary context + - ../../docs/strategies/sarif-strategy.md # SARIF integration issues: [] --- @@ -48,6 +51,38 @@ Implement comprehensive memory safety analysis for Rust and native code. Use Mir - Performance optimization - Memory profiling for non-Rust code +- Static unsafe code counting (Phase 16 cargo-geiger) + +### Phase Boundary + +> **See**: [SAST Strategy](../../docs/strategies/sast-strategy.md) for detailed phase boundaries. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 18 RESPONSIBILITIES │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ IN SCOPE (Dynamic Memory Analysis) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✓ Miri - Undefined behavior detection │ +│ ✓ AddressSanitizer - Buffer overflows, use-after-free │ +│ ✓ MemorySanitizer - Uninitialized reads │ +│ ✓ ThreadSanitizer - Data races, deadlocks │ +│ ✓ LeakSanitizer - Memory leaks │ +│ ✓ cargo-careful - Extra runtime checks │ +│ ✓ Valgrind - Native code memory analysis │ +│ │ +│ OUT OF SCOPE (Other Phases) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✗ cargo-geiger (static unsafe audit) → Phase 16 │ +│ ✗ clippy unsafe lints → Phase 16 │ +│ ✗ Fuzzing input generation → Phase 19 │ +│ │ +│ Analysis Type: DYNAMIC (runtime) │ +│ Execution Frequency: Weekly (scheduled) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` --- @@ -155,6 +190,31 @@ jobs: run: valgrind --error-exitcode=1 ./target/release/binary ``` +### 3.4 SARIF Integration + +> **See**: [SARIF Strategy](../../docs/strategies/sarif-strategy.md) for aggregation details. + +Memory safety findings are reported but not in standard SARIF format. Custom conversion is needed: + +```yaml +# In security-memory-rust.yml +- name: Convert Miri output to SARIF + if: failure() + run: | + python scripts/miri-to-sarif.py \ + --input miri-output.txt \ + --output miri.sarif + +- name: Upload Miri SARIF + if: failure() + uses: actions/upload-artifact@v4 + with: + name: sarif-miri + path: miri.sarif +``` + +**Note**: Memory safety findings typically indicate critical bugs that should always block. + --- ## 4. Review & Validation @@ -163,4 +223,5 @@ jobs: - [ ] Sanitizers run without crashes - [ ] No false positives in clean code - [ ] Clear error reporting +- [ ] SARIF conversion works for failures - [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md b/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md index 9d3b8cc..34be3b7 100644 --- a/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md +++ b/.ai/plans/phases/bundle-contents-phase-19-security-fuzzing.md @@ -6,6 +6,9 @@ depends_on: - c8643976-ddd4-4753-b307-b5b4db81b068 # phase-18 checklists: - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - ../../docs/strategies/sast-strategy.md # Phase boundary context + - ../../docs/strategies/sarif-strategy.md # SARIF integration for crash reports issues: [] --- @@ -50,6 +53,47 @@ Implement comprehensive fuzzing for discovering edge cases and security vulnerab - OSS-Fuzz setup (requires separate process) - Long-running fuzzing campaigns +- Static vulnerability detection (Phase 16, 20) + +### Phase Boundary + +> **See**: [SAST Strategy](../../docs/strategies/sast-strategy.md) for detailed phase boundaries. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 19 RESPONSIBILITIES │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ IN SCOPE (Dynamic Fuzzing) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✓ cargo-fuzz / libFuzzer - Rust parser fuzzing │ +│ ✓ AFL++ - Coverage-guided fuzzing │ +│ ✓ Schemathesis - OpenAPI endpoint fuzzing │ +│ ✓ Atheris - Python fuzzing │ +│ ✓ MCP protocol message fuzzing │ +│ ✓ Corpus management and crash triage │ +│ │ +│ OUT OF SCOPE (Other Phases) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✗ Pattern-based vulnerability detection → Phase 16 │ +│ ✗ Dataflow/taint analysis → Phase 20 │ +│ ✗ Memory safety interpretation → Phase 18 (but crashes feed here) │ +│ │ +│ Analysis Type: DYNAMIC (random input generation) │ +│ Execution Frequency: Daily (scheduled, continuous for OSS-Fuzz) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Integration with MCP Rules + +Fuzzing targets should cover patterns identified in Phase 16 MCP rules: + +| MCP Component | Fuzz Target | Related Semgrep Rule | +|---------------|-------------|----------------------| +| JSON-RPC Parser | `fuzz_target/json_rpc.rs` | mcp-protocol-validation | +| Resource URI | `fuzz_target/resource_uri.rs` | mcp-path-traversal | +| Tool Arguments | `fuzz_target/tool_args.rs` | mcp-command-injection | --- @@ -181,6 +225,45 @@ jobs: # Auto-create issues for new crashes ``` +### 3.5 SARIF Integration for Crashes + +> **See**: [SARIF Strategy](../../docs/strategies/sarif-strategy.md) for aggregation details. + +Fuzz crashes are converted to SARIF for unified security reporting: + +```yaml +# In crash-triage.yml +- name: Convert crashes to SARIF + run: | + python scripts/fuzz-crashes-to-sarif.py \ + --crashes-dir fuzz/artifacts/ \ + --output fuzz-crashes.sarif \ + --severity critical + +- name: Upload crashes SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-fuzz-crashes + path: fuzz-crashes.sarif +``` + +**Crash SARIF Format**: +```json +{ + "ruleId": "fuzz-crash-parse_json", + "level": "error", + "message": { + "text": "Fuzzer found crash in parse_json target" + }, + "properties": { + "crash_input": "base64_encoded_input", + "stack_trace": "...", + "fuzz_target": "parse_json", + "reproducer": "fuzz/artifacts/parse_json/crash-abc123" + } +} +``` + --- ## 4. Review & Validation @@ -189,4 +272,5 @@ jobs: - [ ] Crashes are captured and triaged - [ ] Corpus grows over time - [ ] No crashes in stable code +- [ ] Crash SARIF reports generated - [ ] Implementation tracking checklist updated diff --git a/.ai/plans/phases/bundle-contents-phase-20-security-taint.md b/.ai/plans/phases/bundle-contents-phase-20-security-taint.md index 00fd8dd..6f94e73 100644 --- a/.ai/plans/phases/bundle-contents-phase-20-security-taint.md +++ b/.ai/plans/phases/bundle-contents-phase-20-security-taint.md @@ -4,8 +4,12 @@ title: "Phase 20: Security - Taint" status: pending depends_on: - b3db6c9b-ec1e-4298-b8f5-2149afcd5050 # phase-19 + - 4690fa44-71ef-4f5d-84f4-943c8c50a34b # phase-16 (shares MCP rule definitions) checklists: - 674b3bcb-ee95-496e-ac24-4d144685f05b # implementation-tracking +references: + - ../../docs/strategies/sast-strategy.md # Phase boundary and tool selection + - ../../docs/strategies/sarif-strategy.md # SARIF aggregation issues: [] --- @@ -20,33 +24,98 @@ issues: [] ### Existing Assets -CodeQL (Phase 16) provides some taint tracking. +Phase 16 provides pattern-based detection; this phase adds dataflow depth. ### Gaps Identified -- [ ] security-taint.yml (CodeQL data flow) -- [ ] Semgrep taint rules for MCP -- [ ] Pysa configuration for Python -- [ ] Custom source/sink definitions +- [ ] security-taint.yml (CodeQL dataflow) +- [ ] security-taint-python.yml (Pysa) +- [ ] Semgrep taint mode rules for MCP +- [ ] Custom CodeQL queries for MCP +- [ ] MCP source/sink definitions +- [ ] SARIF aggregation integration --- ## 2. Contextual Goal -Implement taint analysis to track data flow from untrusted sources to sensitive sinks. This is critical for MCP servers where tool inputs flow to system operations. Define MCP-specific sources (tool arguments, resource URIs) and sinks (file operations, command execution) to detect injection vulnerabilities. +Implement **dataflow and taint analysis** to track how untrusted input flows through code to dangerous sinks. This complements Phase 16's pattern matching with semantic understanding of data propagation. Critical for MCP servers where tool inputs flow to system operations. + +> **See**: [SAST Strategy](../../docs/strategies/sast-strategy.md) for tool selection rationale and phase boundaries. ### Success Criteria - [ ] CodeQL taint queries functional -- [ ] Semgrep taint rules for MCP +- [ ] Semgrep taint mode rules for MCP - [ ] Pysa configured for Python servers -- [ ] Custom sources/sinks documented +- [ ] Custom MCP sources/sinks documented +- [ ] SARIF results aggregated - [ ] No false negatives on known patterns ### Out of Scope +- Pattern-based detection (Phase 16) - Runtime taint tracking (RASP) - Full formal verification +- Memory safety (Phase 18) + +### Phase Boundary + +> **See**: [SAST Strategy](../../docs/strategies/sast-strategy.md) for detailed phase boundaries. + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 20 RESPONSIBILITIES │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ IN SCOPE (Dataflow/Taint Analysis) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✓ CodeQL dataflow queries (security-and-quality) │ +│ ✓ CodeQL custom taint queries for MCP │ +│ ✓ Semgrep taint mode (source → sink tracking) │ +│ ✓ Pysa (Facebook's Python taint analyzer) │ +│ ✓ Cross-function vulnerability detection │ +│ ✓ MCP-specific source/sink definitions │ +│ │ +│ OUT OF SCOPE (Other Phases) │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ ✗ Pattern matching without dataflow → Phase 16 │ +│ ✗ Semgrep patterns (non-taint mode) → Phase 16 │ +│ ✗ Language-specific lints → Phase 16 │ +│ ✗ Memory safety → Phase 18 │ +│ ✗ Fuzzing → Phase 19 │ +│ │ +│ Analysis Type: STATIC (semantic dataflow) │ +│ Execution Frequency: Weekly (scheduled) + main branch push │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +### Relationship with Phase 16 + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PHASE 16 vs PHASE 20 TOOL SPLIT │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ SEMGREP │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Phase 16: pattern, pattern-either, pattern-inside (no taint tracking) │ +│ Phase 20: mode: taint, pattern-sources, pattern-sinks │ +│ │ +│ CODEQL │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Phase 16: Not used (defer to Semgrep for speed) │ +│ Phase 20: Full dataflow queries, security-and-quality suite │ +│ │ +│ MCP RULES │ +│ ───────────────────────────────────────────────────────────────────────── │ +│ Phase 16: configs/semgrep/rules/mcp/injection/ (patterns) │ +│ Phase 20: configs/semgrep/rules/mcp/taint/ (taint tracking) │ +│ .codeql/queries/mcp/ (CodeQL dataflow) │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` --- @@ -62,111 +131,456 @@ on: branches: [main] pull_request: schedule: - - cron: '0 5 * * 1' + - cron: '0 5 * * 1' # Weekly deep scan jobs: codeql-taint: + name: CodeQL Dataflow Analysis runs-on: ubuntu-latest + permissions: + security-events: write + + strategy: + matrix: + language: [python, javascript] + steps: - uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: - languages: python + languages: ${{ matrix.language }} queries: security-and-quality + config-file: .codeql/codeql-config.yml - name: Autobuild uses: github/codeql-action/autobuild@v3 - name: Analyze uses: github/codeql-action/analyze@v3 + with: + category: taint-${{ matrix.language }} + output: codeql-${{ matrix.language }}.sarif + + - name: Upload CodeQL SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-codeql-${{ matrix.language }} + path: codeql-${{ matrix.language }}.sarif semgrep-taint: + name: Semgrep Taint Analysis runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Semgrep Taint + - name: Semgrep Taint Scan uses: returntocorp/semgrep-action@v1 with: - config: .semgrep/taint-rules.yml + config: configs/semgrep/rules/mcp/taint/ + generateSarif: true + + - name: Upload Semgrep Taint SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-semgrep-taint + path: semgrep.sarif + + # Aggregate and upload to Security tab + aggregate: + needs: [codeql-taint, semgrep-taint] + uses: ./.github/workflows/sarif-aggregate.yml +``` + +### 3.2 security-taint-python.yml (Pysa) + +```yaml +name: Python Taint Analysis (Pysa) + +on: + push: + branches: [main] + paths: ['**.py'] + schedule: + - cron: '0 5 * * 1' + +jobs: + pysa: + name: Pysa Taint Analysis + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install Pyre/Pysa + run: pip install pyre-check + + - name: Setup Pyre + run: | + pyre init || true + + - name: Run Pysa + run: | + pyre analyze \ + --taint-models-path .pyre/taint.config \ + --save-results-to pysa-results/ + + - name: Convert to SARIF + run: | + python scripts/pysa-to-sarif.py \ + --input pysa-results/ \ + --output pysa.sarif + + - name: Upload Pysa SARIF + uses: actions/upload-artifact@v4 + with: + name: sarif-pysa + path: pysa.sarif ``` -### 3.2 MCP Taint Rules +### 3.3 MCP Taint Rules (Semgrep) + +> **Rule Location**: `configs/semgrep/rules/mcp/taint/` + +These rules use Semgrep's taint mode to track data from MCP sources to dangerous sinks. + +#### 3.3.1 taint/tool-to-file.yaml ```yaml -# .semgrep/taint-rules.yml rules: - id: mcp-taint-tool-to-file mode: taint - message: Untrusted tool input flows to file operation + message: | + Untrusted tool input flows to file operation without validation. + MCP tool arguments must be validated before use in file operations. + + Remediation: + - Validate paths against allowlist + - Use Path.resolve() and check with is_relative_to() + - Sanitize filenames with secure_filename() severity: ERROR languages: [python] + metadata: + category: security + subcategory: path-traversal + cwe: CWE-22 + owasp: "A01:2021" + mcp-component: tools + confidence: HIGH + pattern-sources: - patterns: - pattern: $ARGS["$KEY"] - pattern-inside: | - def $TOOL(..., $ARGS: dict, ...): + async def $TOOL($CTX, $ARGS: dict, ...): + ... + - patterns: + - pattern: $ARGS.get("$KEY", ...) + - pattern-inside: | + async def $TOOL($CTX, $ARGS: dict, ...): ... + pattern-sinks: - pattern: open($PATH, ...) - - pattern: os.path.join(..., $PATH, ...) + - pattern: Path($PATH).read_text(...) + - pattern: Path($PATH).write_text(...) + - pattern: os.path.join($BASE, $PATH) + - pattern: shutil.copy($SRC, $PATH) + - pattern: shutil.move($SRC, $PATH) + + pattern-sanitizers: + - pattern: os.path.realpath($X) + - pattern: Path($X).resolve() + - pattern: secure_filename($X) +``` - - id: mcp-taint-resource-to-command +#### 3.3.2 taint/tool-to-command.yaml + +```yaml +rules: + - id: mcp-taint-tool-to-command mode: taint - message: Resource URI flows to command execution + message: | + Untrusted tool input flows to command execution. + MCP tool arguments must never reach shell commands. + + Remediation: + - Use subprocess with shell=False and argument list + - Validate against strict allowlist + - Consider if command execution is necessary severity: ERROR languages: [python] + metadata: + category: security + subcategory: command-injection + cwe: CWE-78 + owasp: "A03:2021" + mcp-component: tools + confidence: HIGH + pattern-sources: - - pattern: $URI - pattern-inside: | - def read_resource($URI, ...): - ... + - patterns: + - pattern: $ARGS["$KEY"] + - pattern-inside: | + async def $TOOL($CTX, $ARGS: dict, ...): + ... + pattern-sinks: - - pattern: subprocess.run($CMD, ...) + - pattern: subprocess.run($CMD, shell=True, ...) + - pattern: subprocess.call($CMD, shell=True, ...) + - pattern: subprocess.Popen($CMD, shell=True, ...) - pattern: os.system($CMD) + - pattern: os.popen($CMD) + - pattern: eval($CMD) + - pattern: exec($CMD) + + pattern-sanitizers: + - pattern: shlex.quote($X) + - pattern: shlex.split($X) +``` + +#### 3.3.3 taint/resource-to-network.yaml + +```yaml +rules: + - id: mcp-taint-resource-to-network + mode: taint + message: | + Resource URI flows to network request (potential SSRF). + Validate URLs against allowlist before making requests. + severity: ERROR + languages: [python] + metadata: + cwe: CWE-918 + owasp: "A10:2021" + mcp-component: resources + + pattern-sources: + - patterns: + - pattern: $URI + - pattern-inside: | + async def read_resource($URI: str, ...): + ... + + pattern-sinks: + - pattern: requests.get($URL, ...) + - pattern: requests.post($URL, ...) + - pattern: httpx.get($URL, ...) + - pattern: aiohttp.ClientSession().get($URL, ...) + - pattern: urllib.request.urlopen($URL) ``` -### 3.3 MCP Sources and Sinks +### 3.4 CodeQL Custom Queries + +> **Query Location**: `.codeql/queries/mcp/` + +#### 3.4.1 .codeql/codeql-config.yml + +```yaml +name: "MCP Security Configuration" + +queries: + - uses: security-and-quality + - uses: ./.codeql/queries/mcp/ + +paths-ignore: + - '**/tests/**' + - '**/test_*.py' + - '**/node_modules/**' +``` + +#### 3.4.2 .codeql/queries/mcp/tool-injection.ql + +```ql +/** + * @name MCP Tool Argument Injection + * @description Tracks flow from MCP tool arguments to dangerous sinks + * @kind path-problem + * @problem.severity error + * @security-severity 9.0 + * @precision high + * @id mcp/tool-injection + * @tags security + * external/cwe/cwe-78 + * mcp + */ + +import python +import semmle.python.dataflow.new.DataFlow +import semmle.python.dataflow.new.TaintTracking +import semmle.python.ApiGraphs + +/** + * A source of untrusted data from MCP tool arguments + */ +class McpToolArgumentSource extends DataFlow::Node { + McpToolArgumentSource() { + exists(Function f, Parameter p | + // Function named with 'tool' pattern + f.getName().matches("%tool%") and + p = f.getArg(_) and + p.getName() = "arguments" and + this.asExpr() = p.asName().getAUse() + ) + } +} + +/** + * A sink for command execution + */ +class CommandExecutionSink extends DataFlow::Node { + CommandExecutionSink() { + exists(Call c | + c.getFunc().(Attribute).getName() = "run" and + c.getFunc().(Attribute).getObject().(Name).getId() = "subprocess" and + this.asExpr() = c.getArg(0) + ) + or + exists(Call c | + c.getFunc().(Name).getId() = "system" and + this.asExpr() = c.getArg(0) + ) + } +} + +class McpToolInjectionConfig extends TaintTracking::Configuration { + McpToolInjectionConfig() { this = "McpToolInjectionConfig" } + + override predicate isSource(DataFlow::Node source) { + source instanceof McpToolArgumentSource + } + + override predicate isSink(DataFlow::Node sink) { + sink instanceof CommandExecutionSink + } +} + +from McpToolInjectionConfig config, DataFlow::PathNode source, DataFlow::PathNode sink +where config.hasFlowPath(source, sink) +select sink.getNode(), source, sink, + "MCP tool argument flows to command execution without sanitization" +``` + +### 3.5 MCP Sources and Sinks Reference | Category | Sources | Sinks | |----------|---------|-------| -| Tools | `arguments` dict, `name` param | File ops, subprocess, DB | -| Resources | `uri` param, template vars | File read, network fetch | -| Prompts | `arguments` dict | Any output | +| **Tools** | `arguments` dict, `name` param | File ops, subprocess, DB queries | +| **Resources** | `uri` param, template vars | File read, network fetch, path construction | +| **Prompts** | `arguments` dict | Any output (XSS if rendered) | +| **Transport** | Request body, headers | Response construction | -### 3.4 Pysa Configuration +### 3.6 Pysa Configuration ```python # .pyre/taint.config { "sources": [ - {"name": "MCPToolInput", "comment": "Tool arguments from client"}, - {"name": "MCPResourceURI", "comment": "Resource URI from client"} + { + "name": "MCPToolInput", + "comment": "Tool arguments from MCP client" + }, + { + "name": "MCPResourceURI", + "comment": "Resource URI from MCP client" + }, + { + "name": "MCPPromptArgs", + "comment": "Prompt arguments from MCP client" + } ], "sinks": [ - {"name": "FileSystem", "comment": "File system operations"}, - {"name": "CommandExecution", "comment": "Shell/subprocess"} + { + "name": "FileSystem", + "comment": "File system operations" + }, + { + "name": "CommandExecution", + "comment": "Shell/subprocess calls" + }, + { + "name": "NetworkRequest", + "comment": "HTTP/network requests" + }, + { + "name": "SQLQuery", + "comment": "Database queries" + } + ], + "features": [ + { + "name": "mcp-validated", + "comment": "Input has been validated" + } ], - "features": [], "rules": [ { - "name": "MCP Injection", + "name": "MCP Tool Injection", "code": 1001, - "sources": ["MCPToolInput", "MCPResourceURI"], - "sinks": ["FileSystem", "CommandExecution"] + "sources": ["MCPToolInput"], + "sinks": ["FileSystem", "CommandExecution"], + "message_format": "MCP tool input flows to {sink} without validation" + }, + { + "name": "MCP SSRF", + "code": 1002, + "sources": ["MCPResourceURI"], + "sinks": ["NetworkRequest"], + "message_format": "MCP resource URI flows to network request" + }, + { + "name": "MCP SQL Injection", + "code": 1003, + "sources": ["MCPToolInput", "MCPPromptArgs"], + "sinks": ["SQLQuery"], + "message_format": "MCP input flows to SQL query" } ] } ``` +### 3.7 SARIF Aggregation + +> **See**: [SARIF Strategy](../../docs/strategies/sarif-strategy.md) for detailed aggregation workflow. + +This phase contributes SARIF files that are merged with Phase 16 outputs: + +| Source | SARIF Artifact Name | Tool | +|--------|---------------------|------| +| security-taint.yml | sarif-codeql-python | CodeQL Python | +| security-taint.yml | sarif-codeql-javascript | CodeQL JavaScript | +| security-taint.yml | sarif-semgrep-taint | Semgrep Taint | +| security-taint-python.yml | sarif-pysa | Pysa | + +### 3.8 Deduplication with Phase 16 + +Since both Phase 16 and Phase 20 may detect similar vulnerabilities (pattern vs dataflow), deduplication is handled by the SARIF aggregation workflow: + +```yaml +# In sarif-aggregate.yml +- name: Deduplicate findings + run: | + python scripts/sarif-dedup.py \ + --priority-order "codeql,semgrep-taint,semgrep,pysa,bandit" \ + --input merged.sarif \ + --output deduped.sarif +``` + +**Priority**: CodeQL findings are preferred over Semgrep pattern findings for the same location, as CodeQL provides deeper analysis context. + --- ## 4. Review & Validation -- [ ] Taint analysis detects known vulnerabilities -- [ ] Custom rules cover MCP patterns -- [ ] No false negatives on test cases -- [ ] Sources and sinks are complete +- [ ] CodeQL taint analysis completes successfully +- [ ] Semgrep taint rules detect test vulnerabilities +- [ ] Pysa configured and running +- [ ] Custom MCP queries functional +- [ ] SARIF aggregation includes taint findings +- [ ] Deduplication works with Phase 16 +- [ ] No false negatives on known patterns - [ ] Implementation tracking checklist updated From b247e5b91a0331aed2ade5f706793fd2b9ae6123 Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:29:32 -0500 Subject: [PATCH 3/7] planning(bundle-contents): added plan docs for opa/rego development --- .ai/docs/strategies/policy-as-code.md | 714 ++++++++++++++++++++++++++ 1 file changed, 714 insertions(+) create mode 100644 .ai/docs/strategies/policy-as-code.md diff --git a/.ai/docs/strategies/policy-as-code.md b/.ai/docs/strategies/policy-as-code.md new file mode 100644 index 0000000..1ce3ff3 --- /dev/null +++ b/.ai/docs/strategies/policy-as-code.md @@ -0,0 +1,714 @@ +--- +id: d8f1e2a3-4b5c-6d7e-8f9a-0b1c2d3e4f5a +title: "Policy-as-Code Strategy" +status: active +created: 2025-12-05 +type: strategy +related: + - ai-context.md + - tagging-and-versioning.md + - ../../plans/phases/bundle-contents-phase-22a-policy-library.md +--- + +# Policy-as-Code Strategy + +## Overview + +This document defines the strategy for implementing policy-as-code across the MCP bundle. The goal is to establish a unified, testable, and maintainable policy framework using Open Policy Agent (OPA) and Rego as the primary policy language. + +--- + +## Philosophy + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ POLICY-AS-CODE PRINCIPLES │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. DECLARATIVE Policies describe WHAT, not HOW │ +│ 2. TESTABLE Every policy has corresponding tests │ +│ 3. VERSIONED Policies follow semantic versioning │ +│ 4. DOCUMENTED Self-documenting with metadata │ +│ 5. REUSABLE Shared library, not copy-paste │ +│ 6. AUDITABLE Decision logging for compliance │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Language Selection + +### Primary: Rego (OPA) + +Rego is the primary policy language for all JSON/YAML-based configurations. + +**Use Rego for**: +- Container configurations (Dockerfile, docker-compose) +- Kubernetes manifests +- Terraform/OpenTofu +- GitHub Actions workflows +- Generic JSON/YAML validation +- License compliance (unified) +- Compliance frameworks (CIS, PCI-DSS, HIPAA) + +**Why Rego**: +- Purpose-built for policy decisions +- Rich standard library +- Strong testing framework +- Active community and tooling +- Supports data-driven policies + +### Native Tools (Keep As-Is) + +Some domain-specific tools have superior native policy support: + +| Tool | Domain | Keep Because | +|------|--------|--------------| +| `cargo-deny` | Rust dependencies | Deep Cargo.toml understanding, advisory DB integration | +| `cargo-vet` | Rust supply chain | Audit trail, community imports | +| `eslint` | JavaScript/TypeScript | AST-level analysis | +| `ruff` | Python | AST-level analysis | +| `clippy` | Rust | Compiler integration | + +**Rule**: If a tool provides AST-level or compiler-level analysis, keep using it natively. Rego is for configuration validation, not code analysis. + +--- + +## Unified Policy Structure + +### Directory Layout + +``` +policies/ +├── bundles/ # Built policy bundles (gitignored) +│ └── mcp-policies-v1.0.0.tar.gz +│ +├── container/ # Container security policies +│ ├── privileged.rego # No privileged containers +│ ├── root_user.rego # No root user +│ ├── capabilities.rego # Dangerous capability checks +│ ├── networking.rego # Host networking restrictions +│ ├── volumes.rego # Volume mount restrictions +│ ├── resources.rego # Resource limit requirements +│ └── base_image.rego # Allowed base images +│ +├── kubernetes/ # Kubernetes policies +│ ├── pod_security.rego # Pod security standards +│ ├── network_policy.rego # Network policy requirements +│ ├── rbac.rego # RBAC best practices +│ └── resource_quotas.rego # Resource quota enforcement +│ +├── compliance/ # Compliance framework policies +│ ├── cis/ +│ │ ├── docker.rego # CIS Docker Benchmark +│ │ └── kubernetes.rego # CIS Kubernetes Benchmark +│ ├── pci_dss.rego # PCI-DSS requirements +│ └── hipaa.rego # HIPAA requirements +│ +├── license/ # License compliance policies +│ ├── enforcement.rego # Allow/deny enforcement +│ └── compatibility.rego # License compatibility checks +│ +├── workflow/ # CI/CD workflow policies +│ ├── actions.rego # GitHub Actions security +│ └── secrets.rego # Secret handling +│ +├── lib/ # Shared library functions +│ ├── utils.rego # Common utilities +│ ├── semver.rego # Semantic version parsing +│ └── strings.rego # String manipulation +│ +├── data/ # External data for policies +│ ├── allowed_licenses.json # License allowlist +│ ├── denied_licenses.json # License denylist +│ ├── allowed_base_images.json # Base image allowlist +│ └── dangerous_capabilities.json +│ +├── tests/ # Policy tests +│ ├── container_test.rego +│ ├── kubernetes_test.rego +│ ├── compliance_test.rego +│ ├── license_test.rego +│ └── testdata/ # Test fixtures +│ ├── valid_compose.yaml +│ ├── invalid_compose.yaml +│ └── ... +│ +├── .manifest # OPA bundle manifest +└── README.md # Policy documentation +``` + +### Package Naming Convention + +```rego +# Pattern: mcp.{domain}.{subdomain} +package mcp.container.privileged +package mcp.container.root_user +package mcp.kubernetes.pod_security +package mcp.compliance.cis.docker +package mcp.license.enforcement +``` + +### Policy Metadata + +Every policy file should include metadata: + +```rego +# METADATA +# title: No Privileged Containers +# description: Containers must not run in privileged mode +# authors: +# - MCP Bundle Team +# entrypoint: true +# scope: package +# schemas: +# - input: schema.compose +# custom: +# severity: high +# remediation: Remove 'privileged: true' from service definition +# references: +# - https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities + +package mcp.container.privileged + +import future.keywords.contains +import future.keywords.if +import future.keywords.in +``` + +--- + +## Policy Patterns + +### Standard Deny Pattern + +```rego +package mcp.container.privileged + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +# Deny privileged containers in docker-compose +deny contains msg if { + some name, service in input.services + service.privileged == true + msg := sprintf("Service '%s' must not run in privileged mode", [name]) +} +``` + +### Standard Warn Pattern + +```rego +package mcp.container.resources + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +# Warn on missing resource limits +warn contains msg if { + some name, service in input.services + not service.deploy.resources.limits + not service.mem_limit + msg := sprintf("Service '%s' has no memory limits defined", [name]) +} +``` + +### Data-Driven Pattern + +```rego +package mcp.container.capabilities + +import future.keywords.contains +import future.keywords.if +import future.keywords.in + +import data.mcp.dangerous_capabilities + +# Deny dangerous capabilities using external data +deny contains msg if { + some name, service in input.services + some cap in service.cap_add + cap in dangerous_capabilities + msg := sprintf("Service '%s' has dangerous capability: %s", [name, cap]) +} +``` + +### Shared Library Pattern + +```rego +# policies/lib/utils.rego +package mcp.lib.utils + +import future.keywords.if + +# Check if value is in array +array_contains(arr, val) if { + arr[_] == val +} + +# Get with default +get_default(obj, key, default_value) := obj[key] if { + obj[key] +} else := default_value +``` + +Using shared library: + +```rego +package mcp.container.base_image + +import data.mcp.lib.utils +import data.mcp.allowed_base_images + +deny contains msg if { + image := input.image + not utils.array_contains(allowed_base_images, image) + msg := sprintf("Base image '%s' is not in allowed list", [image]) +} +``` + +--- + +## Testing Strategy + +### Test File Structure + +```rego +# policies/tests/container_test.rego +package mcp.container.privileged_test + +import data.mcp.container.privileged + +# Test: privileged container is denied +test_deny_privileged_container if { + result := privileged.deny with input as { + "services": { + "web": {"privileged": true} + } + } + count(result) == 1 + result[_] == "Service 'web' must not run in privileged mode" +} + +# Test: non-privileged container is allowed +test_allow_non_privileged_container if { + result := privileged.deny with input as { + "services": { + "web": {"privileged": false} + } + } + count(result) == 0 +} + +# Test: missing privileged key defaults to allowed +test_allow_missing_privileged_key if { + result := privileged.deny with input as { + "services": { + "web": {"image": "nginx"} + } + } + count(result) == 0 +} +``` + +### Test Data Files + +```yaml +# policies/tests/testdata/valid_compose.yaml +version: "3.8" +services: + web: + image: nginx:alpine + user: "1000:1000" + read_only: true + security_opt: + - no-new-privileges:true + deploy: + resources: + limits: + memory: 256M +``` + +```yaml +# policies/tests/testdata/invalid_compose.yaml +version: "3.8" +services: + web: + image: nginx:latest + privileged: true + user: root + cap_add: + - SYS_ADMIN + volumes: + - /var/run/docker.sock:/var/run/docker.sock +``` + +### Coverage Requirements + +| Policy Domain | Minimum Coverage | +|---------------|-----------------| +| Container | 90% | +| Kubernetes | 90% | +| Compliance | 80% | +| License | 95% | +| Library | 100% | + +--- + +## Versioning Strategy + +### Semantic Versioning for Policies + +``` +MAJOR.MINOR.PATCH + +MAJOR: Breaking changes (removed rules, changed deny→warn) +MINOR: New policies added (backward compatible) +PATCH: Bug fixes, documentation updates +``` + +### Version Tracking + +```json +// policies/.manifest +{ + "revision": "1.2.0", + "roots": ["mcp"], + "metadata": { + "created": "2025-12-05T00:00:00Z", + "bundle_type": "mcp-policies" + } +} +``` + +### Changelog + +```markdown +# Policy Changelog + +## [1.2.0] - 2025-12-05 +### Added +- mcp.container.base_image: Allowed base image validation +- mcp.kubernetes.network_policy: Network policy requirements + +### Changed +- mcp.container.resources: memory limit warning threshold from 128M to 256M + +## [1.1.0] - 2025-11-15 +### Added +- mcp.compliance.pci_dss: PCI-DSS compliance checks +``` + +--- + +## Integration Points + +### Conftest Integration + +```yaml +# .github/workflows/policy-check.yml +- name: Run Conftest + run: | + conftest test docker-compose.yml \ + --policy policies/ \ + --data policies/data/ \ + --output github \ + --all-namespaces +``` + +### OPA Eval for Testing + +```bash +# Run all policy tests +opa test policies/ -v + +# Run specific test +opa test policies/ -v -r 'test_deny_privileged' + +# Check coverage +opa test policies/ --coverage --format=json +``` + +### Bundle Building + +```bash +# Build policy bundle +opa build \ + --bundle policies/ \ + --output bundles/mcp-policies-v1.0.0.tar.gz \ + --revision "1.0.0" + +# Verify bundle +opa inspect bundles/mcp-policies-v1.0.0.tar.gz +``` + +--- + +## Migration Guide + +### From Inline Policies + +**Before** (inline in workflow): +```yaml +- name: Create policy + run: | + cat > policy/container.rego << 'EOF' + package main + deny[msg] { ... } + EOF +``` + +**After** (reference policy library): +```yaml +- name: Download policy bundle + run: | + curl -L -o policies.tar.gz \ + https://github.com/org/repo/releases/download/policies-v1.0.0/mcp-policies.tar.gz + tar -xzf policies.tar.gz + +- name: Run Conftest + run: conftest test docker-compose.yml --policy policies/ +``` + +### From cargo-deny License Policy + +Keep `deny.toml` for Rust-specific dependency checks. Use the unified Rego policy for: +- Cross-language license reporting +- License compatibility analysis +- Compliance documentation + +### From Custom Shell Scripts + +**Before**: +```bash +# Check for allowed base images +if ! grep -q "FROM.*alpine\|FROM.*distroless" Dockerfile; then + echo "Error: Must use alpine or distroless base" + exit 1 +fi +``` + +**After**: +```rego +package mcp.container.base_image + +import data.mcp.allowed_base_images + +deny contains msg if { + instruction := input.Stages[_].Commands[_] + instruction.Cmd == "from" + image := instruction.Value[0] + not image_allowed(image) + msg := sprintf("Base image '%s' not in allowed list", [image]) +} + +image_allowed(image) if { + some allowed in allowed_base_images + startswith(image, allowed) +} +``` + +--- + +## External Data Management + +### Data File Format + +```json +// policies/data/allowed_base_images.json +{ + "mcp": { + "allowed_base_images": [ + "scratch", + "gcr.io/distroless/static", + "gcr.io/distroless/cc", + "alpine", + "cgr.dev/chainguard/" + ] + } +} +``` + +### Loading External Data + +```bash +# Local development +conftest test compose.yml --policy policies/ --data policies/data/ + +# CI/CD with remote data +conftest test compose.yml \ + --policy policies/ \ + --data https://example.com/policy-data/allowed_images.json +``` + +### Data Update Process + +1. Update JSON file in `policies/data/` +2. Increment policy patch version +3. Run tests to verify no breakage +4. Build and release new bundle + +--- + +## Exception Handling + +### Annotation-Based Exceptions + +```yaml +# docker-compose.yml +services: + debug-sidecar: + image: busybox + privileged: true + labels: + # Policy exception annotation + mcp.policy/exception: "privileged-allowed" + mcp.policy/exception-reason: "Debug sidecar requires host access" + mcp.policy/exception-expires: "2025-12-31" + mcp.policy/exception-approved-by: "security-team" +``` + +```rego +package mcp.container.privileged + +deny contains msg if { + some name, service in input.services + service.privileged == true + not has_valid_exception(service) + msg := sprintf("Service '%s' must not run in privileged mode", [name]) +} + +has_valid_exception(service) if { + service.labels["mcp.policy/exception"] == "privileged-allowed" + # Could add expiration check here +} +``` + +### Exception Registry + +For tracking exceptions across the organization: + +```json +// policies/data/exceptions.json +{ + "mcp": { + "exceptions": { + "privileged-allowed": { + "description": "Allow privileged mode for specific use cases", + "approved_by": "security-team", + "valid_until": "2025-12-31", + "services": ["debug-sidecar", "network-debug"] + } + } + } +} +``` + +--- + +## Workflow Integration + +### Pre-commit Hook + +```yaml +# .pre-commit-config.yaml +repos: + - repo: https://github.com/open-policy-agent/conftest + rev: v0.45.0 + hooks: + - id: conftest + args: ['test', '--policy', 'policies/', 'docker-compose.yml'] +``` + +### GitHub Actions + +```yaml +# Reference: Phase 22a implements this workflow +name: Policy Check + +on: + pull_request: + paths: + - 'docker-compose*.yml' + - 'Dockerfile*' + - 'k8s/**' + - 'policies/**' + +jobs: + policy-check: + uses: ./.github/workflows/policy-library.yml +``` + +--- + +## Metrics and Reporting + +### Policy Evaluation Metrics + +| Metric | Description | Target | +|--------|-------------|--------| +| `policy_evaluations_total` | Total policy evaluations | N/A | +| `policy_violations_total` | Total violations found | Minimize | +| `policy_test_coverage` | Test coverage percentage | >90% | +| `policy_bundle_size` | Bundle size in bytes | <1MB | + +### Compliance Reporting + +```bash +# Generate compliance report +conftest test compose.yml \ + --policy policies/ \ + --output json \ + | jq '.[] | {file, violations: [.failures[].msg]}' \ + > compliance-report.json +``` + +--- + +## Related Documents + +- [AI Context Strategy](ai-context.md) - How policies integrate with AI guidance +- [Tagging and Versioning Strategy](tagging-and-versioning.md) - Policy versioning alignment +- [Phase 22a: Policy Library](../../plans/phases/bundle-contents-phase-22a-policy-library.md) - Implementation phase + +--- + +## Appendix: Quick Reference + +### Common Commands + +```bash +# Format all policies +opa fmt -w policies/ + +# Check syntax +opa check policies/ + +# Run all tests +opa test policies/ -v + +# Run tests with coverage +opa test policies/ --coverage + +# Build bundle +opa build -b policies/ -o bundle.tar.gz + +# Evaluate policy locally +conftest test docker-compose.yml --policy policies/ + +# Verify with trace (debugging) +conftest test docker-compose.yml --policy policies/ --trace +``` + +### Conftest Output Formats + +| Format | Use Case | +|--------|----------| +| `stdout` | Local development | +| `json` | Programmatic processing | +| `github` | GitHub Actions annotations | +| `junit` | CI/CD test reporting | +| `sarif` | Security tab integration | From 2baeeb6944987820dc6b4cee4ada987af28828ac Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:29:54 -0500 Subject: [PATCH 4/7] planning(bundle-contents): added plan docs for tagging/versioning strategy --- .ai/docs/strategies/tagging-and-versioning.md | 267 ++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 .ai/docs/strategies/tagging-and-versioning.md diff --git a/.ai/docs/strategies/tagging-and-versioning.md b/.ai/docs/strategies/tagging-and-versioning.md new file mode 100644 index 0000000..dd8d545 --- /dev/null +++ b/.ai/docs/strategies/tagging-and-versioning.md @@ -0,0 +1,267 @@ +--- +title: Tagging and Versioning Strategy +status: approved +date: 2025-12-05 +decision-makers: [arustydev] +tags: [release, versioning, tagging, ci-cd, semantic-release] +related-phases: [24, 25, 26, 27] +--- + +# Tagging and Versioning Strategy + +## Context + +This document defines the versioning and tagging strategy for the MCP bundle. Multiple artifacts require version coordination: git tags, GitHub releases, container images, package manifests (Cargo.toml, package.json, pyproject.toml), and Helm charts. Without a clear strategy, version drift between these artifacts causes publishing failures and confusion. + +## Terminology + +| Term | Definition | Created By | Location | +|------|------------|------------|----------| +| **Version** | Semantic version number (1.2.3) | Determined by semantic-release | Abstract concept | +| **Git Tag** | Immutable pointer to commit SHA | semantic-release | `.git/refs/tags/` | +| **GitHub Release** | GitHub feature wrapping a git tag | semantic-release | GitHub API | +| **Package Version** | Version string in manifest file | `scripts/update-versions.sh` | Manifest files | +| **Container Tag** | Label on container image | `docker/metadata-action` | Container registry | +| **Chart Version** | Helm chart version | Developer/chart-releaser | `Chart.yaml` | +| **Chart appVersion** | Application version in chart | `scripts/update-versions.sh` | `Chart.yaml` | + +### Relationship Diagram + +``` + VERSION (the number: 1.2.3) + │ + ┌───────────────────────────┼───────────────────────────┐ + │ │ │ + ▼ ▼ ▼ + SOURCE CODE ARTIFACTS METADATA + │ │ │ + ┌─────┴─────┐ ┌──────┴──────┐ ┌─────┴─────┐ + │ │ │ │ │ │ + ▼ ▼ ▼ ▼ ▼ ▼ + Git Tag Manifests Container Packages GitHub Changelog + v1.2.3 Cargo.toml ghcr.io/x: crates.io Release CHANGELOG.md + package.json 1.2.3 pypi/npm + pyproject.toml + Chart.yaml +``` + +## Decision + +### Single Source of Truth + +**The git tag created by semantic-release is the single source of truth for versioning.** + +All package manifests are updated by semantic-release to match the git tag version before any publishing occurs. + +### Version Flow + +``` +Commit to main + │ + ▼ +semantic-release analyzes commits + │ + ├── Determines next version: 1.3.0 + │ + ├── Runs: scripts/update-versions.sh 1.3.0 + │ ├── Updates Cargo.toml + │ ├── Updates package.json + │ ├── Updates pyproject.toml + │ └── Updates Chart.yaml appVersion + │ + ├── Commits: "chore(release): 1.3.0 [skip ci]" + │ + ├── Creates git tag: v1.3.0 + │ + └── Creates GitHub Release: v1.3.0 + │ + ▼ + Triggers Phase 25/26/27 workflows + │ + ├── publish-container.yml → tags from git ref + ├── publish-rust.yml → reads Cargo.toml (now 1.3.0) + ├── publish-python.yml → reads pyproject.toml (now 1.3.0) + ├── publish-node.yml → reads package.json (now 1.3.0) + └── publish-helm-oci.yml → reads Chart.yaml +``` + +### Tool Responsibilities + +| Phase | Tool | Responsibility | Trigger | +|-------|------|----------------|---------| +| 24 | **semantic-release** | Determine version, create tag, create release | `push` to main | +| 24 | **scripts/update-versions.sh** | Update all manifest files | Called by semantic-release | +| 24 | **release-drafter** | Categorize PRs (NOT version resolution) | `pull_request` | +| 24 | **version-check.yml** | Detect version drift | `push`, `pull_request` | +| 25 | **docker/metadata-action** | Generate container tags from git ref | `release: [published]` | +| 26 | **cargo publish** | Publish to crates.io (reads Cargo.toml) | `release: [published]` | +| 26 | **pypa/gh-action-pypi-publish** | Publish to PyPI (reads pyproject.toml) | `release: [published]` | +| 26 | **npm publish** | Publish to npm (reads package.json) | `release: [published]` | +| 27 | **chart-releaser** | Create Helm release | `release: [published]` | +| 27 | **helm push** | Publish to OCI registry | `release: [published]` | + +### Version Determination + +semantic-release determines version bumps from conventional commit messages: + +| Commit Type | Version Bump | Example | +|-------------|--------------|---------| +| `fix:` | Patch (0.0.X) | `fix: resolve null pointer` | +| `feat:` | Minor (0.X.0) | `feat: add new endpoint` | +| `BREAKING CHANGE:` | Major (X.0.0) | Footer or `feat!:` | +| `chore:`, `docs:`, `style:` | No release | `docs: update README` | + +### Helm Chart Versioning + +Helm charts have two version fields with different lifecycles: + +| Field | Purpose | Updated By | Lifecycle | +|-------|---------|------------|-----------| +| `version` | Chart version | Developer / workflow_dispatch | Chart template changes | +| `appVersion` | Application version | semantic-release | Synced with git tags | + +**Strategy**: The chart `version` is managed independently (can release chart updates without app changes). The `appVersion` is synced with git tags by `scripts/update-versions.sh`. + +Example: +```yaml +# Chart.yaml +version: 0.1.5 # Chart-specific version +appVersion: "1.3.0" # Synced with git tag v1.3.0 +``` + +### Container Image Tags + +Container images receive multiple tags for flexibility: + +| Tag Pattern | Example | Use Case | +|-------------|---------|----------| +| Full semver | `1.3.0` | Immutable reference | +| Major.Minor | `1.3` | Latest patch in minor | +| Major only | `1` | Latest in major (careful!) | +| SHA | `sha-a1b2c3d` | Exact commit reference | +| `latest` | `latest` | Most recent release | + +### Prerelease Support + +semantic-release supports prerelease branches: + +```json +{ + "branches": [ + "main", + { "name": "beta", "prerelease": true }, + { "name": "alpha", "prerelease": true } + ] +} +``` + +Prerelease versions: `1.3.0-beta.1`, `1.3.0-alpha.1` + +## Conflicts Avoided + +### 1. semantic-release vs Package Manifests + +**Problem**: semantic-release creates git tags but doesn't update manifest files. Publishing workflows read manifests, causing version mismatch. + +**Solution**: `scripts/update-versions.sh` updates all manifests before tag creation. + +### 2. semantic-release vs release-drafter + +**Problem**: Both tools resolve versions differently (commits vs PR labels). + +**Solution**: release-drafter version resolution disabled. Used only for PR categorization. + +### 3. Helm chart-releaser Independent Versioning + +**Problem**: chart-releaser triggered on push, not release, causing unsynchronized releases. + +**Solution**: Changed to trigger on `release: [published]`, ensuring coordination with semantic-release. + +## Drift Detection + +The `version-check.yml` workflow validates consistency: + +```yaml +on: + pull_request: + push: + branches: [main] + paths: + - 'Cargo.toml' + - 'package.json' + - 'pyproject.toml' + - 'charts/*/Chart.yaml' +``` + +- Extracts versions from all manifests +- Compares for consistency +- Warns on PRs, fails on main branch drift + +## Implementation Files + +| File | Phase | Purpose | +|------|-------|---------| +| `.github/workflows/semantic-release.yml` | 24 | Version determination and release | +| `.releaserc.json` | 24 | semantic-release configuration | +| `scripts/update-versions.sh` | 24 | Manifest update script | +| `.github/workflows/release-drafter.yml` | 24 | PR categorization | +| `.github/release-drafter.yml` | 24 | release-drafter config | +| `.github/workflows/version-check.yml` | 24 | Drift detection | +| `.github/workflows/publish-container.yml` | 25 | Container publishing | +| `.github/workflows/publish-rust.yml` | 26 | crates.io publishing | +| `.github/workflows/publish-python.yml` | 26 | PyPI publishing | +| `.github/workflows/publish-node.yml` | 26 | npm publishing | +| `.github/workflows/release-helm.yml` | 27 | Helm chart release | +| `.github/workflows/publish-helm-oci.yml` | 27 | Helm OCI publishing | + +## Developer Guidelines + +### Do + +- Use conventional commit messages (`feat:`, `fix:`, etc.) +- Let semantic-release handle all version bumps +- Use `workflow_dispatch` for chart-only releases when needed +- Check version-check.yml results on PRs + +### Don't + +- Manually edit version numbers in manifest files +- Create git tags manually (use semantic-release) +- Use release-drafter for version determination +- Push directly to main (use PRs for proper versioning) + +## Consequences + +### Positive + +- Single source of truth prevents version drift +- Automated versioning reduces human error +- All artifacts consistently versioned +- Drift detection catches issues early +- Prerelease support for staged rollouts + +### Negative + +- Additional complexity in release process +- `scripts/update-versions.sh` must be maintained for new manifest types +- semantic-release plugins add dependencies +- Helm chart version vs appVersion distinction requires understanding + +### Mitigations + +- Clear documentation (this document) +- version-check.yml catches issues +- Helm chart versioning documented in Phase 27 +- Prerelease branches allow testing release process + +## References + +- [semantic-release documentation](https://semantic-release.gitbook.io/) +- [Conventional Commits](https://www.conventionalcommits.org/) +- [release-drafter](https://github.com/release-drafter/release-drafter) +- [Helm Chart Versioning](https://helm.sh/docs/topics/charts/#the-chartyaml-file) +- [docker/metadata-action](https://github.com/docker/metadata-action) +- Phase 24: Release - Versioning +- Phase 25: Release - Containers +- Phase 26: Release - Packages +- Phase 27: Release - Helm From 921ff407a5d5689860d43177e8b563cd4aa7c668 Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:30:22 -0500 Subject: [PATCH 5/7] planning(bundle-contents): added plan docs for ai context development --- .ai/docs/strategies/ai-context.md | 517 ++++++++++++++++++++++++++++++ 1 file changed, 517 insertions(+) create mode 100644 .ai/docs/strategies/ai-context.md diff --git a/.ai/docs/strategies/ai-context.md b/.ai/docs/strategies/ai-context.md new file mode 100644 index 0000000..ab48573 --- /dev/null +++ b/.ai/docs/strategies/ai-context.md @@ -0,0 +1,517 @@ +--- +id: c7e8f9a0-1b2c-3d4e-5f6a-7b8c9d0e1f2a +title: "AI Context Strategy" +status: active +created: 2025-12-05 +type: strategy +related: + - ../adr/frontmatter-standard.md + - tagging-and-versioning.md +--- + +# AI Context Strategy + +## Overview + +This document defines how the MCP bundle provides context and behavioral guidance to AI coding assistants. The goal is to ensure AI agents working with bundle-initialized repositories follow consistent development practices. + +--- + +## Architecture + +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ AI CONTEXT ARCHITECTURE │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ AGENT.md (Root) │ │ +│ │ ────────────────────────────────────────────────────────────────── │ │ +│ │ Universal behavioral guidance for all AI agents │ │ +│ │ • Git workflow (branches, commits, PRs) │ │ +│ │ • Planning methodology │ │ +│ │ • Debugging approach │ │ +│ │ • Coding standards per language │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ Agent-Specific Configuration │ │ +│ │ ────────────────────────────────────────────────────────────────── │ │ +│ │ │ │ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ +│ │ │ .claude/ │ │ .cursor/ │ │ .github/ │ │ .zed/ │ │ │ +│ │ │ CLAUDE.md│ │ rules/ │ │ copilot/ │ │settings │ │ │ +│ │ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │ │ +│ │ │ │ +│ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ +│ │ │.windsurf/│ │ .vscode/ │ │ .codex/ │ │ │ +│ │ │ rules/ │ │settings │ │ config │ │ │ +│ │ └──────────┘ └──────────┘ └──────────┘ │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ │ +│ ▼ │ +│ ┌─────────────────────────────────────────────────────────────────────┐ │ +│ │ MCP Server Configuration │ │ +│ │ ────────────────────────────────────────────────────────────────── │ │ +│ │ Tool availability and capabilities │ │ +│ │ │ │ +│ │ .mcp/ │ │ +│ │ ├── servers.json # Common servers (context7, github) │ │ +│ │ ├── servers-rust.json # Rust: cargo, rustfmt │ │ +│ │ ├── servers-python.json # Python: ruff, uv │ │ +│ │ └── servers-typescript.json# TypeScript: eslint, prettier │ │ +│ └─────────────────────────────────────────────────────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Context Layers + +### Layer 1: AGENT.md (Universal) + +The root `AGENT.md` file provides behavioral guidance applicable to **all** AI agents regardless of platform. This is the **single source of truth** for development practices. + +**Location**: Repository root (`/AGENT.md`) + +**Contents**: + +| Section | Purpose | Key Elements | +|---------|---------|--------------| +| **Branch Strategy** | Git workflow | Naming conventions, merge targets, protection rules | +| **Commit Strategy** | Version control | Conventional commits, atomic commits, trailers | +| **PR Workflow** | Code review | Lifecycle, merge strategy, CI gates | +| **Planning Strategy** | Task approach | Decomposition, sequencing, risk identification | +| **Debugging Strategy** | Problem solving | Scientific method, bisect, log analysis | +| **Coding Standards** | Language-specific | Style, patterns, documentation | + +**Why AGENT.md?** +- Platform-agnostic (works with any AI agent) +- Human-readable (developers can reference too) +- Version-controlled (changes tracked) +- Single source of truth (no duplication) + +### Layer 2: Agent-Specific Configuration + +Each AI agent may have its own configuration directory that **extends** (not replaces) AGENT.md. + +| Agent | Directory | Config Files | Purpose | +|-------|-----------|--------------|---------| +| Claude Code | `.claude/` | `CLAUDE.md`, `settings.json` | Claude-specific instructions | +| Cursor | `.cursor/` | `rules/` directory | Cursor rules and prompts | +| GitHub Copilot | `.github/copilot/` | `instructions.md` | Copilot context | +| Zed | `.zed/` | `settings.json` | Zed AI configuration | +| Windsurf | `.windsurf/` | `rules/` directory | Windsurf prompts | +| VS Code | `.vscode/` | `settings.json` | Generic VS Code AI | +| Codex | `.codex/` | `config.yaml` | OpenAI Codex config | +| Gemini | `.gemini/` | `config.yaml` | Google Gemini config | + +**Layering Principle**: +``` +AGENT.md (base) + │ + └── Agent-specific config (extends) + │ + └── User preferences (personal overrides) +``` + +### Layer 3: MCP Server Configuration + +MCP servers provide **tool capabilities** to AI agents. This layer defines what tools are available, not how to use them (that's in AGENT.md). + +**Location**: `.mcp/` directory + +**Files**: + +``` +.mcp/ +├── servers.json # Always loaded (common tools) +├── servers-rust.json # Rust language tools +├── servers-python.json # Python language tools +├── servers-typescript.json # TypeScript/Node tools +└── servers-golang.json # Go language tools +``` + +**Common Servers** (always available): +- `context7` - Documentation lookup +- `github` - Repository operations +- `fetch` - Web fetching +- `sequential-thinking` - Complex reasoning + +**Language Servers** (loaded based on project): +- Rust: `cargo`, `rustfmt`, `clippy` +- Python: `ruff`, `uv`, `pytest` +- TypeScript: `eslint`, `prettier`, `vitest` +- Go: `golangci-lint`, `go-test` + +--- + +## Strategy Definitions + +### Commit Strategy + +**Goal**: Ensure every commit is atomic, traceable, and reversible. + +**Key Principles**: + +1. **Atomic**: One logical change per commit +2. **Traceable**: Linked to issue/PR via conventional commit +3. **Reversible**: Can be reverted independently + +**Commit Flow**: +``` +┌──────────────────────────────────────────────────────────────────────────┐ +│ COMMIT DECISION TREE │ +├──────────────────────────────────────────────────────────────────────────┤ +│ │ +│ Is this change logically independent? │ +│ │ │ +│ ├── YES → Can it be reverted without breaking other changes? │ +│ │ │ │ +│ │ ├── YES → Commit separately │ +│ │ │ │ +│ │ └── NO → Combine with dependent change │ +│ │ │ +│ └── NO → Combine into single commit │ +│ │ +└──────────────────────────────────────────────────────────────────────────┘ +``` + +**Conventional Commit Types**: +- `feat` - New feature (MINOR version bump) +- `fix` - Bug fix (PATCH version bump) +- `feat!` / `fix!` - Breaking change (MAJOR version bump) +- `docs`, `style`, `refactor`, `test`, `build`, `ci`, `chore` - No version bump + +### Git Workflow Strategy + +**Goal**: Maintain clean history and enable efficient collaboration. + +**Branch Hierarchy**: +``` +main (protected, production-ready) +├── feature/* (human-created features) +├── fix/* (human-created bug fixes) +├── refactor/* (human-created improvements) +├── docs/* (human-created documentation) +├── pr/* (CI-created for PR validation) +└── deps/* (CI-created for dependency updates) +``` + +**Merge Strategy Decision**: +``` +┌──────────────────────────────────────────────────────────────────────────┐ +│ MERGE STRATEGY SELECTION │ +├──────────────────────────────────────────────────────────────────────────┤ +│ │ +│ How many meaningful commits in PR? │ +│ │ │ +│ ├── 1 commit → Squash and Merge (default) │ +│ │ │ +│ ├── Multiple, same author, logical sequence │ +│ │ → Squash and Merge (combine into one) │ +│ │ │ +│ └── Multiple, different authors OR distinct features │ +│ → Rebase and Merge (preserve individual commits) │ +│ │ +│ NEVER use Merge Commit (creates noise, disabled at repo level) │ +│ │ +└──────────────────────────────────────────────────────────────────────────┘ +``` + +### Planning Strategy + +**Goal**: Approach tasks systematically to minimize rework and maximize clarity. + +**Planning Process**: +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ PLANNING WORKFLOW │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. UNDERSTAND │ +│ ├── Read issue/requirement completely │ +│ ├── Identify acceptance criteria │ +│ ├── Ask clarifying questions BEFORE coding │ +│ └── State understanding back (confirm alignment) │ +│ │ +│ 2. DECOMPOSE │ +│ ├── What existing code is affected? │ +│ ├── What new code is needed? │ +│ ├── What tests are required? │ +│ └── What documentation needs updating? │ +│ │ +│ 3. SEQUENCE │ +│ ├── Order by dependencies (what must exist first?) │ +│ ├── Prioritize by risk (tackle uncertainty early) │ +│ └── Consider value delivery (incremental progress) │ +│ │ +│ 4. EXECUTE │ +│ └── Work through tasks using TDD cycle │ +│ │ +│ 5. VALIDATE │ +│ ├── All acceptance criteria met? │ +│ ├── Tests pass? │ +│ └── Documentation updated? │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +**When AI Should Stop and Ask**: +- Requirements are ambiguous +- Multiple valid approaches exist +- Scope appears to be expanding +- External dependency blocks progress +- Estimated effort significantly exceeds expectations + +### Debugging Strategy + +**Goal**: Find root causes efficiently using scientific method. + +**Debugging Process**: +``` +┌─────────────────────────────────────────────────────────────────────────────┐ +│ DEBUGGING WORKFLOW │ +├─────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ 1. REPRODUCE │ +│ ├── Get exact reproduction steps │ +│ ├── Note environment details │ +│ ├── Create minimal test case │ +│ └── Document in issue │ +│ │ +│ 2. ISOLATE │ +│ ├── Is it this code? → git bisect │ +│ ├── Is it a dependency? → Check changelogs │ +│ ├── Is it configuration? → Diff configs │ +│ └── Is it environment? → Test clean env │ +│ │ +│ 3. HYPOTHESIZE │ +│ ├── State: "I believe X causes Y because Z" │ +│ ├── Predict: "Fixing X will change behavior to W" │ +│ └── Plan: "I'll verify by checking V" │ +│ │ +│ 4. TEST │ +│ ├── Write failing test demonstrating bug │ +│ └── Confirm it fails for the right reason │ +│ │ +│ 5. FIX │ +│ ├── Address root cause (not symptoms) │ +│ ├── Keep fix minimal and focused │ +│ └── Don't refactor unrelated code │ +│ │ +│ 6. VERIFY │ +│ ├── Test passes │ +│ ├── No regressions │ +│ └── Works in original context │ +│ │ +└─────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Agent Configuration Details + +### Claude Code + +**Directory**: `.claude/` + +**Files**: +- `CLAUDE.md` - Project-specific instructions +- `settings.json` - Claude Code settings + +**CLAUDE.md Template**: +```markdown +# Project: {project-name} + +## Quick Reference +- Language: {language} +- Build: `just build` +- Test: `just test` +- Lint: `just lint` + +## Key Patterns +- {Pattern 1 description} +- {Pattern 2 description} + +## Files to Know +- `src/main.rs` - Entry point +- `src/lib.rs` - Library root +- `tests/` - Integration tests + +## Common Tasks +- Run tests: `cargo test` +- Check types: `cargo check` +- Format: `cargo fmt` +``` + +### Cursor + +**Directory**: `.cursor/` + +**Files**: +- `rules/` - Directory of rule files +- `.cursorrules` - (deprecated, use rules/) + +**Rule File Template** (`.cursor/rules/development.md`): +```markdown +# Development Rules + +## Code Style +- Follow existing patterns in codebase +- Use conventional commits for all changes + +## Before Making Changes +1. Read the affected files first +2. Understand existing patterns +3. Write tests before implementation +``` + +### GitHub Copilot + +**Directory**: `.github/copilot/` + +**Files**: +- `instructions.md` - Copilot context + +**Template**: +```markdown +# Copilot Instructions + +This is an MCP server project using {language}. + +## Conventions +- Use conventional commits +- Follow TDD (test-driven development) +- Keep functions small and focused + +## Key Commands +- Build: `just build` +- Test: `just test` +- Lint: `just lint` +``` + +--- + +## MCP Server Configuration + +### Common Servers (`.mcp/servers.json`) + +```json +{ + "mcpServers": { + "context7": { + "command": "npx", + "args": ["-y", "@context7/mcp-server"], + "description": "Documentation and code examples" + }, + "github": { + "command": "npx", + "args": ["-y", "@modelcontextprotocol/server-github"], + "env": { + "GITHUB_TOKEN": "${GITHUB_TOKEN}" + }, + "description": "GitHub repository operations" + }, + "fetch": { + "command": "npx", + "args": ["-y", "@anthropic/mcp-fetch"], + "description": "Web content fetching" + }, + "sequential-thinking": { + "command": "npx", + "args": ["-y", "@anthropic/mcp-sequential-thinking"], + "description": "Complex multi-step reasoning" + } + } +} +``` + +### Language-Specific Servers + +**Rust** (`.mcp/servers-rust.json`): +```json +{ + "mcpServers": { + "cargo": { + "command": "cargo", + "description": "Rust package manager" + } + } +} +``` + +**Python** (`.mcp/servers-python.json`): +```json +{ + "mcpServers": { + "ruff": { + "command": "ruff", + "description": "Python linter and formatter" + }, + "uv": { + "command": "uv", + "description": "Python package manager" + } + } +} +``` + +--- + +## Best Practices + +### For AI Agents + +1. **Read AGENT.md first** - Before any task, understand project conventions +2. **Follow commit strategy** - Atomic commits with conventional format +3. **Use planning methodology** - Decompose before coding +4. **Apply debugging process** - Don't guess, investigate systematically +5. **Ask when uncertain** - Better to clarify than assume + +### For Bundle Maintainers + +1. **Keep AGENT.md as source of truth** - Don't duplicate in agent-specific configs +2. **Agent configs extend, not override** - Specific details only +3. **Test with multiple agents** - Ensure guidance works across platforms +4. **Version control everything** - Including MCP server configs +5. **Document exceptions** - When deviating from standard practices + +### For Developers + +1. **Review AGENT.md when onboarding** - Same guidance as AI uses +2. **Update AGENT.md for new patterns** - Keep AI context current +3. **Use conventional commits** - Enables automated versioning +4. **Follow PR workflow** - Draft → Ready → Review → Merge + +--- + +## Metrics and Validation + +### How to Validate AI Context Effectiveness + +| Metric | Good Signal | Bad Signal | +|--------|-------------|------------| +| Commit messages | Follow conventional format | Random/inconsistent | +| Branch names | Match pattern (`feature/*`, etc.) | Ad-hoc naming | +| PR descriptions | Complete, linked to issues | Empty/minimal | +| Code style | Matches existing patterns | Inconsistent | +| Test coverage | Tests written with features | Tests as afterthought | + +### Continuous Improvement + +1. **Track AI-generated commits** - Look for pattern violations +2. **Review PR quality** - Are descriptions complete? +3. **Monitor CI failures** - Are they preventable with better guidance? +4. **Collect feedback** - What do developers wish AI knew? +5. **Update AGENT.md** - Incorporate learnings + +--- + +## Related Documents + +- [Tagging and Versioning Strategy](tagging-and-versioning.md) - Version management +- [Frontmatter Standard](../adr/frontmatter-standard.md) - Document metadata +- [Phase 01: Foundation](../../plans/phases/bundle-contents-phase-01-foundation.md) - AGENT.md implementation From 216a25fa97b69e675c602ea0e5e004bf586cd39a Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 11:31:00 -0500 Subject: [PATCH 6/7] planning(bundle-contents): added 'planning' as type --- .ai/docs/adr/conventional-commit.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.ai/docs/adr/conventional-commit.md b/.ai/docs/adr/conventional-commit.md index 09ef85e..1fd7c83 100644 --- a/.ai/docs/adr/conventional-commit.md +++ b/.ai/docs/adr/conventional-commit.md @@ -9,6 +9,8 @@ feat | ✨ Features | minor | | release - wip|🚧|👷(): Work in progress +- planning|📝|📝(): Planning tasks + - "Planning tasks and strategies" - chore|🧹(): Maintenance tasks, dependencies - cleanup/trivial changes, syntax fixes, etc. - "Maintenance work and dependency updates" From 621a90735d733e3b26b9ce4f076c6fdd79842899 Mon Sep 17 00:00:00 2001 From: aRustyDev <36318507+aRustyDev@users.noreply.github.com> Date: Fri, 5 Dec 2025 13:38:00 -0500 Subject: [PATCH 7/7] docs(pr): add PR #14 analysis and description draft - Complete file inventory (44 files, ~560KB) - Analyzed main bundle-contents.md plan document - Documented 31-phase implementation structure - Summarized key architectural decisions (4-layer Rust defense, SARIF, OPA/Rego) - Drafted comprehensive PR description ready for use --- .../pull-requests/pr-14-bundle-contents.md | 432 ++++++++++++++++++ 1 file changed, 432 insertions(+) create mode 100644 .ai/plans/pull-requests/pr-14-bundle-contents.md diff --git a/.ai/plans/pull-requests/pr-14-bundle-contents.md b/.ai/plans/pull-requests/pr-14-bundle-contents.md new file mode 100644 index 0000000..6ef5241 --- /dev/null +++ b/.ai/plans/pull-requests/pr-14-bundle-contents.md @@ -0,0 +1,432 @@ +--- +id: E7A3B2C1-4D5E-6F7A-8B9C-0D1E2F3A4B5C +title: "PR #14 Analysis: Bundle Contents Planning" +status: "🔄 In Progress" +date: 2025-12-19 +author: AI Assistant +pr_url: https://github.com/aRustyDev/mcp/pull/14 +--- + +# PR #14: Bundle Contents Planning + +## Overview + +| Field | Value | +| ------------- | ------------------------------------------------------------------ | +| **PR Number** | #14 | +| **Title** | planning(bundle-contents): developing the release bundle templates | +| **State** | Open | +| **Author** | aRustyDev | +| **Created** | 2025-12-05T15:57:10Z | +| **Updated** | 2025-12-05T16:31:04Z | +| **Branch** | `pr/bundle-contents-planning` → `integration` | + +## Statistics + +| Metric | Value | +| ------------------- | ------ | +| **Additions** | 16,596 | +| **Deletions** | 0 | +| **Changed Files** | 44 | +| **Commits** | 6 | +| **Mergeable** | Yes | +| **Mergeable State** | Clean | + +--- + +## Commit History (6 commits) + +| # | SHA | Message | Date | +| --- | ---------- | ------------------------------------------------------------------------------- | ------------------- | +| 1 | `808a8f07` | docs(plans): added plan docs for developing the release bundle and its contents | 2025-12-05 15:56:01 | +| 2 | `89787bdb` | planning(bundle-contents): added plan docs for SAST | 2025-12-05 16:28:58 | +| 3 | `b247e5b9` | planning(bundle-contents): added plan docs for opa/rego development | 2025-12-05 16:29:32 | +| 4 | `2baeeb69` | planning(bundle-contents): added plan docs for tagging/versioning strategy | 2025-12-05 16:29:54 | +| 5 | `921ff407` | planning(bundle-contents): added plan docs for ai context development | 2025-12-05 16:30:22 | +| 6 | `216a25fa` | planning(bundle-contents): added 'planning' as type | 2025-12-05 16:31:00 | + +--- + +## Complete File Inventory (44 files) + +### Category 1: AI Planning Documents (38 files) - ~560KB + +#### Main Plan Document (1 file) + +| File | Size | +| ------------------------------ | ------------ | +| `.ai/plans/bundle-contents.md` | 20,412 bytes | + +#### Phase Documents (31 files) - ~410KB + +| File | Size | Topic | +| ------------------------------------------------------ | ---------- | -------------------- | +| `bundle-contents-phase-00-manual-setup.md` | 8,476 | Manual Setup | +| `bundle-contents-phase-01-foundation.md` | **79,446** | Foundation (LARGEST) | +| `bundle-contents-phase-02-build-pipelines.md` | 2,965 | Build Pipelines | +| `bundle-contents-phase-03-code-quality.md` | 32,756 | Code Quality | +| `bundle-contents-phase-04-testing-unit.md` | 3,050 | Unit Testing | +| `bundle-contents-phase-05-testing-property.md` | 3,411 | Property Testing | +| `bundle-contents-phase-06-testing-integration.md` | 3,405 | Integration Testing | +| `bundle-contents-phase-07-testing-e2e.md` | 3,389 | E2E Testing | +| `bundle-contents-phase-08-testing-performance.md` | 3,502 | Performance Testing | +| `bundle-contents-phase-09-testing-coverage.md` | 4,076 | Coverage | +| `bundle-contents-phase-10-testing-quality-gates.md` | 3,375 | Quality Gates | +| `bundle-contents-phase-11-testing-mcp-protocol.md` | 3,869 | MCP Protocol | +| `bundle-contents-phase-12-testing-mock-harness.md` | 3,705 | Mock Harness | +| `bundle-contents-phase-13-testing-chaos.md` | 3,909 | Chaos Testing | +| `bundle-contents-phase-14-security-dependencies.md` | 6,635 | Dependency Scanning | +| `bundle-contents-phase-15-security-licenses.md` | 9,129 | License Compliance | +| `bundle-contents-phase-16-security-sast.md` | 16,345 | SAST | +| `bundle-contents-phase-17-security-secrets.md` | 3,103 | Secrets Scanning | +| `bundle-contents-phase-18-security-memory.md` | 7,386 | Memory Safety | +| `bundle-contents-phase-19-security-fuzzing.md` | 8,802 | Fuzzing | +| `bundle-contents-phase-20-security-taint.md` | 19,479 | Taint Analysis | +| `bundle-contents-phase-21-security-containers.md` | **24,541** | Container Security | +| `bundle-contents-phase-22-security-compliance.md` | 8,584 | Compliance | +| `bundle-contents-phase-22a-policy-library.md` | 21,500 | Policy Library | +| `bundle-contents-phase-23-security-attestation.md` | 11,628 | Attestation | +| `bundle-contents-phase-24-release-versioning.md` | 14,160 | Versioning | +| `bundle-contents-phase-25-release-containers.md` | 4,086 | Container Release | +| `bundle-contents-phase-26-release-packages.md` | 3,618 | Package Release | +| `bundle-contents-phase-27-release-helm.md` | 9,584 | Helm Charts | +| `bundle-contents-phase-28-automation-issues.md` | 20,634 | Issue Automation | +| `bundle-contents-phase-29-automation-notifications.md` | 4,967 | Notifications | +| `bundle-contents-phase-30-automation-mcp.md` | 22,382 | MCP Automation | + +#### ADR Documents (6 files) - ~72KB + +| File | Size | +| ---------------------------------------------- | --------- | +| `.ai/docs/adr/conventional-commit.md` | 2,565 | +| `.ai/docs/adr/dependency-scanning-strategy.md` | 23,496 | +| `.ai/docs/adr/frontmatter-standard.md` | 16,708 | +| `.ai/docs/adr/keep-a-changelog.md` | 0 (empty) | +| `.ai/docs/adr/linting-strategy.md` | 15,404 | +| `.ai/docs/adr/wiki-documentation-strategy.md` | 13,888 | + +#### Strategy Documents (5 files) - ~101KB + +| File | Size | +| ----------------------------------------------- | ------ | +| `.ai/docs/strategies/ai-context.md` | 26,082 | +| `.ai/docs/strategies/policy-as-code.md` | 17,634 | +| `.ai/docs/strategies/sarif-strategy.md` | 23,716 | +| `.ai/docs/strategies/sast-strategy.md` | 23,730 | +| `.ai/docs/strategies/tagging-and-versioning.md` | 10,306 | + +#### Checklists (3 files) - ~14KB + +| File | Size | +| ------------------------------------------------- | ----- | +| `.ai/plans/checklists/gap-analysis.md` | 4,727 | +| `.ai/plans/checklists/implementation-tracking.md` | 5,472 | +| `.ai/plans/checklists/testing-validation.md` | 4,073 | + +#### References (2 files) - ~17KB + +| File | Size | +| ---------------------------------------------- | ------ | +| `.ai/plans/references/mcp-testing-taxonomy.md` | 12,333 | +| `.ai/plans/references/quick-start.md` | 5,085 | + +### Category 2: Bundle Templates (19 files) - ~34KB + +#### Bundle Root Files (4 files) + +| File | Size | +| ------------------------- | ------ | +| `bundles/CONTRIBUTING.md` | 3,816 | +| `bundles/MANIFEST.md` | 3,244 | +| `bundles/SECURITY.md` | 1,799 | +| `bundles/justfile` | 10,339 | + +#### Bundle GitHub Config (11 files) + +| File | Size | +| ------------------------------------------------------------- | ------ | +| `bundles/.github/CODEOWNERS` | 431 | +| `bundles/.github/FUNDING.yml` | 616 | +| `bundles/.github/labels.yml` | 10,248 | +| `bundles/.github/pull_request_template.md` | 641 | +| `bundles/.github/release-drafter.yml` | 1,527 | +| `bundles/.github/ISSUE_TEMPLATE/comparative-analysis.yml` | 1,279 | +| `bundles/.github/ISSUE_TEMPLATE/gap-identification.yml` | 1,294 | +| `bundles/.github/ISSUE_TEMPLATE/mcp-server-discovery.yml` | 1,613 | +| `bundles/.github/ISSUE_TEMPLATE/rust-rewrite.yml` | 1,395 | +| `bundles/.github/ISSUE_TEMPLATE/transport-implementation.yml` | 1,441 | + +#### Bundle Workflows (5 files) + +| File | Size | +| ------------------------------------------------- | ----- | +| `bundles/.github/workflows/dependency-review.yml` | 456 | +| `bundles/.github/workflows/hadolint.yml` | 358 | +| `bundles/.github/workflows/label-sync.yml` | 328 | +| `bundles/.github/workflows/mdbook-build.yml` | 1,043 | +| `bundles/.github/workflows/stale.yml` | 535 | + +### Category 3: Main Repo GitHub Config (12 files) + +#### Issue Templates (5 files) + +| File | Size | +| ----------------------------------------------------- | ----- | +| `.github/ISSUE_TEMPLATE/comparative-analysis.yml` | 1,279 | +| `.github/ISSUE_TEMPLATE/gap-identification.yml` | 1,294 | +| `.github/ISSUE_TEMPLATE/mcp-server-discovery.yml` | 1,613 | +| `.github/ISSUE_TEMPLATE/rust-rewrite.yml` | 1,395 | +| `.github/ISSUE_TEMPLATE/transport-implementation.yml` | 1,441 | + +#### Workflows (5 files) + +| File | Size | +| ------------------------------------------ | ---- | +| `.github/workflows/hadolint.yml` | 358 | +| `.github/workflows/label-sync.yml` | 328 | +| `.github/workflows/project-automation.yml` | 821 | +| `.github/workflows/stale.yml` | 535 | +| `.github/workflows/triage.yml` | 705 | + +#### Other GitHub Files (2 files) + +| File | Size | +| ---------------------------------- | ----- | +| `.github/labels.yml` | 4,727 | +| `.github/pull_request_template.md` | 641 | + +### Category 4: Documentation (12 files) + +#### mdBook Config (2 files) + +| File | Size | +| ----------------- | ---- | +| `docs/.gitignore` | 5 | +| `docs/book.toml` | 80 | + +#### Development Docs (4 files) + +| File | Size | +| --------------------------------------------------------- | ----- | +| `docs/src/SUMMARY.md` | 888 | +| `docs/src/development/common-features.md` | 1,148 | +| `docs/src/development/debugging.md` | 364 | +| `docs/src/development/security.md` | 951 | +| `docs/src/development/testing/unit-testing-mcp-server.md` | 538 | + +#### Project Management Docs (5 files) + +| File | Size | +| ----------------------------------------------- | ----- | +| `docs/src/project-management/fields.md` | 3,009 | +| `docs/src/project-management/index.md` | 1,292 | +| `docs/src/project-management/issue-strategy.md` | 4,168 | +| `docs/src/project-management/labels.md` | 5,527 | +| `docs/src/project-management/views.md` | 2,820 | + +### Category 5: Root Files (1 file) + +| File | Size | +| ---------- | ------ | +| `justfile` | 28,957 | + +--- + +## Analysis Summary + +### What This PR Delivers + +This PR establishes a **comprehensive planning framework** for developing a versioned MCP Server development bundle. The bundle is designed to be extracted into new repositories to provide standardized CI/CD workflows, templates, and configurations. + +### Core Concept + +> **This plan produces a versioned release artifact (bundle) for onboarding new repositories to "MCP Server Development" standards.** + +The bundle output includes: + +- `mcp-bundle-v{X.Y.Z}.tar.gz` - Versioned release archive +- `MANIFEST.md` - Bundle contents and installation guide +- `justfile` - Automated setup commands +- `AGENT.md` - AI agent instructions for target repo + +### Phase Structure (31 Phases) + +The implementation is organized into logical phases: + +| Category | Phases | Description | +| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------- | +| **Setup** | 00 | Manual setup (wiki, secrets, branch protection) | +| **Foundation** | 01 | Templates, labels, core configs, AGENT.md | +| **Build** | 02-03 | Container, Rust, Python, Node builds + Code quality/linting | +| **Testing** | 04-13 | Unit, property, integration, E2E, performance, coverage, quality gates, MCP protocol, mock harness, chaos | +| **Security** | 14-23 | Dependencies, licenses, SAST, secrets, memory safety, fuzzing, taint analysis, containers, compliance, policy library, attestation | +| **Release** | 24-27 | Versioning, containers, packages, Helm | +| **Automation** | 28-30 | Issues/PR automation, notifications, MCP evaluation | + +### Key Architectural Decisions + +1. **4-Layer Rust Supply Chain Defense** + - `cargo-audit` - Known CVEs (RustSec) + - `cargo-deny` - Policy enforcement (licenses, bans) + - `cargo-vet` - Audit trail verification + - `cargo-crev` - Community trust reviews + +2. **SARIF-Based Security Integration** + - Unified format for all security scanners + - Deduplication across tools + - GitHub Security tab integration + +3. **Policy-as-Code (OPA/Rego)** + - Unified policy library for container, compliance, and license enforcement + - CI/CD integration for policy validation + +4. **Multi-Language Support** + - Rust, Python, JavaScript/TypeScript, Go + - Container (Docker/OCI) support + - Helm chart workflows + +### Estimated Output + +| Category | Phases | Est. Files | +| --------------- | -------------- | -------------- | +| Foundation | 01 | ~48 | +| Build & Quality | 02-03 | ~13 | +| Testing | 04-13 | ~50 | +| Security | 14-22, 22a, 23 | ~65 | +| Release | 24-27 | ~20 | +| Automation | 28-30 | ~11 | +| **Total** | | **~230 files** | + +--- + +## Draft PR Description + +```markdown +## Summary + +This PR introduces comprehensive planning documentation for developing a versioned MCP Server development bundle. The bundle provides standardized CI/CD workflows, security scanning, testing frameworks, and automation for multi-language projects. + +## What's Included + +### 📋 Planning Framework (31 Phases) + +- **Main Plan**: `bundle-contents.md` - Overview and phase coordination +- **31 Phase Documents**: Detailed implementation guides covering setup through automation +- **3 Tracking Checklists**: Gap analysis, implementation tracking, testing validation +- **2 Reference Docs**: MCP testing taxonomy, quick start guide + +### 📚 Architecture Decision Records (ADRs) + +- Conventional commit standards +- Dependency scanning strategy (4-layer Rust defense) +- Frontmatter standards for documentation +- Linting strategy across languages +- Wiki documentation strategy + +### 🎯 Strategy Documents + +- **AI Context Strategy**: AGENT.md and AI agent behavioral guidance +- **Policy-as-Code**: OPA/Rego unified policy library design +- **SAST Strategy**: Static analysis tool selection and quality gates +- **SARIF Strategy**: Security result aggregation and deduplication +- **Tagging/Versioning**: Version source of truth and release coordination + +### 🔧 Bundle Templates + +- GitHub Actions workflows (hadolint, label-sync, stale, dependency-review, mdbook) +- Issue templates (5 types: comparative analysis, gap identification, MCP discovery, Rust rewrite, transport implementation) +- PR template, CODEOWNERS, FUNDING.yml +- justfile for automated setup +- CONTRIBUTING.md, SECURITY.md, MANIFEST.md + +### 📖 Documentation Structure + +- mdBook configuration for static site generation +- Development guides (common features, debugging, security, testing) +- Project management docs (fields, labels, views, issue strategy) + +## Implementation Phases Overview + +| Phase Group | Focus Area | Phases | +| --------------- | ---------------------------------- | ------ | +| Foundation | Templates, labels, core configs | 00-01 | +| Build & Quality | Multi-language builds, linting | 02-03 | +| Testing | Comprehensive test pyramid | 04-13 | +| Security | Defense-in-depth scanning | 14-23 | +| Release | Versioning, publishing | 24-27 | +| Automation | Issue/PR automation, notifications | 28-30 | + +## Security Approach + +- **Dependency Scanning**: 4-layer defense for Rust supply chain +- **SAST**: Semgrep + CodeQL with custom MCP rules +- **Container Security**: Trivy, Grype, Docker Scout integration +- **Secrets Scanning**: Gitleaks + TruffleHog +- **Compliance**: CIS benchmarks, PCI-DSS, HIPAA checklists +- **Attestation**: SLSA, SBOM, cosign signing + +## Testing Strategy + +- Unit, property-based, integration, E2E testing +- Performance benchmarks and regression detection +- Coverage collection with quality gates +- MCP-specific protocol conformance testing +- Chaos engineering for resilience validation + +## Type of Change + +- [x] Research/Analysis +- [x] Documentation +- [ ] Docker/Container +- [ ] Transport implementation +- [ ] Rust rewrite +- [ ] CI/CD + +## Breaking Changes + +None - this PR adds entirely new planning documentation and templates. + +## Checklist + +- [x] Planning documents complete +- [x] ADRs documented +- [x] Bundle template structure defined +- [x] Phase dependencies mapped +- [ ] Implementation ready to begin +``` + +--- + +## Analysis Progress + +### Stage 1: Metadata Collection ✅ COMPLETE + +- [x] PR metadata collected +- [x] Complete file inventory compiled +- [x] Files categorized by type +- [x] Main plan document analyzed +- [x] Quick start guide reviewed +- [x] Gap analysis checklist reviewed + +### Stage 2: Key Document Analysis ✅ COMPLETE + +- [x] `bundle-contents.md` - Main plan overview +- [x] Understanding of 31-phase structure +- [x] Bundle output format documented + +### Stage 3: PR Description Draft ✅ COMPLETE + +- [x] Summary written +- [x] What's Included sections detailed +- [x] Implementation phases overview +- [x] Security and testing approaches summarized + +--- + +## Notes + +- This is entirely NEW content (0 deletions), establishing foundational planning documentation +- The bundle is intended for NEW repositories, not direct application to aRustyDev/mcp +- Tasks marked `[MCP-REPO]` are exceptions for configuring the main repo +- Phase Gate process requires justfile review before each phase +- Estimated ~230 workflow/config/policy files when fully implemented