← back to Filemaker Mcp
lib/george-auth.js
41 lines
// Resolve the George (Gmail agent, :9850) basic-auth credential from the SAME
// canonical fleet source George itself reads, so a rotation there propagates
// here automatically instead of silently breaking this pipeline.
//
// History: before 2026-07-13 these callers hardcoded an empty password
// ('admin:'). On 2026-07-13 the fleet cred was rotated to a real 32-char pass
// AND George was hardened to fail-closed on empty/invalid creds. The empty
// password started returning 401, which made bin/shopify-sync.js throw
// 'George search failed: 401' at its first step — freezing the Shopify→FileMaker
// order sync at order #32600 (see data/sync.out.log FATAL loop). This resolver
// prevents a recurrence: it always tracks the live fleet cred.
//
// Priority: GEORGE_BASIC_AUTH env → fleet DW-MCP/.env → local filemaker-mcp/.env.
import { readFileSync } from 'node:fs';
import { join } from 'node:path';
function fromEnvFile(path, key) {
try {
const m = readFileSync(path, 'utf8').match(new RegExp('^' + key + '=(.+)$', 'm'));
return m ? m[1].trim() : '';
} catch {
return '';
}
}
export function georgeCred() {
const HOME = process.env.HOME || '';
return (
process.env.GEORGE_BASIC_AUTH ||
fromEnvFile(join(HOME, 'Projects/Designer-Wallcoverings/DW-MCP/.env'), 'GEORGE_BASIC_AUTH') ||
fromEnvFile(join(HOME, 'Projects/filemaker-mcp/.env'), 'GEORGE_BASIC_AUTH') ||
'admin:' // legacy fallback — now rejected by George, so it 401s loudly rather than silently
);
}
export function georgeAuthHeader() {
return 'Basic ' + Buffer.from(georgeCred()).toString('base64');
}
export const GEORGE_URL = process.env.GEORGE_URL || 'http://127.0.0.1:9850';