commit 768400214e27b3b31270eb20e1dabb5a18e31776 Author: whekin Date: Thu Mar 5 00:47:18 2026 +0400 docs: add roadmap, ADRs, and initial HOUSEBOT specs diff --git a/docs/decisions/ADR-001-tech-stack.md b/docs/decisions/ADR-001-tech-stack.md new file mode 100644 index 0000000..295070a --- /dev/null +++ b/docs/decisions/ADR-001-tech-stack.md @@ -0,0 +1,42 @@ +# ADR-001: V1 Tech Stack + +## Status +Accepted + +## Context +The project needs to be modern, modular, and scalable while still delivering v1 quickly. + +## Decision +- Runtime/package manager/test runner: Bun +- Language: TypeScript (strict mode) +- Bot framework: grammY +- Database: Supabase Postgres +- Deployment runtime: Google Cloud Run +- Scheduling: Google Cloud Scheduler +- Frontend mini app: SolidJS (Vite SPA) + Tailwind +- Validation: Zod +- Linting: Oxlint +- Error tracking: Sentry +- Logging/metrics baseline: Cloud Logging/Monitoring + +## Rationale +- Bun provides a fast unified developer workflow. +- grammY is TypeScript-friendly with strong middleware patterns. +- Supabase keeps SQL-first data modeling while reducing ops overhead. +- Cloud Run + Scheduler offers serverless simplicity and predictable scheduling. +- Solid SPA provides modern UI performance with lightweight runtime cost. +- Oxlint enables fast linting suitable for small-commit workflow. + +## Consequences +Positive: +- Strong portfolio architecture with pragmatic service count. +- Clear path to production without heavy platform ops. + +Negative: +- Some enterprise tooling (Prometheus/Grafana/K8s) is deferred. +- Serverless constraints require disciplined idempotency and stateless design. + +## Alternatives Considered +- Fly.io runtime: good DX, but Cloud Run better matches serverless objective. +- Convex backend: strong DX, but SQL/reporting fit is weaker for financial ledger. +- Telegraf bot framework: mature ecosystem, but less desirable TS ergonomics. diff --git a/docs/decisions/ADR-002-hexagonal-architecture.md b/docs/decisions/ADR-002-hexagonal-architecture.md new file mode 100644 index 0000000..ee0fc68 --- /dev/null +++ b/docs/decisions/ADR-002-hexagonal-architecture.md @@ -0,0 +1,50 @@ +# ADR-002: Hexagonal Architecture (Ports and Adapters) + +## Status +Accepted + +## Context +The project combines domain-heavy finance logic, Telegram integration, mini-app APIs, and scheduled jobs. Without strict boundaries, framework and infrastructure concerns will leak into core logic. + +## Decision +Adopt hexagonal architecture with explicit layers: +- Domain: pure business model and invariants. +- Application: use-case orchestration. +- Ports: interfaces for repositories/services. +- Adapters: Telegram, DB, LLM, scheduler, HTTP. +- Composition root: runtime wiring only. + +## Boundary Rules +- Domain cannot import adapters, SDKs, HTTP, or SQL clients. +- Application cannot import concrete adapter implementations. +- Adapters can depend on SDKs and infra concerns but must implement ports. +- Entry points create dependency graph and pass ports to use-cases. + +## Module Layout +- `packages/domain` +- `packages/application` +- `packages/ports` +- `packages/adapters-*` +- `apps/*` for composition and delivery endpoints + +## Rationale +- Keeps financial logic testable and framework-independent. +- Enables incremental replacement of adapters (e.g., parser provider). +- Supports clean growth from v1 to larger-scale architecture. + +## Consequences +Positive: +- High maintainability and clear ownership of concerns. +- Better interview-readability of architecture. + +Negative: +- Requires initial discipline and more explicit interfaces. +- Slight boilerplate overhead for small features. + +## Risks and Mitigations +Risk: +- Overengineering through too many tiny abstractions. + +Mitigation: +- Create ports only for external boundaries and meaningful seams. +- Keep use-cases focused; avoid generic base classes. diff --git a/docs/roadmap.md b/docs/roadmap.md new file mode 100644 index 0000000..491dcd2 --- /dev/null +++ b/docs/roadmap.md @@ -0,0 +1,109 @@ +# Household Bot Roadmap + +## Vision +Build a clean, modular Telegram household finance platform with a mini app, designed for real use and portfolio-grade engineering quality. + +## Principles +- Hexagonal architecture with strict ports/adapters boundaries. +- Small, composable modules and strong type safety. +- Incremental delivery with small commits and always-green CI. +- Money-safe calculations (integer minor units only). +- Pragmatic v1, explicit enterprise extensions in later phases. + +## Phase 0 - Foundation +Goal: establish architecture, tooling, and delivery guardrails. + +Deliverables: +- Bun workspace monorepo layout. +- TypeScript strict base config. +- Oxlint setup and formatting conventions (no semicolons). +- CI pipeline for typecheck, lint, tests, and build. +- Initial ADRs and spec template. + +Exit criteria: +- Fresh clone can run quality checks with one command. +- CI passes on default branch. +- Architecture boundaries are documented. + +## Phase 1 - Finance Core +Goal: implement deterministic domain logic for monthly settlements. + +Deliverables: +- Domain value objects (`Money`, `BillingPeriod`, IDs). +- Settlement engine for rent + utility + purchase offsets. +- Default equal utility split, with optional day-based override. +- Domain unit tests covering edge cases. + +Exit criteria: +- Settlement logic is adapter-independent. +- Domain test suite covers normal and failure paths. + +## Phase 2 - Telegram Bot Core +Goal: process household activity and manage billing cycles in Telegram. + +Deliverables: +- grammY bot webhook service. +- Topic listener for `Общие покупки`. +- Utility and rent commands. +- Billing cycle commands and statements. +- Idempotent message processing. + +Exit criteria: +- Purchase messages are ingested and persisted. +- Monthly statement can be produced via command. + +## Phase 3 - Reminders and Scheduling +Goal: automate key payment reminders. + +Deliverables: +- Cloud Scheduler jobs. +- Reminder handlers for day 3/4 utilities, day 17 rent notice, day 20 due date. +- Dedicated topic posting for reminders. + +Exit criteria: +- Scheduled reminders fire reliably. +- Duplicate sends are prevented. + +## Phase 4 - Mini App V1 +Goal: deliver a usable household dashboard. + +Deliverables: +- SolidJS mini app shell. +- Telegram initData verification and membership gate. +- Ledger view, balances, and settlement preview. +- RU/EN localization. + +Exit criteria: +- Active group members can view current month balances. +- Financial views are consistent with bot calculations. + +## Phase 5 - Anonymous Feedback + Safety +Goal: support safer household communication. + +Deliverables: +- Anonymous DM flow to bot. +- Sanitized/rephrased repost to group topic. +- Rate limits and blocklist moderation. + +Exit criteria: +- Sender identity is hidden from group users. +- Abuse controls prevent spam and obvious misuse. + +## Phase 6 - Hardening and Portfolio Polish +Goal: production readiness and strong showcase quality. + +Deliverables: +- Sentry integration and structured logging. +- Integration and end-to-end tests. +- Runbooks and operational docs. +- Architecture diagram and demo instructions. + +Exit criteria: +- Incident/debug workflow is documented. +- Repo can be reviewed as a coherent system design case study. + +## Deferred (Post-v1) +- House wiki pages (Wi-Fi, rules, how-to). +- Cleaning/karma workflow. +- Advanced analytics and trend insights. +- Prometheus/Grafana/Kubernetes stack. diff --git a/docs/specs/HOUSEBOT-001-monorepo-bootstrap.md b/docs/specs/HOUSEBOT-001-monorepo-bootstrap.md new file mode 100644 index 0000000..beb4a40 --- /dev/null +++ b/docs/specs/HOUSEBOT-001-monorepo-bootstrap.md @@ -0,0 +1,78 @@ +# HOUSEBOT-001: Monorepo Bootstrap and Quality Gates + +## Summary +Initialize the repository as a Bun workspace monorepo with strict TypeScript, Oxlint, CI quality gates, and architecture-oriented package layout. + +## Goals +- Establish baseline folder structure for hexagonal architecture. +- Add root scripts for lint, typecheck, test, and build. +- Enforce no-semicolon formatting style and strict linting. +- Ensure CI runs on every push/PR. + +## Non-goals +- Implement business logic. +- Implement Telegram handlers. +- Create production cloud resources. + +## Scope +- In: repo skeleton, workspace config, root tooling config, CI workflow. +- Out: feature code, database schema, external service integration. + +## Interfaces and Contracts +- Root scripts exposed via `package.json`: + - `lint` + - `typecheck` + - `test` + - `build` +- Workspace packages must compile under shared TS config. + +## Architecture Constraints +- Workspace must include: + - `apps/bot` + - `apps/miniapp` + - `packages/domain` + - `packages/application` + - `packages/ports` + - `packages/contracts` + - `packages/observability` +- No cross-import from domain to adapters/apps. + +## File Plan +- Root: + - `package.json` + - `bunfig.toml` + - `tsconfig.base.json` + - `oxlint.json` + - `.editorconfig` + - `.gitignore` +- CI: + - `.github/workflows/ci.yml` +- Workspace placeholders: + - `apps/bot/src/index.ts` + - `apps/miniapp/src/main.tsx` + - `packages/*/src/index.ts` + +## Security and Safety +- No secrets in repo. +- Add `.env.example` templates only. +- CI must fail on type/lint/test failure. + +## Test Plan +- Unit: not applicable in this ticket. +- Integration: not applicable. +- Validation checks: + - Workspace install succeeds. + - All root scripts run locally. + - CI workflow executes all checks. + +## Acceptance Criteria +- [ ] Bun workspace initialized with declared workspaces. +- [ ] Oxlint config present and root lint script works. +- [ ] TypeScript strict base config is shared across workspaces. +- [ ] CI workflow runs lint, typecheck, test, build. +- [ ] Placeholder apps/packages compile. +- [ ] Docs updated with local bootstrap commands. + +## Rollout Plan +- Merge to default branch. +- Use as mandatory baseline for all subsequent tickets. diff --git a/docs/specs/HOUSEBOT-002-finance-domain-model.md b/docs/specs/HOUSEBOT-002-finance-domain-model.md new file mode 100644 index 0000000..de30965 --- /dev/null +++ b/docs/specs/HOUSEBOT-002-finance-domain-model.md @@ -0,0 +1,68 @@ +# HOUSEBOT-002: Finance Domain Model + +## Summary +Define domain entities and invariants for rent, utilities, shared purchases, and monthly settlements. + +## Goals +- Create a deterministic model for monthly household accounting. +- Encode money-safe arithmetic with integer minor units. +- Support equal split by default with optional day-based utility override. + +## Non-goals +- Telegram command handlers. +- Mini app rendering. + +## Scope +- In: domain entities, use-case contracts, and validation rules. +- Out: persistence adapter implementation. + +## Interfaces and Contracts +- `Money` value object (`currency: GEL`, `amountMinor: bigint | number`). +- `SettlementInput` contract with members, rent, utilities, purchases, overrides. +- `SettlementResult` contract with per-member due and explanation lines. + +## Domain Rules +- Rent is fixed per cycle and split equally among active members. +- Utilities split equally unless per-member day override is provided. +- Shared purchases reduce payer due amount and distribute cost across members. +- No floating-point operations. + +## Data Model Changes +- Define required table contracts (implemented in later DB ticket): + - `billing_cycles` + - `rent_rules` + - `utility_bills` + - `presence_overrides` + - `purchase_entries` + - `settlements`, `settlement_lines` + +## Security and Privacy +- Do not store unnecessary personal data. +- Use internal IDs for members in calculations. + +## Observability +- Structured calculation logs (input hash, cycle id, result totals). +- Error event on invalid settlement state. + +## Edge Cases and Failure Modes +- Member count is zero. +- Utility day overrides sum to zero. +- Negative amounts from malformed inputs. +- Duplicate purchase entries. + +## Test Plan +- Unit: + - money arithmetic and normalization + - equal split and day-weighted split cases + - purchase offsets and reconciliation checks +- Integration: not in this ticket. +- E2E: not in this ticket. + +## Acceptance Criteria +- [ ] Value objects implemented and tested. +- [ ] Settlement input/output contracts defined. +- [ ] Deterministic settlement math covered by tests. +- [ ] Edge cases produce explicit domain errors. + +## Rollout Plan +- Merge as dependency for settlement engine and bot handlers. diff --git a/docs/specs/HOUSEBOT-003-purchase-parser.md b/docs/specs/HOUSEBOT-003-purchase-parser.md new file mode 100644 index 0000000..1cc7e7a --- /dev/null +++ b/docs/specs/HOUSEBOT-003-purchase-parser.md @@ -0,0 +1,74 @@ +# HOUSEBOT-003: Purchase Parser (Hybrid Rules + LLM Fallback) + +## Summary +Parse free-form purchase messages (primarily Russian) from the Telegram topic `Общие покупки` into structured ledger entries. + +## Goals +- High precision amount extraction with deterministic rules first. +- Fallback to LLM for ambiguous or irregular message formats. +- Persist raw input, parsed output, and confidence score. + +## Non-goals +- Receipt image OCR. +- Full conversational NLP. + +## Scope +- In: parsing pipeline, confidence policy, parser contracts. +- Out: bot listener wiring (separate ticket). + +## Interfaces and Contracts +- `parsePurchase(input): ParsedPurchaseResult` +- `ParsedPurchaseResult`: + - `amountMinor` + - `currency` + - `itemDescription` + - `confidence` + - `parserMode` (`rules` | `llm`) + - `needsReview` + +## Domain Rules +- GEL is default currency when omitted. +- Confidence threshold determines auto-accept vs review flag. +- Never mutate original message text. + +## Data Model Changes +- `purchase_entries` fields: + - `raw_text` + - `parsed_amount_minor` + - `currency` + - `item_description` + - `confidence` + - `parser_mode` + - `needs_review` + +## Security and Privacy +- Sanitize prompt inputs for LLM adapter. +- Do not send unnecessary metadata to LLM provider. + +## Observability +- Parser mode distribution metrics. +- Confidence histogram. +- Error log for parse failures. + +## Edge Cases and Failure Modes +- Missing amount. +- Multiple possible amounts in one message. +- Non-GEL currencies mentioned. +- Typos and slang variants. + +## Test Plan +- Unit: + - regex extraction fixtures in RU/EN mixed text + - confidence scoring behavior +- Integration: + - LLM fallback contract with mocked provider +- E2E: consumed in bot ingestion ticket. + +## Acceptance Criteria +- [ ] Rules parser handles common RU message patterns. +- [ ] LLM fallback adapter invoked only when rules are insufficient. +- [ ] Confidence and parser mode stored in result. +- [ ] Tests include ambiguous message fixtures. + +## Rollout Plan +- Start with conservative threshold and monitor review rate. diff --git a/docs/specs/HOUSEBOT-004-reminders-and-scheduler.md b/docs/specs/HOUSEBOT-004-reminders-and-scheduler.md new file mode 100644 index 0000000..5bb9f05 --- /dev/null +++ b/docs/specs/HOUSEBOT-004-reminders-and-scheduler.md @@ -0,0 +1,69 @@ +# HOUSEBOT-004: Reminders and Scheduler + +## Summary +Schedule and deliver household billing reminders to dedicated Telegram topics. + +## Goals +- Automate utility and rent reminders on configured dates. +- Ensure idempotent sends and reliable retries. +- Keep scheduling externalized via Cloud Scheduler. + +## Non-goals +- Dynamic natural-language reminder editing. +- Per-user DM reminders in v1. + +## Scope +- In: scheduler endpoints, reminder generation, send guards. +- Out: full statement rendering details. + +## Interfaces and Contracts +- HTTP endpoints triggered by Cloud Scheduler: + - `/jobs/reminder/utilities` + - `/jobs/reminder/rent-warning` + - `/jobs/reminder/rent-due` +- Job payload includes cycle and household references. + +## Domain Rules +- Utilities reminder target: day 3 or 4 (configurable). +- Rent warning target: day 17. +- Rent due target: day 20. +- Duplicate-send guard keyed by household + cycle + reminder type. + +## Data Model Changes +- `reminder_dispatch_log`: + - `household_id` + - `billing_cycle` + - `reminder_type` + - `sent_at` + - `telegram_message_id` + +## Security and Privacy +- Scheduler endpoints protected by shared secret/auth header. +- No sensitive data in scheduler payloads. + +## Observability +- Job execution logs with correlation IDs. +- Success/failure counters per reminder type. +- Alert on repeated send failures. + +## Edge Cases and Failure Modes +- Telegram API temporary failure. +- Scheduler retry causes duplicate call. +- Missing household topic mapping. + +## Test Plan +- Unit: + - date and reminder eligibility logic +- Integration: + - endpoint auth and idempotency behavior +- E2E: + - simulated month schedule through all reminder events + +## Acceptance Criteria +- [ ] Scheduler endpoints implemented and authenticated. +- [ ] Reminder sends are idempotent. +- [ ] Logs and counters available for each job run. +- [ ] Retry behavior validated. + +## Rollout Plan +- Deploy with dry-run mode first, then enable live sends. diff --git a/docs/specs/HOUSEBOT-005-anonymous-feedback.md b/docs/specs/HOUSEBOT-005-anonymous-feedback.md new file mode 100644 index 0000000..74035d3 --- /dev/null +++ b/docs/specs/HOUSEBOT-005-anonymous-feedback.md @@ -0,0 +1,70 @@ +# HOUSEBOT-005: Anonymous Feedback Flow + +## Summary +Allow members to submit anonymous household feedback to the bot via DM, then repost sanitized messages to a configured topic. + +## Goals +- Protect sender identity in group output. +- Reduce conflict by neutralizing wording. +- Prevent abuse with rate limits and blocklist controls. + +## Non-goals +- Anonymous reactions. +- Admin identity reveal path. + +## Scope +- In: DM intake, sanitize/rewrite, posting, moderation guardrails. +- Out: full moderation panel UI. + +## Interfaces and Contracts +- Bot command in DM: `/anon ` (or conversational prompt flow). +- Use-case: `PostAnonymousMessage`. +- Result includes posted message id and moderation outcome. + +## Domain Rules +- Sender identity is never included in reposted content. +- Per-user cooldown and daily cap enforced. +- Blocklisted phrases reject or request rewrite. + +## Data Model Changes +- `anonymous_messages`: + - `household_id` + - `submitted_by_member_id` (internal only) + - `raw_text` + - `sanitized_text` + - `moderation_status` + - `posted_message_id` + - timestamps + +## Security and Privacy +- Internal sender reference is never exposed via group features. +- PII minimization and retention policy documented. +- Abuse logging without public reveal. + +## Observability +- Submission volume metrics. +- Rejection/acceptance rate metrics. +- Error logs for rewrite or post failures. + +## Edge Cases and Failure Modes +- Message too short/too long. +- Spam bursts. +- Telegram post failure after rewrite. + +## Test Plan +- Unit: + - moderation and cooldown policy + - anonymization invariants +- Integration: + - DM ingestion to repost pipeline +- E2E: + - anonymous submission lifecycle in test group + +## Acceptance Criteria +- [ ] DM to group repost works end-to-end. +- [ ] Sender is hidden in group output. +- [ ] Rate limit and blocklist enforced. +- [ ] Sanitization pipeline tested. + +## Rollout Plan +- Start with strict moderation thresholds and tune based on false positives. diff --git a/docs/specs/README.md b/docs/specs/README.md new file mode 100644 index 0000000..125150a --- /dev/null +++ b/docs/specs/README.md @@ -0,0 +1,75 @@ +# Specs Guide + +Each implementation ticket should have one spec file in `docs/specs/`. + +## Naming +Use `HOUSEBOT--.md`. + +Example: +- `HOUSEBOT-001-monorepo-bootstrap.md` + +## Spec Template + +```md +# + +## Summary +Short description of the feature and user value. + +## Goals +- ... + +## Non-goals +- ... + +## Scope +- In: ... +- Out: ... + +## Interfaces and Contracts +- Commands/events/APIs involved. +- Input and output schemas. + +## Domain Rules +- Business constraints and invariants. + +## Data Model Changes +- Tables, fields, indexes, migrations. + +## Security and Privacy +- Auth, authorization, PII handling, abuse prevention. + +## Observability +- Required logs, metrics, traces, and alerts. + +## Edge Cases and Failure Modes +- Invalid input +- External service failures +- Duplicate/retry behavior + +## Test Plan +- Unit: +- Integration: +- E2E: + +## Acceptance Criteria +- [ ] ... +- [ ] ... + +## Rollout Plan +- Feature flags / staged rollout / backout plan. +``` + +## Definition of Done +- Spec exists and matches implementation. +- Code follows architecture boundaries. +- Tests for new behavior are included and passing. +- Lint and typecheck pass in CI. +- Docs/ADR updates included if behavior or architecture changed. +- No TODOs without linked follow-up ticket. + +## Boundary Rules (Hexagonal) +- `packages/domain` must not import framework/DB/HTTP code. +- `packages/application` depends only on domain + ports/contracts. +- `packages/adapters-*` implement ports and may depend on external SDKs. +- Wiring of concrete adapters happens only in app entrypoints. diff --git a/docs/tasks/foundation.md b/docs/tasks/foundation.md new file mode 100644 index 0000000..8eb8b04 --- /dev/null +++ b/docs/tasks/foundation.md @@ -0,0 +1,18 @@ +# Foundation Task Breakdown + +## Epic: Platform Foundation + +1. HOUSEBOT-001 - Monorepo Bootstrap and Quality Gates +- Output: Bun workspaces, strict TS, Oxlint, CI skeleton. + +2. HOUSEBOT-002 - Local Dev Workflow +- Output: unified dev scripts, env templates, runbook for local startup. + +3. HOUSEBOT-003 - Package Boundary Enforcement +- Output: import path policy and boundary lint checks. + +4. HOUSEBOT-004 - Testing Harness Setup +- Output: test runner configuration for unit/integration/e2e layers. + +5. HOUSEBOT-005 - Release/Branching Conventions +- Output: commit conventions, PR template, branch naming guide.