Files
zooqueenandHanzo Dev f717dd89ad keys: the key a user pastes is sk-, not the retired hk-
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]>
2026-08-13 18:07:16 -07:00

88 lines
3.3 KiB
TypeScript

import { describe, it, expect } from 'vitest';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';
import { APIKEY_SETTING, MODEL_SETTING } from '../src/config';
const pkgRoot = join(dirname(fileURLToPath(import.meta.url)), '..');
function readJson(rel: string): any {
return JSON.parse(readFileSync(join(pkgRoot, rel), 'utf8'));
}
describe('manifest.json (ZAF v2 validity)', () => {
const manifest = readJson('manifest.json');
it('is valid JSON with the required ZAF fields present', () => {
expect(manifest).toBeTypeOf('object');
// Required by the ZAF v2 manifest spec.
expect(manifest.frameworkVersion).toBe('2.0');
expect(manifest.author).toBeTypeOf('object');
expect(manifest.author.name).toBeTruthy();
expect(manifest.author.email).toMatch(/@/);
expect(manifest.defaultLocale).toBe('en');
expect(manifest.location).toBeTypeOf('object');
});
it('is a private support app in the ticket_sidebar location', () => {
expect(manifest.private).toBe(true);
const loc = manifest.location.support.ticket_sidebar;
expect(loc).toBeTypeOf('object');
expect(loc.url).toBe('assets/iframe.html');
expect(loc.flexible).toBe(true);
});
it('uses singleInstall (not the invalid singleInstallation key)', () => {
expect(manifest.singleInstall).toBe(true);
expect('singleInstallation' in manifest).toBe(false);
});
it('declares the Hanzo key as a required SECURE password parameter', () => {
const key = manifest.parameters.find((p: any) => p.name === APIKEY_SETTING);
expect(key).toBeTruthy();
expect(key.type).toBe('password');
expect(key.secure).toBe(true);
expect(key.required).toBe(true);
});
it('declares a non-secure default_model parameter defaulting to a Zen model', () => {
const m = manifest.parameters.find((p: any) => p.name === MODEL_SETTING);
expect(m).toBeTruthy();
expect(m.secure).toBe(false);
expect(m.default).toBe('zen5');
});
it('whitelists only the Hanzo gateway domain (no /api/ host, no wildcard)', () => {
expect(manifest.domainWhitelist).toEqual(['api.hanzo.ai']);
});
it('never embeds a secret value in the manifest', () => {
const raw = readFileSync(join(pkgRoot, 'manifest.json'), 'utf8');
expect(raw).not.toMatch(/(?:sk|hk)-[A-Za-z0-9]/); // no literal key, retired shape included
const key = manifest.parameters.find((p: any) => p.name === APIKEY_SETTING);
expect(key.default ?? '').toBe(''); // no default secret
});
});
describe('translations/en.json (localization validity)', () => {
const tr = readJson('translations/en.json');
const manifest = readJson('manifest.json');
it('is valid JSON with the required app metadata keys', () => {
expect(tr.app).toBeTypeOf('object');
expect(tr.app.name).toBeTruthy();
expect(tr.app.short_description).toBeTruthy();
expect(tr.app.short_description.length).toBeLessThanOrEqual(80);
expect(tr.app.long_description).toBeTruthy();
expect(tr.app.installation_instructions).toBeTruthy();
});
it('provides a label for every manifest parameter (keys must match)', () => {
for (const p of manifest.parameters) {
const entry = tr.app.parameters?.[p.name];
expect(entry, `missing translation for parameter ${p.name}`).toBeTruthy();
expect(entry.label).toBeTruthy();
}
});
});