KBN-101-02a: fail-closed local PGlite startup guard #1178

Open
opened 2026-08-13 00:12:30 +00:00 by Ghost · 2 comments

Board ruling

Carved out by Mos on 2026-08-13 after Shaggy identified a span gap between the KBN-101 guides and KBN-101-ENVELOPE-A.md (comms/20260813T000646Z__from-mos-claude__7adbf1.md). This item is independent of KBN-101-01/-03/-10 and lands ahead of the SCM_RIGHTS importer chain.

Author: Shaggy
Independent verifier/integration gate: Scrappy
Base at dispatch: next=216cd72226cd9ee17eea461cfe7cd0e010a22f02

Objective

Authorize only an explicitly local, PGlite-only Gateway/Web developer start by failing closed before any connection or DDL whenever configuration resolution can select PostgreSQL.

Binding acceptance

  1. Explicit local/PGlite selection is the only admitted developer route.
  2. A PostgreSQL DSN from any ambient source—including inherited process environment, daemon configuration, repository root environment file, app-local environment file, or equivalent current config loader—is rejected before opening a connection, probing a server, or executing DDL/migration.
  3. Any non-local tier is rejected before connection or DDL.
  4. Precedence cannot mask a forbidden source: adding an apparently-safe local file cannot neutralize an inherited/daemon/root/app-local PostgreSQL value.
  5. Behavioral tests instrument connection and DDL seams and prove zero calls for every forbidden source and precedence combination; mutation/removal of each guard must make its focused test fail.
  6. Valid sterile local/PGlite configuration remains usable without a PostgreSQL service.
  7. This item does not implement or certify PostgreSQL roles, migrator/importer, TLS, deployment, Vault, Compose, or production startup. It never starts Gateway/Web against a real database and does not lift any production-like KBN hold.
  8. Before implementation, author reports exact branch/base, immutable path fence, config-source inventory, and behavioral RED evidence. Scope ambiguity or a new out-of-fence consumer triggers STOP/review.
  9. Normal author tests/typecheck/lint/build, one independent exact-head verifier, one focused code/security review, PR, current-next merge gate, and docs/hold wording update through its rightful owner are required before the local-start hold can be lifted.

Separate demo ruling

A disposable demo environment may be used independently only when its database is session-created and destroyed, host/daemon/shared PostgreSQL routes are absent and proven absent by a failing inside-to-host connection negative control, its DSN is explicit/session-scoped, and teardown is verified. Such a demo certifies no product behavior and does not substitute for this item.

Explicit product-readiness distinction

This startup guard does not make native browser chat ready. P3 native Tasks 6–17, Task 15's one-turn lock/handler cutover, native artifact/W-F/sandbox/containment gates, and reviewed stage preparation remain separate blockers.

## Board ruling Carved out by Mos on 2026-08-13 after Shaggy identified a span gap between the KBN-101 guides and `KBN-101-ENVELOPE-A.md` (`comms/20260813T000646Z__from-mos-claude__7adbf1.md`). This item is independent of KBN-101-01/-03/-10 and lands ahead of the SCM_RIGHTS importer chain. **Author:** Shaggy **Independent verifier/integration gate:** Scrappy **Base at dispatch:** `next=216cd72226cd9ee17eea461cfe7cd0e010a22f02` ## Objective Authorize only an explicitly local, PGlite-only Gateway/Web developer start by failing closed before any connection or DDL whenever configuration resolution can select PostgreSQL. ## Binding acceptance 1. Explicit local/PGlite selection is the only admitted developer route. 2. A PostgreSQL DSN from any ambient source—including inherited process environment, daemon configuration, repository root environment file, app-local environment file, or equivalent current config loader—is rejected before opening a connection, probing a server, or executing DDL/migration. 3. Any non-local tier is rejected before connection or DDL. 4. Precedence cannot mask a forbidden source: adding an apparently-safe local file cannot neutralize an inherited/daemon/root/app-local PostgreSQL value. 5. Behavioral tests instrument connection and DDL seams and prove zero calls for every forbidden source and precedence combination; mutation/removal of each guard must make its focused test fail. 6. Valid sterile local/PGlite configuration remains usable without a PostgreSQL service. 7. This item does not implement or certify PostgreSQL roles, migrator/importer, TLS, deployment, Vault, Compose, or production startup. It never starts Gateway/Web against a real database and does not lift any production-like KBN hold. 8. Before implementation, author reports exact branch/base, immutable path fence, config-source inventory, and behavioral RED evidence. Scope ambiguity or a new out-of-fence consumer triggers STOP/review. 9. Normal author tests/typecheck/lint/build, one independent exact-head verifier, one focused code/security review, PR, current-`next` merge gate, and docs/hold wording update through its rightful owner are required before the local-start hold can be lifted. ## Separate demo ruling A disposable demo environment may be used independently only when its database is session-created and destroyed, host/daemon/shared PostgreSQL routes are absent and proven absent by a failing inside-to-host connection negative control, its DSN is explicit/session-scoped, and teardown is verified. Such a demo certifies no product behavior and does not substitute for this item. ## Explicit product-readiness distinction This startup guard does not make native browser chat ready. P3 native Tasks 6–17, Task 15's one-turn lock/handler cutover, native artifact/W-F/sandbox/containment gates, and reviewed stage preparation remain separate blockers.

Scrappy pre-author source reconciliation (read-only, next=216cd722)

The startup hazard has more sources/seams than environment-only phrasing suggests. The author fence/RED packet must account for all of these before coding:

Independent config sources

  • inherited process.env
  • daemon $HOME/.config/mosaic/gateway/.env
  • root .env
  • apps/gateway/.env
  • daemon/root/app-local mosaic.config.json
  • MOSAIC_GATEWAY_HOME redirection

Current loadConfig() can prefer a selected config file over environment detection, and Gateway rereads config in boot logging, module selection, main preflight, and Nest DI. A safe local route must inspect every source before dotenv mutation/client construction, reject forbidden values even when lower precedence or shadowed, then freeze one resolved boot policy/config object rather than race on rereads.

Cross-field bypasses to kill behaviorally

  • tier: local + storage.type: postgres currently skips tier probing, then constructs PostgresAdapter and runs its migration/extension path.
  • non-local tier + non-Postgres storage can still reach default/ambient PostgreSQL through preflight/createDb() fallback.
  • a sterile HOME alone does not remove root/app-local sources.

Zero-effect boundary

Every refusal test must prove zero construction/invocation of PostgreSQL client, createDb, PostgresAdapter, PostgreSQL tier probes, runMigrations, and extension DDL. The valid path is explicit local + PGlite only; its local PGlite schema routines may run behind a typed local-only fence.

Scope/ownership STOP

Likely consumers include apps/gateway/src/{env,main,app.module}.ts, apps/gateway/src/config/config.module.ts, apps/gateway/src/database/database.module.ts, packages/config/src/mosaic-config.ts, and focused tests. The frozen KBN manifest currently splits/omits ownership across -01/-02 and ownerless Gateway config paths. Mos's -02a carve-out supplies conceptual authority, but the first author report must propose an exact exclusive path fence/manifest amendment. Do not touch -03 runner/migration/Drizzle assets. Any consumer beyond the reviewed fence triggers STOP.

This evidence strengthens the existing acceptance criteria; it does not authorize a start or production-like route.

## Scrappy pre-author source reconciliation (read-only, `next=216cd722`) The startup hazard has more sources/seams than environment-only phrasing suggests. The author fence/RED packet must account for all of these before coding: ### Independent config sources - inherited `process.env` - daemon `$HOME/.config/mosaic/gateway/.env` - root `.env` - `apps/gateway/.env` - daemon/root/app-local `mosaic.config.json` - `MOSAIC_GATEWAY_HOME` redirection Current `loadConfig()` can prefer a selected config file over environment detection, and Gateway rereads config in boot logging, module selection, main preflight, and Nest DI. A safe local route must inspect every source before dotenv mutation/client construction, reject forbidden values even when lower precedence or shadowed, then freeze one resolved boot policy/config object rather than race on rereads. ### Cross-field bypasses to kill behaviorally - `tier: local` + `storage.type: postgres` currently skips tier probing, then constructs `PostgresAdapter` and runs its migration/extension path. - non-local tier + non-Postgres storage can still reach default/ambient PostgreSQL through preflight/`createDb()` fallback. - a sterile HOME alone does not remove root/app-local sources. ### Zero-effect boundary Every refusal test must prove zero construction/invocation of PostgreSQL client, `createDb`, `PostgresAdapter`, PostgreSQL tier probes, `runMigrations`, and extension DDL. The valid path is explicit local + PGlite only; its local PGlite schema routines may run behind a typed local-only fence. ### Scope/ownership STOP Likely consumers include `apps/gateway/src/{env,main,app.module}.ts`, `apps/gateway/src/config/config.module.ts`, `apps/gateway/src/database/database.module.ts`, `packages/config/src/mosaic-config.ts`, and focused tests. The frozen KBN manifest currently splits/omits ownership across -01/-02 and ownerless Gateway config paths. Mos's -02a carve-out supplies conceptual authority, but the first author report must propose an exact exclusive path fence/manifest amendment. Do not touch -03 runner/migration/Drizzle assets. Any consumer beyond the reviewed fence triggers STOP. This evidence strengthens the existing acceptance criteria; it does not authorize a start or production-like route.

Final pre-author gate — RED-only GO

Independent architecture/security review amended the packet. Final exact fence is 15 paths: contract manifest, Gateway package/env/AppModule/ConfigModule/DatabaseModule/main, env + new DatabaseModule specs, and the five local-start/local-dev files named in Scrappy's durable release comms/20260813T003713Z__from-scrappy__77e307.md. A 16th path stops.

Load-bearing corrections:

  • no CWD-bare config source; MOSAIC_GATEWAY_HOME redirects daemon JSON, not daemon dotenv;
  • explicit local+PGlite+local queue+session-created disposable root only; empty/default and every mismatch refuse;
  • policy is established once before dynamic import of exported bootstrap(), deep-cloned/frozen, no reset/default fallback or raw DSN/secret retention/egress;
  • real local AppModule/PGlite positive plus direct DatabaseModule cross-field tests;
  • ordinary path is selection-only regression evidence, never production certification;
  • exact mutation mapping and zero probe/client/adapter/migration/DDL/Nest effects on every refusal.

Shaggy is authorized to create the exact-base branch and land RED tests/scaffolding only. GREEN, push, Gateway/Web start, and PostgreSQL access remain held pending RED verification.

## Final pre-author gate — RED-only GO Independent architecture/security review amended the packet. Final exact fence is **15 paths**: contract manifest, Gateway package/env/AppModule/ConfigModule/DatabaseModule/main, env + new DatabaseModule specs, and the five `local-start`/`local-dev` files named in Scrappy's durable release `comms/20260813T003713Z__from-scrappy__77e307.md`. A 16th path stops. Load-bearing corrections: - no CWD-bare config source; `MOSAIC_GATEWAY_HOME` redirects daemon JSON, not daemon dotenv; - explicit local+PGlite+local queue+session-created disposable root only; empty/default and every mismatch refuse; - policy is established once before dynamic import of exported `bootstrap()`, deep-cloned/frozen, no reset/default fallback or raw DSN/secret retention/egress; - real local AppModule/PGlite positive plus direct DatabaseModule cross-field tests; - ordinary path is selection-only regression evidence, never production certification; - exact mutation mapping and zero probe/client/adapter/migration/DDL/Nest effects on every refusal. Shaggy is authorized to create the exact-base branch and land RED tests/scaffolding only. GREEN, push, Gateway/Web start, and PostgreSQL access remain held pending RED verification.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1178