Skip to content

refactor: extract verified-identical cloud-substrate machinery into stackless-cloud#7

Merged
snowmead merged 3 commits into
mainfrom
refactor/cloud-shared-helpers
Jun 17, 2026
Merged

refactor: extract verified-identical cloud-substrate machinery into stackless-cloud#7
snowmead merged 3 commits into
mainfrom
refactor/cloud-shared-helpers

Conversation

@snowmead

Copy link
Copy Markdown
Owner

What & why

After implementing every Stripe-Projects-backed provider, we asked what's common across them so adding the next one is cheap. The answer split by family:

  • Catalog integrations (Clerk + 8 Cloudflare): the abstraction already exists (Hostable + CatalogResource + blanket ProviderOps + registry). Only two small dups remained.
  • Cloud substrates (Render/Vercel/Fly/Netlify): the real copy-paste lived here. stackless-cloud already documents the rule for fixing it — only verified-identical machinery, returned as neutral data each substrate maps to its own fault (§2). This PR extends that pattern rather than inventing one.

Changes

stackless-cloud — three new shared helpers (628dc87)

  • health::poll(...) — the health-gate loop (was byte-identical ×4).
  • spend::line(...) — the spend line, parameterized by provider/cap/dashboard.
  • prepare::{resolve_prepare_env, run_service_prepare} — prepare env resolution + the operator-side spawn; the caller supplies the namespace.

Substrate migrations (3d4c790)

  • All four adopt health::poll + spend::line; Render/Vercel/Netlify also route prepare through run_service_prepare. Each maps the neutral result to its own fault, so stable error codes/remediation are unchanged. The three orphaned per-crate prepare.rs wrappers are deleted.
  • Fly is intentionally left on its own resolved_env prepare path — it shares that helper with start_service and maps env-resolution failures to ConfigInvalid (not PrepareFailed). Forcing it through the shared helper would change an agent-facing error code, so Fly only adopts health/spend. (Happy to unify it as a follow-up if we'd rather have one prepare path everywhere.)

Integration cleanups (0fb8ea3)

  • Hoist the identical Workers / Workers-AI / Browser-Run output tables into WORKERS_FAMILY_OUTPUT_FIELDS/_OUTPUTS.
  • Add a hermetic test asserting Hostable::OUTPUTS == names(OUTPUT_FIELDS) for every CatalogResource, so the co-located redundancy can't drift.

Net

~490 lines of duplicated substrate code removed; two new shared modules added. Each substrate lib.rs sheds ~110 lines.

Verification

  • cargo test --workspace — all green, 0 failures.
  • cargo clippy --workspace --all-targets — clean, no warnings.
  • New unit tests: health::poll (wiremock success + timeout), resolve_prepare_env (interp + secret injection), and the catalog_outputs_match_output_fields drift guard.
  • Behavior-preserving: per-substrate error codes, deploy/lifecycle, teardown verification, and namespace shape are untouched. Live smoke (fixtures/smoke/<substrate>) is unchanged behaviorally.

🤖 Generated with Claude Code

snowmead and others added 3 commits June 17, 2026 13:57
Extend stackless-cloud with the next batch of verified-identical cloud
substrate machinery, following the crate's existing rule: shared helpers
return neutral data each substrate maps to its own fault, so per-provider
error codes stay distinct (ARCHITECTURE.md §2).

- health::poll — the health-gate polling loop (was byte-identical across
  all four cloud substrates; only the fault raised differed).
- spend::line — the spend line, parameterized by provider/cap/dashboard.
- prepare::{resolve_prepare_env, run_service_prepare} — operator-side
  prepare env resolution + spawn, with the namespace supplied by the
  caller (substrates differ in what it carries).

Adds reqwest/tokio/stackless-stripe-projects deps + unit tests
(wiremock health, prepare env resolution).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the byte-identical health-gate loop and spend line in all four
cloud substrates with stackless_cloud::{health,spend}, and route prepare
through stackless_cloud::prepare::run_service_prepare on Render, Vercel,
and Netlify. Each substrate maps the neutral helper result to its own
fault, so its stable error codes/remediation are unchanged (§2). The
orphaned per-crate prepare.rs wrappers are removed.

Fly is intentionally left on its own resolved_env path for prepare: it
shares that helper with start_service and maps env-resolution failures
to ConfigInvalid (not PrepareFailed), so it only adopts the shared
health/spend helpers to avoid changing an agent-facing error code.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…drift

The Workers, Workers AI, and Browser Run resources provision the same
account-level Workers enablement and share one output envelope; hoist it
into WORKERS_FAMILY_OUTPUT_FIELDS/_OUTPUTS consts (the three stay distinct
types). Add a hermetic test asserting Hostable::OUTPUTS equals the names
column of CatalogResource::OUTPUT_FIELDS for every catalog resource, so the
co-located redundancy can't silently drift.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@snowmead snowmead merged commit 7015e6e into main Jun 17, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant