---
layout: 'page'
uri: '/framework/overview/architecture'
position: 3
slug: 'framework-overview-architecture'
parent: 'framework-overview'
navTitle: 'Architecture'
title: 'Architecture'
description: 'DDD vrstvy s CQRS, pravidla závislostí, lifecycle, cross-domain izolace.'
---
# Architecture
DDD s CQRS a bus pattern. Čtyři vrstvy s přísnými pravidly závislostí. Komunikace přes CommandBus/QueryBus/EventBus zajišťuje loose coupling -- command handlery neznají HTTP, handlery neznají databázi.
## Čtyři vrstvy
| Vrstva | Složka | Balíčky | Popis |
|---|---|---|---|
| **Domain** | `domain/` | `shared/`, `user/`, `token/` | Entity, value objects, interfaces, errors, events. Žádné závislosti. |
| **Application** | `application/` | `bus/`, `<domain>/command/`, `<domain>/query/`, `<domain>/event/` | CQRS handlery organizované po doménách, bus middleware. Závisí jen na domain. |
| **Infrastructure** | `infrastructure/` | `config/`, `database/`, `sqlite/`, `security/`, `di/` | Implementace domain interfaces, databáze, security. |
| **Presentation** | `presentation/` | `http/handler/`, `http/middleware/`, `http/response/`, `http/server/`, `console/` | HTTP a CLI vrstva. |
```
presentation --> application --> domain <-- infrastructure
| ^
+----------------------------------------+
```
## Startup sequence
```
cmd/main.go
-> signal.NotifyContext(SIGINT, SIGTERM) Root ctx s signal handlingem
-> di.CreateApplication() Wire DI vytvoří vše
-> config.LoadConfig() Načtení .env
-> database.NewSqliteManager() Připojení k SQLite
-> database.MigrationManager.RunUp() Automatické migrace
-> bus.NewCommandBus/NewQueryBus/NewEventBus CQRS busy s middleware chain
-> server.New(handlers, middlewares) HTTP server
-> console.NewRootCommand() Cobra CLI
-> application.Run(ctx)
-> rootCmd.Execute(ctx) Cobra parsuje "serve" (ExecuteContext)
-> server.Start(cmd.Context()) Naslouchá na portu, drainuje při ctx.Done()
```
## Request flow (command)
`POST /api/v1/admin/users` -- vytvoření uživatele:
```
1. HTTP Request -> net/http ServeMux
2. HTTP Middleware (presentation/http/middleware/):
Trace -> Security headers -> CORS -> CSRF -> Logging -> JWT Auth (claims do context)
3. HTTP Handler (presentation/http/handler/):
json.Decode -> CreateUserCommand
bus.ExecVoid(ctx, commandBus, "CreateUser", cmd, fn)
4. Bus Middleware (application/bus/middleware/):
Recovery -> Logging -> Authorize -> DispatchEvents -> Transaction
|
|- Authorize: cmd.(Permissioned) -> PermissionChecker.Check()
|- DispatchEvents: vytvoří per-request EventCollector v ctx
|- Transaction: BEGIN
+-> handler:
5. Command Handler (application/user/command/):
NewNickname() -> NewRole() -> repo.FindByNickname() -> password.Hash()
-> NewUser() -> repo.Save()
-> shared.EventCollectorFromContext(ctx).Collect(UserCreated{...})
6. Bus post-handler:
Transaction -> COMMIT (nebo ROLLBACK při chybě)
DispatchEvents -> pokud commit OK, flush EventCollector -> EventBus.Dispatch (synchronně)
7. HTTP Handler: response.JSON(w, 201, nil)
```
## Request flow (query)
`GET /api/v1/admin/users`:
```
HTTP Request -> Trace -> Security headers -> CORS -> CSRF -> Logging -> JWT Auth
-> Handler -> bus.Exec[[]user.User](ctx, queryBus, "ListUsers", q, fn)
-> Recovery -> Logging -> Authorize -> Query Handler -> repo.FindAll()
-> response.JSON(w, 200, users)
```
## Error flow
```
Command Handler vrátí error
|
Bus: Transaction -> ROLLBACK -> err propaguje skrz DispatchEvents (eventy zahozeny)
|
HTTP Handler: response.HandleError(w, err)
-> ValidationError -> 400
-> AuthError -> 401
-> PermissionError -> 403
-> jiný error -> 500
```
## Detaily
### go-arch-lint konfigurace
Soubor `.go-arch-lint.yml` v kořeni projektu. Spuštění:
```bash
make arch-check # go-arch-lint se instaluje automaticky přes make install
```
Hlavní body konfigurace:
- `workdir: app` -- všechny cesty relativně k `app/`
- `commonComponents: [domain_shared]` -- pouze `domain/shared/` (sdílené typy a porty) je dostupná všem; bounded kontexty (`domain_user`, `domain_token`, ...) common **nejsou**
- `exclude: [infrastructure/di/**]` -- DI balíček nemá omezení
- `excludeFiles: [infrastructure/database/migration_manager.go]` -- lifecycle soubor mimo kontrolu
- Každá komponenta má `mayDependOn` seznam povolených závislostí
### Cross-domain izolace
Každý doménový kontext (`domain/user/`, `domain/token/`, ...) je izolovaný balíček. `domain/shared/` obsahuje sdílené typy (errors, interfaces, auth context). Pravidla:
- **Bounded context nesmí importovat jiný bounded context.** `domain/user/` nesmí importovat `domain/token/` a naopak.
- Komunikace mezi kontexty: **QueryBus** (synchronní) nebo **Domain Events** (asynchronní).
- Eventy používají jen primitivy (string ID, ne celé entity).
- go-arch-lint zachytí cross-domain import při `make arch-check`.
Nový kontext (např. `domain/order/`) **vyžaduje** vlastní komponentu v `.go-arch-lint.yml` -- právě to, že každý kontext je samostatná komponenta (a `domain/**` není jeden společný wildcard), je důvod, proč go-arch-lint cross-context import vůbec zachytí. Cenou za tu izolaci je explicitní zápis: přidat komponentu `domain_order`, povolit ji v `mayDependOn` u každého konzumenta (`application`, `sqlite_repos`, `testfx`, ...) a přidat `infrastructure/sqlite/order/**` do `sqlite_repos`. Naproti tomu broad-glob komponenty (`application/**`, `presentation/http/handler/**`) nové subbalíčky pokrývají automaticky.
### Přidání nové feature (checklist)
1. `domain/` -- entity, value objects, interfaces
2. `infrastructure/sqlite/` -- repository implementace
3. `application/<domain>/command/` nebo `application/<domain>/query/` -- CQRS handler s `Permissioned` nebo `SkipPermission`
4. `presentation/http/handler/` -- HTTP handler přes bus
5. `presentation/http/server/` -- registrace route
6. `infrastructure/di/` -- Wire provider
7. `make di && make arch-check`
---
[← Installation](/framework/overview/commands.md) | [Layers →](/framework/overview/layers.md)