mirror of
https://github.com/hanzoai/extension.git
synced 2026-10-31 21:57:06 +00:00
28 apps told the user to paste an `hk-` key — input placeholders, settings help text, READMEs, the error thrown when the field is empty — and five of them validated that paste against /^hk-/ before sending it as a bearer. Nothing mints that prefix any more: cloud accepts pk- and sk-, IAM mints sk-. So the guard admitted a credential that authenticates nothing, and the panel failed later at the gateway with nothing on screen to explain it. The three leak detectors keep hk- and gain sk-. Salesforce's source scan and the two Zendesk tests exist to catch a key committed to source or echoed back through a request; retired keys are still in circulation and leak exactly as badly, while a detector that only knew hk- would have gone blind to every key minted from here on. `sk-` used to be the example of the foreign key the guard screened out — an OpenAI key. It cannot mean that now, and shape alone cannot tell one vendor's sk- from another's, so those comments say what the check really proves and point at the /v1/models call that proves the rest. The three tests that pinned "sk- is rejected" now pin "hk- is rejected", which is the invariant that survived. Verified: 2029 tests pass across the 28 packages; typecheck clean on 25 of them (hubspot, jupyter and teams fail identically at HEAD on JSX and ESM type conflicts in files this does not touch); salesforce validate-source green. Co-authored-by: Hanzo Dev <[email protected]>
78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
resolveSettings,
|
|
DEFAULT_SETTINGS,
|
|
DEFAULT_MODEL,
|
|
HANZO_API_BASE_URL,
|
|
CommandIds,
|
|
PLUGIN_ID,
|
|
} from '../src/config';
|
|
|
|
describe('resolveSettings', () => {
|
|
it('fills defaults when everything is missing', () => {
|
|
expect(resolveSettings({})).toEqual(DEFAULT_SETTINGS);
|
|
});
|
|
|
|
it('uses provided values', () => {
|
|
const s = resolveSettings({
|
|
apiKey: 'sk-abc',
|
|
model: 'zen5-coder',
|
|
baseUrl: 'https://gw.example.com',
|
|
});
|
|
expect(s).toEqual({
|
|
apiKey: 'sk-abc',
|
|
model: 'zen5-coder',
|
|
baseUrl: 'https://gw.example.com',
|
|
});
|
|
});
|
|
|
|
it('falls back to defaults on blank / whitespace strings', () => {
|
|
const s = resolveSettings({ apiKey: ' ', model: '', baseUrl: ' ' });
|
|
expect(s.model).toBe(DEFAULT_MODEL);
|
|
expect(s.baseUrl).toBe(HANZO_API_BASE_URL);
|
|
expect(s.apiKey).toBe('');
|
|
});
|
|
|
|
it('trims values and strips trailing slashes from baseUrl', () => {
|
|
const s = resolveSettings({
|
|
apiKey: ' sk-x ',
|
|
model: ' zen5 ',
|
|
baseUrl: 'https://api.hanzo.ai///',
|
|
});
|
|
expect(s.apiKey).toBe('sk-x');
|
|
expect(s.model).toBe('zen5');
|
|
expect(s.baseUrl).toBe('https://api.hanzo.ai');
|
|
});
|
|
|
|
it('ignores non-string values', () => {
|
|
const s = resolveSettings({
|
|
apiKey: 123 as unknown,
|
|
model: null as unknown,
|
|
baseUrl: {} as unknown,
|
|
});
|
|
expect(s).toEqual(DEFAULT_SETTINGS);
|
|
});
|
|
|
|
it('default model is a Zen model and default base is api.hanzo.ai', () => {
|
|
expect(DEFAULT_MODEL).toBe('zen5');
|
|
expect(HANZO_API_BASE_URL).toBe('https://api.hanzo.ai');
|
|
});
|
|
});
|
|
|
|
describe('command + plugin identifiers', () => {
|
|
it('every command id is namespaced under hanzo:', () => {
|
|
for (const id of Object.values(CommandIds)) {
|
|
expect(id.startsWith('hanzo:')).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('command ids are unique', () => {
|
|
const ids = Object.values(CommandIds);
|
|
expect(new Set(ids).size).toBe(ids.length);
|
|
});
|
|
|
|
it('plugin id matches the schema basename convention', () => {
|
|
expect(PLUGIN_ID).toBe('@hanzo/jupyter:plugin');
|
|
});
|
|
});
|