ampless 1.0.0-alpha.39 → 1.0.0-alpha.41

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.
@@ -13,6 +13,8 @@
13
13
 
14
14
  設計の経緯と背景は [`docs/architecture/08-plugin-architecture.md`](https://github.com/heavymoons/ampless/blob/main/docs/architecture/08-plugin-architecture.md) に集約。本ページはその実装ハンドブック側です。
15
15
 
16
+ > **ポジショニング**: ampless はエンジニア向けのカスタマイズベース CMS です — プラグインは**サイトエンジニアが `cms.config.ts` でインポート + 設定する npm dep** です。エンジニアは他の npm ライブラリと同様にインストール前に各 dep を審査します(Astro integration / Next.js plugin パターン)。このガイドで説明する trust framework(`trust_level`、capabilities、IAM スコープ付き Lambda)は v1 において**ファーストパーティプラグインの code organization**として実装されています — どの trust 階層の Lambda が各イベントフックを実行するか、各階層が保有する IAM 権限、そして狭い範囲のポイントでのみ runtime hard gate を適用する(最も重要: `settings.secret` は `trust_level: 'trusted'` を要求、シークレット読み取りに trusted Lambda の IAM 権限が必要なため)。ほとんどの capability 宣言は runtime の hard gate ではなく soft warning + admin ラベル + 将来の allow-list surface です。任意の未審査サードパーティ untrusted プラグインを自動的に安全に動かすための marketplace-grade automatic sandbox としては**設計されていません**。マーケットプレイス + ランタイムサンドボックスは v2.0+ の探索であり、v1 の保証ではありません。詳細な trust model は [`docs/architecture/08-plugin-architecture.md#trust-model-v1-scope`](https://github.com/heavymoons/ampless/blob/main/docs/architecture/08-plugin-architecture.md#trust-model-v1-scope) を参照してください。
17
+
16
18
  ---
17
19
 
18
20
  ## 0. テーマとプラグインの境界線
@@ -287,13 +289,15 @@ runtime がチェックする内容:
287
289
 
288
290
  ## 4. `trust_level` の選び方
289
291
 
292
+ trust 階層は v1 において**ファーストパーティプラグインの code organization**として実装されています — イベントフックがどの IAM スコープ付き Lambda で実行されるか、その Lambda が保有する権限を決定します。これはエンジニアが審査した npm dep 向けの code organization surface であり、任意のサードパーティ未審査プラグインを自動的に安全に動かすための marketplace-grade automatic sandbox ではありません(上記の[ポジショニング注記](#ampless-プラグインの書き方)と[詳細な trust model](https://github.com/heavymoons/ampless/blob/main/docs/architecture/08-plugin-architecture.md#trust-model-v1-scope) を参照)。
293
+
290
294
  3 階層、選択基準は **イベントフック (hooks) が何を必要とするか** で決まります (sync サーフェスは IAM に触れない):
291
295
 
292
296
  | 階層 | IAM | 今日動くもの | 用途 |
293
297
  |---|---|---|---|
294
298
  | `untrusted` | なし (SQS consume のみ) | 同期サーフェス + イベントフック | head/body descriptor、webhook 配送、コンテンツ変換 |
295
299
  | `trusted` | 投稿読み出し、`public/plugins/<instanceId ?? name>/...` への書き込み | 同期サーフェス + イベントフック | RSS フィード、sitemap、計算済み JSON インデックス |
296
- | `privileged` | 予約 | 同期サーフェスのみ — イベントフックはサイレントフィルタ(警告ログあり) | 将来: SES、secret、private S3 |
300
+ | `privileged` | 予約(v2.0+ 探索のみ) | 同期サーフェスのみ — イベントフックはサイレントフィルタ(警告ログあり) | 将来のマーケットプレイス探索: SES、secret、private S3 |
297
301
 
298
302
  > **`privileged` プラグイン作者へ:** `trust_level: 'privileged'` とイベント
299
303
  > `hooks` を宣言した場合、**現時点でフックは実行されません**。両 processor が
@@ -301,8 +305,10 @@ runtime がチェックする内容:
301
305
  > `console.warn` を出力するため、サイレントドロップは可視化されます。
302
306
  > 同期サーフェス(`publicHead`、`publicBodyEnd`、`metadata`、`publicBodyForPost`、
303
307
  > `publicHtmlForPost`)は `trust_level` に関わらず正常に動き、警告も出ません。
304
- > privileged Lambda が用意された際、`'privileged'` を宣言済みのプラグインは
305
- > 自動的に新しい tier を使えるようになります — コードの変更は不要です。
308
+ > privileged Lambda プロビジョニングは v2.0+ の探索項目です — ampless が
309
+ > プラグインマーケットプレイスを構築する場合、すでに `'privileged'` を宣言した
310
+ > プラグインは自動的に新しい tier を使えるようになります。
311
+ > v1 ファーストパーティプラグインは trusted Lambda の現行 IAM スコープに収まる用途で `trust_level: 'trusted'` を使ってください。すなわち Post / KvStore / PluginSecret / PostTag の読み取り、`public/plugins/*` への S3 書き込み、外向き HTTP (AWS IAM 認証を必要としないもの) です。このスコープ外の要件 — SES、private S3 プレフィックス、自前の IAM プリンシパルを必要とする AWS API 呼び出し — は v2.0+ privileged Lambda 探索の対象で、v1 `trusted` には収まりません。
306
312
 
307
313
  決め方の目安:
308
314
 
@@ -862,12 +868,18 @@ Secret settings を使うと、trusted プラグインが認証情報 (Webhook
862
868
  - 公開 render surface (`publicHead` など) からは読めない。
863
869
  - **field manifest 検証の範囲**: admin クライアントは UX フィードバック目的で `pattern` / `maxLength` / `required` を検証するが、Lambda 側は **汎用の 10,000 文字ハードキャップと安全文字サニタイザのみ**を強制する。admin/editor が AppSync mutation を直接呼ぶと field 単位の制約は迂回できる。設計上意図したもので、admin/editor は secret 設定を許可された信頼されたオペレータと位置づけている。manifest チェックは UX ガイダンスであり、セキュリティ境界ではない。
864
870
 
865
- ### 要件
871
+ ### 要件と `definePlugin()` の挙動
872
+
873
+ `settings.secret` は `definePlugin()` 時に 4 つの observable な挙動を持ちます(これは v1 のファーストパーティ organization のシークレットアクセス hard gate; [plugin.ts:1004-1019](https://github.com/heavymoons/ampless/blob/main/packages/ampless/src/plugin.ts#L1004-L1019) 参照):
866
874
 
867
- `settings.secret` には 3 つの要件があります:
875
+ 1. **`settings.secret` 非空 + `trust_level !== 'trusted'`** → `definePlugin()` が **throw**。untrusted と privileged Lambda は `PluginSecret` テーブルへの IAM read アクセスを持たない; trusted Lambda の IAM 権限が必要。
876
+ 2. **`settings.secret` 非空 + `capabilities` 宣言済み + `capabilities` に `'secretSettings'` が含まれない** → **soft 不一致 warning**。`'schema'` / `'publicHtmlForPost'` の既存 capability-mismatch パターンと同じ。
877
+ 3. **`settings.secret` 非空 + `capabilities` 未定義**(`capabilities` 配列を持たない legacy プラグイン)→ **warning なし**。`capabilities` が `undefined` のとき不一致チェックをスキップ、後方互換のため。
878
+ 4. **`capabilities: ['secretSettings']` 宣言だけで `settings.secret` フィールドなし** → **no-op**。warning も throw もなし。
868
879
 
869
- 1. `trust_level: 'trusted'` — untrusted Lambda には PluginSecret table への DDB read 権限がない。他の trust level で宣言すると `definePlugin()` 時に throw する。
870
- 2. `'secretSettings'` `capabilities` に含める — admin UI や将来の allow-list から capability を参照できるようにするため必須。省略すると console.warn(`'schema'` vs `publicBodyForPost` の不整合パターンと同じ)。
880
+ `settings.secret` を使うには以下も必要です:
881
+ 1. `trust_level: 'trusted'`(上記 #1 の要件; それ以外は `definePlugin()` throw)。
882
+ 2. `capabilities` に `'secretSettings'` を含める(`capabilities` が定義されているとき省略すると console.warn)。
871
883
  3. **鍵の初回セットアップ** — プロジェクトルートで実行:
872
884
  ```sh
873
885
  npx create-ampless setup-encryption-key
@@ -1234,7 +1246,7 @@ it('admin が空文字保存した場合は空配列', () => {
1234
1246
  - [`packages/plugin-plausible`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-plausible) — `data-*` attrs 付きの単一 `<script>` descriptor、`required` な URL field(self-hosted Plausible 上書き対応)
1235
1247
  - [`packages/plugin-rss`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-rss) — trusted、非同期 hooks + `writePublicAsset`
1236
1248
  - [`packages/plugin-seo`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-seo) — `metadata()` + `siteMetadata()`
1237
- - [`packages/plugin-webhook`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-webhook) — untrusted hook + 外向き HTTP
1249
+ - [`packages/plugin-webhook`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-webhook) — trusted hook + 外向き HTTP + `secretSettings` (admin 管理の signing secret、Phase 6a)
1238
1250
  - [`packages/plugin-og-image`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-og-image) — `ogImage` ルートレンダラ
1239
1251
  - [`packages/plugin-schema-jsonld`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-schema-jsonld) — `publicBodyForPost` + `schema` capability、投稿単位 Article JSON-LD。(Phase 4)
1240
1252
 
@@ -1340,4 +1352,4 @@ export default defineConfig({
1340
1352
  - ファーストパーティプラグインの bug → `heavymoons/ampless` にプラグインの package 名つきで issue
1341
1353
  - プラグインランタイム / admin form の bug → 同じレポ、ラベル `area:plugins`
1342
1354
 
1343
- ampless レポは v1.0 RC まで非公開なので、上記のリンクは現時点では package tarball 内の `node_modules/ampless/docs/` をローカルで見るための参照です。public 化後は実 GitHub URL に解決されます。
1355
+ ampless レポは現在 alpha 期間中は非公開です。beta に進む (npm `beta` dist-tag、リポジトリ公開) と上記のリンクが GitHub URL に解決されます。現状でも同じ docs が package tarball 内の `node_modules/ampless/docs/` に同梱されているので、GitHub にアクセスせずローカルで読めます。
@@ -19,6 +19,8 @@ per-post body injection, the async event hooks, and admin-managed
19
19
  The design rationale is in [`docs/architecture/08-plugin-architecture.md`](https://github.com/heavymoons/ampless/blob/main/docs/architecture/08-plugin-architecture.md);
20
20
  this page is the hands-on companion.
21
21
 
22
+ > **Positioning**: ampless is a customization-based CMS for engineers — plugins are **npm dependencies that the site engineer imports + configures in `cms.config.ts`**. The engineer audits each dep before installing, the way they would for any other npm library (Astro integration / Next.js plugin pattern). The trust framework described in this guide (`trust_level`, capabilities, IAM-scoped Lambdas) is implemented in v1 as **first-party plugin organization** — it decides which trust tier's Lambda runs each event hook, which IAM permissions each tier holds, and applies hard runtime gates only at narrowly-scoped points (most notably: `settings.secret` requires `trust_level: 'trusted'` because secret read needs the trusted Lambda's IAM permission). Most capability declarations are soft warnings + admin labels + future allow-list surfaces, not hard runtime gates. It is **not** designed as a marketplace-grade automatic sandbox that safely runs arbitrary untrusted third-party plugins. Marketplace + runtime sandbox is a v2.0+ exploration, not a v1 guarantee. See [`docs/architecture/08-plugin-architecture.md#trust-model-v1-scope`](https://github.com/heavymoons/ampless/blob/main/docs/architecture/08-plugin-architecture.md#trust-model-v1-scope) for the full trust model.
23
+
22
24
  ---
23
25
 
24
26
  ## 0. Theme vs Plugin Boundary
@@ -358,6 +360,8 @@ not a runtime block.
358
360
 
359
361
  ## 4. Picking a `trust_level`
360
362
 
363
+ The trust tiers are implemented in v1 as **first-party plugin organization** — they decide which IAM-scoped Lambda runs your event hooks and which permissions that Lambda holds. This is a code organization surface for engineer-audited npm deps, not a marketplace-grade automatic sandbox for arbitrary third-party untrusted plugins (see the [Positioning note](#writing-an-ampless-plugin) above and the [full trust model](https://github.com/heavymoons/ampless/blob/main/docs/architecture/08-plugin-architecture.md#trust-model-v1-scope)).
364
+
361
365
  Three tiers, picked by what the plugin needs to do **inside
362
366
  event hooks** (the sync surfaces — metadata, head, body — don't
363
367
  touch IAM):
@@ -366,7 +370,7 @@ touch IAM):
366
370
  |---|---|---|---|
367
371
  | `untrusted` | none (SQS consume only) | sync surfaces + event hooks | head/body descriptors, webhook delivery, content transforms |
368
372
  | `trusted` | read posts, write `public/plugins/<instanceId ?? name>/...` | sync surfaces + event hooks | RSS feed, sitemap, computed JSON indexes |
369
- | `privileged` | reserved | sync surfaces only — event hooks are silently filtered out (warning logged) | future: SES, secrets, private S3 |
373
+ | `privileged` | reserved (v2.0+ exploration only) | sync surfaces only — event hooks are silently filtered out (warning logged) | future marketplace exploration: SES, secrets, private S3 |
370
374
 
371
375
  > **Warning for `privileged` plugin authors:** If you declare
372
376
  > `trust_level: 'privileged'` with event `hooks` today, **your hooks
@@ -375,9 +379,10 @@ touch IAM):
375
379
  > the drop is visible. Sync render surfaces (`publicHead`,
376
380
  > `publicBodyEnd`, `metadata`, `publicBodyForPost`, `publicHtmlForPost`)
377
381
  > work normally regardless of `trust_level` and emit no warning.
378
- > When the privileged Lambda provisioning PR lands, plugins that
379
- > already declared `'privileged'` will automatically pick up the new
380
- > tier nothing needs to change in your code.
382
+ > `privileged` Lambda provisioning is a v2.0+ exploration item — if
383
+ > AmpLess later builds a plugin marketplace, that PR will automatically
384
+ > pick up plugins that already declared `'privileged'`.
385
+ > v1 first-party plugins should use `trust_level: 'trusted'` for capabilities that fit within the trusted Lambda's existing IAM scope: Post / KvStore / PluginSecret / PostTag read, `public/plugins/*` S3 write, and outbound HTTP (no AWS-IAM-authenticated calls). Requirements that fall outside that scope — SES, private S3 prefixes, calling AWS APIs that need an IAM principal of their own — are v2.0+ privileged-Lambda exploration material and don't fit into v1 `trusted`.
381
386
 
382
387
  Rule of thumb:
383
388
 
@@ -1150,16 +1155,18 @@ etc. — but completely wrong for a webhook signing secret.
1150
1155
  (`publicHead`, `publicBodyEnd`, `publicBodyForPost`,
1151
1156
  `publicHtmlForPost`) — those surfaces only see `ctx.setting()`.
1152
1157
 
1153
- ### Requirements
1158
+ ### Requirements and `definePlugin()` behaviour
1159
+
1160
+ `settings.secret` has four observable behaviours at `definePlugin()` time (this is the v1 first-party organization hard gate for secret access; see [plugin.ts:1004-1019](https://github.com/heavymoons/ampless/blob/main/packages/ampless/src/plugin.ts#L1004-L1019)):
1154
1161
 
1155
- `settings.secret` requires:
1162
+ 1. **`settings.secret` non-empty + `trust_level !== 'trusted'`** → `definePlugin()` **throws**. Untrusted and privileged Lambdas have no IAM read access to the `PluginSecret` table; the trusted Lambda's IAM permission is required.
1163
+ 2. **`settings.secret` non-empty + `capabilities` declared + `'secretSettings'` missing from `capabilities`** → **soft mismatch warning**. Matches the existing capability-mismatch pattern for `'schema'` / `'publicHtmlForPost'`.
1164
+ 3. **`settings.secret` non-empty + `capabilities` undefined** (legacy plugin without a `capabilities` array) → **no warning**. The mismatch check is skipped when `capabilities` is `undefined`, for backward compatibility.
1165
+ 4. **`capabilities: ['secretSettings']` declared with no `settings.secret` field** → **no-op**. Neither warning nor throw.
1156
1166
 
1157
- 1. `trust_level: 'trusted'` untrusted Lambdas have no DDB read
1158
- access to the PluginSecret table. `definePlugin()` throws if you
1159
- declare `settings.secret` with any other trust level.
1160
- 2. `'secretSettings'` in `capabilities` — required so admin UI and
1161
- future allow-lists can gate the capability. Omitting it produces
1162
- a console warning (same pattern as `'schema'` vs `publicBodyForPost`).
1167
+ To use `settings.secret`, you also need:
1168
+ 1. `trust_level: 'trusted'` (requirement #1 above; `definePlugin()` throws otherwise).
1169
+ 2. `'secretSettings'` in `capabilities` (omitting it when `capabilities` is defined produces a console warning).
1163
1170
  3. **One-time key setup** — run from your project root:
1164
1171
  ```sh
1165
1172
  npx create-ampless setup-encryption-key
@@ -1676,7 +1683,7 @@ Worked examples to crib from:
1676
1683
  - [`packages/plugin-plausible`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-plausible) — single `<script>` descriptor with `data-*` attrs and a required URL field (self-hosted Plausible override).
1677
1684
  - [`packages/plugin-rss`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-rss) — trusted, async event hooks + `writePublicAsset`.
1678
1685
  - [`packages/plugin-seo`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-seo) — `metadata()` + `siteMetadata()`.
1679
- - [`packages/plugin-webhook`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-webhook) — untrusted hook with outbound HTTP.
1686
+ - [`packages/plugin-webhook`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-webhook) — trusted hook with outbound HTTP + `secretSettings` (admin-managed signing secret, Phase 6a).
1680
1687
  - [`packages/plugin-og-image`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-og-image) — `ogImage` route renderer.
1681
1688
  - [`packages/plugin-schema-jsonld`](https://github.com/heavymoons/ampless/tree/main/packages/plugin-schema-jsonld) — `publicBodyForPost` + `schema` capability; per-post Article JSON-LD. (Phase 4)
1682
1689
 
@@ -1826,6 +1833,8 @@ PROTECTED), so the scaffolded code is safe across ampless upgrades.
1826
1833
  - Bugs in the plugin runtime / admin form → same repo, label
1827
1834
  `area:plugins`.
1828
1835
 
1829
- The ampless repo stays private until v1.0 RC. Once it's public, the
1830
- links above resolve to the actual GitHub URLs; today they live in
1831
- the package tarball directly under `node_modules/ampless/docs/`.
1836
+ The ampless repo is currently private during the alpha stage; the
1837
+ GitHub URLs above start resolving once beta ships (npm `beta`
1838
+ dist-tag, repo flips public). Today the same docs also live in the
1839
+ package tarball directly under `node_modules/ampless/docs/`, so
1840
+ you can read them locally without browsing GitHub.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ampless",
3
- "version": "1.0.0-alpha.39",
3
+ "version": "1.0.0-alpha.41",
4
4
  "description": "Serverless CMS for AWS Amplify",
5
5
  "license": "MIT",
6
6
  "type": "module",