CDK v2 (TypeScript) app for OpenJobRadar's data plane, control plane, and first API route. See
ADR-0021 (data plane: single tenant table vs. one-per-entity, the due-work GSI's date-bucketing),
ADR-0022 (control plane: Cognito user pool, PKCE client, MFA posture), and ADR-0024 (GET /me:
HTTP API + Cognito JWT authorizer, no-Docker-bundling constraint) for the design decisions — and
why no AWS account ID ever appears in this source tree.
bin/app.ts— entry point, instantiates all three stacks in dependency order (data plane → control plane → API, since the API stack needs constructs from both). ResolvesenvName(dev/stage/prod) from CDK context (-c envName=...) orOPENJOBRADAR_ENV, defaulting todev; fails closed on anything else. Account/region come only fromCDK_DEFAULT_ACCOUNT/CDK_DEFAULT_REGION— never a literal. Cognito Hosted UI callback/logout URLs come fromOPENJOBRADAR_CALLBACK_URLS/OPENJOBRADAR_LOGOUT_URLS(comma-separated);devalone gets alocalhostdefault,stage/prodmust set both explicitly or synth fails closed.lib/env.ts— the sharedEnvNametype every stack uses.lib/data-plane-stack.ts(TenantTable+DueWorkTable),lib/control-plane-stack.ts(Cognito user pool + Hosted UI domain + app client),lib/api-stack.ts(HTTP API + Cognito JWT authorizer + one Lambda,GET /me) — one file per construct, independently documented.src/openjobradar/lambda_handlers/(Python side, not here) — thin Lambda entry points.Code.fromAssetzipssrc/verbatim with no dependency-install step, which only works because these handlers stay dependency-light (boto3only — see ADR-0024's consequences for what adding a handler that needsPyYAML/jsonschemawould require).test/— Jest +aws-cdk-lib/assertionsunit tests against the synthesized CloudFormation templates (key schemas, GSI shape, encryption/PITR, password policy, MFA config, JWT authorizer wiring, IAM grant shape, CORS per environment, removal policy per environment, and a direct check that no 12-digit AWS account ID ever appears in synthesized output).
npm ci # install (uses the committed package-lock.json)
npm run build # tsc typecheck (noEmit)
npm test # jest
npm run synth # cdk synth — no AWS credentials required (environment-agnostic)
npx cdk synth -c envName=prod # synth a specific environmentnpm run synth / npx cdk synth never touch AWS by themselves; only cdk deploy does, and
that needs real credentials for whichever of the three accounts (ADR-0010) you're targeting.
Verified locally with AWS credentials fully unset (env -u AWS_PROFILE ..., a fresh HOME) —
synth still succeeds and no account ID leaks into the template — which is exactly the
credential-free environment CI's infra job runs in.
No SES, no KMS CMK for the credentials vault (ADR-0007), no DueWorkIndex/Dispatcher compute
(EventBridge, SQS lanes) — only one Lambda-backed route exists (GET /me). IAM for that route
is table-scoped, not yet entity-scoped (tracked open in ADR-0024's consequences and
docs/THREAT-MODEL.md).