Make specgen's value providers pluggable through pkg/valuesource instead of baking ssm/tailscale into codegen #283

Closed
opened 2026-08-14 01:28:22 +00:00 by coilyco-ops · 0 comments
Member

Split out of the dead-package sweep (see #282). Everything else in that sweep landed; this is the one AWS surface left standing, because it is live and removing it would break AOS.

What is there now

http/specgen/codegen/codegen.go carries a HasSSM (and sibling HasTailscale) flag that gates emitted consumer code:

  • codegen.go:105-107 - HasSSM / HasTailscale fields on the template payload
  • codegen.go:173 - set from the parsed spec
  • codegen.go:251-252 - emits awsconfig "github.com/aws/aws-sdk-go-v2/config" and "github.com/aws/aws-sdk-go-v2/service/ssm" into the generated file
  • codegen.go:320 - registers "ssm": ssmTokenResolver in the generated resolver table
  • codegen.go:411-433 - emits getSSMParam, plus a ~/.aws/credentials SSO-shadowing workaround that prints an operator note to stderr

So the generator knows one cloud vendor's SDK, its config-file precedence rules, and its parameter-store API shape.

Why it did not just get deleted

It is load-bearing. Two AOS guardfiles resolve tokens through it:

  • .specgen/guardfiles/aosguard/actions.kdl:7 - value ssm "/forgejo/coilyco-ops/api-token"
  • .specgen/guardfiles/aosguard/forgejo.kdl:18 - value ssm "/forgejo/coilyco-ops/api-token"

Deleting the branch breaks AOS token minting, so this needs a replacement rather than a removal.

Why it is worth fixing

It contradicts the repo's own doctrine two ways:

  • AGENTS.md, Repo boundaries: "Every package here must be importable from a different binary without consumer-specific types or defaults leaking in."
  • AGENTS.md, Safety: cli-guard "is a policy-free engine."

A vendor SDK hardcoded in the generator is exactly the leak those rules forbid. It also means every consumer of specgen inherits an aws-sdk-go-v2 dependency edge whether or not it resolves anything from SSM.

The shape of the fix

pkg/valuesource already exists as the "shared value <provider> resolution" primitive, and mcp-beaver already imports it. The provider set should come from there and be registerable by the consumer, rather than being a fixed if HasSSM branch in the template:

  1. Give pkg/valuesource a provider-registration surface (name -> resolver constructor).
  2. Have codegen emit a resolver table built from the providers the spec actually names, with no vendor import unless a registered provider supplies one.
  3. Move the ssm provider (and its ~/.aws/credentials SSO workaround) out of umbra and into the consumer that wants it - AOS is the only current one.
  4. Keep tailscale on the same path; it has the identical shape.

Acceptance: grep -ri aws http/ cli/ pkg/ cmd/ returns nothing in shipped non-test code, and AOS's actions.kdl / forgejo.kdl still mint tokens with no guardfile syntax change.

A smaller instance of the same problem is marked TODO(#282) in cli/execverb/argv.go: the valueFlags table is still one vendor's global-flag list. It stayed because dropping it silently weakens a live guard - with aws s3 ls --region us-east-1 s3://my-tfstate, losing the strip makes arg0 resolve to us-east-1 and AOS's deny-when arg0 matches *tfstate* fails open. Right fix there is declaring value-taking flags in the guardfile, where the spec knows its own binary. Worth doing in the same pass if the provider work opens that door.

Split out of the dead-package sweep (see #282). Everything else in that sweep landed; this is the one AWS surface left standing, because it is live and removing it would break AOS. ## What is there now `http/specgen/codegen/codegen.go` carries a `HasSSM` (and sibling `HasTailscale`) flag that gates emitted consumer code: - `codegen.go:105-107` - `HasSSM` / `HasTailscale` fields on the template payload - `codegen.go:173` - set from the parsed spec - `codegen.go:251-252` - emits `awsconfig "github.com/aws/aws-sdk-go-v2/config"` and `"github.com/aws/aws-sdk-go-v2/service/ssm"` into the generated file - `codegen.go:320` - registers `"ssm": ssmTokenResolver` in the generated resolver table - `codegen.go:411-433` - emits `getSSMParam`, plus a `~/.aws/credentials` SSO-shadowing workaround that prints an operator note to stderr So the generator knows one cloud vendor's SDK, its config-file precedence rules, and its parameter-store API shape. ## Why it did not just get deleted It is load-bearing. Two AOS guardfiles resolve tokens through it: - `.specgen/guardfiles/aosguard/actions.kdl:7` - `value ssm "/forgejo/coilyco-ops/api-token"` - `.specgen/guardfiles/aosguard/forgejo.kdl:18` - `value ssm "/forgejo/coilyco-ops/api-token"` Deleting the branch breaks AOS token minting, so this needs a replacement rather than a removal. ## Why it is worth fixing It contradicts the repo's own doctrine two ways: - AGENTS.md, Repo boundaries: "Every package here must be importable from a different binary without consumer-specific types or defaults leaking in." - AGENTS.md, Safety: cli-guard "is a policy-free engine." A vendor SDK hardcoded in the generator is exactly the leak those rules forbid. It also means every consumer of specgen inherits an `aws-sdk-go-v2` dependency edge whether or not it resolves anything from SSM. ## The shape of the fix `pkg/valuesource` already exists as the "shared `value <provider>` resolution" primitive, and mcp-beaver already imports it. The provider set should come from there and be registerable by the consumer, rather than being a fixed `if HasSSM` branch in the template: 1. Give `pkg/valuesource` a provider-registration surface (name -> resolver constructor). 2. Have codegen emit a resolver table built from the providers the spec actually names, with no vendor import unless a registered provider supplies one. 3. Move the `ssm` provider (and its `~/.aws/credentials` SSO workaround) out of umbra and into the consumer that wants it - AOS is the only current one. 4. Keep `tailscale` on the same path; it has the identical shape. Acceptance: `grep -ri aws http/ cli/ pkg/ cmd/` returns nothing in shipped non-test code, and AOS's `actions.kdl` / `forgejo.kdl` still mint tokens with no guardfile syntax change. ## Related A smaller instance of the same problem is marked `TODO(#282)` in `cli/execverb/argv.go`: the `valueFlags` table is still one vendor's global-flag list. It stayed because dropping it silently weakens a live guard - with `aws s3 ls --region us-east-1 s3://my-tfstate`, losing the strip makes `arg0` resolve to `us-east-1` and AOS's `deny-when arg0 matches *tfstate*` fails open. Right fix there is declaring value-taking flags in the guardfile, where the spec knows its own binary. Worth doing in the same pass if the provider work opens that door.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/umbra#283
No description provided.