# Package Boundaries

> Canonical path: `specs/repository/package-boundaries.md`
> Status: living architecture spec
> Scope: repository package-level dependency direction and migration guardrails for the current single-repo implementation.

## 1. Purpose

This document owns the package-level architecture map that used to live in `AGENTS.md`. It describes intended dependency direction for current single-repo work. Verify exact current wiring in code before editing a package.

Use `docs/architecture-spec.md` for target architecture direction and `docs/tech_design.md` for current implementation status. This document bridges those sources into concrete package-boundary rules for day-to-day changes.

## 2. Package-Level Map

The primary production dependency direction is:

```text
internal/api/{domain} -> internal/service/{domain} -> internal/store/{domain} -> core and infrastructure
```

Packages may skip a layer only for a narrow downward dependency, such as a pure
DTO converter consuming a store result type. A lower layer must not call back
into a higher layer. Process composition may construct several layers, but that
construction privilege does not make the composition root a business-logic
owner.

```mermaid
flowchart TB
    Clients["web + desktop/ + cmd/*"]
    Composition["internal/server + internal/router + internal/meshxruntime"]

    APIRoot["internal/api"]
    APIDomains["internal/api/{domain}"]
    DTO["internal/api/dto"]
    Converter["internal/api/dto/converter"]

    Services["internal/service/{domain}"]
    StoreRoot["internal/store"]
    StoreDomains["internal/store/{domain}"]
    StoreModel["internal/store/model"]
    StoreInfra["internal/store/{coordinator,storeerr} + internal/coredb + internal/tidb"]

    Core["internal/core/*"]
    Infra["shared internal infrastructure owners"]

    Clients --> Composition --> APIRoot --> APIDomains
    APIDomains --> DTO
    APIDomains --> Converter
    APIDomains --> Services

    Converter --> DTO
    Converter --> StoreDomains

    Composition -. "construction only" .-> StoreRoot
    StoreRoot --> StoreDomains
    StoreRoot --> StoreInfra
    Services --> StoreDomains
    Services --> Core
    StoreDomains --> StoreModel
    StoreDomains --> StoreInfra
    Services --> Infra
    StoreDomains --> Core
    StoreDomains --> Infra
```

### 2.1 Current package roster

This roster is current-state navigation, not permission to create sibling
packages casually. Update it when a production package is added, renamed, or
retired; service additions must also update the executable service allowlist in
`guardrails/store/check-store-refactor-boundaries.sh`.

| Layer | Current owners and support packages |
| --- | --- |
| API domains | `actionsrunner`, `admin`, `agent`, `ags`, `app`, `auth`, `automation`, `billing`, `channel`, `content`, `daemon`, `extension`, `identity/lookup`, `im`, `kb`, `knowledgeqa`, `llm`, `media`, `memory`, `meshxapi`, `onboarding`, `org`, `providertokens`, `provider`, `public`, `repocache`, `repotokens`, `roles`, `schedule`, `serviceaccount`, `skills`, `task`, `team`, `teamworkflow`, `trigger`, `webagent`, `workflow/binding`, `workflow/invocation`, `workflow/plan`, `workflow/run`, `workspace` |
| API support | `internal/api`, `internal/api/dto`, `internal/api/dto/converter`, `internal/api/testdata`, `internal/api/testkit` |
| Services | `actionsrunner`, `agentapproval`, `agentmemory`, `agentruntime`, `app/installation`, `approvalapp`, `appruntime`, `authflow`, `automation`, `automation/runtime`, `channeladmin`, `collaborator`, `content`, `content/migration`, `extensionflow`, `kb`, `knowledgeqa`, `knowledgeqa/runtime`, `maas`, `memory`, `message`, `organization`, `providertokens`, `prwatch`, `repocache`, `repotokens`, `resource/access`, `resource/activity`, `resource/repos`, `role/agents`, `role/execution`, `roles`, `serviceaccount`, `serviceevent`, `skills`, `team/roleproposal`, `teamworkflow`, `workspace` |
| Store domains | `access`, `admin`, `agent`, `agentops`, `app`, `approval`, `attachment`, `automation`, `channel`, `channeladmin`, `content`, `content/migration`, `extension`, `identity`, `im`, `kb`, `knowledgeqa`, `message`, `onboarding`, `organization`, `orgmembership`, `providertokens`, `plan`, `privateagent`, `provider`, `reaction`, `repocache`, `reporting`, `repotokens`, `resource/activity`, `resource/memory`, `resource/repos`, `resource/roles`, `resource/skills`, `review`, `rewind`, `role/execution`, `schedule`, `seatbilling`, `serviceaccount`, `serviceactor`, `taskboard`, `taskcompat`, `tasktimeline`, `team`, `teamworkflow`, `unread`, `workflow/binding`, `workflow/calendar`, `workflow/invocation`, `workflow/plan`, `workflow/run`, `workspace` |
| Store support | `internal/store` composition, `internal/store/coordinator`, `internal/store/model`, `internal/store/storeerr`, `internal/store/testfixture`, `internal/store/testkit` |

## 3. Boundary Rules

`internal/api/dto` owns HTTP wire request and response types. It must not import store packages or `internal/api/dto/converter`.

`internal/api/dto/converter` owns pure DTO conversion. It may depend on `internal/api/dto`, `internal/store/model`, and store domain packages, but must not import `internal/api/{domain}` packages.

`internal/api/{domain}` packages own handlers, route wiring, consumer-side ports, and domain assembly or presenter logic. Business requests flow through the owning service; handler files must not acquire new direct store dependencies. Existing direct handler-to-store references are migration debt ratcheted by `guardrails/store/check-store-refactor-boundaries.sh`. New REST API endpoints belong under the owning domain package. Create a new domain package only when existing domains do not cover the feature area. Shared helpers such as auth and response helpers live in root `internal/api`; route composition lives in `internal/router`.

`internal/store/model` owns persistence models only. Store model structs must not carry JSON tags. HTTP and browser wire contracts belong in `internal/api/dto` and conversion belongs in handlers or `internal/api/dto/converter`.

`internal/store/{domain}` packages own domain data access and store-local domain rules. They must not import root `internal/store`, API packages, or service packages. Production `internal/store -> internal/service` edges are forbidden and held at zero by `guardrails/store/store-domain-split-debt-baseline.json`.

Root `internal/store` is a composition and migration-compatibility facade only. New business logic belongs in a store domain package or an approved `internal/service/*` orchestration package.

Production imports of root `internal/store` are temporary migration debt and are allowlisted or ratcheted by `guardrails/store/check-store-refactor-boundaries.sh`. Do not add new production root-store callers.

Root `func (*Store)` methods, root type aliases, and root alias or facade files are ratcheted by the boundary script. Cleanup rounds should delete or move them into domain stores, not add more root business methods.

`internal/service/<domain>` packages own reusable business algorithms and cross-store orchestration extracted out of store or API layers. Services depend downward on narrow store capabilities and must not import API packages. Service packages should be domain-scoped; avoid adding a single-child capability wrapper under a service domain unless the domain genuinely owns multiple capabilities and the subpackage name adds durable meaning. Approved service orchestration packages are listed in the roster above and mirrored by the explicit allowlist in `guardrails/store/check-store-refactor-boundaries.sh`; adding another package requires updating both places.

Store child packages require an independent invariant and a dependency cut that
does not need a parent facade, alias, or reverse import. In particular,
`internal/store/message/{diagnostics,readstate,search}` are retired semantic
helper paths and remain forbidden by the store-domain split guardrail. Do not
recreate them solely to reduce file or line counts.

## 4. Related Guardrails And Specs

- `guardrails/store/check-store-refactor-boundaries.sh` protects the root store migration boundary.
- `guardrails/store/check-store-domain-split-guardrails.py` protects oversized store-domain ceilings, child-package boundaries, and the zero-target production store-to-service direction.
- `guardrails/store/store-domain-split-debt-baseline.json` records the versioned accepted debt with an owner, reason, and retirement condition.
- `guardrails/store/check-store-json-tags.py` protects the store JSON boundary.
- `specs/storage/storage.md` defines TiDB-only core storage and schema source of truth.
- `specs/api/internal-api-clean-code-design.md` defines handler package organization and API cleanup rules.
- `specs/api/handler-adapter.md` defines typed handler adapter boundaries.

These targeted guardrails cover enforceable slices of the package-boundary contract. There is no single repository-wide import graph guardrail for the full map; add a deterministic domain guardrail when a new boundary rule can be checked reliably in CI.
