From 31c6b7036d7e7965949dbf3ac9caf01d20967083 Mon Sep 17 00:00:00 2001 From: os-zhuang Date: Thu, 25 Jun 2026 23:45:48 +0800 Subject: [PATCH] feat(serve): thread api.enforceProjectMembership to the dispatcher (ADR-0024 D9) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit serve.ts built the dispatcher with `scoping` but never threaded `enforceProjectMembership`, so per-project membership (the `sys_environment_member` 403 gate) was always forced ON whenever project-scoping was on. Read it from the app's `api` config and pass it through, so a host can opt OUT — env-native auth IS the membership (ADR-0024 D9) — via `api.enforceProjectMembership: false`. Undefined keeps the existing default (= `enableProjectScoping`): backward-compatible. Co-Authored-By: Claude Opus 4.8 --- packages/cli/src/commands/serve.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/cli/src/commands/serve.ts b/packages/cli/src/commands/serve.ts index a341dc8a00..a988b48b63 100644 --- a/packages/cli/src/commands/serve.ts +++ b/packages/cli/src/commands/serve.ts @@ -1354,6 +1354,11 @@ export default class Serve extends Command { const apiConfig = (config as any).api ?? {}; const enableProjectScoping = apiConfig.enableProjectScoping ?? false; const projectResolution = apiConfig.projectResolution ?? 'auto'; + // Per-project membership (sys_environment_member 403 gate) is, by + // default, ON whenever project-scoping is on. A host can opt OUT + // (env-native auth IS the membership — ADR-0024 D9) by setting + // `api.enforceProjectMembership: false`. Undefined → dispatcher default. + const enforceProjectMembership = apiConfig.enforceProjectMembership; // `requireAuth: true` rejects anonymous requests on `/api/v1/data/*` // with HTTP 401 before they reach ObjectQL. Default-on when the // stack opts in OR when the resolved tier set includes `auth` @@ -1383,6 +1388,7 @@ export default class Serve extends Command { await kernel.use( createDispatcherPlugin({ scoping: { enableProjectScoping, projectResolution }, + enforceProjectMembership, observability, }), );