Skip to content

Coding patterns

Implemented

Source: doc/governance/Coding_Standards.md (353 lines)

The standard handler shape

func (h *Handler) CreateAllocation(w http.ResponseWriter, r *http.Request) {
    // 1) correlation + claims at the TOP
    ctx := r.Context()
    corrID := middleware.CorrelationIDFrom(ctx)
    claims, ok := middleware.ClaimsFrom(ctx)
    if !ok {
        h.writeErr(ctx, w, corrID, errors.NewToken("token_missing"))
        return
    }

    // 2) decode + sanitize input
    var in apigen.CreateAllocationRequest
    if err := json.NewDecoder(r.Body).Decode(&in); err != nil {
        h.writeErr(ctx, w, corrID, errors.NewValidation("invalid_request", err))
        return
    }

    // 3) map to domain type at the boundary
    domain := mapping.AllocationCreateFromAPI(in)
    domain.RequestedBy = claims.UserID
    domain.OrgID = claims.OrgID

    // 4) call service — NO HTTP types below this line
    alloc, err := h.alloc.CreateRequested(ctx, domain)
    if err != nil {
        h.writeErr(ctx, w, corrID, err) // mapping in writeErr — sentinel → http code
        return
    }

    // 5) sanitize output
    out := mapping.AllocationToAPI(alloc)
    middleware.Sanitize(&out)

    // 6) respond
    h.writeJSON(w, http.StatusCreated, out)
}

The standard service function shape

// Service function — no HTTP types here.
func (s *Service) CreateRequested(ctx context.Context, in CreateRequestedInput) (*Allocation, error) {
    tx, err := s.db.Begin(ctx)
    if err != nil {
        return nil, err
    }
    defer tx.Rollback(ctx)

    // 1) reserve placement (sentinel errors mapped at boundary)
    nodeID, slotIDs, err := s.reservePlacement(ctx, tx, in)
    if err != nil {
        return nil, err // ErrSKUUnavailable, etc.
    }

    // 2) insert allocation
    alloc, err := s.insertAllocation(ctx, tx, in, nodeID, slotIDs)
    if err != nil {
        return nil, err
    }

    // 3) outbox row IN SAME TX
    if err := s.outbox.Insert(ctx, tx, outbox.Row{
        EventType:     "provisioning.requested",
        Subject:       "provisioning.requested",
        CorrelationID: middleware.CorrelationIDFrom(ctx),
        Envelope:      envelope(alloc),
    }); err != nil {
        return nil, err
    }

    // 4) audit row IN SAME TX
    if err := s.audit.Write(ctx, tx, audit.Row{
        ActorUserID:   in.RequestedBy,
        ActorRole:     "user",
        Action:        "allocation.create",
        TargetType:    "allocation",
        TargetID:      alloc.ID,
        Result:        "success",
        CorrelationID: middleware.CorrelationIDFrom(ctx),
    }); err != nil {
        return nil, err
    }

    if err := tx.Commit(ctx); err != nil {
        return nil, err
    }
    return alloc, nil
}

Mandatory rules

mindmap
  root((Mandatory rules))
    Contract-first
      Edit OpenAPI/AsyncAPI before code
      Domain fragments where migrated
    Idempotent mutations
      X-Idempotency-Key
      Exception: terminal token mint
    No hardcoded policy
      policy.Client only
      Test-only constants OK
    Sanitize first
      Middleware.Sanitize before log/trace
      REDACTED never omitted
    Immutable ledger
      No UPDATE / DELETE on ledger
      Corrections are new entries
      No balance column
    Outbox required
      Domain change + outbox in 1 tx
      Never NATS-publish from handler
    Raw body for Stripe
      Buffer before parse
      Signature on exact bytes
    No query-string tokens
      Auth never in URL
      WS uses Sec-WebSocket-Protocol
    Audit required
      Every privileged mutation
      actor, role, action, target, result, corrID
    DB access boundaries
      Service queries only its tables
      Cross-domain via events / API
    CI portability
      Logic in scripts/ci
      YAML is wrapper only
    Root-cause-first
      No symptom-only fixes
      Mark blocked if upstream
    Postgres typing
      ::text ::int ::uuid casts
      Test against real PG
    5xx classification
      Upstream vs local defect
      Regression test required

Numbered rules from Coding_Standards.md

  1. Contract-first — every API/event change starts in doc/api/.
  2. Idempotent mutations — all POST/PUT/PATCH safe with same X-Idempotency-Key. Exception: terminal token mint.
  3. No hardcoded business policy constants — billing thresholds, rate limits, refund windows from PolicyClient, not literals.
  4. Sanitize firstmiddleware.Sanitize() before any log/trace.
  5. Immutable ledger — never UPDATE/DELETE ledger_entries. Corrections are new entries.
  6. Outbox for events — domain change + outbox in same tx. Never publish to NATS from a handler.
  7. Stripe raw-body-first — buffer raw body before JSON parse.
  8. No query-string tokens — auth material never in URL params.
  9. Audit required — every privileged mutation writes audit_logs.
  10. DB access boundaries — each service queries only its own tables.
    • 10a. API-first ops verification — use admin/read-model APIs; direct SQL only temporarily.
  11. CI portability — gate logic in scripts/ci/*.sh; YAML is wrapper.
  12. Root-cause ownership — no symptom-only fixes. Mark blocked if upstream.
  13. Postgres polymorphic typing — explicit ::text/::int/::uuid casts on bind params.
  14. 5xx classification gate — every new 5xx path classified upstream vs local; add regression test.

Naming + structure

Thing Pattern
Service struct type Service struct { db, log, policy, audit, outbox … }
Handler struct type Handler struct { svc, ... }
Sentinel errors var ErrSKUUnavailable = errors.New("sku unavailable")
API → domain mapping packages/services/<svc>/mapping/
Sanitize blocklist maintained in packages/shared/middleware/sanitize.go

Where to look next