142: EnvironmentProvider port + Cloudflare ephemeral-environment provider (Workers for Platforms + Containers); K8s/Daytona optional#194
Open
agent-relay-code[bot] wants to merge 3 commits into
Conversation
added 3 commits
July 21, 2026 21:31
…force-factory-5a9a545c # Conflicts: # .agentworkforce/features/manifest.yaml
kjgbot
had a problem deploying
to
factory-test-infra
July 22, 2026 14:42 — with
GitHub Actions
Failure
6 tasks
Contributor
Author
|
Verdict: Clean. Preserves the maintainability review · |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of Epic: Factory Verification Environments (#141). This is the core provisioning primitive.
Why
The Factory needs to create and destroy isolated environments on demand to verify features. Follow the repo's existing port + provider seam (
src/ports/fleet.tswithRelayFleetClient/InternalFleetClientimplementations) so the environment substrate is swappable and testable. The primary provider is Cloudflare (the org's substrate — see #146); K8s/Daytona are optional providers behind the same port for stacks that can't run on Cloudflare.What
Add an
EnvironmentProviderport (src/ports/environment.ts) and a Cloudflare implementation (src/environments/cloudflare-provider.ts):provision(spec): Promise<Environment>— create a Workers for Platforms dispatch namespace for the environment, wire per-env bindings/secrets, and (per the stack descriptor Verification-stack descriptor contract + deployer: repos declare their full stack, Factory brings it up #143) deploy the environment's Workers and Cloudflare Containers into it.Environmentcarries{ id, dispatchNamespace, endpoints, bindings, status, createdAt, ttl }.status(id)— readiness of the namespace's Workers/Containers.endpoints(id)— resolve the environment's reachable URLs (Worker preview URL / Container ingress) so callers (E2E driver, load harness) can hit them.destroy(id)— delete the dispatch namespace + Container instances; idempotent.src/orchestrator/reaper.ts(identity-checked) to delete environments past TTL or whose owning run died, so namespaces/Containers can't leak.src/config/schema.ts) for the Cloudflare account/API-token (read via aResource.*-style secret, notprocess.env), default limits, TTL.KubernetesEnvironmentProvider/DaytonaEnvironmentProviderimplementing the same port later.src/index.ts.Acceptance
EnvironmentProviderport with a Cloudflare provider; unit tests with a faked Cloudflare API/miniflare.destroyis idempotent (namespace + Containers gone).src/index.ts; config schema covers account/token + limits + TTL; port leaves room for K8s/Daytona providers.✅ End-to-end verification — Factory success criteria (REQUIRED)
"Compiles" is not done. Run the provider against a REAL Cloudflare dispatch namespace and observe an environment come up, be reachable, and get reaped. CI uses miniflare for the fast path and a real dispatch namespace for the E2E.
Run it
The E2E must (against real Cloudflare):
provision()→ assert the dispatch namespace exists, per-env bindings are set, andstatus()reports ready.endpoints()resolves to a reachable URL (curl returns 200).destroy()→ assert the namespace + Container instances are gone.destroy(proves leaks are cleaned).Deliverable
test/e2e/environment-provider.e2e.tsrunning provision→reachable→destroy→reap against a real dispatch namespace in CI, one command.Anchor files
src/ports/fleet.ts(port pattern) → newsrc/ports/environment.tssrc/fleet/relay-fleet-client.ts(provider-impl pattern) → newsrc/environments/cloudflare-provider.ts(+ later optionalkubernetes-provider.ts/daytona-provider.ts)src/orchestrator/reaper.ts(reaper pattern),src/config/schema.ts,src/index.tsrelaycast-cloud, cloud'sminiflare-sage+test:integrationFixes #142
Summary by cubic
Adds a Cloudflare-backed
EnvironmentProviderfor ephemeral verification environments (Workers for Platforms + Containers), with endpoint resolution and a full provision → ready → destroy → reap lifecycle. Fixes #142.New Features
CloudflareEnvironmentProviderwithprovision,status,endpoints, anddestroy; per-environment bindings/secrets, Workers for Platforms dispatch namespace, Container ingress; idempotent teardown and a TTL reaper for past-TTL/orphaned envs.CloudflareEnvironmentConfigSchema(Resource.*-only credentials, defaults/limits); wired intoFactoryConfigSchema.environments.cloudflare; provider, types, and constants exported fromsrc/environments/index.tsand main index.test/e2e/environment-provider.e2e.ts; new workflowcloudflare-environment-provider.yml; run vianpm run test:e2e:cloudflarewithCLOUDFLARE_API_TOKENand optionalCLOUDFLARE_ACCOUNT_ID.Dependencies
wrangler@4.113.0,@cloudflare/containers@0.3.7,miniflare@4.20260721.0; Node engine set to>=22and CI updated to Node 22; overrides includeundici@7.28.0andesbuild@0.28.1.Written for commit 987427a. Summary will update on new commits.