148 lines
6.4 KiB
Markdown
148 lines
6.4 KiB
Markdown
# Repository Guidelines
|
|
|
|
This is a Kratos service template. This file owns the layering contract
|
|
agents must follow when changing the template.
|
|
|
|
## Project structure
|
|
|
|
```
|
|
cmd/ Entrypoint, Wire injector, main.go.
|
|
configs/ Runtime config (config.yaml). No secrets.
|
|
internal/config/ Viper config models, loading, snapshots, and reloads.
|
|
internal/logging/ Structured logging sinks and source metadata.
|
|
internal/server/ Gin handlers, middleware, routers, static files.
|
|
internal/service/dto/ Hand-written request and response DTOs.
|
|
internal/service/ DTO/DO transport adapters.
|
|
internal/biz/ Domain models, usecases, repo interfaces, errors.
|
|
internal/data/ Repo implementations, database clients, migrations.
|
|
internal/initialize/ First-install and configuration orchestration.
|
|
internal/integration/ External I/O adapters (cache, email, payment, storage).
|
|
internal/paymentkit/ Shared payment normalization, signing, and JSON helpers.
|
|
internal/modules/ Built-in module schema, seed, menu, API, and task contributions.
|
|
internal/routecatalog/ HTTP route metadata and runtime policies.
|
|
internal/worker/ Timed-task runtime and scheduler.
|
|
internal/utils/ Stateless internal helpers.
|
|
docs/ Review notes and operational documentation.
|
|
pkg/ Reusable infrastructure packages.
|
|
web/ Vue administration frontend.
|
|
```
|
|
|
|
## Layering & dependency rules
|
|
|
|
Three model shapes flow through three layers. `biz` owns the DO, `data`
|
|
owns the PO; `service` is a pass-through that converts at its boundary.
|
|
|
|
```
|
|
client ──► DTO ──► service ──► DO ──► biz ──► DO ──► data ──► PO ──► storage
|
|
▲ ▲
|
|
│ declares │ implements
|
|
└─── repo IF ────┘
|
|
|
|
DTO Data Transfer Object — hand-written HTTP request / response.
|
|
DO Domain Object — pure biz model, no proto, no storage tags.
|
|
PO Persistent Object — storage shape, owned by `data`.
|
|
```
|
|
|
|
| Layer | Owns | Speaks at boundary | Never speaks |
|
|
|---------|------|--------------------|-------------------------|
|
|
| service | — | DTO ↔ DO | PO, storage client |
|
|
| biz | DO | DO | DTO, PO, storage client |
|
|
| data | PO | DO ↔ PO | DTO |
|
|
|
|
- `service` imports `internal/service/dto` (DTO) and `biz` (DO). Never `data`.
|
|
- `biz` never imports `service` or `data`. The repo interface declared here is
|
|
the inversion seam.
|
|
- `data` imports `biz` to implement the repo interface. Never `service`,
|
|
never DTOs.
|
|
- `integration` implements external I/O boundaries and may import `biz` and
|
|
provider SDKs; it is not a utility layer.
|
|
- `cmd` is the only place that wires all layers via Wire.
|
|
|
|
A change crossing these arrows the wrong way is a layering bug; fix the
|
|
design rather than add the import.
|
|
|
|
### Layer responsibilities
|
|
|
|
**service (DTO ↔ DO)**
|
|
|
|
- Convert hand-written HTTP DTOs into domain objects at the service boundary,
|
|
and build response DTOs from returned domain objects.
|
|
- Keep handlers focused on binding, authentication context, response envelopes,
|
|
and transport-specific limits.
|
|
- Validate request inputs at the service boundary before delegating to the
|
|
usecase.
|
|
- Return `biz` errors. No business rules, no storage access, no PO.
|
|
|
|
**biz (DO only)**
|
|
|
|
- Owns the DO (`type <Resource> struct` — no proto, no storage tags),
|
|
the usecase, and the repo interface (`type <Resource>Repo interface`).
|
|
- Owns typed errors built with `errors.NotFound` / `errors.BadRequest`
|
|
plus stable reason strings.
|
|
- Owns `ListOption` helpers — `ListFilter`, `ListOrderBy`, `ListOffset`,
|
|
`ListLimit` — so callers compose queries without leaking storage
|
|
primitives.
|
|
|
|
**data (DO ↔ PO)**
|
|
|
|
- _Repo shape_: implement `biz.<Resource>Repo`. The constructor returns
|
|
the interface, never the concrete type:
|
|
`func New<Resource>Repo(d *Data) biz.<Resource>Repo`.
|
|
- _PO and conversion_: define a PO when the storage shape diverges from
|
|
the DO. PO types stay inside `data`. Use free functions
|
|
`new<Resource>` (DO → PO, write) and `toBiz` (PO → DO, read).
|
|
Driver-specific builder types never leave `data`.
|
|
- _Shared clients_: `*Data` (declared in `internal/data/data.go`) holds
|
|
long-lived storage clients. Repos receive `*Data` and never construct
|
|
their own clients.
|
|
- _Querying_: translate `ListOptions.Filter` and `ListOptions.OrderBy`
|
|
into the storage driver's query language inside the repo.
|
|
- _Errors_: map driver errors to `biz` typed errors so callers above
|
|
never branch on the driver.
|
|
|
|
**server**
|
|
|
|
- Construct HTTP servers, apply middleware, register services. No
|
|
translation, no business logic.
|
|
|
|
### Add-a-resource checklist
|
|
|
|
1. **DTO**: define request and response types in `internal/service/dto/`.
|
|
2. **DO + repo interface**: declare both in `biz`; build the usecase on
|
|
top of the interface.
|
|
3. **Repo impl**: implement in `data` returning `biz.<Resource>Repo`;
|
|
add a PO and the matching conversion helpers when storage shape
|
|
diverges from DO.
|
|
4. **Transport**: add the service adapter, handler, router registration, and
|
|
routecatalog metadata.
|
|
5. **Wiring**: register providers in the relevant sets.
|
|
6. **Regenerate**: `make generate` or `make all` to refresh Wire and `go.mod`.
|
|
|
|
### Testing seam
|
|
|
|
Tests live beside the code they cover (`*_test.go`). Test layers in
|
|
isolation: service tests fake the usecase, biz tests fake the repo, data
|
|
tests exercise repo implementations at the storage boundary.
|
|
|
|
## Generation & generated files
|
|
|
|
Regenerate via `make generate` or `make all`; never hand-edit `wire_gen.go`.
|
|
|
|
## Naming & error reasons
|
|
|
|
- Resource: `<Resource>` (e.g., `Todo`); collection RPC:
|
|
`List<Resources>`.
|
|
- Types: repo `<Resource>Repo`, usecase `<Resource>Usecase`, service
|
|
`<Resource>Service`. PO types live inside `internal/data/`; pick a
|
|
name that fits the storage driver and convert with
|
|
`new<Resource>(do)` / `toBiz(po)` free functions.
|
|
- Error reasons use stable strings and are surfaced as `Err<Resource><Cause>` in
|
|
`biz`.
|
|
|
|
## Commits & security
|
|
|
|
- Conventional Commits: `feat:`, `fix:`, `refactor:`, `chore(deps):`,
|
|
`docs:`, `test:`. Regenerated files belong in the same commit as
|
|
their source.
|
|
- Never commit real credentials in `configs/config.yaml`.
|