@auth-craft/aws-cf-stack 1.7.0 → 1.8.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/lib/common.sh CHANGED
@@ -76,11 +76,18 @@ load_env_file() {
76
76
  }
77
77
 
78
78
  # ── Stage / naming derivation (mirrors the CI workflow + CDK app.ts) ──────────
79
- # Inputs: STAGE, PROJECT, optional AUTH_CRAFT_APP_NAME.
80
- # Exports STAGE (normalized), PROJECT, APP_NAME, RESOURCE_NAME, RUNTIME_NODE_ENV.
79
+ # Inputs: STAGE, PROJECT, LAYER, optional AUTH_CRAFT_APP_NAME.
80
+ # Exports STAGE (normalized), PROJECT, APP_NAME, LAYER, RESOURCE_NAME, RUNTIME_NODE_ENV.
81
+ #
82
+ # Naming pattern: {app}-{env}-{layer}, with a per-resource {component} appended
83
+ # (data/api/system/…). So table = {app}-{env}-{layer}-data, lambda = …-api, etc.
84
+ # RESOURCE_NAME is the {app}-{env}-{layer} base (also the AUTH_SYSTEM_NAME / JWT
85
+ # issuer). LAYER (default "auth") namespaces this deploy within a larger app that
86
+ # has other layers (e.g. billing); a consumer sets --layer/LAYER to reuse the CLI.
81
87
  derive_naming() {
82
88
  STAGE="${STAGE:-dev}"
83
89
  PROJECT="${PROJECT:-default}"
90
+ LAYER="${LAYER:-auth}"
84
91
 
85
92
  # #2 Normalize common stage aliases so a consumer can pass either form.
86
93
  # production -> prod, development -> dev, staging stays staging.
@@ -103,9 +110,12 @@ derive_naming() {
103
110
  APP_NAME="auth-craft-${PROJECT}"
104
111
  fi
105
112
 
106
- RESOURCE_NAME="${APP_NAME}-${STAGE}"
113
+ # Base name shared by every resource: {app}-{env}-{layer}. Per-resource component
114
+ # (data/api/system/…) is appended at each call site. Also the AUTH_SYSTEM_NAME /
115
+ # JWT issuer, so it must NOT carry a component (keeps the iss claim stable).
116
+ RESOURCE_NAME="${APP_NAME}-${STAGE}-${LAYER}"
107
117
  RUNTIME_NODE_ENV="$([[ "$STAGE" == "prod" ]] && echo production || echo development)"
108
- export STAGE PROJECT APP_NAME RESOURCE_NAME RUNTIME_NODE_ENV
118
+ export STAGE PROJECT APP_NAME LAYER RESOURCE_NAME RUNTIME_NODE_ENV
109
119
  }
110
120
 
111
121
  # ── Gateway JWT key pair (#5: one source, derive the rest) ────────────────────
@@ -188,16 +198,16 @@ gateway_mode() {
188
198
  }
189
199
 
190
200
  # Derive a gateway worker URL for a scope (custom domain > workers.dev > empty).
191
- # In shared mode all scopes resolve to the single worker ${APP_NAME}-${STAGE}.
201
+ # In shared mode all scopes resolve to the single worker ${RESOURCE_NAME}.
192
202
  gateway_url_for() {
193
203
  local scope="$1" upper dom_var custom worker_name
194
204
  upper="$(echo "$scope" | tr '[:lower:]' '[:upper:]')"
195
205
  dom_var="CF_WORKER_CUSTOM_DOMAIN_${upper}"
196
206
  custom="${!dom_var:-}"
197
207
  if [[ "$(gateway_mode)" == "shared" ]]; then
198
- worker_name="${APP_NAME}-${STAGE}"
208
+ worker_name="${RESOURCE_NAME}"
199
209
  else
200
- worker_name="${APP_NAME}-${STAGE}-${scope}"
210
+ worker_name="${RESOURCE_NAME}-${scope}"
201
211
  fi
202
212
  if [[ -n "$custom" ]]; then
203
213
  echo "https://$custom"
@@ -221,7 +231,7 @@ gateway_url_for() {
221
231
  print_outputs_json() {
222
232
  require_cmd aws; require_cmd jq
223
233
  require_aws_identity
224
- local api_stack="${APP_NAME}-${STAGE}-api"
234
+ local api_stack="${RESOURCE_NAME}-api"
225
235
  local url base name table fn backend issuer
226
236
  url="$(cfn_output "$api_stack" LambdaFunctionUrl)"
227
237
  base="$(cfn_output "$api_stack" ApiBasePath)"
@@ -244,20 +254,20 @@ print_outputs_json() {
244
254
  svcPub="$(lambda_env "$fn" INTERNAL_JWT_PUBLIC_KEY)"; svcPub="${svcPub:-${LAMBDA_INTERNAL_JWT_PUBLIC_KEY:-}}"
245
255
 
246
256
  # Worker names per scope. In multi mode (default) each scope is its own worker
247
- # (${APP_NAME}-${STAGE}-${scope}); in shared mode all scopes are the single worker
248
- # ${APP_NAME}-${STAGE}. These are what a consumer's Cloudflare Pages project references
257
+ # (${RESOURCE_NAME}-${scope}); in shared mode all scopes are the single worker
258
+ # ${RESOURCE_NAME}. These are what a consumer's Cloudflare Pages project references
249
259
  # in a Service Binding (`[[services]] service = "<worker name>"`) to front auth
250
260
  # same-origin via @auth-craft/pages-auth-proxy. The binding lives in the consumer's
251
261
  # Pages project, not here — `serviceBindings` is a ready-to-paste snippet.
252
262
  local mode wnSystem wnTenant wnCustomer bindingService
253
263
  mode="$(gateway_mode)"
254
264
  if [[ "$mode" == "shared" ]]; then
255
- wnSystem="${APP_NAME}-${STAGE}"; wnTenant="$wnSystem"; wnCustomer="$wnSystem"
265
+ wnSystem="${RESOURCE_NAME}"; wnTenant="$wnSystem"; wnCustomer="$wnSystem"
256
266
  bindingService="$wnSystem"
257
267
  else
258
- wnSystem="${APP_NAME}-${STAGE}-system"
259
- wnTenant="${APP_NAME}-${STAGE}-tenant"
260
- wnCustomer="${APP_NAME}-${STAGE}-customer"
268
+ wnSystem="${RESOURCE_NAME}-system"
269
+ wnTenant="${RESOURCE_NAME}-tenant"
270
+ wnCustomer="${RESOURCE_NAME}-customer"
261
271
  bindingService="$wnCustomer"
262
272
  fi
263
273
  local bindingSnippet
@@ -295,7 +295,7 @@ deploy_gateway() {
295
295
  # ── Shared worker: one worker serves all scopes; scope comes from the path's first
296
296
  # segment (worker AUTH_SCOPE unset). CORS unions all scopes; KV uses the customer id.
297
297
  local worker_name custom_domain allowed_origins origin_suffixes cors_kv_id
298
- worker_name="${APP_NAME}-${STAGE}"
298
+ worker_name="${RESOURCE_NAME}"
299
299
  custom_domain="$(custom_domain_for shared)"
300
300
  allowed_origins="$(merge_cors_for_shared allowed_origins_for)"
301
301
  origin_suffixes="$(merge_cors_for_shared origin_suffixes_for)"
@@ -324,7 +324,7 @@ deploy_gateway() {
324
324
  local scope worker_name route_prefix custom_domain
325
325
  local allowed_origins origin_suffixes cors_kv_id
326
326
  for scope in system tenant customer; do
327
- worker_name="${APP_NAME}-${STAGE}-${scope}"
327
+ worker_name="${RESOURCE_NAME}-${scope}"
328
328
  route_prefix="$(route_prefix_for "$scope")"
329
329
  custom_domain="$(custom_domain_for "$scope")"
330
330
  allowed_origins="$(allowed_origins_for "$scope")"
@@ -21,11 +21,11 @@ deploy_lambda() {
21
21
  [[ -f "$LAMBDA_ASSET_DIR/index.mjs" ]] \
22
22
  || die "Prebuilt Lambda bundle missing: $LAMBDA_ASSET_DIR/index.mjs (was the package built?)"
23
23
 
24
- local api_stack="${APP_NAME}-${STAGE}-api"
24
+ local api_stack="${RESOURCE_NAME}-api"
25
25
  OUTPUTS_FILE="${OUTPUTS_FILE:-$(mktemp -t auth-craft-cdk-outputs.XXXXXX.json)}"
26
26
  export OUTPUTS_FILE
27
27
 
28
- info "Deploying CDK stacks (${APP_NAME}-${STAGE}-data, ${api_stack})…"
28
+ info "Deploying CDK stacks (${RESOURCE_NAME}-data, ${api_stack})…"
29
29
  (
30
30
  cd "$CDK_DIR"
31
31
  CDK_DEFAULT_ACCOUNT="$AWS_ACCOUNT_ID" \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@auth-craft/aws-cf-stack",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Self-contained, versioned distribution of the Auth Craft AWS (DynamoDB + Lambda) + Cloudflare gateway stack. Bundles prebuilt Lambda/worker artifacts + CDK app so consumers deploy without cloning auth-craft.",
5
5
  "type": "module",
6
6
  "bin": {