morphit/apps/web/scripts/2fa-recommended-apps-coverage-smoke.ts

144 lines
4.7 KiB
TypeScript

#!/usr/bin/env tsx
/**
* Smoke: TOTP-2FA recommended-apps i18n coverage across all 10
* locales.
*
* For every app in RECOMMENDED_AUTHENTICATOR_APPS, every locale
* MUST carry a `settings.totp.recommended_apps.<i18nKey>.tagline`
* string. Same invariant for NOT_RECOMMENDED. Missing or
* empty strings fail the smoke. Also verifies that the
* `officialUrl` and `sourceUrl` fields are HTTPS, non-empty,
* and not `localhost`.
*
* Tamper: adding a new app to RECOMMENDED_AUTHENTICATOR_APPS
* without adding its i18n strings → fails. Setting an app's
* `officialUrl` to `http://localhost:8080` → fails.
*/
import { readFileSync, readdirSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const REPO_ROOT = join(__dirname, '..', '..', '..');
const RECOMMENDED_APPS_TS = readFileSync(
join(REPO_ROOT, 'apps/web/src/lib/auth/recommendedAuthenticatorApps.ts'),
'utf8'
);
const LOCALES_DIR = join(REPO_ROOT, 'apps/web/src/lib/i18n/locales');
const LOCALE_FILES = readdirSync(LOCALES_DIR)
.filter((f) => f.endsWith('.json'))
.sort();
interface AppRow {
readonly name: string;
readonly i18nKey: string;
readonly officialUrl: string;
readonly sourceUrl: string;
}
function parseAppsBlock(arrayName: string): AppRow[] {
const startIdx = RECOMMENDED_APPS_TS.indexOf(arrayName);
if (startIdx < 0) {
throw new Error(`Could not locate ${arrayName}`);
}
const arrOpen = RECOMMENDED_APPS_TS.indexOf('[', startIdx);
const endIdx = RECOMMENDED_APPS_TS.indexOf('];', arrOpen);
if (arrOpen < 0 || endIdx < 0) {
throw new Error(`Malformed ${arrayName} array`);
}
const body = RECOMMENDED_APPS_TS.slice(arrOpen + 1, endIdx);
const rows: AppRow[] = [];
// Brace-depth walk to split top-level entries.
let depth = 0;
let entryStart = -1;
for (let i = 0; i < body.length; i++) {
const ch = body[i];
if (ch === '{') {
if (depth === 0) entryStart = i;
depth += 1;
} else if (ch === '}') {
depth -= 1;
if (depth === 0 && entryStart >= 0) {
const entry = body.slice(entryStart, i + 1);
const name = entry.match(/name:\s*'([^']+)'/)?.[1] ?? '';
const i18nKey = entry.match(/i18nKey:\s*'([^']+)'/)?.[1] ?? '';
const officialUrl = entry.match(/officialUrl:\s*'([^']+)'/)?.[1] ?? '';
const sourceUrl = entry.match(/sourceUrl:\s*'([^']+)'/)?.[1] ?? '';
if (name && i18nKey) {
rows.push({ name, i18nKey, officialUrl, sourceUrl });
}
entryStart = -1;
}
}
}
return rows;
}
let failures = 0;
let passes = 0;
function expect(label: string, cond: boolean): void {
if (cond) {
passes += 1;
} else {
failures += 1;
console.error(`${label}`);
}
}
console.log('2fa-recommended-apps-coverage-smoke\n');
const recommended = parseAppsBlock('RECOMMENDED_AUTHENTICATOR_APPS');
const notRecommended = parseAppsBlock('NOT_RECOMMENDED_AUTHENTICATOR_APPS');
console.log(`recommended apps: ${recommended.length}`);
console.log(`not-recommended apps: ${notRecommended.length}`);
// URL hygiene
console.log('\nURL hygiene:');
for (const app of recommended) {
expect(`${app.name}: officialUrl is https://`, app.officialUrl.startsWith('https://'));
expect(`${app.name}: officialUrl is not localhost`, !app.officialUrl.includes('localhost'));
expect(`${app.name}: sourceUrl is https://`, app.sourceUrl.startsWith('https://'));
expect(`${app.name}: sourceUrl is not localhost`, !app.sourceUrl.includes('localhost'));
}
// i18n coverage
console.log('\ni18n coverage:');
for (const localeFile of LOCALE_FILES) {
const d = JSON.parse(readFileSync(join(LOCALES_DIR, localeFile), 'utf8'));
const totp = d?.settings?.totp;
if (!totp) {
failures += 1;
console.error(`${localeFile} is missing settings.totp tree`);
continue;
}
const recTree = totp.recommended_apps ?? {};
const notRecTree = totp.not_recommended_apps ?? {};
for (const app of recommended) {
const tagline = recTree?.[app.i18nKey]?.tagline;
expect(
`${localeFile}: settings.totp.recommended_apps.${app.i18nKey}.tagline exists and is non-empty`,
typeof tagline === 'string' && tagline.length > 0
);
}
for (const app of notRecommended) {
const sub = notRecTree?.[app.i18nKey];
expect(
`${localeFile}: settings.totp.not_recommended_apps.${app.i18nKey}.name exists`,
typeof sub?.name === 'string' && sub.name.length > 0
);
expect(
`${localeFile}: settings.totp.not_recommended_apps.${app.i18nKey}.reason exists`,
typeof sub?.reason === 'string' && sub.reason.length > 0
);
}
}
console.log(`\n${passes} passed, ${failures} failed`);
if (failures > 0) process.exit(1);
console.log(`✓ all ${passes} 2fa-recommended-apps-coverage-smoke scenarios passed`);