feat(environment): add opt-in module, settings surface, API, and nightly fetch

Add the opt-in Environment module (default off), its Settings surface (home
location search, travel overrides, backfill, with Open-Meteo attribution), the
gated API routes (overview, home, geocode, travel CRUD, backfill), the nightly
pg-boss fetch job with a lookback window plus on-demand backfill, the query
keys, six-locale strings, and the regenerated OpenAPI. The module performs an
outbound weather fetch tied to a coarse location, so it ships dark and the user
turns it on deliberately; off means no job, no row, no egress.
This commit is contained in:
Marc-André Bombeck committed 2026-06-28 16:58:52 +02:00
1 parent cdee3e3efc
commit 088cad6c64
30 files changed
+1537 -2

No files matched your search

+7 -2
View File
@@ -352,10 +352,15 @@ describe("resolveModuleEnabled — mcp module (opt-in, default-OFF)", () => {
});
describe("registry — opt-in marker", () => {
it("marks only the mcp module opt-in (every other module is default-on)", () => {
it("marks the mcp + environment modules opt-in (every other module is default-on)", () => {
expect(isOptInModule("mcp")).toBe(true);
// v1.25 (W-ENV) — the environmental-context module is opt-in too: it
// performs an outbound weather fetch tied to a coarse location, so it ships
// dark like the remote MCP endpoint.
expect(isOptInModule("environment")).toBe(true);
const optIn = new Set(["mcp", "environment"]);
for (const key of MODULE_KEYS) {
if (key === "mcp") continue;
if (optIn.has(key)) continue;
expect(isOptInModule(key)).toBe(false);
}
});
+17
View File
@@ -115,6 +115,12 @@ export const MODULE_KEYS = [
// re-enabling finds the rows intact.
"medications",
"doctorReport",
// v1.25.0 (W-ENV) — environmental-context module. Like `mcp`, it is OPT-IN
// (off by default): it performs an outbound weather fetch tied to where the
// user physically is (a coarse home / travel location), so opt-in is the
// right privacy default. With it off no job runs, no row is written, and no
// egress happens. The `optIn` marker inverts the per-user default.
"environment",
// v1.22.0 — the remote Model Context Protocol endpoint (`/mcp`). Unlike
// every other module this is OPT-IN (off by default): it exposes a new
// external-assistant attack surface, so it ships dark and the operator /
@@ -256,6 +262,17 @@ export const MODULE_REGISTRY: Readonly<Record<ModuleKey, ModuleDefinition>> =
descriptionKey: "modules.doctorReport.description",
category: "export",
},
environment: {
key: "environment",
labelKey: "modules.environment.label",
descriptionKey: "modules.environment.description",
category: "device",
// Off by default: performs an outbound weather fetch tied to a coarse
// location, so it ships dark and the user turns it on deliberately. The
// home location + travel overrides + backfill live on the dedicated
// Environment settings surface (rendered when the module is on).
optIn: true,
},
mcp: {
key: "mcp",
labelKey: "modules.mcp.label",