Skip to content

fix(aws): harden CloudFormation BYOC releases - #179

Merged
alongubkin merged 23 commits into
mainfrom
alon/alien-320-harden-aws-cloudformation-byoc-release-path
Jul 25, 2026
Merged

fix(aws): harden CloudFormation BYOC releases#179
alongubkin merged 23 commits into
mainfrom
alon/alien-320-harden-aws-cloudformation-byoc-release-path

Conversation

@alongubkin

@alongubkin alongubkin commented Jul 23, 2026

Copy link
Copy Markdown
Member

Summary

  • emit valid NextGen OpenSearch Serverless and storage CORS CloudFormation resources
  • preserve deployer input values and include transitive native-addon bytes in build cache keys
  • avoid unauthenticated bootstrap OTLP export when runtime secrets are vault-backed
  • parse raw storage keys before signing so reserved characters are encoded exactly once

Validation

  • focused OpenSearch and storage CloudFormation generator tests
  • AWS CloudFormation ValidateTemplate and real create/update deployment proof
  • real AWS NextGen collection-group deployment: Generation: NEXTGEN, zero minimum indexing/search OCU, on.aws endpoint
  • full locally built application proof through Platform pnpm dev: TLS/health, send, asynchronous indexing, full-text search hit, and content retrieval
  • focused native storage-path and transitive-cache tests
  • focused worker-runtime OTLP test plus deployed cold-start/export proof
  • cargo check --locked -p alien-bindings-node

Linear: ALIEN-320

@greptile-apps

greptile-apps Bot commented Jul 23, 2026

Copy link
Copy Markdown

Greptile Summary

This PR hardens the AWS BYOC release path across several independently validated dimensions. CloudFormation emitters now emit valid NextGen OpenSearch Serverless collection groups with optional OCU capacity limits and valid S3 CORS rules. Storage bindings switch from Path::from to Path::parse so reserved characters are encoded exactly once before signing. The Lambda runtime pre-starts its transport before secret loading to satisfy AWS's Init window, and vault-backed OTLP credentials are no longer exported unauthenticated at bootstrap.

  • CloudFormation: S3 buckets get a CorsConfiguration block when cors_allowed_origins is non-empty; OpenSearch collection groups emit Generation: NEXTGEN and an optional CapacityLimits object, with OCU validation enforced before template generation.
  • Deployment runner: delay_threshold is replaced by DelayStrategy; a concurrent lease-renewal loop keeps the manager's distributed lock alive during long cloud operations; non-retryable checkpoint errors are now propagated immediately.
  • Executor concurrency: Ready resources are stepped up to 4 at a time via buffer_unordered; HeartbeatCollector is Arc-based so heartbeats are correctly shared across parallel tasks.

Confidence Score: 5/5

Safe to merge; all five hardening paths are independently validated with real AWS deployments and focused unit tests.

Changes are well-scoped: CloudFormation template generation is purely additive, the storage path fix is a targeted single-call swap, OTLP deferral is guarded by an env-var check, and the Lambda pre-start sequence correctly orders registration before secret loading. The executor parallelism is safe because HeartbeatCollector uses Arc and all parallel tasks read from the same immutable state snapshot. The only inconsistency found — setup_teardown.rs yielding on a zero-delay step where runner.rs would not — is a cosmetic edge case that does not affect correctness in practice.

Files Needing Attention: crates/alien-deployment/src/setup_teardown.rs — minor inconsistency in the zero-delay yield guard compared to runner.rs

Important Files Changed

Filename Overview
crates/alien-cloudformation/src/emitters/aws/storage.rs Adds S3 CorsConfiguration block (GET/HEAD, AllowedHeaders *, ETag exposed, 3600 MaxAge) when cors_allowed_origins is non-empty; guarded by an emptiness check so existing buckets are unaffected.
crates/alien-cloudformation/src/emitters/aws/open_search.rs Emits Generation: NEXTGEN on collection groups and conditionally inserts CapacityLimits; calls validate_capacity() before template generation to catch invalid OCU values early.
crates/alien-bindings-node/src/storage.rs Replaces Path::from() with Path::parse() for all storage operations so reserved characters in object keys are encoded exactly once rather than double-encoded when signing.
crates/alien-worker-runtime/src/otlp.rs Defers OTLP bootstrap when ENV_ALIEN_RUNTIME_SECRETS is present so an unauthenticated tracing bridge is not installed before vault-backed credentials are resolved.
crates/alien-worker-runtime/src/runtime.rs Pre-starts the Lambda transport before secret loading to satisfy AWS's 10-second Init window; cleanly shuts it down if application startup fails.
crates/alien-deployment/src/runner.rs Replaces delay_threshold with DelayStrategy enum; adds a concurrent lease-renewal loop and correctly propagates non-retryable checkpoint errors immediately without further retries.
crates/alien-deployment/src/setup_teardown.rs Adopts DelayStrategy::Yield in place of delay_threshold but omits the !delay.is_zero() guard present in runner.rs, so a zero suggested_delay_ms would cause an unnecessary yield.
crates/alien-infra/src/core/executor.rs Converts sequential resource stepping to parallel (up to 4 concurrent via buffer_unordered); HeartbeatCollector is Arc-based so cloning correctly shares state across tasks. Adds RunningResourcePolicy enum.
crates/alien-cli/src/commands/release.rs Push cache now validates that a cached URI belongs to the resolved destination repository before applying it, preventing cross-manager/project cache cross-contamination.
crates/alien-manager/src/routes/sync.rs New /v1/sync/renew endpoint renews a deployment lease without writing state; auth, ownership, and authz are all verified before the store call.

Sequence Diagram

sequenceDiagram
    participant CLI as alien-cli
    participant Mgr as Manager API
    participant Runner as DeploymentRunner
    participant Executor as StackExecutor

    CLI->>Mgr: POST /v1/sync/acquire (session)
    Mgr-->>CLI: deployment_id + state

    loop Step loop (max 200)
        Runner->>Executor: step(state, config)
        Executor->>Executor: buffer_unordered(4) – step ready resources
        Executor-->>Runner: suggested_delay_ms, heartbeats
        Runner->>Mgr: POST /v1/sync/reconcile (checkpoint)
        alt non-retryable rejection
            Mgr-->>Runner: 4xx (non-retryable)
            Runner-->>CLI: Err(DEPLOYMENT_CHECKPOINT_FAILED)
        else delay and Yield strategy
            Runner-->>CLI: Ok(Delayed) – yield to scheduler
        end
    end

    par Lease renewal (every 60s)
        Runner->>Mgr: POST /v1/sync/renew (session)
        Mgr-->>Runner: 200 OK
    end

    Runner-->>CLI: Ok(Synced / Failed)
    CLI->>Mgr: POST /v1/sync/release
Loading

Reviews (9): Last reviewed commit: "test(helm): update worker memory snapsho..." | Re-trigger Greptile

export const StorageSchema = z.object({
"id": z.string().describe("Name of the the storage bucket.\nFor names with dots, each dot-separated label must be ≤ 63 characters."),
"corsAllowedOrigins": z.optional(z.array(z.string()).describe("Browser origins allowed to read objects through signed URLs.\n\nWhen non-empty, providers configure CORS for `GET` and `HEAD` requests.\nAn origin of `*` is appropriate for private buckets whose signed URLs\nare bearer credentials and do not use browser cookies.\nDefault: `[]` (CORS disabled).")),
"id": z.string().describe("Name of the the storage bucket.\nFor names with dots, each dot-separated label must be ≤ 63 characters."),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Generated file drops indentation for id field

The newly added corsAllowedOrigins property is indented (4 spaces) but "id" and the remaining pre-existing properties ("publicRead", "versioning") have zero indentation. This is a generator artifact: the tool appears to emit consistent indentation only for the first alphabetical property. TypeScript and Zod parse the file correctly, so this has no runtime impact, but it points to an inconsistency in the code generator that may resurface as the schema grows.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/core/src/generated/zod/storage-schema.ts
Line: 14

Comment:
**Generated file drops indentation for `id` field**

The newly added `corsAllowedOrigins` property is indented (4 spaces) but `"id"` and the remaining pre-existing properties (`"publicRead"`, `"versioning"`) have zero indentation. This is a generator artifact: the tool appears to emit consistent indentation only for the first alphabetical property. TypeScript and Zod parse the file correctly, so this has no runtime impact, but it points to an inconsistency in the code generator that may resurface as the schema grows.

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@alongubkin
alongubkin force-pushed the alon/alien-320-harden-aws-cloudformation-byoc-release-path branch 2 times, most recently from f9e9801 to d0e58d7 Compare July 23, 2026 02:18
@alongubkin
alongubkin force-pushed the alon/alien-320-harden-aws-cloudformation-byoc-release-path branch from d0e58d7 to b1d404a Compare July 23, 2026 02:31
@alongubkin

Copy link
Copy Markdown
Member Author

Final AWS validation update:

  • Live OpenSearch Serverless rejected 1 OCU for both indexing and search; the supported nonzero floor is 2. Validation/schema and the CloudFormation fixture now enforce that before deployment (4229ed78, 3a45a908).
  • The generated CloudFormation setup path updated a real NEXTGEN collection group to min indexing/search 2.0 OCU; the stack reached UPDATE_COMPLETE. The runtime manager correctly refused to mutate the frozen setup-owned capacity.
  • Real Lambda testing exposed that an 8-second pre-poll readiness budget could still cross Lambda’s 10-second init limit. 22c1bcc3 now polls the Runtime API immediately and keeps readiness waiting inside invocation handling. A cold API invocation had one init (1334.03 ms), HTTP 200, and no init timeout/restart.
  • A cold events invocation initialized once (1165.78 ms) and a deliberately unmatched valid SQS event returned FunctionError: Unhandled / TASK_DELIVERY_FAILED, proving failures are no longer silently acknowledged.
  • Focused results: OpenSearch core 8/8, CloudFormation generator 7/7, TypeScript core 67/67, AWS runtime 80/80. Fresh CI is running on 3a45a908.

@alongubkin

Copy link
Copy Markdown
Member Author

@greptileai

@alongubkin

Copy link
Copy Markdown
Member Author

@greptileai

alongubkin and others added 3 commits July 25, 2026 22:27
## Summary

- persist delayed reconciliation wakeups instead of repeatedly
reacquiring work that is not ready
- keep eligible controller work under one bounded lease and run
independent ready resources concurrently
- renew ownership through a dedicated endpoint without rewriting
deployment state
- cancel promptly when ownership is lost and clear scheduled delays for
explicit user actions

## Why

A fresh multi-resource deployment exposed two framework failures: short
controller waits were repeatedly yielded through the shared scheduler,
and manager replicas could remain occupied retrying work after lease
loss. This preserves durable checkpoints while avoiding unnecessary
distributed scheduling between adjacent controller steps.

## Validation

- `cargo check -p alien-infra -p alien-deployment -p alien-manager
--all-features`
- 851 tests across `alien-infra`, `alien-deployment`, and
`alien-manager` passed (1 skipped)
- generated OpenAPI artifacts were produced through the repository
generators

## Dependency

Stacked on #179.

Linear:
https://linear.app/alienplatform/issue/ALIEN-324/make-deployment-leases-cancellable-and-keep-short-controller
@alongubkin

Copy link
Copy Markdown
Member Author

The remaining 4/5 finding is fixed in 35400f5: valid_nonzero_ocu no longer accepts 1, and the invalid-range test now explicitly covers maxOcu: 1. This matches the schema and the live AWS validation result. @greptileai

@greptile-apps

greptile-apps Bot commented Jul 25, 2026

Copy link
Copy Markdown

The fix looks correct. valid_nonzero_ocu now starts at 2matches!(value, 2 | 4 | 8 | 16) || (value >= 32 && value <= 1696 && value % 16 == 0) — and the invalid-range test case explicitly covers maxOcu: Some(1), confirming it's rejected. The validation and test coverage are consistent with the AWS AOSS schema. Acknowledged, thanks for the follow-up.

Tip: You can customize Greptile's behavior for this repo with .greptile/rules.md and .greptile/config.json.

@alongubkin

Copy link
Copy Markdown
Member Author

@greptileai The generated API schema is now synchronized from the source generator, removing the erroneous nullable component wrapper that broke the Rust SDK and CLI.

@alongubkin

Copy link
Copy Markdown
Member Author

@greptileai review

@alongubkin
alongubkin merged commit 98c2c71 into main Jul 25, 2026
17 checks passed
@alongubkin
alongubkin deleted the alon/alien-320-harden-aws-cloudformation-byoc-release-path branch July 25, 2026 20:38
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