Contents

Layers

LayerPathResponsibility
Domaininternal/domain/*Entity, value object, domain event, repository port
Applicationinternal/application/*Use case, DTO, orchestration, CQRS command/query
Adaptersinternal/adapters/{http,goui,persistence,shared}Fiber handler, GoUI, sqlc repo, shared adapter helpers
Infrastructureinternal/infrastructure/*Config, DB, JWT/Argon2/TOTP, SMTP, SMS, payment gateway, outbox, cache
Bootstrapinternal/bootstrap (Build + wire_*.go)Manual DI; composition root split across wiring files

Domain does not depend on application or outer layers. Application only references domain ports and its own DTOs.

Bounded contexts

ContextDomainApplicationNotes
Userdomain/userapplication/userCRUD, profile, soft-delete
Authdomain/authapplication/authToken, MFA, OAuth events
Authz / RBACdomain/rbacapplication/authzRole/permission aggregate; resolution in authz
Notificationdomain/notificationapplication/notificationDispatcher, inbox, bulk
Settingsdomain/settingsapplication/settingsActive SMS/payment provider
Paymentdomain/paymentapplication/payment3DS, transaction
Contactdomain/contactapplication/contactPublic form + admin inbox
Uploaddomain/uploadapplication/uploadSecure file upload
Auditapplication/auditNo domain aggregate; application service
Idempotency / Outboxapplication/{idempotency,outbox}Infrastructure-backed

Shared domain types: domain/shared.

pkg/ contracts

These are not domain; they are cross-cutting helper packages.

PackageUsage
pkg/rbacPerm* constants, Catalog, Checker — aggregate in domain/rbac, use cases in application/authz
pkg/recipientsCSV/XLSX recipient import (notification bulk) — distinct from contact form domain/contact
pkg/tabularList export (CSV/XLSX)
pkg/i18nLocale files (locales/tr.json, en.json)
pkg/validationgo-playground tag registration + field messages
pkg/paginationOffset/limit helpers
pkg/fieldencSensitive field encryption (payment card, etc.)

There is no pkg/user; user lives only under internal/domain/user.

Surfaces (adapters)

HTTP API — internal/adapters/http

  • Registration: server.go/api/v1/...
  • Handlers: handler/*.go
  • Middleware: auth, i18n, idempotency, permission

Summary groups:

  • Public: health, OpenAPI, contact submit, auth login/refresh/oauth, payment callback/webhook
  • Protected: /me, users, notifications send/bulk, rbac, settings, payments, audit, contacts, uploads

GoUI panel — internal/adapters/goui

  • Page routes: routes.gopageRoutes()
  • Controllers: controller_*.go
  • Export: export_routes.go
  • Utilities (OAuth, locale, 3DS start): utility_routes.go

Web session uses HttpOnly cookies; API uses Bearer JWT. Both call the same application use cases.

Example panel paths: /dashboard, /dashboard/users, /dashboard/notifications/bulk, /dashboard/payments/checkout, /dashboard/audit/logs.

Data

PiecePath
Migrationmigrations/000001_schema.*, 000002_seed.* (embed: migrations.go)
sqlc sourcedb/queries/*.sql
sqlc outputinternal/adapters/persistence/postgres/db/

During development the schema is kept in a single file (000001). After production launch, incremental migrations are added.

Notification flow (brief)

  1. Use case → Dispatcher (channel: inapp | sms | email)
  2. Recipient resolution: user ID, email, phone, or pkg/recipients parse
  3. In-app: DB record + inbox.updated over /api/v1/ws (panel/mobile/API)
  4. SMS/email: active provider (settings) + worker/async

Related documentation