deploy-web
Publish a Kiro Crew artifact (HTML / markdown / widget) to a public HTTPS URL on the user's own AWS account (private S3 + CloudFront + OAC). Use when the user says "publish this publicly", "deploy thi
SKILL.mdsrc/kiro_crew/deploy/skills/deploy-web/SKILL.md
GitHubdeploy-web — publish artifacts to your own AWS
deploy-web is a core Artifact Deploy feature, not an installable built-in app. The
deploy/recall/destroy mechanics run as deterministic Python in src/kiro_crew/deploy/
(it shells to the aws CLI with --profile). This skill is the chat-native front
door + the AI-guided one-time setup. You never read, store, or manage credentials,
and you never perform an IAM write — the /deploy console generates policy text the user
applies themselves (design Option A).
UI entry point (Route B, design §1.1): publishing is initiated from an artifact's page (Publish → "Publish to public web (your AWS)"), backed by
POST /api/deploy/deploy. The core Artifact Deploy console at/deployowns profile setup, health checks, pending confirmations, and Manage Sites (Recall/Destroy); it has no static-artifact publish form. The chat-native path (this skill) still drives the same deploy endpoint, through the preview-onlydeploy_artifacttool.
Hard rules (never violate)
- Never run
aws configure,aws sso login,ada, or any credential-establishing command on the user's behalf. Tell them to run it themselves. - Never create/attach/modify IAM roles or policies. Generate the JSON; the user applies it.
- Never auto-approve deploy / recall / destroy. Each is per-invocation confirmed.
- Publishing makes content world-readable. Always state this before deploying.
Backend endpoints (dashboard/core contract; do not reinvent the aws flow)
Agents use the MCP deploy_artifact tool for previews; they do not self-confirm by
posting these routes. Profile management, pending confirmation, Recall, and Destroy belong
in the /deploy console.
GET/PUT /api/deploy/config— legacy default-profile view; GET also returnscloudDeploymentEnabledGET/POST /api/deploy/profiles;PUT/DELETE /api/deploy/profiles/{name}— multi-profile registry control planeGET /api/deploy/iam-policy[?tier=static|fullstack]— generated policy JSONGET /api/deploy/pricing?profile=<name>— live/fallback estimate ratesPOST /api/deploy/verify{profile}— read-only reachability, not full verificationPOST /api/deploy/deploy{site_id, artifact_slug|local_dir, profile?, ttl_hours?, confirm?, override_scan?}— direct dashboard two-step flowPOST /api/deploy/recall/destroy— two-step withdrawal flowsGET /api/deploy/list— live site listPOST /api/deploy/teardown/{slug}— webapp tombstone/reaper handoffGET /api/deploy/pending;POST /api/deploy/pending/{id}/confirm|dismiss— human handling of MCP-generated previews
Guided installation (one-time, ~10–15 min — runs once, reused forever)
Step 1 — AWS access (user-run; console-managed)
Send the user to /deploy. They run aws configure sso or configure a named profile
on the gateway host themselves, then register its name and region in the Profiles control
plane. The console may write only the allowlisted region and credential_process AWS
config keys; it never writes credential values. Click Verify access, which calls
POST /api/deploy/verify with the registered profile.
- If not reachable: tell them exactly what to run (
aws sso login --profile <name>for expired SSO; install AWS CLI v2 if missing) and re-verify. Do not run it for them. - On success, report the resolved account + that access is reachable (not "verified").
Step 2 — Permissions (console generates; user applies)
The console calls GET /api/deploy/iam-policy, shows the JSON, and tells the user to
apply it themselves (AWS console or their own aws iam command) on a dedicated
role/identity. For fullstack it also emits the required kirocrew-deploy-app-boundary
policy. Offer only: "I'll apply it myself" (the only apply path) / "Explain it".
You do not apply IAM. A second read-only Verify check still means "access reachable,
not fully verified — first deploy is the real test."
Step 3 — Done
Confirm config is saved (profile name + region only). Offer to publish the first artifact.
Deploy flow (MCP preview, human execution)
- For
widget,html, ormarkdown, calldeploy_artifactwithsite_idandartifact_slug. Awebappartifact also goes byartifact_slug: the server resolves its builtpublic/root fromwebapp_metadata.app_dirand records the deployment back onto the artifact. It refuses withcode: "webapp_root_unavailable"when there is no built root; awebappwithout metadata is still rejected. Uselocal_dironly for a static directory that is not an artifact. - The tool calls the preview path without
confirmoroverride_scan→ you get a preview that states the public nature + a pre-publish scan summary. It never creates infrastructure. A clean preview or overridable non-credential scan finding is stored under Pending confirmations on/deploy. - Show the preview to the user, state that the URL will be world-readable with no authentication, then direct the human to review and confirm there. If the scan blocked, show the flagged findings: credential findings are a hard block, and only the dashboard can explicitly override non-credential findings after the user says publish anyway. Never self-confirm.
The preview makes no AWS call and you never see the confirmed deploy's result: the human
confirms on /deploy, and that page shows the outcome. A preview is not a deployment;
never tell the user a site is live or provisioning on the strength of it. If the user
reports back what the dashboard showed:
- On
AccessDenied(502; the error names the policy statement), tell the user the exact IAM statement to add to the policy, then they re-run (deploys are idempotent). - After a first deploy (
status: "InProgress",reused: false), tell the user the site is provisioning and can take up to ~15 minutes to go live while CloudFront finishes its first global deployment — until then the URL returns a DNS / "site can't be reached" error (this is expected, not a failure). They can watch the live status flip from In Progress → Deployed in the Deployments card on/deploy(or viaGET /api/deploy/list). Re-deploys to an existing site go live in seconds.
For an app with a backend, this skill is not the fullstack path: the operator must use the
artifact-deploy skill's scripts/deploy-app.sh, which places static and API resources
behind the same shared distribution.
Recall vs Destroy
Run both from the /deploy console; the dashboard performs the preview + explicit
confirmation and binds the confirmed call to the previewed resource ids.
- Recall = fast unpublish (empties objects + invalidates; URL → 404; infra stays; reversible). Caveat: edge caches may serve briefly; already-downloaded content can't be recalled.
- Destroy = full teardown (disable → wait → delete distribution, OAC, bucket). Irreversible.