fix(street-level): point a key-gated layer at Street View; button beside the hint

Review of #966: with a Google Maps key but no Mapillary token, switching
Street Level on read KEY REQUIRED / "Needs MAPILLARY_CLIENT_TOKEN" with
nothing about Street View, which stayed off (billing), so the layer looked
broken.

- While the switched-on providers lack their keys, the layer reports the
  switched-off ones that would draw with a key already set
  (keyAlternatives: Street View on Google 3D with a Google key). The
  panel's KEY REQUIRED tooltip, its coverage line and the layer row's
  tooltip then read "Needs MAPILLARY_CLIENT_TOKEN — add it in Provider
  Settings, or light STREET VIEW to use your Google Maps key"
  (keySetupWithAlternatives). Off Google 3D the plain KEY REQUIRED stays.
  Street View stays off by default.
- OPEN STREET VIEW moves beside the coverage hint: at the default panel
  width the PROVIDERS row has no room for it, so it wrapped onto a line of
  its own.
- The panel gate's corner drag names what lay under the pointer when it
  fails.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Said TurkseverandClaude Opus 5.5 committed 2026-10-09 00:05:58 +01:00
1 parent f5c4f3fda3
commit e823e15025
15 files changed
+669 -138

No files matched your search

+433 -118
View File
@@ -9,6 +9,7 @@ import {
isKeySetupExternallyManaged,
keySetupStatus,
keySetupRequirement,
keySetupWithAlternatives,
knownKeySetupEnvVars,
parseWindowsUserSid,
upsertDotenvValues,
@@ -28,7 +29,10 @@ test('the boot provenance snapshot survives in-process Vite config re-evaluation
// panel save has already set its values live on process.env. A recomputed
// snapshot would classify the panel's own keys as external (read-only) until
// a full process relaunch, so the first evaluation's snapshot must win.
const source = readFileSync(new URL('../server/standalone/key-setup.js', import.meta.url), 'utf8');
const source = readFileSync(
new URL('../server/standalone/key-setup.js', import.meta.url),
'utf8',
);
assert.match(
source,
/const PROVIDER_ENV_AT_BOOT\s*=\s*\(?globalThis\.__GEV_PROVIDER_ENV_AT_BOOT\s*\?\?=\s*Object\.freeze\(/,
@@ -36,24 +40,40 @@ test('the boot provenance snapshot survives in-process Vite config re-evaluation
});
test('external ownership uses boot provenance even when store and shell values match', () => {
assert.equal(isKeySetupExternallyManaged({
effectiveValue: 'same-value',
storedValue: 'same-value',
wasExternalAtBoot: true,
}), true, 'equal bytes cannot turn a shell/Keychain value into a file-owned value');
assert.equal(isKeySetupExternallyManaged({
effectiveValue: 'file-value',
storedValue: 'file-value',
}), false, 'a value loaded only from the owned store remains editable');
assert.equal(isKeySetupExternallyManaged({
effectiveValue: 'shell-value',
storedValue: 'stale-file-value',
}), true, 'a differing live value remains external');
assert.equal(isKeySetupExternallyManaged({
effectiveValue: '',
storedValue: 'stale-file-value',
wasExternalAtBoot: true,
}), false, 'an absent live credential has no external owner');
assert.equal(
isKeySetupExternallyManaged({
effectiveValue: 'same-value',
storedValue: 'same-value',
wasExternalAtBoot: true,
}),
true,
'equal bytes cannot turn a shell/Keychain value into a file-owned value',
);
assert.equal(
isKeySetupExternallyManaged({
effectiveValue: 'file-value',
storedValue: 'file-value',
}),
false,
'a value loaded only from the owned store remains editable',
);
assert.equal(
isKeySetupExternallyManaged({
effectiveValue: 'shell-value',
storedValue: 'stale-file-value',
}),
true,
'a differing live value remains external',
);
assert.equal(
isKeySetupExternallyManaged({
effectiveValue: '',
storedValue: 'stale-file-value',
wasExternalAtBoot: true,
}),
false,
'an absent live credential has no external owner',
);
});
test('the status payload reports presence without any credential material', () => {
@@ -63,17 +83,35 @@ test('the status payload reports presence without any credential material', () =
// Secret missing: the OpenSky pair must read as NOT set.
};
const status = keySetupStatus(env);
assert.equal(status.total, KEY_SETUP_KEYS.filter((key) => !key.hidden).length);
assert.equal(
status.total,
KEY_SETUP_KEYS.filter((key) => !key.hidden).length,
);
const google = status.keys.find((key) => key.id === 'google-maps');
assert.equal(google.set, true);
const opensky = status.keys.find((key) => key.id === 'opensky');
assert.equal(opensky.set, false, 'half a credential pair is not configured');
const serialized = JSON.stringify(status);
assert.ok(!serialized.includes('AIzaSyFakeFakeFakeFake1234'), 'a value leaked into status');
assert.ok(!serialized.includes('client-id-abcdef'), 'a value leaked into status');
assert.ok(!serialized.includes('1234'), 'a credential suffix leaked into status');
assert.ok(!serialized.includes('abcdef'), 'a credential suffix leaked into status');
assert.ok(!serialized.includes('tails'), 'status must not expose a credential-tail field');
assert.ok(
!serialized.includes('AIzaSyFakeFakeFakeFake1234'),
'a value leaked into status',
);
assert.ok(
!serialized.includes('client-id-abcdef'),
'a value leaked into status',
);
assert.ok(
!serialized.includes('1234'),
'a credential suffix leaked into status',
);
assert.ok(
!serialized.includes('abcdef'),
'a credential suffix leaked into status',
);
assert.ok(
!serialized.includes('tails'),
'status must not expose a credential-tail field',
);
assert.equal(status.setCount, 1);
});
@@ -84,25 +122,57 @@ test('whitespace-only env values do not count as configured', () => {
test('subprocess success requires a clean zero exit', () => {
assert.equal(commandCompletedSuccessfully({ status: 0, signal: null }), true);
assert.equal(commandCompletedSuccessfully({ status: 1, signal: null }), false);
assert.equal(commandCompletedSuccessfully({ status: 0, signal: 'SIGTERM' }), false);
assert.equal(commandCompletedSuccessfully({ status: 0, signal: null, error: new Error('spawn failed') }), false);
assert.equal(
commandCompletedSuccessfully({ status: 1, signal: null }),
false,
);
assert.equal(
commandCompletedSuccessfully({ status: 0, signal: 'SIGTERM' }),
false,
);
assert.equal(
commandCompletedSuccessfully({
status: 0,
signal: null,
error: new Error('spawn failed'),
}),
false,
);
assert.equal(commandCompletedSuccessfully(null), false);
});
test('Windows owner SID parsing reads only the structured user-SID CSV field', () => {
const localUser = 'S-1-5-21-1111111111-2222222222-3333333333-1001';
const entraUser = 'S-1-12-1-1111111111-2222222222-3333333333-4444444444';
assert.equal(parseWindowsUserSid(`"WORKSTATION\\alice","${localUser}"\r\n`), localUser);
assert.equal(parseWindowsUserSid(`"AzureAD\\alice","${entraUser}"`), entraUser);
assert.equal(
parseWindowsUserSid(`"WORKSTATION\\alice","${localUser}"\r\n`),
localUser,
);
assert.equal(
parseWindowsUserSid(`"AzureAD\\alice","${entraUser}"`),
entraUser,
);
assert.equal(
parseWindowsUserSid(`"${localUser}","S-1-5-32-545"`),
null,
'an SID-looking account name must never be mistaken for the token SID',
);
assert.equal(parseWindowsUserSid('"WORKSTATION\\alice","S-1-5-32-545"'), null, 'broad group SID refused');
assert.equal(parseWindowsUserSid(`"WORKSTATION\\alice","${localUser}"\n"extra","${localUser}"`), null);
assert.equal(parseWindowsUserSid(`"WORKSTATION\\alice","${localUser}`), null, 'unterminated CSV refused');
assert.equal(
parseWindowsUserSid('"WORKSTATION\\alice","S-1-5-32-545"'),
null,
'broad group SID refused',
);
assert.equal(
parseWindowsUserSid(
`"WORKSTATION\\alice","${localUser}"\n"extra","${localUser}"`,
),
null,
);
assert.equal(
parseWindowsUserSid(`"WORKSTATION\\alice","${localUser}`),
null,
'unterminated CSV refused',
);
});
test('validation accepts every registry env var and only those', () => {
@@ -112,8 +182,16 @@ test('validation accepts every registry env var and only those', () => {
assert.equal(verdict.ok, true, `${name} should validate`);
assert.equal(verdict.updates[name], 'valid-value-123');
}
assert.equal(validateKeySetupUpdates({ PATH: '/usr/bin' }).ok, false, 'PATH must be refused');
assert.equal(validateKeySetupUpdates({ NODE_OPTIONS: '--x' }).ok, false, 'NODE_OPTIONS must be refused');
assert.equal(
validateKeySetupUpdates({ PATH: '/usr/bin' }).ok,
false,
'PATH must be refused',
);
assert.equal(
validateKeySetupUpdates({ NODE_OPTIONS: '--x' }).ok,
false,
'NODE_OPTIONS must be refused',
);
});
test('validation trims, and refuses empties, newlines, spaces, and oversize values', () => {
@@ -122,11 +200,25 @@ test('validation trims, and refuses empties, newlines, spaces, and oversize valu
assert.equal(trimmed.updates.OPENAI_API_KEY, 'sk-abc123');
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: '' }).ok, false);
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: ' ' }).ok, false);
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: 'a\nb' }).ok, false, 'newline injection');
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: 'a b' }).ok, false, 'inner space');
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: 'kéy' }).ok, false, 'non-ASCII');
assert.equal(
validateKeySetupUpdates({ OPENAI_API_KEY: 'x'.repeat(KEY_SETUP_VALUE_LIMIT + 1) }).ok,
validateKeySetupUpdates({ OPENAI_API_KEY: 'a\nb' }).ok,
false,
'newline injection',
);
assert.equal(
validateKeySetupUpdates({ OPENAI_API_KEY: 'a b' }).ok,
false,
'inner space',
);
assert.equal(
validateKeySetupUpdates({ OPENAI_API_KEY: 'kéy' }).ok,
false,
'non-ASCII',
);
assert.equal(
validateKeySetupUpdates({
OPENAI_API_KEY: 'x'.repeat(KEY_SETUP_VALUE_LIMIT + 1),
}).ok,
false,
);
assert.equal(validateKeySetupUpdates(null).ok, false);
@@ -144,13 +236,16 @@ test('upsert replaces the last active assignment in place', () => {
'',
].join('\n');
const next = upsertDotenvValues(text, { OPENAI_API_KEY: 'new-key' });
assert.equal(next, [
'# comment stays',
'OPENAI_API_KEY=old-one',
'PORT=4173',
'OPENAI_API_KEY=new-key',
'',
].join('\n'));
assert.equal(
next,
[
'# comment stays',
'OPENAI_API_KEY=old-one',
'PORT=4173',
'OPENAI_API_KEY=new-key',
'',
].join('\n'),
);
});
test('upsert uncomments a commented assignment in place, keeping file shape', () => {
@@ -161,36 +256,49 @@ test('upsert uncomments a commented assignment in place, keeping file shape', ()
'PORT=4173',
].join('\n');
const next = upsertDotenvValues(text, { FIRMS_MAP_KEY: 'firms-123' });
assert.equal(next, [
'# Optional: NASA FIRMS live active fires.',
'FIRMS_MAP_KEY=firms-123',
'',
'PORT=4173',
].join('\n') + '\n');
assert.equal(
next,
[
'# Optional: NASA FIRMS live active fires.',
'FIRMS_MAP_KEY=firms-123',
'',
'PORT=4173',
].join('\n') + '\n',
);
});
test('upsert appends unknown keys under one shared header, once', () => {
const first = upsertDotenvValues('PORT=4173\n', { OPENAI_API_KEY: 'sk-1' });
assert.equal(first, [
'PORT=4173',
'',
KEY_SETUP_APPEND_HEADER,
'OPENAI_API_KEY=sk-1',
].join('\n') + '\n');
assert.equal(
first,
['PORT=4173', '', KEY_SETUP_APPEND_HEADER, 'OPENAI_API_KEY=sk-1'].join(
'\n',
) + '\n',
);
const second = upsertDotenvValues(first, { FIRMS_MAP_KEY: 'f-2' });
assert.equal(second, [
'PORT=4173',
'',
KEY_SETUP_APPEND_HEADER,
'OPENAI_API_KEY=sk-1',
'FIRMS_MAP_KEY=f-2',
].join('\n') + '\n');
assert.equal(second.split(KEY_SETUP_APPEND_HEADER).length, 2, 'header written once');
assert.equal(
second,
[
'PORT=4173',
'',
KEY_SETUP_APPEND_HEADER,
'OPENAI_API_KEY=sk-1',
'FIRMS_MAP_KEY=f-2',
].join('\n') + '\n',
);
assert.equal(
second.split(KEY_SETUP_APPEND_HEADER).length,
2,
'header written once',
);
});
test('upsert births a well-formed file from nothing', () => {
const next = upsertDotenvValues('', { GOOGLE_MAPS_API_KEY: 'AIza-x' });
assert.equal(next, `${KEY_SETUP_APPEND_HEADER}\nGOOGLE_MAPS_API_KEY=AIza-x\n`);
assert.equal(
next,
`${KEY_SETUP_APPEND_HEADER}\nGOOGLE_MAPS_API_KEY=AIza-x\n`,
);
});
test('upsert handles export-prefixed lines and never touches lookalike keys', () => {
@@ -207,15 +315,21 @@ test('upsert handles export-prefixed lines and never touches lookalike keys', ()
});
test('upsert is idempotent for a repeated save', () => {
const once = upsertDotenvValues('', { OPENAI_API_KEY: 'sk-1', FIRMS_MAP_KEY: 'f-1' });
const twice = upsertDotenvValues(once, { OPENAI_API_KEY: 'sk-1', FIRMS_MAP_KEY: 'f-1' });
const once = upsertDotenvValues('', {
OPENAI_API_KEY: 'sk-1',
FIRMS_MAP_KEY: 'f-1',
});
const twice = upsertDotenvValues(once, {
OPENAI_API_KEY: 'sk-1',
FIRMS_MAP_KEY: 'f-1',
});
assert.equal(once, twice);
});
test('a real .env.example round-trip: the curated file keeps its shape', () => {
// A representative slice of the shipped .env.example.
const example = [
'# God\'s Eye View — environment variables',
"# God's Eye View — environment variables",
'GOOGLE_MAPS_API_KEY=your_google_maps_api_key_here',
'',
'# Optional: OpenAI Realtime voice control. Do not prefix with VITE_.',
@@ -232,8 +346,16 @@ test('a real .env.example round-trip: the curated file keeps its shape', () => {
const lines = next.split('\n');
assert.equal(lines[1], 'GOOGLE_MAPS_API_KEY=AIza-real');
assert.equal(lines[4], 'OPENAI_API_KEY=sk-real');
assert.equal(lines[5], 'OPENAI_REALTIME_MODEL=gpt-realtime-2', 'sibling key untouched');
assert.equal(lines[7], 'TOMTOM_API_KEY=tt-real', 'commented key uncommented in place');
assert.equal(
lines[5],
'OPENAI_REALTIME_MODEL=gpt-realtime-2',
'sibling key untouched',
);
assert.equal(
lines[7],
'TOMTOM_API_KEY=tt-real',
'commented key uncommented in place',
);
});
test('the admission gate refuses every non-local shape, one assertion per refusal', async () => {
@@ -246,29 +368,111 @@ test('the admission gate refuses every non-local shape, one assertion per refusa
contentType: 'application/json',
env: {},
};
assert.equal(admitKeySetupRequest(local).ok, true, 'the honest local request is admitted');
assert.equal(admitKeySetupRequest({ ...local, method: 'GET', contentType: undefined }).ok, true, 'local GET needs no content type');
assert.equal(admitKeySetupRequest({ ...local, origin: undefined }).ok, false, 'POST without Origin is refused');
assert.equal(admitKeySetupRequest({ ...local, method: 'GET', origin: undefined, contentType: undefined }).ok, true, 'local GET may omit Origin');
assert.equal(admitKeySetupRequest({ ...local, remoteAddress: '::ffff:127.0.0.1', hostHeader: '[::1]:4173', origin: 'http://[::1]:4173' }).ok, true, 'IPv6 loopback forms are local');
assert.equal(
admitKeySetupRequest(local).ok,
true,
'the honest local request is admitted',
);
assert.equal(
admitKeySetupRequest({ ...local, method: 'GET', contentType: undefined })
.ok,
true,
'local GET needs no content type',
);
assert.equal(
admitKeySetupRequest({ ...local, origin: undefined }).ok,
false,
'POST without Origin is refused',
);
assert.equal(
admitKeySetupRequest({
...local,
method: 'GET',
origin: undefined,
contentType: undefined,
}).ok,
true,
'local GET may omit Origin',
);
assert.equal(
admitKeySetupRequest({
...local,
remoteAddress: '::ffff:127.0.0.1',
hostHeader: '[::1]:4173',
origin: 'http://[::1]:4173',
}).ok,
true,
'IPv6 loopback forms are local',
);
// Tunnel/LAN sharing of any kind removes the surface outright — tunnel
// traffic arrives FROM loopback, so no socket check can carry this boundary.
assert.equal(admitKeySetupRequest({ ...local, env: { PINOKIO_SHARE_CLOUDFLARE: 'true' } }).ok, false, 'sharing disables the surface');
assert.equal(admitKeySetupRequest({ ...local, env: { PINOKIO_SHARE_LOCAL: '1' } }).ok, false, 'LAN sharing disables the surface');
assert.equal(
admitKeySetupRequest({
...local,
env: { PINOKIO_SHARE_CLOUDFLARE: 'true' },
}).ok,
false,
'sharing disables the surface',
);
assert.equal(
admitKeySetupRequest({ ...local, env: { PINOKIO_SHARE_LOCAL: '1' } }).ok,
false,
'LAN sharing disables the surface',
);
// A LAN peer reaching a wide-bound server.
assert.equal(admitKeySetupRequest({ ...local, remoteAddress: '192.168.1.20' }).ok, false, 'non-loopback socket refused');
assert.equal(
admitKeySetupRequest({ ...local, remoteAddress: '192.168.1.20' }).ok,
false,
'non-loopback socket refused',
);
// Tunnel and DNS-rebinding traffic carries a foreign Host over a loopback socket.
assert.equal(admitKeySetupRequest({ ...local, hostHeader: 'abc.trycloudflare.com' }).ok, false, 'foreign Host refused');
assert.equal(admitKeySetupRequest({ ...local, hostHeader: 'workstation.local:4173' }).ok, false, 'non-localhost hostnames refused');
assert.equal(admitKeySetupRequest({ ...local, hostHeader: '' }).ok, false, 'missing Host refused');
assert.equal(admitKeySetupRequest({ ...local, hostHeader: '[::1].evil:4173' }).ok, false, 'malformed bracketed Host refused');
assert.equal(
admitKeySetupRequest({ ...local, hostHeader: 'abc.trycloudflare.com' }).ok,
false,
'foreign Host refused',
);
assert.equal(
admitKeySetupRequest({ ...local, hostHeader: 'workstation.local:4173' }).ok,
false,
'non-localhost hostnames refused',
);
assert.equal(
admitKeySetupRequest({ ...local, hostHeader: '' }).ok,
false,
'missing Host refused',
);
assert.equal(
admitKeySetupRequest({ ...local, hostHeader: '[::1].evil:4173' }).ok,
false,
'malformed bracketed Host refused',
);
// A hostile web page POSTing at localhost carries its own Origin.
assert.equal(admitKeySetupRequest({ ...local, origin: 'https://evil.example' }).ok, false, 'cross-origin refused');
assert.equal(admitKeySetupRequest({ ...local, origin: 'not a url' }).ok, false, 'unparseable Origin refused');
assert.equal(admitKeySetupRequest({ ...local, origin: 'http://localhost:4174' }).ok, false, 'cross-port Origin refused');
assert.equal(admitKeySetupRequest({ ...local, origin: 'https://localhost:4173' }).ok, false, 'cross-scheme Origin refused');
assert.equal(admitKeySetupRequest({ ...local, origin: 'http://127.0.0.1:4173' }).ok, false, 'different loopback host Origin refused');
assert.equal(
admitKeySetupRequest({ ...local, origin: 'https://evil.example' }).ok,
false,
'cross-origin refused',
);
assert.equal(
admitKeySetupRequest({ ...local, origin: 'not a url' }).ok,
false,
'unparseable Origin refused',
);
assert.equal(
admitKeySetupRequest({ ...local, origin: 'http://localhost:4174' }).ok,
false,
'cross-port Origin refused',
);
assert.equal(
admitKeySetupRequest({ ...local, origin: 'https://localhost:4173' }).ok,
false,
'cross-scheme Origin refused',
);
assert.equal(
admitKeySetupRequest({ ...local, origin: 'http://127.0.0.1:4173' }).ok,
false,
'different loopback host Origin refused',
);
// A simple-request POST (no JSON content type) is the CSRF write shape.
const noJson = admitKeySetupRequest({ ...local, contentType: 'text/plain' });
assert.equal(noJson.ok, false, 'non-JSON POST refused');
@@ -279,8 +483,16 @@ test('a null value validates as a removal; an empty string still does not', () =
const removal = validateKeySetupUpdates({ OPENAI_API_KEY: null });
assert.equal(removal.ok, true);
assert.equal(removal.updates.OPENAI_API_KEY, null);
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: '' }).ok, false, 'empty is a mistake, not a removal');
assert.equal(validateKeySetupUpdates({ PATH: null }).ok, false, 'removal is registry-bound too');
assert.equal(
validateKeySetupUpdates({ OPENAI_API_KEY: '' }).ok,
false,
'empty is a mistake, not a removal',
);
assert.equal(
validateKeySetupUpdates({ PATH: null }).ok,
false,
'removal is registry-bound too',
);
});
test('removal comments the assignment back out, returning the file to template shape', () => {
@@ -291,7 +503,11 @@ test('removal comments the assignment back out, returning the file to template s
].join('\n');
const next = upsertDotenvValues(text, { OPENAI_API_KEY: null });
const lines = next.split('\n');
assert.equal(lines[1], '# OPENAI_API_KEY=', 'active line commented out, not deleted');
assert.equal(
lines[1],
'# OPENAI_API_KEY=',
'active line commented out, not deleted',
);
assert.equal(lines[2], 'PORT=4173', 'neighbors untouched');
// Removing a key with no active assignment changes nothing.
assert.equal(upsertDotenvValues(next, { FIRMS_MAP_KEY: null }), next);
@@ -303,62 +519,161 @@ test('removal comments the assignment back out, returning the file to template s
test('the sharing gate treats a real PINOKIO_SHARE_VAR as sharing, but not the empty/sentinel normal state', async () => {
const { admitKeySetupRequest } = await import('./keySetupCore.mjs');
const base = {
method: 'POST', remoteAddress: '127.0.0.1', hostHeader: 'localhost:4173',
origin: 'http://localhost:4173', contentType: 'application/json',
method: 'POST',
remoteAddress: '127.0.0.1',
hostHeader: 'localhost:4173',
origin: 'http://localhost:4173',
contentType: 'application/json',
};
// The ordinary launch states: unset, empty, or the explicit disabled sentinel.
assert.equal(admitKeySetupRequest({ ...base, env: {} }).ok, true, 'unset SHARE_VAR is normal');
assert.equal(admitKeySetupRequest({ ...base, env: { PINOKIO_SHARE_VAR: '' } }).ok, true, 'empty SHARE_VAR is normal');
assert.equal(admitKeySetupRequest({ ...base, env: { PINOKIO_SHARE_VAR: '__gev_sharing_disabled__' } }).ok, true, 'the disabled sentinel is normal');
assert.equal(
admitKeySetupRequest({ ...base, env: {} }).ok,
true,
'unset SHARE_VAR is normal',
);
assert.equal(
admitKeySetupRequest({ ...base, env: { PINOKIO_SHARE_VAR: '' } }).ok,
true,
'empty SHARE_VAR is normal',
);
assert.equal(
admitKeySetupRequest({
...base,
env: { PINOKIO_SHARE_VAR: '__gev_sharing_disabled__' },
}).ok,
true,
'the disabled sentinel is normal',
);
// A real tunnel var disables the surface.
assert.equal(admitKeySetupRequest({ ...base, env: { PINOKIO_SHARE_VAR: 'MY_TUNNEL_TOKEN' } }).ok, false, 'a real share var is sharing');
assert.equal(
admitKeySetupRequest({
...base,
env: { PINOKIO_SHARE_VAR: 'MY_TUNNEL_TOKEN' },
}).ok,
false,
'a real share var is sharing',
);
});
test('the gate refuses proxied requests even from a loopback socket with local headers', async () => {
const { admitKeySetupRequest } = await import('./keySetupCore.mjs');
const base = {
method: 'POST', remoteAddress: '127.0.0.1', hostHeader: 'localhost:4173',
origin: 'http://localhost:4173', contentType: 'application/json', env: {},
method: 'POST',
remoteAddress: '127.0.0.1',
hostHeader: 'localhost:4173',
origin: 'http://localhost:4173',
contentType: 'application/json',
env: {},
};
assert.equal(admitKeySetupRequest(base).ok, true, 'no proxy headers → admitted');
for (const header of ['x-forwarded-for', 'forwarded', 'via', 'cf-connecting-ip', 'cf-ray', 'x-real-ip', 'x-forwarded-host', 'x-forwarded-port', 'x-forwarded-proto']) {
assert.equal(
admitKeySetupRequest(base).ok,
true,
'no proxy headers → admitted',
);
for (const header of [
'x-forwarded-for',
'forwarded',
'via',
'cf-connecting-ip',
'cf-ray',
'x-real-ip',
'x-forwarded-host',
'x-forwarded-port',
'x-forwarded-proto',
]) {
assert.equal(
admitKeySetupRequest({ ...base, proxyHeaders: { [header]: 'anything' } }).ok,
admitKeySetupRequest({ ...base, proxyHeaders: { [header]: 'anything' } })
.ok,
false,
`${header} present → refused`,
);
}
// An empty forwarding header is not a proxy signal.
assert.equal(admitKeySetupRequest({ ...base, proxyHeaders: { 'x-forwarded-for': '' } }).ok, true);
assert.equal(
admitKeySetupRequest({ ...base, proxyHeaders: { 'x-forwarded-for': '' } })
.ok,
true,
);
});
test('validation rejects dotenv metacharacters that would round-trip wrong', () => {
for (const bad of ['abc#def', 'ab"cd', "ab'cd", 'ab$cd', 'ab\\cd', 'ab`cd']) {
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: bad }).ok, false, `${JSON.stringify(bad)} refused`);
assert.equal(
validateKeySetupUpdates({ OPENAI_API_KEY: bad }).ok,
false,
`${JSON.stringify(bad)} refused`,
);
}
// Real key alphabets still pass: base64url, JWT dots, hex, plus/slash.
for (const good of ['sk-AbC0-9_x', 'eyJhbGc.eyJzdWI.QWxpY2U', 'a1b2c3d4e5f6', 'AB+cd/ef=']) {
assert.equal(validateKeySetupUpdates({ OPENAI_API_KEY: good }).ok, true, `${good} accepted`);
for (const good of [
'sk-AbC0-9_x',
'eyJhbGc.eyJzdWI.QWxpY2U',
'a1b2c3d4e5f6',
'AB+cd/ef=',
]) {
assert.equal(
validateKeySetupUpdates({ OPENAI_API_KEY: good }).ok,
true,
`${good} accepted`,
);
}
});
test('server Google key remains supported without appearing in setup or its missing count', () => {
const secret = 'server-key-fixture';
assert.deepEqual(validateKeySetupUpdates({ GOOGLE_MAPS_SERVER_API_KEY: secret }), {
ok: true, updates: { GOOGLE_MAPS_SERVER_API_KEY: secret },
});
assert.equal(validateKeySetupUpdates({ GOOGLE_MAPS_SERVER_API_KEY: null }).ok, true);
assert.deepEqual(
validateKeySetupUpdates({ GOOGLE_MAPS_SERVER_API_KEY: secret }),
{
ok: true,
updates: { GOOGLE_MAPS_SERVER_API_KEY: secret },
},
);
assert.equal(
validateKeySetupUpdates({ GOOGLE_MAPS_SERVER_API_KEY: null }).ok,
true,
);
const status = keySetupStatus({ GOOGLE_MAPS_SERVER_API_KEY: secret });
assert.deepEqual(status, keySetupStatus({}));
assert.equal(status.keys.some((key) => key.id === 'google-maps-server'), false);
assert.equal(
status.keys.some((key) => key.id === 'google-maps-server'),
false,
);
assert.equal(keySetupRequirement('google-maps-server'), '');
assert.equal(status.keys.find((key) => key.id === 'google-maps').title, 'GOOGLE MAPS');
const allVisibleConfigured = Object.fromEntries(status.keys.flatMap((key) =>
key.envVars.map((name) => [name, 'configured-fixture']),
));
assert.equal(
status.keys.find((key) => key.id === 'google-maps').title,
'GOOGLE MAPS',
);
const allVisibleConfigured = Object.fromEntries(
status.keys.flatMap((key) =>
key.envVars.map((name) => [name, 'configured-fixture']),
),
);
const complete = keySetupStatus(allVisibleConfigured);
assert.equal(complete.setCount, complete.total, 'an absent server key must not leave setup incomplete');
assert.deepEqual(complete, keySetupStatus({ ...allVisibleConfigured, GOOGLE_MAPS_SERVER_API_KEY: secret }));
assert.equal(
complete.setCount,
complete.total,
'an absent server key must not leave setup incomplete',
);
assert.deepEqual(
complete,
keySetupStatus({
...allVisibleConfigured,
GOOGLE_MAPS_SERVER_API_KEY: secret,
}),
);
assert.ok(!JSON.stringify(status).includes('GOOGLE_MAPS_SERVER_API_KEY'));
assert.ok(!JSON.stringify(status).includes(secret));
});
test('key guidance can offer another source that works with a key already set', () => {
const streetView = { label: 'STREET VIEW', requiresKeyId: 'google-maps' };
assert.equal(
keySetupWithAlternatives(keySetupRequirement('mapillary'), [streetView]),
'Needs MAPILLARY_CLIENT_TOKEN — add it in Provider Settings, or light STREET VIEW to use your Google Maps key',
);
assert.equal(
keySetupWithAlternatives('', [streetView]),
'Light STREET VIEW to use your Google Maps key',
);
assert.equal(keySetupWithAlternatives('Needs X', []), 'Needs X');
});