Skip to content

Migrate Swift Lambda build to Amazon Linux 2023 - #6

Merged
bradwindy merged 4 commits into
mainfrom
migrate-al2023
Jul 9, 2026
Merged

bradwindy merged 4 commits into
mainfrom
migrate-al2023

Conversation

@bradwindy

Copy link
Copy Markdown
Owner

Summary

  • provided.al2 is EOL: AWS blocks new-function creation Jul 31 2026 and updates Aug 31 2026, and officially recommends an AL2023-based runtime.
  • The CI swift-test job was failing outright: GitHub Actions now defaults marketplace actions to Node 24, which needs glibc ≥2.28 — newer than swift:6.3-amazonlinux2 ships, so actions/checkout couldn't run inside the container at all.
  • Switches scripts/build.sh, the Makefile, template.yaml's Runtime, and the CI container to amazonlinux2023/provided.al2023. The AL2023 Swift image already bundles git + openssl-devel, so the CI workflow's manual install step is removed too.
  • Updated README.md's stale manual-deploy instructions to match (also fixed an already-stale swift:6.0-amazonlinux2 reference along the way).

Test plan

  • sam validate --lint passes clean (previously warned about provided.al2 EOL).
  • YAML syntax validated.
  • Confirm swift-test job goes green on this PR (real AL2023 container on GitHub-hosted arm64 runner — this is the actual verification, since Docker wasn't available locally to dry-run).
  • Confirm python-test still passes (unaffected by this change, included as a sanity check).
  • deploy job stays skipped on this PR (by design — only runs on push to main).

🤖 Generated with Claude Code

https://claude.ai/code/session_019Ex6D4aZJirG2b5yhjZsNR

bradwindy and others added 4 commits July 9, 2026 12:53
provided.al2 is EOL: AWS blocks new-function creation Jul 31 2026 and
updates Aug 31 2026, and recommends migrating to an AL2023-based runtime.
Also fixes the CI swift-test job, which was failing outright: GitHub Actions
now defaults to Node 24 for marketplace actions, and Node 24 needs a newer
glibc than AL2 ships, so actions/checkout couldn't even run inside the old
container. swift:6.3-amazonlinux2023 has a current glibc and ships git +
openssl-devel already, so the CI workflow's manual install step is no
longer needed either.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Ex6D4aZJirG2b5yhjZsNR
swift test had never actually run on Linux before (previously blocked by
the CI checkout failure). It surfaced real portability gaps: on Linux,
Foundation splits URLSession/URLRequest/HTTPURLResponse into a separate
FoundationNetworking module, and ImageIO doesn't exist at all. Guard the
imports/usages with #if canImport(...), matching the pattern already used
in NetworkRequestManager.swift/ValidatedRequestManager.swift. No behavior
change on macOS; ImageResolutionChecker (a macOS-only local dev CLI, never
run in CI) gets a Linux stub that returns nil so the package still compiles.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Ex6D4aZJirG2b5yhjZsNR
Another gap swift test never caught before running on Linux for the first
time: Glibc's stdout/stderr overlay (unlike Darwin's) doesn't mark these
extern C globals Sendable, so Swift 6 strict concurrency rejects direct
references in CollectionReviewer, ImageResolutionChecker, and
CollectionLister. These are single-threaded interactive/batch CLI tools, so
aliasing the globals as nonisolated(unsafe) locals (the SE-0412-documented
escape hatch) is safe and requires no behavior change.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Ex6D4aZJirG2b5yhjZsNR
nonisolated(unsafe) on my own wrapper globals alone wasn't enough — the
diagnostic was on the *read* of Glibc's stdout/stderr in the initializer,
which nonisolated(unsafe) on the LHS doesn't launder. Per
swiftlang/swift#77866, the actual fix is
@preconcurrency import Glibc, and critically it has to be the first import
in the file — otherwise Foundation's own transitive (non-preconcurrency)
Glibc import wins and the diagnostic persists. Keeping nonisolated(unsafe)
on the wrapper lets too: that addresses a separate, independent diagnostic
(a new global of non-Sendable type UnsafeMutablePointer<FILE>).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Ex6D4aZJirG2b5yhjZsNR
@bradwindy
bradwindy merged commit 1d4a53b into main Jul 9, 2026
3 checks passed
bradwindy added a commit that referenced this pull request Jul 9, 2026
…nstant-time auth, input validation (#31)

* fix: address code-review findings (races, SSRF, constant-time auth, input validation)

Web app (collection-reviewer-web):
- Route progress writes through the existing write mutex so /api/sync and
  /api/progress no longer race and clobber the progress index (#1).
- Give atomicWrite a unique per-write temp name + failure cleanup, so
  concurrent writers can't collide on a shared *.tmp and leave a partial
  write / ENOENT crash (#4).
- Validate and clamp the /api/images count param (parseImageCount): a
  non-numeric value no longer silently yields 0 images, and a huge value
  can't spawn unbounded concurrent lambda fetches (#2).
- Clamp a stale/out-of-range progress index in mergeCollections
  (remapProgress) instead of silently resetting the reviewer to 0 (#5).
- Guard await request.json() in the decision + progress routes so a
  malformed body returns 400 instead of a raw 500 (#7).

Swift API Lambda:
- constantTimeEquals now reduces each operand to a fixed 32-byte SHA-256
  digest before the XOR compare, removing the secret-length timing leak
  from the previous early length-mismatch return (#6).

Converter Lambda:
- Enforce an http/https scheme allowlist, re-validate every redirect target
  against internal IP ranges (IMDS / loopback / RFC1918) while still
  permitting the legitimate public S3 redirect, and return generic error
  bodies instead of echoing raw exceptions (#3).

Tests: add Vitest plus web unit tests (atomicWrite, remapProgress,
parseImageCount, progress mutex, JSON-body guards); extend
AuthorizedConsumerTests with unequal-length cases; extend the converter
pytest suite with scheme/redirect SSRF and error-opacity coverage.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YqwmybDadEYqqfDMrHvxs

* fix: reject null/primitive JSON bodies in decision + progress routes

CodeRabbit review: request.json() returns null (or a bare primitive) without
throwing for a body like "null" or "42"; the subsequent destructuring then threw
a TypeError outside the try/catch, yielding a 500 instead of the intended 400.
Add an explicit non-null-object guard before destructuring in both write routes,
and cover it with valid-JSON "null" body tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019YqwmybDadEYqqfDMrHvxs

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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