@ampless/backend 1.0.0-alpha.48 → 1.0.0-alpha.49

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.
Files changed (2) hide show
  1. package/dist/index.js +35 -41
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -434,20 +434,25 @@ function amplessSchemaModels(a, opts = {}) {
434
434
  // never flows back to the browser.
435
435
  //
436
436
  // Authorization design:
437
- // - admin / editor: NO direct AppSync access. All writes go
438
- // through the plugin-secret-handler Lambda mutation.
439
- // - `allow.resource(pluginSecretHandlerFunction)`: grants the
440
- // plugin-secret-handler Lambda AppSync access to this model
441
- // (used internally by the mutation's resolver path).
442
- // - trusted-processor Lambda reads directly via DDB SDK with the
443
- // `grantReadData` IAM grant in `backend.ts`, bypassing AppSync
444
- // entirely no `@auth` rule needed for that path.
445
- // - Fallback (when `pluginSecretHandlerFunction` is not provided
446
- // by the caller): admin-only Cognito group. Encryption renders
447
- // ciphertext meaningless without the env-var key, but the
448
- // feature won't actually work without the handler — this
449
- // fallback only exists to keep CDK synth from failing in a
450
- // partially-wired deployment.
437
+ // - admin / editor: NO AppSync access. The model uses a
438
+ // placeholder group (`__ampless_internal__`) that no Cognito
439
+ // user belongs to. Amplify Gen 2 requires every model to have
440
+ // at least one auth rule, and this is the minimum-viable one
441
+ // that synthesizes cleanly while denying all AppSync access.
442
+ // - plugin-secret-handler Lambda: full DDB access via the
443
+ // `grantReadWriteData` IAM grant in `backend.ts`. It calls
444
+ // the DDB SDK directly (NOT through AppSync), so the model's
445
+ // @auth rule is irrelevant to its actual write path.
446
+ // - trusted-processor Lambda: read-only DDB access via the
447
+ // `grantReadData` IAM grant in `backend.ts`. Same pattern
448
+ // bypasses AppSync entirely.
449
+ // - Lambda `allow.resource(...)` is unavailable at the model
450
+ // level in `@aws-amplify/data-schema` (the `resource` helper
451
+ // is destructured out of `allow` before model-level callbacks
452
+ // run; see line 141 in this file). Schema-level resource auth
453
+ // would grant the Lambda AppSync access to ALL models — too
454
+ // broad for our needs. The DDB-SDK direct path keeps the
455
+ // access scoped to the table the Lambda needs.
451
456
  //
452
457
  // Storage key convention:
453
458
  // siteId = 'default' (single-site architecture)
@@ -475,17 +480,12 @@ function amplessSchemaModels(a, opts = {}) {
475
480
  // / deploy artifact access, NOT defeated for a malicious
476
481
  // trusted plugin co-located in the same Lambda.
477
482
  value: a.string().required()
478
- }).identifier(["siteId", "sk"]).authorization((allow) => {
479
- const rules = [];
480
- if (opts.pluginSecretHandlerFunction) {
481
- rules.push(
482
- allow.resource(opts.pluginSecretHandlerFunction).to(["read", "create", "update", "delete"])
483
- );
484
- } else {
485
- rules.push(allow.groups(["ampless-admin"]));
486
- }
487
- return rules;
488
- }),
483
+ }).identifier(["siteId", "sk"]).authorization((allow) => [
484
+ // Deny-all-via-AppSync sentinel. See the comment above this
485
+ // model for why this is a non-existent group name and how the
486
+ // real Lambda access path works (DDB SDK + IAM grants).
487
+ allow.groups(["__ampless_internal__"])
488
+ ]),
489
489
  // Existence-only indicator for PluginSecret rows.
490
490
  //
491
491
  // Admin/editor Cognito users cannot read from PluginSecret at all
@@ -508,22 +508,16 @@ function amplessSchemaModels(a, opts = {}) {
508
508
  // ISO 8601 datetime string — set by plugin-secret-handler on
509
509
  // every write. Admin UI may show this as "last updated" hint.
510
510
  lastSetAt: a.datetime().required()
511
- }).identifier(["siteId", "sk"]).authorization((allow) => {
512
- const rules = [
513
- // Admin/editor have AppSync read for `hasPluginSecret` and
514
- // direct write+delete as a fallback path (the Lambda is the
515
- // normal write path, but allowing admin write here keeps the
516
- // indicator and ciphertext aligned if a clear operation is
517
- // retried after a partial failure).
518
- allow.groups(["ampless-admin", "ampless-editor"])
519
- ];
520
- if (opts.pluginSecretHandlerFunction) {
521
- rules.push(
522
- allow.resource(opts.pluginSecretHandlerFunction).to(["read", "create", "update", "delete"])
523
- );
524
- }
525
- return rules;
526
- }),
511
+ }).identifier(["siteId", "sk"]).authorization((allow) => [
512
+ // Admin/editor have AppSync read for `hasPluginSecret` and
513
+ // direct write+delete as a recovery path. The Lambda is the
514
+ // normal write path (it calls the DDB SDK directly with IAM,
515
+ // not through AppSync same pattern as PluginSecret above),
516
+ // but allowing admin write here lets a clear-retry after a
517
+ // partial dual-write failure heal the inconsistency from the
518
+ // admin side without redeploying.
519
+ allow.groups(["ampless-admin", "ampless-editor"])
520
+ ]),
527
521
  // Custom return type for public post reads. Decoupling from `Post` lets
528
522
  // AppSync skip the model-level (admin-only) auth check on fields.
529
523
  //
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ampless/backend",
3
- "version": "1.0.0-alpha.48",
3
+ "version": "1.0.0-alpha.49",
4
4
  "description": "Amplify Gen 2 backend factories for ampless: auth, data, storage, event processors, API key renewer",
5
5
  "license": "MIT",
6
6
  "type": "module",