Skip to content

fix(content): validate complete content before publication - #3842

Closed
khoinguyenpham04 wants to merge 1 commit into
noah/content-visual-revisionsfrom
noah/content-publish-validation
Closed

khoinguyenpham04 wants to merge 1 commit into
noah/content-visual-revisionsfrom
noah/content-publish-validation

Conversation

@khoinguyenpham04

Copy link
Copy Markdown
Collaborator

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

  • Bug fix
  • Feature (requires maintainer-approved Discussion)
  • Refactor (no behavior change)
  • Translation
  • Documentation
  • Performance improvement
  • Tests
  • Chore (dependencies, CI, tooling)

Checklist

  • I have read CONTRIBUTING.md
  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm test passes (or targeted tests for my change)
  • pnpm format has been run
  • I have added/updated tests for my changes (if applicable)
  • User-visible strings in the admin UI are wrapped for translation (if applicable). Do not include messages.po changes except in translation PRs — a workflow extracts catalogs on merge to main.
  • I have added and reviewed the user-facing changeset (if this PR changes a published package)
  • New features link to an approved Discussion: https://github.com/emdash-cms/emdash/discussions/...
  • I have included screenshots below if this PR changes the UI

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

  • This PR includes AI-generated code — model/tool: Codex, GPT-6.1 Sol (max). Persistent second-opinion review: GPT-5.6 (xhigh), clean and converged on pass 2.

Screenshots / test output

Screenshots: Not applicable; no UI changes.

  • 12 initial SQLite/PostgreSQL regressions fail on the parent for missing required fields; 8 additional contention assertions fail when the publication fences are temporarily removed.
  • 14 additional assertions reproduce the review's MIME and required-live-reference gaps before their fixes.
  • 66 focused SQLite/PostgreSQL cases pass; the broader validation/media/references/lifecycle/MCP/CAS/scheduler suite passes 242 cases, including those focused cases.
  • 10 real D1 cases pass, covering required fields, MIME refusals, actual live reference selections, and contention.
  • Current pnpm format, root pnpm 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.

@changeset-bot

changeset-bot Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: d9f13e6

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/plugin-test Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
create-emdash Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
@emdash-cms/auth-atproto Patch
@emdash-cms/plugin-embeds Patch

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
docs d9f13e6 Oct 04 2026, 08:05 PM

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Scope check

This 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.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

🚀 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 deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://33a8f450.try.emdashcms.com, https://33a8f450-emdash-playground.emdash-cms.workers.dev d9f13e6 2026-10-04T20:06:15.431Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://c7683bed.try.emdashcms.com, https://c7683bed-emdash-playground.emdash-cms.workers.dev e917323 2026-10-03T23:44:43.023Z Visit the dashboard ↗

@emdashbot emdashbot Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_ERROR with details.issues, and media MIME errors still return INVALID_MIME_FOR_FIELD.
  • Required live references are validated in both handleContentPublish and 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.

@github-actions github-actions Bot added review/approved Approved; no new commits since and removed review/needs-review No maintainer or bot review yet labels Oct 3, 2026
@khoinguyenpham04
khoinguyenpham04 added this pull request to stack #3844 October 4, 2026 01:18
@pkg-pr-new

pkg-pr-new Bot commented Oct 4, 2026

Copy link
Copy Markdown

Open in StackBlitz

@emdash-cms/admin

npm i https://pkg.pr.new/@emdash-cms/admin@3842

@emdash-cms/auth

npm i https://pkg.pr.new/@emdash-cms/auth@3842

@emdash-cms/auth-atproto

npm i https://pkg.pr.new/@emdash-cms/auth-atproto@3842

@emdash-cms/blocks

npm i https://pkg.pr.new/@emdash-cms/blocks@3842

@emdash-cms/cloudflare

npm i https://pkg.pr.new/@emdash-cms/cloudflare@3842

@emdash-cms/contentful-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/contentful-to-portable-text@3842

emdash

npm i https://pkg.pr.new/emdash@3842

create-emdash

npm i https://pkg.pr.new/create-emdash@3842

@emdash-cms/gutenberg-to-portable-text

npm i https://pkg.pr.new/@emdash-cms/gutenberg-to-portable-text@3842

@emdash-cms/plugin-cli

npm i https://pkg.pr.new/@emdash-cms/plugin-cli@3842

@emdash-cms/plugin-test

npm i https://pkg.pr.new/@emdash-cms/plugin-test@3842

@emdash-cms/plugin-types

npm i https://pkg.pr.new/@emdash-cms/plugin-types@3842

@emdash-cms/registry-client

npm i https://pkg.pr.new/@emdash-cms/registry-client@3842

@emdash-cms/registry-lexicons

npm i https://pkg.pr.new/@emdash-cms/registry-lexicons@3842

@emdash-cms/registry-loader

npm i https://pkg.pr.new/@emdash-cms/registry-loader@3842

@emdash-cms/registry-moderation

npm i https://pkg.pr.new/@emdash-cms/registry-moderation@3842

@emdash-cms/registry-verification

npm i https://pkg.pr.new/@emdash-cms/registry-verification@3842

@emdash-cms/sandbox-workerd

npm i https://pkg.pr.new/@emdash-cms/sandbox-workerd@3842

@emdash-cms/x402

npm i https://pkg.pr.new/@emdash-cms/x402@3842

@emdash-cms/plugin-ai-moderation

npm i https://pkg.pr.new/@emdash-cms/plugin-ai-moderation@3842

@emdash-cms/plugin-atproto

npm i https://pkg.pr.new/@emdash-cms/plugin-atproto@3842

@emdash-cms/plugin-audit-log

npm i https://pkg.pr.new/@emdash-cms/plugin-audit-log@3842

@emdash-cms/plugin-color

npm i https://pkg.pr.new/@emdash-cms/plugin-color@3842

@emdash-cms/plugin-embeds

npm i https://pkg.pr.new/@emdash-cms/plugin-embeds@3842

@emdash-cms/plugin-field-kit

npm i https://pkg.pr.new/@emdash-cms/plugin-field-kit@3842

@emdash-cms/plugin-forms

npm i https://pkg.pr.new/@emdash-cms/plugin-forms@3842

@emdash-cms/plugin-webhook-notifier

npm i https://pkg.pr.new/@emdash-cms/plugin-webhook-notifier@3842

commit: e917323

@khoinguyenpham04
khoinguyenpham04 force-pushed the noah/content-publish-validation branch from e917323 to d9f13e6 Compare October 4, 2026 20:03
@khoinguyenpham04 khoinguyenpham04 mentioned this pull request Oct 4, 2026
8 of 19 tasks
@khoinguyenpham04
khoinguyenpham04 removed this pull request from stack #3844 October 4, 2026 20:12
@khoinguyenpham04
khoinguyenpham04 added this pull request to stack #3866 October 4, 2026 20:12
@github-actions github-actions Bot added review/needs-rereview Author pushed changes since the last review and removed review/approved Approved; no new commits since labels Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant