X/Twitter (live posting gated on an X developer app, registered separately):
- schema: add 'twitter' to OutletSchema (sanitize 280-char limit already present).
- packages/twitter-client: X API v2 client (POST /2/tweets, OAuth2 user Bearer),
injectable fetch, 280-char guard; 4 contract tests.
- apps/scheduler/src/dispatch.ts: makeOutletDispatcher routes by outlet
(linkedin.* -> linkedin, twitter -> twitter), fail-closed for unconfigured
outlets; 4 tests. main.ts wires both outlets fail-closed until creds exist.
Monorepo fix: add a local tsconfig.json (extends root, include src) to each
package + non-admin app. Without it, every package's `tsc --noEmit` compiled the
WHOLE repo via the root config (no JSX/DOM) and choked on the admin .tsx — masked
until now by turbo build caching.
Tests: 135 passing + 13 gated across 12 tasks.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- packages/schema/src/client.ts: createDb(url) -> { db, sql } drizzle/postgres-js
factory. Exposed as the ./client subpath export so the node-only driver never
leaks into client bundles.
- packages/schema/src/db.integration.test.ts: 6 tests gated behind INTEGRATION=1
(content insert/read, vault_path UNIQUE, idempotency_key UNIQUE no-double-post,
content_id FK, audit append, kill-switch upsert). Verified against Postgres 17.
- Default CI suite unchanged: integration tests skip without INTEGRATION.
Closes the Stage 2.1 DoD against a live database (unblocked by Gate 0.8).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>