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_logsrow 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 |