# Service and module map This is an ownership map, not an API dump. Read the owning implementation and tests before changing behavior. ## Lifecycle and account ownership | Module | Owns | Important constraints | | --- | --- | --- | | `src/bootstrap.ts` | Dependency composition and startup wiring | Keep business policy in services; preserve initialization order and test seams. | | `src/main-loop.ts` | Shared discovery/screening/dispatch workers and legacy loop | Loops are abortable; queue transitions and shutdown must remain recoverable. | | `services/reddit-account-runtime.ts` | Immutable account runtime/factory/manager lifecycle | Same-account operations serialize; session refresh replaces one runtime. | | `services/reddit-account-runtime-builder.ts` | Concrete account dependency graph and account loop | Account-specific browser, Matrix, repos, limiter, automation, chat, and media live here. | | `services/reddit-accounts.ts` | Account import/activation orchestration | Verification must bind Reddit cookies and Matrix identity before activation. | | `services/account-auth-context.ts` | Current verified identity snapshot | Account work pauses unless both sides authenticate. | | `services/session-bound-runtime.ts` | Legacy auth-bound background lifecycle | Prevents background work while logged out. | ## Discovery, preparation, and delivery | Module | Owns | Important constraints | | --- | --- | --- | | `services/monitor.ts` | Subreddit ordering, candidate fetching, age/gender/seller screening, rejection summaries | Cheap checks first; preserve exact rejection/deferred counts; listing 404 disables the subreddit. | | `reddit/api.ts` | Reddit JSON calls, post parsing, seller/profile evidence, username resolution, error types | All reads must use the coordinator; redact error metadata. | | `reddit/request-coordinator.ts` | Process-wide Reddit request spacing and cooldown | Space failed requests too; 429 cooldown is global. | | `services/processor.ts` | Source-specific AI preparation and outbound safety | Returns prepared or explicit skip; performs no remote chat send. | | `services/strategy-selector.ts` | Weighted explore/exploit selection and experiment metadata | Separate image/chat strategy sections; respect mature response window and sample floor. | | `services/recipient-deduplicator.ts` | Global recipient history plus live reservation | Case-insensitive; release failures, commit successes, recover stale claims. | | `utils/rate-limiter.ts` | Per-account send spacing/hour limits/jitter | Increment only for confirmed sends; reply priority may use the same limiter. | | `database/candidate-queue-repository.ts` | Durable candidate state machine, leases, retries, counts | Mutations require the expected worker lease; recover expired/interrupted work. | ## Conversation, chat, and media | Module | Owns | Important constraints | | --- | --- | --- | | `services/chat/service.ts` | Matrix conversation sync, cache updates, starts/replies, scoped cooldowns | Room-creation limits pause new outreach without blocking existing-room replies; Matrix acceptance and UI visibility are distinct. | | `services/chat/matrix/client.ts` | Matrix HTTP protocol and error classification | Authentication/rate-limit errors need typed handling. | | `services/chat/cache.ts` | Account-scoped cached conversations and sync state | SQLite is durable; do not share caches across accounts. | | `services/chat/matrix/username-resolver.ts` | Matrix/Reddit identity mapping | Preserve unresolved internal IDs without leaking them in operator text. | | `services/chat/matrix/token-refresher.ts` | Explicit refresh-unavailable behavior | New credentials come from verified extension dumps, not token sniffing. | | `services/conversation-automation.ts` | Reply-first policy, claims, retries, send-time refresh, handoffs, turn budgets | Snapshot policy; claim before send; supersede stale queued work; reconcile pending claims; fail closed. | | `services/conversation-state.ts` | Pure conversation parsing/state/safety helpers | Conversation text is untrusted data; keep prompt boundaries explicit. | | `services/conversation-boundaries.ts` | Sequence-aware media requests, refusals, and full-stop detection | Short ambiguous replies become boundaries only in the matching request context. | | `services/outbound-message-safety.ts` | Final no-proximity/no-meeting rule | This is defense in depth beyond prompts. | | `services/conversation-outcome*.ts` | Response outcome classification/recording | Keep analytics attribution account/message scoped. | | `services/response-checker.ts` | Inbox/performance response checks and successful examples | Non-overlapping; do not confuse chat sync with outcome maturity. | | `services/media.ts` | Download, deduplicate, index, and list private media | Preserve account ownership and authenticated serving. | | `services/media-sync.ts` | Periodic authenticated media sync | Stop while auth is unavailable and on runtime shutdown. | | `services/media-library.ts` | Shared operator uploads, image validation/re-encoding, classification state, and private files | Require consent confirmation; received media never enters this store. | | `services/media-library-exchange.ts` | Inbound request detection, progressive selection, reservation, and image-first exchange | Never offer proactively; exact tags do not substitute; no asset reuse per conversation. | | `database/media-library-repository.ts` | Shared asset metadata and durable account/conversation send audit | Reserve before remote send; uncertain sends stay consumed. | ## Persistence | Module | Owns | | --- | --- | | `database/client.ts` | Database open settings and ordered migrations. | | `database/repositories.ts` | Posts, messages, successes, activity, outbox, states, claims, outcomes, users, recipient history. | | `database/account-repositories.ts` | Verified account records, conversations, sync cursors, and media content. | | `database/ai-usage-repository.ts` | Model request/cost/reliability records. | | `database/legacy-content-import.ts` | One-time ownership of legacy file-backed chat/media data. | | `config/persistence.ts` | Secret-free application configuration in SQLite. | Repositories should expose domain operations rather than raw SQL to callers. Multi-step state transitions belong in SQLite transactions when partial completion would break invariants. ## Web and agent surfaces | Module | Owns | | --- | --- | | `web/server.ts` | Express lifecycle, middleware order, route registration, static dashboard/media. | | `web/auth.ts` | Dashboard session and bearer-token authorization. | | `web/context.ts` | Narrow route dependency container. | | `web/routes/*.ts` | Focused endpoint families. | | `web/api-catalog.ts` | Operation metadata, OpenAPI, and capability discovery. | | `web/agent-job-manager.ts` | Bounded async sync jobs and job status. | | `web/events/*` | Typed event publication, replay, subscriptions, and Express SSE. | | `web/log-broadcaster.ts` | Recent logs plus legacy/typed stream adapters. | | `mcp/api-client.ts`, `mcp/server.ts` | HTTP-backed stdio MCP tools. | Authorization is semantic, not just authentication: read and control agent tokens intentionally cannot import sessions, send messages, activate accounts, mutate legacy config, or use debug routes. ## Frontend | Area | Owns | | --- | --- | | `apps/dashboard/src/app/` | Shell, routing, providers, auth status, notifications, realtime repair. | | `apps/dashboard/src/api/` | HTTP client, schema parsing, query keys/hooks. | | `apps/dashboard/src/features/` | Route-level feature slices. | | `apps/dashboard/src/components/` | Reusable domain-aware UI elements. | | `packages/api-contracts/` | Shared strict transport schemas and inferred types. | ## Utility boundaries - `utils/logger.ts`: Winston creation, child context, and attachable sinks. No production `console.log`. - `utils/retry.ts`: bounded retry behavior for operations that are safe to repeat. - `utils/image.ts`: download/MIME/size helpers. - `utils/gender-tag.ts`: deterministic self-declared tag parsing. - `utils/fetch-with-timeout.ts`: abortable HTTP timeout wrapper. - `utils/json-safe.ts`: safe serialization for log/event data. When a module starts owning two independent reasons to change, extract a narrow collaborator and inject it. Do not solve size alone by moving methods into a generic utility file.