Skip to content

Commit 837de6b

Browse files
author
Cheems
committed
fix(byok): restore local runtime configuration
Return BYOK settings to the browser-local configuration path and pass credentials only to the active OpenCode child run. Remove the unpublished secure-profile migration, credential backends, API, CLI, contracts, and MCP exposure while retaining raw-secret rejection on external MCP calls. Validated with focused web and daemon suites, full web tests, workspace typecheck, guard, and diff checks.
1 parent dceac12 commit 837de6b

45 files changed

Lines changed: 309 additions & 3891 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/daemon/src/byok/credential-service.ts

Lines changed: 0 additions & 596 deletions
This file was deleted.

apps/daemon/src/cli.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { DESIGN_SYSTEMS_USAGE, isDesignSystemsHelpArg } from './cli-help/index.j
1212
import { BRAND_USAGE, isBrandHelpArg } from './cli-help/index.js';
1313
import { parseDesignSystemRenameArgs } from './design-systems/rename-args.js';
1414
import { runLiveArtifactsToolCli } from './tools-live-artifacts-cli.js';
15-
import { runByokToolCli } from './tools-byok-cli.js';
1615
import { splitResearchSubcommand } from './research/cli-args.js';
1716
import { resolveDaemonUrl } from './daemon-url.js';
1817
import { requestJsonIpc } from '@open-design/sidecar';
@@ -334,7 +333,6 @@ const SUBCOMMAND_MAP = {
334333
artifacts: runArtifacts,
335334
media: runMedia,
336335
mcp: runMcp,
337-
byok: runByok,
338336
amr: runAmr,
339337
'message-center': runMessageCenter,
340338
research: runResearch,
@@ -1472,15 +1470,6 @@ artifact / message body. The daemon writes the bytes into the project's
14721470
files folder so the FileViewer can preview them immediately.`);
14731471
}
14741472

1475-
// ---------------------------------------------------------------------------
1476-
// Subcommand: od byok
1477-
// ---------------------------------------------------------------------------
1478-
1479-
async function runByok(args) {
1480-
const result = await runByokToolCli(args);
1481-
if (result.exitCode !== 0) process.exit(result.exitCode);
1482-
}
1483-
14841473
// ---------------------------------------------------------------------------
14851474
// Subcommand: od mcp
14861475
// ---------------------------------------------------------------------------

apps/daemon/src/mcp-brief.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ const BRIEF_COPY: Record<LocalMcpBriefLocale, LocalizedBriefCopy> = {
5151
artifactNames: ENGLISH_ARTIFACT_NAMES,
5252
title: (artifactName) => `Choose the ${artifactName} direction`,
5353
description:
54-
'Choose one option for each decision. The same readable brief can be used with Open Design Cloud, Local Codex, or Secure BYOK.',
54+
'Choose one option for each decision. The same readable brief can be used with Open Design Cloud or Local Codex.',
5555
submitLabel: 'Confirm brief',
5656
completeCard:
5757
'Complete the rendered Open Design brief card. The confirmation returns a readable summary; internal correlation values must remain hidden.',

apps/daemon/src/mcp.ts

Lines changed: 6 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const OPEN_DESIGN_BRIEF_APP_RESOURCE =
6767
'ui://open-design/artifact-card-v6.html';
6868

6969
export const MCP_SERVER_INSTRUCTIONS = [
70-
'Use only these product names in user-facing replies: Open Design Cloud, Local Codex, and Secure BYOK.',
70+
'Use only these product names in user-facing replies: Open Design Cloud and Local Codex.',
7171
'Tool names, runtime ids, endpoints, and correlation values are machine protocol. Never repeat them as product copy.',
7272
].join('\n');
7373

@@ -84,7 +84,7 @@ interface ProjectPayload { project?: ProjectSummary; id?: string; name?: string;
8484
interface ActiveContext { active?: boolean; projectId?: string; projectName?: string | null; fileName?: string | null; ageMs?: number | null }
8585
type ResolvedProject = { id: string; name: string; source: 'uuid' | 'id' | 'exact' | 'slug' | 'substring' };
8686
interface ProjectListCache { baseUrl: string; t: number; list: ProjectSummary[] }
87-
interface McpArgs extends JsonObject { project?: unknown; entry?: unknown; include?: unknown; maxBytes?: unknown; path?: unknown; offset?: unknown; limit?: unknown; since?: unknown; query?: unknown; pattern?: unknown; max?: unknown; name?: unknown; content?: unknown; encoding?: unknown; artifactManifest?: unknown; confirm?: unknown; prompt?: unknown; plugin?: unknown; inputs?: unknown; agent?: unknown; model?: unknown; serviceTier?: unknown; byokProfile?: unknown; apiKey?: unknown; requestId?: unknown; resume?: unknown; runId?: unknown; id?: unknown; designSystem?: unknown; skill?: unknown; includeUnavailable?: unknown; artifactType?: unknown; projectTitle?: unknown; locale?: unknown; knownAnswers?: unknown; skip?: unknown; briefDraftId?: unknown; nonce?: unknown; answers?: unknown; externalPluginContext?: unknown; pluginWorkflowId?: unknown }
87+
interface McpArgs extends JsonObject { project?: unknown; entry?: unknown; include?: unknown; maxBytes?: unknown; path?: unknown; offset?: unknown; limit?: unknown; since?: unknown; query?: unknown; pattern?: unknown; max?: unknown; name?: unknown; content?: unknown; encoding?: unknown; artifactManifest?: unknown; confirm?: unknown; prompt?: unknown; plugin?: unknown; inputs?: unknown; agent?: unknown; model?: unknown; serviceTier?: unknown; apiKey?: unknown; requestId?: unknown; resume?: unknown; runId?: unknown; id?: unknown; designSystem?: unknown; skill?: unknown; includeUnavailable?: unknown; artifactType?: unknown; projectTitle?: unknown; locale?: unknown; knownAnswers?: unknown; skip?: unknown; briefDraftId?: unknown; nonce?: unknown; answers?: unknown; externalPluginContext?: unknown; pluginWorkflowId?: unknown }
8888
interface ProjectFileBundleEntry { name: string; mime: string; size: number | null; content: string | null; binary: boolean }
8989
interface BundleInput { project: ProjectPayload | ProjectSummary; entry: string; files: ProjectFileBundleEntry[]; truncated: boolean; skippedFileCount?: number; active: ActiveContext | null; resolved?: ResolvedProject | null }
9090
interface ErrorWithCode { message?: string; code?: string; cause?: { code?: string } }
@@ -616,17 +616,6 @@ export const TOOL_DEFS = [
616616
},
617617
annotations: { ...READ_ANNOTATIONS, title: 'List Open Design plugins' },
618618
},
619-
{
620-
name: 'list_byok_profiles',
621-
description:
622-
'List secure local BYOK profile references available to start_run.byokProfile. Returns only non-secret metadata; API keys never cross MCP.',
623-
inputSchema: {
624-
type: 'object',
625-
properties: { pluginWorkflowId: PLUGIN_WORKFLOW_ID_ARG },
626-
additionalProperties: false,
627-
},
628-
annotations: { ...READ_ANNOTATIONS, title: 'List secure BYOK profiles' },
629-
},
630619
{
631620
name: 'start_vela_login',
632621
description:
@@ -695,11 +684,6 @@ export const TOOL_DEFS = [
695684
type: 'string',
696685
description: "Service tier override for the selected model, e.g. 'priority' for Codex Fast. Optional.",
697686
},
698-
byokProfile: {
699-
type: 'string',
700-
description:
701-
'Secure profile id from list_byok_profiles. Selects the local BYOK OpenCode runtime; raw API keys are never accepted by MCP.',
702-
},
703687
requestId: {
704688
type: 'string',
705689
description:
@@ -849,7 +833,7 @@ export function localMcpResourceDefinitions() {
849833
name: 'Open Design brief',
850834
title: 'Choose the artifact direction',
851835
description:
852-
'Interactive local Open Design brief card shared by Open Design Cloud, Local Codex, and Secure BYOK modes.',
836+
'Interactive local Open Design brief card shared by Open Design Cloud and Local Codex modes.',
853837
mimeType: 'text/html;profile=mcp-app',
854838
_meta: {
855839
ui: {
@@ -1271,7 +1255,7 @@ function mcpFailureFacts(
12711255
const failureStage =
12721256
name === 'collect_brief' || name === 'confirm_brief'
12731257
? 'brief'
1274-
: name.includes('vela_login') || name === 'list_byok_profiles'
1258+
: name.includes('vela_login')
12751259
? 'auth'
12761260
: name.includes('project')
12771261
? 'project'
@@ -1622,12 +1606,9 @@ export async function runMcpStdio({ daemonUrl }: RunMcpOptions): Promise<void> {
16221606
' - collect_brief first for a new artifact unless the user explicitly',
16231607
' asks to skip questions. Let the user complete the rendered card;',
16241608
' confirm_brief returns the readable brief to reuse with Open Design',
1625-
' Cloud, Local Codex, or Secure BYOK. Never print or ask the user to copy',
1609+
' Cloud or Local Codex. Never print or ask the user to copy',
16261610
' briefDraftId, nonce, or any other internal correlation value.',
16271611
' - list_skills / list_plugins to see what you can ask OD to make.',
1628-
' - list_byok_profiles returns secure local credential references when',
1629-
' the user explicitly chooses Secure BYOK. Never request or pass a',
1630-
' raw API key through MCP; pass only start_run.byokProfile.',
16311612
' - for Open Design Cloud, call the Cloud login-status tool first.',
16321613
' If signed out, call the Cloud sign-in tool once, show its activation',
16331614
' URL/code when present, and poll login status until loggedIn:true.',
@@ -2037,8 +2018,6 @@ async function handleMcpToolCall(
20372018
return ok(await getJson<SkillsPayload>(`${baseUrl}/api/skills`));
20382019
case 'list_plugins':
20392020
return ok(await listPlugins(baseUrl));
2040-
case 'list_byok_profiles':
2041-
return ok(await listByokProfiles(baseUrl));
20422021
case 'list_agents':
20432022
return ok(await listAgents(baseUrl, args.includeUnavailable === true));
20442023
case 'start_vela_login': {
@@ -2263,58 +2242,6 @@ async function listAgents(baseUrl: string, includeUnavailable: boolean): Promise
22632242
return { agents };
22642243
}
22652244

2266-
async function listByokProfiles(baseUrl: string): Promise<JsonObject> {
2267-
const payload = await getJson<JsonObject>(`${baseUrl}/api/byok/profiles`);
2268-
const rawProfiles = Array.isArray(payload.profiles) ? payload.profiles : [];
2269-
const profiles = rawProfiles.flatMap((value) => {
2270-
if (!value || typeof value !== 'object' || Array.isArray(value)) return [];
2271-
const profile = value as JsonObject;
2272-
if (
2273-
typeof profile.id !== 'string'
2274-
|| typeof profile.label !== 'string'
2275-
|| typeof profile.protocol !== 'string'
2276-
|| typeof profile.baseUrl !== 'string'
2277-
|| typeof profile.model !== 'string'
2278-
) {
2279-
return [];
2280-
}
2281-
try {
2282-
const parsed = new URL(profile.baseUrl);
2283-
if (
2284-
!['http:', 'https:'].includes(parsed.protocol)
2285-
|| parsed.username.length > 0
2286-
|| parsed.password.length > 0
2287-
|| parsed.search.length > 0
2288-
|| parsed.hash.length > 0
2289-
) {
2290-
return [];
2291-
}
2292-
} catch {
2293-
return [];
2294-
}
2295-
return [{
2296-
id: profile.id,
2297-
label: profile.label,
2298-
protocol: profile.protocol,
2299-
baseUrl: profile.baseUrl,
2300-
model: profile.model,
2301-
...(typeof profile.apiVersion === 'string'
2302-
? { apiVersion: profile.apiVersion }
2303-
: {}),
2304-
requiresApiKey: profile.requiresApiKey === true,
2305-
configured: profile.configured === true,
2306-
...(typeof profile.keyTail === 'string' ? { keyTail: profile.keyTail } : {}),
2307-
...(typeof profile.createdAt === 'number' ? { createdAt: profile.createdAt } : {}),
2308-
...(typeof profile.updatedAt === 'number' ? { updatedAt: profile.updatedAt } : {}),
2309-
}];
2310-
});
2311-
return {
2312-
available: payload.available === true,
2313-
backend: typeof payload.backend === 'string' ? payload.backend : 'unknown',
2314-
profiles,
2315-
};
2316-
}
2317-
23182245
// Derive a valid project id ([A-Za-z0-9._-], <=128) from a display name,
23192246
// with a short random suffix so repeated creates with the same name
23202247
// don't collide on the daemon's primary key.
@@ -2341,7 +2268,7 @@ async function startRun(
23412268
|| containsMcpCredentialField(args.inputs)
23422269
) {
23432270
throw new Error(
2344-
'raw API keys are not accepted by Open Design MCP. Save the key through the Open Design UI or `od byok save --api-key-stdin`, then pass only byokProfile.',
2271+
'raw API keys are not accepted by Open Design MCP. Configure Local BYOK in the Open Design UI and start that run from the local product instead.',
23452272
);
23462273
}
23472274
const { id, resolved, active } = await resolveProjectArg(baseUrl, args.project);
@@ -2397,18 +2324,6 @@ async function startRun(
23972324
if (typeof args.serviceTier === 'string' && args.serviceTier.length > 0) {
23982325
body.serviceTier = args.serviceTier;
23992326
}
2400-
if (args.byokProfile !== undefined) {
2401-
requireString(args.byokProfile, 'byokProfile');
2402-
if (
2403-
typeof args.agent === 'string'
2404-
&& args.agent.length > 0
2405-
&& args.agent !== 'byok-opencode'
2406-
) {
2407-
throw new Error('byokProfile can only be used with the byok-opencode agent.');
2408-
}
2409-
body.agentId = 'byok-opencode';
2410-
body.byokProfileId = args.byokProfile;
2411-
}
24122327
if (args.inputs !== undefined) {
24132328
if (args.inputs === null || typeof args.inputs !== 'object' || Array.isArray(args.inputs)) {
24142329
throw new Error('inputs must be an object');

apps/daemon/src/routes/byok-credentials.ts

Lines changed: 0 additions & 162 deletions
This file was deleted.

0 commit comments

Comments
 (0)