Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,39 @@ jobs:
run: pytest packages/mcp/tests/ -x -q --timeout=30
if: hashFiles('packages/mcp/tests/') != ''

security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install packages
run: |
pip install --upgrade pip
pip install -e ./packages/core
pip install -e ./packages/cli
pip install -e ./packages/web
pip install -e ./packages/mcp
- run: pip install pip-audit
- name: Audit dependencies for known CVEs
# Blocking gate: verified locally (2026-07) that the real dependency
# tree (anthropic, openai, pydantic, pyyaml, fastapi, ...) is clean;
# the only prior noise was pip itself on an unpatched runner image,
# which the pip upgrade above resolves. The 4 cloudwright-ai-* local
# editable packages are skipped as "not found on PyPI", which is expected.
run: pip-audit

version-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Check version markers agree
run: python3 scripts/check_version_sync.py

build:
runs-on: ubuntu-latest
steps:
Expand Down
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,32 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.7.0] - 2026-07-08

Closes the July 2026 product audit findings. The differentiating features (offline review,
compliance with OSCAL) now reach every MCP-capable coding agent, not just the CLI; the web tier
is hardened against event-loop stalls and oversized payloads; cost output stops claiming
freshness it does not have; and a new `integrate` command wires cloudwright into 11 coding
harnesses.

### Added

- **`cloudwright integrate`.** Generates the exact MCP server config for each popular coding agent (Claude Code, Cursor, Cline, Windsurf, GitHub Copilot, Zed, OpenAI Codex CLI, JetBrains Junie, Kiro, Antigravity) in that client's own format (`mcpServers`, VS Code `servers`, Zed `context_servers`, or Codex TOML), plus a CLI-pipe path for Aider (not an MCP client). `--rules` emits a harness-agnostic gate block for AGENTS.md, CLAUDE.md, or GEMINI.md that tells any agent to run `cloudwright review`/`cost`/`compliance` before it writes infrastructure. `--write` merges into the right file without clobbering existing servers. See `docs/integrations.md`.
- **Review, compliance, and plan as MCP tools.** The MCP server now exposes `review_architecture` (offline critique, no API key), `scan_compliance_controls` (control-mapped findings, with an `oscal` flag returning the OSCAL 1.1.2 component-definition), and `plan_infrastructure` (read-only, validate-only by default, never applies). Any MCP client gets cloudwright's design-time checks in its agent loop.
- **Review and OSCAL on the web canvas.** New `POST /api/review` runs the offline critique; `POST /api/compliance` takes an `oscal` flag. The canvas gains a Review tab (score, grade, findings) and an OSCAL JSON download on the Compliance panel.
- **Honest cost signals.** Cost estimates now report `prices_as_of` (the catalog vintage) and `estimated_on` (today) separately instead of stamping today's date on older price data, and expose a `pricing_confidence_detail` ratio ("17/20 line items catalog-backed"). Cross-provider `compare` carries a per-alternative confidence column. Region pricing uses a real regional catalog row when one exists (high confidence) and only falls back to the static multiplier (medium) when none does. New `docs/provider-coverage.md` states per-provider coverage plainly.
- **MCP session TTL.** MCP sessions older than `CLOUDWRIGHT_MCP_SESSION_TTL_DAYS` (default 7) are swept on server start and session-list.
- **Release and security docs.** `RELEASING.md` (the release runbook) and `SECURITY.md` (disclosure policy) are now committed, plus `schema_version` on the persisted spec for future migrations.

### Fixed

- **Web tier no longer stalls the event loop.** Diagram rendering (a d2 subprocess up to 300s) now runs via `asyncio.to_thread`, so one PNG request no longer freezes every other request on the worker. `/api/diagram` gained a request model, so bad input returns 4xx instead of a raw 500.
- **Request-size and component-count caps.** A 1 MB body-size limit and a component-count cap protect the spec-accepting endpoints from resource-exhaustion payloads. The per-IP rate-limiter buckets are now evicted instead of growing without bound.
- **Container no longer serves unauthenticated by accident.** With `CLOUDWRIGHT_REQUIRE_AUTH=1` (set in the Dockerfile) and no `CLOUDWRIGHT_API_KEY`, the app refuses to start; docker-compose fails fast on an empty key. Local `uvicorn` stays open-by-default for development.
- **Structured logging activates on real launch paths.** `configure_logging()` now runs in `create_app()`, so `cloudwright chat --web` and bare `uvicorn` get structured logs and request-id correlation, not just `serve()`.
- **Clean CLI errors.** A malformed spec file now prints `Error: Invalid spec file: field 'name' is required` instead of a Pydantic traceback, and `--json` mode emits `{"error": {"code": ..., "message": ...}}` on failure. Full tracebacks remain available with `--verbose`.
- **CI gains a dependency-CVE gate and a version-sync check.** A `pip-audit` job and a `check_version_sync.py` job (asserting all 13 version markers agree) now run in CI.

## [1.6.1] - 2026-07-08

Hotfix for a crash in the flagship command, found by the July 2026 product audit.
Expand Down
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ COPY packages/web/cloudwright_web/ packages/web/cloudwright_web/

RUN pip install --no-cache-dir ./packages/core ./packages/web

# This CMD binds 0.0.0.0 directly via uvicorn, bypassing the CLI's serve()
# (the only place that used to enforce CLOUDWRIGHT_API_KEY). Setting this
# makes cloudwright_web.app.create_app() refuse to start unauthenticated.
ENV CLOUDWRIGHT_REQUIRE_AUTH=1

EXPOSE 8000

CMD ["uvicorn", "cloudwright_web.app:app", "--host", "0.0.0.0", "--port", "8000"]
27 changes: 22 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ cloudwright design "HIPAA healthcare API on AWS with Postgres and Redis"

Cloudwright takes a one-line description of a cloud system and produces a structured architecture spec, a per-component cost breakdown, a compliance report, and ready-to-apply Terraform, Pulumi (TypeScript or Python), or CloudFormation. It works across AWS, GCP, Azure, and Databricks. The latest work adds compliance scanning that maps every finding to the framework control it violates (HIPAA / SOC 2 / FedRAMP / PCI-DSS / ISO 27001 / NIST), a `cloudwright plan` step that proves the exported infrastructure actually deploys, and live import for GCP and Azure alongside AWS.

[Try it](#quickstart) - [What's new](#whats-new) - [Docs](docs/) - [MCP server](#mcp-server-claude--cursor--cline)
[Try it](#quickstart) - [What's new](#whats-new) - [Docs](docs/) - [MCP server](#mcp-server-works-with-every-mcp-client)

## What you get

Expand Down Expand Up @@ -68,18 +68,18 @@ cloudwright chat --web
# Open http://localhost:8765, use the Catalog drawer, then Export -> Terraform
```

## MCP server (Claude / Cursor / Cline)
## MCP server (works with every MCP client)

Expose Cloudwright as [Model Context Protocol](https://modelcontextprotocol.io/) tools so AI agents can design, cost, validate, and export architectures directly. 18 tools across 6 groups (design, cost, validate, analyze, export, session).
Expose Cloudwright as [Model Context Protocol](https://modelcontextprotocol.io/) tools so AI agents can design, cost, validate, review, check compliance, plan, and export architectures directly. Almost every popular coding agent is an MCP client (Claude Code, Cursor, Cline, Windsurf, GitHub Copilot, Zed, OpenAI Codex CLI, JetBrains Junie, Kiro, Antigravity), so one server puts cloudwright inside all of their agent loops. Tool groups: design, cost, validate, analyze, export, session, review, compliance, plan.

```bash
pip install cloudwright-ai-mcp
cloudwright mcp # all tools, stdio
cloudwright mcp --tools design,cost # subset
cloudwright mcp --tools design,cost,review # subset
cloudwright mcp --transport sse # SSE for HTTP clients
```

`claude_desktop_config.json` (same shape works for Cursor and Cline):
Do not hand-write the config. `cloudwright integrate --harness <name>` prints the exact wiring for your agent in its own format, and `--write` merges it into the right file. For a manual setup, the base shape (Claude Code, Cursor, Cline, Windsurf, Copilot, Junie) is:

```json
{
Expand All @@ -92,6 +92,8 @@ cloudwright mcp --transport sse # SSE for HTTP clients
}
```

Zed uses `context_servers`, VS Code Copilot uses `servers`, and Codex CLI uses a `[mcp_servers.cloudwright]` TOML table. `cloudwright integrate` emits the right one for each, and Aider (not an MCP client) gets a CLI-pipe recipe. Full matrix in [docs/integrations.md](docs/integrations.md).

## Analysis

`cloudwright lint` (10 anti-pattern checks), `cloudwright score` (5-dimension quality grade), `cloudwright analyze` (blast radius and SPOF), `cloudwright drift <spec> <tfstate>` (design vs deployed), `cloudwright policy --rules policy.yaml` (policy-as-code with 9 built-in checks), `cloudwright security` (security anti-patterns; also scans exported Terraform HCL), `cloudwright compliance <spec> --frameworks hipaa,soc2,fedramp` (every finding mapped to its HIPAA / SOC 2 / FedRAMP / PCI-DSS / ISO 27001 / NIST control ID, with optional Checkov deep scan), and `cloudwright plan <spec> --target terraform` (proves the exported artifact validates / plans). Every command supports `--json`. See [docs/](docs/) and the `examples/` directory for end-to-end samples.
Expand All @@ -112,6 +114,21 @@ hcl = export_spec(spec, "terraform", output_dir="./infra")

<a id="whats-new"></a>

## What's new in v1.7.0

Cloudwright's design-time checks now reach every coding agent, not just its own CLI. Almost every popular AI coding harness speaks MCP, so one server puts `review`, `compliance`, and `plan` inside their agent loops.

- **`cloudwright integrate` wires cloudwright into 11 harnesses.** It writes the MCP server config in each client's own format (Claude Code, Cursor, Cline, Windsurf, GitHub Copilot, Zed, OpenAI Codex CLI, JetBrains Junie, Kiro, Antigravity), and gives Aider the CLI-pipe path. `cloudwright integrate --rules` emits a gate block for AGENTS.md, CLAUDE.md, or GEMINI.md that tells any agent to run `cloudwright review`/`cost`/`compliance` before it writes infrastructure. See [docs/integrations.md](docs/integrations.md).
- **The MCP server exposes the differentiators.** New `review_architecture` (offline critique, no key), `scan_compliance_controls` (control-mapped, with an `oscal` flag), and read-only `plan_infrastructure` tools. Every MCP client gets them.
- **Review and OSCAL on the web canvas.** A Review tab (score, grade, findings) and an OSCAL JSON download on the Compliance panel.
- **Cost stops overclaiming.** Estimates report `prices_as_of` (catalog vintage) separately from `estimated_on` (today), show a "17/20 catalog-backed" ratio, carry per-alternative confidence in `compare`, and use a real regional price row when the catalog has one. [docs/provider-coverage.md](docs/provider-coverage.md) states per-provider coverage plainly.
- **Web hardening.** Diagram rendering no longer blocks the event loop, spec payloads are size- and component-capped, the container refuses to serve unauthenticated by accident, and malformed input returns a clean error instead of a traceback.

```bash
cloudwright integrate --harness claude-code # MCP config for your agent
cloudwright integrate --rules --agent-file claude # gate block for CLAUDE.md
```

## What's new in v1.6.0

<p align="center">
Expand Down
105 changes: 105 additions & 0 deletions RELEASING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Releasing Cloudwright

This repo publishes four PyPI packages from one monorepo: `cloudwright-ai` (core),
`cloudwright-ai-cli`, `cloudwright-ai-web`, `cloudwright-ai-mcp`. All four always ship
together at the same version number.

## 1. Bump the version in all four packages

Edit `__version__` in:

- `packages/core/cloudwright/__init__.py`
- `packages/cli/cloudwright_cli/__init__.py`
- `packages/web/cloudwright_web/__init__.py`
- `packages/mcp/cloudwright_mcp/__init__.py`

Then update the `==X.Y.Z` extras pins in `packages/core/pyproject.toml`
(`cli`, `web`, `mcp`, `all`) to match.

## 2. Bump server.json

`server.json` describes the MCP registry entry. Update both:

- the top-level `"version"` field
- `"packages"[0]["version"]`

Keep `"description"` at 100 characters or fewer; the MCP registry rejects longer values.

## 3. Update the changelog

Add a new `## [X.Y.Z] - YYYY-MM-DD` section to `CHANGELOG.md` under `[Unreleased]`,
following the existing Keep a Changelog format. Update the README "What's new" section
if the release changes user-facing behavior.

## 4. Verify version sync locally

```bash
python3 scripts/check_version_sync.py
```

This checks that all four `__init__.py` files, the core package's extras pins, and
both version fields in `server.json` agree. It exits 1 with a listing of every
mismatched source if they don't. The same check runs in CI (`version-sync` job) and
gates every push, PR, and tag build.

Optionally pass an expected version to check against a specific tag:

```bash
python3 scripts/check_version_sync.py 1.7.0
```

## 5. Branch, PR, merge

- Cut a feature branch off `origin/main` for the version bump and changelog entry.
- Open a PR. Wait for CI to go green: `lint`, `test`, `security`, `version-sync`, `build`.
- Squash-merge to `main`.

## 6. Tag and push

```bash
git checkout main
git pull origin main
git tag -a vX.Y.Z -m "vX.Y.Z"
git push origin vX.Y.Z
```

Pushing a `v*` tag triggers `.github/workflows/publish.yml`, which re-runs the full CI
workflow and then builds and publishes all four wheels to PyPI using the
`PYPI_API_TOKEN` repository secret.

Watch the run:

```bash
gh run list --workflow=publish.yml
```

## 7. Smoke test the published wheels

PyPI's CDN can lag a minute or two after a successful publish. Once the workflow
succeeds:

```bash
python3 -m venv /tmp/release-verify
source /tmp/release-verify/bin/activate
pip install 'cloudwright-ai[cli]==X.Y.Z'
cloudwright --help
# exercise every new or changed CLI command with a minimal real input
```

Do not rely on an editable install for this step. Editable installs skip packaging
concerns entirely: missing bundled data files, wheel layout paths, and entry-point
bugs only show up against the built wheel.

## 8. Publish to the MCP registry

This step is interactive and requires the maintainer to log in. Once the wheels are
live on PyPI (the registry validates that the referenced package and version exist):

```bash
mcp-publisher login github
mcp-publisher validate server.json
mcp-publisher publish server.json
```

After this, Glama's tool re-introspection for the updated server is a manual click in
the Glama dashboard and must be done by the maintainer separately.
37 changes: 37 additions & 0 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Security Policy

## Supported Versions

Cloudwright ships four packages (`cloudwright-ai`, `cloudwright-ai-cli`,
`cloudwright-ai-web`, `cloudwright-ai-mcp`) that always release together at the same
version. Only the latest published version on PyPI is supported with security fixes.
Older versions do not receive backports; upgrade to the latest release to pick up a fix.

## Reporting a Vulnerability

Do not open a public GitHub issue for a suspected security vulnerability.

Instead, open a private security advisory on this repository:
https://github.com/xmpuspus/cloudwright/security/advisories/new

Include:

- A description of the vulnerability and its impact
- Steps to reproduce, or a minimal proof of concept
- The affected version(s)

## Response Window

Expect an initial response within 5 business days. Confirmed vulnerabilities are fixed
and released as soon as practical given severity; the reporter is credited in the
advisory and the release notes unless anonymity is requested.

## Scope

This policy covers the code in this repository: the ArchSpec model, the LLM-driven
architect, cost estimation, security/compliance scanning, the exporters (Terraform,
Pulumi, CloudFormation, OpenTofu), the live cloud importers, the CLI, the web backend
and frontend, and the MCP server. It does not cover the security of the third-party
cloud accounts, credentials, or generated infrastructure a user provisions with
Cloudwright's output; review generated Terraform/Pulumi/CloudFormation before applying
it, as you would any infrastructure code.
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ services:
ports:
- "8000:8000"
environment:
- CLOUDWRIGHT_API_KEY=${CLOUDWRIGHT_API_KEY}
- CLOUDWRIGHT_API_KEY=${CLOUDWRIGHT_API_KEY:?set CLOUDWRIGHT_API_KEY}
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- CLOUDWRIGHT_CORS_ORIGINS=${CLOUDWRIGHT_CORS_ORIGINS:-http://localhost:5173}
- CLOUDWRIGHT_LOG_FORMAT=json
Expand Down
Loading
Loading