Skip to content

fix(core): pass site context to trusted plugin routes#2080

Open
logelog wants to merge 1 commit into
emdash-cms:mainfrom
logelog:fix/plugin-route-site-info
Open

fix(core): pass site context to trusted plugin routes#2080
logelog wants to merge 1 commit into
emdash-cms:mainfrom
logelog:fix/plugin-route-site-info

Conversation

@logelog

@logelog logelog commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Passes the runtime's configured site context into trusted plugin API route contexts. Route handlers now receive the same normalized ctx.site data as plugin hooks, and ctx.url(path) returns an absolute URL when a site URL is configured.

The route registry was previously created with database and storage dependencies but without siteInfo, so it fell back to an empty site context.

Closes #1813

Type of change

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

Checklist

  • I have read CONTRIBUTING.md
  • pnpm --filter emdash typecheck passes
  • Type-aware lint passes for the changed source and test files
  • Targeted tests pass
  • Formatting checks pass
  • I added a regression test
  • No admin UI strings were added
  • A patch changeset is included

Validation

  • pnpm --filter emdash typecheck
  • pnpm --filter emdash build
  • pnpm --filter emdash check
  • vitest run tests/integration/runtime/plugin-route-site-info.test.ts
  • oxlint --type-aware --deny-warnings on changed source and test files
  • oxfmt --check on changed source and test files
  • prettier --check .changeset/plugin-route-site-context.md

@changeset-bot

changeset-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f9f3391

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

This PR includes changesets to release 16 packages
Name Type
emdash Patch
@emdash-cms/cloudflare Patch
@emdash-cms/sandbox-workerd Patch
@emdash-cms/fixture-perf-site Patch
@emdash-cms/perf-demo-site Patch
@emdash-cms/cache-demo-site Patch
@emdash-cms/do-demo-site Patch
@emdash-cms/do-solo-demo-site Patch
@emdash-cms/admin Patch
@emdash-cms/auth Patch
@emdash-cms/blocks Patch
@emdash-cms/gutenberg-to-portable-text Patch
@emdash-cms/x402 Patch
create-emdash 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

@logelog
logelog marked this pull request as ready for review July 16, 2026 22:13
@github-actions github-actions Bot added the review/needs-review No maintainer or bot review yet label Jul 16, 2026

@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 is the right fix for the reported issue: trusted plugin API routes were getting their context factory built from a partial options bag (db + storage) while plugin hooks were built from pipelineFactoryOptions, which includes siteInfo. Reusing this.pipelineFactoryOptions in handlePluginApiRoute aligns the two paths with the smallest possible surface change and is consistent with the existing media:write fix that also broadened the options passed to the route registry.

I checked:

  • The diff in packages/core/src/emdash-runtime.ts: PluginRouteRegistry now receives ...this.pipelineFactoryOptions, which carries siteInfo and getDb, plus the previously-passed emailPipeline and trustedProxyHeaders.
  • packages/core/src/plugins/routes.ts and packages/core/src/plugins/context.ts: PluginRouteRegistry stores a PluginContextFactoryOptions and uses it to create a PluginContextFactory; the factory normalizes siteInfo into ctx.site and builds ctx.url() from the configured base URL.
  • packages/core/src/emdash-runtime.ts (EmDashRuntime.create): pipelineFactoryOptions is already built with db, getDb, storage, and siteInfo, so trusted routes now pick up the same snapshot as hooks.
  • The new regression test packages/core/tests/integration/runtime/plugin-route-site-info.test.ts: it manually constructs a runtime whose pipelineFactoryOptions carry siteInfo, invokes a trusted route, and asserts both ctx.site shape and an absolute ctx.url() output.
  • The changeset .changeset/plugin-route-site-context.md: correctly scoped to emdash: patch, user-facing, present-tense, describes the observable fix.

No logic bugs, authorization gaps, SQL issues, locale-filter issues, or convention violations. The sandboxed-plugin route path is intentionally untouched by this PR (it uses a different, sandbox-isolated invocation), and the standalone PluginManager route registry is not exercised by the production route dispatch path, so I did not flag it. Clean to merge.

@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 Jul 17, 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.

Trusted plugin routes get empty site info — ctx.url() returns relative paths

1 participant