Skip to content

feat(aws)!: generate 100% AWS Resource & Binding coverage - #797

Merged
sam-goodwin merged 108 commits into
mainfrom
claude/aws-fanout-coverage-plan-6eddae
Jul 18, 2026
Merged

feat(aws)!: generate 100% AWS Resource & Binding coverage#797
sam-goodwin merged 108 commits into
mainfrom
claude/aws-fanout-coverage-plan-6eddae

Conversation

@sam-goodwin

@sam-goodwin sam-goodwin commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

AWS resource-factory run — one PR, updated wave by wave until all phases (Serverless → ECS/Fargate → EKS → EC2 → long tail) are complete. Every wave is implemented and live-tested against real AWS by fleets of agents; every SDK gap found becomes a distilled patch (companion distilled PR per wave).

Status: the full workspace type-checks clean (bun tsc -b → 0 errors). Phases 1–5 plus the complete T2 deferred list (waves A–E) are implemented — every serverless, container, EKS, EC2, and long-tail service across ~120 AWS service dirs, with bindings, event sources, and Effect-first runtime functions, live-tested against real AWS. The final catalog tiering: 428 distilled modules → 122 implemented, 114 T2-deferred (on demand), 192 T3-out-of-scope (deprecated / data-only / vertical). The companion distilled PR carries every SDK improvement the run produced (Presign, Smithy hostPrefix, syntheticErrors, rest-xml fixes, paginator + schema patches).

Convergence: suite green + zero-orphan, twice consecutively

The nuke → full-suite → leak-census → fix-fleet loop (now codified in AGENTS.md) ran 12 iterations and terminated at its bar: two consecutive rounds (11 & 12) of 0 failed / 2692 passed with a zero-AWS-residue census — the suite provably deploys from a nuked account and leaves nothing behind. Runs settle at ~12 min wall-clock (--concurrency 96; unbounded saturates the single-process runner and fakes beforeAll timeouts).

Provider bugs the loop caught and fixed (each verified live):

  • Amplify: create now observe-adopts an app a timed-out CreateApp actually made (new distilled-typed TimeoutException); rate-exceeded retries spread across the account throttle bucket, deletes retry it too
  • EC2 VpcEndpoint: spurious modify-after-create (policy diff vs undefinedResetPolicy racing propagation → stranded endpoint blocking VPC deletes), unretried NotFound race, delete not waiting for async ENI release
  • Batch: wait-until-gone polls silently returned on budget expiry → engine deleted the service role mid-teardown → CEs wedged DISABLED+INVALID forever; polls fail loud + delete restores a minimal same-name role to unwedge; fresh creates recover from IAM-propagation INVALID (reap + bounded recreate)
  • MediaPackageV2 / Deadline: parent deletes now reap children (stub list()s made real); ConflictException-forever leaks gone
  • Polly: precreate persists deterministic identity so a mid-create crash can't orphan the lexicon
  • Lambda: post-delete log-flush recreations are re-reaped in a bounded observe→delete loop instead of failing the whole destroy
  • Census correctness: EC2 list() excludes default-VPC account furniture (test/AWS/DefaultVpc.ts recreates it as standing infra); nuke spares B2BI vended-log singletons

Default-pass coverage: 2692 live tests green; 375 gated (AWS_TEST_SLOW long-provisioning, cost/entitlement locks, external prerequisites like APNs/WABA/GitHub-OAuth, account-singletons) — each gated lifecycle keeps an ungated typed probe that runs green.

AWS test suite: green + zero-orphan guaranteed (tree type-clean)

Live-tested every AWS service against real AWS (memory-safe single-fork) and raised the bar for "green": a passing test must leave zero orphaned cloud resources.

  • All ~204 tested services green (every AWS service dir with a test suite). Real failures fixed at the root; ~117 lifecycle tests skipIf-gated with the exact reason (cost / singleton / slow-provisioning / entitlement) plus ungated typed probes. Companion distilled patches: cloudfront Comment, rds validation errors, s3tables modifiedBy, wafv2 WAFUnavailableEntityException, s3 BucketHasAccessPointsAttached.
  • Zero-orphan enforced + live-verified. Every test.provider body is wrapped in Effect.ensuring(scratch.destroy()); the gaps were out-of-band resources (adoption/import tests) and provider delete bugs. Fixed fleet-wide: deterministic names (no Math.random()/Date.now()), Effect.acquireRelease/ensuring cleanup with idempotent typed deletes, delete-if-exists pre-clean. After each suite an out-of-band AWS sweep asserts zero leftovers.
  • Provider leaks fixed (every consumer hit these, not just tests):
    • Lambda Function delete now reaps the auto-created /aws/lambda/{name} log group (re-reap watch for the ~35s post-delete flush).
    • DynamoDB Table delete disables Contributor Insights and waits for the CloudWatch rules to clear before deleteTable (else they strand forever).
    • ECS Task delete hard-deletes deregistered task-definition revisions (deregister alone leaks an INACTIVE revision forever).
    • InternetMonitor / MWAAServerless / Deadline / Batch deletes reap the auto-created /aws/{service}/… CloudWatch log groups (same class as the Lambda bug — they survive their parent's deletion).
  • nuke.sh hardened — it was targeting the alchemy-state-*/alchemy-assets-* buckets; now spares them and AWS-managed account resources (ServiceLinkedRole, LakeFormation, default-named singletons, DO-NOT-DELETE-*).
  • The account-wide nuke is the acceptance test, run in a loop: its deletion list (by test-named resource) surfaces exactly which tests leaked, those get fixed + re-verified, repeat. It reduced the account 494 → 44 → 104 → 65 across rounds, converging to only documented-undeletable residue (BackupSearch terminal records ~7-day retention; 2 DynamoDB Contributor-Insights rules with no delete API; PaymentCrypto keys in scheduled deletion) plus AWS-managed defaults.
  • Type-safety footgun fixed — a compound Effect.retry({ while }) predicate gets inferred as a type-predicate, collapses the error channel to unknown, and poisons the provider Layer type → a 600-error StackServices cascade across every test. Annotated : boolean.

Durable Functions + fleet-wide prop data-type audit (tree type-clean)

AWS.Lambda.DurableFunction — a code-first, replay-based orchestrator that is a durable Lambda Function (a wrapper of AWS.Lambda.Function, not a binding or a boolean prop; the base Function stays durability-agnostic and only carries an @internal durableConfig the wrapper sets at CreateFunction).

export class OrderFlow extends AWS.Lambda.DurableFunction<OrderFlow>()(
  "OrderFlow",
  Effect.gen(function* () {
    const putItem = yield* AWS.DynamoDB.PutItem(table);
    return (input: { orderId: string }) =>
      Effect.gen(function* () {
        const r = yield* Lambda.Durable.step("reserve", reserve(putItem, input), {
          retry: { limit: 3, delay: "5 seconds", backoff: "exponential" },
        });
        yield* Lambda.Durable.sleep("cooldown", "10 minutes"); // real suspend/resume
        return r;
      });
  }),
) {}
  • Durable.step / Durable.sleep / Durable.waitForCallback mirror the Cloudflare Workflow vocabulary; the DurableExecutionInvocationInput envelope routes through the owned Lambda entrypoint like an event source (isDurableExecutionEvent predicate + fresh per-invocation Scope), driven by AWS's @aws/durable-execution-sdk-js behind an Effect-native DurableStep service.
  • Determinism is type-enforced: the run body's requirement set excludes Credentials/Region, so the only path to I/O is an init-resolved binding client called inside Durable.step.
  • Ungated typed probe (ResourceNotFoundException) green; full suspend/resume lifecycle verified green live (AWS_TEST_DURABLE=1, ~43s warm, Status: SUCCEEDED). The wrapper captures its own functionName Output unresolved (avoids a plan-time self-reference deadlock) and defers the durable-SDK import() to first invocation; durable functions reject unqualified invokes, so a version is published and invoked with a Qualifier.

Props/attributes data-type audit across 205 AWS services (174 files):

  • 26 sensitive Props/Attributes are now Redacted.Redacted<string> (master/admin passwords, session keys, client secrets, LoRaWAN keys) — Redacted.value on write, Redacted.make on read, round-tripped through StateEncoding.
  • 124 duration Props are now Duration.Input (callers write "1 hour" / Duration.hours(1)), each converted to the exact wire unit in its provider (seconds / millis / days / minutes / ISO-8601) with state-JSON normalization guards.

Documentation pass (dimensions 3 & 4) across ~200 services: resource @section/@example blocks with coherent cross-references (grounded in the test suites), field-level prop/attr docs, and — the key gap — a usage @example on every capability / event source / sink (bind + provide the impl layer + call the runtime client), fixing the "describes behavior, never shows usage" anti-pattern. bun docs:gen regenerates 1191 provider pages clean.

Next surface — runtime layers, Step Functions DSL, DB drivers (tree type-clean)

Building on 100% resource coverage, three design tracks (full designs in processes/AWS/design/) — all live-tested, bun tsc -b --force → 0.

  • Runtime: makeBatchedSink engine + 6 Tier-1 sinks (DynamoDB/Firehose/CloudWatch/Logs/EventBridge/Timestream); SQS/Cognito event sources standardized onto Binding.Service. Breaking: sink In is now the raw distilled entry type with a typed error channel.
  • DSL: a typed Effect-mirrored Step Functions program (Sfn.gen/retry/catchTag/forEach/all) compiling to ASL via StateMachine.fromProgram — the raw definition path stays first-class; simulate() local interpreter; ValidateStateMachineDefinition/TestState bindings. Plus a 12-service IAM PolicyDocument sweep + generated IamAction types.
  • DB drivers: Runtime/ExecutionMemo (per-execution pool), Connection scaffolding + DbAuthToken SigV4 presign, AWS.SimpleDB full data plane (7 per-operation bindings — closes the zero-bindings gap), DSQL Connect+Drizzle e2e, RDS url+IAM-auth+VPC, Redshift Connect.

Bindings are 1:1 with IAM actions (one binding per operation via make{Service}Binding), not Read/Write splits.

T2 full-coverage push — final tail (wave E3, complete, tree type-clean)

The last 9 T2 services — combined gate bun tsc -b --force0 errors.

  • devops-guru, mailmanager (6 resources), healthlake, finspace (Environment + kdb), deadline (6 resources), qapps, mwaa-serverless, socialmessaging, s3files

Flywheel: distilled response-parser.ts + rest-json.ts core fixes for the deadline/finspace response shapes; SigV2 already added in E1/E2. wickr (AWS-retired) and nova-act (browser-agent SDK, not IaC) are documented T3 out-of-scope.

T2 coverage is complete: 206 AWS service directories on disk. The full workspace type-checks clean.

T2 full-coverage push — media/iot/ai/comms tail (waves E1+E2, complete, tree type-clean)

The final T2 cluster — 26 more services, combined gate bun tsc -b --force0 errors.

  • E1 — media + IoT: mediaconvert, mediatailor, mediapackagev2, mediaconnect, medialive, ivs(+realtime/chat), greengrassv2, iotsitewise, iotfleetwise, iot-wireless, iot-managed-integrations, imagebuilder, glacier
  • E2 — AI/ML + comms: sagemaker(+featurestore bindings), bedrock-agentcore(+control), bedrock-data-automation, omics, medical-imaging, qbusiness, lex-v2(+runtime), pinpoint-sms-voice-v2, appintegrations, geo-maps/places/routes (read bindings), route-53-domains, simpledb, repostspace

Flywheel output: SigV2 auth added to the distilled core (api.ts HMAC-SHA256 + traits.ts) — classic SimpleDB is the last SigV2-only AWS service, plus a hand-written simpledb module (no Smithy model exists); rest-json/stream fixes for the geo data-plane; generator/protocol coverage for iot-managed-integrations. Entitlement/cost-gated lifecycles (medialive channels, mediaconnect flows, healthlake, omics, qbusiness, chatbot, glacier's deprecated vault API, …) env-gated behind AWS_TEST_* with ungated typed-error probes.

T2 full-coverage push — 54 services (waves A–D, complete, tree type-clean)

Fable fan-out over the 114 T2-deferred modules, ~13 services per wave, each implemented + live-tested + registered, with distilled patched inline for every SDK gap. All four waves green; combined gate bun tsc -b --force0 errors.

  • A — cheap control planes: resource-groups, resource-explorer-2, schemas, signer, rbin, dlm, fis, global-accelerator, route53resolver/-profiles, service-catalog, oam, synthetics, notifications
  • B — data/analytics/gov: lakeformation, databrew, datazone, dataexchange, entityresolution, s3-control, kinesis-analytics-v2, kinesis-video, emr(+serverless/containers), redshift, opensearch, neptune(+graph), dax, docdb-elastic, keyspaces, timestream-influxdb, kendra
  • C — security/identity: rolesanywhere, license-manager, cloudtrail, config, network-firewall, acm-pca, directory-service, securitylake, cloudhsm-v2, payment-cryptography, controltower, shield
  • D — obs/ops/cost: rum, application-signals, cost-explorer, cost-and-usage-report, bcm-data-exports, internetmonitor, aiops, auditmanager, ssm-incidents/-contacts, service-quotas, backupsearch, pricing, chatbot

Entitlement/cost-gated lifecycles (Shield Advanced, CloudHSM, Directory Service, ControlTower, ACM-PCA, SecurityLake, payment-cryptography, CloudTrail Lake, …) are env-gated behind AWS_TEST_* with ungated typed-error probes proving the distilled union. Flywheel output this push: a distilled generator fix (per-op @http derivation for shared input shapes — deletes were silently issuing GETs), rest-json empty-body + Unit-input + comma-joined-errortype core fixes, and 24 new service error-tag patch files.

Remaining: Wave E (iot/media/ai/comms/misc long tail, ~35 services, split E1/E2).

Wave 1A — serverless test-debt burn-down + quick wins (complete, all suites green)

New coverage

  • AWS.SSM.Parameter resource + GetParameter/GetParameters bindings (String/StringList/SecureString, kms:Decrypt composition for WithDecryption)
  • AWS.S3.PresignGetObject/PresignPutObject — presigned URLs minted inside deployed Lambdas, verified by real HTTP PUT/GET round-trips (signing seam upstreamed to @distilled.cloud/aws/Presign)
  • AWS.KMS.Encrypt/Decrypt/GenerateDataKey bindings (standing test key by alias, kms:RequestAlias-scoped least privilege)
  • Live Lambda-fixture binding suites for SQS (5 ops + QueueEventSource end-to-end), EventBridge (PutEvents + consume loops on custom/default buses), CloudWatch (22 of 24 bindings), SecretsManager, RDSData (gated AWS_TEST_SLOW=1, skip-clean green)
  • scripts/aws-leak-sweep.ts — tag-scoped stray sweeper (dry-run default; deleted 23 strays from past sessions on first live run)

Bugs found by the live tests and fixed

  • DynamoDB Table: pinned-tableName replacement collided with the doomed table and silently adopted it; now deleteFirst replace with wait-until-released
  • EventBridge: PutEventsHttp serialized an unresolved Output into IAM policy (MalformedPolicyDocumentException on every deploy); Rule.read crashed the destroy path on unresolved props
  • SecretsManager: recreate-after-ForceDeleteWithoutRecovery raced the async deletion
  • RDS: Aurora passed vpcSecurityGroupIds to cluster-member instances (AWS rejects); EC2 Network was runtime-unsafe at Lambda INIT (AZ discovery + eager AWSEnvironment)
  • Engine Plan.ts: destroy-after-failed-create handed providers unresolved Output expressions; now guarded like the adoption probe (isResolved)
  • Engine Binding.ts: BindParameters dropped optional parameters (PutEvents(bus) → "Expected 0 arguments") and truncated variadic parameter lists (GetParameters(...))
  • SecretProvider's inlined Effect.retry widened to unknown R in declaration emit, breaking AWS.providers() for every consumer — now an explicitly-typed helper
-// lib/AWS/Providers.d.ts (before)
-providers: () => Layer<..., never, unknown>
+// after
+providers: () => Layer<..., never, ... | Stack | Stage>

Test-harness learnings baked into the suites

  • Suites whose tests share one mutable fixture (a queue, a secret) opt out of the global concurrent test execution (describe.sequential)
  • Lambda fixtures set explicit timeout (AWS's 3s default kills long-poll routes after the side effect already happened)
  • Distilled response-schema patches used inside deployed bundles require a distilled lib rebuild (bundles resolve lib/, vitest resolves src/)

Wave 1B — greenfield flagships (complete, all suites green)

New services (all live-tested end-to-end)

  • ApiGatewayV2: Api / Integration / Route / Stage / Authorizer / DomainName / ApiMapping / VpcLink, plus the high-level HttpApi helper (Api + payload-2.0 proxy Integration + $default Route + auto-deploy Stage + invoke Permission in one call), the ManageConnections binding (server-push over WebSocket from a deployed Lambda), and WebSocketEventSource (onWebSocketRoute DX). WebSocket e2e: real wss client connects, Lambda echoes via postToConnection — 4 consecutive green runs.
  • Step Functions: StateMachine (auto-created execution role + binding-contract wiring for referenced Lambdas) + Activity, with StartExecution / StartSyncExecution / DescribeExecution / StopExecution / SendTask* bindings. Upstreamed Smithy hostPrefix support to distilled so StartSyncExecution targets sync-states.*.
  • Cognito: UserPool / UserPoolClient / UserPoolDomain / Group / ResourceServer + UserPoolAuth/UserPoolAdmin bindings — e2e creates a user, authenticates, and returns a valid JWT through a deployed Lambda.
  • SES v2: EmailIdentity / ConfigurationSet (+ event destinations) / EmailTemplate + SendEmail binding (sandbox-gated live send behind AWS_TEST_SES_FROM, ungated typed-error probe).
  • Firehose: DeliveryStream (DirectPut→S3, Kinesis source) + PutRecord/PutRecordBatch bindings.
  • EventBridge Pipes: Pipe (SQS→Lambda, filtering, enrichment) with typed PipeFailed/PipeStateTimeout — a failed pipe can never hang a deploy.
  • Scheduler runtime bindings: CreateSchedule / DeleteSchedule / GetSchedule — a deployed Lambda schedules future invocations dynamically (group-scoped IAM, iam:PassRole contributed by the binding).
  • CloudWatch Logs completion: SubscriptionFilter + LogGroupEventSource (a Lambda consuming another function's logs, gunzip/decode handled) + MetricFilter + ResourcePolicy + FilterLogEvents binding.

Engine: isResource now requires Type AND FQN — user prop objects carrying Type (e.g. ASL states { Type: "Pass" }) are no longer mistaken for resources.

Wave 1C — Phase 1 nears complete (8/8 green; run survived a session-limit interruption via workflow resume)

  • WAFv2: WebACL (REGIONAL + us-east-1-pinned CLOUDFRONT scope, managed/rate-based/byte-match rules) / IPSet / RuleGroup / WebACLAssociation — associated live to a Cognito UserPool, re-pointed, destroy-order proven. LockToken optimistic-concurrency handled with typed bounded retries.
  • EFS: FileSystem / MountTarget / AccessPoint plus Lambda fileSystemConfigs mount support — ungated e2e mounts an access point into a VPC Lambda, writes over HTTP, and proves persistence across a redeploy.
  • AppSync: GraphqlApi (multi-auth, async schema creation, cache folded in as a prop) / DataSource (auto-role) / Resolver (JS + VTL, unit + pipeline) / Function / ApiKey / DomainName + ApiAssociation — live GraphQL e2e through a Lambda datasource.
  • X-Ray: SamplingRule / Group, Lambda tracingConfig, trace read bindings.
  • Bedrock: Converse / InvokeModel bindings with exact model-ARN IAM (foundation models + inference profiles) — ungated live e2e (a deployed Lambda converses with us.amazon.nova-micro-v1:0).
  • AI capability set: Rekognition.DetectLabels, Textract.DetectDocumentText, Polly.SynthesizeSpeech, Translate.TranslateText, Comprehend.DetectSentiment — one shared fixture, all live.
  • ElastiCache: ServerlessCache + env-only Connect binding (gated lifecycle green in 97s).
  • Aurora: the full gated composite smoke is green — 7/7 in ~21 min (Aurora SV2 cluster + Data API + RDS.Connect through a deployed Lambda), skip-clean when ungated.
  • Gate: list() added to 13 providers (required by ProviderService; its absence collapses record inference into misleading per-op errors), plus an eventstream decode fix in distilled.

Wave 1D — Phase 1 (Serverless) complete (8/8 green)

  • Composite smoke — the Phase-1 exit criterion — passes twice back-to-back: one stack wires Cognito (pool + client), an HTTP API with a JWT authorizer, DynamoDB, S3 presign, an SQS-consuming worker Lambda, and an EXPRESS Step Functions machine; the test signs a user up, mints a JWT via the bindings, exercises the protected todo API (asserting the 401 path never touches DynamoDB), uploads through a presigned URL, round-trips the queue, and gets a synchronous workflow result.
  • Distilled gains syntheticErrors: patch-schema support for message-matcher-derived typed error classes ({ name, from, message: exact | includes | matches }), with runtime specialization ahead of base-code lookup and hard-fail orphan detection. Applied to X-Ray (SamplingRuleNotFound, GroupNotFound, …) — the provider now uses plain Effect.catchTag.
  • Distilled rest-xml protocol fix: the deserializer now handles Smithy's default <member>-wrapped non-flattened lists (found by Route53 live tests, plus 3 route-53 response-schema patches).
  • ElastiCache data plane proven: iovalkey round-trip through a VPC Lambda using the Connect binding (gated, green).
  • Cognito triggers DX: preSignUp/postConfirmation/… handlers on alchemy Lambdas (lambdaConfig + Permission materialized automatically); e2e signs up a user auto-confirmed by a deployed trigger. Plus User resource and a risk-configuration typed probe.
  • P1 completion sweeps: S3 configs (lifecycle/CORS/website/logging/PAB/intelligent-tiering/replication — 22/22), IAM (GitHub-Actions OIDC federation e2e, SAMLProvider, ServiceLinkedRole, policy version-cap pruning — 36 tests), DynamoDB (resource policy, Kinesis streaming destination, contributor insights), CloudFront (KeyValueStore, Functions, RealtimeLogConfig, CreateInvalidation binding) and Route53 (query logging, VPC association auths).
  • Engine fix: Effect-mode Lambdas pin Handler to index.default (a user handler: prop only addresses exports of isExternal modules — previously deployed functions that died at init with Runtime.HandlerNotFound).

Phase 2 (ECS Containers & Fargate) — Wave 2A complete (8/8 green)

  • ECS runtime: RunTask/StopTask/ListTasks/DescribeTasks bindings (fixed a real bug sending Effect objects as ARNs) with a live Fargate one-shot-task fixture; standalone TaskDefinition for BYO containers.
  • ECR.Image: build+push extracted from ECS/Task.ts into its own content-hash-identity resource (rebuild only on content change) — the dependency Phase 3's EKS ServerHost needs. Task delegates to it; the existing ECS e2e passes unchanged.
  • ApplicationAutoScaling (ScalableTarget/ScalingPolicy/ScheduledAction, ECS + DynamoDB), Batch (ComputeEnvironment→JobQueue→JobDefinition + SubmitJob binding), Cloud Map (namespaces/Service + DiscoverInstances runtime binding), App Runner (Service/AutoScalingConfiguration/VpcConnector).
  • ELBv2: ListenerRule / ListenerCertificate / TargetGroupAttachment (ip/instance/lambda targets) + ALB event support in the Lambda bridge; flagship ALB→2-Lambda routing e2e green.
  • Engine fixes shipped alongside: Resource.ref stables now carry LogicalId (refs usable in host.bind templates); LoadBalancer.delete waits for the ALB to fully clear so downstream subnet/SG deletes stop spinning on ENI release; TargetGroupAttachment retries the AccessDeniedException Permission-propagation race.

Phase 3 (EKS) + Phase 4 (EC2) + engine fix + long-tail L2–L5

  • Engine — Platform-in-Platform OOM fixed: yielding a Platform (ECS.Task / EKS.ServerHost / EC2.Instance) inside a Lambda/Worker init program no longer recurses the intercepting ConfigProvider to Runtime.OutOfMemory. The container host bridge read config via Config.string (ambient ConfigProvider = the interceptor → infinite loop); it now reads process.env directly like the Lambda/Cloudflare bridges. Live regression + 364 engine unit tests green.
  • EKS.ServerHost (Phase 3 flagship): the ECS.Task analog for Kubernetes — bundles an Effect program to an ECR image, applies Deployment+Service via server-side apply, routes bindings through a pod-identity role. Plus a cross-cutting win: isFunctionisBindingHost across all binding guards so ECS.Task and EKS.ServerHost now light up every AWS binding (previously Lambda-only). EKS Nodegroup + FargateProfile added.
  • Phase 4 EC2: EBS Volume/Snapshot/VolumeAttachment + NetworkInterface; VpcPeeringConnection, FlowLog, ManagedPrefixList, DhcpOptions; Auto Scaling ScheduledAction/LifecycleHook + CompleteLifecycleAction binding + lifecycle event source.
  • Long-tail L2–L5: bedrock-agent (+ Retrieve/RetrieveAndGenerate), opensearch-serverless, glue, athena, redshift-serverless, s3tables, appconfig, cloudtrail + config.

Long-tail L5–L7 — security/governance, data stores + event sources, devops, AI (landed in worktree)

  • Security/governance (account-singleton, capture-and-restore): GuardDuty Detector, SecurityHub Hub, Inspector2 Enabler, Macie2/Detective, AccessAnalyzer + VerifiedPermissions with an IsAuthorized Cedar-authorization binding (a Lambda making authz decisions), Backup (Vault/Plan/Selection), Budgets.
  • Data stores + their Lambda event sources (the previously-orphaned ones, now owned): MSK (+ MSK event source), Amazon MQ broker/config (+ MQ event source), DocDB cluster (+ change-stream event source), plus DSQL, Keyspaces, MemoryDB.
  • Devops/interop: CloudFormation Stack + CloudControl, CodeBuild/CodePipeline/CodeConnections, Transfer + DMS, ecr-public/account/vpc-lattice/amplify.
  • AI + observability: ComprehendMedical/SageMaker-runtime/Transcribe/s3vectors bindings, AMP (Managed Prometheus).
  • AppConfig (+ appconfigdata GetLatestConfiguration binding) and CloudTrail + Config landed alongside the Phase 3/4 wave.

Companion distilled PR: alchemy-run/distilled (Wave 1A patches, paginator fix, ValidationException fields, Presign module).

🤖 Generated with Claude Code

…presign, KMS caps, engine fixes

- SSM.Parameter resource + GetParameter/GetParameters bindings
- S3 PresignGetObject/PresignPutObject (via new distilled Presign module)
- KMS Encrypt/Decrypt/GenerateDataKey bindings (standing key by alias)
- live Lambda-fixture binding suites: SQS (+QueueEventSource e2e), EventBridge, CloudWatch (22 bindings), SecretsManager, RDSData (AWS_TEST_SLOW-gated)
- DynamoDB pinned-name replacement fix (deleteFirst); EventBridge PutEventsHttp IAM serialization + Rule destroy-path fixes; SecretsManager force-delete race fix; RDS Aurora cluster-member SG fix; EC2 Network runtime safety
- engine: Plan.ts unresolved-olds guards on read; Binding.ts BindParameters optional/variadic support
- SecretProvider declaration-emit fix (Effect.retry widened AWS.providers() to unknown R)
- scripts/aws-leak-sweep.ts (tag-scoped stray sweeper)
- distilled submodule -> wave-1A patches (see alchemy-run/distilled#369)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@alchemy-version-bot

alchemy-version-bot Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Install the packages built from this commit:

alchemy

bun add alchemy@https://pkg.ing/alchemy/fed5c78

@alchemy.run/better-auth

bun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/fed5c78

@alchemy.run/pr-package

bun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/fed5c78

sam-goodwin and others added 7 commits July 9, 2026 18:02
…ognito, SES v2, Firehose, Pipes, Scheduler bindings, Logs completion

- ApiGatewayV2: full v2 surface + HttpApi helper + ManageConnections binding + WebSocketEventSource (live wss e2e w/ server push)
- StepFunctions: StateMachine/Activity + StartExecution/StartSyncExecution/DescribeExecution/StopExecution/SendTask* bindings
- Cognito: UserPool/Client/Domain/Group/ResourceServer + UserPoolAuth/UserPoolAdmin bindings (JWT e2e)
- SESv2: EmailIdentity/ConfigurationSet/EmailTemplate + SendEmail binding (sandbox-gated send, typed probe ungated)
- Firehose: DeliveryStream + PutRecord(Batch) bindings; Pipes: Pipe w/ typed failure states + SQS->Lambda e2e
- Scheduler: CreateSchedule/DeleteSchedule/GetSchedule runtime bindings (dynamic scheduling DX)
- Logs: SubscriptionFilter + LogGroupEventSource + MetricFilter + ResourcePolicy + FilterLogEvents binding
- engine: isResource requires Type AND FQN (ASL states are not resources)
- distilled submodule -> hostPrefix + sesv2 patches

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…Sync, X-Ray, Bedrock, AI capabilities, ElastiCache, Aurora smoke green

- WAFv2: WebACL (REGIONAL + us-east-1 CLOUDFRONT) / IPSet / RuleGroup / WebACLAssociation (Cognito target)
- EFS: FileSystem/MountTarget/AccessPoint + Lambda fileSystemConfigs mount support; ungated mount-persistence e2e
- AppSync: GraphqlApi/DataSource/Resolver/Function/ApiKey/DomainName/ApiAssociation + GraphQL e2e
- X-Ray: SamplingRule/Group + Lambda tracing + trace read bindings
- Bedrock: Converse/InvokeModel bindings (live ungated e2e via inference profile)
- AI capability set: Rekognition/Textract/Polly/Translate/Comprehend flagship ops, one shared fixture
- ElastiCache: ServerlessCache + env-only Connect binding (gated lifecycle green)
- Aurora composite smoke fully green (7/7 gated, 1243s)
- gate: list() added to 13 providers (required by ProviderService; absence collapsed record inference), StateMachine list item typing, eventstream parser R fix (distilled)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- composite smoke (Phase-1 exit criterion): Cognito+HttpApi(JWT)+DynamoDB+S3 presign+SQS worker+EXPRESS SFN in one stack, e2e green twice back-to-back
- Cognito Lambda triggers DX (preSignUp auto-confirm e2e) + User resource
- ElastiCache data-plane round-trip via iovalkey in a VPC Lambda (gated)
- S3 config completion (lifecycle/CORS/website/logging/PAB/tiering/replication)
- IAM completion: OIDCProvider (GitHub Actions e2e), SAMLProvider, ServiceLinkedRole, policy version pruning
- DynamoDB resourcePolicy + kinesisStreamingDestination + contributorInsights; Kinesis ResourcePolicy
- CloudFront KeyValueStore/Functions/RealtimeLogConfig/CreateInvalidation; Route53 QueryLoggingConfig + VPC association auths
- X-Ray converted to typed synthetic error tags (distilled syntheticErrors)
- engine: Effect-mode Lambda Handler pinned to index.default (user handler: prop is isExternal-only)
- distilled submodule -> syntheticErrors + rest-xml fix + route-53 patches

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… Batch, Cloud Map, App Runner, ELBv2

- ECS: RunTask/StopTask/ListTasks/DescribeTasks bindings (fixed Output-force-cast bug) + live Fargate fixture; TaskDefinition (BYO); Task refactored onto ECR.Image
- ECR.Image: standalone build+push resource (content-hash identity), extracted from ECS/Task.ts — Phase 3 EKS ServerHost dependency
- ApplicationAutoScaling: ScalableTarget/ScalingPolicy/ScheduledAction (ECS + DynamoDB)
- Batch: ComputeEnvironment/JobQueue/JobDefinition chain + SubmitJob binding
- CloudMap: namespaces/Service/InstanceRegistration + DiscoverInstances/Register/Deregister bindings (data- endpoint)
- AppRunner: AutoScalingConfiguration/Service/VpcConnector
- ELBv2: ListenerRule/ListenerCertificate/TargetGroupAttachment + ALB Lambda-target flagship e2e
- engine: Resource.ref stables carry LogicalId (refs in host.bind templates); LoadBalancer.delete waits for full ALB teardown (downstream network deletes no longer spin on ENI release); TargetGroupAttachment retries AccessDeniedException
- distilled submodule -> batch/apprunner/servicediscovery patches

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…rrupted mid-flight)

Waves 3-4 complete + verified; wave 5 (final long-tail sweep) interrupted mid-flight
so the tree does not fully type-check yet. Pushing to preserve work.

- engine: Platform-in-Platform OOM fix (host ctx.get reads process.env, not Config.string); isFunction->isBindingHost so ECS.Task + EKS.ServerHost light up all AWS bindings; LoadBalancer.delete waits for full ALB teardown
- Phase 3 EKS: ServerHost + Nodegroup + FargateProfile
- Phase 4 EC2: EBS trio + ENI, peering/flow-logs/prefix-lists/dhcp, ASG orchestration + LifecycleHook ES
- long-tail L2-L7: bedrock-agent, opensearch-serverless, glue, athena, redshift-serverless, s3tables, appconfig, cloudtrail/config, guardduty/securityhub/inspector2, accessanalyzer/verifiedpermissions, backup/budgets, MSK/MQ/DocDB (+ event sources), dsql/keyspaces/memorydb, cloudformation, codebuild/codepipeline, transfer/dms, iot, ram, timestream, amp, ecr-public + partial wave-5 services (Location/DataSync/FraudDetector/Personalize/Forecast/MediaConvert/etc.)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gate)

Finishes the 6 interrupted wave-5 services (IoT + TopicRule event source, Location + geo bindings, Timestream, FSx/DataSync, AppFlow/B2BI, Personalize/Forecast/FraudDetector) and resolves the full type gate for waves 3-5:

- 130 genuine source type errors fixed (root cause: agents used { news = {} } destructuring defaults that widened required Props to Props|{}, corrupting inference; vitest never caught it since it doesn't type-check)
- cleared the AWS.providers() unknown-R cascade (inline Effect.retry in CloudFormation/EC2.VolumeAttachment/EKS.ServerHost providers -> typed pipeable retry helpers)
- Platform.ts props-Effect overload widened to InputProps (lets Effect-props programs pass ref'd resources; enables the EKS ServerHost fixture)
- residual test/fixture fixes (SensitiveString/Redacted unwraps, Accessor resolution in fixtures, provider-context wrapping, undefined guards)
- distilled submodule -> ec2 NotFound tags + location/geo/timestream schema patches

Full workspace bun tsc -b: 0 errors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…s/ops/cost

Adds ~60 AWS services (resources, bindings, live tests) toward full T2
coverage, in Fable fan-out waves:

- cheap control planes: resource-groups, resource-explorer-2, schemas,
  signer, rbin, dlm, fis, global-accelerator, route53resolver/-profiles,
  service-catalog, oam, synthetics, notifications
- data/analytics/gov: lakeformation, databrew, datazone, dataexchange,
  entityresolution, s3-control, kinesis-analytics-v2, kinesis-video,
  emr(+serverless/containers), redshift, opensearch, neptune(+graph), dax,
  docdb-elastic, keyspaces, timestream-influxdb, kendra
- security/identity: rolesanywhere, license-manager, cloudtrail, config,
  network-firewall, acm-pca, directory-service, securitylake, cloudhsm-v2,
  payment-cryptography, controltower, shield
- obs/ops/cost: rum, application-signals, cost-explorer,
  cost-and-usage-report, bcm-data-exports, internetmonitor, aiops,
  auditmanager, ssm-incidents/-contacts, service-quotas, backupsearch,
  pricing, chatbot

Entitlement/cost-gated lifecycles are env-gated behind AWS_TEST_* with
ungated typed-error probes. Region-pinned services (cost-*, pricing) provide
the distilled Region service via Effect.succeed. Bumps the distilled
submodule for the T2 typed-error + generator coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sam-goodwin sam-goodwin changed the title feat(aws): resource factory — full AWS coverage (Serverless → ECS → EKS → EC2 → long tail) feat(aws): generate 100% AWS Resource & Binding coverage Jul 11, 2026
sam-goodwin and others added 12 commits July 10, 2026 18:33
…1+E2)

Completes the T2 long tail with the media, IoT, AI/ML, and comms clusters:

- media: mediaconvert, mediatailor, mediapackagev2, mediaconnect, medialive,
  ivs(+realtime/chat)
- iot: greengrassv2, iotsitewise, iotfleetwise, iot-wireless,
  iot-managed-integrations
- compute/config: imagebuilder, glacier
- ai/ml: sagemaker(+featurestore bindings), bedrock-agentcore(+control),
  bedrock-data-automation, omics, medical-imaging, qbusiness
- comms/data: lex-v2(+runtime binding), pinpoint-sms-voice-v2, appintegrations,
  geo-maps/places/routes (read bindings), route-53-domains, simpledb,
  repostspace

Entitlement/cost-gated lifecycles env-gated behind AWS_TEST_* with ungated
typed-error probes. Bumps the distilled submodule for SigV2 auth (SimpleDB) +
the media/iot/ai typed-error and generator coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Completes the T2 deferred list:

- devops-guru (NotificationChannel, ResourceCollection)
- mailmanager (RuleSet, TrafficPolicy, IngressPoint, Relay, AddonSubscription,
  AddonInstance)
- healthlake (FHIRDatastore), finspace (Environment + kdb: KxEnvironment/
  Database/Cluster), deadline (Farm, Queue, Fleet, Monitor, Budget,
  StorageProfile)
- qapps (QApp), mwaa-serverless (Workflow), socialmessaging
  (LinkedWhatsAppBusinessAccount), s3files (FileSystem, AccessPoint)

Entitlement/cost/onboarding-gated lifecycles env-gated behind AWS_TEST_* with
ungated typed-error probes. Bumps the distilled submodule for the tail's
typed-error + protocol coverage. wickr (AWS-retired) and nova-act (browser-agent
SDK, not IaC) are out of scope.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- normalizePolicyDocument (sorted-key stable stringify, handles IAM's
  URL-encoded documents) exported from IAM/Policy.ts for drift diffs
- actions.generated.ts: shallow literal union of 18,270 `service:Op`
  IAM actions (+ `service:*` per prefix, (string & {}) escape hatch)
  generated from distilled sigv4 names + operationName metadata via
  scripts/generate-iam-actions.ts
- PolicyStatement.Action?: IamAction[] | string[] for autocomplete
- ServiceControlPolicyDocument narrowing interface (SCP-legal subset)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Three design tracks from the AWS next-surface proposal (processes/AWS/design/):

Runtime layers
- makeBatchedSink engine (size/byte batching, ordered partial-failure retry,
  unprocessed-vs-rejected); rebased SQS/SNS/Kinesis sinks onto it (BREAKING: sink
  `In` is now the raw distilled entry type, error channel is typed not never)
- 6 Tier-1 sinks: DynamoDB, Firehose, CloudWatch, Logs, EventBridge, Timestream
- standardized SQS/Cognito event-source contracts onto Binding.Service

Step Functions DSL
- StepFunctions/Asl: a typed Effect-mirrored program (Sfn.gen/retry/catchTag/
  forEach/all/…) that compiles to ASL; StateMachine.fromProgram is sugar over the
  raw `definition` path, which stays first-class. simulate() local interpreter.
  ValidateStateMachineDefinition + TestState bindings.
- IAM PolicyDocument sweep across 12 services (+ generated IamAction types,
  ServiceControlPolicyDocument dialect)

Database / connection drivers
- Runtime/ExecutionMemo (per-execution pool primitive; Drizzle refactored onto it)
- Connection scaffolding (SqlConnectionInfo+url, DbAuthToken SigV4 presign);
  RuntimeContext retrofit on RDS/ElastiCache/RDSData
- AWS.SimpleDB full data plane (7 per-operation bindings via makeSimpleDbBinding —
  closes the zero-bindings gap); DSQL Connect+Drizzle e2e; RDS url+IAM-auth+VPC;
  Redshift + RedshiftServerless Connect

Bindings follow the 1:1 IAM-action-per-operation convention (make{Service}Binding
helper), not Read/Write splits. Bumps distilled for SimpleDB.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… audit

AWS.Lambda.DurableFunction — a code-first, replay-based orchestrator that
IS a durable Lambda Function (wrapper of AWS.Lambda.Function, not a binding
or a boolean prop). The base Function is durability-agnostic; DurableFunction
configures its create-time DurableConfig and owns the checkpoint/replay
protocol via @aws/durable-execution-sdk-js.

- Durable.step / Durable.sleep / Durable.waitForCallback orchestrator combinators
- DurableBridge routes the DurableExecutionInvocationInput envelope through the
  owned Lambda entrypoint (isDurableExecutionEvent predicate + per-invocation Scope)
- determinism is type-enforced: the run body excludes Credentials/Region, so the
  only path to I/O is an init-resolved client called inside Durable.step
- ungated typed probe (ResourceNotFoundException) + AWS_TEST_DURABLE=1 full
  suspend/resume lifecycle test

Props/attributes data-type audit across 205 AWS services:
- 26 sensitive Props/Attributes now Redacted.Redacted<string> (passwords, session
  keys, client secrets, admin passwords) — unwrapped with Redacted.value on write,
  wrapped with Redacted.make on read, round-tripped through StateEncoding
- 124 duration Props now Duration.Input (callers write "1 hour"/Duration.hours(1)),
  each converted to the exact wire unit in its provider (seconds/millis/days/minutes/
  ISO-8601) with state-JSON normalization guards

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…le fix

Documentation pass over ~200 AWS services (dimensions 3 & 4 of the prop audit):
- resource-level @section/@example blocks with coherent cross-references
  (e.g. AutoScalingGroup from LaunchTemplate+Vpc/Subnet + ScalingPolicy;
  CloudFront Distribution + Invalidation; DataSync EFS→S3 via Task) — real
  usage grounded in the test suites, not invented APIs
- the binding/event-source/sink gap closed: every capability, event source,
  and sink now carries a usage @example (bind + provide the impl layer + call
  the runtime client) — fixes the "describes behavior, never shows usage"
  anti-pattern (e.g. EventBridge BusSink)
- field-level JSDoc filled in on props/attributes across the fleet
- website API reference regenerated (bun docs:gen)

DurableFunction lifecycle now green live (AWS_TEST_DURABLE=1, ~43s warm,
real suspend/resume, Status SUCCEEDED):
- fixed a plan-time self-reference deadlock — init captured the host's own
  functionName Output raw (no eager yield) and the runtime handle callables
  resolve Output → Accessor → string lazily per invocation
- deferred the durable-execution SDK import to first invocation (was loading
  at listener construction / deploy time)
- durable functions reject unqualified invokes — the test publishes a version
  and invokes with a Qualifier

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Ran every AWS service's suite against real AWS (memory-safe single-fork).
31/32 services green (ApiGateway follows separately); each service triaged,
real failures fixed at the root, platform-limited cases skipIf-gated with the
exact error. Companion distilled patches (submodule): cloudfront Comment,
rds validation errors, s3tables modifiedBy.

Zero-orphan guarantee — a passing test now implies zero leftover cloud
resources. The framework already wraps every `test.provider` body in
`Effect.ensuring(scratch.destroy())`; the hole was out-of-band resources
(created directly via SDK to test `adopt`/takeover). Across 17 services:

- deterministic names — replaced every `Math.random()`/`Date.now()` in a
  resource name with a stable constant, so a re-run reclaims a prior orphan
  instead of minting a new one (partial-state recovery). Also fixed a Config
  recorder named "default" (indistinguishable from a foreign recorder).
- guaranteed cleanup — wrapped each out-of-band resource in
  `Effect.acquireRelease`/`ensuring` with an idempotent typed delete
  (tolerates the not-found tag), running on success, failure, AND interruption;
  idempotent delete-if-exists pre-clean at test start.
- verified live — after each suite, an out-of-band sweep confirmed zero
  leftovers for the service (all 17 clean).
- subtle windows closed: CloudFront PublicKey interruption ordering, CloudWatch
  MetricStream Firehose-bucket emptying before delete, ECS task-definition
  family reclaim, CloudTrail Lake probe.

Also: S3Tables diff() dropped the banned `news = {}` default (Input typing);
SNS/MetricStream cleanup finalizers collapse to `never` via Effect.orDie.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Verified clean-slate (live out-of-band sweep after each suite) for the 14
tested services outside the adoption pass — all clean. Real leaks found + fixed:

- Lambda: `Function` delete now reaps the auto-created `/aws/lambda/{name}`
  CloudWatch log group — previously EVERY invoked function leaked one. A bounded
  re-reap watch (t=0/20/40s) handles Lambda's final log flush silently
  re-creating the group ~35s after function+role deletion; an idle-function
  quiescence fast-path keeps the common case single-call.
- Route53: `Record.test` kept a standing hosted zone that was never deleted
  (every passing run leaked one) — converted to a suite-scoped fixture with an
  idempotent teardown finalizer. `QueryLoggingConfig.test` created its
  out-of-band us-east-1 log groups + resource policy before the cleanup region
  attached (leaked on setup failure) — moved inside the ensured region.
- ELBv2: `ListenerCertificate` / `ListenerActions` / `TrustStore` imported ACM
  certs / trust stores out-of-band with success-path-only cleanup — wrapped in
  `Effect.ensuring` so they're deleted on failure/interruption too.
- StateStore: out-of-band S3 state objects now cleaned via `Effect.ensuring`.
- S3Tables: added a `purgeOrphanedTableBuckets` deterministic-prefix pre-clean.

All cleanup deletes are idempotent (catchTag the not-found tag) and end in
`Effect.orDie` so they're valid `never`-channel `ensuring` finalizers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A full account-wide nuke revealed the orphans earlier passes missed. Two were
provider-level leaks that every consumer hit, not just tests:

- DynamoDB `Table` delete: DISABLE Contributor Insights and wait for the
  `DynamoDBContributorInsights-*` CloudWatch rules to actually be removed BEFORE
  deleteTable — deleting the table mid-cleanup strands those rules forever
  (CloudWatch rejects Delete/Disable/Put on DynamoDB-created rules, even under
  AdministratorAccess). reconcile also settles the DISABLING→DISABLED transition
  so a destroy can't race the cleanup. New reproduction test + post-destroy
  assertion of zero rules.
- ECS `Task` delete: hard-delete the deregistered revision via
  `deleteTaskDefinitions` — `deregister` alone leaves an INACTIVE revision
  forever (a fleet-wide leak; a live sweep found + removed 15).

Test-side guaranteed cleanup for out-of-band / undeletable resources:

- BackupSearch/SearchJob: search jobs have no delete API — added a stop-sweeper
  (pre-clean + ensuring) and documented the ~7-day server retention of terminal
  records (the BackupSearch analogue of KMS PENDING_DELETION).
- RDSData/Bindings: new idempotent reaper (reap.ts) tears down the whole VPC
  stack (Lambdas, log groups, roles, DB clusters/subnet groups, secrets, ENIs,
  SGs, subnets, VPC with DependencyViolation retries) — beforeAll pre-clean +
  afterAll ensuring.
- PaymentCryptography: reapKeys.ts schedules deletion (3-day, the only delete)
  for test-tagged keys via ensuring + an ungated reap test for crashed runs.
- ECS Fargate E2E + KMS bindings: orphan sweeps / verified acquire-release.

nuke.sh hardening — it was targeting `alchemy-state-*` (the deployment STATE
store) and `alchemy-assets-*` buckets: spare both by name; exclude AWS-managed
account resources (ServiceLinkedRole, LakeFormation, Notifications,
ApiGateway.Account) and default-named singletons (Athena primary, DAX default,
AppConfig predefined strategies, …) plus `DO-NOT-DELETE-*`.

Known-undeletable residue (documented, zero-cost): 2 pre-existing DynamoDB
Contributor-Insights rules (no API removes them; source tables gone) and
BackupSearch terminal job records (~7-day retention).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Live-tested the 166 AWS services that had tests but weren't covered by the
earlier passes (the original count was corrupted by a cwd bug — the real total
is ~204 tested services, of which only 35 had been verified this session).

Result: 166/166 ungated suites GREEN and 166/166 verified ZERO-ORPHAN via a
live out-of-band sweep after each suite. 117 tests legitimately skipIf-gated,
each with the exact reason (cost — e.g. ACMPCA private CA prorated billing;
singleton conflicts — e.g. AIOps one-investigation-group-per-region;
slow/entitlement provisioning — MWAA, OpenSearch, SageMaker, MemoryDB, Neptune;
domain/cert prerequisites CI can't complete). Two ungated typed probes kept per
gated lifecycle so the distilled error union stays proven on every pass.

Same contract applied per service: fix failures at the root, deterministic
names (no Math.random/Date.now), Effect.acquireRelease/ensuring cleanup with
idempotent typed deletes, provider-delete fixes where a delete stranded
sub-resources, and prove clean-slate with an out-of-band sweep.

Companion distilled patch: s3 deleteBucket now surfaces BucketHasAccessPointsAttached
(ConflictError) instead of UnknownAwsError — S3 rejects DeleteBucket while the
eventually-consistent access-point attachment view is non-empty, so consumers
need the typed tag to retry (was the direct cause of S3Control destroy failures).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The account-wide nuke (the acceptance test) caught what per-service clean-slate
sweeps missed — auto-created sub-resources of a different type, and
replacement/rename orphans. Fixed + re-verified clean-slate for 8 services:

Auto-created CloudWatch log groups that survive their parent's deletion —
reaped in the provider delete (modeled on the Lambda `/aws/lambda/{name}` reap,
with a bounded re-reap for asynchronously-materializing groups):

- InternetMonitor `Monitor`: reaps `/aws/internet-monitor/{name}/*` (byCity/…).
- MWAAServerless `Workflow`: reaps `/aws/mwaa-serverless/{workflow}` (name
  derived from the ARN, so a rename's old group is deleted through the same path).
- Deadline `Queue`/`Farm`: reap `/aws/deadline/{farmId}/*` after wait-until-gone.
- Batch: test-side reaper deletes test-owned `/aws/batch/job` streams, and the
  shared group only when no foreign streams remain.

Replacement/rename orphans (deterministic out-of-band + guaranteed cleanup):

- KinesisAnalyticsV2: the Flink code zip was staged in an IN-STACK S3 bucket
  whose per-instance physical name a crashed run could never reclaim — moved to
  a deterministic out-of-band code bucket with `Effect.ensuring` delete
  (fixed a latent identical leak in the CloudWatch-logging test too).
- ApiGateway `Deployment.test`: `reapRestApis` pre-clean + ensuring to survive
  the ~1/30s deleteRestApi throttle race.
- IoT `ThingType`: deterministic name + delete-if-exists pre-clean; documented
  the mandatory 5-minute deprecation→deletion window (worst case: one deprecated
  type, reused by the next run).
- DMS: reap the out-of-band VPC stack (subnets/IGW/route tables/ENIs) on teardown.

All new retry predicates annotated `: boolean` to avoid the inferred-type-predicate
provider-layer poison.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@sam-goodwin sam-goodwin changed the title feat(aws): generate 100% AWS Resource & Binding coverage feat(aws)!: generate 100% AWS Resource & Binding coverage Jul 13, 2026
sam-goodwin and others added 7 commits July 14, 2026 12:41
Brings Effect 4.0.0-beta.97 (removed Schedule.both/either/tapOutput + modifyDelay
metadata signature) and the TypeScript 7 stable toolchain.

- Migrated Schedule APIs across ~490 files: both→max, either→min, tapOutput→tap
  ({ attempt }), modifyDelay callback → ({ duration }).
- Conflicts: S3 Bucket.ts kept our BucketHasAccessPointsAttached retry with main's
  Schedule.max syntax; distilled submodule merged (kept our AWS patches + main's
  Cloudflare workers); bun.lock from main.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sources, Redacted (snapshot 2026-07-14 22:58)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sources, Redacted (snapshot 2026-07-14 23:13)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sources, Redacted (snapshot 2026-07-14 23:28)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sources, Redacted (snapshot 2026-07-14 23:43)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sources, Redacted (snapshot 2026-07-14 23:58)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…sources, Redacted (snapshot 2026-07-15 00:13)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sam-goodwin and others added 22 commits July 15, 2026 21:50
…onfig, Athena, Backup, DAX, EventBridge, +4 more

Services touched (9):
- AppConfig
- Athena
- Backup
- DAX
- EventBridge
- Keyspaces
- MediaConvert
- MemoryDB
- Personalize

Files: +1 new, ~18 modified, -0 deleted, 2 non-AWS.
Bumps distilled submodule.

Snapshot 2026-07-15 21:50

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…unner, Backup, CloudWatch, ECS, PinpointSMSVoiceV2, +3 more

Services touched (8):
- AppRunner
- Backup
- CloudWatch
- ECS
- PinpointSMSVoiceV2
- Route53Resolver
- S3
- XRay

Files: +0 new, ~12 modified, -0 deleted, 2 non-AWS.
Bumps distilled submodule.

Snapshot 2026-07-15 22:02

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…al runs

Each fork loads the full distilled-from-src graph (~2-4 GB), so the
CI-tuned `maxWorkers: 16` OOMs a memory-constrained machine when running
the whole AWS suite. Gate it behind `VITEST_MAX_WORKERS` (e.g. 4) so
`bun vitest run` works locally without OOM; CI is unaffected (env unset
-> 16). Config-level maxWorkers propagates to all projects via
`extends: true` and vitest maps it to the forks pool cap (the CLI
`--maxWorkers` / `--poolOptions` flags are not honored under `projects`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
AIOps, Account, CostAndUsageReport, and Rbin had resources but no
`Binding.Service`, so a deployed Lambda couldn't invoke their read
plane. Add read-oriented bindings (each with an un-exported shared
`BindingHttp.ts` scaffold + thin per-op `{Op}Http.ts` layers), modeled
on the OAM/DLM/Organizations/CostExplorer exemplars, and a live
`Bindings.test.ts` Lambda fixture per service (idempotent: destroy on
entry and exit, deterministic names).

- AIOps: GetInvestigationGroup, GetInvestigationGroupPolicy,
  ListTagsForResource (group-ARN scoped) + ListInvestigationGroups
- Account: GetContactInformation, GetAlternateContact,
  GetAccountInformation, ListRegions, GetRegionOptStatus (account-level,
  IAM on "*"); fixture returns presence booleans only, never contact PII
- CostAndUsageReport: DescribeReportDefinitions, ListTagsForResource
  (Region pinned to us-east-1, the CUR global endpoint)
- Rbin: GetRule (rule-ARN scoped) + ListRules (account-scoped)

13 bindings, all live-verified single-fork (AIOps 5/5, Account 6/6,
CUR 3/3, Rbin 3/3). No distilled patches needed — every error was
already a typed tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The AWS/Cloudflare suites run on alchemy-test now. Delete
packages/alchemy/vitest.config.ts and the unused Test/Vitest adapter,
drop vitest/@effect/vitest/@vitest-ui from alchemy + root devDeps, and
point the RpcWorker JSDoc example at alchemy-test. The root catalog
keeps vitest entries — distilled workspace packages still resolve them
for their own unit tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…S.md

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…V2, Polly

Full-suite run (2687 pass / 6 fail, 21min @ concurrency 32) + nuke
--dry-run census produced a 6-service worklist; one agent per service
root-caused provider-first. All suites green, zero orphans verified
out-of-band.

- Amplify: create is now observe-ensure (findOwnApp before each retry
  adopts an app a timed-out CreateApp actually made); bounded retries on
  the new typed TimeoutException + 'Rate exceeded' across App/Branch ops.
- EC2 VpcEndpoint: no more spurious modify-after-create (structural
  policy compare vs the AWS default full-access doc); NotFound
  propagation races retried bounded; delete waits for async ENI release
  so parent VPC/subnet/SG deletes stop hitting DependencyViolation.
- Batch: wait-until-gone polls failed silently on budget expiry
  (Effect.repeat returns the last value), letting the engine delete the
  CE's service role mid-teardown and wedging CEs DISABLED+INVALID
  forever. Polls now fail loudly (typed timeout errors) and delete
  recovers wedged CEs by restoring a minimal same-name service role
  before deleting. Same class fixed in JobQueue.
- MediaPackageV2: Channel/OriginEndpoint list() were stubs, so sweeps
  could never reap children and ChannelGroup deletes ConflictException'd
  forever; real paginated list() + child-reaping deletes, plus an
  env-gated orphan-sweep test (MPV2_SWEEP).
- Polly Lexicon: precreate persists deterministic identity before
  reconcile so a mid-create crash can't orphan the lexicon.

Known cross-cutting follow-up (not in this commit): Apply.ts destroy
skips provider.delete for 'creating' rows with no attrs — the engine-
level orphan class Polly's precreate works around.

Bumps distilled (typed Amplify TimeoutException).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/aws/vendedlogs/b2bi/{default,transformers} are AWS-managed groups the
B2BI provider deliberately retains; filtering them keeps the leak census
noise-free.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The nuke census enumerated the default VPC and its intrinsic furniture
(4 default subnets, IGW, main-route-table route, default-NACL
associations, default-SG rules, account DhcpOptions) and deleted it
every round — but test/AWS/DefaultVpc.ts deliberately recreates the
default VPC as standing test infrastructure, so every census flagged 13
phantom items and every nuke churned them.

New un-exported defaultVpcScope.ts resolves {vpcId, dhcpOptionsId} of
the default VPC once per list(); each EC2 list() now skips only what
AWS itself provisions. User resources inside the default VPC (custom
subnets/SGs/NACLs/route tables) still list.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A ComputeEnvironment created in the same deploy as its service role can
settle INVALID (CLIENT_ERROR: role 'is not authorized to perform
ecs:DescribeClusters') because Batch validates the role before the
managed-policy attachment propagates — and INVALID is terminal until
Batch's slow periodic re-validation, so the deploy failed loudly.

Reconcile now routes creates through createAndSettle: a freshly-created
CE settling INVALID with an auth-propagation statusReason is reaped
(disable → delete → wait gone) and re-created, bounded at 3 attempts.
Any other INVALID reason, or exhaustion, still fails loudly with the
typed ComputeEnvironmentInvalidError.

Caught by the convergence loop's confirmation round (intermittent —
passed two prior full-suite rounds).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The delete-path re-reap watch observed a post-delete log flush recreate
/aws/lambda/{name} and then unconditionally died — aborting the whole
stack destroy and stranding downstream resources (CloudMap namespace +
services + Route53 zone in the live repro). The watch is now a bounded
observe→delete convergence loop (every 5s up to ~90s; delete is
idempotent, ResourceNotFoundException = done). The loud failure remains
for genuinely undeletable groups. Happy path drops from two observes to
one.

A flush landing after the final check is inherently unobservable; the
nuke census is the documented backstop.

Caught by convergence-loop round 5.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every convergence-loop round nukes the ECR repo, so the fixture's
container build+push is always cold; 210s tripped at c96. 330s covers
the measured cold path (162s healthy) with contention headroom.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Amplify can report the old job still active for a beat after its
successor deploys; the immediate delete then correctly returns the
typed BadRequestException and the assertion flaked. Bounded retry
(3s x 10) until the delete lands.

Caught by convergence-loop round 8.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A farm holding storage profiles/budgets/queues/fleets/limits conflicts
forever on deleteFarm — children never drain on their own, so the
bounded ConflictException retry exhausted and the farm leaked. New
reapFarmChildren(farmId) stops+deletes queue-fleet/queue-limit
associations, then budgets, queues, fleets, limits, and storage
profiles (post-queue, whose allowedStorageProfileIds block profile
deletion), each step idempotent. Farm.delete and the Bindings suite's
pre-clean share it. Both crash-leaked farms reaped live through the
new path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…cket

The front-loaded exponential (2s base x5) burned its attempts in the
first seconds of Amplify's ~per-minute account throttle bucket, so a
post-nuke DeleteApp storm exhausted it. App/Branch writes now retry on
an evenly-spread ~80s schedule, and deleteApp/deleteBranch also retry
'Rate exceeded' (previously only TimeoutException) so destroys survive
the storm too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…very

- CodeArtifact: the fixture surfaces typed errors as 500s and the test
  retried them all as transient — a runner-level body retry then hit a
  deterministic ConflictException re-publishing version 1.0.0 and
  burned 3x63s. Only genuinely transient tags retry now; a /reset
  route makes the lifecycle idempotent under runner retries.
- ApiGateway/OAM TestLease (the only two fs-based leases): rewritten on
  effect/FileSystem with a no-fs-error-escapes contract — dead-PID
  locks reclaimed, unreadable owners stolen after a grace window; a
  reboot-stale lock (EFAULT on rm) can no longer fail a hook.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolves conflicts from the distilled #369 merge landing on main; bumps
the distilled submodule to distilled main (a945d874c) and initializes
the new cloudflare-tools submodule from main.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@sam-goodwin
sam-goodwin merged commit 532c811 into main Jul 18, 2026
4 checks passed
@sam-goodwin
sam-goodwin deleted the claude/aws-fanout-coverage-plan-6eddae branch July 18, 2026 05:54
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