feat(worker): stream through API Gateway REST V1, and grant kv access in CloudFormation - #267
Closed
ItamarZand88 wants to merge 5 commits into
Closed
feat(worker): stream through API Gateway REST V1, and grant kv access in CloudFormation#267ItamarZand88 wants to merge 5 commits into
ItamarZand88 wants to merge 5 commits into
Conversation
Linking a kv to a permission profile emitted no IAM in the CloudFormation package, so a package install got no DynamoDB data-plane access while the identical stack worked on push (the runtime permissions generator supplies the grants there). Queue, storage, vault, email, and OpenSearch already emit these policies; kv was the one data resource that did not. The permission-owner scan the emitters share was duplicated byte-for-byte in queue and email; it now lives in helpers so kv reuses it instead of adding a third copy.
Binding service tags must be globally unique across resource types — serde and every env-var scanner dispatch on the tag alone. The external AI binding and the external Postgres binding both claimed "external", so the gateway launcher grabbed a BYO database binding, failed to parse it as an AI key, and died at startup with "missing field 'provider'" for any workload that links both. Compatible only while 3.3.0 is unpublished; the dev prereleases carry the old tag and heal on their next publish.
A streaming worker (WORKER_RESPONSE_STREAMING=true) is served through an API Gateway REST (V1) API with responseTransferMode=STREAM — the only API Gateway flavor that both streams and carries a custom domain. Buffered workers stay on the V2 HTTP API. Adds an apigateway REST client, the controller create/update/delete states, the importer fields, and the setup-role /restapis + basepathmapping permissions.
Teardown treated a permission error as a deleted resource, which would report a REST API and its custom domain cleaned up while both stayed live and billed; only a missing resource is tolerated now, matching the V2 path. A worker with no endpoint yet that reruns the update path after enabling streaming reached a state its wrapper rejected, wedging the resource in UpdateFailed on every retry. CreateDeployment takes no tags, so the stage it creates sat outside the deployment tag boundary that every management grant is conditioned on. An imported worker never learns its base path mapping key, so deletion skipped the mapping and then failed on the domain that still referenced it. Also regenerates the import-data schema snapshots for the new REST fields and the CloudFormation full-stack snapshot, names the failing operation in mapped API Gateway errors, and corrects the permission-set descriptions that still described the grants as HTTP-only.
Greptile SummaryThis follow-up scopes Lambda invocation permission to the selected API Gateway and makes REST stage tagging retryable after partial provisioning failures.
Confidence Score: 5/5The PR appears safe to merge because both previously reported failures are fixed and no eligible blocking failure remains. No blocking failure remains.
|
| Filename | Overview |
|---|---|
| crates/alien-infra/src/worker/aws.rs | The prior invocation-scope and stage-tag retry defects are both addressed without an eligible distinct residual failure. |
| crates/alien-aws-clients/src/aws/apigateway.rs | Adds the signed REST V1 API Gateway operations and request models needed for streaming worker endpoints. |
| crates/alien-cloudformation/src/emitters/aws/kv.rs | Adds resource-scoped DynamoDB data-plane policy emission for linked KV permission profiles. |
| crates/alien-core/src/bindings/ai.rs | Separates the external AI serialization tag from other external resource bindings. |
Sequence Diagram
sequenceDiagram
participant Controller as AWS Worker Controller
participant REST as API Gateway REST V1
participant Lambda as Lambda
Controller->>REST: Create deployment and prod stage
REST-->>Controller: Deployment ID
Controller->>REST: Tag prod stage
alt Tagging fails transiently
REST-->>Controller: Error
Controller->>REST: Retry stage tagging
end
Controller->>Lambda: Add invoke permission with API-specific SourceArn
Lambda-->>Controller: Permission recorded
Reviews (2): Last reviewed commit: "fix(worker): scope the API Gateway invok..." | Re-trigger Greptile
…g retryable The Lambda invoke grant named apigateway.amazonaws.com with no source, so any API Gateway in any account could call the function; it now names the API that fronts the worker. Stage tagging sat inside the deployment-creation guard, so a transient failure left the deployment id recorded and every retry skipped the tag.
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.
Summary
Three fixes to how AWS workers are exposed and permissioned. A worker can now stream its response through an API Gateway REST (V1) API with a custom domain; the CloudFormation package finally grants a linked kv store's data-plane access; and the external AI binding gets a service tag that doesn't collide with the external Postgres binding.
When a streaming worker is provisioned:
WORKER_RESPONSE_STREAMING=truefrom the worker's environment and takes the REST V1 path instead of the V2 HTTP API.{proxy+}resource, anANYmethod, and anAWS_PROXYintegration — the integration is the heart: it targets the Lambda'sresponse-streaming-invocationsURI withresponseTransferMode = STREAMand a 900s timeout, which is what lets bytes reach the client as they are produced.prodstage, tags it, and attaches the custom domain through a base path mapping.A Lambda Function URL also streams, but cannot carry a custom domain, so REST V1 is the only flavor that does both.
What was broken
"service": "external", and service tags must be globally unique because serde dispatches on the tag alone. The gateway launcher claims everyALIEN_*_BINDINGwhose tag is in its AI set and fails fast when one doesn't parse as an AI binding, so such a workload died at startup withmissing field 'provider'.What I did
Added the REST V1 client and controller states; added kv IAM emission mirroring the queue emitter; renamed the external AI binding's tag to
external-ai. The permission-owner scan was byte-identical in the queue and email emitters, so it moved tohelpers.rsrather than gaining a third copy.Files touched
crates/alien-aws-clients/src/aws/apigateway.rs(new REST V1 client) ·crates/alien-infra/src/worker/aws.rs(controller states) ·crates/alien-cloudformation/src/emitters/aws/{kv,queue,email,helpers}.rs·crates/alien-core/src/bindings/ai.rs·crates/alien-ai-gateway/src/config.rs·crates/alien-permissions/permission-sets/worker/{management,provision}.jsonc·packages/ai-gateway/src/binding.ts· regenerated schemas and snapshots.How I tested
Deployed a streaming worker to a real AWS account and drove it end to end:
aws apigateway get-integrationreportsAWS_PROXY,responseTransferMode=STREAM,timeoutInMillis=900000, and theresponse-streaming-invocationsURI.message_stop— well past the 29s cap the V2 API imposes.mainand passes here. I also rendered a template onmainwith a wildcardkv/*grant to check whether the service-account inline policy covered it — it does not;mainemits no DynamoDB data-plane action anywhere in CloudFormation.cargo test: cloudformation 87, core 479, permissions 130, aws-clients 43, infra 518. Clippy clean.Reviewed for the security questions this touches: the new
/restapisandbasepathmappingsgrants mirror the existing/apisandapimappingsentries in action set, ARN shape and tag condition — no statement was added without one; the stage is now tagged so it sits inside the same boundary every management grant is conditioned on (I confirmed on a live deployment that it previously was not); the kv policy is pinned to the table's ARN viaFn::GetAtt, so it cannot reach another table in the account; and no grant reaches/apikeysorexecute-api:Invoke. Nothing turned up.Known limitations
create_resourcehas no conflict read-back: a lost response on that one call needs a delete rather than a retry. Same shape as the existing V2 domain path.CloudPlatformErrorwith no source, matching the V2 code beside them; switching them all to a concrete variant is a separate cleanup.