Skip to content

Service packages

Implemented

Source: packages/services/* + packages/shared/*

Domain services

12 packages under packages/services/, each owning its own database tables (no cross-service direct joins; cross-domain data flows through NATS events or explicit API calls).

flowchart LR
    classDef pkg fill:#e8f5e9,stroke:#2e7d32

    subgraph Identity
        auth["auth<br/>OIDC exchange<br/>JWT issuance<br/>session mgmt"]:::pkg
    end

    subgraph Capacity
        inv["inventory<br/>SKUs, nodes,<br/>marketplace,<br/>resource slots"]:::pkg
        prov["provisioning<br/>orchestrator (placement) +<br/>worker (Temporal activities)"]:::pkg
        maas["maas<br/>bare-metal MAAS client +<br/>state mapping"]:::pkg
        rel["releases<br/>SSH key release +<br/>access mint"]:::pkg
    end

    subgraph Money
        bill["billing<br/>usage metering,<br/>ledger debits,<br/>balance"]:::pkg
        pay["payments<br/>Stripe checkout,<br/>webhook verify,<br/>ledger credits"]:::pkg
    end

    subgraph Sessions
        term["terminal<br/>WS terminal primitives,<br/>token validation"]:::pkg
        appr["appruntime<br/>app lifecycle"]:::pkg
        stor["storage<br/>S3 ops,<br/>path safety"]:::pkg
    end

    subgraph Operations
        admin["admin<br/>users, nodes, audit,<br/>refunds"]:::pkg
        notif["notification<br/>WS + email"]:::pkg
    end
Package Tables (owned) Key responsibilities
auth oidc_sessions, user_posix_identities, service_account_* Token exchange, JWT verify, refresh, dev/internal login
inventory sku_catalog, nodes, node_resource_slots, os_images, node_image_cache SKU catalog, node lifecycle, slot map, image catalog
provisioning allocations, allocation_resource_claims, allocation_placements, outbox_intents Placement (orchestrator), Temporal activities (worker)
billing usage_records, ledger_entries, low_balance_events Accrual, ledger, balance compute, force-release trigger
payments payment_sessions, ledger credit rows Stripe checkout, webhook signature, refund hybrid policy
terminal (Redis: terminal_token:*) Token mint, session binding, stream relay primitives
appruntime app_instances, app_instance_members, app_instance_events, app_manifests App lifecycle: launch/run/stop/release
storage storage_objects, storage_namespaces Object-storage CRUD, path traversal protection
admin audit_logs, refund records Cross-user views, force-release, audit query/export
notification (Redis pub/sub channels) WS + email fan-out from NATS events
releases allocation_ssh_public_keys SSH public key registration for allocations
maas (none — facade over MAAS API) Bare-metal commission/deploy/release

Shared packages

9 cross-cutting libraries under packages/shared/ consumed by every binary.

Package Purpose
errors ErrorResponse envelope + ErrCode catalog (token_, validation_error, allocation_, etc.)
events NATS client, typed event structs, InitStreams() for stream/consumer setup
middleware Auth (JWKS), rate-limit, PII scrubber (Sanitize), OTel tracing, correlation-id
outbox Outbox claim/publish/retry primitives consumed by cmd/outbox-relay
policy PolicyClient reading policy_values rows — no hardcoded business constants
pki CAClient interface for step-ca today, Vault PKI migration path
crypto Hashing, key gen helpers (no roll-your-own; wraps crypto/*)
db pgxpool wrappers, retry helpers, transaction patterns
rdb Redis helpers (rate-limit, cache, terminal tokens)
vault Vault KV reader (where used)
readcache Read-model cache (see UI_Read_Model_Cache_Architecture_v1.md)
storagepath Path-safety enforcement for object storage operations
authz Centralized role/policy decisions; scope-aware (global → tenant → project)
buildinfo Build version stamping for OTel + /api/v1/buildinfo
gen/openapigen Auto-generated OpenAPI types — used only at HTTP boundaries

Boundary rules

These are enforced by review and CI gates, not by the type system:

flowchart LR
    HANDLER[HTTP handler] -->|sanitize first,<br/>then map to domain types| SVC[Service function]
    SVC -->|owns only its own tables| DB[(Postgres)]
    SVC -->|writes outbox row in same tx| OB[(outbox_events)]
    SVC -.never publishes directly.-> NATS[(NATS)]
    OR[outbox-relay] --> NATS
    SVC --> AUDIT[(audit_logs)]
  • DB access boundary: each service queries only its own domain tables. No cross-domain direct joins.
  • No direct NATS publish from handlers: domain change + outbox row in one transaction; relay publishes.
  • Sanitize first: every log line / trace span passes through middleware.Sanitize() before emission.
  • Idempotent mutations: all POST/PUT/PATCH safe to retry with the same X-Idempotency-Key. Exception: terminal token mint (single-use by design).
  • Immutable ledger: never UPDATE or DELETE ledger_entries; corrections are new entries. No direct balance column — balance always computed.
  • No query-string tokens: auth material never in URL params; browser WS uses Sec-WebSocket-Protocol.
  • Audit required: every privileged mutation writes an audit_logs row with actor, role, action, target, result, correlation_id.

Where to look next

Question Page
How do these services route incoming requests? Runtime binaries → cmd/api
Which events flow between services? Outbox & event flow
What's the actual schema? Database schema
How do I add a new endpoint or event? Contract workflow