Skip to content

Slice 6: jotsmith setup #6

@MaxAnderson95

Description

@MaxAnderson95

What to build

Implement jotsmith setup per PRD §6.1. This is the first slice that writes to Azure. It enables static website hosting if needed, creates the RSA 2048 signing key if missing, uploads the discovery doc and JWKS, and writes the local config file. Re-running setup with the same args is a no-op for KV state and a refresh-upload for storage state. --force rotates the signing key (same effect as key rotate from a later slice).

The only control-plane mutation this tool is ever allowed to make (per ADR-0002) is enabling static website hosting on an existing SA. No other resource provisioning is added.

Acceptance criteria

  • CLI surface matches PRD §6.1 exactly: jotsmith setup --subscription <id> --storage-account <name> --key-vault <name> [--key-name signing-key] [--force] [--force-issuer-rewrite]
  • Missing required-flag → exit code 2 with clear stderr error
  • DefaultAzureCredential failure prints which chain step failed and the resolved tenant (if any); exits non-zero
  • Verifies the subscription is accessible and the named SA + KV are visible via ARM Get
  • If SA static website hosting is not enabled, it is enabled (index document = empty, no error doc); otherwise existing state is accepted
  • Reads SA PrimaryEndpoints.Web after enable; freezes it (trailing / stripped) as config issuer
  • Validates the SA region supports static websites and the SKU is GPv2; clear error otherwise (resolves PRD §10 OQ Slice 2: config package + jotsmith config show #2)
  • If KV is in legacy access-policy mode, refuses with the same error as doctor
  • If KV key with --key-name exists and is enabled: kept as-is unless --force, in which case a new version is created
  • If KV key does not exist: created as RSA 2048 with keyOps: [sign, verify]
  • JWK computed from current public key; kid = RFC 7638 thumbprint
  • Discovery doc + JWKS uploaded (overwriting) to $web/<discovery_path> and $web/<jwks_path> with Content-Type: application/json and Cache-Control: no-cache
  • Config file written to the resolved path after the upload succeeds (no half-written config)
  • Summary printed to stderr: issuer URL, kid, discovery URL, JWKS URL
  • Re-running setup with the same args is idempotent: no-op for KV, refresh-upload for storage
  • --force documented in --help as "rotates the key (same effect as key rotate)"
  • --force-issuer-rewrite lets the user opt into rewriting config issuer when the SA endpoint legitimately changed (used by doctor's repair flow in a later slice)
  • Confirmation prompt before destructive operations (--force rotation, --force-issuer-rewrite) unless --yes
  • Integration test behind //go:build integration documents required RBAC

Blocked by

Originally created in OpenCode session ID: ses_17ca8efd8ffexLcFSysAMDVNBQ

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentFully specified, ready for an AFK agent to pick up

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions