@auth-craft/aws-cf-stack 1.7.1 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +24 -4
- package/README.md +61 -11
- package/assets/admin/cli.mjs +82 -82
- package/assets/gateway/worker.js +1 -1
- package/assets/lambda/index.mjs +42 -37
- package/bin/deploy.sh +13 -1
- package/cdk/bin/app.ts +28 -22
- package/cdk/lib/dynamodb-stack.ts +4 -6
- package/cdk/lib/lambda-stack.ts +109 -11
- package/lib/common.sh +34 -14
- package/lib/deploy-gateway.sh +2 -2
- package/lib/deploy-lambda.sh +2 -2
- package/package.json +10 -6
package/.env.example
CHANGED
|
@@ -11,12 +11,20 @@
|
|
|
11
11
|
# Required vs optional is marked per line.
|
|
12
12
|
|
|
13
13
|
# ─── Stage / project / naming ────────────────────────────────────────────────
|
|
14
|
+
# Resources are named {app}-{env}-{layer}-{component}, e.g. snapshot-commerce-prod-auth-data.
|
|
15
|
+
# app = AUTH_CRAFT_APP_NAME, else auth-craft[-<project>]
|
|
16
|
+
# env = STAGE
|
|
17
|
+
# layer = LAYER (default "auth")
|
|
18
|
+
# component = per-resource: data (table), api (Lambda), system/tenant/customer (workers)
|
|
19
|
+
# The {app}-{env}-{layer} base (no component) is also AUTH_SYSTEM_NAME / the JWT issuer.
|
|
14
20
|
STAGE=dev # optional (flag --stage), default dev | staging | prod
|
|
15
21
|
# also accepts production -> prod, development -> dev
|
|
16
|
-
PROJECT=default # optional (flag --project), default "default"
|
|
17
|
-
AUTH_CRAFT_APP_NAME= # optional (flag --app-name) —
|
|
18
|
-
# (e.g. snapshot-
|
|
19
|
-
#
|
|
22
|
+
PROJECT=default # optional (flag --project), default "default". app = auth-craft-<project>
|
|
23
|
+
AUTH_CRAFT_APP_NAME= # optional (flag --app-name) — full rebrand of the app name
|
|
24
|
+
# (e.g. snapshot-commerce, drops the auth-craft prefix).
|
|
25
|
+
# Unset = auth-craft[-<project>].
|
|
26
|
+
LAYER=auth # optional (flag --layer), default "auth" — layer namespace within
|
|
27
|
+
# the app; use a larger app's other layers (e.g. billing) per deploy.
|
|
20
28
|
|
|
21
29
|
# ─── Tool command overrides (optional — pin your own binaries) ───────────────
|
|
22
30
|
AUTH_CRAFT_WRANGLER_CMD= # optional — e.g. "pnpm wrangler"; default "npx --yes wrangler"
|
|
@@ -147,6 +155,18 @@ LAMBDA_REFRESH_COOKIE_TENANT=refresh_token_tenant
|
|
|
147
155
|
LAMBDA_REFRESH_COOKIE_SYSTEM=refresh_token_system
|
|
148
156
|
LAMBDA_AUDIT_ENABLED=false
|
|
149
157
|
LAMBDA_DEVICE_TRACKING=true
|
|
158
|
+
|
|
159
|
+
# ─── Observability cost controls (optional) ──────────────────────────────────
|
|
160
|
+
# CloudWatch Logs are billed for ingestion AND stored volume; retention only affects
|
|
161
|
+
# storage. Short retention in dev is the cheap default.
|
|
162
|
+
# Unset → 3 days in dev, 30 days in staging/prod.
|
|
163
|
+
# Valid → 1,3,5,7,14,30,60,90,120,150,180,365,400,545,731,1096,1827,2192,2557,
|
|
164
|
+
# 2922,3288,3653 (CloudWatch's fixed set — anything else fails at synth),
|
|
165
|
+
# or 'infinite' to never expire.
|
|
166
|
+
LAMBDA_LOG_RETENTION_DAYS=
|
|
167
|
+
# X-Ray tracing is billed per recorded trace. Unset → disabled in dev, active otherwise.
|
|
168
|
+
# active | disabled | pass_through
|
|
169
|
+
LAMBDA_TRACING=
|
|
150
170
|
LAMBDA_APP_URL=
|
|
151
171
|
LAMBDA_SUPPORT_EMAIL=
|
|
152
172
|
LAMBDA_CORS_ORIGINS=
|
package/README.md
CHANGED
|
@@ -28,17 +28,30 @@ process env.
|
|
|
28
28
|
|
|
29
29
|
### Naming convention
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
Pattern: **`{app}-{env}-{layer}-{component}`**.
|
|
32
|
+
|
|
33
|
+
- **`app`** — `auth-craft` by default; `auth-craft-<project>` with `--project`; or a full
|
|
34
|
+
rebrand with `--app-name` / `AUTH_CRAFT_APP_NAME` (e.g. `snapshot-commerce`).
|
|
35
|
+
- **`env`** — `--stage` (`dev|staging|prod`).
|
|
36
|
+
- **`layer`** — `--layer` / `LAYER`, default `auth`. Namespaces this deploy within a larger
|
|
37
|
+
app that has other layers (e.g. `--layer billing`), so the CLI is reused per layer.
|
|
38
|
+
- **`component`** — per-resource: `data` (table), `api` (Lambda), `system`/`tenant`/`customer`
|
|
39
|
+
(gateway workers).
|
|
33
40
|
|
|
34
41
|
| Resource | Name |
|
|
35
42
|
|----------|------|
|
|
36
|
-
| CDK stacks | `<app>-<
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
| Gateway
|
|
40
|
-
|
|
41
|
-
|
|
43
|
+
| CDK stacks | `<app>-<env>-<layer>-data`, `<app>-<env>-<layer>-api` |
|
|
44
|
+
| DynamoDB table | `<app>-<env>-<layer>-data` |
|
|
45
|
+
| Lambda fn (+ log group) | `<app>-<env>-<layer>-api` |
|
|
46
|
+
| Gateway workers (`multi`) | `<app>-<env>-<layer>-system` / `-tenant` / `-customer` |
|
|
47
|
+
| Gateway worker (`shared`) | `<app>-<env>-<layer>` |
|
|
48
|
+
| `AUTH_SYSTEM_NAME` / JWT issuer | `<app>-<env>-<layer>` (no component — keeps the `iss` claim stable) |
|
|
49
|
+
|
|
50
|
+
Example (`--app-name snapshot-commerce --stage prod`, default layer):
|
|
51
|
+
`snapshot-commerce-prod-auth-data` (table), `snapshot-commerce-prod-auth-api` (Lambda),
|
|
52
|
+
`snapshot-commerce-prod-auth-system` (worker), issuer `snapshot-commerce-prod-auth`.
|
|
53
|
+
|
|
54
|
+
So `outputs`/`gateway` look up the api stack `<app>-<env>-<layer>-api`. The CDK output keys are
|
|
42
55
|
`LambdaFunctionUrl`, `ApiBasePath`, `AuthSystemName`, `DynamoDBTableName`.
|
|
43
56
|
|
|
44
57
|
### Deploy model (multi vs shared)
|
|
@@ -150,6 +163,43 @@ CF_EDGE_GATE_SECRET="$SNAP_EDGE" CLOUDFLARE_ACCOUNT_ID="$SNAP_CF_ACCT" \
|
|
|
150
163
|
npx auth-craft-stack all --stage "$STAGE"
|
|
151
164
|
```
|
|
152
165
|
|
|
166
|
+
## Observability cost controls (log retention, tracing)
|
|
167
|
+
|
|
168
|
+
CloudWatch Logs and X-Ray are usually the two line items that make a low-traffic **dev**
|
|
169
|
+
stage cost more than the Lambda itself. Both are configurable, with stage-aware defaults
|
|
170
|
+
that keep dev cheap without touching staging/prod behaviour:
|
|
171
|
+
|
|
172
|
+
| Setting | Env var / flag | Default (dev) | Default (staging/prod) |
|
|
173
|
+
|---------|----------------|---------------|------------------------|
|
|
174
|
+
| Log retention | `LAMBDA_LOG_RETENTION_DAYS` / `--log-retention-days` | `3` days | `30` days |
|
|
175
|
+
| X-Ray tracing | `LAMBDA_TRACING` / `--tracing` | `disabled` | `active` |
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Cheapest dev: keep 1 day of logs, no tracing (tracing is already off by default in dev)
|
|
179
|
+
npx auth-craft-stack lambda --stage dev --log-retention-days 1
|
|
180
|
+
|
|
181
|
+
# Turn tracing back on in dev while debugging
|
|
182
|
+
npx auth-craft-stack lambda --stage dev --tracing active
|
|
183
|
+
|
|
184
|
+
# Long retention for an audited prod
|
|
185
|
+
npx auth-craft-stack lambda --stage prod --log-retention-days 365
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Notes:
|
|
189
|
+
- Retention accepts only **CloudWatch's fixed set** — `1, 3, 5, 7, 14, 30, 60, 90, 120, 150,
|
|
190
|
+
180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288, 3653` — or `infinite` to never
|
|
191
|
+
expire. Any other value fails at **synth** time with the valid list, so a typo can't
|
|
192
|
+
silently deploy the wrong retention.
|
|
193
|
+
- Retention caps **storage** cost only; you are still billed for log **ingestion**. To cut
|
|
194
|
+
ingestion, reduce what the app logs.
|
|
195
|
+
- Changing retention applies to the existing log group too (it's the same CloudFormation
|
|
196
|
+
resource), so old logs beyond the new window age out — it is not just for new logs.
|
|
197
|
+
- In `prod` the log group has `RemovalPolicy.RETAIN`, so destroying the stack keeps the logs
|
|
198
|
+
(and the group must be deleted manually before a same-name redeploy). In dev/staging it is
|
|
199
|
+
destroyed with the stack.
|
|
200
|
+
- `LogRetentionDays` and `TracingMode` are emitted as CDK outputs, so
|
|
201
|
+
`npx auth-craft-stack outputs` shows what is actually deployed.
|
|
202
|
+
|
|
153
203
|
## CORS (per scope + dynamic allowlist)
|
|
154
204
|
|
|
155
205
|
CORS is resolved **per scope** (system / tenant / customer) — the 3 workers no longer
|
|
@@ -214,8 +264,8 @@ worker names + a ready-to-paste snippet are in `auth-craft-stack outputs`:
|
|
|
214
264
|
```jsonc
|
|
215
265
|
// auth-craft-stack outputs →
|
|
216
266
|
{
|
|
217
|
-
"workerNames": { "system": "auth-craft-prod-system", "tenant": "...", "customer": "auth-craft-prod-customer" },
|
|
218
|
-
"pagesProxy": { "serviceBindingExample": "[[services]]\nbinding = \"AUTH_GATEWAY\"\nservice = \"auth-craft-prod-customer\"\n" }
|
|
267
|
+
"workerNames": { "system": "auth-craft-prod-auth-system", "tenant": "...", "customer": "auth-craft-prod-auth-customer" },
|
|
268
|
+
"pagesProxy": { "serviceBindingExample": "[[services]]\nbinding = \"AUTH_GATEWAY\"\nservice = \"auth-craft-prod-auth-customer\"\n" }
|
|
219
269
|
}
|
|
220
270
|
```
|
|
221
271
|
|
|
@@ -225,7 +275,7 @@ In the Pages app:
|
|
|
225
275
|
# wrangler.toml (your Pages project) — bind the gateway worker for the scope this app serves
|
|
226
276
|
[[services]]
|
|
227
277
|
binding = "AUTH_GATEWAY"
|
|
228
|
-
service = "auth-craft-prod-customer" # from outputs.workerNames.<scope>
|
|
278
|
+
service = "auth-craft-prod-auth-customer" # from outputs.workerNames.<scope>
|
|
229
279
|
```
|
|
230
280
|
|
|
231
281
|
```ts
|