dineway 0.2.33 → 0.2.34
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/dist/{activity-CfryM8jO.mjs → activity-CZnq5YlZ.mjs} +2 -2
- package/dist/{activity-events-BVo9rMUz.mjs → activity-events-D-yGV7cW.mjs} +1 -1
- package/dist/{actor-DrJJsvy6.mjs → actor-DxUAJgQX.mjs} +20 -6
- package/dist/{adapters-DHt3f2lu.d.mts → adapters-BQ8CQbBm.d.mts} +5 -7
- package/dist/after-BVaUn7bK.mjs +24 -0
- package/dist/{allowed-origins-DGSyhRCz.mjs → allowed-origins-DV3LWuWW.mjs} +1 -1
- package/dist/api/route-utils.d.mts +10 -10
- package/dist/api/route-utils.mjs +23 -19
- package/dist/api/schemas/index.d.mts +1 -1
- package/dist/api/schemas/index.mjs +5 -5
- package/dist/{api-CTf1SLmg.mjs → api-CL4pG2zf.mjs} +55 -1215
- package/dist/api-tokens-D5K_Csub.mjs +3 -0
- package/dist/{api-tokens-CSomx-l3.mjs → api-tokens-_6tMD1W4.mjs} +1 -1
- package/dist/{apply-Bs2jXsms.mjs → apply-CYLUMiZg.mjs} +109 -93
- package/dist/astro/index.d.mts +16 -12
- package/dist/astro/index.mjs +50 -9
- package/dist/astro/middleware/auth.d.mts +9 -9
- package/dist/astro/middleware/auth.mjs +29 -8
- package/dist/astro/middleware/redirect.mjs +8 -7
- package/dist/astro/middleware/request-context.mjs +17 -10
- package/dist/astro/middleware/seed.d.mts +1 -1
- package/dist/astro/middleware/seed.mjs +93 -71
- package/dist/astro/middleware/setup.mjs +1 -1
- package/dist/astro/middleware/workers.d.mts +6 -0
- package/dist/astro/middleware/workers.mjs +8 -0
- package/dist/astro/middleware.mjs +288 -159
- package/dist/astro/routes/api/admin/allowed-domains/_domain_.mjs +7 -7
- package/dist/astro/routes/api/admin/allowed-domains/index.mjs +7 -7
- package/dist/astro/routes/api/admin/api-tokens/_id_.mjs +4 -4
- package/dist/astro/routes/api/admin/api-tokens/index.mjs +7 -7
- package/dist/astro/routes/api/admin/briefing.mjs +25 -23
- package/dist/astro/routes/api/admin/byline-fields/_slug_/usage.mjs +5 -4
- package/dist/astro/routes/api/admin/byline-fields/_slug_.mjs +11 -10
- package/dist/astro/routes/api/admin/byline-fields/index.mjs +11 -10
- package/dist/astro/routes/api/admin/byline-fields/reorder.mjs +11 -10
- package/dist/astro/routes/api/admin/bylines/_id_/index.mjs +22 -20
- package/dist/astro/routes/api/admin/bylines/_id_/translations.mjs +22 -20
- package/dist/astro/routes/api/admin/bylines/index.mjs +22 -20
- package/dist/astro/routes/api/admin/comments/_id_/status.mjs +17 -16
- package/dist/astro/routes/api/admin/comments/_id_.mjs +8 -7
- package/dist/astro/routes/api/admin/comments/bulk.mjs +14 -13
- package/dist/astro/routes/api/admin/comments/counts.mjs +8 -7
- package/dist/astro/routes/api/admin/comments/index.mjs +14 -13
- package/dist/astro/routes/api/admin/context/_id_/history.mjs +43 -31
- package/dist/astro/routes/api/admin/context/_id_/index.mjs +43 -31
- package/dist/astro/routes/api/admin/context/_id_/review.mjs +48 -36
- package/dist/astro/routes/api/admin/context/_id_/supersede.mjs +48 -36
- package/dist/astro/routes/api/admin/context/diff.mjs +47 -35
- package/dist/astro/routes/api/admin/context/index.mjs +48 -36
- package/dist/astro/routes/api/admin/context/stale.mjs +47 -35
- package/dist/astro/routes/api/admin/hitl-requests/_id_/index.mjs +43 -31
- package/dist/astro/routes/api/admin/hitl-requests/_id_/resolve.mjs +47 -35
- package/dist/astro/routes/api/admin/hitl-requests/index.mjs +47 -35
- package/dist/astro/routes/api/admin/hooks/exclusive/_hookName_.mjs +44 -32
- package/dist/astro/routes/api/admin/hooks/exclusive/index.mjs +3 -3
- package/dist/astro/routes/api/admin/oauth-clients/_id_.mjs +7 -7
- package/dist/astro/routes/api/admin/oauth-clients/index.mjs +7 -7
- package/dist/astro/routes/api/admin/plugins/_id_/disable.mjs +72 -66
- package/dist/astro/routes/api/admin/plugins/_id_/enable.mjs +72 -66
- package/dist/astro/routes/api/admin/plugins/_id_/index.mjs +64 -58
- package/dist/astro/routes/api/admin/plugins/_id_/uninstall.mjs +71 -65
- package/dist/astro/routes/api/admin/plugins/_id_/update.mjs +71 -65
- package/dist/astro/routes/api/admin/plugins/index.mjs +64 -58
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/icon.mjs +2 -2
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/index.mjs +64 -58
- package/dist/astro/routes/api/admin/plugins/marketplace/_id_/install.mjs +71 -65
- package/dist/astro/routes/api/admin/plugins/marketplace/index.mjs +64 -58
- package/dist/astro/routes/api/admin/plugins/updates.mjs +64 -58
- package/dist/astro/routes/api/admin/review-requests/_id_/image.mjs +26 -23
- package/dist/astro/routes/api/admin/review-requests/_id_/index.mjs +33 -25
- package/dist/astro/routes/api/admin/review-requests/_id_/resolve.mjs +56 -43
- package/dist/astro/routes/api/admin/review-requests/_id_/revoke.mjs +10 -9
- package/dist/astro/routes/api/admin/review-requests/index.mjs +54 -41
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/index.mjs +64 -58
- package/dist/astro/routes/api/admin/themes/marketplace/_id_/thumbnail.mjs +2 -2
- package/dist/astro/routes/api/admin/themes/marketplace/index.mjs +64 -58
- package/dist/astro/routes/api/admin/users/_id_/disable.mjs +20 -12
- package/dist/astro/routes/api/admin/users/_id_/enable.mjs +1 -1
- package/dist/astro/routes/api/admin/users/_id_/index.mjs +40 -32
- package/dist/astro/routes/api/admin/users/_id_/send-recovery.mjs +3 -3
- package/dist/astro/routes/api/admin/users/index.mjs +7 -7
- package/dist/astro/routes/api/auth/dev-bypass.mjs +6 -5
- package/dist/astro/routes/api/auth/invite/accept.mjs +1 -1
- package/dist/astro/routes/api/auth/invite/complete.mjs +12 -12
- package/dist/astro/routes/api/auth/invite/index.mjs +9 -9
- package/dist/astro/routes/api/auth/invite/register-options.mjs +11 -11
- package/dist/astro/routes/api/auth/logout.mjs +2 -2
- package/dist/astro/routes/api/auth/magic-link/send.mjs +12 -11
- package/dist/astro/routes/api/auth/magic-link/verify.mjs +2 -2
- package/dist/astro/routes/api/auth/me.mjs +11 -11
- package/dist/astro/routes/api/auth/mode.mjs +1 -1
- package/dist/astro/routes/api/auth/oauth/_provider_/callback.mjs +5 -4
- package/dist/astro/routes/api/auth/oauth/_provider_.mjs +5 -4
- package/dist/astro/routes/api/auth/passkey/_id_.mjs +7 -7
- package/dist/astro/routes/api/auth/passkey/index.mjs +1 -1
- package/dist/astro/routes/api/auth/passkey/options.mjs +14 -13
- package/dist/astro/routes/api/auth/passkey/register/options.mjs +11 -11
- package/dist/astro/routes/api/auth/passkey/register/verify.mjs +12 -12
- package/dist/astro/routes/api/auth/passkey/verify.mjs +12 -12
- package/dist/astro/routes/api/auth/setup-token/index.mjs +32 -23
- package/dist/astro/routes/api/auth/setup-token/verify.mjs +32 -26
- package/dist/astro/routes/api/auth/signup/complete.mjs +12 -12
- package/dist/astro/routes/api/auth/signup/request.mjs +12 -11
- package/dist/astro/routes/api/auth/signup/verify.mjs +1 -1
- package/dist/astro/routes/api/comments/_collection_/_contentId_/index.mjs +21 -18
- package/dist/astro/routes/api/comments/_collection_/_contentId_/reactions.mjs +19 -16
- package/dist/astro/routes/api/content/_collection_/_id_/compare.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/discard-draft.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_/duplicate.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_/permanent.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_/preview-url.mjs +24 -21
- package/dist/astro/routes/api/content/_collection_/_id_/publish.mjs +35 -22
- package/dist/astro/routes/api/content/_collection_/_id_/release-readiness.mjs +9 -9
- package/dist/astro/routes/api/content/_collection_/_id_/restore.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_/revisions.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/schedule.mjs +35 -22
- package/dist/astro/routes/api/content/_collection_/_id_/terms/_taxonomy_.mjs +23 -19
- package/dist/astro/routes/api/content/_collection_/_id_/translations.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/_id_/unpublish.mjs +8 -7
- package/dist/astro/routes/api/content/_collection_/_id_.mjs +14 -13
- package/dist/astro/routes/api/content/_collection_/authors.mjs +2 -2
- package/dist/astro/routes/api/content/_collection_/index.mjs +14 -13
- package/dist/astro/routes/api/content/_collection_/trash.mjs +8 -8
- package/dist/astro/routes/api/dashboard.mjs +16 -11
- package/dist/astro/routes/api/dev/emails.mjs +2 -2
- package/dist/astro/routes/api/health.mjs +1 -1
- package/dist/astro/routes/api/import/probe.d.mts +3 -3
- package/dist/astro/routes/api/import/probe.mjs +25 -24
- package/dist/astro/routes/api/import/wordpress/analyze.mjs +12 -11
- package/dist/astro/routes/api/import/wordpress/execute.d.mts +9 -9
- package/dist/astro/routes/api/import/wordpress/execute.mjs +51 -42
- package/dist/astro/routes/api/import/wordpress/media.d.mts +9 -9
- package/dist/astro/routes/api/import/wordpress/media.mjs +14 -14
- package/dist/astro/routes/api/import/wordpress/prepare.mjs +52 -40
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.d.mts +10 -10
- package/dist/astro/routes/api/import/wordpress/rewrite-urls.mjs +50 -38
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.d.mts +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/analyze.mjs +29 -27
- package/dist/astro/routes/api/import/wordpress-plugin/callback.mjs +1 -1
- package/dist/astro/routes/api/import/wordpress-plugin/execute.d.mts +9 -9
- package/dist/astro/routes/api/import/wordpress-plugin/execute.mjs +56 -47
- package/dist/astro/routes/api/integration/artifact.mjs +11 -8
- package/dist/astro/routes/api/integration/dispatch.mjs +17 -14
- package/dist/astro/routes/api/integrations/_provider_.mjs +11 -8
- package/dist/astro/routes/api/integrations/index.mjs +10 -7
- package/dist/astro/routes/api/manifest.mjs +5 -5
- package/dist/astro/routes/api/mcp.mjs +98 -88
- package/dist/astro/routes/api/media/_id_/confirm.mjs +12 -12
- package/dist/astro/routes/api/media/_id_.mjs +9 -9
- package/dist/astro/routes/api/media/file/_...key_.mjs +1 -1
- package/dist/astro/routes/api/media/providers/_providerId_/_itemId_.mjs +2 -2
- package/dist/astro/routes/api/media/providers/_providerId_/index.mjs +2 -2
- package/dist/astro/routes/api/media/providers/index.mjs +2 -2
- package/dist/astro/routes/api/media/upload-url.mjs +13 -13
- package/dist/astro/routes/api/media.mjs +16 -16
- package/dist/astro/routes/api/menus/_name_/items/_id_.mjs +48 -36
- package/dist/astro/routes/api/menus/_name_/items.mjs +48 -36
- package/dist/astro/routes/api/menus/_name_/reorder.mjs +48 -36
- package/dist/astro/routes/api/menus/_name_/translations.mjs +48 -36
- package/dist/astro/routes/api/menus/_name_.mjs +48 -36
- package/dist/astro/routes/api/menus/index.mjs +48 -36
- package/dist/astro/routes/api/oauth/authorize.mjs +9 -7
- package/dist/astro/routes/api/oauth/device/authorize.mjs +7 -6
- package/dist/astro/routes/api/oauth/device/code.mjs +11 -9
- package/dist/astro/routes/api/oauth/device/token.mjs +10 -8
- package/dist/astro/routes/api/oauth/register.mjs +4 -4
- package/dist/astro/routes/api/oauth/token/refresh.mjs +7 -6
- package/dist/astro/routes/api/oauth/token/revoke.mjs +7 -6
- package/dist/astro/routes/api/oauth/token.mjs +8 -6
- package/dist/astro/routes/api/openapi.json.mjs +5 -5
- package/dist/astro/routes/api/plugins/_pluginId_/_...path_.mjs +4 -4
- package/dist/astro/routes/api/redirects/404s/index.mjs +15 -14
- package/dist/astro/routes/api/redirects/404s/summary.mjs +15 -14
- package/dist/astro/routes/api/redirects/_id_.mjs +48 -37
- package/dist/astro/routes/api/redirects/index.mjs +48 -37
- package/dist/astro/routes/api/revisions/_revisionId_/index.mjs +2 -2
- package/dist/astro/routes/api/revisions/_revisionId_/restore.mjs +2 -2
- package/dist/astro/routes/api/schema/collections/_slug_/fields/_fieldSlug_.mjs +66 -60
- package/dist/astro/routes/api/schema/collections/_slug_/fields/index.mjs +66 -60
- package/dist/astro/routes/api/schema/collections/_slug_/fields/reorder.mjs +66 -60
- package/dist/astro/routes/api/schema/collections/_slug_/index.mjs +66 -60
- package/dist/astro/routes/api/schema/collections/index.mjs +66 -60
- package/dist/astro/routes/api/schema/index.mjs +12 -11
- package/dist/astro/routes/api/schema/orphans/_slug_.mjs +64 -58
- package/dist/astro/routes/api/schema/orphans/index.mjs +64 -58
- package/dist/astro/routes/api/search/enable.mjs +15 -14
- package/dist/astro/routes/api/search/index.mjs +14 -13
- package/dist/astro/routes/api/search/rebuild.mjs +15 -14
- package/dist/astro/routes/api/search/stats.mjs +9 -8
- package/dist/astro/routes/api/search/suggest.mjs +14 -13
- package/dist/astro/routes/api/sections/_slug_.mjs +48 -36
- package/dist/astro/routes/api/sections/index.mjs +48 -36
- package/dist/astro/routes/api/settings/email.mjs +5 -5
- package/dist/astro/routes/api/settings/reviews.mjs +11 -10
- package/dist/astro/routes/api/settings.mjs +48 -36
- package/dist/astro/routes/api/setup/admin-verify.mjs +14 -14
- package/dist/astro/routes/api/setup/admin.mjs +12 -12
- package/dist/astro/routes/api/setup/dev-bypass.mjs +35 -31
- package/dist/astro/routes/api/setup/dev-reset.mjs +2 -2
- package/dist/astro/routes/api/setup/index.mjs +37 -33
- package/dist/astro/routes/api/setup/status.mjs +3 -3
- package/dist/astro/routes/api/snapshot.mjs +11 -9
- package/dist/astro/routes/api/system/heartbeat.mjs +2 -2
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_/translations.mjs +51 -39
- package/dist/astro/routes/api/taxonomies/_name_/terms/_slug_.mjs +51 -39
- package/dist/astro/routes/api/taxonomies/_name_/terms/index.mjs +51 -39
- package/dist/astro/routes/api/taxonomies/index.mjs +51 -39
- package/dist/astro/routes/api/themes/preview.mjs +8 -6
- package/dist/astro/routes/api/typegen.mjs +4 -4
- package/dist/astro/routes/api/well-known/auth.mjs +3 -3
- package/dist/astro/routes/api/well-known/oauth-authorization-server.mjs +3 -3
- package/dist/astro/routes/api/well-known/oauth-protected-resource.mjs +3 -3
- package/dist/astro/routes/api/widget-areas/_name_/reorder.mjs +47 -35
- package/dist/astro/routes/api/widget-areas/_name_/widgets/_id_.mjs +48 -36
- package/dist/astro/routes/api/widget-areas/_name_/widgets.mjs +48 -36
- package/dist/astro/routes/api/widget-areas/_name_.mjs +45 -33
- package/dist/astro/routes/api/widget-areas/index.mjs +48 -36
- package/dist/astro/routes/api/widget-components.mjs +2 -2
- package/dist/astro/routes/robots.txt.mjs +11 -10
- package/dist/astro/routes/sitemap-_collection_.xml.mjs +20 -18
- package/dist/astro/routes/sitemap.xml.mjs +19 -17
- package/dist/astro/session-driver.d.mts +1 -1
- package/dist/astro/session-driver.mjs +4 -4
- package/dist/astro/types.d.mts +13 -13
- package/dist/atomic-authority-CnBQJ14T.mjs +33 -0
- package/dist/{audit-CYjfxG9i.mjs → audit-F5iWkbcJ.mjs} +11 -4
- package/dist/auth/providers/github.d.mts +1 -1
- package/dist/auth/providers/google.d.mts +1 -1
- package/dist/{auth-control-guard-CITT8ZA_.mjs → auth-control-guard-D4WW-wFF.mjs} +1 -1
- package/dist/{authorize-KcI0pAfN.mjs → authorize-EnP57AQl.mjs} +1 -1
- package/dist/{briefing-r3hXCDQC.mjs → briefing-BXsVwd4P.mjs} +1 -1
- package/dist/{briefing-BgQTljQt.mjs → briefing-CkCi6S-W.mjs} +445 -447
- package/dist/{bundle-S6zx-V4D.mjs → bundle-Cgak1zGE.mjs} +3 -3
- package/dist/{byline-Ctil4rij.mjs → byline-DEZKlzD9.mjs} +107 -113
- package/dist/{byline-fields-QpmruT5r.mjs → byline-fields-BGEIA9dZ.mjs} +3 -3
- package/dist/{byline-fields-51ja6JDa.d.mts → byline-fields-BmkhEDFF.d.mts} +10 -10
- package/dist/{byline-fields-DiCyW6eQ.mjs → byline-fields-Qg8TesxL.mjs} +1 -1
- package/dist/{byline-registry-rkr73qSE.mjs → byline-registry-CkuVVeJJ.mjs} +46 -76
- package/dist/{bylines-BcuBpzVi.mjs → bylines-7BQxRGyG.mjs} +4 -4
- package/dist/{bylines-v_ZUQnR-.mjs → bylines-LqNRjma2.mjs} +6 -6
- package/dist/{cache-V2BCplaY.mjs → cache-CSTy-R-K.mjs} +2 -2
- package/dist/{chunks-CnuL55JE.mjs → chunks-BnG3LPMN.mjs} +1 -1
- package/dist/cli/index.mjs +452 -263
- package/dist/cli/plugin-kit.d.mts +9 -9
- package/dist/cli/plugin-kit.mjs +2 -2
- package/dist/client/external-auth-headers.d.mts +1 -1
- package/dist/client/index.d.mts +11 -11
- package/dist/client/index.mjs +2 -2
- package/dist/{client-factory-C-y9VZDX.mjs → client-factory-BLSkgsTg.mjs} +1 -1
- package/dist/{comment-_nvJSS-A.mjs → comment-Bi7cJ9SS.mjs} +2 -2
- package/dist/{comment-reaction-DhVgJ17S.mjs → comment-reaction-BLqIj5mx.mjs} +1 -1
- package/dist/{comments-D4mIDjvA.mjs → comments-Dg_gWBEB.mjs} +1 -1
- package/dist/content-De_XeXy_.mjs +1230 -0
- package/dist/{content-CVCrcuvD.mjs → content-NobcQti0.mjs} +240 -161
- package/dist/{content-refresh-QvBIyb_g.mjs → content-refresh-l4mPoGeX.mjs} +170 -193
- package/dist/{context-MftkHbWx.mjs → context-6uqzU-M9.mjs} +95 -77
- package/dist/{context-JjKucxBm.mjs → context-B0SG9Xkc.mjs} +2 -2
- package/dist/{context-route-helpers-e1APrqSm.mjs → context-route-helpers-C8s26uDT.mjs} +2 -2
- package/dist/{cron-mGVPQ5e6.mjs → cron-D7zB6m8i.mjs} +36 -32
- package/dist/d1-binding-D6HZa3ks.mjs +8 -0
- package/dist/d1-dialect-B1b8cmxX.mjs +48 -0
- package/dist/{dashboard-ZJ7sMcBI.mjs → dashboard-B-OybCMw.mjs} +5 -5
- package/dist/database/batch.d.mts +20 -0
- package/dist/database/batch.mjs +69 -0
- package/dist/database/d1/index.d.mts +18 -0
- package/dist/database/d1/index.mjs +8 -0
- package/dist/db/d1.d.mts +7 -0
- package/dist/db/d1.mjs +13 -0
- package/dist/db/index.d.mts +4 -4
- package/dist/db/index.mjs +10 -7
- package/dist/db/libsql.d.mts +1 -1
- package/dist/db/libsql.mjs +46 -3
- package/dist/db/postgres.d.mts +1 -1
- package/dist/db/sqlite.d.mts +1 -1
- package/dist/{device-flow-eOcL5m0Q.mjs → device-flow-DhpCzMo0.mjs} +130 -94
- package/dist/{dialect-helpers-fk43GbDb.mjs → dialect-helpers-C6xtO-Ui.mjs} +1 -1
- package/dist/{discovery-CJkuHGhZ.mjs → discovery-CqXbN0WZ.mjs} +5 -5
- package/dist/{enrich-KErvJOuI.mjs → enrich-BjF-J4sF.mjs} +1 -1
- package/dist/{evidence-6IUv9ML3.mjs → evidence-xJf8hQgH.mjs} +7 -7
- package/dist/{field-defs-cache-CwrIyZFT.mjs → field-defs-cache-BKKFFf_V.mjs} +5 -5
- package/dist/{forgeway-account-lYJ8iX3G.mjs → forgeway-account-BeKJlKh1.mjs} +1 -1
- package/dist/{fts-manager-DX7ZkrCa.mjs → fts-manager-BeWtB7ZD.mjs} +72 -57
- package/dist/{hitl-requests-CmYVunm-.mjs → hitl-requests-evSsel48.mjs} +2 -2
- package/dist/{hitl-route-helpers-CRm537zS.mjs → hitl-route-helpers-D2kJSOFX.mjs} +5 -5
- package/dist/{import-DqRAgsKr.mjs → import-Jpta-CYE.mjs} +9 -9
- package/dist/{index-Co7xtjkd.d.mts → index-CSUSBfdD.d.mts} +7 -4
- package/dist/index.d.mts +16 -16
- package/dist/index.mjs +104 -96
- package/dist/{integration-credentials-qudN6yRr.mjs → integration-credentials-BrQr0fb_.mjs} +2 -2
- package/dist/{jsonld-BpvnSp2m.d.mts → jsonld-CqIVIeZK.d.mts} +2 -2
- package/dist/{load-fCOciq0Q.mjs → load-Dc5ttyg4.mjs} +1 -1
- package/dist/{loader-BDje8ME2.mjs → loader-Cgsx23wU.mjs} +4 -4
- package/dist/{manifest-schema-CfKD0thC.mjs → manifest-schema-DG29meRy.mjs} +1 -1
- package/dist/{mcp-reviewed-executor-DmhM3Cy6.mjs → mcp-reviewed-executor-DAZL3Ckt.mjs} +7 -7
- package/dist/media/image-endpoint.mjs +1 -1
- package/dist/media/index.d.mts +1 -1
- package/dist/media/index.mjs +2 -2
- package/dist/media/local-runtime.d.mts +11 -11
- package/dist/media/local-runtime.mjs +3 -3
- package/dist/{media-dvRjj4po.mjs → media-3fK0u-bo.mjs} +1 -1
- package/dist/{media-allowlist-DaG6lNoy.mjs → media-allowlist-rN4qIF6W.mjs} +1 -1
- package/dist/{menus-CpuR4Qkm.mjs → menus-5liJusbp.mjs} +138 -90
- package/dist/{menus-CZbz5L_V.mjs → menus-CbR_J8cJ.mjs} +8 -8
- package/dist/migrations-CMdxWKx-.mjs +76 -0
- package/dist/oauth-authority-CCqo4eBm.mjs +43 -0
- package/dist/{oauth-authorization-Jf5e3azH.mjs → oauth-authorization--0UtTZpv.mjs} +89 -98
- package/dist/{oauth-clients-tovQ4D4h.mjs → oauth-clients-D4WBYaYW.mjs} +2 -2
- package/dist/object-cache/memory.d.mts +1 -1
- package/dist/{object-cache-D51qOseS.mjs → object-cache-BGjIlY9s.mjs} +1 -1
- package/dist/page/index.d.mts +10 -10
- package/dist/page/index.mjs +1 -1
- package/dist/{parse-IsGn-5lt.mjs → parse--7nG62_h.mjs} +1 -1
- package/dist/plugin-utils.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.d.mts +9 -9
- package/dist/plugins/adapt-sandbox-entry.mjs +1 -1
- package/dist/{plugins-DXyLI3Hb.mjs → plugins-DK1wLuao.mjs} +35 -84
- package/dist/{policy-DKdNMv8y.mjs → policy-Dej7NJFD.mjs} +2 -2
- package/dist/{preview-BXmS1SXL.mjs → preview-q0pkibNO.mjs} +2 -2
- package/dist/{provider-loader-DDq7R_RN.d.mts → provider-loader-C0GaLwKB.d.mts} +1 -1
- package/dist/{public-url-Ci7UbC0W.d.mts → public-url-B9zEdO8p.d.mts} +1 -1
- package/dist/{public-url-BQ9vf0AS.d.mts → public-url-BV-YQ_LF.d.mts} +2 -2
- package/dist/{publication-authorization-C-vYPGD8.mjs → publication-authorization-BrEZ2TsE.mjs} +459 -33
- package/dist/{query-CrW2yI6G.mjs → query-CEn9HXnf.mjs} +15 -15
- package/dist/{query-DcB9uGTW.mjs → query-DAS6VbMS.mjs} +4 -4
- package/dist/{rate-limit-DEkoxTsP.mjs → rate-limit-Dd1TnzZP.mjs} +2 -2
- package/dist/{redirect-DG-o0CKV.mjs → redirect-HLI3wT5Y.mjs} +26 -14
- package/dist/{redirects-Bjp4iKJU.mjs → redirects-DmOdfRjI.mjs} +5 -5
- package/dist/{redirects-N8gmWhVM.mjs → redirects-UCXyL0lP.mjs} +3 -3
- package/dist/{registry-D-IV_h50.mjs → registry-RD9qTnYL.mjs} +183 -186
- package/dist/release-BR08Slqf.mjs +5148 -0
- package/dist/request-context.d.mts +8 -0
- package/dist/{request-meta-BW0the1R.mjs → request-meta-BOcuHAXD.mjs} +1 -1
- package/dist/{resolve-pZ4NQM-X.mjs → resolve-C80Pm2DW.mjs} +1 -1
- package/dist/{review-payload-f1L4lzQg.mjs → review-payload-DEylbssM.mjs} +52 -4
- package/dist/{review-requests-DICrYH2-.mjs → review-requests-BF2eEKr8.mjs} +93 -37
- package/dist/{review-requests-BTKfeWlS.mjs → review-requests-CyfWbJ6W.mjs} +2 -2
- package/dist/{review-route-helpers-DaZBBps8.mjs → review-route-helpers-lKA-CXms.mjs} +2 -2
- package/dist/{revision-De7OmYVD.mjs → revision-090sZyGc.mjs} +28 -22
- package/dist/revocation-B7GL5fMl.mjs +53 -0
- package/dist/{runner-DJiRFyLI.mjs → runner-CVeq0266.mjs} +594 -491
- package/dist/{runner-Dye73myO.d.mts → runner-JnJSGXEB.d.mts} +1 -1
- package/dist/{runs-DEujUDOj.mjs → runs-B5BExdKO.mjs} +5 -5
- package/dist/runtime-env-CQVAWHzH.mjs +19 -0
- package/dist/runtime.d.mts +10 -10
- package/dist/runtime.mjs +5 -5
- package/dist/schema-DLMkODQc.mjs +8 -0
- package/dist/{search-DxUKN9Zz.mjs → search-CRzWNfxX.mjs} +4 -4
- package/dist/{secrets-AdCrGg1c.mjs → secrets-Cg0D2gQW.mjs} +10 -11
- package/dist/{sections-BPFOEMK6.mjs → sections-BwUjOGqn.mjs} +2 -2
- package/dist/seed/index.d.mts +2 -2
- package/dist/seed/index.mjs +29 -25
- package/dist/seo/index.d.mts +3 -3
- package/dist/seo/index.mjs +11 -10
- package/dist/{seo-DWHdo5aW.mjs → seo-BOTuCeh-.mjs} +25 -15
- package/dist/{seo-GfovzqpU.mjs → seo-B_tBFyud.mjs} +1 -1
- package/dist/{service-DbgjHWyW.mjs → service--bQht6oN.mjs} +2 -2
- package/dist/{service-BrNKVCjC.mjs → service-DilVsWGD.mjs} +3 -3
- package/dist/{session-user-D8WwGEPH.mjs → session-user-DeqTcAmR.mjs} +1 -1
- package/dist/{settings-CAsQLi0N.mjs → settings-DFzevIrU.mjs} +8 -8
- package/dist/{settings-BKEHw6Bu.mjs → settings-Deqx3Upy.mjs} +2 -2
- package/dist/{setup-complete-CHCYS5KV.mjs → setup-complete-BFqudwbW.mjs} +1 -1
- package/dist/{site-activity-7oezuHXK.mjs → site-activity-BrN2NviL.mjs} +11 -4
- package/dist/{site-context-CA7rbxux.mjs → site-context-vCiDRr4H.mjs} +50 -37
- package/dist/{site-url-DoZf_jVj.mjs → site-url-wXFqbm9c.mjs} +1 -1
- package/dist/state-jyNZ6-7L.mjs +30 -0
- package/dist/storage/local.d.mts +1 -1
- package/dist/storage/local.mjs +1 -1
- package/dist/storage/s3.d.mts +1 -1
- package/dist/storage/s3.mjs +3 -3
- package/dist/{store-c4qx3gVh.mjs → store-C1yDxxfv.mjs} +37 -12
- package/dist/submission-BsHNfHc7.mjs +155 -0
- package/dist/{taxonomies-ALDiRQ84.mjs → taxonomies-4cnTcbD6.mjs} +3 -3
- package/dist/{taxonomies-93DV-1QT.mjs → taxonomies-CllxqaH0.mjs} +7 -7
- package/dist/{taxonomy-BOBTJ_aE.mjs → taxonomy-DWxxLpp5.mjs} +3 -3
- package/dist/{tokens-c-qxNqzC.mjs → tokens-Bjuf1HID.mjs} +1 -1
- package/dist/{trusted-proxy-CdEl6g6B.mjs → trusted-proxy-CAW9o4Dw.mjs} +4 -12
- package/dist/{types-BRCUO8NR.d.mts → types-7Th6Mwz3.d.mts} +1 -0
- package/dist/{types-BpSTdH1H.mjs → types-BqxIv8Il.mjs} +2 -2
- package/dist/{types-6KmeXInJ.d.mts → types-CFgTpfPk.d.mts} +1 -1
- package/dist/{types-CfpX1og5.d.mts → types-QjOcidFc.d.mts} +301 -173
- package/dist/ui/server-runtime.d.mts +13 -13
- package/dist/ui/server-runtime.mjs +28 -26
- package/dist/{user-D0NJ7gYf.mjs → user-1-YV30lf.mjs} +2 -2
- package/dist/{utils-BK2efsHv.mjs → utils-Cglcqpm2.mjs} +2 -2
- package/dist/{validate-CDWVODvc.d.mts → validate-A27peRc4.d.mts} +3 -3
- package/dist/{validate-C9g9iX3q.mjs → validate-Wl4MSf3V.mjs} +3 -3
- package/dist/version-BWxyC5s4.mjs +6 -0
- package/dist/{widgets-Cm5Qx2Np.mjs → widgets-Di-6yDH7.mjs} +3 -3
- package/dist/{wordpress-slugs-WdPZaVXf.mjs → wordpress-slugs-vOx7R1dM.mjs} +1 -1
- package/dist/{worker-Bhuu7eqS.mjs → worker-RpaMP71d.mjs} +76 -47
- package/dist/workers-build-BaQCrSmf.mjs +36 -0
- package/dist/{zod-generator-DS5oZNaL.mjs → zod-generator-Cylvl_SM.mjs} +2 -2
- package/package.json +35 -9
- package/dist/after-BfniwgIf.mjs +0 -9
- package/dist/api-tokens-CmT83Bgj.mjs +0 -3
- package/dist/db/libsql-http.d.mts +0 -27
- package/dist/db/libsql-http.mjs +0 -29
- package/dist/libsql-dialect-CANq6UNI.mjs +0 -47
- package/dist/oauth-user-lookup-B451pZmd.mjs +0 -25
- package/dist/revocation-CkTOhdlw.mjs +0 -42
- package/dist/schema-IjuRxkqq.mjs +0 -8
- package/dist/submission-C47cHBIg.mjs +0 -67
- package/dist/transaction-BGQgnwUi.mjs +0 -28
- package/dist/version-CJqc1mwj.mjs +0 -6
- /package/dist/{base64-F8-DUraK.mjs → base64-Cz-aU0X1.mjs} +0 -0
- /package/dist/{challenge-store-CDKfye2r.mjs → challenge-store-D-_-VavY.mjs} +0 -0
- /package/dist/{components-DAq_4iPX.mjs → components-BWQUCJEr.mjs} +0 -0
- /package/dist/{config-CVssduLe.mjs → config-XW5tMrH8.mjs} +0 -0
- /package/dist/{content-index-names-Bbu1FY1r.mjs → content-index-names-CDc2IQIx.mjs} +0 -0
- /package/dist/{context-types-CPWAJRs5.mjs → context-types-DqTo6C79.mjs} +0 -0
- /package/dist/{default-BeIzUa1e.mjs → default-D9zxuUU7.mjs} +0 -0
- /package/dist/{email-console-Bfi_exVg.mjs → email-console-BONByQiC.mjs} +0 -0
- /package/dist/{error-DLg1H2LT.mjs → error-Dd8LtpG5.mjs} +0 -0
- /package/dist/{escape-C6lkys0j.mjs → escape-BWC4s5bV.mjs} +0 -0
- /package/dist/{experimental-workflows-B9x8delL.mjs → experimental-workflows-M5D3RTFo.mjs} +0 -0
- /package/dist/{hash-jhbF98tT.mjs → hash-lNx3KJis.mjs} +0 -0
- /package/dist/{media-url-CL3NzgLh.mjs → media-url-B4YtTY6c.mjs} +0 -0
- /package/dist/{mime-CDTtL7jE.mjs → mime-D_ae-u_U.mjs} +0 -0
- /package/dist/{mode-DJeacFCZ.mjs → mode-CPf_KZ37.mjs} +0 -0
- /package/dist/{normalize-Ev3FiBMx.mjs → normalize-5rct_U0I.mjs} +0 -0
- /package/dist/{oauth-state-store-Do1a_o3H.mjs → oauth-state-store-CMgcimzA.mjs} +0 -0
- /package/dist/{options-1dBRkoCl.mjs → options-BcqHWpc-.mjs} +0 -0
- /package/dist/{output-8j9oltTf.mjs → output-BYpiVUBf.mjs} +0 -0
- /package/dist/{parser-C9rzPuSZ.mjs → parser-BV0wzQHo.mjs} +0 -0
- /package/dist/{passkey-config-CRN44T04.mjs → passkey-config-BG4GO4OO.mjs} +0 -0
- /package/dist/{patterns-3XE9bU4r.mjs → patterns-CZ7D4y_R.mjs} +0 -0
- /package/dist/{placeholder-D03pGvqM.d.mts → placeholder-BHTaoCYx.d.mts} +0 -0
- /package/dist/{portable-text-tIk9_uz_.mjs → portable-text-B9YuySom.mjs} +0 -0
- /package/dist/{portable-text-BdRm4uZq.d.mts → portable-text-FKf3IrPz.d.mts} +0 -0
- /package/dist/{process-cache-B-L-A9zg.mjs → process-cache-MHM4Sqzs.mjs} +0 -0
- /package/dist/{provider-loader-C4i82ll1.mjs → provider-loader-3MY1SjzA.mjs} +0 -0
- /package/dist/{public-discovery-CyDzK1-S.mjs → public-discovery-BAbOvKiR.mjs} +0 -0
- /package/dist/{public-url-oudwI7K0.mjs → public-url-C7pbmS_7.mjs} +0 -0
- /package/dist/{public-url-BVIjzMo3.mjs → public-url-D5Wjq0sy.mjs} +0 -0
- /package/dist/{redirect-Dp5u-8dH.mjs → redirect-Bx96u2nS.mjs} +0 -0
- /package/dist/{request-cache-BruBnFAR.mjs → request-cache-DPmV5nk4.mjs} +0 -0
- /package/dist/{seo-contributions-BAtRDXEQ.mjs → seo-contributions-Dt57p6Sq.mjs} +0 -0
- /package/dist/{service-DeX1PRNt.mjs → service-wYQ_ePZ4.mjs} +0 -0
- /package/dist/{setup-nonce-D-CEYlw7.mjs → setup-nonce-CAqDUxxU.mjs} +0 -0
- /package/dist/{sidecar-client-Bw2C0XTf.mjs → sidecar-client-CnpGTvYq.mjs} +0 -0
- /package/dist/{slugify-KSsVD_D3.mjs → slugify-Di8Q_MFq.mjs} +0 -0
- /package/dist/{ssrf-C7tTSD1r.mjs → ssrf-LN16WMip.mjs} +0 -0
- /package/dist/{stable-hash-DF7R5eN8.mjs → stable-hash-DEtJgcp7.mjs} +0 -0
- /package/dist/{status-Bba6RbkS.mjs → status-Bwkeuz8g.mjs} +0 -0
- /package/dist/{transport-BddGhTAI.mjs → transport-472KVGBe.mjs} +0 -0
- /package/dist/{transport-ktLL9r2O.d.mts → transport-C0jj-Nc8.d.mts} +0 -0
- /package/dist/{types-BQZFeZjd.mjs → types-BDq9t5lG.mjs} +0 -0
- /package/dist/{types-CKIt_jmM.d.mts → types-Bs-7Geuh.d.mts} +0 -0
- /package/dist/{types-CLMOusxP.d.mts → types-CwkJp6zr.d.mts} +0 -0
- /package/dist/{types-C0DPvhR5.mjs → types-CyBH89BS.mjs} +0 -0
- /package/dist/{types-BbkkkAb6.mjs → types-D17dJRht.mjs} +0 -0
- /package/dist/{types--3oJQ0hs.d.mts → types-DTjrkhKU.d.mts} +0 -0
- /package/dist/{types-CPaVj_GC.d.mts → types-DkXuBo8k.d.mts} +0 -0
- /package/dist/{types-CU3Wn2HC.d.mts → types-b2sq7ZDk.d.mts} +0 -0
- /package/dist/{url-C_pLSrGZ.mjs → url-D375-6LM.mjs} +0 -0
- /package/dist/{url-Dumsft7G.mjs → url-bv5i4JN0.mjs} +0 -0
- /package/dist/{validate-VPnKoIzW.mjs → validate-Co3j6T_K.mjs} +0 -0
package/dist/{publication-authorization-C-vYPGD8.mjs → publication-authorization-BrEZ2TsE.mjs}
RENAMED
|
@@ -1,39 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as
|
|
8
|
-
import { n as
|
|
1
|
+
import { AtomicWriteConflict, atomicBatch, isD1Database, rowUnchanged } from "./database/batch.mjs";
|
|
2
|
+
import { r as currentIsoTimestampValue } from "./dialect-helpers-C6xtO-Ui.mjs";
|
|
3
|
+
import { i as encodeCursor, r as decodeCursor } from "./types-BqxIv8Il.mjs";
|
|
4
|
+
import { r as getOAuthTokenHash, t as SYSTEM_ACTOR_ID } from "./actor-DxUAJgQX.mjs";
|
|
5
|
+
import { o as invalidateCollectionCache } from "./object-cache-BGjIlY9s.mjs";
|
|
6
|
+
import { t as ContentRepository } from "./content-NobcQti0.mjs";
|
|
7
|
+
import { t as SiteActivityRepository } from "./site-activity-BrN2NviL.mjs";
|
|
8
|
+
import { n as stableStringify } from "./stable-hash-DEtJgcp7.mjs";
|
|
9
|
+
import { r as ReviewRequestRepository } from "./review-requests-BF2eEKr8.mjs";
|
|
10
|
+
import { n as buildStableActionHash, t as ReviewPayloadBuilder } from "./review-payload-DEylbssM.mjs";
|
|
11
|
+
import { a as getSiteSettingsWithDb } from "./settings-DFzevIrU.mjs";
|
|
12
|
+
import { i as invalidateRedirectCache } from "./cache-CSTy-R-K.mjs";
|
|
13
|
+
import { x as prepareContentPublication } from "./content-De_XeXy_.mjs";
|
|
14
|
+
import { n as redactActivityRecord } from "./activity-CZnq5YlZ.mjs";
|
|
15
|
+
import { sql } from "kysely";
|
|
9
16
|
import { ulid } from "ulidx";
|
|
17
|
+
import { canActOnOwn, hasPermission, hasScope, toRoleLevel } from "@dineway-ai/auth";
|
|
18
|
+
import { z } from "zod";
|
|
10
19
|
|
|
11
20
|
//#region src/database/repositories/content-release-grants.ts
|
|
12
21
|
var ContentReleaseGrantRepository = class {
|
|
13
22
|
constructor(db) {
|
|
14
23
|
this.db = db;
|
|
15
24
|
}
|
|
16
|
-
async
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
async prepareCreateOrReplaceActive(input) {
|
|
26
|
+
const current = await this.db.selectFrom("_dineway_content_release_grants").selectAll().where("collection", "=", input.collection).where("entry_id", "=", input.entryId).where("operation", "=", input.operation).where("status", "=", "active").executeTakeFirst();
|
|
27
|
+
const checks = [current ? rowUnchanged("_dineway_content_release_grants", current) : sql`NOT EXISTS (SELECT 1 FROM _dineway_content_release_grants WHERE collection = ${input.collection} AND entry_id = ${input.entryId} AND operation = ${input.operation} AND status = 'active')`];
|
|
28
|
+
if (current?.action_hash === input.actionHash) return {
|
|
29
|
+
grant: rowToGrant(current),
|
|
30
|
+
batch: {
|
|
31
|
+
checks,
|
|
32
|
+
statements: []
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
const now = input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
36
|
+
const statements = [];
|
|
37
|
+
if (current) statements.push(this.db.updateTable("_dineway_content_release_grants").set({
|
|
38
|
+
status: "revoked",
|
|
39
|
+
updated_at: now,
|
|
40
|
+
revoked_at: now,
|
|
41
|
+
revocation_reason: "replaced"
|
|
42
|
+
}).where("id", "=", current.id).where("status", "=", "active").compile());
|
|
43
|
+
const row = toInsertableGrant(ulid(), input, now);
|
|
44
|
+
statements.push(this.db.insertInto("_dineway_content_release_grants").values(row).compile());
|
|
45
|
+
return {
|
|
46
|
+
grant: rowToGrant(row),
|
|
47
|
+
batch: {
|
|
48
|
+
checks,
|
|
49
|
+
statements
|
|
29
50
|
}
|
|
30
|
-
const id = ulid();
|
|
31
|
-
await transaction.insertInto("_dineway_content_release_grants").values(toInsertableGrant(id, input, now)).execute();
|
|
32
|
-
const created = await findById(transaction, id);
|
|
33
|
-
if (!created) throw new Error("Failed to create content release grant");
|
|
34
|
-
return created;
|
|
35
51
|
};
|
|
36
|
-
|
|
52
|
+
}
|
|
53
|
+
async createOrReplaceActive(input) {
|
|
54
|
+
const prepared = await this.prepareCreateOrReplaceActive(input);
|
|
55
|
+
await atomicBatch(this.db, prepared.batch);
|
|
56
|
+
const grant = await this.findById(prepared.grant.id);
|
|
57
|
+
if (!grant) throw new Error("Failed to create content release grant");
|
|
58
|
+
return grant;
|
|
37
59
|
}
|
|
38
60
|
async findById(id) {
|
|
39
61
|
return findById(this.db, id);
|
|
@@ -511,7 +533,8 @@ var PublicationAuthorizationService = class {
|
|
|
511
533
|
now;
|
|
512
534
|
constructor(options) {
|
|
513
535
|
this.options = options;
|
|
514
|
-
|
|
536
|
+
const reviewRepository = new ReviewRequestRepository(options.db);
|
|
537
|
+
this.reviewRequests = { findById: async (id) => options.preparedReview?.review.id === id ? options.preparedReview.review : reviewRepository.findById(id) };
|
|
515
538
|
this.releaseGrants = new ContentReleaseGrantRepository(options.db);
|
|
516
539
|
this.hitlRequests = new HitlRequestRepository(options.db);
|
|
517
540
|
this.activity = new SiteActivityRepository(options.db);
|
|
@@ -655,7 +678,7 @@ var PublicationAuthorizationService = class {
|
|
|
655
678
|
};
|
|
656
679
|
}
|
|
657
680
|
async releaseApprovedReview(reviewId) {
|
|
658
|
-
if (!this.options.db.isTransaction) throw new PublicationAuthorizationError("RELEASE_GRANT_FAILED", "Automated release requires a transaction.");
|
|
681
|
+
if (!this.options.db.isTransaction && !isD1Database(this.options.db)) throw new PublicationAuthorizationError("RELEASE_GRANT_FAILED", "Automated release requires a transaction.");
|
|
659
682
|
const job = await this.options.db.selectFrom("_dineway_review_jobs").selectAll().where("review_id", "=", reviewId).where("release_state", "=", "releasing").executeTakeFirst();
|
|
660
683
|
const review = await this.reviewRequests.findById(reviewId);
|
|
661
684
|
if (!job || !review || review.status !== "approved" || review.revokedAt) throw new PublicationAuthorizationError("EDITORIAL_REVIEW_INVALID", "An active exact review approval is required.");
|
|
@@ -673,6 +696,27 @@ var PublicationAuthorizationService = class {
|
|
|
673
696
|
sourceType: "system",
|
|
674
697
|
sourceName: "review-automation"
|
|
675
698
|
};
|
|
699
|
+
if (isD1Database(this.options.db)) {
|
|
700
|
+
const future = job.scheduled_at && job.scheduled_at > this.now();
|
|
701
|
+
const outcome = future ? "scheduled" : "published";
|
|
702
|
+
await this.publishAtomic(future ? {
|
|
703
|
+
...input,
|
|
704
|
+
scheduledAt: job.scheduled_at
|
|
705
|
+
} : input, future ? "schedule" : "publish", {
|
|
706
|
+
checks: [rowUnchanged("_dineway_review_jobs", {
|
|
707
|
+
review_id: job.review_id,
|
|
708
|
+
release_state: job.release_state,
|
|
709
|
+
updated_at: job.updated_at,
|
|
710
|
+
scheduled_at: job.scheduled_at
|
|
711
|
+
})],
|
|
712
|
+
statements: [this.options.db.updateTable("_dineway_review_jobs").set({
|
|
713
|
+
release_state: outcome,
|
|
714
|
+
release_reason: null,
|
|
715
|
+
updated_at: this.now()
|
|
716
|
+
}).where("review_id", "=", job.review_id).where("release_state", "=", "releasing").compile()]
|
|
717
|
+
});
|
|
718
|
+
return outcome;
|
|
719
|
+
}
|
|
676
720
|
if (job.scheduled_at && job.scheduled_at > this.now()) {
|
|
677
721
|
await this.scheduleAuthorizedContent({
|
|
678
722
|
...input,
|
|
@@ -683,7 +727,13 @@ var PublicationAuthorizationService = class {
|
|
|
683
727
|
await this.publishAuthorizedContent(input);
|
|
684
728
|
return "published";
|
|
685
729
|
}
|
|
730
|
+
/** Commit a host-prepared review and publication as one explicit batch. */
|
|
731
|
+
async publishPreparedContent(input) {
|
|
732
|
+
if (!this.options.preparedReview) throw new PublicationAuthorizationError("CONFIRMATION_REQUIRED", "A prepared host confirmation is required");
|
|
733
|
+
return this.publishAtomic(input, "publish");
|
|
734
|
+
}
|
|
686
735
|
async publishAuthorizedContent(input) {
|
|
736
|
+
if (isD1Database(this.options.db)) return this.publishAtomic(input, "publish");
|
|
687
737
|
const siteTimezone = await this.getSiteTimezone();
|
|
688
738
|
const authorized = await this.authorize({
|
|
689
739
|
...input,
|
|
@@ -706,6 +756,7 @@ var PublicationAuthorizationService = class {
|
|
|
706
756
|
};
|
|
707
757
|
}
|
|
708
758
|
async scheduleAuthorizedContent(input) {
|
|
759
|
+
if (isD1Database(this.options.db)) return this.publishAtomic(input, "schedule");
|
|
709
760
|
const siteTimezone = await this.getSiteTimezone();
|
|
710
761
|
const authorized = await this.authorize({
|
|
711
762
|
...input,
|
|
@@ -722,6 +773,7 @@ var PublicationAuthorizationService = class {
|
|
|
722
773
|
};
|
|
723
774
|
}
|
|
724
775
|
async publishAuthorizedDueContent(input) {
|
|
776
|
+
if (isD1Database(this.options.db)) return this.publishDueAtomic(input);
|
|
725
777
|
const grant = await this.releaseGrants.findActiveForTarget(input.collection, input.id, "schedule");
|
|
726
778
|
if (!grant) {
|
|
727
779
|
await this.blockScheduledRelease(input, null, "schedule_grant_required");
|
|
@@ -760,6 +812,7 @@ var PublicationAuthorizationService = class {
|
|
|
760
812
|
};
|
|
761
813
|
}
|
|
762
814
|
async unscheduleAuthorizedContent(input) {
|
|
815
|
+
if (isD1Database(this.options.db)) return this.unscheduleAtomic(input);
|
|
763
816
|
const activeGrant = await this.releaseGrants.findActiveForTarget(input.collection, input.id, "schedule");
|
|
764
817
|
let revokedGrant = null;
|
|
765
818
|
if (activeGrant) {
|
|
@@ -791,6 +844,366 @@ var PublicationAuthorizationService = class {
|
|
|
791
844
|
await this.releasePolicies(prepared, "release_request_prepared");
|
|
792
845
|
}
|
|
793
846
|
}
|
|
847
|
+
async unscheduleAtomic(input) {
|
|
848
|
+
const db = this.options.db;
|
|
849
|
+
const snapshot = await new ContentRepository(db).snapshot(input.collection, input.id);
|
|
850
|
+
if (!snapshot) throw new PublicationAuthorizationError("NOT_FOUND", "Content not found");
|
|
851
|
+
const checks = [snapshot.check, ...await this.atomicActorChecks(input, snapshot.item)];
|
|
852
|
+
const rawGrant = await db.selectFrom("_dineway_content_release_grants").selectAll().where("collection", "=", input.collection).where("entry_id", "=", input.id).where("operation", "=", "schedule").where("status", "=", "active").executeTakeFirst();
|
|
853
|
+
checks.push(rawGrant ? rowUnchanged("_dineway_content_release_grants", rawGrant) : sql`NOT EXISTS (SELECT 1 FROM _dineway_content_release_grants WHERE collection = ${input.collection} AND entry_id = ${input.id} AND operation = 'schedule' AND status = 'active')`);
|
|
854
|
+
const grant = rawGrant ? await this.releaseGrants.findById(rawGrant.id) : null;
|
|
855
|
+
if (grant?.policyContributions.some((contribution) => contribution.reservationId)) throw new PublicationAuthorizationError("RELEASE_POLICY_FAILED", "Reservation policies require a transactional database adapter");
|
|
856
|
+
const statements = [sql`UPDATE ${sql.table(`ec_${input.collection}`)} SET scheduled_at = NULL, status = CASE WHEN status = 'published' THEN 'published' ELSE 'draft' END, updated_at = ${this.now()} WHERE id = ${input.id}`.compile(db)];
|
|
857
|
+
if (grant) statements.push(db.updateTable("_dineway_content_release_grants").set({
|
|
858
|
+
status: "revoked",
|
|
859
|
+
revoked_at: this.now(),
|
|
860
|
+
revocation_reason: "content_unscheduled",
|
|
861
|
+
updated_at: this.now()
|
|
862
|
+
}).where("id", "=", grant.id).compile(), db.updateTable("_dineway_review_jobs").set({
|
|
863
|
+
release_state: "blocked",
|
|
864
|
+
release_reason: "content_unscheduled",
|
|
865
|
+
updated_at: this.now()
|
|
866
|
+
}).where("review_id", "=", grant.editorialReviewRequestId).where("release_state", "in", [
|
|
867
|
+
"queued",
|
|
868
|
+
"scheduled",
|
|
869
|
+
"releasing"
|
|
870
|
+
]).compile());
|
|
871
|
+
statements.push(this.activity.prepareCreate({
|
|
872
|
+
...input.actor,
|
|
873
|
+
actionType: "content.unschedule",
|
|
874
|
+
subjectType: "content",
|
|
875
|
+
subjectId: input.id,
|
|
876
|
+
scope: `content:${input.collection}:${input.id}`,
|
|
877
|
+
summary: `Unscheduled ${input.collection}/${input.id}`,
|
|
878
|
+
sourceType: input.sourceType ?? "unknown",
|
|
879
|
+
sourceName: input.sourceName ?? null,
|
|
880
|
+
detail: {
|
|
881
|
+
releaseGrantId: grant?.id ?? null,
|
|
882
|
+
revocationReason: "content_unscheduled"
|
|
883
|
+
}
|
|
884
|
+
}).statement);
|
|
885
|
+
await atomicBatch(db, {
|
|
886
|
+
checks,
|
|
887
|
+
statements
|
|
888
|
+
});
|
|
889
|
+
invalidateCollectionCache(input.collection);
|
|
890
|
+
const result = await this.options.handlers.handleContentGet(input.collection, input.id);
|
|
891
|
+
await this.options.onUnscheduleCommitted?.(input.collection, input.id, snapshot.item);
|
|
892
|
+
return {
|
|
893
|
+
grant: grant ? await this.releaseGrants.findById(grant.id) : null,
|
|
894
|
+
result
|
|
895
|
+
};
|
|
896
|
+
}
|
|
897
|
+
async publishDueAtomic(input) {
|
|
898
|
+
const db = this.options.db;
|
|
899
|
+
const snapshot = await new ContentRepository(db).snapshot(input.collection, input.id);
|
|
900
|
+
if (!snapshot || !snapshot.item.scheduledAt || snapshot.item.scheduledAt > this.now()) throw new PublicationAuthorizationError("NOT_DUE", "Content is no longer due for publication");
|
|
901
|
+
const checks = [snapshot.check];
|
|
902
|
+
const rawGrant = await db.selectFrom("_dineway_content_release_grants").selectAll().where("collection", "=", input.collection).where("entry_id", "=", input.id).where("operation", "=", "schedule").where("status", "=", "active").executeTakeFirst();
|
|
903
|
+
const grant = rawGrant ? await this.releaseGrants.findById(rawGrant.id) : null;
|
|
904
|
+
checks.push(rawGrant ? rowUnchanged("_dineway_content_release_grants", rawGrant) : sql`NOT EXISTS (SELECT 1 FROM _dineway_content_release_grants WHERE collection = ${input.collection} AND entry_id = ${input.id} AND operation = 'schedule' AND status = 'active')`);
|
|
905
|
+
let release;
|
|
906
|
+
try {
|
|
907
|
+
if (!grant) throw new PublicationAuthorizationError("SCHEDULE_GRANT_REQUIRED", "Due content has no active schedule grant");
|
|
908
|
+
const review = await db.selectFrom("_dineway_review_requests").selectAll().where("id", "=", grant.editorialReviewRequestId).executeTakeFirst();
|
|
909
|
+
if (!review) throw new PublicationAuthorizationError("SCHEDULE_GRANT_INVALID", "Editorial review is missing");
|
|
910
|
+
checks.push(rowUnchanged("_dineway_review_requests", review));
|
|
911
|
+
const ids = [snapshot.item.liveRevisionId, snapshot.item.draftRevisionId].filter((id) => id !== null);
|
|
912
|
+
const revisions = ids.length ? await db.selectFrom("revisions").selectAll().where("id", "in", ids).execute() : [];
|
|
913
|
+
checks.push(...revisions.map((row) => rowUnchanged("revisions", row)));
|
|
914
|
+
const timezone = await db.selectFrom("options").selectAll().where("name", "=", "site:timezone").executeTakeFirst();
|
|
915
|
+
checks.push(timezone ? rowUnchanged("options", timezone) : sql`NOT EXISTS (SELECT 1 FROM options WHERE name = 'site:timezone')`);
|
|
916
|
+
const pluginStates = await db.selectFrom("_plugin_state").selectAll().execute();
|
|
917
|
+
checks.push(sql`(SELECT COUNT(*) FROM _plugin_state) = ${pluginStates.length}`, ...pluginStates.map((row) => rowUnchanged("_plugin_state", row)));
|
|
918
|
+
const preparedPolicies = this.restorePreparedPolicies(grant.policyContributions);
|
|
919
|
+
release = await this.revalidateScheduledGrant(input, grant, preparedPolicies, checks);
|
|
920
|
+
checks.push(...await this.atomicActorChecks({
|
|
921
|
+
actor: grantActor(grant),
|
|
922
|
+
editorialReviewRequestId: grant.editorialReviewRequestId
|
|
923
|
+
}, snapshot.item, true));
|
|
924
|
+
} catch (error) {
|
|
925
|
+
const reason = errorReason(error);
|
|
926
|
+
const statements = [sql`UPDATE ${sql.table(`ec_${input.collection}`)} SET scheduled_at = NULL, status = CASE WHEN status = 'published' THEN 'published' ELSE 'draft' END, updated_at = ${this.now()} WHERE id = ${input.id}`.compile(db)];
|
|
927
|
+
if (grant) statements.push(db.updateTable("_dineway_content_release_grants").set({
|
|
928
|
+
status: "revoked",
|
|
929
|
+
revoked_at: this.now(),
|
|
930
|
+
updated_at: this.now(),
|
|
931
|
+
revocation_reason: reason
|
|
932
|
+
}).where("id", "=", grant.id).compile(), db.updateTable("_dineway_review_jobs").set({
|
|
933
|
+
release_state: "blocked",
|
|
934
|
+
release_reason: reason,
|
|
935
|
+
updated_at: this.now()
|
|
936
|
+
}).where("review_id", "=", grant.editorialReviewRequestId).where("release_state", "=", "scheduled").compile());
|
|
937
|
+
statements.push(this.activity.prepareCreate({
|
|
938
|
+
actorType: "system",
|
|
939
|
+
actorId: SYSTEM_ACTOR_ID,
|
|
940
|
+
actionType: "content.schedule_blocked",
|
|
941
|
+
subjectType: "content",
|
|
942
|
+
subjectId: input.id,
|
|
943
|
+
scope: `content:${input.collection}:${input.id}`,
|
|
944
|
+
summary: "Blocked scheduled publication",
|
|
945
|
+
detail: {
|
|
946
|
+
reason,
|
|
947
|
+
releaseGrantId: grant?.id ?? null
|
|
948
|
+
},
|
|
949
|
+
sourceType: "system",
|
|
950
|
+
sourceName: "scheduled_publish",
|
|
951
|
+
resultStatus: "blocked"
|
|
952
|
+
}).statement);
|
|
953
|
+
await atomicBatch(db, {
|
|
954
|
+
checks,
|
|
955
|
+
statements
|
|
956
|
+
});
|
|
957
|
+
invalidateCollectionCache(input.collection);
|
|
958
|
+
throw error;
|
|
959
|
+
}
|
|
960
|
+
if (!grant) throw new Error("Validated schedule grant is missing");
|
|
961
|
+
const content = await prepareContentPublication(db, input.collection, input.id, {
|
|
962
|
+
publishedAt: input.publishedAt,
|
|
963
|
+
requireScheduledDue: true
|
|
964
|
+
});
|
|
965
|
+
checks.push(...content.batch.checks);
|
|
966
|
+
if (grant.expiresAt) checks.push(sql`${grant.expiresAt} > ${currentIsoTimestampValue(db)}`);
|
|
967
|
+
await atomicBatch(db, {
|
|
968
|
+
checks,
|
|
969
|
+
statements: [
|
|
970
|
+
...content.batch.statements,
|
|
971
|
+
db.updateTable("_dineway_content_release_grants").set({
|
|
972
|
+
status: "consumed",
|
|
973
|
+
consumed_at: this.now(),
|
|
974
|
+
updated_at: this.now()
|
|
975
|
+
}).where("id", "=", grant.id).where("status", "=", "active").compile(),
|
|
976
|
+
db.updateTable("_dineway_review_jobs").set({
|
|
977
|
+
release_state: "published",
|
|
978
|
+
release_reason: null,
|
|
979
|
+
updated_at: this.now()
|
|
980
|
+
}).where("review_id", "=", grant.editorialReviewRequestId).where("release_state", "in", ["scheduled", "releasing"]).compile(),
|
|
981
|
+
this.activity.prepareCreate({
|
|
982
|
+
actorType: "system",
|
|
983
|
+
actorId: SYSTEM_ACTOR_ID,
|
|
984
|
+
actionType: "content.schedule_published",
|
|
985
|
+
subjectType: "content",
|
|
986
|
+
subjectId: input.id,
|
|
987
|
+
relatedSubjectType: "review_request",
|
|
988
|
+
relatedSubjectId: grant.editorialReviewRequestId,
|
|
989
|
+
scope: release.scope,
|
|
990
|
+
summary: `Published scheduled ${input.collection}/${input.id}`,
|
|
991
|
+
detail: {
|
|
992
|
+
releaseGrantId: grant.id,
|
|
993
|
+
actionHash: release.actionHash
|
|
994
|
+
},
|
|
995
|
+
sourceType: "system",
|
|
996
|
+
sourceName: "scheduled_publish",
|
|
997
|
+
resultStatus: "succeeded"
|
|
998
|
+
}).statement
|
|
999
|
+
]
|
|
1000
|
+
});
|
|
1001
|
+
invalidateCollectionCache(input.collection);
|
|
1002
|
+
invalidateRedirectCache();
|
|
1003
|
+
const consumed = await this.releaseGrants.findById(grant.id);
|
|
1004
|
+
if (!consumed) throw new Error("Committed schedule grant is missing");
|
|
1005
|
+
const result = await this.options.handlers.handleContentGet(input.collection, input.id);
|
|
1006
|
+
await this.options.onPublicationCommitted?.("publish", input.collection, input.id, snapshot.item);
|
|
1007
|
+
return {
|
|
1008
|
+
grant: consumed,
|
|
1009
|
+
result,
|
|
1010
|
+
receipt: publicationReceipt(consumed, "published")
|
|
1011
|
+
};
|
|
1012
|
+
}
|
|
1013
|
+
async atomicActorChecks(input, content, scheduledAutomation = false) {
|
|
1014
|
+
const db = this.options.db;
|
|
1015
|
+
const checks = [];
|
|
1016
|
+
const automated = input.actor.actorType === "system" && input.actor.actorId === "review-automation" && input.actor.authMetadata.auth_method === "review_automation";
|
|
1017
|
+
if (input.actor.actorType === "system" && scheduledAutomation && automated) return checks;
|
|
1018
|
+
if (input.actor.actorType === "system") {
|
|
1019
|
+
const claim = automated ? await db.selectFrom("_dineway_review_jobs").selectAll().where("review_id", "=", input.editorialReviewRequestId ?? "").where("release_state", "=", "releasing").executeTakeFirst() : null;
|
|
1020
|
+
if (!claim) throw new PublicationAuthorizationError("ACTOR_NOT_ALLOWED", "System publication requires a claimed approved review");
|
|
1021
|
+
checks.push(rowUnchanged("_dineway_review_jobs", {
|
|
1022
|
+
review_id: claim.review_id,
|
|
1023
|
+
release_state: claim.release_state,
|
|
1024
|
+
updated_at: claim.updated_at,
|
|
1025
|
+
scheduled_at: claim.scheduled_at
|
|
1026
|
+
}));
|
|
1027
|
+
} else {
|
|
1028
|
+
let userId = input.actor.actorId;
|
|
1029
|
+
if (input.actor.actorType === "api_token") {
|
|
1030
|
+
const token = await db.selectFrom("_dineway_api_tokens").select([
|
|
1031
|
+
"id",
|
|
1032
|
+
"user_id",
|
|
1033
|
+
"scopes",
|
|
1034
|
+
"expires_at"
|
|
1035
|
+
]).where("id", "=", input.actor.actorId).executeTakeFirst();
|
|
1036
|
+
if (!token || !hasScope(z.array(z.string()).parse(JSON.parse(token.scopes)), "content:write")) throw new PublicationAuthorizationError("ACTOR_NOT_ALLOWED", "Publication token is unavailable");
|
|
1037
|
+
userId = token.user_id;
|
|
1038
|
+
checks.push(rowUnchanged("_dineway_api_tokens", token), sql`EXISTS (SELECT 1 FROM _dineway_api_tokens WHERE id = ${token.id} AND (expires_at IS NULL OR expires_at > ${currentIsoTimestampValue(db)}))`);
|
|
1039
|
+
} else if (input.actor.authMetadata.auth_method === "oauth_token") {
|
|
1040
|
+
if (!scheduledAutomation) {
|
|
1041
|
+
const hash = getOAuthTokenHash(input.actor);
|
|
1042
|
+
const token = hash ? await db.selectFrom("_dineway_oauth_tokens").select([
|
|
1043
|
+
"token_hash",
|
|
1044
|
+
"token_type",
|
|
1045
|
+
"user_id",
|
|
1046
|
+
"scopes",
|
|
1047
|
+
"expires_at",
|
|
1048
|
+
"client_id"
|
|
1049
|
+
]).where("token_hash", "=", hash).executeTakeFirst() : void 0;
|
|
1050
|
+
if (!token || token.token_type !== "access" || token.user_id !== userId || !hasScope(z.array(z.string()).parse(JSON.parse(token.scopes)), "content:write")) throw new PublicationAuthorizationError("ACTOR_NOT_ALLOWED", "The authenticated OAuth publication token is unavailable");
|
|
1051
|
+
checks.push(rowUnchanged("_dineway_oauth_tokens", token), sql`${token.expires_at} > ${currentIsoTimestampValue(db)}`);
|
|
1052
|
+
}
|
|
1053
|
+
} else if (input.actor.authMetadata.auth_method !== "session") throw new PublicationAuthorizationError("ACTOR_NOT_ALLOWED", "This authentication method requires an atomic authorization provider");
|
|
1054
|
+
const user = await db.selectFrom("users").select([
|
|
1055
|
+
"id",
|
|
1056
|
+
"role",
|
|
1057
|
+
"disabled"
|
|
1058
|
+
]).where("id", "=", userId).executeTakeFirst();
|
|
1059
|
+
const principal = user ? {
|
|
1060
|
+
id: user.id,
|
|
1061
|
+
role: toRoleLevel(user.role)
|
|
1062
|
+
} : null;
|
|
1063
|
+
if (!user || user.disabled || !principal || !canActOnOwn(principal, content.authorId ?? "", "content:publish_own", "content:publish_any") || "publishedAt" in input && input.publishedAt !== void 0 && !hasPermission(principal, "content:publish_any")) throw new PublicationAuthorizationError("ACTOR_NOT_ALLOWED", "Publication permission is no longer available");
|
|
1064
|
+
checks.push(rowUnchanged("users", user));
|
|
1065
|
+
}
|
|
1066
|
+
return checks;
|
|
1067
|
+
}
|
|
1068
|
+
async publishAtomic(input, operation, extra = { statements: [] }) {
|
|
1069
|
+
const db = this.options.db;
|
|
1070
|
+
const snapshot = await new ContentRepository(db).snapshot(input.collection, input.id);
|
|
1071
|
+
if (!snapshot) throw new PublicationAuthorizationError("NOT_FOUND", "Content not found");
|
|
1072
|
+
const checks = [snapshot.check, ...extra.checks ?? []];
|
|
1073
|
+
const ids = [snapshot.item.liveRevisionId, snapshot.item.draftRevisionId].filter((id) => id !== null);
|
|
1074
|
+
const revisions = ids.length ? await db.selectFrom("revisions").selectAll().where("id", "in", ids).execute() : [];
|
|
1075
|
+
checks.push(...revisions.map((row) => rowUnchanged("revisions", row)));
|
|
1076
|
+
const storedReview = await db.selectFrom("_dineway_review_requests").selectAll().where("id", "=", input.editorialReviewRequestId).executeTakeFirst();
|
|
1077
|
+
const confirmation = this.options.preparedReview;
|
|
1078
|
+
const review = confirmation ? {
|
|
1079
|
+
id: confirmation.review.id,
|
|
1080
|
+
status: confirmation.review.status,
|
|
1081
|
+
revoked_at: confirmation.review.revokedAt
|
|
1082
|
+
} : storedReview;
|
|
1083
|
+
if (!review || review.status !== "approved" || review.revoked_at) throw new PublicationAuthorizationError("EDITORIAL_REVIEW_INVALID", "An active editorial approval is required");
|
|
1084
|
+
if (confirmation) {
|
|
1085
|
+
if (operation !== "publish" || confirmation.review.id !== input.editorialReviewRequestId || !isHumanSessionActor(input.actor) || confirmation.review.requestedByActorId !== input.actor.actorId || confirmation.review.resolvedByActorId !== input.actor.actorId || confirmation.authorizationChecks.length === 0) throw new PublicationAuthorizationError("ACTOR_NOT_ALLOWED", "Confirmed publication requires explicit host authority for this review");
|
|
1086
|
+
checks.push(...confirmation.batch.checks ?? [], ...confirmation.authorizationChecks);
|
|
1087
|
+
} else if (storedReview) checks.push(rowUnchanged("_dineway_review_requests", storedReview));
|
|
1088
|
+
const automated = input.actor.actorType === "system" && input.actor.actorId === "review-automation" && input.actor.authMetadata.auth_method === "review_automation";
|
|
1089
|
+
if (!confirmation) checks.push(...await this.atomicActorChecks(input, snapshot.item));
|
|
1090
|
+
if ((input.policyOverrides?.length ?? 0) > 0 && !isHumanSessionActor(input.actor)) throw new PublicationAuthorizationError("POLICY_OVERRIDE_NOT_ALLOWED", "Only a human session can confirm policy warnings");
|
|
1091
|
+
const timezone = await db.selectFrom("options").selectAll().where("name", "=", "site:timezone").executeTakeFirst();
|
|
1092
|
+
checks.push(timezone ? rowUnchanged("options", timezone) : sql`NOT EXISTS (SELECT 1 FROM options WHERE name = 'site:timezone')`);
|
|
1093
|
+
const pluginStates = await db.selectFrom("_plugin_state").selectAll().execute();
|
|
1094
|
+
checks.push(sql`(SELECT COUNT(*) FROM _plugin_state) = ${pluginStates.length}`, ...pluginStates.map((row) => rowUnchanged("_plugin_state", row)));
|
|
1095
|
+
const releaseInput = {
|
|
1096
|
+
...input,
|
|
1097
|
+
operation,
|
|
1098
|
+
siteTimezone: await this.getSiteTimezone()
|
|
1099
|
+
};
|
|
1100
|
+
const baseRelease = await this.buildRelease(releaseInput, []);
|
|
1101
|
+
const reviewJob = await db.selectFrom("_dineway_review_jobs").selectAll().where("review_id", "=", review.id).executeTakeFirst();
|
|
1102
|
+
if (reviewJob) checks.push(rowUnchanged("_dineway_review_jobs", reviewJob));
|
|
1103
|
+
const active = await this.releaseGrants.findActiveForTarget(input.collection, input.id, operation);
|
|
1104
|
+
if (active?.policyContributions.some((contribution) => contribution.reservationId)) throw new PublicationAuthorizationError("RELEASE_POLICY_FAILED", "Reservation policies require a transactional database adapter");
|
|
1105
|
+
const preparedPolicies = [];
|
|
1106
|
+
for (const policy of this.policies) {
|
|
1107
|
+
if (!policy.prepareAtomic || !policy.validateAtomic) throw new PublicationAuthorizationError("RELEASE_POLICY_FAILED", `Policy ${policy.id} does not provide atomic D1 checks`);
|
|
1108
|
+
const prepared = await policy.prepareAtomic(toPreparationTarget(baseRelease, active?.policyContributions ?? [], input.actor, input.policyOverrides ?? []));
|
|
1109
|
+
if (prepared.contribution.providerId !== policy.id || prepared.contribution.reservationId) throw new PublicationAuthorizationError("RELEASE_POLICY_FAILED", "Invalid atomic policy contribution");
|
|
1110
|
+
checks.push(...prepared.checks);
|
|
1111
|
+
preparedPolicies.push({
|
|
1112
|
+
policy,
|
|
1113
|
+
contribution: prepared.contribution
|
|
1114
|
+
});
|
|
1115
|
+
}
|
|
1116
|
+
const release = await this.buildRelease(releaseInput, preparedPolicies.map((prepared) => prepared.contribution));
|
|
1117
|
+
for (const prepared of preparedPolicies) checks.push(...await prepared.policy.validateAtomic(release, prepared.contribution));
|
|
1118
|
+
const hitl = isTokenAuthenticatedActor(input.actor) ? await this.requireApprovedReleaseHitl(releaseInput, release) : null;
|
|
1119
|
+
if (hitl) {
|
|
1120
|
+
const raw = await db.selectFrom("_dineway_hitl_requests").selectAll().where("id", "=", hitl.id).executeTakeFirstOrThrow();
|
|
1121
|
+
checks.push(rowUnchanged("_dineway_hitl_requests", raw));
|
|
1122
|
+
}
|
|
1123
|
+
const preparedGrant = await this.releaseGrants.prepareCreateOrReplaceActive({
|
|
1124
|
+
collection: release.collection,
|
|
1125
|
+
entryId: release.entryId,
|
|
1126
|
+
scope: release.scope,
|
|
1127
|
+
liveRevisionId: release.liveRevisionId,
|
|
1128
|
+
draftRevisionId: release.draftRevisionId,
|
|
1129
|
+
reviewedRev: release.reviewedRev,
|
|
1130
|
+
editorialReviewRequestId: release.editorialReviewRequestId,
|
|
1131
|
+
releaseHitlRequestId: hitl?.id ?? null,
|
|
1132
|
+
operation,
|
|
1133
|
+
scheduledAt: release.scheduledAt,
|
|
1134
|
+
publishedAt: release.publishedAt,
|
|
1135
|
+
siteTimezone: release.siteTimezone,
|
|
1136
|
+
actionHash: release.actionHash,
|
|
1137
|
+
policyContributions: toStoredPolicyContributions(release.policyContributions),
|
|
1138
|
+
authorizationMethod: automated ? "review_automation" : hitl ? "approved_hitl" : "human_action",
|
|
1139
|
+
authorizedByActorType: input.actor.actorType,
|
|
1140
|
+
authorizedByActorId: input.actor.actorId,
|
|
1141
|
+
authorizedAuthMetadata: redactActivityRecord(input.actor.authMetadata),
|
|
1142
|
+
createdAt: this.now()
|
|
1143
|
+
});
|
|
1144
|
+
checks.push(...preparedGrant.batch.checks ?? []);
|
|
1145
|
+
const statements = [...confirmation?.batch.statements ?? [], ...preparedGrant.batch.statements];
|
|
1146
|
+
if (operation === "publish") {
|
|
1147
|
+
const preparedContent = await prepareContentPublication(db, input.collection, input.id, "publishedAt" in input ? { publishedAt: input.publishedAt } : {});
|
|
1148
|
+
checks.push(...preparedContent.batch.checks);
|
|
1149
|
+
statements.push(...preparedContent.batch.statements, db.updateTable("_dineway_content_release_grants").set({
|
|
1150
|
+
status: "consumed",
|
|
1151
|
+
consumed_at: this.now(),
|
|
1152
|
+
updated_at: this.now()
|
|
1153
|
+
}).where("id", "=", preparedGrant.grant.id).where("status", "=", "active").compile());
|
|
1154
|
+
} else {
|
|
1155
|
+
if (!release.scheduledAt || release.scheduledAt <= this.now()) throw new PublicationAuthorizationError("VALIDATION_ERROR", "Scheduled date must be in the future");
|
|
1156
|
+
statements.push(sql`UPDATE ${sql.table(`ec_${input.collection}`)} SET status = CASE WHEN status = 'published' THEN 'published' ELSE 'scheduled' END, scheduled_at = ${release.scheduledAt}, updated_at = ${this.now()} WHERE id = ${input.id}`.compile(db));
|
|
1157
|
+
}
|
|
1158
|
+
statements.push(db.updateTable("_dineway_review_jobs").set({
|
|
1159
|
+
release_state: operation === "publish" ? "published" : "scheduled",
|
|
1160
|
+
release_reason: null,
|
|
1161
|
+
updated_at: this.now()
|
|
1162
|
+
}).where("review_id", "=", review.id).compile());
|
|
1163
|
+
statements.push(this.activity.prepareCreate({
|
|
1164
|
+
...input.actor,
|
|
1165
|
+
authMetadata: redactActivityRecord(input.actor.authMetadata),
|
|
1166
|
+
actionType: release.actionType,
|
|
1167
|
+
subjectType: "content",
|
|
1168
|
+
subjectId: input.id,
|
|
1169
|
+
relatedSubjectType: "review_request",
|
|
1170
|
+
relatedSubjectId: review.id,
|
|
1171
|
+
sourceType: input.sourceType ?? "unknown",
|
|
1172
|
+
sourceName: input.sourceName ?? null,
|
|
1173
|
+
resultStatus: "succeeded",
|
|
1174
|
+
scope: release.scope,
|
|
1175
|
+
summary: `${operation === "publish" ? "Published" : "Scheduled"} ${input.collection}/${input.id}`,
|
|
1176
|
+
detail: {
|
|
1177
|
+
editorialReviewRequestId: review.id,
|
|
1178
|
+
releaseHitlRequestId: hitl?.id ?? null,
|
|
1179
|
+
releaseGrantId: preparedGrant.grant.id,
|
|
1180
|
+
actionHash: release.actionHash,
|
|
1181
|
+
scheduledAt: release.scheduledAt,
|
|
1182
|
+
publishedAt: release.publishedAt
|
|
1183
|
+
},
|
|
1184
|
+
createdAt: this.now()
|
|
1185
|
+
}).statement, ...extra.statements);
|
|
1186
|
+
try {
|
|
1187
|
+
await atomicBatch(db, {
|
|
1188
|
+
checks,
|
|
1189
|
+
statements
|
|
1190
|
+
});
|
|
1191
|
+
} catch (error) {
|
|
1192
|
+
if (error instanceof AtomicWriteConflict) throw new PublicationAuthorizationError("EDITORIAL_REVIEW_INVALID", "Content, approval or publication permissions changed before commit");
|
|
1193
|
+
throw error;
|
|
1194
|
+
}
|
|
1195
|
+
invalidateCollectionCache(input.collection);
|
|
1196
|
+
invalidateRedirectCache();
|
|
1197
|
+
const grant = await this.releaseGrants.findById(preparedGrant.grant.id);
|
|
1198
|
+
if (!grant) throw new Error("Committed release grant is missing");
|
|
1199
|
+
const result = await this.options.handlers.handleContentGet(input.collection, input.id);
|
|
1200
|
+
await this.options.onPublicationCommitted?.(operation, input.collection, input.id, snapshot.item);
|
|
1201
|
+
return {
|
|
1202
|
+
grant,
|
|
1203
|
+
result,
|
|
1204
|
+
receipt: publicationReceipt(grant, operation === "publish" ? "published" : "scheduled")
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
794
1207
|
async authorize(input) {
|
|
795
1208
|
const automated = input.actor.actorType === "system" && input.actor.actorId === "review-automation" && input.actor.authMetadata.auth_method === "review_automation";
|
|
796
1209
|
if (input.actor.actorType === "system") {
|
|
@@ -839,7 +1252,7 @@ var PublicationAuthorizationService = class {
|
|
|
839
1252
|
throw new PublicationAuthorizationError("RELEASE_GRANT_FAILED", error instanceof Error ? error.message : "Failed to authorize content release");
|
|
840
1253
|
}
|
|
841
1254
|
}
|
|
842
|
-
async revalidateScheduledGrant(input, grant, preparedPolicies) {
|
|
1255
|
+
async revalidateScheduledGrant(input, grant, preparedPolicies, atomicChecks) {
|
|
843
1256
|
const now = this.now();
|
|
844
1257
|
if (grant.expiresAt && grant.expiresAt <= now) throw new PublicationAuthorizationError("SCHEDULE_GRANT_EXPIRED", "Schedule grant expired before execution");
|
|
845
1258
|
if (grant.scheduledAt !== input.scheduledAt) throw new PublicationAuthorizationError("SCHEDULE_GRANT_INVALID", "Schedule grant time does not match the due content");
|
|
@@ -930,7 +1343,11 @@ var PublicationAuthorizationService = class {
|
|
|
930
1343
|
const request = grant.releaseHitlRequestId ? await this.hitlRequests.findById(grant.releaseHitlRequestId) : null;
|
|
931
1344
|
if (!request || !matchesReleaseHitl(request, release, grantActor(grant))) throw new PublicationAuthorizationError("SCHEDULE_GRANT_INVALID", "Schedule grant release approval is no longer valid");
|
|
932
1345
|
}
|
|
933
|
-
|
|
1346
|
+
if (atomicChecks) for (const prepared of preparedPolicies) {
|
|
1347
|
+
if (!prepared.policy.validateAtomic || prepared.contribution.reservationId) throw new PublicationAuthorizationError("RELEASE_POLICY_FAILED", "Scheduled policy lacks atomic D1 checks");
|
|
1348
|
+
atomicChecks.push(...await prepared.policy.validateAtomic(release, prepared.contribution));
|
|
1349
|
+
}
|
|
1350
|
+
else await this.validatePolicies(release, preparedPolicies);
|
|
934
1351
|
return release;
|
|
935
1352
|
}
|
|
936
1353
|
async buildRelease(input, policyContributions) {
|
|
@@ -962,7 +1379,12 @@ var PublicationAuthorizationService = class {
|
|
|
962
1379
|
const prepared = [];
|
|
963
1380
|
try {
|
|
964
1381
|
for (const policy of this.policies) {
|
|
965
|
-
|
|
1382
|
+
let contribution;
|
|
1383
|
+
if (isD1Database(this.options.db)) {
|
|
1384
|
+
if (!policy.prepareAtomic) throw new Error(`Policy ${policy.id} does not provide atomic D1 checks`);
|
|
1385
|
+
contribution = (await policy.prepareAtomic(target)).contribution;
|
|
1386
|
+
} else contribution = await policy.prepare(target);
|
|
1387
|
+
if (isD1Database(this.options.db) && contribution.reservationId) throw new Error("D1 policies cannot reserve external state");
|
|
966
1388
|
if (contribution.providerId !== policy.id) throw new Error(`Publication policy ${policy.id} returned another provider ID`);
|
|
967
1389
|
prepared.push({
|
|
968
1390
|
policy,
|
|
@@ -977,7 +1399,10 @@ var PublicationAuthorizationService = class {
|
|
|
977
1399
|
}
|
|
978
1400
|
async validatePolicies(release, preparedPolicies) {
|
|
979
1401
|
try {
|
|
980
|
-
for (const prepared of preparedPolicies)
|
|
1402
|
+
for (const prepared of preparedPolicies) if (isD1Database(this.options.db)) {
|
|
1403
|
+
if (!prepared.policy.validateAtomic) throw new Error(`Policy ${prepared.policy.id} does not provide atomic D1 checks`);
|
|
1404
|
+
await prepared.policy.validateAtomic(release, prepared.contribution);
|
|
1405
|
+
} else await prepared.policy.validate(release, prepared.contribution);
|
|
981
1406
|
} catch (error) {
|
|
982
1407
|
throw new PublicationAuthorizationError("RELEASE_POLICY_FAILED", error instanceof Error ? error.message : "Publication release policy rejected release");
|
|
983
1408
|
}
|
|
@@ -991,6 +1416,7 @@ var PublicationAuthorizationService = class {
|
|
|
991
1416
|
for (const prepared of preparedPolicies) await prepared.policy.consume?.(prepared.contribution);
|
|
992
1417
|
}
|
|
993
1418
|
async releasePolicies(preparedPolicies, reason) {
|
|
1419
|
+
if (isD1Database(this.options.db)) return;
|
|
994
1420
|
for (const prepared of preparedPolicies.toReversed()) await prepared.policy.release?.(prepared.contribution, reason);
|
|
995
1421
|
}
|
|
996
1422
|
async releaseReplacedPolicies(contributions, currentPolicies) {
|