Home
# Build System Audit for Syntax Method v2 (synt-mx)
## Scope
Audited repositories:
- `ddh-core`
- `daily-devhabit-cli`
- `ddh-notion-bridge`
Goal:
- Prepare a local-first `synt-mx` fork of `ddh-core`
- Reduce architectural coupling and context-switching friction
- Define a migration checklist for Repository Pattern and DB provider decoupling
---
## Deep-Rooted Dependencies
### ddh-core
- Data driver lock-in to `pg` at repository and bootstrap layers.
- Postgres-specific schema choices (`SERIAL`, `TEXT[]`, `JSONB`) in setup/migrations.
- Embedded CLI logic inside core repo introduces mixed responsibilities.
- Docker/Postgres runtime assumptions leak into defaults and docs.
### daily-devhabit-cli
- Runtime dependency on a single default cloud endpoint.
- Token and output path assumptions embedded directly in command logic.
- Scope vocabulary drift risk vs server-side validation if not centrally shared.
### ddh-notion-bridge
- Tight coupling to strict Notion property names and types.
- PostgreSQL dependency for source log retrieval.
- Hardcoded sync user selection in runner script.
- Environment key inconsistency (`NOTION_KEY` vs `NOTION_TOKEN`) adds setup ambiguity.
---
## Context-Switching Friction
- Two CLI surfaces with overlapping purpose (`ddh-core/src/cli` and standalone `daily-devhabit-cli`) can blur source-of-truth boundaries.
- Scope enum and payload shape can drift across client/server/bridge unless extracted into shared contracts.
- Config conventions differ per repo, increasing onboarding and debug time.
- Notion schema updates require coordinated edits in multiple files and services.
- Local-vs-cloud execution assumptions are mixed into business flows rather than isolated at config boundaries.
---
## Hardcoded Debt to Move into config.ts
### ddh-core
- API host binding and listen address.
- Swagger server URLs (`localhost:3000`, `localhost:3005`).
- DB fallback host/port/user/pass defaults.
- Notion sync timeout behavior and retry policy constants.
- Default API URL in embedded CLI flow.
### daily-devhabit-cli
- Default cloud API URL.
- Offline output filename and path policy.
- Export filename format and output root assumptions.
### ddh-notion-bridge
- DB fallback host/port/user/pass defaults.
- Hardcoded `USER_ID` and sync limits in `run-sync`.
- Token key fallback behavior for Notion auth.
---
## The Axial Refactor
### Replacing Axios with Native Fetch for Security Hardening
What changed:
- Removed Axios imports and dependency references from core CLI and standalone CLI paths.
- Replaced `axios.get/post` with explicit `fetch` calls.
- Introduced explicit request method, JSON content headers, and payload serialization.
- Normalized response handling to parse body and throw on non-2xx responses.
- Added network + HTTP error mapping so caller `try/catch` remains reliable.
Why this matters:
- Reduces supply-chain risk from third-party HTTP client vulnerabilities.
- Makes request/response behavior explicit and auditable.
- Ensures `401/500` are surfaced as thrown errors (not silent success paths).
- Preserves offline fallback and auth error branching with cleaner control flow.
Security and reliability checklist:
- [x] Explicit `method` per request.
- [x] `Content-Type: application/json` for JSON requests.
- [x] Authorization header consistently shaped as `Bearer <token>`.
- [x] Payloads wrapped with `JSON.stringify`.
- [x] Response body parsed and non-OK status triggers throw.
- [x] Network exceptions captured in `try/catch` and mapped for fallback logic.
---
## Repository Pattern Checklist for synt-mx Scaffold
### Phase 1: Contracts First (No DB Rewrite Yet)
- [ ] Create domain ports:
- [ ] `UserRepositoryPort`
- [ ] `EntryRepositoryPort`
- [ ] Optional `UnitOfWorkPort` / `TransactionPort`
- [ ] Update services to depend only on ports (interfaces), not concrete repositories.
- [ ] Move all SQL out of service/controller layers.
### Phase 2: Infrastructure Split
- [ ] Move existing `pg` repositories to `infrastructure/postgres/*`.
- [ ] Add `infrastructure/sqlite/*` implementations using `better-sqlite3`.
- [ ] Introduce `DatabaseClient` abstraction (query, execute, transaction helpers).
- [ ] Add DB provider selector in `config.ts` (`db.provider = sqlite | postgres`).
### Phase 3: Schema and Migration Compatibility
- [ ] Convert Postgres DDL to SQLite-compatible DDL:
- [ ] `SERIAL` -> `INTEGER PRIMARY KEY AUTOINCREMENT`
- [ ] `TEXT[]` -> `TEXT` (JSON-stringified array)
- [ ] `JSONB` -> `TEXT` (JSON-stringified object)
- [ ] Enable SQLite safety defaults (`foreign_keys`, `journal_mode=WAL`).
- [ ] Add migration runner that supports both providers.
### Phase 4: Composition Root
- [ ] Build `createRepositories(config)` factory to wire provider-specific repositories.
- [ ] Keep controller and route wiring unchanged except dependency injection source.
- [ ] Add startup validation for required config and storage paths.
### Phase 5: Test Strategy
- [ ] Define provider-agnostic repository behavior tests.
- [ ] Run same test suite against both providers.
- [ ] Add golden tests for payload normalization and auth/fallback behavior.
### Phase 6: Cutover Plan
- [ ] Default `synt-mx` to SQLite local file (Tier 0).
- [ ] Keep Postgres provider optional for Tier 1/hosted use.
- [ ] Add export/import path for backup and portability.
---
## EmDash Integration Guidance
### synt-mx as a Content Source for Astro/EmDash
Design principles:
- Stable, versioned read APIs.
- Cursor-based incremental sync.
- Strong provenance metadata for every item.
- Deterministic IDs and timestamps for idempotent ingestion.
Recommended API surface:
- `GET /v1/content/collections`
- `GET /v1/content/:collection?updated_since=&cursor=&limit=`
- `GET /v1/content/:collection/:id`
- `GET /v1/schema/collections`
- `GET /v1/events?cursor=&since=`
- `GET /v1/health`
- `GET /v1/version`
Minimum record fields:
- `id`, `source`, `source_id`, `origin`, `project`, `tags`
- `content_plain`, `content_structured`
- `status`, `created_at`, `updated_at`, `hash`
Initial collections to expose:
- `engineering_logs`
- `journal_logs`
- `synthesized_briefs`
Integration priority:
1. Implement read-only content endpoints first.
2. Add event feed for incremental pull into EmDash.
3. Add optional webhook push once contracts stabilize.
---
## Priority Actions
1. Centralize runtime constants in `config.ts` across all three audited repos.
2. Extract shared schema/types package for scope enums and payload contracts.
3. Remove or clearly scope duplicated CLI responsibilities.
4. Implement repository ports before DB provider migration.
5. Standardize Notion bridge env keys and sync runner parameters.
6. Start `synt-mx` in SQLite-first mode with Postgres as optional provider.