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]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
a835215eb8
commit
2b4f0afb72
@@ -4,35 +4,28 @@ import {
|
||||
type DatabaseTransportPolicy,
|
||||
createDatabaseTransportPolicy,
|
||||
} from "../database/transport.js";
|
||||
import { loadHostConfiguration } from "../host/index.js";
|
||||
|
||||
/**
|
||||
* The one place every Core-owned executable reads its database transport policy from the process
|
||||
* environment, so `pnpm doctor`, `pnpm migrations:plan`, `pnpm migrations:apply`, and
|
||||
* `pnpm authorization:bootstrap-owner` cannot drift from each other or from `apps/api`.
|
||||
* 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.
|
||||
*
|
||||
* Environment reading lives here, in the executable layer, deliberately: the reusable Core
|
||||
* database/migration constructors keep taking explicit typed inputs and never touch `process.env`.
|
||||
* `NODE_ENV` is interpreted exactly as `apps/api` interprets it — only the literal string
|
||||
* `"development"` relaxes anything, so an unset or misspelled value validates as production.
|
||||
* 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 environment: DatabaseTransportEnvironment =
|
||||
process.env.NODE_ENV === "development" ? "development" : "production";
|
||||
const transport = createDatabaseTransportPolicy(
|
||||
{
|
||||
...(process.env.EKKLESIA_DATABASE_CA === undefined
|
||||
? {}
|
||||
: { certificateAuthority: process.env.EKKLESIA_DATABASE_CA }),
|
||||
...(process.env.EKKLESIA_DATABASE_TLS_MODE === undefined
|
||||
? {}
|
||||
: { mode: process.env.EKKLESIA_DATABASE_TLS_MODE }),
|
||||
},
|
||||
{ environment },
|
||||
);
|
||||
return { environment, transport };
|
||||
const host = loadHostConfiguration(process.env);
|
||||
const transport = createDatabaseTransportPolicy(host.databaseTransport, {
|
||||
environment: host.environment,
|
||||
});
|
||||
return { environment: host.environment, transport };
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user