Effect TS in Pawrrtal
Pawrrtal's Effect workspace is backend-ts/:
backend-ts/packages/domain-core(@pawrrtal/domain-core) owns shared transport-neutral contracts: domain schemas, ids, branded values, and public tagged errors used by HTTP, RPC, harness, services, and tests.backend-ts/packages/api-core(@pawrrtal/api-core) owns HTTP/OpenAPI contracts only:HttpApigroups, endpoint declarations, OpenAPI annotations, and rootApi.backend-ts/packages/rpc-core(@pawrrtal/rpc-core) owns Effect RPC protocol contracts only. It imports shared schemas/errors fromdomain-core; it must not import fromapi-core.backend-ts/packages/harness(@pawrrtal/harness) owns provider lifecycle, adapters, normalized streams, cancellation, continuation, and conformance. It may importdomain-core, but not HTTP/RPC app handlers.backend-ts/apps/api(@pawrrtal/api) owns HTTP runtime wiring: handlers, services, repos, policies, infrastructure layers, auth, andMain.ts.backend-ts/apps/rpcowns RPC runtime wiring: protocol handlers, streaming transport, auth/profile boundary, and app composition.backend/vendor/effect-smolis the Effect v4 beta source of truth. Do not infer APIs from Effect v3 docs orbackend/vendor/effect.
Current package pins: effect@4.0.0-beta.74 and matching @effect/* platform
packages. Do not file: link effect-smol; it contains internal workspace
references.
Before Writing Code
- Read the local module you are changing plus its caller and tests.
- Check
backend/vendor/effect-smol/ai-docs/or source for any API you are about to use. - Keep Python on
:8000canonical until route parity; Effect TS runs on:8001for the strangler slice. - Run the scoped gate for your change: usually
cd backend-ts && bun run typecheckpluscd backend-ts && bun run testwhen behavior changed.
Rules
- For new 006+ Effect TS work, shared schemas/errors live in
@pawrrtal/domain-core; HTTP contracts live in@pawrrtal/api-core; RPC contracts live in@pawrrtal/rpc-core; runtime behavior lives in app packages. - Existing modules may still keep schemas/errors in
api-core; when touching those boundaries for new work, move toward the split instead of deepening the old coupling. - Do not put
RpcProtocol.tsinapi-core. Put RPC protocol declarations inrpc-core, RPC handlers inapps/rpc, and HTTP handlers inapps/api. rpc-coremust not importapi-core, andapi-coremust not importrpc-core; both should depend ondomain-corewhen they share shapes.- The provider harness is a reusable library boundary, not an API transport. It should not define HTTP routes or RPC handlers.
- For the 006 session engine, use
Sessionsas the canonical domain module and remove/replace the old backend-tsConversationspractice module. Do not add new provider execution behavior underConversations. - Http handlers unpack input, call services, apply auth/policy, and translate boundary errors. They do not own mutable state.
- Services own business rules and dependency composition.
- Repos own SQL/storage details and return raw persistence shapes; decode into domain types at service boundaries.
- Tagged errors are data. Use
Schema.TaggedErrorfor expected failures and keep error channels explicit. - Prefer
Effect.Servicefor application services. UseContext.Tagfor injected resources, config bags, and test seams. - Do not preserve compatibility with in-progress branch shapes. Update consumers directly.
References
- Module Structure
- Services And Layers
- HTTP API
- RPC And Shared Contracts
- Testing