- Add bearer token auth to internal MPC API (port 9800): /keygen, /keys,
/backup now require Authorization header. Token from MPC_INTERNAL_API_KEY
env (KMS-synced) or derived from Ed25519 node identity.
- Replace DualModeListener with TLSOnlyListener: plaintext peer connections
are rejected. TLS 1.3 with PQ key exchange is mandatory.
- Add dedicated 20 RPM rate limiter on bridge signing and intent signing
endpoints (separate from global 100 RPM).
- Add body size limit (1MB), read/write timeouts, and 10 RPM rate limiter
to internal MPC API server.
- Restrict K8s NetworkPolicy egress for MPC nodes to peers, postgres,
valkey, DNS, and HTTPS only (was unrestricted).
- Wire cluster-api-key in api-deployment for authenticated proxy to
internal MPC API. Forward as Authorization: Bearer header.
- Remove hardcoded dev JWT_SECRET default from compose.yml (now required).
- Add internal-api-key to KMSSecret CRD and StatefulSet env.
Bump hanzoai/base from v0.28.0 (broken module path) to v0.39.1
(correct module path). Removes the local development replace
directive so the module resolves from the Go module proxy.
db.New() auto-detects backend from DSN:
- "" or "sqlite://path" or "file.db" → SQLite (default)
- "postgres://..." → PostgreSQL (production upgrade)
KV (Valkey/Redis) is optional — pass "" to skip.
No postgres, no redis required to run mpcd out of the box.
Removed pgxpool direct dependency from db package.
MPC is generic infrastructure — no hardcoded tenant URLs.
- Remove pars.network, zoo.network from OIDC issuers, ingress, TLS
- Remove satschel.com, liquidity.io from CORS, WebAuthn, tests
- CORS/WebAuthn origins now env-driven: MPC_CORS_ORIGINS, MPC_WEBAUTHN_ORIGINS
- Ingress: mpc.lux.network only — tenants route through their own ingress
- Tests updated to match infrastructure-only origin lists
CheckKeyInAllNodes was assigning *badger.DB to kvstore.Store.DB which
requires database.Database — badger.DB is missing the Compact method.
The test only needs Get and Close, so use badger.View/txn.Get directly.
KMS routes now live inside MPC API server — one binary for both:
- POST /api/v1/keys/generate — create validator BLS + Ringtail keys
- GET /api/v1/keys — list all validator key sets
- GET /api/v1/keys/{id} — get validator key set
- POST /api/v1/keys/{id}/sign — sign with validator key
- POST /api/v1/keys/{id}/rotate — reshare validator keys
Storage: ORM (same postgres/ZapDB as MPC wallets).
No separate KMS binary needed — mpcd serves both.
- Remove pkg/bridge/ (btc_watcher + orchestrator) — bridge/opnet-watcher
is the single source of truth for chain watching per CTO directive
- Add Handler() to API server for mounting on Hanzo Base
- MPC is signing-only; bridge is the control plane
Add QEMU setup step before Buildx in both build-api and
build-dashboard jobs. Without QEMU, buildx cannot emulate
arm64 on amd64 runners, causing multi-platform builds to fail.
release.yml already had QEMU — this aligns deploy.yml.
Add MPC_WEBAUTHN_RP_ID and MPC_WEBAUTHN_ORIGINS env vars to make
WebAuthn relying party and origin allowlist configurable. Adds
Liquidity exchange origins (exchange.{dev,test,main}.satschel.com,
liquidity.io) to WebAuthn origin checks, CORS, and security tests.
Backup shard (shard 3) is encrypted with user's WebAuthn passkey
public key (P-256 ECDH). HSM stores the ciphertext but cannot
decrypt — only user's biometric (via Secure Enclave private key) can.
ATS shard (2) + encrypted_backup (3) = company CANNOT sign.
User shard (1) + passkey_decrypt(3) = user CAN exit independently.
Added UserPasskeyFingerprint to WalletBackup model.
Backup handler looks up user's WebAuthn credential for encryption.
EncryptedKVStore: AES-256-GCM wrapper over ZapDB for per-user shard encryption.
Each user's key shards encrypted with a unique DEK:
user DEK = HMAC-SHA256(masterKey, "mpc:shard:" + orgID + ":" + userID)
org DEK = HMAC-SHA256(masterKey, "mpc:org:" + orgID)
Three layers of MPC data protection:
1. ZapDB ChaCha20-Poly1305 (node-level, existing)
2. EncryptedKVStore AES-256-GCM (per-user, NEW)
3. API filter on createdBy (access control, NEW)
Even if ZapDB is fully dumped, individual users' shards are
independently encrypted. Wrong user key → decryption fails.
5 new tests: roundtrip, key uniqueness, wrong-key rejection,
empty values, org vs user key separation.
Three fixes:
1. OrgScopedKey sanitizes colons in orgID to prevent key injection
via the ":" separator (e.g. orgID "evil:org:fake" would create
ambiguous key paths).
2. All 5 keygen sessions (CGGMP21, FROST, BLS, SR25519, LSS) now
write key shares with OrgScopedKey(orgID, key) instead of bare
keys. Previously keygen wrote unscoped but signing read scoped,
causing key-not-found errors in multi-tenant deployments.
3. Added orgID field to session struct and threaded it through all
keygen constructors and Node.Create*KeyGenSession methods using
variadic orgID ...string for backward compatibility.
StatefulSets don't allow updating immutable spec fields with regular
kubectl apply. Use --server-side --force-conflicts to handle this,
falling back to --force if server-side apply isn't available.
Co-authored-by: Hanzo Dev <[email protected]>
The deploy step was failing with 'doctl: command not found' because
doctl isn't pre-installed on ubuntu-latest runners. Use the official
digitalocean/action-doctl@v2 action to install and authenticate.
Co-authored-by: Hanzo Dev <[email protected]>
Show HTTP status codes and error messages to diagnose
why the Universal Auth login or secrets fetch is failing.
Co-authored-by: Hanzo Dev <[email protected]>
Add GOEXPERIMENT=runtimesecret to Makefile, CI, and Dockerfile builds.
Wrap key share loading in all 5 signing session types with
withSecretErasure() so stack/register state containing raw share bytes
is zeroed after parsing. Build-tagged stub ensures everything compiles
without the experiment flag.
- Run goimports -w on all 17 Go files with formatting issues
- Set CGO_ENABLED=0 on all CI steps (test, lint, build, CodeQL, SBOM)
- Remove -race flag from tests (requires CGO which pulls in blst.h)
- All 17 test packages pass with CGO_ENABLED=0
Stale checksum for luxfi/[email protected] caused CI build failures.
Removed old entry, re-downloaded with correct hash.
Added .gcloudignore to exclude go.work, e2e/, and binaries from cloud builds.