KeiSeiKit-1.0/skills/vm-provision/phase-1-select-provider.md
Parfii-bot eee5eecc20 feat(skills): /vm-provision 6-phase pipeline
Hub-and-spoke skill:
- SKILL.md (index) + phase-1-select-provider, phase-2-plan,
  phase-3-provision, phase-4-harden, phase-5-verify, phase-6-handoff.

Pipeline: select provider → Plan Mode doc → provision (hetzner/vultr
primitives, SSH first-contact TOFU) → harden-base.sh over SSH →
ssh-check + firewall-diff HARD GATE → artefact ledger + optional
/web-deploy handoff.

Invariants:
- ≥ 6 AskUserQuestion calls (Phase 1×2, 2×1, 3×1, 4×1, 5×1).
- Hard gate: Phase 6 refuses to run unless ssh-check AND firewall-diff
  both exit 0. "Ignore and proceed" is BLOCKED by design.
- RULE 0.8 (secrets ENV-ref only), RULE 0.4 (cite provider specifics),
  RULE 0.5 (plan.md written to <run-dir>/plan.md before provisioning),
  RULE -1 (every failure branch returns 2-3 constructive paths).

Defensive-only — no scanning tools, no CVE probes, no third-party
attack-surface analysis. Every phase file ≤ 200 LOC per Constructor
Pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 21:00:14 +08:00

3.6 KiB

Phase 1 — Select Provider + Region + Plan

Goal: lock PROVIDER, REGION, PLAN, ARCH via two AskUserQuestion calls. No provisioning yet — this is pure decision. Verify criterion: all four variables set; provider credentials (one env-var name) identified in ~/.claude/secrets/.env.


1.a — First AskUserQuestion (4 options max)

Provider? (single-select, stored as PROVIDER):

  • Hetzner Cloud — cheapest EU, CX22 x86 / CAX11 ARM64 both €3.79/mo [VERIFIED _blocks/deploy-hetzner-cloud.md]. Requires HCLOUD_TOKEN.
  • Vultr — broad region list, HF compute, $5-10/mo tiers. Requires VULTR_API_KEY.
  • DigitalOcean — strong US presence, simple API. Requires DIGITALOCEAN_TOKEN. Uses deploy-vps-generic.md cloud-init.
  • UpCloud — preferred for RU-routed workloads (Finnish ASN). Requires UPCLOUD_USERNAME + UPCLOUD_PASSWORD.

If the intent argument mentions a provider already, pre-select it.

Credential check BEFORE the click: read ~/.claude/secrets/.env; if the chosen provider's env var is absent, surface a ONE-line remediation:

"Provider X needs <VAR> in ~/.claude/secrets/.env. Add it and re-invoke — I don't accept tokens pasted into chat (RULE 0.8)."

Do NOT proceed until the token is in place.


1.b — Second AskUserQuestion (region + plan + arch, 3 Q's)

Send three questions in one AskUserQuestion call. Options are provider-specific; generate them from the following matrix (do NOT hallucinate codes — re-verify against the provider doc link on each run):

Region (stored as REGION):

  • Hetzner: fsn1 (Falkenstein DE), nbg1 (Nürnberg DE), hel1 (Helsinki FI), ash (Ashburn US), hil (Hillsboro US), sin (Singapore) [VERIFIED https://docs.hetzner.com/cloud/general/locations].
  • Vultr: ams (Amsterdam), fra (Frankfurt), ewr (Newark), lax (LA), nrt (Tokyo), sgp (Singapore).
  • DigitalOcean: nyc1/2/3, sfo3, ams3, fra1, lon1, sgp1.
  • UpCloud: de-fra1, fi-hel1, fi-hel2, us-nyc1, sg-sin1.

Pick the closest region to the user's stated audience. Prefer the EU when the user doesn't specify (lower GDPR exposure).

Plan (stored as PLAN):

  • Hetzner x86: cx22 (2 vCPU / 4 GB / 40 GB / €3.79/mo), cx32 (4 vCPU / 8 GB / €6.79/mo).
  • Hetzner ARM: cax11 (2 vCPU / 4 GB / €3.79/mo), cax21 (4 vCPU / 8 GB / €6.49/mo).
  • Vultr: vc2-1c-1gb ($6/mo), vc2-2c-4gb ($24/mo), vhp-1c-2gb-amd ($14/mo).
  • DigitalOcean: s-1vcpu-1gb ($6/mo), s-2vcpu-2gb ($18/mo).
  • UpCloud: 1xCPU-1GB, 2xCPU-2GB.

Quote only the plans you can verify against the provider's live pricing at call-time; do not embed stale pricing as fact.

Arch (stored as ARCH):

  • x86_64 — default; works with every Debian 12 image.
  • arm64 — Hetzner cax*, AWS Graviton, Oracle Ampere. ~25% cheaper. Rust builds run natively; Node/Python binary wheels may need extra install steps.

1.c — Verify criterion

Before moving to Phase 2:

  • PROVIDER, REGION, PLAN, ARCH all set.
  • The provider credential env-var EXISTS in ~/.claude/secrets/.env (we only read the env-var name, never the value).
  • The user clicked OK, not "back".

Emit one-liner:

Phase 1 done: PROVIDER=<x> REGION=<y> PLAN=<z> ARCH=<a>. Credentials ref: $<VAR>.

Proceed to Phase 2.


1.d — Constructive-fail paths

If the user says "I don't know":

  • (A) Default to Hetzner CX22 fsn1 x86 (cheapest EU). 1-click.
  • (B) Clone an existing project's provider (ask which project, pattern-match from ~/.claude/projects/*/memory/*.md).
  • (C) Defer provisioning — emit a decision memo and exit cleanly.

Never pick silently.