Skip to content

Added a shared initializer for IndexNow and signing keys - #31701

Open
ErisDS wants to merge 7 commits into
mainfrom
codex/two-service-initializer-preview
Open

ErisDS wants to merge 7 commits into
mainfrom
codex/two-service-initializer-preview

Conversation

@ErisDS

@ErisDS ErisDS commented Oct 10, 2026

Copy link
Copy Markdown
Member

Start standardizing service initialization with IndexNow and signing keys. Both now use a small kernel helper that shares initialization, exposes the ready instance through .service, and permits an explicit retry after failure. Boot owns when each service starts and awaits readiness.

IndexNow rolls back partial event subscriptions if startup fails. Signing-key background scheduling keeps its existing owner. The inventory records 2 of 72 entries migrated and validates those counts.

Verification:

  • Passed: pnpm test:types from ghost.

  • Passed: pnpm exec vitest run test/unit/server/services/service-inventory.test.ts from ghost (74 tests).

  • Passed: real Ghost boot on a fresh MySQL database; both instances ready, one IndexNow listener per event, staff/member key providers available, and both verification endpoints returning 200. Site and Admin also loaded in the browser.

  • Full validation is not clean locally. NX_PARALLEL=1 pnpm check passed formatting, lint and the other workspace tests, but Core timed out in the unchanged jobs shutdown-deadline test. A retry exited with code 139. pnpm exec vitest run --maxWorkers=2 then passed 9,760 tests and timed out in the unchanged gift-preview image test. Both affected files passed when run individually.

  • I've read and followed the Contributor Guide

  • I've explained my change

  • I've written an automated test to prove my change works

no ref

Use one initializer so synchronous subscriptions and asynchronous key checks share readiness and retry behavior. Keep job registration in its existing background phase, and undo partial IndexNow subscriptions when startup fails.
no ref

Give runtime framework code a clear home alongside server and frontend. Move the initializer and its tests without changing behavior, document the boundary, and include the directory in lint and dependency checks.
no ref

Keep kernel primitives independent of Ghost application code, including shared. Document the intended dependency direction and enforce it across the Ghost package.
no ref

Keep the familiar .service access while guarding against use before
initialization. Export the signing-keys wrapper intact so imports don't
read the getter before boot, and update its callers and tests.
no ref

Use the same service terminology as the rest of the initializer.
no ref

Track adoption of the shared initializer separately from contract audits, with validated total and migrated counts. Refresh the first two migrated service records against their current implementation.
@nx-cloud

nx-cloud Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

🤖 Nx Cloud AI Fix

Ensure the fix-ci command is configured to always run in your CI pipeline to get automatic fixes in future runs. For more information, please see https://nx.dev/ci/features/self-healing-ci


View your CI Pipeline Execution ↗ for commit e9f92d7

Command Status Duration Result
nx run ghost:test:ci:integration ✅ Succeeded 2m 44s View ↗
nx run ghost:test:ci:e2e ✅ Succeeded 5m 19s View ↗
nx run ghost:test:integration ✅ Succeeded 1m 38s View ↗
nx run ghost:test:legacy ✅ Succeeded 3m 2s View ↗
nx run ghost:test:e2e ✅ Succeeded 2m 55s View ↗
nx run ghost:test:ci:unit ✅ Succeeded 1m 20s View ↗
nx run-many -t test:unit -p ghost ✅ Succeeded 1m View ↗
nx run ghost-monorepo:lint:boundaries ✅ Succeeded 18s View ↗
Additional runs (6) ✅ Succeeded ... View ↗

💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗


☁️ Nx Cloud last updated this comment at 2026-10-10 07:22:19 UTC

@coderabbitai

coderabbitai Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: TryGhost/Ghost/.coderabbit.yaml
  • Review profile: QUIET
  • Plan: Essentials
  • Run ID: 3d588e7f-9bb3-4c71-93fc-a0e4f70c2539

📥 Commits

Reviewing files that changed from the base of the PR and between c23e8de and 5103a27.


📒 Files selected for processing (23)
  • .dependency-cruiser.cjs
  • .lintstagedrc.cjs
  • docs/codebase/monorepo-structure.md
  • ghost/core/boot.js
  • ghost/core/kernel/README.md
  • ghost/core/kernel/define-service.ts
  • ghost/core/server/services/README.md
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • ghost/core/server/services/members/api.js
  • ghost/core/server/services/service-inventory.yaml
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/core/server/web/well-known.js
  • ghost/eslint.config.mjs
  • ghost/package.json
  • ghost/test/unit/boot-signing-keys.test.ts
  • ghost/test/unit/kernel/define-service.test.ts
  • ghost/test/unit/server/services/indexnow-ping/index.test.ts
  • ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts
  • ghost/test/unit/server/services/service-inventory.test.ts
  • ghost/test/unit/server/services/signing-keys/index.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📜 Recent review details
⏰ Context from checks skipped due to timeout. (5)
  • GitHub Check: Legacy tests (Node 24.20.0, mysql8)
  • GitHub Check: Acceptance tests (Node 22.23.3, mysql8)
  • GitHub Check: Acceptance tests (Node 24.20.0, mysql8)
  • GitHub Check: Build Docker Images
  • GitHub Check: Legacy tests (Node 22.23.3, mysql8)

🧰 Additional context used
📚 Code guidelines (4)
docs/codebase/monorepo-structure.md — configured
docs/codebase/jobs.md — configured
docs/contributing/testing.md — configured
docs/practices/error-handling.md — configured

📓 Path-based instructions (10)
Review new or changed service boundaries for explicit dependency ownership, deterministic/idempotent initialisation, boot ordering, transaction and event semantics, cache coherence, and restart/multi-instance safety.

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/core/server/services/members/api.js
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • ghost/core/server/services/README.md
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js
  • ghost/core/server/services/service-inventory.yaml

Review whether tests prove changed behaviour, meaningful error/edge paths, and externally observable contracts without coupling to implementation details.

⚙️ CodeRabbit configuration file

Files:

  • ghost/test/unit/boot-signing-keys.test.ts
  • ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts
  • ghost/test/unit/server/services/service-inventory.test.ts
  • ghost/test/unit/kernel/define-service.test.ts
  • ghost/test/unit/server/services/indexnow-ping/index.test.ts
  • ghost/test/unit/server/services/signing-keys/index.test.ts

New source files must be TypeScript: flag new JS files as a required change unless exempt (DB migrations, apps/ember-admin/, tool/config files, scripts/, docker/, generated code).

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/server/services/members/api.js
  • ghost/eslint.config.mjs
  • ghost/core/boot.js
  • ghost/core/server/web/well-known.js
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js

Review lens: "where does this data become trusted?" Boundary data (HTTP input, external API/SDK responses, env/config, DB/filesystem reads, queue/webhook/event payloads) is `unknown` until validated — Zod by default.

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/test/unit/boot-signing-keys.test.ts
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts
  • ghost/test/unit/server/services/service-inventory.test.ts
  • ghost/core/kernel/define-service.ts
  • ghost/test/unit/kernel/define-service.test.ts
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/test/unit/server/services/indexnow-ping/index.test.ts
  • ghost/test/unit/server/services/signing-keys/index.test.ts

Check technical claims, paths, commands, and declared authority/status against the current repository.

⚙️ CodeRabbit configuration file

Files:

  • docs/codebase/monorepo-structure.md

Prioritise concrete correctness, security, data-integrity, compatibility, and regression risks.

⚙️ CodeRabbit configuration file

Files:

  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/test/unit/boot-signing-keys.test.ts
  • ghost/package.json
  • ghost/core/server/services/members/api.js
  • ghost/eslint.config.mjs
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • docs/codebase/monorepo-structure.md
  • ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts
  • ghost/core/boot.js
  • ghost/core/server/web/well-known.js
  • ghost/core/server/services/README.md
  • ghost/test/unit/server/services/service-inventory.test.ts
  • ghost/core/kernel/README.md
  • ghost/core/kernel/define-service.ts
  • ghost/test/unit/kernel/define-service.test.ts
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js
  • ghost/test/unit/server/services/indexnow-ping/index.test.ts
  • ghost/test/unit/server/services/signing-keys/index.test.ts
  • ghost/core/server/services/service-inventory.yaml

Source excerpt: Built Admin assets are copied into `ghost/core/built/admin/` for the Ghost release.

📄 CodeRabbit inference engine (docs/codebase/monorepo-structure.md)

Files:

  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/test/unit/boot-signing-keys.test.ts
  • ghost/package.json
  • ghost/core/server/services/members/api.js
  • ghost/eslint.config.mjs
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts
  • ghost/core/boot.js
  • ghost/core/server/web/well-known.js
  • ghost/core/server/services/README.md
  • ghost/test/unit/server/services/service-inventory.test.ts
  • ghost/core/kernel/README.md
  • ghost/core/kernel/define-service.ts
  • ghost/test/unit/kernel/define-service.test.ts
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js
  • ghost/test/unit/server/services/indexnow-ping/index.test.ts
  • ghost/test/unit/server/services/signing-keys/index.test.ts
  • ghost/core/server/services/service-inventory.yaml

Source excerpt: Jobs run in-process and share the main process's initialized services.

📄 CodeRabbit inference engine (docs/codebase/jobs.md)

Files:

  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/core/server/services/members/api.js
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • ghost/core/server/services/README.md
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js
  • ghost/core/server/services/service-inventory.yaml

Source excerpt: Ghost has several test suites across the monorepo.

📄 CodeRabbit inference engine (docs/contributing/testing.md)

Files:

  • ghost/test/unit/boot-signing-keys.test.ts
  • ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts
  • ghost/test/unit/server/services/service-inventory.test.ts
  • ghost/test/unit/kernel/define-service.test.ts
  • ghost/test/unit/server/services/indexnow-ping/index.test.ts
  • ghost/test/unit/server/services/signing-keys/index.test.ts

Source excerpt: Errors are part of the product experience.

📄 CodeRabbit inference engine (docs/practices/error-handling.md)

Files:

  • ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts
  • ghost/core/server/services/members/api.js
  • ghost/core/server/services/jobs-service/register-job-handlers.ts
  • ghost/core/server/web/well-known.js
  • ghost/core/server/services/README.md
  • ghost/core/server/services/indexnow-ping/index.ts
  • ghost/core/server/services/signing-keys/index.ts
  • ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js
  • ghost/core/server/services/service-inventory.yaml

🧠 Learnings (1)
📓 Common learnings
Learnt from: CR
Repo: TryGhost/Ghost

Timestamp: 2026-10-10T06:43:14.600Z
Learning: Source excerpt:
# Ghost Core services

## Implementation and migration

The summary counts all inventory entries in `total` and entries marked
`migrated: true` in `migrated`. Mark a root as migrated once it uses the
[kernel's `defineService` initializer](../../kernel/README.md#service-initialization).
IndexNow and signing keys are the first two. This tracks adoption of the
initializer, independently of audit completeness or remaining lifecycle work.
Update the summary when entries or migration markers change; the inventory test
checks both counts.
Learnt from: CR
Repo: TryGhost/Ghost

Timestamp: 2026-10-10T06:43:14.600Z
Learning: Source excerpt:
# Ghost Core services

## Implementation and migration

The summary counts all inventory entries in `total` and entries marked
`migrated: true` in `migrated`. Mark a root as migrated once it uses the
[kernel's `defineService` initializer](../../kernel/README.md#service-initialization).
IndexNow and signing keys are the first two. This tracks adoption of the
initializer, independently of audit completeness or remaining lifecycle work.
Update the summary when entries or migration markers change; the inventory test
checks both counts.

🔇 Additional comments (22)
.dependency-cruiser.cjs (1)

27-34: LGTM!


ghost/core/kernel/README.md (1)

1-24: LGTM!


ghost/test/unit/kernel/define-service.test.ts (1)

1-91: LGTM!


docs/codebase/monorepo-structure.md (1)

49-56: LGTM!


.lintstagedrc.cjs (1)

138-138: LGTM!


ghost/eslint.config.mjs (1)

88-93: LGTM!


ghost/package.json (1)

75-80: LGTM!


ghost/core/server/services/signing-keys/index.ts (1)

2-34: LGTM!


ghost/core/boot.js (1)

147-147: LGTM!


ghost/core/server/services/jobs-service/register-job-handlers.ts (1)

27-27: LGTM!

Also applies to: 136-136


ghost/core/server/services/members/api.js (1)

26-26: LGTM!

Also applies to: 64-64


ghost/core/server/services/identity-tokens/identity-token-service-wrapper.js (1)

15-18: LGTM!


ghost/core/server/web/well-known.js (1)

4-9: LGTM!


ghost/test/unit/boot-signing-keys.test.ts (1)

27-27: LGTM!


ghost/test/unit/server/services/signing-keys/index.test.ts (1)

25-237: LGTM!


ghost/core/server/services/service-inventory.yaml (1)

4-6: LGTM!


ghost/test/unit/server/services/jobs-service/register-job-handlers.test.ts (1)

30-30: LGTM!

Also applies to: 63-63, 274-274


ghost/core/server/services/indexnow-ping/index.ts (1)

1-22: LGTM!


ghost/core/server/services/indexnow-ping/indexnow-ping-service.ts (1)

336-340: LGTM!


ghost/test/unit/server/services/indexnow-ping/index.test.ts (1)

125-159: LGTM!


ghost/core/server/services/README.md (1)

66-73: LGTM!

Also applies to: 121-121


ghost/test/unit/server/services/service-inventory.test.ts (1)

34-34: LGTM!

Also applies to: 48-53, 75-80



Walkthrough

Adds defineService in the kernel and applies it to the signing-keys and IndexNow services. Updates service consumers to use the new service getter. Adds cleanup and retry coverage for failed IndexNow initialization, plus tests for shared initialization and retries. Adds kernel dependency and lint coverage. Updates service inventory metadata and count validation.

Suggested reviewers: acburdine

Priority: ➖ Normal

Change: Feature

Merge Risk: ⚪ Minimal · up to 5103a

No actionable issue remains from this review; the change is mergeable subject to normal checks.

Pre-merge checks | Passed 6
✅ Passed checks (6 passed)
Check name Status Explanation
Title check Passed The title clearly summarizes the main change: adding a shared initializer for IndexNow and signing keys.
Description check Passed The description directly explains the initializer, service readiness, retry behavior, rollback handling, inventory updates, and validation results.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Type-Safe Boundaries Passed The changed runtime code adds no unvalidated boundary-data consumption. defineService is a typed internal factory, and the IndexNow and signing-key changes only assemble existing dependencies, initi…
New Files Are Typescript Passed The pull request adds only ghost/core/kernel/README.md, ghost/core/kernel/define-service.ts, and ghost/test/unit/kernel/define-service.test.ts. It adds no .js, .jsx, .cjs, or .mjs files.…

✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR


🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.62500% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.64%. Comparing base (c23e8de) to head (e9f92d7).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
ghost/core/server/services/indexnow-ping/index.ts 71.42% 2 Missing ⚠️
ghost/core/server/services/signing-keys/index.ts 66.66% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #31701      +/-   ##
==========================================
+ Coverage   81.40%   81.64%   +0.23%     
==========================================
  Files        1653     1654       +1     
  Lines       60268    60273       +5     
  Branches    10544    10542       -2     
==========================================
+ Hits        49064    49209     +145     
+ Misses       9584     9464     -120     
+ Partials     1620     1600      -20     
Flag Coverage Δ
e2e-tests 72.35% <84.21%> (-0.03%) ⬇️
unit-tests 67.59% <85.71%> (+0.31%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Explain which startup guarantees belong to defineService and which
cleanup belongs to its callback. Put the contract in developer guides
and link it from the API comment.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant