managarten/services/mana-ai/src/config.ts
Till JS f0f5b7dcf6 fix(infra): relocate mana-ai from 3066 to 3067 — port clash with news-ingester
news-ingester already owns 3066 (see docker-compose.macmini.yml:1620).
Moving mana-ai to 3067 — the next free slot in the 306x services block
(credits 3061, user 3062, subscriptions 3063, analytics 3064,
events 3065, news-ingester 3066, mana-ai 3067).

Updated: Dockerfile EXPOSE + HEALTHCHECK, config.ts default,
compose service/healthcheck/port mapping, webapp getManaAiUrl()
fallback, root CLAUDE.md service list, mana-ai/CLAUDE.md, and
COMPANION_BRAIN_ARCHITECTURE.md §20 file map.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 14:32:07 +02:00

57 lines
2.1 KiB
TypeScript

/**
* Env-driven config for the mana-ai service.
*
* Only references the secrets/URLs the tick loop needs. Auth is
* service-to-service via MANA_SERVICE_KEY (same pattern as mana-credits,
* mana-user); no end-user JWTs reach this service.
*/
export interface Config {
port: number;
/** mana_sync DB — source of Mission rows (via sync_changes replay). */
syncDatabaseUrl: string;
/** mana-llm HTTP endpoint (OpenAI-compatible). */
manaLlmUrl: string;
/** Shared key for service-to-service calls. */
serviceKey: string;
/** How often the background tick scans for due Missions, in ms. */
tickIntervalMs: number;
/** Flip to false to boot the HTTP surface without the background tick
* — useful for local smoke-tests + Docker image build verification. */
tickEnabled: boolean;
/**
* PEM-encoded RSA-OAEP-2048 private key for unwrapping Mission Grants.
* Paired with the public key pinned in mana-auth's config. Provision
* via Docker secret / out-of-band env; never commit.
*
* Optional at boot so the service can start without grant support
* (development, legacy deployments). When absent, Missions that
* carry a Grant are skipped with state='grant-missing'.
*
* Generate with:
* openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out priv.pem
* openssl pkey -in priv.pem -pubout -out pub.pem
*/
missionGrantPrivateKeyPem?: string;
}
function requireEnv(key: string, fallback?: string): string {
const value = process.env[key] ?? fallback;
if (!value) throw new Error(`Missing required env var: ${key}`);
return value;
}
export function loadConfig(): Config {
return {
port: parseInt(process.env.PORT ?? '3067', 10),
syncDatabaseUrl: requireEnv(
'SYNC_DATABASE_URL',
'postgresql://mana:devpassword@localhost:5432/mana_sync'
),
manaLlmUrl: requireEnv('MANA_LLM_URL', 'http://localhost:3020'),
serviceKey: requireEnv('MANA_SERVICE_KEY', 'dev-service-key'),
tickIntervalMs: parseInt(process.env.TICK_INTERVAL_MS ?? '60000', 10),
tickEnabled: process.env.TICK_ENABLED !== 'false',
missionGrantPrivateKeyPem: process.env.MANA_AI_PRIVATE_KEY_PEM || undefined,
};
}