Files
Ekklesia/core/src/cli/database-transport-environment.ts
T
ekklesiaandClaude Opus 5 2b4f0afb72
CI / verify (pull_request) Successful in 42s
CI / infrastructure-smoke (pull_request) Successful in 14s
CI / migration-smoke (pull_request) Successful in 1m24s
fix: give Doctor the host configuration the runtime receives
`pnpm doctor` and `startApi` each read their own subset of the same
environment variables, and the subsets had drifted. Doctor never read
`S3_*` or module secrets at all, so a correctly configured installation
was told its object storage was "not configured" and every module
requiring a bucket or a secret was reported blocked -- while the runtime,
from the identical environment, bound those buckets and ran the modules.

Both executables now map the environment through one
`loadHostConfiguration(env)` in Core, which takes the environment as an
argument and never reads `process.env` itself. Validation stays with the
existing per-domain validators, so each caller keeps its own failure
behaviour: startup refuses a rejected value, Doctor reports it as a
sanitized code.

Doctor's storage option becomes raw input like its mail option, so a
half-configured provider is reported as a blocking configuration failure
instead of throwing before a report exists. The outbound-email check --
computed, counted toward the result, but absent from every rendered
section -- is now printed, and the rendered set is asserted against a
real report so a future check cannot go missing the same way.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-24 19:15:49 -05:00

40 lines
1.7 KiB
TypeScript

import {
assertProductionDatabaseTransport,
type DatabaseTransportEnvironment,
type DatabaseTransportPolicy,
createDatabaseTransportPolicy,
} from "../database/transport.js";
import { loadHostConfiguration } from "../host/index.js";
/**
* The database transport policy for the small Core-owned executables — `pnpm migrations:plan`,
* `pnpm migrations:apply`, `pnpm modules:enable`, and the owner-bootstrap commands — resolved from
* the process environment.
*
* The mapping itself belongs to `loadHostConfiguration`, which `startApi` and `pnpm doctor` also
* call, so `NODE_ENV` and the two TLS variables have exactly one interpretation across every entry
* point. Environment *reading* still happens here, in the executable layer: the reusable Core
* database and migration constructors keep taking explicit typed inputs and never touch
* `process.env`.
*/
export function readDatabaseTransportFromEnvironment(): {
readonly environment: DatabaseTransportEnvironment;
readonly transport: DatabaseTransportPolicy;
} {
const host = loadHostConfiguration(process.env);
const transport = createDatabaseTransportPolicy(host.databaseTransport, {
environment: host.environment,
});
return { environment: host.environment, transport };
}
/**
* Resolves the policy and asserts it is safe for the given database URL before any client, pool,
* or connection is constructed. Throws the sanitized `DatabaseTransportError` otherwise.
*/
export function resolveExecutableDatabaseTransport(databaseUrl: string): DatabaseTransportPolicy {
const { environment, transport } = readDatabaseTransportFromEnvironment();
assertProductionDatabaseTransport(databaseUrl, transport, environment);
return transport;
}