- packages/config: add src/startup.ts exposing assertValidConfig (builds on
the T01 TypeBox/Ajv schema) and the field-specific startup errors
(MissingRequiredSettingError names the missing field; ConfigStartupError
names each violating field); re-export from the package boundary
- apps/server: validate the startup configuration (including the required
EPPP_SESSION_SECRET) before the server binds, so a missing required
setting crashes the process at startup naming the field; depends on
@personal-blog/config
- compose.yaml: provide EPPP_SESSION_SECRET for the app service (dev-only
>= 32 char default; override via .env / shell)
- Dockerfile: ship the compiled packages/config in the image (build source +
runtime dist), matching the server's new workspace dependency
- pnpm-lock.yaml: apps/server importer gains @personal-blog/config
Adds packages/config (@personal-blog/config) — the EPPP configuration
service foundation. The package defines the configuration schema with
TypeBox (configSchema: host, port, databaseUrl, sessionSecret — the
validated config fields, golden-tuple pins @sinclair/typebox@0.34.52 and
ajv@8.20.0) and compiles it with Ajv (validateConfig). The environment
adapter (T04), field-specific startup errors (T02) and secret redaction
(T03) build on this boundary in later tasks; nothing reads process.env yet.
Wiring for the new workspace package: lockfile importer + resolved
typebox/ajv tree, apps/server/Dockerfile manifest copy (frozen in-image
install must match the lockfile importers), config-schema CI job, package
set fixtures (workspace-layout, workspace-config, strict-tsconfig,
typescript-pin), probe-file gitignore entry.
Review finding on PR #391: packages/database-postgres pinned pg@8.23.0 and
kysely@0.29.5, but the architecture doc's golden tuple (Technology-Stack
section 5.2 / section 7) pins pg@8.22.0 and Kysely@0.29.4. Reproducibility
requires the exact documented versions.
- packages/database-postgres/package.json: pg 8.23.0 -> 8.22.0,
kysely 0.29.5 -> 0.29.4, @types/pg 8.23.1 -> 8.21.0 (no 8.22.x of
@types/pg is published; 8.21.0 is the closest matching release, types
for the immediately preceding pg minor)
- pnpm-lock.yaml: regenerated with pnpm 11.23.0 (Node 24); the resolved
pg dependency tree is unchanged apart from the driver version itself
- tests/database-postgres-imports.test.mjs: exact-pin assertions updated
to the corrected versions, with a comment noting the @types/pg choice
- packages/database-postgres (@personal-blog/database-postgres): the single
workspace package allowed to import the PostgreSQL driver — declares pg and
kysely as exact dependencies (@types/pg for types) and its src/index.ts
imports and re-exports the driver pieces (Pool, Kysely, PostgresDialect) so
the isolation is real, not a placeholder
- pnpm-lock.yaml: importer for packages/database-postgres plus the resolved
pg/kysely dependency tree (frozen-lockfile install keeps working)
- .gitea/workflows/ci.yml: new database-postgres-imports job runs
tests/database-postgres-imports.test.mjs on every PR so the isolation
criterion gates merges
Adds root scripts so build, test and typecheck run from the workspace root:
- root package.json gains scripts: build (pnpm -r run build), test
(node --test on tests/**/*.test.mjs), typecheck (pnpm -r run typecheck)
- every workspace package (apps/server, packages/core,
extensions/example) gains build (tsc -p tsconfig.json) and typecheck
(tsc -p tsconfig.json --noEmit) scripts
- typescript 6.0.3 pinned as an exact root devDependency so the commands
run from a clean checkout; lockfile regenerated with pnpm 11.23.0
Verified from a clean state: pnpm install --frozen-lockfile passes,
pnpm build emits dist for all 3 packages, pnpm typecheck passes for all 3,
pnpm test runs tests/architecture-import.test.mjs 10/10 green, and CI's
pnpm -r list --depth -1 still lists all 4 workspace projects.
Closes#158