fix: report OpenSky Basic and auto modes accurately

This commit is contained in:
Sameh Khamis committed 2026-09-20 16:43:16 -07:00
1 parent a716b059b8
commit 9ad64112dc
5 files changed
+50 -12

No files matched your search

+4 -3
View File
@@ -268,9 +268,10 @@ of current runtime behavior, see [`docs/CURRENT-STATE.md`](docs/CURRENT-STATE.md
### Fixed ### Fixed
- Make `npm run doctor` report keyless anonymous OpenSky access for explicit - Make `npm run doctor` report keyless anonymous OpenSky access for explicit
`OPENSKY_AUTH_MODE=anon` and missing OAuth client pairs while retaining the `OPENSKY_AUTH_MODE=anon` and OAuth mode without a client pair, retain the
existing OAuth-pair capability wording. OpenSky proxy authentication is existing OAuth-pair capability wording, and identify selected Basic or auto
unchanged. modes without guessing their eventual credential choice. OpenSky proxy
authentication is unchanged.
- Bikeshare stations load again. The extracted station source addressed the - Bikeshare stations load again. The extracted station source addressed the
proxy as `/api/gbfs?url=`, but the proxy reads its upstream target from the proxy as `/api/gbfs?url=`, but the proxy reads its upstream target from the
path, so every request answered 400 and the layer reported a fetch error for path, so every request answered 400 and the layer reported a fetch error for
+5 -4
View File
@@ -414,10 +414,11 @@ Add these if you need higher polling allowances.
where each configured provider was found without printing credential values. where each configured provider was found without printing credential values.
On macOS its Keychain-aware result previews `./scripts/dev-fresh.sh`; plain On macOS its Keychain-aware result previews `./scripts/dev-fresh.sh`; plain
`npm run dev` reads only explicit environment and Vite dotenv values. The `npm run dev` reads only explicit environment and Vite dotenv values. The
OpenSky summary reports keyless anonymous access for explicit `anon` or when OpenSky summary reports keyless anonymous access for explicit `anon` or an
no OAuth client pair is present, and retains presence-only wording for a OAuth mode without a client pair, retains presence-only wording for a complete
complete OAuth pair unless `anon` is selected. Basic and credentials-file OAuth pair, and identifies selected Basic or auto mode without guessing which
modes remain advanced `dev-fresh.sh` configuration. credentials runtime will accept. Basic and credentials-file modes remain
advanced `dev-fresh.sh` configuration.
<details> <details>
<summary>Advanced setup: environment variables and macOS Keychain</summary> <summary>Advanced setup: environment variables and macOS Keychain</summary>
+1 -1
View File
@@ -3557,7 +3557,7 @@ are omitted rather than framing the wrong part of the globe.
- Build gate: `npm run build` - Build gate: `npm run build`
- Network access: local-only by default (`HOST=localhost` in dev-fresh.sh); LAN is an explicit opt-in via `HOST=0.0.0.0` (launcher prints a key-exposure warning + LAN URL; see SECURITY.md) - Network access: local-only by default (`HOST=localhost` in dev-fresh.sh); LAN is an explicit opt-in via `HOST=0.0.0.0` (launcher prints a key-exposure warning + LAN URL; see SECURITY.md)
- OpenSky default mode: OAuth (`OPENSKY_AUTH_MODE=oauth`; `anon` works without credentials) - OpenSky default mode: OAuth (`OPENSKY_AUTH_MODE=oauth`; `anon` works without credentials)
- Setup doctor resolves `OPENSKY_AUTH_MODE` from the environment and dotenv files. Explicit `anon` and a missing OAuth client pair report keyless anonymous access (rate-limited); a complete OAuth pair retains the existing presence-only capability wording unless `anon` is selected. The proxy's auth behavior is unchanged. - Setup doctor resolves `OPENSKY_AUTH_MODE` from the environment and dotenv files. Explicit `anon` and OAuth mode without a client pair report keyless anonymous access (rate-limited); a complete OAuth pair retains the existing presence-only capability wording. Basic and auto modes report the selected mode without guessing which credentials runtime will accept. The proxy's auth behavior is unchanged.
- Google key expected in Keychain service `google-maps-api` (or `GOOGLE_MAPS_API_KEY`, or `.env`) - Google key expected in Keychain service `google-maps-api` (or `GOOGLE_MAPS_API_KEY`, or `.env`)
- OpenSky credentials expected in Keychain service `opensky-network` (or env, or `.env`); `OPENSKY_AUTH_MODE` and `OPENSKY_CREDENTIALS_FILE` read from `.env` too - OpenSky credentials expected in Keychain service `opensky-network` (or env, or `.env`); `OPENSKY_AUTH_MODE` and `OPENSKY_CREDENTIALS_FILE` read from `.env` too
- Optional-key precedence in `dev-fresh.sh` is uniform — explicit shell env, then `.env`, then Keychain: `OPENAI_API_KEY` (Keychain `openai-api`/`api-key` — voice + HUD summary), `AISSTREAM_API_KEY` (`aisstream-api`/`api-key` — live vessels), `CESIUM_ION_TOKEN` (`cesium-ion`/`token` — Bing stacks), `TOMTOM_API_KEY` (`tomtom-api`/`api-key` — live traffic flow), `FIRMS_MAP_KEY` (`firms-map`/`map-key` — live fires), `LL2_API_TOKEN` (`.env` only) - Optional-key precedence in `dev-fresh.sh` is uniform — explicit shell env, then `.env`, then Keychain: `OPENAI_API_KEY` (Keychain `openai-api`/`api-key` — voice + HUD summary), `AISSTREAM_API_KEY` (`aisstream-api`/`api-key` — live vessels), `CESIUM_ION_TOKEN` (`cesium-ion`/`token` — Bing stacks), `TOMTOM_API_KEY` (`tomtom-api`/`api-key` — live traffic flow), `FIRMS_MAP_KEY` (`firms-map`/`map-key` — live fires), `LL2_API_TOKEN` (`.env` only)
+14 -4
View File
@@ -151,7 +151,19 @@ export function buildCapabilitySummary(
) { ) {
const configured = (name) => credentials[name]?.configured === true; const configured = (name) => credentials[name]?.configured === true;
const hasOAuthCredentials = configured('OPENSKY_CLIENT_ID') && configured('OPENSKY_CLIENT_SECRET'); const hasOAuthCredentials = configured('OPENSKY_CLIENT_ID') && configured('OPENSKY_CLIENT_SECRET');
const anonymousOpenSkyMode = String(openSkyAuthMode || '').trim().toLowerCase() === 'anon'; const requestedOpenSkyMode = String(openSkyAuthMode || '').trim().toLowerCase();
const openSkyMode = OPENSKY_AUTH_MODES.has(requestedOpenSkyMode)
? requestedOpenSkyMode
: OPENSKY_AUTH_MODE_DEFAULT;
const flights = openSkyMode === 'anon'
? 'OpenSky keyless anonymous access (rate-limited)'
: openSkyMode === 'basic'
? 'OpenSky Basic mode selected (credential presence and validity not verified)'
: openSkyMode === 'auto'
? 'OpenSky auto mode selected (runtime credential choice and validity not verified)'
: hasOAuthCredentials
? 'OpenSky OAuth credentials present (runtime mode and validity not verified)'
: 'OpenSky keyless anonymous access (rate-limited)';
const route = selectMapStartupRoute({ const route = selectMapStartupRoute({
googleApiKey: configured('GOOGLE_MAPS_API_KEY') ? 'configured' : '', googleApiKey: configured('GOOGLE_MAPS_API_KEY') ? 'configured' : '',
cesiumToken: configured('CESIUM_ION_TOKEN') ? 'configured' : '', cesiumToken: configured('CESIUM_ION_TOKEN') ? 'configured' : '',
@@ -162,9 +174,7 @@ export function buildCapabilitySummary(
: route === 'google-ion' : route === 'google-ion'
? 'Google Photorealistic 3D Tiles through Cesium ion; Bing and world-terrain stacks available' ? 'Google Photorealistic 3D Tiles through Cesium ion; Bing and world-terrain stacks available'
: 'Esri World Imagery (keyless satellite basemap) with keyless terrain', : 'Esri World Imagery (keyless satellite basemap) with keyless terrain',
flights: hasOAuthCredentials && !anonymousOpenSkyMode flights,
? 'OpenSky OAuth credentials present (runtime mode and validity not verified)'
: 'OpenSky keyless anonymous access (rate-limited)',
voice: configured('OPENAI_API_KEY') ? 'available' : 'off until an OpenAI key is added', voice: configured('OPENAI_API_KEY') ? 'available' : 'off until an OpenAI key is added',
vessels: configured('AISSTREAM_API_KEY') ? 'live AISStream feed' : 'off until an AISStream key is added', vessels: configured('AISSTREAM_API_KEY') ? 'live AISStream feed' : 'off until an AISStream key is added',
fires: configured('FIRMS_MAP_KEY') ? 'live NASA FIRMS feed' : 'off until a FIRMS key is added', fires: configured('FIRMS_MAP_KEY') ? 'live NASA FIRMS feed' : 'off until a FIRMS key is added',
+26
View File
@@ -181,6 +181,32 @@ test('doctor retains OAuth capability wording for a complete client pair', () =>
); );
}); });
test('doctor reports Basic mode without inferring runtime auth from OAuth credentials', () => {
const oauthCredentials = {
OPENSKY_CLIENT_ID: { configured: true },
OPENSKY_CLIENT_SECRET: { configured: true },
};
for (const credentials of [{}, oauthCredentials]) {
assert.equal(
buildCapabilitySummary(credentials, { openSkyAuthMode: 'basic' }).flights,
'OpenSky Basic mode selected (credential presence and validity not verified)',
);
}
});
test('doctor reports auto mode without assuming its eventual credential choice', () => {
const oauthCredentials = {
OPENSKY_CLIENT_ID: { configured: true },
OPENSKY_CLIENT_SECRET: { configured: true },
};
for (const credentials of [{}, oauthCredentials]) {
assert.equal(
buildCapabilitySummary(credentials, { openSkyAuthMode: 'auto' }).flights,
'OpenSky auto mode selected (runtime credential choice and validity not verified)',
);
}
});
test('doctor describes the credential ladder without exposing values', () => { test('doctor describes the credential ladder without exposing values', () => {
const credentials = { const credentials = {
GOOGLE_MAPS_API_KEY: { configured: false }, GOOGLE_MAPS_API_KEY: { configured: false },