Production-ready

The checklist the wallet and the ledger meet, and how they meet each item, with the page that builds it. Check your own gRPC services against it.

The wallet and the ledger meet each item. Check your own gRPC services against them:

ItemHowWhere
Every setting sourced and checked; a bad one exits 78, naming its variableconfig.Struct and the packages’ checks, in both servicesThe wallet’s settings, The ledger’s settings
No secret in the environment, the logs or the spansPostgreSQL’s password and the private keys are files, read through s.Host.FS. The token is metadata, which otelgrpc doesn’t record, and no handler logs it, which a test of the Apps checksThe secrets, as files, Their log records
Certificates and signing keys renewed without a restartinternal/certfile, for both servers’ certificates and the wallet’s client certificate. The key set is fetched again for a kid the wallet lacksThe certificates, read again when renewed, The fetched key set
Two replicas of each servicea PodDisruptionBudget of minAvailable: 1, and a rolling update of maxUnavailable: 0The Deployments, The disruption budgets
Ready once it has reached its dependency, and still ready through its outagesConnected, and the ledger’s latch on PostgreSQLReadiness: Connected, The ledger’s probes, Readiness
A rollout loses no callgrpcserver.Main’s 5s drain. A unary call is bounded by LEDGER_TIMEOUT, 10s, inside the 15s grace period. Watches end with Unavailable and are opened again. terminationGracePeriodSeconds is 30, above the drain, the grace period and the telemetry’s shutdownThe drain, Relaying the watch
Calls spread across podsMaxConnectionAge on both serversMaxConnectionAge
Money is never made or lostone transaction per transfer, locks in the order of the IDs, and a CHECK that no account but external goes below zeroschema.sql, A transfer’s transaction
A retry never moves money twiceevery transfer’s ID: the subject and the request’s IDWhy every transfer is safe to retry
The contract never breaks a callerbuf breaking against main, in CIbuf’s rules, buf generate
Least privilegethe ledger’s role has SELECT, INSERT and UPDATE on its two tables. Only the internal CA’s certificates call the ledger. A token can use only its subject’s account. A non-root, read-only container, with no service account tokenRunning it on kind, mTLS, grpcauth, The subject’s account, The Deployments
Observabletraces across both services, logs and metrics over OTLP, deploy/alerts.yaml, deploy/dashboard.json, and alerts on each Deployment from the Collector’s Kubernetes cluster receiverObserving
Failures say whystatuses with PreconditionFailure, BadRequest, ErrorInfo and RetryInfo detailsThe statuses, with details, The ledger’s answers, as the wallet’s, A key set that can’t be fetched
Failures are rehearsedthe failure injection cases, in CI and against staging through its own TargetThe shared cases, The failure injection cases
Safe by defaultFAULT_TRUST_SCOPE empty, so no scenario is trusted. Server reflection off. The probes ports serve gRPC health and nothing elseTrustScenario, The gRPC probes