cleanup(config): remove literal credential compatibility residue

Adapter schemas now carry only credential references, but the Models join, onboarding readiness, shipped overlays, SDK scaffolding, fixtures, and active decision prose still treated a redacted literal apiKey as a supported compatibility state. That residue made an unsupported field look contractual and pinned Schemastery silent-dropping as behavior.

Delete those branches and examples, and let compositions and scaffolds use adapter-owned reference and environment resolution. Do not add a tombstone validator or change generic unknown-key behavior: literal adapter credentials have no migration contract to preserve.
This commit is contained in:
Tianyi Cui
2026-08-07 22:03:49 +08:00
parent ac154b2dfa
commit 356453d6cb
37 changed files with 78 additions and 189 deletions
@@ -35,9 +35,7 @@ function capacityInputs(label: string): HTMLInputElement[] {
}
const PiAiConfig = Schema.object({
token: Schema.string().role('secret'),
providers: Schema.dict(Schema.object({
apiKey: Schema.string().role('secret'),
apiKeyEnv: Schema.string().role('credential-ref'),
baseURL: Schema.string(),
reasoning: Schema.union(['off', 'minimal', 'low', 'medium', 'high', 'xhigh', 'max']),
@@ -46,7 +44,6 @@ const PiAiConfig = Schema.object({
})
const DeepSeekConfig = Schema.object({
apiKey: Schema.string().role('secret'),
apiKeyEnv: Schema.string().role('credential-ref'),
baseURL: Schema.string().pattern(/^https:\/\//),
reasoningEffort: Schema.union(['off', 'high', 'max']),
@@ -100,7 +97,7 @@ function wireNamespaces(): SettingsNamespaceView[] {
base: { defaultContextWindow: 1_000_000, maxTokens: 256_000, models: DEFAULT_DEEPSEEK_MODELS },
user: { reasoningEffort: 'high' },
applies: 'live',
secrets: [{ path: ['apiKey'], set: false }],
secrets: [],
revision: 0,
},
{
@@ -119,7 +116,7 @@ function wireNamespaces(): SettingsNamespaceView[] {
value: { providers: { openai: { apiKeyEnv: 'OPENAI_API_KEY', baseURL: 'https://proxy', headers: { 'X-Team': 'a' } }, zombie: {} } },
user: { providers: { openai: { apiKeyEnv: 'OPENAI_API_KEY', baseURL: 'https://proxy', headers: { 'X-Team': 'a' } }, zombie: {} } },
applies: 'live',
secrets: [{ path: ['token'], set: false }, { path: ['providers', 'openai', 'apiKey'], set: false }],
secrets: [],
revision: 0,
},
]
@@ -263,22 +260,17 @@ describe('ModelsSection', () => {
expect(screen.queryByLabelText(en.keyInput)).toBeNull()
})
it('decides setup need from the joined credential state and literal-key sidecar', () => {
it('decides setup need from the joined credential state', () => {
const entry = { provider: 'p', displayName: 'p', settingsNs: 'llm-deepseek', settingsPath: [], active: true }
const row = (
credential: ProviderRow['credential'],
literalApiKeyConfigured = false,
): ProviderRow => ({
const row = (credential: ProviderRow['credential']): ProviderRow => ({
entry,
configured: true,
removable: false,
apiKeyEnv: 'X',
credential,
literalApiKeyConfigured,
})
expect(needsSetup(row(undefined))).toBe(true)
expect(needsSetup(row({ configured: true, writable: true }))).toBe(false)
expect(needsSetup(row(undefined, true))).toBe(false)
const nested = { ...row(undefined), entry: { ...entry, settingsPath: ['providers', 'x'] } }
expect(needsSetup(nested)).toBe(false)
})
@@ -295,9 +287,7 @@ describe('ModelsSection', () => {
expect(providerTargetLabel(OPENAI_TARGET)).toBe('openai')
})
it('names only the fields the card can see, so an unseen secret survives', () => {
// `before` is the REDACTED subtree: a stored literal apiKey is in neither
// side, so no op mentions it and the seam leaves it alone.
it('names only changed fields instead of rebuilding the section', () => {
expect(pathOps(['providers', 'openai'], { baseURL: 'https://old', reasoning: 'high' }, { reasoning: 'high' }))
.toEqual([{ op: 'unset', path: ['providers', 'openai', 'baseURL'] }])
expect(pathOps([], { b: 1 }, { b: 2, d: 3 }))
@@ -725,8 +715,7 @@ describe('ModelsSection', () => {
})
it('clears an inherited override with an unset op, never a whole-section replace', async () => {
// The data-loss shape: the old path rebuilt the section from the REDACTED
// user layer and replaced it wholesale, deleting any stored literal key.
// The old path rebuilt the whole user section to clear one inherited field.
const { replace, update, mutate } = await mountSection()
fireEvent.click(screen.getByText(en.customized))
const effort = screen.getByLabelText<HTMLSelectElement>(en.effort)
@@ -800,9 +789,7 @@ describe('ModelsSection', () => {
fireEvent.click(screen.getAllByText(en.apply)[1] as HTMLElement)
await waitFor(() => { expect(mutate).toHaveBeenCalledTimes(1) })
// Only the edited field travels: apiKeyEnv, baseURL and headers were
// already stored with these values, so no op restates them — and the
// profile's stored literal apiKey, absent from the redacted view the card
// read, is named by nothing at all.
// already stored with these values, so no op restates them.
expect(mutate.mock.calls[0]?.[0]).toEqual({
ns: 'llm-pi-ai',
ops: [{ op: 'set', path: ['providers', 'openai', 'reasoning'], value: 'xhigh' }],
@@ -1134,8 +1121,8 @@ describe('ModelsSection', () => {
})
it('removes by unsetting the profile path, never by rebuilding the section', async () => {
// The section rebuild is what dropped stored literal secrets: this page
// only ever holds the redacted descriptor, so the removal names the path.
// The page only needs to name the profile path; rebuilding the section
// would widen the write for no benefit.
const { face, mutate, replace, controller } = await mountSection()
await removeProviderProfile(
face as unknown as Parameters<typeof removeProviderProfile>[0],
@@ -28,7 +28,6 @@ function harness(options: {
providerActive?: boolean
settingsNamespace?: boolean
apiKeyEnv?: string | null
literal?: boolean
configured?: () => boolean
credential?: { source?: string; writable: boolean }
describeFailure?: string
@@ -66,7 +65,7 @@ function harness(options: {
? {}
: { apiKeyEnv: options.apiKeyEnv ?? 'DEEPSEEK_API_KEY' },
applies: 'live' as const,
secrets: [{ path: ['apiKey'], set: options.literal === true }],
secrets: [],
revision: 0,
}],
})),
@@ -153,11 +152,10 @@ describe('DeepSeekOnboardingDialog', () => {
}
})
it('skips an absent adapter and already-configured literal or environment credentials', async () => {
it('skips an absent adapter and an already-configured environment credential', async () => {
for (const h of [
harness({ provider: false }),
harness({ providerSettingsNs: '' }),
harness({ literal: true, describeFailure: 'credential seam absent' }),
harness({ configured: () => true, credential: { source: 'env', writable: false } }),
]) {
const view = render(<DeepSeekOnboardingDialog {...h.props} />)
@@ -19,7 +19,6 @@ function row(overrides: Partial<ProviderRow> = {}): ProviderRow {
removable: false,
apiKeyEnv: 'DEEPSEEK_API_KEY',
credential: missingCredential,
literalApiKeyConfigured: false,
...overrides,
}
}
@@ -64,13 +63,6 @@ describe('deepSeekReadiness', () => {
}))).toEqual({ kind: 'configured' })
})
it('accepts the redacted literal-key sidecar before judging the credential domain', () => {
expect(deepSeekReadiness(state({
credentialError: 'credentials service absent',
rows: [row({ literalApiKeyConfigured: true, credential: undefined })],
}))).toEqual({ kind: 'configured' })
})
it('turns missing capabilities and inconsistent descriptors into diagnostics', () => {
expect(deepSeekReadiness(state({ status: 'error', error: 'settings down' }))).toEqual({
kind: 'unavailable',
+1 -26
View File
@@ -25,7 +25,7 @@ const NAMESPACES = [
value: { apiKeyEnv: 'DEEPSEEK_API_KEY', baseURL: 'https://base' },
base: { baseURL: 'https://base' },
applies: 'live' as const,
secrets: [{ path: ['apiKey'], set: false }],
secrets: [],
revision: 0,
},
{
@@ -85,7 +85,6 @@ describe('ModelsSettingsStore', () => {
removable: false,
apiKeyEnv: 'DEEPSEEK_API_KEY',
credential: { configured: false, writable: true },
literalApiKeyConfigured: false,
})
expect(byProvider.get('openai')).toMatchObject({
configured: true,
@@ -131,30 +130,6 @@ describe('ModelsSettingsStore', () => {
expect(store.store.getSnapshot().credentialError).toBe('credential transport refusal')
})
it('joins a configured literal key from the redacted secret sidecar', async () => {
const { face } = api({
describeSettings: () => Promise.resolve(ok({
writable: true,
hasDocument: false,
namespaces: [{
...NAMESPACES[0],
secrets: [
{ path: ['apiKey', 'nested'], set: true },
{ path: ['different'], set: true },
{ path: ['apiKey'], set: true },
],
}] as never,
})),
providers: () => Promise.resolve(ok({ providers: [DIRECTORY[0]] as never })),
})
const store = new ModelsSettingsStore(face)
await store.load()
expect(store.store.getSnapshot().rows[0]).toMatchObject({
literalApiKeyConfigured: true,
apiKeyEnv: 'DEEPSEEK_API_KEY',
})
})
it('surfaces a directory failure and keeps the last good rows', async () => {
const { face } = api()
const store = new ModelsSettingsStore(face)