Upgrade to v0.39.0: reapply fork patches on clean upstream base
Some checks failed
PR Checks / Lint (push) Has been cancelled
PR Checks / Typecheck (push) Has been cancelled
PR Checks / Build (push) Has been cancelled
PR Checks / Test shard 1/4 (push) Has been cancelled
PR Checks / Test shard 2/4 (push) Has been cancelled
PR Checks / Test shard 3/4 (push) Has been cancelled
PR Checks / Test shard 4/4 (push) Has been cancelled
Some checks failed
PR Checks / Lint (push) Has been cancelled
PR Checks / Typecheck (push) Has been cancelled
PR Checks / Build (push) Has been cancelled
PR Checks / Test shard 1/4 (push) Has been cancelled
PR Checks / Test shard 2/4 (push) Has been cancelled
PR Checks / Test shard 3/4 (push) Has been cancelled
PR Checks / Test shard 4/4 (push) Has been cancelled
Strategy: reset main to upstream/main (v0.39.0) and reapply only the fork-specific patches that survive — most older patches (plugin-loader routing, heartbeat resolver, autoload, cross-spawn, scope-resolution fixes) were absorbed by upstream between v0.28.1 → v0.39.0. Surviving patches: - Dockerfile: keep single-stage Coolify-compatible build (upstream went multi-stage which breaks our bind-mount strategy for /home/s/.codex, /home/s/.claude, /usr/lib/node_modules) - packages/engine/src/sandbox-tester-gate.ts: shared Phase-3 pre-merge gate module (Opus 4.7 + OpenSandbox + Playwright smoke) - packages/engine/src/executor.ts: call runSandboxTesterGate from finalizeAlreadyReviewedTask recovery path - packages/engine/src/project-engine.ts: call applySandboxTesterGate from primary direct-merge dispatch (the path that actually fires in prod — recovery path only catches stuck tasks) - packages/dashboard/src/auth-middleware.ts: registerPluginExemptPath for webhook endpoints (Grafana, Gitea) that must bypass daemon-token - packages/dashboard/src/plugin-routes.ts: auto-register plugin-defined routes as daemon-exempt so external plugins (telemetry-watcher, gitea-issues) work out of the box Tested locally: pnpm install + pnpm -r build green, no TS errors. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -19,6 +19,24 @@ export const TOKEN_QUERY_PARAM = "fn_token";
|
||||
/** Paths that are exempt from authentication (liveness probes). */
|
||||
const EXEMPT_PATHS = ["/api/health"];
|
||||
|
||||
/**
|
||||
* Plugin-registered paths that should bypass daemon-token auth.
|
||||
* Used for webhook endpoints (Grafana, Gitea, GitHub, etc.) that need to be
|
||||
* reachable from external services without holding the daemon token.
|
||||
*/
|
||||
const PLUGIN_EXEMPT_PATHS = new Set<string>();
|
||||
|
||||
/**
|
||||
* Register a webhook path defined by a plugin so daemon auth lets it through.
|
||||
* Paths must start with `/api/plugins/`. Idempotent.
|
||||
*/
|
||||
export function registerPluginExemptPath(path: string): void {
|
||||
if (!path.startsWith("/api/plugins/")) {
|
||||
throw new Error(`registerPluginExemptPath: path must start with /api/plugins/ (got: ${path})`);
|
||||
}
|
||||
PLUGIN_EXEMPT_PATHS.add(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only /api/* paths are gated by this middleware. The SPA shell (index.html,
|
||||
* /assets/*, favicon, etc.) must load unauthenticated so the frontend JS can
|
||||
@@ -66,7 +84,13 @@ export function getDaemonToken(options?: { daemon?: { token: string }; noAuth?:
|
||||
* Check if a request path is exempt from authentication.
|
||||
*/
|
||||
function isExemptPath(path: string): boolean {
|
||||
return EXEMPT_PATHS.some((exempt) => path === exempt || path.startsWith(exempt + "/"));
|
||||
if (EXEMPT_PATHS.some((exempt) => path === exempt || path.startsWith(exempt + "/"))) {
|
||||
return true;
|
||||
}
|
||||
for (const exempt of PLUGIN_EXEMPT_PATHS) {
|
||||
if (path === exempt || path.startsWith(exempt + "/")) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,6 +32,7 @@ import {
|
||||
notFound,
|
||||
} from "./api-error.js";
|
||||
import { getOrCreateProjectStore } from "./project-store-resolver.js";
|
||||
import { registerPluginExemptPath } from "./auth-middleware.js";
|
||||
|
||||
|
||||
// PluginRunner interface for optional plugin runner
|
||||
@@ -627,6 +628,15 @@ export function createPluginRouter(
|
||||
router.delete(fullPath, handler);
|
||||
break;
|
||||
}
|
||||
|
||||
// Webhook endpoints (Grafana, Gitea, GitHub) must be reachable without the
|
||||
// daemon token. Plugin-defined routes handle their own auth via webhook
|
||||
// secrets in plugin settings; bypass daemon auth here.
|
||||
try {
|
||||
registerPluginExemptPath(`/api/plugins${fullPath}`);
|
||||
} catch {
|
||||
// ignore — non-/api/plugins paths are rejected; safe to skip.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user