@anthusai/papyrus 2.0.0-next.11 → 2.0.0-next.110

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 (227) hide show
  1. package/amplify/auth/resource.js +16 -1
  2. package/amplify/auth/resource.ts +19 -1
  3. package/amplify/data/function-handler.js +20 -0
  4. package/amplify/data/function-handler.ts +40 -0
  5. package/amplify/data/resource.js +152 -62
  6. package/amplify/data/resource.ts +158 -62
  7. package/amplify/data/schema.js +2101 -1987
  8. package/amplify/data/schema.ts +197 -70
  9. package/amplify/functions/assignment-action/data-access.js +2 -0
  10. package/amplify/functions/assignment-action/data-access.ts +2 -0
  11. package/amplify/functions/assignment-action/handler.ts +1 -1
  12. package/amplify/functions/automation-view/handler.py +17 -0
  13. package/amplify/functions/automation-view/resource.js +24 -0
  14. package/amplify/functions/automation-view/resource.ts +34 -0
  15. package/amplify/functions/automation-view/schema.js +26 -0
  16. package/amplify/functions/automation-view/schema.ts +28 -0
  17. package/amplify/functions/automation-view/wire.js +56 -0
  18. package/amplify/functions/automation-view/wire.ts +76 -0
  19. package/amplify/functions/content-actions/handler.py +64 -3
  20. package/amplify/functions/content-actions/requirements.txt +1 -0
  21. package/amplify/functions/content-actions/resource.js +1 -1
  22. package/amplify/functions/content-actions/resource.ts +1 -1
  23. package/amplify/functions/editorial-checks/handler.py +2 -2
  24. package/amplify/functions/editorial-checks/requirements.txt +1 -1
  25. package/amplify/functions/editorial-checks/resource.js +3 -3
  26. package/amplify/functions/editorial-checks/resource.ts +3 -3
  27. package/amplify/functions/editorial-checks/schema.js +38 -8
  28. package/amplify/functions/editorial-checks/schema.ts +38 -8
  29. package/amplify/functions/editorial-checks/wire.js +4 -0
  30. package/amplify/functions/editorial-checks/wire.ts +4 -0
  31. package/amplify/functions/monitoring-view/handler.py +11 -0
  32. package/amplify/functions/monitoring-view/resource.js +24 -0
  33. package/amplify/functions/monitoring-view/resource.ts +34 -0
  34. package/amplify/functions/monitoring-view/schema.js +29 -0
  35. package/amplify/functions/monitoring-view/schema.ts +31 -0
  36. package/amplify/functions/monitoring-view/wire.js +64 -0
  37. package/amplify/functions/monitoring-view/wire.ts +81 -0
  38. package/amplify/functions/public-forms/core.js +247 -0
  39. package/amplify/functions/public-forms/core.ts +310 -0
  40. package/amplify/functions/public-forms/handler.ts +41 -0
  41. package/amplify/functions/public-forms/origins.js +35 -0
  42. package/amplify/functions/public-forms/origins.ts +43 -0
  43. package/amplify/functions/public-forms/resource.js +9 -0
  44. package/amplify/functions/public-forms/resource.ts +10 -0
  45. package/amplify/functions/public-forms/wire.js +25 -0
  46. package/amplify/functions/public-forms/wire.ts +32 -0
  47. package/amplify/functions/shared/editorial-context.ts +63 -4
  48. package/amplify/functions/shared/python-bundle.js +20 -14
  49. package/amplify/functions/shared/python-bundle.ts +25 -18
  50. package/amplify/plugins/newsletter/config.js +245 -0
  51. package/amplify/plugins/newsletter/config.ts +305 -0
  52. package/amplify/plugins/newsletter/function/handler.py +6 -0
  53. package/amplify/plugins/newsletter/function/requirements.txt +5 -0
  54. package/amplify/plugins/newsletter/ops/handler.py +12 -0
  55. package/amplify/plugins/newsletter/ops/resource.js +27 -0
  56. package/amplify/plugins/newsletter/ops/resource.ts +37 -0
  57. package/amplify/plugins/newsletter/papyrus.plugin.js +263 -0
  58. package/amplify/plugins/newsletter/papyrus.plugin.ts +311 -0
  59. package/amplify/plugins/newsletter/schema.js +57 -0
  60. package/amplify/plugins/newsletter/schema.ts +62 -0
  61. package/amplify/plugins/newsletter/secure-string-parameter.js +107 -0
  62. package/amplify/plugins/newsletter/secure-string-parameter.ts +120 -0
  63. package/amplify/plugins/newsletter/sending.js +140 -0
  64. package/amplify/plugins/newsletter/sending.ts +186 -0
  65. package/amplify/plugins/reader-steering/config.js +182 -0
  66. package/amplify/plugins/reader-steering/config.ts +290 -0
  67. package/amplify/plugins/reader-steering/function/ai_moderation.py +246 -0
  68. package/amplify/plugins/reader-steering/function/handler.py +1589 -0
  69. package/amplify/plugins/reader-steering/function/moderation-prompt.md +27 -0
  70. package/amplify/plugins/reader-steering/function/moderation.py +316 -0
  71. package/amplify/plugins/reader-steering/function/proposals.py +487 -0
  72. package/amplify/plugins/reader-steering/function/resource.js +27 -0
  73. package/amplify/plugins/reader-steering/function/resource.ts +35 -0
  74. package/amplify/plugins/reader-steering/papyrus.plugin.js +187 -0
  75. package/amplify/plugins/reader-steering/papyrus.plugin.ts +213 -0
  76. package/amplify/plugins/reader-steering/schema.js +252 -0
  77. package/amplify/plugins/reader-steering/schema.ts +254 -0
  78. package/amplify/plugins/registry.js +4 -0
  79. package/amplify/plugins/registry.ts +4 -0
  80. package/amplify/plugins/signup/schema.js +2 -1
  81. package/amplify/plugins/signup/schema.ts +2 -1
  82. package/amplify/plugins/types.ts +5 -0
  83. package/amplify/plugins/wire.js +1 -0
  84. package/amplify/plugins/wire.ts +1 -0
  85. package/amplify/publication/projection-lease.js +30 -0
  86. package/amplify/publication/projection-lease.ts +39 -0
  87. package/amplify/publication/redirect-and-index.js +105 -0
  88. package/amplify/publication/redirect-rules.js +73 -0
  89. package/amplify/publication/redirect-rules.ts +93 -0
  90. package/amplify/publication/s3-projection.js +7 -1
  91. package/amplify/publication/s3-projection.ts +9 -1
  92. package/amplify/site-backend-config.js +19 -0
  93. package/amplify/site-backend-config.ts +45 -1
  94. package/amplify/site-backend-names.js +4 -2
  95. package/amplify/site-backend-names.ts +4 -2
  96. package/amplify/site-backend.js +42 -4
  97. package/amplify/site-backend.ts +45 -4
  98. package/app/.well-known/papyrus-cli.json/route.ts +9 -0
  99. package/app/api/auth/prospectus/sign-in/route.ts +4 -0
  100. package/app/api/newsletter/confirm/route.ts +13 -0
  101. package/app/api/newsletter/preferences/route.ts +13 -0
  102. package/app/api/newsletter/state/route.ts +9 -0
  103. package/app/api/newsletter/subscribe/route.ts +9 -0
  104. package/app/api/newsletter/unsubscribe/route.ts +13 -0
  105. package/app/api/newsroom/chat/[...path]/route.ts +17 -0
  106. package/app/api/newsroom/curation/context/route.ts +9 -0
  107. package/app/api/newsroom/curation/priming/route.ts +9 -0
  108. package/app/api/newsroom/curation/publication/route.ts +9 -0
  109. package/app/api/reader/comment/delete/route.ts +9 -0
  110. package/app/api/reader/comment/edit/route.ts +9 -0
  111. package/app/api/reader/comment/route.ts +9 -0
  112. package/app/api/reader/flag/route.ts +9 -0
  113. package/app/api/reader/handle/route.ts +9 -0
  114. package/app/api/reader/me/route.ts +9 -0
  115. package/app/api/reader/rating/route.ts +9 -0
  116. package/app/api/reader/report/route.ts +9 -0
  117. package/app/api/reader/retired/route.ts +9 -0
  118. package/app/api/reader/submit/route.ts +9 -0
  119. package/app/api/reader/vote/route.ts +9 -0
  120. package/app/layout.tsx +5 -1
  121. package/bin/papyrus-infra.mjs +20 -1
  122. package/components/automation-panel.tsx +49 -0
  123. package/components/automation-run-now.tsx +97 -0
  124. package/components/automation-view.tsx +195 -0
  125. package/components/editorial-checks-admin-panel.tsx +32 -17
  126. package/components/moderation-panel.tsx +248 -0
  127. package/components/monitoring-overview-view.tsx +422 -0
  128. package/components/monitoring-panel.tsx +60 -0
  129. package/components/news-desk-client-provider.tsx +18 -18
  130. package/components/news-desk-taxonomy-client.ts +28 -8
  131. package/components/newsletter-panel.tsx +474 -0
  132. package/components/newsletter-sections.tsx +163 -0
  133. package/components/newsroom-access-gate.tsx +16 -2
  134. package/components/newsroom-article-editor.tsx +9 -7
  135. package/components/newsroom-articles-view.tsx +6 -6
  136. package/components/newsroom-assignment-detail.tsx +6 -6
  137. package/components/newsroom-board-view.tsx +8 -3
  138. package/components/newsroom-curation-bootstrap.tsx +45 -0
  139. package/components/newsroom-ops-overview.tsx +26 -96
  140. package/components/newsroom-ops-shell.tsx +2 -2
  141. package/components/newsroom-organizer.css +33 -0
  142. package/components/newsroom-overview-skeleton.tsx +25 -0
  143. package/components/newsroom-references-view.tsx +192 -49
  144. package/components/notification-center.tsx +281 -0
  145. package/components/papyrus-console-conversation.css +14 -0
  146. package/components/papyrus-console-conversation.tsx +55 -0
  147. package/components/papyrus-console-shell.tsx +62 -420
  148. package/components/papyrus-private-chat-panel.tsx +134 -0
  149. package/components/publication-cyclotron-panel.tsx +15 -10
  150. package/components/reader-auth-state.ts +1 -1
  151. package/components/reference-add-entry.tsx +75 -0
  152. package/components/reference-curation-controls.tsx +31 -22
  153. package/components/reference-cyclotron-priming.tsx +58 -19
  154. package/components/reference-cyclotron-suggestion.tsx +10 -6
  155. package/components/reference-priming.tsx +14 -10
  156. package/components/reference-relevance-review.tsx +3 -3
  157. package/components/reference-section-suggestion.tsx +1 -1
  158. package/components/topic-steering-workspace.tsx +230 -144
  159. package/infra/amplify-app-shell.js +96 -16
  160. package/infra/amplify-app-shell.ts +108 -18
  161. package/infra/cloud-email-config.js +32 -0
  162. package/infra/cloud-email-config.ts +39 -0
  163. package/infra/cloud-email.js +57 -0
  164. package/infra/cloud-email.test.js +69 -0
  165. package/infra/cloud-email.test.ts +66 -0
  166. package/infra/cloud-email.ts +60 -0
  167. package/infra/index.js +1 -0
  168. package/infra/secure-string-parameter-handler.js +41 -0
  169. package/infra/secure-string-parameter-handler.ts +41 -0
  170. package/infra/secure-string-parameter.js +79 -0
  171. package/infra/secure-string-parameter.ts +91 -0
  172. package/infra/site-config.js +92 -6
  173. package/infra/site-config.ts +138 -6
  174. package/lib/automation-client.ts +54 -0
  175. package/lib/automation-fixture.ts +93 -0
  176. package/lib/automation-overview.ts +252 -0
  177. package/lib/category-repository.ts +14 -12
  178. package/lib/cli-login-discovery.ts +78 -0
  179. package/lib/console-web-context.ts +1 -1
  180. package/lib/curation-routes.ts +345 -0
  181. package/lib/cyclotron-suggestions.ts +4 -4
  182. package/lib/editorial-checks-client.ts +18 -0
  183. package/lib/editorial-checks-demo.ts +1 -1
  184. package/lib/editorial-checks.ts +8 -4
  185. package/lib/editorial-preview.ts +5 -5
  186. package/lib/monitoring-client.ts +83 -0
  187. package/lib/monitoring-overview-fixture.ts +51 -0
  188. package/lib/monitoring-overview.ts +191 -0
  189. package/lib/news-desk-session.ts +12 -21
  190. package/lib/newsletter-api.ts +418 -0
  191. package/lib/newsletter-client.ts +46 -0
  192. package/lib/newsletter-fixture.ts +184 -0
  193. package/lib/newsletter-model.ts +202 -0
  194. package/lib/newsroom-demo-dashboard.ts +1 -1
  195. package/lib/newsroom-nav.ts +1 -1
  196. package/lib/newsroom-organizer-nav.ts +2 -1
  197. package/lib/papyrus-chat-admission.ts +65 -0
  198. package/lib/papyrus-hosted-chat.ts +217 -0
  199. package/lib/papyrus-private-chat-client.ts +81 -0
  200. package/lib/prospectus-session.ts +30 -14
  201. package/lib/prospectus-sign-in-routes.ts +106 -31
  202. package/lib/prospectus-site-identity.ts +46 -6
  203. package/lib/reader-api.ts +145 -0
  204. package/lib/reader-moderation.ts +220 -0
  205. package/lib/reader-retirement-route.ts +89 -0
  206. package/lib/reader-subject.md +29 -0
  207. package/lib/reader-subject.ts +53 -0
  208. package/lib/reference-review-details.ts +71 -0
  209. package/lib/reference-review-request.ts +14 -0
  210. package/lib/relevance-decisions.ts +42 -10
  211. package/lib/relevance-status.ts +2 -2
  212. package/lib/review-client.ts +120 -0
  213. package/lib/review-fixture.ts +45 -0
  214. package/lib/review-requests.ts +246 -0
  215. package/lib/semantic-graph.ts +2 -0
  216. package/lib/shared-chat-admission.ts +182 -0
  217. package/lib/site-brand-tenant.ts +11 -6
  218. package/lib/site-brand.ts +6 -3
  219. package/lib/site-origin-value.ts +50 -0
  220. package/lib/site-origin.ts +8 -0
  221. package/lib/use-reference-review-data.ts +44 -0
  222. package/middleware.ts +14 -3
  223. package/package.json +67 -3
  224. package/routes.manifest.json +238 -2
  225. package/src/sync.mjs +11 -2
  226. package/src/with-papyrus.d.mts +1 -0
  227. package/src/with-papyrus.mjs +17 -1
@@ -2,13 +2,17 @@ import { type ClientSchema, a } from "@aws-amplify/backend";
2
2
  import { assignmentAction } from "../functions/assignment-action/resource";
3
3
  import { categoryAction } from "../functions/category-action/resource";
4
4
  import { editorialChecksSchemaDefinitions } from "../functions/editorial-checks/schema";
5
+ import { automationViewSchemaDefinitions } from "../functions/automation-view/schema";
6
+ import { monitoringViewSchemaDefinitions } from "../functions/monitoring-view/schema";
5
7
  import { contentActions } from "../functions/content-actions/resource";
6
8
  import { knowledgeQuery } from "../functions/knowledge-query/resource";
7
9
  import { manageUserRole } from "../functions/manage-user-role/resource";
8
10
  import { modelAttachmentUpload } from "../functions/model-attachment-upload/resource";
9
11
  import { newsroomSummary } from "../functions/newsroom-summary/resource";
12
+ import { publicForms } from "../functions/public-forms/resource";
10
13
  import { procedureAction } from "../functions/procedure-action/resource";
11
14
  import { readerSettings } from "../functions/reader-settings/resource";
15
+ import { functionHandler } from "./function-handler";
12
16
 
13
17
  const authoringOperations: ("read" | "create" | "update" | "delete")[] = [
14
18
  "read",
@@ -24,7 +28,27 @@ const modelWithoutSubscriptions = <Fields extends Parameters<typeof a.model>[0]>
24
28
  a.model(fields).disableOperations(["subscriptions"]);
25
29
  const realtimeModel = <Fields extends Parameters<typeof a.model>[0]>(fields: Fields) => a.model(fields);
26
30
 
27
- const baseDefinitions = {
31
+ /**
32
+ * Model groups a site may leave out of its data API. CloudFormation creates at most 2,500 resources in one stack
33
+ * operation, nested stacks included, and the full model set exceeds that on a fresh create. A first deploy that
34
+ * excludes a group fits; a second deploy without the exclusion adds the models as an ordinary update.
35
+ */
36
+ export const OPTIONAL_MODEL_GROUPS = {
37
+ editions: ["Edition", "EditionItem", "PublishedEdition", "PublishedEditionItem"],
38
+ } as const;
39
+
40
+ export type OptionalModelGroup = keyof typeof OPTIONAL_MODEL_GROUPS;
41
+
42
+ export function assertKnownModelGroups(groups: readonly string[]): asserts groups is readonly OptionalModelGroup[] {
43
+ for (const group of groups) {
44
+ if (!(group in OPTIONAL_MODEL_GROUPS)) {
45
+ throw new Error(`Unknown model group "${group}"; known groups: ${Object.keys(OPTIONAL_MODEL_GROUPS).join(", ")}`);
46
+ }
47
+ }
48
+ }
49
+
50
+ function buildBaseDefinitions(includeEditions: boolean) {
51
+ const definitions = {
28
52
  UserProfile: modelWithoutSubscriptions({
29
53
  id: a.id().required(),
30
54
  email: a.email(),
@@ -139,7 +163,7 @@ const baseDefinitions = {
139
163
  .query()
140
164
  .returns(a.ref("UserDirectoryResult"))
141
165
  .authorization((allow) => [allow.group(adminGroup)])
142
- .handler(a.handler.function(manageUserRole)),
166
+ .handler(functionHandler("manageUserRole", manageUserRole)),
143
167
 
144
168
  grantUserRole: a
145
169
  .mutation()
@@ -151,7 +175,7 @@ const baseDefinitions = {
151
175
  })
152
176
  .returns(a.ref("UserRoleMutationResult"))
153
177
  .authorization((allow) => [allow.group(adminGroup)])
154
- .handler(a.handler.function(manageUserRole)),
178
+ .handler(functionHandler("manageUserRole", manageUserRole)),
155
179
 
156
180
  revokeUserRole: a
157
181
  .mutation()
@@ -163,7 +187,7 @@ const baseDefinitions = {
163
187
  })
164
188
  .returns(a.ref("UserRoleMutationResult"))
165
189
  .authorization((allow) => [allow.group(adminGroup)])
166
- .handler(a.handler.function(manageUserRole)),
190
+ .handler(functionHandler("manageUserRole", manageUserRole)),
167
191
 
168
192
  mergeUserProfiles: a
169
193
  .mutation()
@@ -176,13 +200,13 @@ const baseDefinitions = {
176
200
  })
177
201
  .returns(a.ref("UserDirectoryEntry"))
178
202
  .authorization((allow) => [allow.group(adminGroup)])
179
- .handler(a.handler.function(manageUserRole)),
203
+ .handler(functionHandler("manageUserRole", manageUserRole)),
180
204
 
181
205
  getReaderSettings: a
182
206
  .query()
183
207
  .returns(a.ref("ReaderSettingsResult"))
184
208
  .authorization((allow) => [allow.authenticated()])
185
- .handler(a.handler.function(readerSettings)),
209
+ .handler(functionHandler("readerSettings", readerSettings)),
186
210
 
187
211
  updateReaderSettings: a
188
212
  .mutation()
@@ -191,7 +215,7 @@ const baseDefinitions = {
191
215
  })
192
216
  .returns(a.ref("ReaderSettingsResult"))
193
217
  .authorization((allow) => [allow.authenticated()])
194
- .handler(a.handler.function(readerSettings)),
218
+ .handler(functionHandler("readerSettings", readerSettings)),
195
219
 
196
220
  SteeringActionResult: a.customType({
197
221
  ok: a.boolean().required(),
@@ -221,7 +245,7 @@ const baseDefinitions = {
221
245
  })
222
246
  .returns(a.ref("SteeringActionResult"))
223
247
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
224
- .handler(a.handler.function(categoryAction)),
248
+ .handler(functionHandler("categoryAction", categoryAction)),
225
249
 
226
250
  CurationDelegationResult: a.customType({
227
251
  ok: a.boolean().required(),
@@ -308,7 +332,7 @@ const baseDefinitions = {
308
332
  .authorization((allow) => [
309
333
  allow.groups(categoryWriteGroups),
310
334
  ])
311
- .handler(a.handler.function(categoryAction)),
335
+ .handler(functionHandler("categoryAction", categoryAction)),
312
336
 
313
337
  createCurationDelegation: a
314
338
  .mutation()
@@ -320,7 +344,7 @@ const baseDefinitions = {
320
344
  .authorization((allow) => [
321
345
  allow.groups(categoryWriteGroups),
322
346
  ])
323
- .handler(a.handler.function(categoryAction)),
347
+ .handler(functionHandler("categoryAction", categoryAction)),
324
348
 
325
349
  revokeCurationDelegation: a
326
350
  .mutation()
@@ -331,7 +355,7 @@ const baseDefinitions = {
331
355
  .authorization((allow) => [
332
356
  allow.groups(categoryWriteGroups),
333
357
  ])
334
- .handler(a.handler.function(categoryAction)),
358
+ .handler(functionHandler("categoryAction", categoryAction)),
335
359
 
336
360
  listCurationDelegations: a
337
361
  .query()
@@ -339,7 +363,7 @@ const baseDefinitions = {
339
363
  .authorization((allow) => [
340
364
  allow.groups(categoryWriteGroups),
341
365
  ])
342
- .handler(a.handler.function(categoryAction)),
366
+ .handler(functionHandler("categoryAction", categoryAction)),
343
367
 
344
368
  requestCurationDelegation: a
345
369
  .mutation()
@@ -353,7 +377,7 @@ const baseDefinitions = {
353
377
  .authorization((allow) => [
354
378
  allow.authenticated("identityPool"),
355
379
  ])
356
- .handler(a.handler.function(categoryAction)),
380
+ .handler(functionHandler("categoryAction", categoryAction)),
357
381
 
358
382
  approveCurationDelegation: a
359
383
  .mutation()
@@ -364,7 +388,7 @@ const baseDefinitions = {
364
388
  .authorization((allow) => [
365
389
  allow.groups(categoryWriteGroups),
366
390
  ])
367
- .handler(a.handler.function(categoryAction)),
391
+ .handler(functionHandler("categoryAction", categoryAction)),
368
392
 
369
393
  denyCurationDelegation: a
370
394
  .mutation()
@@ -375,7 +399,7 @@ const baseDefinitions = {
375
399
  .authorization((allow) => [
376
400
  allow.groups(categoryWriteGroups),
377
401
  ])
378
- .handler(a.handler.function(categoryAction)),
402
+ .handler(functionHandler("categoryAction", categoryAction)),
379
403
 
380
404
  getCurationDelegationStatus: a
381
405
  .query()
@@ -386,7 +410,7 @@ const baseDefinitions = {
386
410
  .authorization((allow) => [
387
411
  allow.authenticated("identityPool"),
388
412
  ])
389
- .handler(a.handler.function(categoryAction)),
413
+ .handler(functionHandler("categoryAction", categoryAction)),
390
414
 
391
415
  recordDelegatedCuration: a
392
416
  .mutation()
@@ -408,7 +432,7 @@ const baseDefinitions = {
408
432
  .authorization((allow) => [
409
433
  allow.authenticated("identityPool"),
410
434
  ])
411
- .handler(a.handler.function(categoryAction)),
435
+ .handler(functionHandler("categoryAction", categoryAction)),
412
436
 
413
437
  setReferenceQualityRating: a
414
438
  .mutation()
@@ -423,7 +447,7 @@ const baseDefinitions = {
423
447
  .authorization((allow) => [
424
448
  allow.groups(categoryWriteGroups),
425
449
  ])
426
- .handler(a.handler.function(categoryAction)),
450
+ .handler(functionHandler("categoryAction", categoryAction)),
427
451
 
428
452
  createCategorySetDraft: a
429
453
  .mutation()
@@ -435,7 +459,7 @@ const baseDefinitions = {
435
459
  })
436
460
  .returns(a.ref("CategorySetDraftActionResult"))
437
461
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
438
- .handler(a.handler.function(categoryAction)),
462
+ .handler(functionHandler("categoryAction", categoryAction)),
439
463
 
440
464
  promoteCategorySetDraft: a
441
465
  .mutation()
@@ -446,7 +470,7 @@ const baseDefinitions = {
446
470
  })
447
471
  .returns(a.ref("CategorySetDraftActionResult"))
448
472
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
449
- .handler(a.handler.function(categoryAction)),
473
+ .handler(functionHandler("categoryAction", categoryAction)),
450
474
 
451
475
  discardCategorySetDraft: a
452
476
  .mutation()
@@ -457,7 +481,7 @@ const baseDefinitions = {
457
481
  })
458
482
  .returns(a.ref("CategorySetDraftActionResult"))
459
483
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
460
- .handler(a.handler.function(categoryAction)),
484
+ .handler(functionHandler("categoryAction", categoryAction)),
461
485
 
462
486
  createDraftCategory: a
463
487
  .mutation()
@@ -473,7 +497,7 @@ const baseDefinitions = {
473
497
  })
474
498
  .returns(a.ref("SteeringActionResult"))
475
499
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
476
- .handler(a.handler.function(categoryAction)),
500
+ .handler(functionHandler("categoryAction", categoryAction)),
477
501
 
478
502
  updateDraftCategory: a
479
503
  .mutation()
@@ -489,7 +513,7 @@ const baseDefinitions = {
489
513
  })
490
514
  .returns(a.ref("SteeringActionResult"))
491
515
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
492
- .handler(a.handler.function(categoryAction)),
516
+ .handler(functionHandler("categoryAction", categoryAction)),
493
517
 
494
518
  archiveDraftCategory: a
495
519
  .mutation()
@@ -500,7 +524,7 @@ const baseDefinitions = {
500
524
  })
501
525
  .returns(a.ref("SteeringActionResult"))
502
526
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
503
- .handler(a.handler.function(categoryAction)),
527
+ .handler(functionHandler("categoryAction", categoryAction)),
504
528
 
505
529
  reviewReferenceTopicLabel: a
506
530
  .mutation()
@@ -514,7 +538,7 @@ const baseDefinitions = {
514
538
  })
515
539
  .returns(a.ref("TopicLabelActionResult"))
516
540
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
517
- .handler(a.handler.function(categoryAction)),
541
+ .handler(functionHandler("categoryAction", categoryAction)),
518
542
 
519
543
  NewsroomSummary: a.customType({
520
544
  generatedAt: a.datetime().required(),
@@ -534,49 +558,63 @@ const baseDefinitions = {
534
558
  .query()
535
559
  .returns(a.ref("NewsroomSummary"))
536
560
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
537
- .handler(a.handler.function(newsroomSummary)),
561
+ .handler(functionHandler("newsroomSummary", newsroomSummary)),
538
562
 
539
563
  deriveMarkus: a
540
564
  .query()
541
565
  .arguments({ input: a.json().required() })
542
566
  .returns(a.json())
543
567
  .authorization((allow) => [allow.groups(contentWriteGroups)])
544
- .handler(a.handler.function(contentActions)),
568
+ .handler(functionHandler("contentActions", contentActions)),
545
569
 
546
570
  intakePendingReferences: a
547
571
  .mutation()
548
572
  .arguments({ input: a.json().required() })
549
573
  .returns(a.json())
550
574
  .authorization((allow) => [allow.groups(contentWriteGroups)])
551
- .handler(a.handler.function(contentActions)),
575
+ .handler(functionHandler("contentActions", contentActions)),
576
+
577
+ intakeEmailSubmissionReferences: a
578
+ .mutation()
579
+ .arguments({ input: a.json().required() })
580
+ .returns(a.json())
581
+ .authorization((allow) => [allow.groups(contentWriteGroups)])
582
+ .handler(functionHandler("contentActions", contentActions)),
552
583
 
553
584
  saveItemDraft: a
554
585
  .mutation()
555
586
  .arguments({ input: a.json().required() })
556
587
  .returns(a.json())
557
588
  .authorization((allow) => [allow.groups(contentWriteGroups)])
558
- .handler(a.handler.function(contentActions)),
589
+ .handler(functionHandler("contentActions", contentActions)),
559
590
 
560
591
  publishItem: a
561
592
  .mutation()
562
593
  .arguments({ input: a.json().required() })
563
594
  .returns(a.json())
564
595
  .authorization((allow) => [allow.groups(contentWriteGroups)])
565
- .handler(a.handler.function(contentActions)),
596
+ .handler(functionHandler("contentActions", contentActions)),
597
+
598
+ moveStoryStage: a
599
+ .mutation()
600
+ .arguments({ input: a.json().required() })
601
+ .returns(a.json())
602
+ .authorization((allow) => [allow.groups(contentWriteGroups)])
603
+ .handler(functionHandler("contentActions", contentActions)),
566
604
 
567
605
  unpublishItem: a
568
606
  .mutation()
569
607
  .arguments({ input: a.json().required() })
570
608
  .returns(a.json())
571
609
  .authorization((allow) => [allow.groups(contentWriteGroups)])
572
- .handler(a.handler.function(contentActions)),
610
+ .handler(functionHandler("contentActions", contentActions)),
573
611
 
574
612
  requestStagingBuild: a
575
613
  .mutation()
576
614
  .arguments({ input: a.json().required() })
577
615
  .returns(a.json())
578
616
  .authorization((allow) => [allow.groups(contentWriteGroups)])
579
- .handler(a.handler.function(contentActions)),
617
+ .handler(functionHandler("contentActions", contentActions)),
580
618
 
581
619
  knowledgeQuery: a
582
620
  .query()
@@ -585,7 +623,7 @@ const baseDefinitions = {
585
623
  })
586
624
  .returns(a.json())
587
625
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
588
- .handler(a.handler.function(knowledgeQuery)),
626
+ .handler(functionHandler("knowledgeQuery", knowledgeQuery)),
589
627
 
590
628
  updateNewsroomSummary: a
591
629
  .mutation()
@@ -596,7 +634,7 @@ const baseDefinitions = {
596
634
  })
597
635
  .returns(a.ref("NewsroomSummary"))
598
636
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
599
- .handler(a.handler.function(newsroomSummary)),
637
+ .handler(functionHandler("newsroomSummary", newsroomSummary)),
600
638
 
601
639
  ModelAttachmentUploadSlot: a.customType({
602
640
  ok: a.boolean().required(),
@@ -656,7 +694,7 @@ const baseDefinitions = {
656
694
  })
657
695
  .returns(a.ref("ModelAttachmentUploadSlot"))
658
696
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
659
- .handler(a.handler.function(modelAttachmentUpload)),
697
+ .handler(functionHandler("modelAttachmentUpload", modelAttachmentUpload)),
660
698
 
661
699
  completeModelAttachmentUpload: a
662
700
  .mutation()
@@ -678,7 +716,7 @@ const baseDefinitions = {
678
716
  })
679
717
  .returns(a.ref("ModelAttachment"))
680
718
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
681
- .handler(a.handler.function(modelAttachmentUpload)),
719
+ .handler(functionHandler("modelAttachmentUpload", modelAttachmentUpload)),
682
720
 
683
721
  abortModelAttachmentUpload: a
684
722
  .mutation()
@@ -700,7 +738,7 @@ const baseDefinitions = {
700
738
  })
701
739
  .returns(a.ref("ModelAttachmentUploadAbortResult"))
702
740
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
703
- .handler(a.handler.function(modelAttachmentUpload)),
741
+ .handler(functionHandler("modelAttachmentUpload", modelAttachmentUpload)),
704
742
 
705
743
  createModelAttachmentDownload: a
706
744
  .mutation()
@@ -709,7 +747,7 @@ const baseDefinitions = {
709
747
  })
710
748
  .returns(a.ref("ModelAttachmentDownloadSlot"))
711
749
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
712
- .handler(a.handler.function(modelAttachmentUpload)),
750
+ .handler(functionHandler("modelAttachmentUpload", modelAttachmentUpload)),
713
751
 
714
752
  AssignmentActionResult: a.customType({
715
753
  ok: a.boolean().required(),
@@ -804,7 +842,7 @@ const baseDefinitions = {
804
842
  })
805
843
  .returns(a.ref("AssignmentContext").array().required())
806
844
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
807
- .handler(a.handler.function(assignmentAction)),
845
+ .handler(functionHandler("assignmentAction", assignmentAction)),
808
846
 
809
847
  listAssignmentQueue: a
810
848
  .query()
@@ -815,7 +853,7 @@ const baseDefinitions = {
815
853
  })
816
854
  .returns(a.ref("AssignmentContext").array().required())
817
855
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
818
- .handler(a.handler.function(assignmentAction)),
856
+ .handler(functionHandler("assignmentAction", assignmentAction)),
819
857
 
820
858
  getEditorialContext: a
821
859
  .query()
@@ -825,10 +863,11 @@ const baseDefinitions = {
825
863
  storyLineageId: a.id(),
826
864
  assignmentId: a.id(),
827
865
  maxCharacters: a.integer(),
866
+ optionalPublicationDoctrine: a.boolean(),
828
867
  })
829
868
  .returns(a.json().required())
830
869
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
831
- .handler(a.handler.function(assignmentAction)),
870
+ .handler(functionHandler("assignmentAction", assignmentAction)),
832
871
 
833
872
  getAssignmentContext: a
834
873
  .query()
@@ -837,7 +876,7 @@ const baseDefinitions = {
837
876
  })
838
877
  .returns(a.ref("AssignmentContext"))
839
878
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
840
- .handler(a.handler.function(assignmentAction)),
879
+ .handler(functionHandler("assignmentAction", assignmentAction)),
841
880
 
842
881
  claimAssignment: a
843
882
  .mutation()
@@ -854,7 +893,7 @@ const baseDefinitions = {
854
893
  })
855
894
  .returns(a.ref("AssignmentActionResult"))
856
895
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
857
- .handler(a.handler.function(assignmentAction)),
896
+ .handler(functionHandler("assignmentAction", assignmentAction)),
858
897
 
859
898
  releaseAssignment: a
860
899
  .mutation()
@@ -866,7 +905,7 @@ const baseDefinitions = {
866
905
  })
867
906
  .returns(a.ref("AssignmentActionResult"))
868
907
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
869
- .handler(a.handler.function(assignmentAction)),
908
+ .handler(functionHandler("assignmentAction", assignmentAction)),
870
909
 
871
910
  completeAssignment: a
872
911
  .mutation()
@@ -878,7 +917,7 @@ const baseDefinitions = {
878
917
  })
879
918
  .returns(a.ref("AssignmentActionResult"))
880
919
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
881
- .handler(a.handler.function(assignmentAction)),
920
+ .handler(functionHandler("assignmentAction", assignmentAction)),
882
921
 
883
922
  cancelAssignment: a
884
923
  .mutation()
@@ -890,7 +929,7 @@ const baseDefinitions = {
890
929
  })
891
930
  .returns(a.ref("AssignmentActionResult"))
892
931
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
893
- .handler(a.handler.function(assignmentAction)),
932
+ .handler(functionHandler("assignmentAction", assignmentAction)),
894
933
 
895
934
  reopenAssignment: a
896
935
  .mutation()
@@ -902,7 +941,7 @@ const baseDefinitions = {
902
941
  })
903
942
  .returns(a.ref("AssignmentActionResult"))
904
943
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
905
- .handler(a.handler.function(assignmentAction)),
944
+ .handler(functionHandler("assignmentAction", assignmentAction)),
906
945
 
907
946
  retryImmediateAssignment: a
908
947
  .mutation()
@@ -914,13 +953,13 @@ const baseDefinitions = {
914
953
  })
915
954
  .returns(a.ref("AssignmentActionResult"))
916
955
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
917
- .handler(a.handler.function(assignmentAction)),
956
+ .handler(functionHandler("assignmentAction", assignmentAction)),
918
957
 
919
958
  listNewsroomProcedureDefinitions: a
920
959
  .query()
921
960
  .returns(a.json())
922
961
  .authorization((allow) => [allow.group(adminGroup)])
923
- .handler(a.handler.function(procedureAction)),
962
+ .handler(functionHandler("procedureAction", procedureAction)),
924
963
 
925
964
  getNewsroomProcedureDefinition: a
926
965
  .query()
@@ -930,7 +969,7 @@ const baseDefinitions = {
930
969
  })
931
970
  .returns(a.json())
932
971
  .authorization((allow) => [allow.group(adminGroup)])
933
- .handler(a.handler.function(procedureAction)),
972
+ .handler(functionHandler("procedureAction", procedureAction)),
934
973
 
935
974
  saveNewsroomProcedureDefinition: a
936
975
  .mutation()
@@ -939,7 +978,7 @@ const baseDefinitions = {
939
978
  })
940
979
  .returns(a.json())
941
980
  .authorization((allow) => [allow.group(adminGroup)])
942
- .handler(a.handler.function(procedureAction)),
981
+ .handler(functionHandler("procedureAction", procedureAction)),
943
982
 
944
983
  saveNewsroomProcedureVersionDraft: a
945
984
  .mutation()
@@ -948,7 +987,7 @@ const baseDefinitions = {
948
987
  })
949
988
  .returns(a.json())
950
989
  .authorization((allow) => [allow.group(adminGroup)])
951
- .handler(a.handler.function(procedureAction)),
990
+ .handler(functionHandler("procedureAction", procedureAction)),
952
991
 
953
992
  publishNewsroomProcedureVersion: a
954
993
  .mutation()
@@ -957,7 +996,7 @@ const baseDefinitions = {
957
996
  })
958
997
  .returns(a.json())
959
998
  .authorization((allow) => [allow.group(adminGroup)])
960
- .handler(a.handler.function(procedureAction)),
999
+ .handler(functionHandler("procedureAction", procedureAction)),
961
1000
 
962
1001
  startNewsroomProcedureRun: a
963
1002
  .mutation()
@@ -972,7 +1011,7 @@ const baseDefinitions = {
972
1011
  })
973
1012
  .returns(a.json())
974
1013
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
975
- .handler(a.handler.function(procedureAction)),
1014
+ .handler(functionHandler("procedureAction", procedureAction)),
976
1015
 
977
1016
  getNewsroomProcedureRun: a
978
1017
  .query()
@@ -981,7 +1020,7 @@ const baseDefinitions = {
981
1020
  })
982
1021
  .returns(a.json())
983
1022
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
984
- .handler(a.handler.function(procedureAction)),
1023
+ .handler(functionHandler("procedureAction", procedureAction)),
985
1024
 
986
1025
  listNewsroomProcedureRunsByProcedure: a
987
1026
  .query()
@@ -990,7 +1029,7 @@ const baseDefinitions = {
990
1029
  })
991
1030
  .returns(a.json())
992
1031
  .authorization((allow) => [allow.groups(categoryWriteGroups)])
993
- .handler(a.handler.function(procedureAction)),
1032
+ .handler(functionHandler("procedureAction", procedureAction)),
994
1033
 
995
1034
  Assignment: modelWithoutSubscriptions({
996
1035
  id: a.id().required(),
@@ -1134,6 +1173,8 @@ const baseDefinitions = {
1134
1173
  error: a.json(),
1135
1174
  attempt: a.integer(),
1136
1175
  newsroomFeedKey: a.string(),
1176
+ usage: a.json(),
1177
+ costUsd: a.float(),
1137
1178
  })
1138
1179
  .secondaryIndexes((index) => [
1139
1180
  index("procedureId").sortKeys(["requestedAt"]).queryField("listProcedureRunsByProcedureAndRequestedAt"),
@@ -1146,6 +1187,74 @@ const baseDefinitions = {
1146
1187
  allow.group(adminGroup).to(authoringOperations),
1147
1188
  ]),
1148
1189
 
1190
+ /** A named "when X happens, run procedure Y" (PPY-9ff95b). Step 1 mirrors the monitoring router's procedureTriggers and starts nothing itself. */
1191
+ Automation: modelWithoutSubscriptions({
1192
+ id: a.id().required(),
1193
+ title: a.string().required(),
1194
+ description: a.string(),
1195
+ enabled: a.boolean().required(),
1196
+ trigger: a.json().required(),
1197
+ procedureKey: a.string().required(),
1198
+ inputTemplate: a.json(),
1199
+ limits: a.json(),
1200
+ createdBy: a.string(),
1201
+ createdAt: a.datetime().required(),
1202
+ updatedBy: a.string(),
1203
+ updatedAt: a.datetime().required(),
1204
+ })
1205
+ .authorization((allow) => [
1206
+ allow.group("editor").to(["read", "create", "update"]),
1207
+ allow.group(adminGroup).to(authoringOperations),
1208
+ ]),
1209
+
1210
+ /** A human review point raised by a step on any item (PPY-ab6a50). Review is not a story state. */
1211
+ ReviewRequest: modelWithoutSubscriptions({
1212
+ id: a.id().required(),
1213
+ subject: a.json().required(),
1214
+ mode: a.string().required(),
1215
+ reason: a.string().required(),
1216
+ ask: a.string(),
1217
+ raisedBy: a.string().required(),
1218
+ raisedAt: a.datetime().required(),
1219
+ deadline: a.datetime(),
1220
+ state: a.string().required(),
1221
+ answer: a.json(),
1222
+ links: a.json(),
1223
+ history: a.json(),
1224
+ appliedIn: a.json(),
1225
+ updatedAt: a.datetime().required(),
1226
+ })
1227
+ .authorization((allow) => [
1228
+ allow.group("editor").to(["read", "create", "update"]),
1229
+ allow.group(adminGroup).to(authoringOperations),
1230
+ ]),
1231
+
1232
+ /** One user's read mark on one review request; id is "<userKey>#<requestId>". */
1233
+ ReviewReadMark: modelWithoutSubscriptions({
1234
+ id: a.id().required(),
1235
+ requestId: a.string().required(),
1236
+ userKey: a.string().required(),
1237
+ readAt: a.datetime().required(),
1238
+ })
1239
+ .authorization((allow) => [
1240
+ allow.groups(["editor", adminGroup]).to(["read", "create", "update"]),
1241
+ ]),
1242
+
1243
+ /** Who is told about review requests: scope default, mode or automation. Changed by data, not code. */
1244
+ ReviewRecipientRule: modelWithoutSubscriptions({
1245
+ id: a.id().required(),
1246
+ scope: a.string().required(),
1247
+ key: a.string(),
1248
+ roles: a.string().array(),
1249
+ emails: a.string().array(),
1250
+ updatedBy: a.string(),
1251
+ updatedAt: a.datetime().required(),
1252
+ })
1253
+ .authorization((allow) => [
1254
+ allow.group("editor").to(["read"]),
1255
+ allow.group(adminGroup).to(authoringOperations),
1256
+ ]),
1257
+
1149
1258
  NewsroomSection: modelWithoutSubscriptions({
1150
1259
  id: a.id().required(),
1151
1260
  tenantId: a.string(),
@@ -1790,7 +1899,7 @@ const baseDefinitions = {
1790
1899
  updatedAt: a.datetime(),
1791
1900
  tags: a.hasMany("ItemTag", "itemId"),
1792
1901
  mediaAssets: a.hasMany("MediaAsset", "itemId"),
1793
- editionItems: a.hasMany("EditionItem", "itemId"),
1902
+ ...(includeEditions ? { editionItems: a.hasMany("EditionItem", "itemId") } : {}),
1794
1903
  })
1795
1904
  .secondaryIndexes((index) => [
1796
1905
  index("lineageId").sortKeys(["versionNumber"]).queryField("listItemsByLineageAndVersion"),
@@ -2114,21 +2223,25 @@ const baseDefinitions = {
2114
2223
  allow.groups(contentWriteGroups),
2115
2224
  ]),
2116
2225
  ...editorialChecksSchemaDefinitions,
2226
+ ...monitoringViewSchemaDefinitions,
2227
+ ...automationViewSchemaDefinitions,
2117
2228
  };
2229
+ if (!includeEditions) {
2230
+ const mutableDefinitions = definitions as Record<string, unknown>;
2231
+ for (const modelName of OPTIONAL_MODEL_GROUPS.editions) delete mutableDefinitions[modelName];
2232
+ }
2233
+ return definitions;
2234
+ }
2118
2235
 
2119
- export const schema = a.schema(baseDefinitions).authorization((allow) => [
2120
- allow.resource(assignmentAction).to(["query", "mutate"]),
2121
- allow.resource(categoryAction),
2122
- allow.resource(contentActions),
2123
- allow.resource(manageUserRole),
2124
- allow.resource(modelAttachmentUpload),
2125
- allow.resource(newsroomSummary),
2126
- allow.resource(procedureAction),
2127
- ]);
2236
+ export function baseModelNames(excludedGroups: readonly OptionalModelGroup[] = []): string[] {
2237
+ return Object.keys(buildBaseDefinitions(!excludedGroups.includes("editions")));
2238
+ }
2128
2239
 
2129
- /** The deployed schema of a site that enables plugins: the base definitions plus what each plugin contributes (docs/plugins.md). */
2130
- export function schemaWithPlugins(pluginDefinitions: Record<string, any>) {
2131
- return a.schema({ ...baseDefinitions, ...pluginDefinitions } as typeof baseDefinitions).authorization((allow) => [
2240
+ const baseDefinitions = buildBaseDefinitions(true);
2241
+
2242
+ /** Schema-level function grants shared by every deployed schema, with or without plugins, so none can drop one. */
2243
+ function functionGrants(allow: any) {
2244
+ return [
2132
2245
  allow.resource(assignmentAction).to(["query", "mutate"]),
2133
2246
  allow.resource(categoryAction),
2134
2247
  allow.resource(contentActions),
@@ -2136,7 +2249,21 @@ export function schemaWithPlugins(pluginDefinitions: Record<string, any>) {
2136
2249
  allow.resource(modelAttachmentUpload),
2137
2250
  allow.resource(newsroomSummary),
2138
2251
  allow.resource(procedureAction),
2139
- ]);
2252
+ allow.resource(publicForms).to(["mutate"]),
2253
+ ];
2254
+ }
2255
+
2256
+ export const schema = a.schema(baseDefinitions).authorization(functionGrants);
2257
+
2258
+ /** The deployed schema of a site that enables plugins: the base definitions plus what each plugin contributes (docs/plugins.md). */
2259
+ export function schemaWithPlugins(pluginDefinitions: Record<string, any>) {
2260
+ return a.schema({ ...baseDefinitions, ...pluginDefinitions } as typeof baseDefinitions).authorization(functionGrants);
2261
+ }
2262
+
2263
+ /** The schema of a site that leaves optional model groups out of its first deploy. */
2264
+ export function schemaExcludingGroups(excludedGroups: readonly OptionalModelGroup[], pluginDefinitions: Record<string, any> = {}) {
2265
+ const definitions = buildBaseDefinitions(!excludedGroups.includes("editions")) as unknown as typeof baseDefinitions;
2266
+ return a.schema({ ...definitions, ...pluginDefinitions } as typeof baseDefinitions).authorization(functionGrants);
2140
2267
  }
2141
2268
 
2142
2269
  export type Schema = ClientSchema<typeof schema>;