Commit Graph
17 Commits
Author SHA1 Message Date
zeekay 324b88fa8b feat(mpc): treasury 3-of-5 + purge Postgres, SQLite-only
- Postgres purge: delete cas_postgres_test.go, strip PG sidecar from CI
- Treasury 3-of-5 governance: pkg/api/handlers_treasury.go + models
- Routes: POST /v1/mpc/treasury/wallets, POST /v1/mpc/treasury/sign,
  GET /v1/mpc/treasury/wallets/{id}
- Per-org HSM isolation via tenant-scoped cosigner key
- Threshold escalation: small=3-of-5, large=4-of-5
2025-12-28 11:29:17 -08:00
zeekay cc52b14802 fix(mpc): R2-1/R2-2 — webauthn verification + CAS under Postgres
R2-1: biometric enrollment is a forged-enrollment oracle fixed.
- pkg/webauthn/verify.go: full WebAuthn verification — compare against the
  random challenge bytes we issued (not the DB row ID), origin allowlist,
  rpIDHash equality, UP+UV authenticator-flag enforcement, ceremony type.
- pkg/webauthn/liveness.go: SecureGate-signed liveness attestation. Ed25519
  envelope over {providerId, userId, score, timestamp, nonce}. MPC verifies
  against MPC_SECUREGATE_PUBKEY_ED25519 and enforces userId match, score
  floor, max age. Body-supplied livenessScore is never trusted again.
- If SecureGate pubkey is unconfigured, handleBiometricEnroll returns 503.
- 14 new tests cover each rejection path.

R2-2: CAS-under-Postgres. The previous in-Go check-then-write +
unconditional UPSERT works on SQLite (writeMu) but loses updates under
Postgres READ COMMITTED. Switched to SELECT ... FOR UPDATE inside READ
COMMITTED tx via orm.RunInTransactionWith + orm.GetForUpdate[T]. Requires
hanzoai/[email protected] (tagged today).
- Session consume: operationLimit strictly respected under concurrency;
  valueAccum computed under the lock.
- Operation approve: ApprovedBy append under the row lock, quorum
  finalization transitions at most once even under racing approvers.
- pkg/db.New now supports postgres:// DSNs.
- New Postgres-backed regression tests in cas_postgres_test.go —
  auto-skipped when no TEST_PG_DSN reachable; 10 concurrent consumers
  against operationLimit=5 yields exactly 5 successes and 5 denials.

Bumps github.com/hanzoai/orm v0.3.2 → v0.4.0.

Test plan:
  go test -tags sqlite_json1 -count=10 \
    -run 'CASUnderRace|CASUnderRace_Postgres|RequireRoleOrAPIPermission' \
    ./pkg/api/ ./pkg/webauthn/
2025-12-28 10:49:33 -08:00
zeekay 8e644b8fe3 fix(mpc): F1/F4/F5/F6/F14/F15/F22 — harden /v1/mpc/sign + biometric + default wallet
- F1: /v1/mpc/sign now requires sessionId (403 without). Same for
  settlement/sign. No silent auto-session selection in handlers.
- F15: /v1/mpc/sign now gated by requireRole("owner","admin","signer","api")
  to match /v1/mpc/settlement/sign.
- F6: decodeMessage is strict — returns error when the declared encoding
  does not parse. Removed the raw-string fallback that made the endpoint
  an arbitrary-bytes signing oracle.
- F4: /v1/mpc/balances/{address} now resolves the address against the
  caller's org (ETH/BTC/SOL columns). Unknown or cross-tenant address
  returns 404 — no more "empty balances" leak.
- F5: biometric enroll requires a server-issued challenge, signed
  attestation (P-256 ECDSA verify), and a SecureGate liveness score
  above 0.8 (PAD-2). Raw templates are no longer accepted. Added
  consumeBiometricChallenge + verifyBiometricAttestation helpers.
- F14: added Wallet.DefaultForUserID column; handleMpcSetDefaultWallet
  now writes to it instead of stuffing a "default:<userID>" sentinel
  into the user-facing Name field. Previous default (if any) is cleared
  atomically per (orgId, userId).
- F22: findDefaultWalletID reads the new is_default column (via
  defaultForUserId) — no more "most recently created wallet" fallback
  that produced non-deterministic behavior.
2025-12-28 10:23:04 -08:00
zeekay da6efbd5bc feat(api): /v1/mpc/* spec surface (wallets, sessions, operations, policies, audit)
Implement the canonical Liquidity MPC surface frozen in
openapi/mpc.yaml. All endpoints mount under /v1/mpc/* — one and only
one path per operation, no aliases, no backwards compatibility.

New:
- handlers_mpc.go — wallets, balances, default wallet, sign,
  settlement/sign, webauthn/biometric spec shapes
- handlers_sessions.go — time-bounded signing grants with operation
  and value limits, enforced on every /sign via consumeSessionForSign
- handlers_operations.go — unified Operation view over db.Transaction
  with kind ∈ {sign,send,mint,burn,transfer,contract_call}

Changed:
- server.go: mount r.Route("/mpc", …); remove top-level /v1/policies
  and /v1/audit (moved to /v1/mpc/policies, /v1/mpc/audit); retain
  /v1/transactions POST as internal wiring
- handlers_policy.go: accept both {id} (internal) and {policyId} (spec)
- pkg/db/models.go: add Session model (registered as "mpc-session")
2025-12-28 10:09:49 -08:00
zeekay 847ddebc2e fix: remove postgres/valkey/legacy mode — consensus+ZapDB only
- Removed --mode, --api-db, --api-kv, --db flags
- Removed legacy NATS/Consul transport (runNode, ~200 lines)
- Removed standalone API server (runAPIOnly, ~200 lines)
- Removed Consul helpers, NATS connection, interactive prompts
- Dashboard now uses ZapDB (SQLite) instead of postgres
- pkg/db: removed postgres backend, removed valkey client
- Consensus mode is the only mode. Zero external deps.
2025-12-28 06:18:03 -08:00
zeekay 55a6d85e10 feat: SQLite default — zero external deps to start
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.
2025-12-28 02:26:17 -08:00
zeekay 4e915d77c3 security: fix 15 custody audit findings, add regression + fuzz tests
Fixes all findings from the Blue Team defensive security review of the
redacted → redacted custody architecture transition.

HIGH:
- S-1: Implement P-256 ECDH + AES-256-GCM encryption of passkey backup shards
- W-2: Reject unparseable WebAuthn public keys (was silently skipping verification)
- O-1: Add Ed25519 binary signature verification package (pkg/integrity)

MEDIUM:
- W-1: Validate attestation is a real P-256 curve point, not raw attestation object
- W-3: Add origin validation to all WebAuthn flows (register, verify, trade approve)
- N-2: Remove plaintext TCP fallback from MPC node transport (TLS mandatory)
- K-1: Fail-closed on empty/whitespace orgID (prevents cross-tenant key leakage)
- A-1: Make AuditEntry immutable (Update/Delete return error)
- A-2: Add MPC-level signing audit log (wallet, message hash, intent, trigger)
- O-3: Invalidate backup shards after key reshare (stale shares are useless)
- O-2: Reject env/file password providers in production (require cloud HSM)

LOW:
- T-1: Add error handling + MarkSignFailed to signing goroutine
- T-2: Verify caller authorization in handleTradeSubmit
- K-2: Secret erasure stub now calls runtime.GC() instead of no-op
- N-1: Add VerifyConnection callback to reject peers without TLS certs

Tests: 69 unit + 7 fuzz targets, ~900K fuzz executions, 19/19 packages green.
Makefile: add -tags json1 for SQLite JSON function support in ORM tests.
2025-12-28 01:00:12 -08:00
zeekay 21fc7ef1c2 feat: passkey-encrypted backup shard — company CANNOT decrypt
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.
2025-12-28 00:53:34 -08:00
zeekay 49e96324c8 feat: add biometric trade approval flow with push notifications
- Trade approval service: submit, approve (WebAuthn), reject, pending
- Push notifier: APNS (iOS) + FCM (Android) for trade approval requests
- Biometric verification: Face ID/Touch ID with 30s freshness, nonce replay guard
- Custody policy engine: KYC/AML/sanctions/limits checks before co-signing
- Device store: register/revoke mobile devices with Secure Enclave keys
- API routes: POST /api/v1/trade/{submit,approve,reject}, GET pending
- Trade expiry reaper: cleanup expired approvals (>5 min)
- 17 custody tests + 33 API tests passing
2025-12-28 00:46:57 -08:00
zeekay 3954d11f50 fix: goimports formatting + CGO_ENABLED=0 for CI tests
- 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
2025-12-27 23:01:00 -08:00
zeekay a42050c830 feat: tx lifecycle tracking, Shamir backup sharding, settlement engine
Transaction Lifecycle ("did the tx land?"):
- TxTracker polls eth_getTransactionReceipt for block inclusion
- Receipt fields: blockNumber, blockHash, receiptStatus, gasUsed, revertReason
- Confirmation counter with configurable target (default 12)
- StatusHistory records every state transition with timestamp and actor
- Stuck/dropped tx detection with webhook alerts

Backup Key Sharding (Secure Recovery Flow):
- GF(2^8) Shamir Secret Sharing (ShamirSplit/ShamirCombine)
- WalletBackup: AES-256-GCM encrypt key share, Shamir-split the key
- Labeled shard destinations: icloud, hsm, offline, custody, device
- Default 2-of-2 (iCloud + Platform HSM), institutional 3-of-5

Settlement & Intent Engine:
- Intent lifecycle: pending_sign → signed → co_signed → recorded → matched
- HSM co-signing as second signer in multisig flow
- Settlement with HSM multisig attestation collection
- TransferAgency hash registration and verification
- WalletBackup, Intent, Settlement DB models

API Routes:
- POST/GET /intents, /intents/:id/sign, /intents/:id/co-sign
- GET /settlements, /settlements/:id
- POST/GET /wallets/:id/backup
- New webhooks: tx.included, tx.finalized, tx.reverted, intent.*

40 tests passing across backup, settlement, txtracker, api packages.
2025-12-27 18:09:37 -08:00
zeekay 0e3349fdc4 feat: bridge admin dashboard, WebAuthn device management, LSS protocol selection
- Bridge admin pages: /bridge (overview), /bridge/wallets (signing wallet
  selector), /bridge/fees (fee config), /bridge/contracts (BRIDGE_ROLE mgmt)
- Bridge config API: GET/PATCH /api/v1/bridge/config, GET /bridge/networks
- BridgeConfig model in DB (org-scoped, stores wallet ID, fees, toggles)
- WebAuthn device management: /settings/devices (register/delete devices)
- Biometric approve button on transaction detail page using WebAuthn API
- Dashboard lib/webauthn.ts with startRegistration, startAuthentication
- Protocol selection in wallet creation wizard (CGGMP21, LSS, FROST)
- Protocol field on Wallet model, validation in create handler
- Wallet detail page shows protocol type
- Bridge nav link in sidebar
2025-12-27 12:12:02 -08:00
zeekay be54888298 feat: WebAuthn biometric signing, enforce approver roles in policies
- Add WebAuthn/FIDO2 registration and verification endpoints
  POST /webauthn/register/begin, /register/complete, /verify
- Biometric approval: Face ID/Touch ID/YubiKey approve transactions
- Challenge bound to transaction ID (SHA256) preventing replay
- Enforce ApproverRoles from policy engine during transaction approval
- Add WebAuthnCredential DB model (pending_registration, active, revoked)
- Policy decisions now carry ApproverRoles for role-gated approvals
2025-12-27 11:52:10 -08:00
zeekay ced778a524 fix(ci): goimports formatting, no-panic logger test, remove unconvert
- goimports -w on all pkg/api, pkg/db, cmd/mpcd files
- TestError_PanicsOnOddKeyValues → TestError_OddKeyValuesLogsWarning
  (logger was intentionally changed to warn+sentinel instead of panic)
- int(threshold) → threshold (threshold is already int from c.Int())
2025-12-27 16:36:55 -08:00
zeekay ab93c012ae feat: API key permissions in context, clean up stale files
- validateAPIKey returns *db.APIKey so middleware has access to permissions
- API key permissions propagated into request context via ctxPermissions
- requirePermission middleware checks actual key permissions (not just role)
- PasswordHash/MFASecret fields marked api:"-" to prevent serialization
- Remove stale generated files (CHANGELOG, CI_STATUS, DOCKER_BUILD etc.)
- Update LLM.md with production deployment state and architecture decisions
2025-12-27 15:43:56 -08:00
zeekay 7fd512051e feat: replace BadgerDB with ZapDB, remove local replace directives, vendor mode CI/CD
- Replace github.com/dgraph-io/badger/v4 with github.com/luxfi/zapdb/v4 v4.9.2
  throughout pkg/kvstore/, pkg/transport/, cmd/mpcd/, e2e/, scripts/
- Rename BadgerPath/BadgerPassword → ZapDBPath/ZapDBPassword in FactoryConfig
- Remove local replace directives from go.mod:
  - hanzoai/orm: now uses published v0.3.2 (tagged on GitHub)
  - hanzoai/kv-go/v9: now uses published v9.17.2-hanzo.1
  - Only remaining replace: agl/ed25519 → luxfi/edwards25519
- Add vendor/ directory (GOWORK=off go mod vendor) for reproducible builds
- Update Dockerfile to golang:1.26-alpine + -mod=vendor build flag
- Update CI/CD to use self-hosted linux/amd64 runners (no cross-compilation)
- Add k8s/valkey.yaml for session KV store
- Update k8s manifests: api-kv support, ZapDB password env, fresh secrets
- Dashboard API and MPC nodes all tested running on cluster (3/3 nodes healthy)
2025-12-27 15:30:42 -08:00
zeekay 6b38df60a4 feat: MPC wallet dashboard - full-stack implementation
Complete MPC wallet management platform rivaling Fireblocks/Utila/Fordefi:

Backend (Go):
- REST API with 60+ endpoints on chi router (pkg/api/)
- PostgreSQL schema with 13 tables (pkg/db/)
- JWT + MFA auth, bcrypt passwords, API key management
- Policy engine (deny/approve/require_approval)
- Transaction signing flow with approval workflow
- Subscription scheduler for recurring payments
- Payment requests with public pay pages
- Safe + ERC-4337 smart wallet integration (pkg/smart/)
- Rate limiting, webhook delivery (HMAC-SHA256), audit logging
- 27 passing tests (auth, policy engine, middleware)

Frontend (Next.js 14):
- 27 routes with monochrome dark theme (Tailwind + Geist fonts)
- Full API client with JWT auto-refresh
- React Query hooks for all resources
- Pages: dashboard, vaults, wallets, transactions, policies,
  whitelist, team, settings, API keys, webhooks, audit,
  subscriptions, payments, smart wallets

Infrastructure:
- Dockerfiles for API (Go) and dashboard (Next.js standalone)
- compose.yml for local development (PostgreSQL + API + dashboard)
- K8s manifests for mpc.lux.network + cloud.lux.network
- GitHub Actions deploy workflow (build → push GHCR → kubectl apply)
- TLS via cert-manager, Traefik IngressRoute for both domains
2025-12-27 13:11:38 -08:00