fix(security): JWT require env, remove *** token, WS auth disabled
fix(automation): implement all 6 actions + real cron parser fix(db): pq.Array for TEXT[], add sqlmock tests fix(schema): single source migrations docs: v2 architecture + frontend refactor proposals
This commit is contained in:
@@ -0,0 +1,173 @@
|
||||
# BOC v2 — Architecture Proposal
|
||||
|
||||
## Nuvarande Problem (v1.0)
|
||||
- 13K rader Go i ett enda monolit-paket
|
||||
- 20 handlers i samma package, delar `*sql.DB`
|
||||
- Ingen repository pattern — SQL direkt i handlers
|
||||
- Ingen service layer — affärslogik i HTTP-handlers
|
||||
- Ledger-integration är en pass-through proxy
|
||||
- Ingen event sourcing trots Kafka-definitioner
|
||||
- Frontend: 12 HTML-filer med copy-paste
|
||||
|
||||
## V2 Vision: Clean Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ Transport (HTTP / WebSocket / CLI) │
|
||||
│ - handlers/ chi routers │
|
||||
│ - middleware/ auth, cors, rate │
|
||||
│ - dto/ request/response │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Application (Use Cases) │
|
||||
│ - services/ business logic │
|
||||
│ - commands/ CQRS write │
|
||||
│ - queries/ CQRS read │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Domain (Core Business) │
|
||||
│ - models/ entities, value obj │
|
||||
│ - events/ domain events │
|
||||
│ - repositories/ interfaces │
|
||||
├─────────────────────────────────────────┤
|
||||
│ Infrastructure │
|
||||
│ - db/ PostgreSQL impl │
|
||||
│ - cache/ Redis impl │
|
||||
│ - events/ Kafka impl │
|
||||
│ - email/ Resend impl │
|
||||
│ - pdf/ gofpdf impl │
|
||||
│ - ledger/ aamos-ledger client │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## V2 Förändringar
|
||||
|
||||
### 1. Repository Pattern
|
||||
```go
|
||||
// domain/repositories/customer.go
|
||||
type CustomerRepository interface {
|
||||
FindByID(ctx context.Context, id uuid.UUID) (*models.Customer, error)
|
||||
FindByTenant(ctx context.Context, tenantID uuid.UUID, opts ListOptions) ([]*models.Customer, error)
|
||||
Create(ctx context.Context, c *models.Customer) error
|
||||
Update(ctx context.Context, c *models.Customer) error
|
||||
Delete(ctx context.Context, id uuid.UUID) error
|
||||
}
|
||||
|
||||
// infrastructure/db/customer_repo.go
|
||||
type PostgresCustomerRepo struct { db *sql.DB }
|
||||
```
|
||||
|
||||
### 2. Service Layer (Transactions)
|
||||
```go
|
||||
// application/services/quote_service.go
|
||||
func (s *QuoteService) ConvertToOrder(ctx context.Context, quoteID uuid.UUID) (*models.Order, error) {
|
||||
return s.db.WithTx(ctx, func(tx *sql.Tx) error {
|
||||
quote, err := s.quotes.FindByIDTx(ctx, tx, quoteID)
|
||||
if err != nil { return err }
|
||||
|
||||
order := quote.ToOrder()
|
||||
if err := s.orders.CreateTx(ctx, tx, order); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
quote.Status = models.QuoteConverted
|
||||
return s.quotes.UpdateTx(ctx, tx, quote)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Domain Events (Kafka aktiverad)
|
||||
```go
|
||||
// domain/events/customer_events.go
|
||||
type CustomerCreated struct {
|
||||
CustomerID uuid.UUID
|
||||
TenantID uuid.UUID
|
||||
Email string
|
||||
}
|
||||
|
||||
// application/event_publisher.go
|
||||
func (p *KafkaPublisher) Publish(ctx context.Context, event domain.Event) error {
|
||||
// Actually uses Kafka now, not just defined
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Ledger Integration med Circuit Breaker
|
||||
```go
|
||||
// infrastructure/ledger/client.go
|
||||
type LedgerClient struct {
|
||||
baseURL string
|
||||
httpClient *http.Client
|
||||
circuitBreaker *gobreaker.CircuitBreaker
|
||||
cache cache.Cache
|
||||
}
|
||||
|
||||
func (c *LedgerClient) GetBalanceSheet(ctx context.Context) (*BalanceSheet, error) {
|
||||
// Cache-first, circuit breaker, fallback to stale data
|
||||
}
|
||||
```
|
||||
|
||||
### 5. CQRS för Analytics
|
||||
```go
|
||||
// application/queries/dashboard_query.go
|
||||
type DashboardQuery struct {
|
||||
readDB *sql.DB // Read replica or materialized view
|
||||
}
|
||||
|
||||
func (q *DashboardQuery) GetKPIs(ctx context.Context, tenantID uuid.UUID) (*KPIs, error) {
|
||||
// Optimized read query, no business logic
|
||||
}
|
||||
```
|
||||
|
||||
## V2 Teknisk Stack
|
||||
|
||||
| Komponent | Nu | V2 |
|
||||
|-----------|-----|-----|
|
||||
| Router | chi | chi (behåll) |
|
||||
| DB | database/sql | sqlx eller pgx |
|
||||
| Migrations | custom | golang-migrate |
|
||||
| Validation | manual | go-playground/validator |
|
||||
| Testing | testify | testify + sqlmock + dockertest |
|
||||
| Events | Kafka stub | Kafka aktiverad |
|
||||
| Cache | Redis wrapper | Redis + cache-aside pattern |
|
||||
| Frontend | 12 HTML | Vanilla JS SPA (se FRONTEND_REFACTOR_PROPOSAL.md) |
|
||||
|
||||
## V2 Migreringsplan
|
||||
|
||||
### Fas 1: Foundation (1 vecka)
|
||||
1. Refactor till Clean Architecture packages
|
||||
2. Implementera Repository pattern för CRM + Sales
|
||||
3. Lägg till service layer med transaktioner
|
||||
4. Riktiga integrationstester med dockertest
|
||||
|
||||
### Fas 2: Events + Cache (1 vecka)
|
||||
1. Aktivera Kafka publishing från services
|
||||
2. Implementera cache-aside för analytics
|
||||
3. Circuit breaker för ledger
|
||||
|
||||
### Fas 3: Frontend (3 dagar)
|
||||
1. Vanilla JS SPA shell
|
||||
2. Konvertera moduler en i taget
|
||||
3. Ta bort gamla HTML-filer
|
||||
|
||||
### Fas 4: Polish (2 dagar)
|
||||
1. OpenAPI/Swagger docs
|
||||
2. Health checks för alla dependencies
|
||||
3. Metrics (Prometheus)
|
||||
4. Structured logging med trace IDs
|
||||
|
||||
## V2 "Inte Nu"
|
||||
- GraphQL (YAGNI)
|
||||
- Microservices (för tidigt)
|
||||
- Kubernetes operators (overkill)
|
||||
- React/Vue (för tungt)
|
||||
|
||||
## Sammanfattning
|
||||
|
||||
V2 handlar inte om nya features. V2 handlar om att **det vi har faktiskt fungerar pålitligt**.
|
||||
|
||||
Nuvarande v1.0 är en demo som ser komplett ut men har:
|
||||
- Säkerhetshål (fixade idag)
|
||||
- Tysta databasfel (fixade idag)
|
||||
- Ingen transaktionssäkerhet
|
||||
- Död kod (Rust, C, Kafka)
|
||||
- Noll testtäckning
|
||||
|
||||
V2 = produktionsklar.
|
||||
Reference in New Issue
Block a user