- LocalStack-friendly client factory (
src/core/awsClients.ts). All AWS clients now respectcfg.endpoint/TRANSFLOW_AWS_ENDPOINT,cfg.credentials/TRANSFLOW_AWS_*env vars, and force S3 path-style addressing automatically when an endpoint is configured. - New CLI commands:
transflow bake --out <dir>— buildtemplates.index.cjs+ runtime context locally.transflow local:start— provision LocalStack-side buckets, queue, DDB table, and the S3 → SQS notification.transflow local:worker [--templates-index <path>]— long-lived process that polls SQS and runs the Lambda handler in-process. Replaces the Lambda for local e2e.
- Cost-optimization defaults applied by
deploy:- S3 lifecycle on the tmp bucket (
uploads/expires afters3.tmpRetentionDays, default 7;outputs/after 4×; abort multipart after 1 day). - DynamoDB TTL on
ttlattribute (dynamoDb.ttlDays, default 30). - ECR lifecycle policy keeps last
ecr.retainImages(default 10) images. - Reserved Lambda concurrency cap (default 10).
- Configurable
s3.corsAllowedOrigins.
- S3 lifecycle on the tmp bucket (
sqs.fifotoggle — set tofalseto let S3 deliver events straight to SQS, halving Lambda invocations per upload. Recommended for most production deployments and required for the S3 → SQS direct path used bylocal:start.- Webhook helper (
src/core/webhook.ts) — single source of truth for HMAC-signed retry-with-backoff webhooks; both lambda handlers use it. exportToBucketpopulatesresults— previously onlyuploadResultdid, which meant DDBresultswas empty even when files were exported.- Dependency updates — AWS SDK 3.948 → 3.1037, esbuild 0.23 → 0.28, yargs 17 → 18, zod 3 → 4, typescript 5.9 → 6.0, vitest 2 → 3, jsdom 26 → 29, aws-sdk-client-mock 3 → 4. (Held back:
execa/orav9 — pure ESM;vitest@4— broken mock-constructor semantics;react@19— peer-dep change.) - CI — switched to bun (root + example), added Node 24-ready
actions/checkout@v5andactions/setup-node@v5, added a LocalStack-backed e2e job that runs the full integration suite. - Docs — full README rewrite with config table, dual mermaid diagrams (FIFO vs standard SQS), LocalStack walkthrough.
- Batch-upload race: two SQS messages sharing an
assembly_idran as parallelprocessJobcalls and clobbered DDBuploads. The handler now merges jobs byassembly_idbefore processing so each assembly has exactly one writer. x-amz-checksum-crc32rejection: AWS SDK ≥3.660 auto-attaches a CRC32 header on PUTs, which older LocalStack/MinIO releases reject. The S3 client factory setsrequestChecksumCalculation: "WHEN_REQUIRED"to opt out.parseSQSJobsshape detection: now handles three message bodies — pre-parsedProcessingJob, S3 event from a direct S3 → SQS notification, ors3:TestEvent(skipped silently).local:run:ctx.inputsLocalPathswas undefined; templates that iterated it crashed. Also missing theexportToBucketshim. Both fixed.local:startnow applies the same S3 lifecycle policydeploydoes, for parity with prod.- GitHub Actions templates (
assets/workflows/*): removed the redundantbakestep (deploy bakes internally) and addeddocker/setup-buildx-action.
src/lambda/sqsBridge.{ts,test.ts}— was orphaned (deploy.ts:521 already noted it).- Dead auth code in
src/server/auth.ts(extractUserContext,generateUserPath,generateUserOutputPath,validateUserAccess, error classes,sanitizePathComponent). KeptvalidateContentTypeandvalidateFileSizewhich are actually used. UserContexttype andStepContext.user/AssemblyStatus.userfields — were defined in types but never populated anywhere.- Stale
ioredisdependency in the runtimepackage.jsonemitted bybake(SSE was removed; ioredis was a leftover).
aws sts get-caller-identity,aws ecr get-login-password, andaws dynamodb create-tableshell-outs indeploy.tsare now SDK calls (ECRGetAuthorizationToken, DynamoDBDescribe/CreateTableCommand).
Initial release.