@aotter/mantle 0.1.5-alpha.1 → 0.2.0-alpha.10
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/README.md +166 -298
- package/dist/auth/adapter.d.ts +32 -0
- package/dist/auth/adapter.js +288 -0
- package/dist/auth/admin.d.ts +3 -0
- package/dist/auth/admin.js +21 -0
- package/dist/auth/caller.d.ts +86 -0
- package/dist/auth/caller.js +155 -0
- package/dist/auth/hardening.d.ts +24 -0
- package/dist/auth/hardening.js +40 -0
- package/dist/auth/identity.d.ts +121 -0
- package/dist/auth/identity.js +203 -0
- package/dist/auth/oauth.d.ts +63 -0
- package/dist/auth/oauth.js +217 -0
- package/dist/auth/resource-seeds.js +10 -0
- package/dist/auth/routes.d.ts +32 -0
- package/dist/auth/routes.js +226 -0
- package/dist/build/compiler.d.ts +721 -0
- package/dist/build/compiler.js +7029 -0
- package/dist/build/spec/domain/model/ManifestGrammar.d.ts +439 -0
- package/dist/build/spec/domain/model/RuntimePlan.d.ts +168 -0
- package/dist/build/spec/domain/model/SqlIr.d.ts +129 -0
- package/dist/build/spec/domain/model/UserFields.d.ts +21 -0
- package/dist/build/spec/domain/service/PlanFingerprint.d.ts +7 -0
- package/dist/build/spec/kernel/diagnostic.d.ts +108 -0
- package/dist/bun/assets.d.ts +2 -0
- package/dist/bun/assets.js +24 -0
- package/dist/domain/adminOrder.js +24 -0
- package/dist/domain/columns.js +57 -0
- package/dist/domain/describe/chunk-ZVXBGP7Y.js +424 -0
- package/dist/domain/describe/index.d.ts +58 -0
- package/dist/domain/describe/index.js +115 -0
- package/dist/domain/describe/target-hash.d.ts +8 -0
- package/dist/domain/describe/target-hash.js +12 -0
- package/dist/domain/describe/targets.d.ts +40 -0
- package/dist/domain/entry.js +33 -0
- package/dist/domain/generated-tools.js +19 -0
- package/dist/domain/generation.d.ts +16 -0
- package/dist/domain/generation.js +1 -0
- package/dist/domain/input.js +17 -0
- package/dist/domain/model.js +1 -0
- package/dist/domain/paging.js +230 -0
- package/dist/domain/recipes.js +24 -0
- package/dist/domain/userReferences.js +5 -0
- package/dist/domain/wireScalars.js +47 -0
- package/dist/infrastructure/adminEntries.js +153 -0
- package/dist/infrastructure/adminPaging.js +72 -0
- package/dist/infrastructure/artifacts.js +71 -0
- package/dist/infrastructure/authSchema.js +83 -0
- package/dist/infrastructure/bundle.js +188 -0
- package/dist/infrastructure/cli.js +118 -0
- package/dist/infrastructure/generate.d.ts +12 -0
- package/dist/infrastructure/generate.js +189 -0
- package/dist/infrastructure/generateAuth.d.ts +8 -0
- package/dist/infrastructure/generateAuth.js +74 -0
- package/dist/infrastructure/help.js +60 -0
- package/dist/infrastructure/init.js +54 -0
- package/dist/infrastructure/inputs.js +41 -0
- package/dist/infrastructure/mounts.js +25 -0
- package/dist/infrastructure/wrangler.js +109 -0
- package/dist/kernel/authorization.d.ts +4 -0
- package/dist/kernel/authorization.js +16 -0
- package/dist/kernel/binds.d.ts +60 -0
- package/dist/kernel/binds.js +49 -0
- package/dist/kernel/caller-identity.d.ts +24 -0
- package/dist/kernel/caller-identity.js +22 -0
- package/dist/kernel/contract-error.d.ts +12 -0
- package/dist/kernel/contract-error.js +14 -0
- package/dist/kernel/contracts.d.ts +143 -0
- package/dist/kernel/contracts.js +97 -0
- package/dist/kernel/cron.d.ts +1 -0
- package/dist/kernel/cron.js +58 -0
- package/dist/kernel/dialect/common.d.ts +38 -0
- package/dist/kernel/dialect/common.js +6 -0
- package/dist/kernel/dialect/postgres.d.ts +16 -0
- package/dist/kernel/dialect/postgres.js +18 -0
- package/dist/kernel/dialect/sqlite.d.ts +20 -0
- package/dist/kernel/dialect/sqlite.js +34 -0
- package/dist/kernel/drain.d.ts +5 -0
- package/dist/kernel/drain.js +35 -0
- package/dist/kernel/driver/bun-sqlite.d.ts +19 -0
- package/dist/kernel/driver/bun-sqlite.js +77 -0
- package/dist/kernel/driver/d1.d.ts +24 -0
- package/dist/kernel/driver/d1.js +22 -0
- package/dist/kernel/driver/postgres.d.ts +25 -0
- package/dist/kernel/driver/postgres.js +99 -0
- package/dist/kernel/driver/transaction-context.d.ts +10 -0
- package/dist/kernel/driver/transaction-context.js +29 -0
- package/dist/kernel/email.d.ts +28 -0
- package/dist/kernel/email.js +38 -0
- package/dist/kernel/host-access.d.ts +10 -0
- package/dist/kernel/host-access.js +65 -0
- package/dist/kernel/host-caller.d.ts +39 -0
- package/dist/kernel/host-caller.js +56 -0
- package/dist/kernel/json-body.d.ts +4 -0
- package/dist/kernel/json-body.js +44 -0
- package/dist/kernel/mcp-apps.d.ts +69 -0
- package/dist/kernel/mcp-apps.js +40 -0
- package/dist/kernel/mcp-call.d.ts +5 -0
- package/dist/kernel/mcp-call.js +25 -0
- package/dist/kernel/mcp-handler.js +371 -0
- package/dist/kernel/mcp.d.ts +110 -0
- package/dist/kernel/mcp.js +50 -0
- package/dist/kernel/media.d.ts +27 -0
- package/dist/kernel/media.js +216 -0
- package/dist/kernel/paging.d.ts +55 -0
- package/dist/kernel/paging.js +95 -0
- package/dist/kernel/publishing.d.ts +4 -0
- package/dist/kernel/publishing.js +16 -0
- package/dist/kernel/r2-media.d.ts +42 -0
- package/dist/kernel/r2-media.js +78 -0
- package/dist/kernel/rest-dispatch.js +38 -0
- package/dist/kernel/rest-router.js +64 -0
- package/dist/kernel/rest.d.ts +58 -0
- package/dist/kernel/rest.js +41 -0
- package/dist/kernel/scalars.d.ts +6 -0
- package/dist/kernel/scalars.js +44 -0
- package/dist/kernel/search.js +5 -0
- package/dist/kernel/site-types.d.ts +146 -0
- package/dist/kernel/site-types.js +1 -0
- package/dist/kernel/site.d.ts +39 -0
- package/dist/kernel/site.js +32 -0
- package/dist/kernel/store.d.ts +175 -0
- package/dist/kernel/store.js +269 -0
- package/dist/kernel/surface.d.ts +10 -0
- package/dist/kernel/surface.js +19 -0
- package/dist/kernel/sweep.d.ts +17 -0
- package/dist/kernel/sweep.js +27 -0
- package/dist/kernel/translations.d.ts +1 -0
- package/dist/kernel/translations.js +13 -0
- package/dist/kernel/user-caller.d.ts +31 -0
- package/dist/kernel/user-caller.js +67 -0
- package/dist/kernel/user-field-name.js +3 -0
- package/dist/kernel/user-fields.d.ts +35 -0
- package/dist/kernel/user-fields.js +81 -0
- package/dist/kernel/validation.d.ts +15 -0
- package/dist/kernel/validation.js +54 -0
- package/dist/kernel/web-gateway.js +68 -0
- package/dist/kernel/web-head.js +15 -0
- package/dist/kernel/web-index.js +40 -0
- package/dist/kernel/web-response.js +8 -0
- package/dist/kernel/web.d.ts +77 -0
- package/dist/kernel/web.js +124 -0
- package/dist/kernel/where.js +27 -0
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.js +1 -0
- package/dist/usecase/adminBindings.js +143 -0
- package/dist/usecase/adminClient.js +87 -0
- package/dist/usecase/adminDescriptors.js +107 -0
- package/dist/usecase/generate.js +166 -0
- package/dist/usecase/handlers.js +21 -0
- package/dist/usecase/mcp-media.js +17 -0
- package/dist/usecase/mcp.js +100 -0
- package/dist/usecase/paging.js +71 -0
- package/dist/usecase/publishing.js +63 -0
- package/dist/usecase/refusals.js +27 -0
- package/dist/usecase/rest.js +54 -0
- package/dist/usecase/search.js +7 -0
- package/dist/usecase/site.js +39 -0
- package/dist/usecase/stores.js +64 -0
- package/dist/usecase/tool-version.js +9 -0
- package/dist/usecase/translations.js +78 -0
- package/dist/usecase/ttl.js +20 -0
- package/dist/usecase/validation.js +241 -0
- package/dist/usecase/web.js +23 -0
- package/docs/examples/README.md +39 -18
- package/docs/examples/app-shell/.dev.vars.example +4 -0
- package/docs/examples/app-shell/README.md +121 -0
- package/docs/examples/app-shell/accept.mjs +91 -0
- package/docs/examples/app-shell/gitignore +7 -0
- package/docs/examples/app-shell/package.json +43 -0
- package/docs/examples/app-shell/pnpm-workspace.yaml +8 -0
- package/docs/examples/app-shell/smoke-kit.mjs +168 -0
- package/docs/examples/app-shell/src/auth.ts +58 -0
- package/docs/examples/app-shell/src/handlers.ts +5 -0
- package/docs/examples/app-shell/src/index.ts +4 -0
- package/docs/examples/app-shell/src/routes.ts +14 -0
- package/docs/examples/app-shell/src/schedule.ts +8 -0
- package/docs/examples/app-shell/src/service.ts +70 -0
- package/docs/examples/app-shell/src/sign-in.ts +41 -0
- package/docs/examples/app-shell/src/signup.ts +8 -0
- package/docs/examples/app-shell/tsconfig.json +26 -0
- package/docs/examples/app-shell/worker-configuration.d.ts +22 -0
- package/docs/examples/app-shell/wrangler.jsonc +62 -0
- package/docs/examples/club-events/README.md +65 -0
- package/docs/examples/club-events/manifests/club-events.yaml +247 -0
- package/docs/examples/club-events/smoke.mjs +127 -0
- package/docs/examples/club-events/src/handlers.ts +25 -0
- package/docs/examples/club-events/src/signup.ts +9 -0
- package/docs/examples/generated-web/README.md +78 -0
- package/docs/examples/generated-web/posts.yaml +38 -0
- package/docs/examples/generated-web/seed.sql +6 -0
- package/docs/examples/generated-web/src/worker.ts +43 -0
- package/docs/examples/generated-web/tsconfig.json +8 -0
- package/docs/examples/generated-web/wrangler.jsonc +8 -0
- package/docs/examples/purchasing/.dev.vars.example +6 -0
- package/docs/examples/purchasing/README.md +99 -0
- package/docs/examples/purchasing/manifests/purchasing.yaml +374 -0
- package/docs/examples/purchasing/seed.sql +4 -0
- package/docs/examples/purchasing/smoke.mjs +191 -0
- package/docs/examples/purchasing/src/admin.tsx +13 -0
- package/docs/examples/purchasing/src/handlers.ts +33 -0
- package/docs/examples/purchasing/src/notify.ts +29 -0
- package/docs/examples/purchasing/src/requests-page.ts +57 -0
- package/docs/examples/purchasing/src/routes.ts +53 -0
- package/docs/examples/purchasing/src/schedule.ts +31 -0
- package/docs/examples/purchasing/src/signup.ts +5 -0
- package/docs/examples/purchasing/src/supplier.ts +32 -0
- package/docs/examples/purchasing/wrangler.jsonc +69 -0
- package/docs/examples/recipes/README.md +60 -0
- package/docs/examples/recipes/manifests/recipes.yaml +75 -0
- package/docs/examples/recipes/smoke.mjs +102 -0
- package/docs/examples/recipes/src/media.ts +13 -0
- package/docs/examples/recipes/src/pages.ts +99 -0
- package/docs/examples/recipes/src/routes.ts +71 -0
- package/docs/examples/recipes/src/site-config.ts +12 -0
- package/docs/examples/recipes/wrangler.jsonc +74 -0
- package/docs/handbook/cloudflare/authentication.md +180 -322
- package/docs/handbook/cloudflare/chatgpt-sites.md +5 -23
- package/docs/handbook/cloudflare/deploy-and-operate.md +55 -77
- package/docs/handbook/cloudflare/media-r2.md +61 -205
- package/docs/handbook/cloudflare/service-entry.md +239 -0
- package/docs/handbook/concepts/authorization.md +10 -107
- package/docs/handbook/concepts/four-atoms.md +9 -168
- package/docs/handbook/concepts/lifecycle-and-locales.md +9 -132
- package/docs/handbook/concepts/mcp-and-agents.md +24 -121
- package/docs/handbook/concepts/procedures-and-triggers.md +5 -217
- package/docs/handbook/concepts/runtime-and-adapters.md +15 -169
- package/docs/handbook/concepts/views.md +10 -185
- package/docs/handbook/examples/hub.md +3 -8
- package/docs/handbook/guides/adapter-guide.md +11 -0
- package/docs/handbook/guides/admin-ui.md +115 -133
- package/docs/handbook/guides/agent-setup.md +64 -74
- package/docs/handbook/guides/agent-workflow-acceptance.md +232 -0
- package/docs/handbook/guides/email.md +86 -0
- package/docs/handbook/guides/local-testing.md +40 -0
- package/docs/handbook/guides/mcp-apps.md +560 -0
- package/docs/handbook/guides/native-admin.md +566 -0
- package/docs/handbook/guides/native-execution.md +133 -0
- package/docs/handbook/guides/oauth.md +219 -0
- package/docs/handbook/guides/postgres-adapters.md +56 -0
- package/docs/handbook/guides/public-pages.md +87 -0
- package/docs/handbook/guides/size-and-startup.md +9 -0
- package/docs/handbook/guides/sql-patterns.md +266 -0
- package/docs/handbook/guides/typed-queries.md +211 -107
- package/docs/handbook/navigation.json +176 -55
- package/docs/handbook/reference/admin-descriptors.md +53 -0
- package/docs/handbook/reference/authorization.md +39 -266
- package/docs/handbook/reference/describe.md +56 -0
- package/docs/handbook/reference/diagnostics.md +19 -186
- package/docs/handbook/reference/features.md +45 -55
- package/docs/handbook/reference/manifest.md +6 -129
- package/docs/handbook/reference/procedure.md +11 -303
- package/docs/handbook/reference/schema.md +64 -240
- package/docs/handbook/reference/site-config.md +5 -218
- package/docs/handbook/reference/sql.md +64 -0
- package/docs/handbook/reference/surface.md +392 -201
- package/docs/handbook/reference/trigger.md +56 -192
- package/docs/handbook/reference/view.md +24 -243
- package/docs/handbook/releases/index.md +244 -77
- package/docs/handbook/start/agents.md +45 -0
- package/docs/handbook/start/overview.md +9 -48
- package/docs/handbook/start/project-and-cli.md +51 -104
- package/docs/handbook/start/quickstart-worker.md +43 -178
- package/docs/skills/develop/SKILL.md +79 -249
- package/docs/skills/integrate/SKILL.md +39 -50
- package/docs/skills/media-gc/SKILL.md +34 -10
- package/docs/skills/provision/SKILL.md +36 -186
- package/docs/skills/update/SKILL.md +23 -38
- package/docs/source/scripts/postgres-adapter.ts +101 -0
- package/docs/upgrade-0.1-to-0.2.md +227 -0
- package/package.json +120 -131
- package/skills/README.md +48 -108
- package/skills/mantle/SKILL.md +76 -0
- package/dist/admin-ui.d.ts +0 -2
- package/dist/admin-ui.d.ts.map +0 -1
- package/dist/admin-ui.js +0 -2
- package/dist/admin-ui.js.map +0 -1
- package/dist/admin.d.ts +0 -2
- package/dist/admin.d.ts.map +0 -1
- package/dist/admin.js +0 -2
- package/dist/admin.js.map +0 -1
- package/dist/auth.d.ts +0 -2
- package/dist/auth.d.ts.map +0 -1
- package/dist/auth.js +0 -2
- package/dist/auth.js.map +0 -1
- package/dist/bun.d.ts +0 -2
- package/dist/bun.d.ts.map +0 -1
- package/dist/bun.js +0 -2
- package/dist/bun.js.map +0 -1
- package/dist/cli/generate-cloudflare.d.ts +0 -7
- package/dist/cli/generate-cloudflare.d.ts.map +0 -1
- package/dist/cli/generate-cloudflare.js +0 -123
- package/dist/cli/generate-cloudflare.js.map +0 -1
- package/dist/cli/generate-project.d.ts +0 -25
- package/dist/cli/generate-project.d.ts.map +0 -1
- package/dist/cli/generate-project.js +0 -282
- package/dist/cli/generate-project.js.map +0 -1
- package/dist/cli/generate-sites.d.ts +0 -8
- package/dist/cli/generate-sites.d.ts.map +0 -1
- package/dist/cli/generate-sites.js +0 -273
- package/dist/cli/generate-sites.js.map +0 -1
- package/dist/cli/generate.d.ts +0 -20
- package/dist/cli/generate.d.ts.map +0 -1
- package/dist/cli/generate.js +0 -299
- package/dist/cli/generate.js.map +0 -1
- package/dist/cli/harness.d.ts +0 -3
- package/dist/cli/harness.d.ts.map +0 -1
- package/dist/cli/harness.js +0 -214
- package/dist/cli/harness.js.map +0 -1
- package/dist/cli/main.d.ts +0 -3
- package/dist/cli/main.d.ts.map +0 -1
- package/dist/cli/main.js +0 -77
- package/dist/cli/main.js.map +0 -1
- package/dist/cli/skills.d.ts +0 -3
- package/dist/cli/skills.d.ts.map +0 -1
- package/dist/cli/skills.js +0 -128
- package/dist/cli/skills.js.map +0 -1
- package/dist/cloudflare.d.ts +0 -2
- package/dist/cloudflare.d.ts.map +0 -1
- package/dist/cloudflare.js +0 -2
- package/dist/cloudflare.js.map +0 -1
- package/dist/codegen/emitMantleModule.d.ts +0 -22
- package/dist/codegen/emitMantleModule.d.ts.map +0 -1
- package/dist/codegen/emitMantleModule.js +0 -291
- package/dist/codegen/emitMantleModule.js.map +0 -1
- package/dist/codegen.d.ts +0 -2
- package/dist/codegen.d.ts.map +0 -1
- package/dist/codegen.js +0 -2
- package/dist/codegen.js.map +0 -1
- package/dist/runtime-testing.d.ts +0 -2
- package/dist/runtime-testing.d.ts.map +0 -1
- package/dist/runtime-testing.js +0 -2
- package/dist/runtime-testing.js.map +0 -1
- package/dist/runtime.d.ts +0 -2
- package/dist/runtime.d.ts.map +0 -1
- package/dist/runtime.js +0 -2
- package/dist/runtime.js.map +0 -1
- package/dist/spec.d.ts +0 -2
- package/dist/spec.d.ts.map +0 -1
- package/dist/spec.js +0 -2
- package/dist/spec.js.map +0 -1
- package/dist/vercel-libsql.d.ts +0 -2
- package/dist/vercel-libsql.d.ts.map +0 -1
- package/dist/vercel-libsql.js +0 -2
- package/dist/vercel-libsql.js.map +0 -1
- package/dist/vercel.d.ts +0 -2
- package/dist/vercel.d.ts.map +0 -1
- package/dist/vercel.js +0 -2
- package/dist/vercel.js.map +0 -1
- package/dist/web.d.ts +0 -2
- package/dist/web.d.ts.map +0 -1
- package/dist/web.js +0 -2
- package/dist/web.js.map +0 -1
- package/docs/adapter-guide.md +0 -222
- package/docs/adr/0001-four-atom-manifest-model.md +0 -440
- package/docs/adr/0002-closed-enums-for-bindings.md +0 -253
- package/docs/adr/0007-ai-as-primary-author.md +0 -473
- package/docs/adr/0008-structured-diagnostic-shape.md +0 -338
- package/docs/adr/0009-consumer-supplied-manifests.md +0 -149
- package/docs/adr/0010-locale-and-translates.md +0 -453
- package/docs/adr/0011-adapter-port-spec.md +0 -281
- package/docs/adr/0012-views-as-public-rest.md +0 -161
- package/docs/adr/0013-agent-provisioned-consumer-projects.md +0 -154
- package/docs/adr/0014-auth-better-auth-and-multi-tenant-mcp.md +0 -900
- package/docs/adr/0016-site-semantic-layer.md +0 -70
- package/docs/adr/0017-media-multi-variant-agent-side-optimization.md +0 -181
- package/docs/adr/0018-core-starters-repository-boundary.md +0 -179
- package/docs/adr/0019-sealed-manifest-runtime-pipeline.md +0 -240
- package/docs/adr/0020-builtin-handler-contracts-and-matched-upsert.md +0 -199
- package/docs/adr/0021-retire-starter-scaffolding.md +0 -30
- package/docs/adr/0022-caller-observed-version-occ.md +0 -212
- package/docs/adr/0023-port-failure-contract.md +0 -69
- package/docs/adr/0024-manifest-native-schema-tables.md +0 -264
- package/docs/adr/0025-reserved-native-columns-and-published-only-public-views.md +0 -105
- package/docs/adr/0026-progressive-generate.md +0 -36
- package/docs/adr/0027-scheduled-procedure-triggers.md +0 -31
- package/docs/adr/0028-schema-ttl-expiry.md +0 -33
- package/docs/adr/README.md +0 -81
- package/docs/adr/adr-lite-803-request-diagnostics.md +0 -38
- package/docs/adr/adr-lite-808-route-readiness.md +0 -47
- package/docs/adr/adr-lite-809-bounded-public-content.md +0 -71
- package/docs/adr/adr-lite-812-native-parity.md +0 -150
- package/docs/adr/adr-lite-823-home-statistics.md +0 -64
- package/docs/adr/adr-lite-842-mcp-authoring.md +0 -30
- package/docs/adr/adr-lite-845-frontend-client.md +0 -38
- package/docs/adr/adr-lite-861-admin-webmcp.md +0 -42
- package/docs/adr/adr-lite-909-admin-ui-kit.md +0 -37
- package/docs/agent-prompts.md +0 -64
- package/docs/api-mcp-authorization.md +0 -5
- package/docs/assets/mantle-admin-developer.png +0 -0
- package/docs/assets/mantle-admin-operations.png +0 -0
- package/docs/assets/mantle-hero.jpg +0 -0
- package/docs/auth-hosting-model.md +0 -166
- package/docs/cloudflare-low-level-composition.md +0 -5
- package/docs/consumer-onboarding-audit.md +0 -65
- package/docs/deferred-lifecycle-queues.md +0 -5
- package/docs/design-atoms.md +0 -16
- package/docs/design-references/editorial-blog-2026-05-05.md +0 -218
- package/docs/direct-authoring.md +0 -5
- package/docs/examples/builtin-commerce.md +0 -269
- package/docs/examples/builtin-intake.md +0 -143
- package/docs/examples/builtin-legal-documents.md +0 -189
- package/docs/examples/builtin-procurement.md +0 -241
- package/docs/examples/builtin-publication.md +0 -241
- package/docs/examples/builtin-reservation.md +0 -149
- package/docs/examples/cf-primitives-commerce-inventory.md +0 -809
- package/docs/examples/cf-primitives-guarded-api.md +0 -429
- package/docs/examples/cf-primitives-intake-hooks.md +0 -319
- package/docs/examples/host-chatgpt-sites/.openai/hosting.json +0 -1
- package/docs/examples/host-chatgpt-sites/README.md +0 -70
- package/docs/examples/host-chatgpt-sites/drizzle/0000_sites_users.sql +0 -8
- package/docs/examples/host-chatgpt-sites/drizzle/0001_mantle.sql +0 -294
- package/docs/examples/host-chatgpt-sites/drizzle/0002_article_cover.sql +0 -5
- package/docs/examples/host-chatgpt-sites/drizzle/0003_store_instance_id.sql +0 -1
- package/docs/examples/host-chatgpt-sites/drizzle/0004_mantle.sql +0 -10
- package/docs/examples/host-chatgpt-sites/drizzle/0005_mantle.sql +0 -24
- package/docs/examples/host-chatgpt-sites/drizzle/meta/_journal.json +0 -1
- package/docs/examples/host-chatgpt-sites/drizzle/meta/mantle-state.json +0 -60
- package/docs/examples/host-chatgpt-sites/manifests/site.yaml +0 -27
- package/docs/examples/host-chatgpt-sites/package.json +0 -1
- package/docs/examples/host-chatgpt-sites/public/site.css +0 -1
- package/docs/examples/host-chatgpt-sites/scripts/build.mjs +0 -13
- package/docs/examples/host-chatgpt-sites/scripts/check.mjs +0 -101
- package/docs/examples/host-chatgpt-sites/scripts/migration.mjs +0 -43
- package/docs/examples/host-chatgpt-sites/src/chatgpt-auth.ts +0 -66
- package/docs/examples/host-chatgpt-sites/src/index.ts +0 -46
- package/docs/examples/host-chatgpt-sites/src/mcp.ts +0 -49
- package/docs/examples/host-chatgpt-sites/src/media.ts +0 -109
- package/docs/examples/host-chatgpt-sites/src/r2-lab.ts +0 -38
- package/docs/examples/host-chatgpt-sites/src/storage-fingerprint.json +0 -1
- package/docs/examples/host-chatgpt-sites/src/web.ts +0 -35
- package/docs/examples/host-chatgpt-sites/tsconfig.json +0 -1
- package/docs/examples/host-chatgpt-sites/wrangler.jsonc +0 -10
- package/docs/examples/host-local-admin-otp/.dev.vars.example +0 -3
- package/docs/examples/host-local-admin-otp/README.md +0 -80
- package/docs/examples/host-local-admin-otp/ensure-dev-vars.mjs +0 -5
- package/docs/examples/host-local-admin-otp/manifests/site.yaml +0 -25
- package/docs/examples/host-local-admin-otp/package.json +0 -29
- package/docs/examples/host-local-admin-otp/public/.gitkeep +0 -1
- package/docs/examples/host-local-admin-otp/smoke.mjs +0 -141
- package/docs/examples/host-local-admin-otp/src/index.ts +0 -54
- package/docs/examples/host-local-admin-otp/tsconfig.json +0 -17
- package/docs/examples/host-local-admin-otp/wrangler.jsonc +0 -23
- package/docs/examples/host-minimal-worker/README.md +0 -41
- package/docs/examples/host-minimal-worker/manifests/site.yaml +0 -25
- package/docs/examples/host-minimal-worker/package.json +0 -26
- package/docs/examples/host-minimal-worker/smoke.mjs +0 -23
- package/docs/examples/host-minimal-worker/src/index.ts +0 -4
- package/docs/examples/host-minimal-worker/tsconfig.json +0 -17
- package/docs/examples/host-minimal-worker/wrangler.jsonc +0 -22
- package/docs/handbook/chatgpt-sites/equipment-checkout.md +0 -231
- package/docs/handbook/chatgpt-sites/generated-app.md +0 -84
- package/docs/handbook/chatgpt-sites/host-reference.md +0 -113
- package/docs/handbook/chatgpt-sites/index.md +0 -133
- package/docs/handbook/cloudflare/bindings.md +0 -291
- package/docs/handbook/cloudflare/conventional-worker.md +0 -166
- package/docs/handbook/cloudflare/deferred-hooks-queues.md +0 -170
- package/docs/handbook/cloudflare/low-level-composition.md +0 -169
- package/docs/handbook/cloudflare/public-web.md +0 -144
- package/docs/handbook/cloudflare/site-chrome.md +0 -75
- package/docs/handbook/examples/commerce-transaction.md +0 -11
- package/docs/handbook/examples/commerce.md +0 -11
- package/docs/handbook/examples/guarded-api.md +0 -10
- package/docs/handbook/examples/intake-form.md +0 -12
- package/docs/handbook/examples/intake-hooks.md +0 -11
- package/docs/handbook/examples/legal-documents.md +0 -10
- package/docs/handbook/examples/procurement-approvals.md +0 -10
- package/docs/handbook/examples/publication.md +0 -10
- package/docs/handbook/examples/reservation.md +0 -10
- package/docs/handbook/start/quickstart-admin.md +0 -52
- package/docs/labels.md +0 -71
- package/docs/media-uploads.md +0 -5
- package/docs/migration-0.1.2.md +0 -13
- package/docs/performance-harness.md +0 -228
- package/docs/release-process.md +0 -244
- package/docs/schema-indexes.md +0 -5
- package/docs/sealed-pipeline-ownership.md +0 -101
- package/docs/skills/plugin/SKILL.md +0 -132
- package/docs/skills/theme/SKILL.md +0 -77
- package/docs/spec-only-host-adoption.md +0 -157
- package/docs/transaction-patterns.md +0 -5
- package/skills/develop/SKILL.md +0 -258
- package/skills/install/SKILL.md +0 -112
- package/skills/integrate/SKILL.md +0 -60
- package/skills/media-gc/SKILL.md +0 -85
- package/skills/plugin/SKILL.md +0 -132
- package/skills/provision/SKILL.md +0 -194
- package/skills/theme/SKILL.md +0 -77
- package/skills/update/SKILL.md +0 -51
- package/templates/chatgpt-sites/auth.ts +0 -66
- package/templates/chatgpt-sites/build.mjs +0 -14
- package/templates/chatgpt-sites/env.ts +0 -1
- package/templates/chatgpt-sites/mcp.ts +0 -48
- package/templates/chatgpt-sites/public-mcp.ts +0 -29
- package/templates/chatgpt-sites/smoke-local.mjs +0 -20
|
@@ -1,104 +1,82 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
2
|
+
description: Install schema explicitly, migrate before deploying, and operate a native Worker.
|
|
3
3
|
---
|
|
4
4
|
# Deploy and operate
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Run the same generation command with `--check`, typecheck the application and test its selected routes before deploying. Keep generated TypeScript, SQL and Wrangler edits committed; keep bundle `dist/` untracked. The app owns the database, auth secrets, trusted origin and assets.
|
|
7
7
|
|
|
8
|
-
##
|
|
8
|
+
## Public fetch routing
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- Enable observability:
|
|
10
|
+
Workers use `compatibility_flags: ["nodejs_compat", "global_fetch_strictly_public"]`.
|
|
11
|
+
The public-fetch flag routes native `fetch` through Cloudflare's public Internet
|
|
12
|
+
boundary. OAuth verification needs it to fetch JWKS on the service's own public
|
|
13
|
+
hostname; CIMD also requires this boundary for client metadata. `nodejs_compat`
|
|
14
|
+
alone does not establish it.
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
16
|
+
`mantle generate cloudflare-*` adds these flags without replacing other flags,
|
|
17
|
+
including in environments with their own `compatibility_flags` array. The same
|
|
18
|
+
command with `--check` refuses missing flags without writing. JSON/JSONC configs
|
|
19
|
+
are updated; TOML receives manual-edit instructions. Keep both flags in every
|
|
20
|
+
TOML environment override. An explicit `global_fetch_private_origin` is preserved
|
|
21
|
+
for applications without OAuth/CIMD, but conflicts with selected OAuth/CIMD auth
|
|
22
|
+
and with the public-fetch flag: generation refuses that config without rewriting
|
|
23
|
+
it. Such applications must use public routing for their OAuth/CIMD transport.
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
After deployment, complete a real OAuth sign-in and use the resulting bearer
|
|
26
|
+
for MCP `initialize` and `tools/list`. Local development and cookie-only Admin
|
|
27
|
+
checks do not verify production public-hostname routing.
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
mantle generate && mantle generate --check && mantle validate \
|
|
28
|
-
&& mantle skills && mantle skills --check && tsc --noEmit && node smoke.mjs
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
Add tests and the frontend build where the project has them, then confirm index coverage for every public View:
|
|
29
|
+
## Install and change schemas
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
pnpm exec mantle-harness indexes --require-public --format text
|
|
35
|
-
```
|
|
31
|
+
The runtime never creates, alters or checks tables. Boot and requests run no DDL, introspection or schema checks.
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
For the first install, apply generated `schema.sql`, including selected auth/site DDL, to an empty database. Apply selected seed SQL explicitly.
|
|
38
34
|
|
|
39
|
-
|
|
40
|
-
as a conservative preflight; use post-deploy D1 metrics for production cost and
|
|
41
|
-
latency claims.
|
|
35
|
+
For every later schema change, the application's coding agent diffs the regenerated `schema.sql`, writes a migration with the host's native tool (`wrangler d1 migrations` or the app's PostgreSQL migration tool), rehearses it on a copy, and applies it before deploying the new code.
|
|
42
36
|
|
|
43
|
-
|
|
44
|
-
wrangler deploy --dry-run
|
|
45
|
-
wrangler deploy
|
|
46
|
-
```
|
|
37
|
+
Destructive changes and type changes need explicit data migration. Mantle drops nothing. Initial `schema.sql` is not an upgrade script.
|
|
47
38
|
|
|
48
|
-
|
|
39
|
+
For D1, create a migration with `pnpm exec wrangler d1 migrations create <database> <name>`, review its SQL, then rehearse `pnpm exec wrangler d1 migrations apply <database> --local` against copied data. Apply the reviewed migrations to the target before `wrangler deploy`. Initial DDL may be placed in the first migration for a new database.
|
|
49
40
|
|
|
50
|
-
|
|
51
|
-
the application mounts and configures:
|
|
41
|
+
For PostgreSQL, use the app's migration tool and deployment credentials. Plan lock waits and long index builds there; request credentials need no DDL privileges. Configure session settings on the role/database as described in [native execution](../guides/native-execution.md#postgresql-settings). Hyperdrive query caching must be disabled for authority and mutation visibility.
|
|
52
42
|
|
|
53
|
-
|
|
54
|
-
|---|---|
|
|
55
|
-
| `GET /api/views/<public-view>` | `200`, `{ "ok": true, "data": { "rows": [...] } }` |
|
|
56
|
-
| `GET /<locale>/<segment>/<slug>` and `GET /<locale>/<segment>/<slug>.md` | `200` HTML and Markdown for a published entry |
|
|
57
|
-
| `GET /llms.txt`, `GET /sitemap.xml`, `GET /robots.txt` | `200` |
|
|
58
|
-
| `GET /<locale>/<segment>/does-not-exist` | `404` from your `notFoundRenderer` |
|
|
59
|
-
| `POST /mcp/staff` without credentials | `401` with `WWW-Authenticate`; `GET /mcp` is `405` |
|
|
60
|
-
| `GET /admin` | Sign-in page; sign in with the `ADMIN_GITHUB_LOGIN` account |
|
|
43
|
+
## Latency placement and D1 read replication
|
|
61
44
|
|
|
62
|
-
|
|
45
|
+
Measure these options against the application's real traffic; neither is a
|
|
46
|
+
default latency guarantee. [Smart Placement](https://developers.cloudflare.com/workers/configuration/placement/)
|
|
47
|
+
can move fetch execution closer to observed back-end services:
|
|
63
48
|
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
--route recent=/api/views/recent-posts --route page=/en/posts/hello --rounds 20 --warmup 2
|
|
49
|
+
```jsonc
|
|
50
|
+
"placement": { "mode": "smart" }
|
|
67
51
|
```
|
|
68
52
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
For globally distributed, read-heavy D1 traffic, enable
|
|
54
|
+
[read replication](https://developers.cloudflare.com/d1/best-practices/read-replication/)
|
|
55
|
+
on the database and pass one request-scoped `env.DB.withSession(...)` handle to
|
|
56
|
+
the selected generated Views, Procedures and Store. Those D1 entry points accept
|
|
57
|
+
`D1DatabaseSession`. Without the Sessions API, queries continue to use the primary.
|
|
72
58
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
59
|
+
Use `first-unconstrained` only when a replica snapshot is acceptable,
|
|
60
|
+
`first-primary` when the flow must start from the latest primary state, or carry
|
|
61
|
+
a bookmark between logical sessions for sequential consistency. Reuse the same
|
|
62
|
+
session within that logical flow; all writes still go to the primary. Keep fresh
|
|
63
|
+
authentication/authorization checks and mutation/read-after-write paths on their
|
|
64
|
+
required current-authority path rather than weakening them for replica latency.
|
|
77
65
|
|
|
78
|
-
|
|
66
|
+
## Operate
|
|
79
67
|
|
|
80
|
-
|
|
68
|
+
Enable Workers Logs and traces in production. The top-level `observability.enabled` alone does not enable traces:
|
|
81
69
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
70
|
+
```jsonc
|
|
71
|
+
"observability": {
|
|
72
|
+
"enabled": true,
|
|
73
|
+
"logs": { "enabled": true, "head_sampling_rate": 1 },
|
|
74
|
+
"traces": { "enabled": true, "head_sampling_rate": 0.01 }
|
|
75
|
+
}
|
|
76
|
+
```
|
|
85
77
|
|
|
86
|
-
|
|
87
|
-
2. Keep application source, Worker/D1/KV identity, origins, auth mode and secrets.
|
|
88
|
-
3. Run `mantle generate`, `generate --check`, `skills`, `skills --check`, `validate`, typecheck and tests.
|
|
89
|
-
4. Test local routes and authorization, then deploy.
|
|
78
|
+
Auth configuration and production email delivery are app-owned; follow [authentication](authentication.md). Keep secrets in the platform's secret store. With `secrets.required`, `wrangler deploy` refuses to upload while a required secret is unset: set them with `wrangler secret put` (or pass `--secrets-file` on the first deploy). Serve the selected Admin assets through the [native Admin](../guides/native-admin.md) shell contract.
|
|
90
79
|
|
|
91
|
-
|
|
80
|
+
Scheduling is app-owned. Wire generated system-only TTL sweeps into `scheduled()` and configure Wrangler crons explicitly. Bound each invocation and retain a cursor if work remains; see [TTL maintenance](../guides/native-execution.md#ttl-maintenance). Expired rows remain stored and hold unique keys until removed.
|
|
92
81
|
|
|
93
|
-
|
|
94
|
-
- [`packages/mantle/README.md`](../../../packages/mantle/README.md)
|
|
95
|
-
- [`packages/adapters/cloudflare/README.md`](../../../packages/adapters/cloudflare/README.md)
|
|
96
|
-
- [`docs/direct-authoring.md`](../../../docs/direct-authoring.md)
|
|
97
|
-
- [`docs/performance-harness.md`](../../../docs/performance-harness.md)
|
|
98
|
-
- [`docs/examples/host-minimal-worker/README.md`](../../../docs/examples/host-minimal-worker/README.md)
|
|
99
|
-
- [`docs/examples/host-minimal-worker/package.json`](../../../docs/examples/host-minimal-worker/package.json)
|
|
100
|
-
- [`docs/examples/host-minimal-worker/wrangler.jsonc`](../../../docs/examples/host-minimal-worker/wrangler.jsonc)
|
|
101
|
-
- [`docs/examples/host-minimal-worker/smoke.mjs`](../../../docs/examples/host-minimal-worker/smoke.mjs)
|
|
102
|
-
- [`packages/mantle-spec/src/domain/model/SiteConfig.ts`](../../../packages/mantle-spec/src/domain/model/SiteConfig.ts)
|
|
103
|
-
- [`packages/mantle-admin/src/mountMantleAdmin.ts`](../../../packages/mantle-admin/src/mountMantleAdmin.ts)
|
|
104
|
-
- [`packages/adapters/cloudflare/src/oauth/cachePolicy.ts`](../../../packages/adapters/cloudflare/src/oauth/cachePolicy.ts)
|
|
82
|
+
After deployment, verify public and protected reads, member/admin sign-in, a persisted write, stale OCC and selected MCP/Admin/web routes. An `OUTCOME_UNKNOWN` write may have committed; reconcile before deciding what to do next and never retry automatically.
|
|
@@ -1,216 +1,72 @@
|
|
|
1
|
-
|
|
2
|
-
description: Enable staff media uploads on R2 — presigned PUT flow through Staff MCP, media purposes, wrangler config, commit cost and cleanup.
|
|
3
|
-
---
|
|
4
|
-
# Media uploads with R2
|
|
1
|
+
# Optional site settings and media
|
|
5
2
|
|
|
6
|
-
|
|
3
|
+
Declare a TypeScript `siteDefaults` object using the 0.2 `SiteDefaults` shape and
|
|
4
|
+
pass it to generation, or use `mantle generate ... --site ./site-config.ts`.
|
|
5
|
+
Apply the emitted `schema.sql` to a new database; apply idempotent `site-seed.sql`
|
|
6
|
+
on subsequent deployments to seed only absent operator fields. Import `site` from the generated
|
|
7
|
+
`site` module; call `site(db, verifiedCaller).read()`, `.updateSettings({brand,title,
|
|
8
|
+
description})`, or `.media(storage)` to access the library. Construction runs no
|
|
9
|
+
queries, migrations, seeds, or storage work. The library accepts verified admin
|
|
10
|
+
Callers of any credential kind; the Admin handler must additionally keep its
|
|
11
|
+
cookie-session-only gate and the shared session-mutation origin check. The optional module is absent from
|
|
12
|
+
a Worker that does not import it.
|
|
7
13
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Turn this on only after the site already has a working deploy, staff auth configured, and a real need for staff-managed media. R2 setup may require billing, so it is deliberately not part of the first-deploy path. Everything on this page is inert until the bucket, credentials and at least one media purpose all exist.
|
|
11
|
-
|
|
12
|
-
Media maintenance also needs an agent that can read local files, process images and make outbound `PUT` requests to `*.r2.cloudflarestorage.com`. A sandboxed agent without egress cannot finish the flow.
|
|
13
|
-
|
|
14
|
-
## The upload flow
|
|
15
|
-
|
|
16
|
-
```txt
|
|
17
|
-
1. create_media_upload staff MCP -> purpose, variants, mime types, byte sizes
|
|
18
|
-
2. Mantle -> signed upload URLs + required headers
|
|
19
|
-
3. agent or browser -> PUT bytes directly to R2
|
|
20
|
-
4. commit_media_upload staff MCP -> validate, stamp, save the asset row
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
Bytes travel from the agent to R2 over a signed URL; the Worker sees policy, not payload. Never pass image bytes or base64 payloads through MCP tool arguments — the tool dispatchers count streamed JSON bytes and return `413` above the 1 MiB control-plane limit. The Worker validates; the agent runtime does the file work.
|
|
24
|
-
|
|
25
|
-
## Cloudflare setup
|
|
26
|
-
|
|
27
|
-
```sh
|
|
28
|
-
wrangler r2 bucket create <project>-media
|
|
29
|
-
wrangler r2 bucket dev-url enable <project>-media
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
Then create an R2 S3 API token in the dashboard: open **R2**, open **Manage R2 API Tokens**, create an **Object Read & Write** token, and copy the Access Key ID and Secret Access Key.
|
|
33
|
-
|
|
34
|
-
The R2 binding alone cannot issue presigned `PUT` URLs: presigning is an S3-protocol operation, so this **direct-to-R2 adapter** needs these credentials in addition to the binding. This is not a requirement of Mantle's `MediaStorage` port: a host may return an authenticated same-origin Worker `PUT` URL instead. Media tools appear whenever `mediaStorage` and a media purpose are bound, regardless of which transport the adapter uses.
|
|
35
|
-
|
|
36
|
-
## Wrangler configuration
|
|
37
|
-
|
|
38
|
-
```toml
|
|
39
|
-
[vars]
|
|
40
|
-
R2_ACCOUNT_ID = "<account-id>"
|
|
41
|
-
MEDIA_PUBLIC_URL_BASE = "https://pub-<hash>.r2.dev"
|
|
42
|
-
|
|
43
|
-
[[r2_buckets]]
|
|
44
|
-
binding = "MEDIA_BUCKET"
|
|
45
|
-
bucket_name = "<project>-media"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
A `wrangler.jsonc` project writes the same binding as an `"r2_buckets"` array; see [Bindings and primitives](./bindings.md#r2-media-bucket-optional) for the JSON form and the matching `Env` fields.
|
|
49
|
-
|
|
50
|
-
```sh
|
|
51
|
-
wrangler secret put R2_ACCESS_KEY_ID
|
|
52
|
-
wrangler secret put R2_SECRET_ACCESS_KEY
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
`MEDIA_PUBLIC_URL_BASE` is the origin public URLs are built from — the `r2.dev` development URL, or a custom domain in production. `R2_ACCOUNT_ID` builds the S3 endpoint, which is a different host from the public one.
|
|
56
|
-
|
|
57
|
-
## Wiring `R2MediaStorage`
|
|
58
|
-
|
|
59
|
-
Build the adapter from `env`, returning `undefined` when any part is missing so a half-configured environment degrades to no media rather than failing to boot:
|
|
14
|
+
Each media purpose in `siteDefaults.media.purposes` lists mime **slots** and a byte cap per full mime type:
|
|
60
15
|
|
|
61
16
|
```ts
|
|
62
|
-
|
|
63
|
-
import { AwsClient } from "aws4fetch";
|
|
64
|
-
|
|
65
|
-
function buildMediaStorage(env: Env) {
|
|
66
|
-
if (
|
|
67
|
-
!env.MEDIA_BUCKET ||
|
|
68
|
-
!env.R2_ACCOUNT_ID ||
|
|
69
|
-
!env.R2_ACCESS_KEY_ID ||
|
|
70
|
-
!env.R2_SECRET_ACCESS_KEY ||
|
|
71
|
-
!env.MEDIA_PUBLIC_URL_BASE
|
|
72
|
-
) {
|
|
73
|
-
return undefined;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const s3 = new AwsClient({
|
|
77
|
-
accessKeyId: env.R2_ACCESS_KEY_ID,
|
|
78
|
-
secretAccessKey: env.R2_SECRET_ACCESS_KEY,
|
|
79
|
-
region: "auto",
|
|
80
|
-
service: "s3",
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
return new R2MediaStorage(
|
|
84
|
-
env.MEDIA_BUCKET,
|
|
85
|
-
s3,
|
|
86
|
-
`https://<project>-media.${env.R2_ACCOUNT_ID}.r2.cloudflarestorage.com`,
|
|
87
|
-
env.MEDIA_PUBLIC_URL_BASE,
|
|
88
|
-
);
|
|
89
|
-
}
|
|
17
|
+
{ name: "cover", required: ["image/jpeg,image/png,image/webp"], maxBytes: { "image/jpeg": 5_000_000, "image/png": 5_000_000, "image/webp": 5_000_000 } }
|
|
90
18
|
```
|
|
91
19
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
```ts
|
|
95
|
-
export default createMantleWorker<Env>({
|
|
96
|
-
plan,
|
|
97
|
-
bindings: (env, conventional) => ({
|
|
98
|
-
...conventional,
|
|
99
|
-
mediaStorage: buildMediaStorage(env),
|
|
100
|
-
}),
|
|
101
|
-
});
|
|
102
|
-
```
|
|
20
|
+
`required` entries use `<input accept>` grammar (full mime, comma list, or a subtype shorthand such as `webp`);
|
|
21
|
+
`maxBytes` must cover every mime the slots allow, keyed by the full mime type.
|
|
103
22
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
## Declaring media purposes
|
|
107
|
-
|
|
108
|
-
A purpose is the upload policy: which variants an asset must have, and how large each may be.
|
|
23
|
+
Applications own their R2 binding, public bucket URL and S3 credentials; the SDK
|
|
24
|
+
package does not manage them. Import `r2MediaStorage` from `@aotter/mantle/media/r2`:
|
|
109
25
|
|
|
110
26
|
```ts
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
`required` is slot-based, in the grammar of an `<input accept>` list. The example declares three slots: slot 0 takes exactly one fallback mime preserving source semantics (`image/jpeg` for opaque photos, `image/png` when alpha must survive), slot 1 a WebP variant, slot 2 an AVIF variant. That models a multi-variant `<picture>`. A narrower purpose may declare a single slot such as `["image/jpeg,image/png,image/webp,image/gif"]`, in which case the agent picks exactly one mime from that list and must not upload one variant per listed mime.
|
|
130
|
-
|
|
131
|
-
Purpose names are slugs (`^[a-z0-9]+(-[a-z0-9]+)*$`), every slot must be non-empty, slots may not overlap on a mime, and every `maxBytes` key must be a mime some slot accepts with a positive value. Violations fail at boot. SVG uploads are rejected unless the Worker sets `mediaAllowSvg`. See [Site defaults and site_config](../reference/site-config.md).
|
|
132
|
-
|
|
133
|
-
The runtime emits the policy summary into the `create_media_upload` tool description, so an agent reads the contract straight from `tools/list` without an extra round trip.
|
|
134
|
-
|
|
135
|
-
## Tool visibility
|
|
136
|
-
|
|
137
|
-
`create_media_upload` and `commit_media_upload` are registered only when **both** hold:
|
|
138
|
-
|
|
139
|
-
- `bindings.mediaStorage` is set;
|
|
140
|
-
- `siteDefaults.media.purposes` contains at least one purpose.
|
|
141
|
-
|
|
142
|
-
If either is missing the tools never appear in `tools/list`. That is the intended diagnostic: an agent that cannot see the tools is looking at a deployment where media is not configured, not at a permissions problem. A call that reaches a runtime without media storage answers `MEDIA_NOT_CONFIGURED`.
|
|
143
|
-
|
|
144
|
-
## Referencing an asset from a Schema
|
|
145
|
-
|
|
146
|
-
Entries store asset ids, not URLs. Mark the field with both existing v0.1 grammar extensions:
|
|
147
|
-
|
|
148
|
-
```yaml
|
|
149
|
-
apiVersion: cms.mantle.aotter.net/v1
|
|
150
|
-
kind: Schema
|
|
151
|
-
metadata:
|
|
152
|
-
name: pages
|
|
153
|
-
spec:
|
|
154
|
-
title: Pages
|
|
155
|
-
schema:
|
|
156
|
-
type: object
|
|
157
|
-
additionalProperties: false
|
|
158
|
-
required: [slug, title]
|
|
159
|
-
properties:
|
|
160
|
-
slug: { type: string, pattern: "^[a-z0-9-]+$" }
|
|
161
|
-
title: { type: string, minLength: 1 }
|
|
162
|
-
coverAssetId:
|
|
163
|
-
type: string
|
|
164
|
-
x-mantle-ref: media_assets
|
|
165
|
-
x-mcp-hint: media-image
|
|
27
|
+
const storage = r2MediaStorage({
|
|
28
|
+
bucket: env.MEDIA,
|
|
29
|
+
endpoint: "https://bucket.account.r2.cloudflarestorage.com",
|
|
30
|
+
publicBase: "https://media.example.com",
|
|
31
|
+
signer, // app-owned SigV4 signer: sign(url, {method:"PUT",aws:{signQuery:true,service:"s3"}})
|
|
32
|
+
});
|
|
33
|
+
const media = site(db, caller).media(storage);
|
|
34
|
+
const upload = await media.createUpload({
|
|
35
|
+
filename: "cover.jpg", purpose: "cover",
|
|
36
|
+
variants: [{mimeType:"image/jpeg",byteSize:1234,role:"primary"}]
|
|
37
|
+
});
|
|
38
|
+
// Client PUTs bytes directly to upload.capabilities[i].uploadUrl,
|
|
39
|
+
// with its requiredHeaders. Never send the bytes through Mantle.
|
|
40
|
+
const asset = await media.commitUpload(upload.uploadGroupId);
|
|
166
41
|
```
|
|
167
42
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
| `MEDIA_SVG_REJECTED` | 400 | An SVG was offered while SVG is not allowed; object storage does not sanitize SVG payloads |
|
|
199
|
-
| `MEDIA_VARIANTS_INCOMPLETE` | 400 | The bundle misses a mime the purpose requires; the missing set is returned |
|
|
200
|
-
| `MEDIA_VARIANT_SIZE_EXCEEDED` | 400 | One variant exceeds the cap declared for its mime |
|
|
201
|
-
| `MEDIA_VARIANTS_SUSPICIOUS_SIZE` | 400 | A modern variant is larger than its fallback (AVIF above JPEG), so it looks unoptimized |
|
|
202
|
-
| `MEDIA_ASSET_NOT_FOUND` | 404 | No `media_assets` row matches the id |
|
|
203
|
-
| `MEDIA_UPLOAD_EXPIRED` | 410 | The upload capability's TTL elapsed, or it was never created |
|
|
204
|
-
| `MEDIA_OBJECT_NOT_FOUND` | 409 | A variant's bytes were never PUT before commit |
|
|
205
|
-
|
|
206
|
-
The full catalog is in [Diagnostic codes](../reference/diagnostics.md).
|
|
207
|
-
|
|
208
|
-
## Source
|
|
209
|
-
- [`docs/media-uploads.md`](../../../docs/media-uploads.md)
|
|
210
|
-
- [`docs/adr/0017-media-multi-variant-agent-side-optimization.md`](../../../docs/adr/0017-media-multi-variant-agent-side-optimization.md)
|
|
211
|
-
- [`packages/mantle-runtime/src/domain/port/MediaStorage.ts`](../../../packages/mantle-runtime/src/domain/port/MediaStorage.ts)
|
|
212
|
-
- [`packages/mantle-runtime/src/domain/port/MediaAssetRepository.ts`](../../../packages/mantle-runtime/src/domain/port/MediaAssetRepository.ts)
|
|
213
|
-
- [`packages/mantle-spec/src/domain/service/SiteDefaultsValidator.ts`](../../../packages/mantle-spec/src/domain/service/SiteDefaultsValidator.ts)
|
|
214
|
-
- [`packages/mantle-spec/src/kernel/diagnostic.ts`](../../../packages/mantle-spec/src/kernel/diagnostic.ts)
|
|
215
|
-
- [`packages/adapters/cloudflare/README.md`](../../../packages/adapters/cloudflare/README.md)
|
|
216
|
-
- [`docs/skills/media-gc/SKILL.md`](../../skills/media-gc/SKILL.md)
|
|
43
|
+
An existing S3 signer (for example an application already using aws4fetch) fits
|
|
44
|
+
this port. This package adds no AWS SDK. The signer must return a SigV4
|
|
45
|
+
query-signed PUT URL and preserve `X-Amz-Expires`; never give its credentials to
|
|
46
|
+
the client. Configure bucket CORS to allow PUT from the application's origins
|
|
47
|
+
and the returned Content-Type header. Serve the `committed/` prefix on the public domain; these keys differ from 0.2's `{purpose}/{group}/{role}` keys. Keep `uploads/` private/unserved on the
|
|
48
|
+
public domain and add a bucket lifecycle rule for abandoned upload keys.
|
|
49
|
+
|
|
50
|
+
Commit checks every object's MIME and size, then rechecks the exact GET
|
|
51
|
+
response used for the copy. Public keys cannot be reached by an upload URL. Each commit attempt has a separate
|
|
52
|
+
public-key UUID, while the asset id remains the upload-group UUID. A concurrent
|
|
53
|
+
loser can neither overwrite nor remove the winner's objects. After SQL selects
|
|
54
|
+
the durable asset, the losing attempt removes only its own unselected copies.
|
|
55
|
+
Upload sources remain until the database commit succeeds, so an uncertain DB
|
|
56
|
+
write can be reconciled/retried with the same UUID. Failed object deletion keeps
|
|
57
|
+
the media row; retry the same id. An upload group expires after 15 minutes. Asset `createdAt` is the upload-group creation time (epoch milliseconds), not the later commit time.
|
|
58
|
+
No R2 upload or deployment is performed by generation.
|
|
59
|
+
|
|
60
|
+
A positively identified native rollback deletes only that attempt's copied
|
|
61
|
+
objects. Plain/network failures lack rollback evidence, retain copies, and return
|
|
62
|
+
`OUTCOME_UNKNOWN`, including a lost D1 batch response.
|
|
63
|
+
An uncertain native write preserves copies, because they may belong to the
|
|
64
|
+
durable winning row. If SQL durability or unselected-copy cleanup returns `OUTCOME_UNKNOWN`, reconcile
|
|
65
|
+
storage with the durable `media_assets.variants` keys. Attempt-isolated copies
|
|
66
|
+
may remain after an uncertain outcome; never delete the winning asset's keys or
|
|
67
|
+
expire all `committed/` objects indiscriminately. The group UUID remains the
|
|
68
|
+
reconciliation and retry id.
|
|
69
|
+
|
|
70
|
+
Admin's `media` option takes a `MediaStorage` value, so build it where `env` is available (for example once per
|
|
71
|
+
Worker in the fetch handler). Uploads use presigned S3 PUT URLs: `wrangler dev --local` has an R2 binding but no S3
|
|
72
|
+
endpoint, so test the upload flow against a real bucket; local tests can cover everything up to the signed URL.
|