Skip to content
This repository was archived by the owner on Apr 7, 2026. It is now read-only.

refactor: migrate holyship to bootPlatformServer - #259

Merged
TSavo merged 1 commit into
mainfrom
refactor/boot-platform-server
Mar 26, 2026
Merged

TSavo merged 1 commit into
mainfrom
refactor/boot-platform-server

Conversation

@TSavo

@TSavo TSavo commented Mar 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Replace manual platform boot (DB, migrations, auth, credits, org, gateway) with bootPlatformServer() from platform-core
  • Delete app.ts — Hono app, CORS, health endpoint now handled by boot
  • Use createTRPCContext from core instead of local copy
  • Engine DB created from container.pool instead of old singleton
  • All product-specific code stays: engine, flows, github, worker pool, ship-it, notification pipeline
  • Bump platform-core to 1.71.0

Test plan

  • npm run check passes (biome + tsc)
  • CI passes
  • Verify engine + worker pool boot in staging

🤖 Generated with Claude Code

Note

Migrate holyship server boot to bootPlatformServer from platform-core

  • Replaces the manual server setup (direct @hono/node-server usage and src/app.ts) with bootPlatformServer from @wopr-network/platform-core, which provides the Hono app instance and a shared service container.
  • BetterAuth, tRPC, inference gateway, and all route mounts are now wired onto the platform app using container-provided services (db, pool, creditLedger, orgService, etc.).
  • createTRPCContext is now imported from platform-core/trpc instead of defined locally, which may change how user and tenantId are populated in tRPC procedures.
  • Risk: The crypto webhook route (/api/webhooks/crypto) and the explicit /health endpoint are removed and will no longer be served by this module.

Macroscope summarized 3acd750.

Summary by CodeRabbit

  • Chores
    • Updated platform core dependency to the latest compatible version, which may include performance improvements and internal enhancements.
    • Refactored internal server initialization and configuration architecture for improved maintainability.

Replace manual platform boot sequence with bootPlatformServer() from
platform-core. Keeps all product-specific code (engine, flows, github,
worker pool, ship-it) as route plugins on platform.app.

- Delete app.ts (Hono app, CORS, health now handled by boot)
- Use createTRPCContext from core instead of local copy
- Engine DB created from container.pool
- Engine migrations run after platform boot
- Bump platform-core to 1.71.0

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @TSavo, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented Mar 26, 2026 •

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The changes consolidate application boot logic by replacing manual sequential setup with a single bootPlatformServer() call, removing the standalone app configuration file, and reorganizing dependency injection patterns for database, authentication, and tRPC wiring. The @wopr-network/platform-core dependency is updated to version ^1.71.0.

Changes

Cohort / File(s) Summary
Dependency Management
package.json
Updated @wopr-network/platform-core from ^1.67.1 to ^1.71.0.
Application Bootstrap & Routing Refactoring
src/app.ts, src/index.ts
Removed standalone app configuration file (src/app.ts); consolidated boot sequence in src/index.ts by replacing manual DB/auth/middleware setup with bootPlatformServer() call. Updated BetterAuth handler mounting, tRPC context creation, engine DB initialization, and server lifecycle management (serve() → platform.start()/stop()). Removed global product config cache and crypto webhook logic.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 The boot sequence hops with grace,
One call to rule them all in place,
Dependencies aligned so neat,
Auth and tRPC skip and beat,
Platform Core now leads the way,
A simpler start to greet the day!

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'refactor: migrate holyship to bootPlatformServer' directly and accurately describes the main change: replacing the manual platform boot sequence with bootPlatformServer() from platform-core.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/boot-platform-server

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions

Copy link
Copy Markdown

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 46.76% 1519 / 3248
🔵 Statements 46.86% 1668 / 3559
🔵 Functions 43.75% 259 / 592
🔵 Branches 47.87% 1162 / 2427
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
src/index.ts 0% 0% 0% 0%
Generated in workflow #1190 for commit 3acd750 by the Vitest Coverage Report Action

@TSavo
TSavo added this pull request to the merge queue Mar 26, 2026
@greptile-apps

greptile-apps Bot commented Mar 26, 2026

Copy link
Copy Markdown

Greptile Summary

This PR replaces holyship's manual platform boot sequence (DB, migrations, auth, credits, org, gateway) with a single bootPlatformServer() call from platform-core 1.71.0, deletes src/app.ts, and reuses createTRPCContext from core. All product-specific initialization (engine, flows, GitHub, worker pool, notification pipeline) is preserved and mounted on the app returned by the platform boot.\n\nKey changes:\n- bootPlatformServer() now owns DB connection, platform migrations, product config, credits ledger, org service, and server lifecycle (start()/stop())\n- Engine DB is now created via drizzle(container.pool, { schema: engineSchema }) instead of a separate singleton\n- createTRPCContext and setTrpcOrgMemberRepo imported from platform-core instead of local copies\n- platform-core bumped from 1.67.1 → 1.71.0, pulling in @aws-sdk/client-ses and @wopr-network/platform-crypto-server as new transitive deps\n\nIssues found:\n- The crypto payment webhook block (old step 13: setCryptoWebhookDeps + app.route(\"/api/webhooks/crypto\", ...)) has been completely removed. CRYPTO_WEBHOOK_SECRET is not forwarded to bootPlatformServer(), so if platform-core doesn't internally reconstruct the route, incoming payment confirmations will silently 404 and users won't be credited.\n- container.productConfig is accessed without an optional chain (productConfig.product?.fromEmail), where the old code used _productConfig?.product.fromEmail. If container.productConfig is falsy the notification pipeline fails silently due to the outer try/catch — a regression from the previous null-safety.\n- CI is not yet green (the test plan checkbox is unchecked), which is required by the WOPR CI gate convention.

Confidence Score: 3/5

Hold until the crypto webhook regression is confirmed resolved and CI passes.

The refactor is clean and well-structured, but the silent removal of the crypto payment webhook route is a potential data-loss regression — incoming payment confirmations could 404 undetected. The fix is small (confirm platform-core handles it or re-mount the route), but it needs explicit verification. The productConfig null-safety issue is also a regression, though caught by try/catch. CI is not yet green per the PR's own checklist.

src/index.ts — verify the crypto webhook route is handled by bootPlatformServer() or re-add the explicit mount; fix productConfig optional chaining.

Important Files Changed

Filename Overview
src/index.ts Major boot refactor to bootPlatformServer(); crypto webhook route silently dropped, productConfig null-safety regression, and as-never type cast introduced.
src/app.ts Deleted — Hono app, CORS, secure headers, and BetterAuth handler moved into bootPlatformServer() and index.ts respectively.
package.json platform-core bumped from ^1.67.1 to ^1.71.0; lock file updated with new transitive deps (@aws-sdk/client-ses, platform-crypto-server, viem, ox).
pnpm-lock.yaml Lock file updated consistently with package.json bump; platform-crypto-server 1.1.1 introduces a second drizzle-orm version (0.44.7) as a transitive dep alongside the app's 0.45.1.

Sequence Diagram

sequenceDiagram
    participant Main as main()
    participant Boot as bootPlatformServer()
    participant Platform as platform container
    participant App as Hono app

    Main->>Boot: { slug, databaseUrl, host, port, features }
    Boot-->>Main: { app, container, start(), stop() }

    Main->>Platform: container.db (platformDb)
    Main->>Main: run local drizzle/ migrations
    Main->>Platform: container.pool → drizzle(engineDb)

    Main->>App: mount /api/auth/* (BetterAuth)
    Main->>Platform: container.orgMemberRepo → setTrpcOrgMemberRepo()
    Main->>App: mount /v1 gateway (if OPENROUTER_API_KEY)
    Main->>App: mount /trpc/* (appRouter)

    Main->>Main: init Engine + WorkerPool
    Main->>App: mount /api engine routes
    Main->>App: mount /api/ship-it routes
    Main->>App: mount /api/github/* routes
    Main->>App: mount /api flow-editor + interrogation routes

    Main->>Boot: platform.start() → listen on HOST:PORT

    note over Main,App: ⚠️ /api/webhooks/crypto NOT remounted
Loading
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/index.ts
Line: 670-714

Comment:
**Crypto webhook route silently dropped**

The old code (step 13 in the previous boot sequence) wired and mounted the crypto payment webhook route:

```ts
setCryptoWebhookDeps({ chargeStore: cryptoChargeRepo, creditLedger, replayGuard }, config.CRYPTO_WEBHOOK_SECRET);
app.route("/api/webhooks/crypto", cryptoWebhookRoutes);
```

This block is entirely absent from the new code. `features.crypto` is passed to `bootPlatformServer()`, but `CRYPTO_SERVICE_URL` and `CRYPTO_WEBHOOK_SECRET` are **not** — meaning platform-core cannot reconstruct the route with the correct webhook secret. If `bootPlatformServer()` does not internally mount `/api/webhooks/crypto`, any incoming crypto payment confirmations will receive a 404 and users will never be credited. This is a silent data-loss regression when `CRYPTO_SERVICE_URL` and `CRYPTO_WEBHOOK_SECRET` are set.

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/index.ts
Line: 684-688

Comment:
**`container.productConfig` null-safety regression**

The old code accessed `_productConfig?.product.fromEmail` — safe because `_productConfig` could be `null` after a failed product config boot. The new code:

```ts
const productConfig = container.productConfig;
const emailClient = getEmailClient({
  from: productConfig.product?.fromEmail || undefined,
```

If `container.productConfig` is `undefined` or `null`, `productConfig.product` throws a `TypeError` at runtime. The entire notification pipeline is wrapped in a `try/catch`, so this would be swallowed silently, but it represents a regression in null-safety compared to the previous pattern. Consider using:

```suggestion
      const productConfig = container.productConfig;
      const emailClient = getEmailClient({
        from: productConfig?.product?.fromEmail || undefined,
        replyTo: productConfig?.product?.emailSupport || undefined,
```

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: src/index.ts
Line: 104

Comment:
**`as never` type cast bypasses type safety**

`platformDb as never` is an overly aggressive cast that completely erases the type and suppresses any future type-checker complaints. The `migrate` function expects `NodePgDatabase<any>`, which `container.db` almost certainly satisfies. A safer cast would be:

```suggestion
      await migrate(platformDb as import("drizzle-orm/node-postgres").NodePgDatabase<Record<string, never>>, { migrationsFolder: localMigrations });
```

Or at minimum `as any` with a `biome-ignore` comment and reason, which is already the established pattern in this file.

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "refactor: migrate holyship to bootPlatfo..." | Re-trigger Greptile

Comment thread src/index.ts
Comment on lines 670 to 714
@@ -715,9 +681,10 @@ async function main() {

// biome-ignore lint/suspicious/noExplicitAny: PgDatabase generic
const pgDb = platformDb as any;
const productConfig = container.productConfig;
const emailClient = getEmailClient({
from: _productConfig?.product.fromEmail || undefined,
replyTo: _productConfig?.product.emailSupport || undefined,
from: productConfig.product?.fromEmail || undefined,
replyTo: productConfig.product?.emailSupport || undefined,
});
const queueStore = new DrizzleNotificationQueueStore(platformDb);
const prefsStore = new DrizzleNotificationPreferencesStore(platformDb);
@@ -746,24 +713,22 @@ async function main() {
}
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Crypto webhook route silently dropped

The old code (step 13 in the previous boot sequence) wired and mounted the crypto payment webhook route:

setCryptoWebhookDeps({ chargeStore: cryptoChargeRepo, creditLedger, replayGuard }, config.CRYPTO_WEBHOOK_SECRET);
app.route("/api/webhooks/crypto", cryptoWebhookRoutes);

This block is entirely absent from the new code. features.crypto is passed to bootPlatformServer(), but CRYPTO_SERVICE_URL and CRYPTO_WEBHOOK_SECRET are not — meaning platform-core cannot reconstruct the route with the correct webhook secret. If bootPlatformServer() does not internally mount /api/webhooks/crypto, any incoming crypto payment confirmations will receive a 404 and users will never be credited. This is a silent data-loss regression when CRYPTO_SERVICE_URL and CRYPTO_WEBHOOK_SECRET are set.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/index.ts
Line: 670-714

Comment:
**Crypto webhook route silently dropped**

The old code (step 13 in the previous boot sequence) wired and mounted the crypto payment webhook route:

```ts
setCryptoWebhookDeps({ chargeStore: cryptoChargeRepo, creditLedger, replayGuard }, config.CRYPTO_WEBHOOK_SECRET);
app.route("/api/webhooks/crypto", cryptoWebhookRoutes);
```

This block is entirely absent from the new code. `features.crypto` is passed to `bootPlatformServer()`, but `CRYPTO_SERVICE_URL` and `CRYPTO_WEBHOOK_SECRET` are **not** — meaning platform-core cannot reconstruct the route with the correct webhook secret. If `bootPlatformServer()` does not internally mount `/api/webhooks/crypto`, any incoming crypto payment confirmations will receive a 404 and users will never be credited. This is a silent data-loss regression when `CRYPTO_SERVICE_URL` and `CRYPTO_WEBHOOK_SECRET` are set.

How can I resolve this? If you propose a fix, please make it concise.

Comment thread src/index.ts
Comment on lines +684 to 688
const productConfig = container.productConfig;
const emailClient = getEmailClient({
from: _productConfig?.product.fromEmail || undefined,
replyTo: _productConfig?.product.emailSupport || undefined,
from: productConfig.product?.fromEmail || undefined,
replyTo: productConfig.product?.emailSupport || undefined,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 container.productConfig null-safety regression

The old code accessed _productConfig?.product.fromEmail — safe because _productConfig could be null after a failed product config boot. The new code:

const productConfig = container.productConfig;
const emailClient = getEmailClient({
  from: productConfig.product?.fromEmail || undefined,

If container.productConfig is undefined or null, productConfig.product throws a TypeError at runtime. The entire notification pipeline is wrapped in a try/catch, so this would be swallowed silently, but it represents a regression in null-safety compared to the previous pattern. Consider using:

Suggested change
const productConfig = container.productConfig;
const emailClient = getEmailClient({
from: _productConfig?.product.fromEmail || undefined,
replyTo: _productConfig?.product.emailSupport || undefined,
from: productConfig.product?.fromEmail || undefined,
replyTo: productConfig.product?.emailSupport || undefined,
});
const productConfig = container.productConfig;
const emailClient = getEmailClient({
from: productConfig?.product?.fromEmail || undefined,
replyTo: productConfig?.product?.emailSupport || undefined,
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/index.ts
Line: 684-688

Comment:
**`container.productConfig` null-safety regression**

The old code accessed `_productConfig?.product.fromEmail` — safe because `_productConfig` could be `null` after a failed product config boot. The new code:

```ts
const productConfig = container.productConfig;
const emailClient = getEmailClient({
  from: productConfig.product?.fromEmail || undefined,
```

If `container.productConfig` is `undefined` or `null`, `productConfig.product` throws a `TypeError` at runtime. The entire notification pipeline is wrapped in a `try/catch`, so this would be swallowed silently, but it represents a regression in null-safety compared to the previous pattern. Consider using:

```suggestion
      const productConfig = container.productConfig;
      const emailClient = getEmailClient({
        from: productConfig?.product?.fromEmail || undefined,
        replyTo: productConfig?.product?.emailSupport || undefined,
```

How can I resolve this? If you propose a fix, please make it concise.

Comment thread src/index.ts
const { migrate } = await import("drizzle-orm/node-postgres/migrator");
const localMigrations = path.resolve(process.cwd(), "drizzle");
if (existsSync(localMigrations)) {
await migrate(platformDb as never, { migrationsFolder: localMigrations });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 as never type cast bypasses type safety

platformDb as never is an overly aggressive cast that completely erases the type and suppresses any future type-checker complaints. The migrate function expects NodePgDatabase<any>, which container.db almost certainly satisfies. A safer cast would be:

Suggested change
await migrate(platformDb as never, { migrationsFolder: localMigrations });
await migrate(platformDb as import("drizzle-orm/node-postgres").NodePgDatabase<Record<string, never>>, { migrationsFolder: localMigrations });

Or at minimum as any with a biome-ignore comment and reason, which is already the established pattern in this file.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/index.ts
Line: 104

Comment:
**`as never` type cast bypasses type safety**

`platformDb as never` is an overly aggressive cast that completely erases the type and suppresses any future type-checker complaints. The `migrate` function expects `NodePgDatabase<any>`, which `container.db` almost certainly satisfies. A safer cast would be:

```suggestion
      await migrate(platformDb as import("drizzle-orm/node-postgres").NodePgDatabase<Record<string, never>>, { migrationsFolder: localMigrations });
```

Or at minimum `as any` with a `biome-ignore` comment and reason, which is already the established pattern in this file.

How can I resolve this? If you propose a fix, please make it concise.

Merged via the queue into main with commit bcb12ce Mar 26, 2026
11 of 12 checks passed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.47.1 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant