# store Guardrails

> Canonical path: `guardrails/store/README.md`

This README lists executable guardrails for the `store` domain in recommended order.

- [`check-store-sql-ownership.sh`](./check-store-sql-ownership.sh) — inventories SQL-owning Go/SQL files and ratchets the exact allowlist for production SQL that still lives outside canonical store/coredb/tidb/migration directories.
- [`check-store-domain-split-guardrails.py`](./check-store-domain-split-guardrails.py) — primary ratchet for store-domain child package allowlists, parent metrics, upward imports, direct forbidden paths, generic child package names, and production store-to-service edges. Its executable debt inventory is [`store-domain-split-debt-baseline.json`](./store-domain-split-debt-baseline.json).
- [`../../scripts/check-import-aliases.py`](../../scripts/check-import-aliases.py) — repository-wide Go import alias audit used by `make check-import-aliases`; it replaces the former store-only alias guardrail.
- [`check-store-json-tags.py`](./check-store-json-tags.py) — enforces the store JSON boundary: no `json` tags in non-test `internal/store`, no store-owned JSON marshal/unmarshal outside `internal/store/model/jsonobject.go`, no direct store imports/aliases to DTO or temporary payload packages, and an empty allowlist.
- [`check-store-txstore-pattern.sh`](./check-store-txstore-pattern.sh) — enforces the `Store` / `TxStore` transaction API pattern for migrated store packages listed in the SQL ownership inventory.
- [`check-app-canonical-runtime.sh`](./check-app-canonical-runtime.sh) — rejects runtime Go SQL references to the 18 retired App tables; migration/bootstrap/admin inventory remains owned by `internal/tidb` checks.
- [`check-store-refactor-boundaries.sh`](./check-store-refactor-boundaries.sh) — broader historical refactor ratchet, including the explicit `internal/service` orchestration allowlist owned with `specs/repository/package-boundaries.md`. Default execution keeps the long-term zero targets and may fail on existing debt. `scripts/harness-fast.sh` passes explicit current baselines so the same script blocks new growth while cleanup continues.

## Store-domain split debt baseline

`store-domain-split-debt-baseline.json` is the versioned ceiling for the five
oversized store parents. Each package entry records the owning package, why the
current debt is accepted, and the condition for retiring it. The baseline also
records production `internal/store -> internal/service` edges; the current and
durable target is zero. A new edge fails, and any stale debt entry also fails.

The current inventory provenance is `949a11d0332151cc96bb66c5c57eabf7d58c41e2`, with
the #t2771 collaborator-request scope ratcheted on top (taskboard durable state and
its api/service importers, plus one store/app approval-subject importer).
This hash is only a reproducible snapshot marker, not a normative requirement.
Regenerate raw metrics from a clean target revision with:

```bash
python3 guardrails/store/check-store-domain-split-guardrails.py \
  --write-baseline \
  --baseline /tmp/store-domain-split-baseline.json
```

The generated file is evidence, not a ready-to-merge replacement: copy only
verified ceiling changes into the tracked baseline, preserve or improve the
owner/reason/retirement metadata, and review the diff. Never consume freed
budget in another metric or package. Lower every ceiling that decreases.
No prospective child package is currently pre-approved. Existing child packages
come only from `existingChildPackages`; a new child requires its own reviewed
boundary evidence and a matching baseline change.

For `internal/store/organization`, the sibling-store ceiling of `4` includes a
direct import of `internal/store/agent`, which owns AgentTeam proxy provider-ID
semantics. This makes the dependency previously hidden by the retired root-store
forwarder explicit; it does not authorize copying the provider-ID prefix rule
into organization. Move that cross-domain semantic to an existing or future
neutral provider contract before lowering the ceiling back to `3`.

## Fast harness debt ceilings

`scripts/harness-fast.sh` owns the active store ceilings. They were last
regenerated from `origin/main` at `0e3e3685a2`; this revision is
non-normative inventory provenance. The zero defaults in the scripts remain
hard targets unless a nonzero ceiling is listed below.

| Inventory | Active ceilings | Debt owner | Why the debt is temporarily accepted | Retirement condition |
| --- | --- | --- | --- | --- |
| Store JSON boundary | JSON-tagged store lines `350`; JSON operations outside `model/jsonobject.go` `95` | The matching `internal/store/{domain}` package; `internal/store/model/jsonobject.go` owns persistence JSON conversion | Existing persistence models and store-local encoders have not all moved to the canonical conversion owner | Move tags and encode/decode work into the canonical model conversion boundary, then lower the matching ceiling in the same change |
| Store JSON forbidden edges | direct store DTO or temporary-payload edges `0` | All store packages | Upward store-to-wire dependencies are not accepted debt | Keep the ceiling at zero |
| API-to-store migration | `api_*.go` store refs `68`; API `store/model` refs `14`; production API root-store imports `1` | The matching `internal/api/{domain}` package and its domain service/store port | Handler migrations are incomplete and must be split by domain instead of hidden behind another broad facade | Move persistence access behind narrow domain ports and DTO converters; lower each ceiling on every decrease |
| Root store composition | non-test root files `1`; root test files `1`; unapproved root files `0`; root `Graph` methods `1`; root type aliases `0` | `internal/store` composition | The root package is limited to the startup/integration-test composition graph | Keep business types and behavior in their domain owners; keep the compatibility and alias ceilings at zero |
| Redundant import aliases | obvious no-op aliases `18` | Owners of the Go files reported by `check-store-refactor-boundaries.sh` | Existing aliases are mechanical cleanup debt and do not justify a cross-package rewrite | Remove aliases when their files are touched and lower the ceiling on every decrease |
| Domain method migration inventories | rewind `27`; reaction `5`; review `0`; agent-ops `4`; app ecosystem `211` | `internal/store/{rewind,reaction,review,agentops,app}` respectively | These inventories keep package-local migration work visible without allowing another domain to consume the freed budget | Move or delete methods at the owning boundary and lower only that domain's ceiling; keep review at zero |
| Root-store import files | production files `4`; store-domain files importing root store `1`; legacy usecase imports `0` | Server/e2e composition and the two test fixture packages | The remaining imports construct or wrap the root graph; no production domain imports it | Keep root imports confined to explicit composition/test-fixture boundaries and keep legacy usecase imports at zero |

All unlisted boundary metrics keep their script defaults, normally zero.
Increases require a reviewed scope and an updated owner, reason, and retirement
condition here. Decreases must update `scripts/harness-fast.sh` in the same
change.
