// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // The modules that deploy to the Convex backend on this profile, derived from the app's one // module list (modules/index.ts) -- named exclusions, not a second list. // // Why a module is excluded: its callable procedure graph needs a Node-only runtime or a workflow // that has not been composed here. These are explicit gaps, not inferred from the module // importing a package which has unrelated Node-only exports. Auth is included: its procedure // handlers use Web Crypto; the OIDC redirects and sealed session storage remain in the trusted // Next BFF, which invokes Convex functions with server-only admin auth and a verified identity. // // Convex actions have no ctx.db, so the runtime cannot run an effect procedure that changes the // app's own rows in an action. File upload and delete have explicit action→mutation compositions // in files.ts; other effects remain omitted until they have an equivalent state-machine workflow. export const CONVEX_EXCLUDED_MODULES = new Map([]) // The modules whose effect procedures are generated as Convex actions (convex/lib/effects.ts): // each effect is one call to a platform service through the module's own port and owns no app // row, so it needs no transaction -- except the account module's, whose rows are reached through // its bound store, one transaction per resumable step. The kernel still resolves the tenant scope and checks the // permission, against ctx.db in an internal query (convex/effectScope.ts), and the handler's // nested reads and writes run as the generated queries and mutations they always are. export const CONVEX_ACTION_EFFECT_MODULES = new Map() CONVEX_ACTION_EFFECT_MODULES.set("guides", "Guides runtime calls through GUIDES_PLATFORM; no app rows") // kit:guides CONVEX_ACTION_EFFECT_MODULES.set("support", "Support session/contact calls through SUPPORT_PLATFORM") // kit:support // The account module's export and deletion compose every module's share (platform calls) and own the // deletion ledger, which they reach through ACCOUNT_STORE: one internal query or mutation per step. CONVEX_ACTION_EFFECT_MODULES.set("account", "account export/deletion; ledger steps through convex/account.ts") export const CONVEX_EXCLUDED_PROCEDURES = new Map([ ["branding.logo.set", "logo decoding and Blob writes require an audited action workflow"], ["branding.logo.clear", "logo record updates and concurrent Blob cleanup require an action workflow"], ["branding.logo.get", "logo bytes require an authorized Blob action workflow"], ["files.file.delete", "the BFF composes the object delete action with internal mutations"], ]) // The account page's platform analytics erasure and export (ADR-049) call the platform with the // deployment token through ACCOUNT_PRIVACY, which only the web's composition root binds; no Convex // action binds it yet, so on this profile the panel answers "unavailable". for (const name of ["account.analytics.request", "account.analytics.status", "account.analytics.export"]) { CONVEX_EXCLUDED_PROCEDURES.set(name, "ACCOUNT_PRIVACY is bound by the web's composition root only") } // kit:guides:begin -- a survey file's bytes are the streamed body of a PUT, which cannot be a Convex // action's argument, and no BFF composition streams it to the platform on this profile yet. CONVEX_EXCLUDED_PROCEDURES.set( "guides.runtime.uploadFile", "a streamed request body cannot be a Convex action argument", ) // kit:guides:end const modulesFor = (appModules, includeBffFileEffects) => appModules .filter((module) => !CONVEX_EXCLUDED_MODULES.has(module.id)) .map((module) => ({ ...module, procedures: (module.procedures ?? []).filter((procedure) => { const composedBffFileProcedure = includeBffFileEffects && module.id === "files" && procedure.name.startsWith("files.file.") const runnable = procedure.kind !== "effect" || CONVEX_ACTION_EFFECT_MODULES.has(module.id) return composedBffFileProcedure || (runnable && !CONVEX_EXCLUDED_PROCEDURES.has(procedure.name)) }), })) // The backend generator and deployment registry omit procedures that are composed as actions by // the BFF. The web HTTP registry keeps those file contracts so their routes still validate input, // tenancy, permissions, rate limits and CSRF before the caller invokes the action workflow. export const convexModules = (appModules) => modulesFor(appModules, false) export const convexBffModules = (appModules) => modulesFor(appModules, true)