fix(content): validate complete content before publication - #3842
khoinguyenpham04 wants to merge 1 commit into
Conversation
🦋 Changeset detectedLatest commit: d9f13e6 The changes in this PR will be included in the next version bump. This PR includes changesets to release 12 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
docs | d9f13e6 | Oct 04 2026, 08:05 PM |
Scope checkThis PR changes 777 lines across 6 files. Large PRs are harder to review and more likely to be closed without review. If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs. See CONTRIBUTING.md for contribution guidelines. |
🚀 Deploying Preview to Cloudflare 🚀Preview URL: https://noah-content-publish-validation.try.emdashcms.com, https://noah-content-publish-validation-emdash-playground.emdash-cms.workers.dev (commit d9f13e6)This URL reflects your latest Preview deploymentPreview Deployments by commit
|
There was a problem hiding this comment.
This PR is the right fix for the content-safety audit finding: it enforces complete schema validation before any publication, using the existing validateContentData / validateMediaFields / validateStagedReferences helpers, and it adds an optimistic fence on the validated row snapshot so a concurrent edit cannot cause the validator and the publisher to see different content. The distinction between publish (which can promote a draft) and an explicit status: "published" update (which only validates the live row it writes) is correct and consistent with the revision model.
I traced the changed paths in packages/core/src/api/handlers/content.ts and validation.ts, the runtime draft-staging flow in emdash-runtime.ts, the repository publish/update implementation, and the staged-references.ts / validate-references.ts helpers. I also checked the REST docs and the changeset against .changeset/README.md.
Everything looks sound:
- Field-schema errors still return
VALIDATION_ERRORwithdetails.issues, and media MIME errors still returnINVALID_MIME_FOR_FIELD. - Required live references are validated in both
handleContentPublishand explicit status updates. - Partial saves and scheduled invalid entries are left alone, as intended.
- No SQL interpolation, no authorization bypass, no new logged-out queries, and no AGENTS.md convention violations were introduced.
- The new tests cover SQLite/PostgreSQL and D1, including contention fences.
No blocking issues found.
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-test
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/registry-loader
@emdash-cms/registry-moderation
@emdash-cms/registry-verification
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
e917323 to
d9f13e6
Compare
What does this PR do?
Fourth layer of the content-safety stack, based on #3840. The lower layers are #3832 (atomic saves), #3834 (manual Save history), and #3840 (on-page revision safety).
Publish validates the complete effective draft/live snapshot against the current schema before promoting references or content. It includes media MIME restrictions and required reference selections, preserves existing error codes, and retains structured field-schema issues.
Explicit
status: "published"updates validate the live fields and references they actually write; they do not promote revision-backed drafts. Publication also fences the validated row snapshot, including blind callers. Partial saves and historical revisions with retired fields remain supported. Invalid scheduled entries stay scheduled for correction and retry.This does not redesign scheduling, hooks, reference/taxonomy leases, or concurrent schema changes. No existing issue is linked; this fixes independently reproduced findings from the content-safety audit.
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runmessages.pochanges except in translation PRs — a workflow extracts catalogs on merge tomain.Admin-string localization and UI screenshots are not applicable: this layer changes server validation and REST documentation. A feature Discussion is not applicable to this bug fix.
AI-generated code disclosure
Screenshots / test output
Screenshots: Not applicable; no UI changes.
pnpm format, rootpnpm build, package/demo typechecks, full/quick lint, zero JSON lint diagnostics, docs build, and diff checks pass.Remote CI is not verified; the Codex CI connection currently requires sign-in. These results are local validation, not a claim that GitHub checks are green.