Commit Graph
85 Commits
Author SHA1 Message Date
zeekay a99d4b42e8 fix: webhook retry test — assert 2+ attempts (timing-safe) 2026-04-07 15:28:23 -07:00
zeekay e57d388cfd feat: webhook infrastructure — 16 BD events, HMAC delivery, routes, store 2026-04-07 15:10:25 -07:00
zeekay 3972925c18 feat: auto-register Kraken and Gemini in public-data mode for local dev
When ENVIRONMENT=local or ENABLE_PUBLIC_DATA is set, register Kraken
and Gemini without API keys. Their public endpoints provide real-time
crypto prices without authentication.
2026-04-06 20:35:37 -07:00
zeekay bf09f371b2 fix: red team findings — 5 critical + 3 high from Alpaca sign-off review
C1: queryCountryInfos endpoint typo (-1 suffix removed)
C2: ValidateTIF wired into CreateOrder (was dead code)
C3: GetFixedIncomeQuote returns honest error (Moment ToS required)
C4: Agreement signing uses real client IP (was 0.0.0.0)
C5: Overnight trading uses America/New_York timezone (was UTC-4)
H1: Background asset sync goroutine (1-hour ticker)
H2: ACATS disclosure API endpoint
H3: Crypto $200K aggregate limit on split plans
2026-04-06 15:53:47 -07:00
zeekay 986666f8b1 feat: complete Alpaca sign-off — ACATS, Fixed Income, Crypto, Omnibus
ACATS (7/7 items):
- ValidateACATSAccount/Assets, CreateACATSTransfer, GetACATSTransfer
- ListACATSTransfers, CancelACATSTransfer, ListACATSActivities
- GetACATSRejection, ACATSDisclosure constant
- 13 tests with subtests covering all validation paths

Fixed Income (11/11 items):
- ListCorporateBonds, ListTreasuryBonds (/v1/assets/fixed_income/*)
- CreateFixedIncomeOrder (market-only, TIF=day, decimal validation)
- GetFixedIncomeActivities (maturity filter), GetFixedIncomePositions
- CloseFixedIncomePosition, CancelFixedIncomeOrder
- 11 tests including 6 validation error subtests

Remaining Crypto (5/5 items):
- AddCryptoAgreement PATCH for existing accounts
- ListCryptoAssets with min_order_size/price_increment
- NonMarginableBuyingPower in Portfolio
- ListCryptoWallets, GetCryptoWallet stubs
- GetCountryInfo for regional license checks

Remaining Omnibus (5/5 items):
- ValidateTIF with per-asset-class TIF maps
- GetSubaccountConfirms for trade confirmations
- trading_blocked flag in SSE account events
- fractional_eh_enabled already in Asset struct

All 38 Alpaca provider tests pass. Full broker build clean.
2026-04-06 14:03:54 -07:00
zeekay 72facc0488 feat: overnight attributes, decimal validation, crypto order limits
Asset struct: add overnight_tradable, overnight_halted,
fractional_eh_enabled, min_order_size, price_increment,
min_trade_increment — parsed from Alpaca assets API.

CreateOrder: add pre-flight validation:
- Notional max 2 decimal places, qty max 9 decimal places
- Crypto: TIF must be gtc or ioc (rejects day)
- Crypto: max $200k notional, min $1 buy notional
- Crypto: min qty 0.000000002

CreateOrderRequest: add AssetClass field for asset-class-aware
validation without symbol heuristics.

Addresses Alpaca Tech Sign Off items across all 5 checklists.
2026-04-06 13:47:28 -07:00
zeekay b9a2b50d41 fix: wallet-screen route path (remove /compliance prefix) 2026-04-03 17:39:31 -07:00
zeekay 3091a6199a fix: bump compliance to v0.2.1 (AlpacaAccountID) 2026-04-03 17:13:59 -07:00
zeekay 1ed243014c feat: auto-provision Alpaca account on application approval 2026-04-03 16:15:58 -07:00
zeekay e771f3b1ed feat: ScamSniffer scam database integration, 153 addresses, 6h auto-refresh 2026-04-03 16:10:06 -07:00
zeekay a43e175760 feat: OFAC wallet screening + crypto KYT endpoint
- POST /compliance/wallet-screen: checks addresses against 47 OFAC SDN
  sanctioned wallets (Tornado Cash, Lazarus Group, Garantex, etc.)
- Falls through to Jube for real-time risk scoring
- Self-service accessible (any org)
- 11 new tests covering OFAC hits, case insensitivity, chains, directions
2026-04-03 16:00:04 -07:00
zeekay 8fc466fd0a feat: add Unregister to provider Registry (runtime provider removal) 2026-04-03 15:29:50 -07:00
zeekay d4fb39fa11 add applications table migration (016, 017) 2026-04-03 15:04:45 -07:00
zeekay 2957c9e773 refactor: org-based RBAC, drop isAdmin/roles claims
Org IS the role:
- built-in org = full admin access to all compliance modules
- Any other org = self-service only (sessions, applications, kyc)

Removed: RequirePermission, HasRole, X-User-Roles, X-User-IsAdmin
Added: requireOrgAccess (checks X-Org-Id against adminOrg)
Added: localnet environment config
2026-04-03 14:57:22 -07:00
zeekay b6191d040e fix: built-in org users get X-User-IsAdmin (Casdoor JWT lacks isAdmin claim) 2026-04-03 14:48:47 -07:00
zeekay 872c13d867 split self-service vs admin routes: sessions/applications open, admin behind built-in org 2026-04-03 14:27:39 -07:00
zeekay 454b735593 feat: compliance restricted to built-in org, RequireOrg middleware
- auth.RequireOrg() middleware rejects requests from wrong org
- Compliance routes require built-in org (COMPLIANCE_ADMIN_ORG env var)
- SuperAdmin users (built-in org) manage compliance for all customer orgs
- Customer data lives in liquidity org, admin access via built-in org
- Tests updated to use built-in org
2026-04-03 14:22:51 -07:00
zeekay 1a99305992 allow self-service onboarding for authenticated users without roles 2026-04-03 14:19:44 -07:00
zeekay b219edd2c9 security: fix all critical/high findings from red team review
- Strip 9 identity headers at start of every request (prevents injection via direct pod access)
- Remove X-Account-Id fast path and fallback headers from frontend handlers (fixes IDOR)
- Add gRPC auth interceptor with IAM JWKS validation
- Fix RBAC role splitting (comma-separated X-User-Roles)
- Move webhook endpoint outside auth middleware
- Fatal on empty SSN_HMAC_KEY in production
- Remove dead admin store code
- Remove duplicate CORS handler from compliance router
- Fix writeErr JSON injection (use json.Marshal)
- Propagate isAdmin + roles claims from JWT
2026-04-03 14:13:17 -07:00
zeekay f29020297f feat: add IAM JWKS validation to auth middleware
Middleware now validates Bearer tokens against IAM JWKS endpoint
(IAM_ENDPOINT/.well-known/jwks). Extracts sub, owner, email claims
and sets X-User-Id, X-Org-Id, X-User-Email headers.

Also accepts gateway-propagated headers (X-User-Id) for deployments
behind Hanzo Gateway. One auth path: IAM only.
2026-04-03 13:56:14 -07:00
zeekay 0c02dd3424 fix: compliance auth checks X-User-IsAdmin from IAM JWT (no separate admin store) 2026-04-03 13:53:58 -07:00
zeekay 4df5223100 refactor: remove internal auth, use IAM via gateway only
All authentication now goes through Hanzo Gateway → IAM JWKS.
The broker reads identity from gateway-propagated headers
(X-User-Id, X-Org-Id, X-User-Email, X-User-Roles) and never
validates JWTs or API keys internally.

- Remove auth.Store, auth.APIKey, API key middleware
- Remove admin.Middleware from compliance router
- Remove /auth/login and /auth/verify endpoints
- RBAC reads X-User-Roles header from gateway
- Reviewer identity from X-User-Id header
- /healthz remains unauthenticated
- Rename super_admin → superadmin
2026-04-03 13:40:51 -07:00
zeekay 1d940ce212 chore: symlink AGENTS.md and CLAUDE.md to LLM.md
Canonical project context lives in LLM.md. Symlinks ensure
agentic coding tools (Claude Code, Cursor, etc.) find context
automatically regardless of which filename they look for.
2026-04-01 14:08:13 -07:00
zeekay 5e5edb227a chore: update dependencies 2026-04-01 13:59:38 -07:00
zeekay a710df9da2 ci: use <tenant>/.github shared workflow (GKE runners) 2026-04-01 13:36:46 -07:00
zeekay a644e17f16 ci: native multi-arch Docker builds (amd64 + arm64, no QEMU) 2026-04-01 13:33:29 -07:00
zeekay 49d964fdef fix: require explicit role for trade permission (SEC Rule 301(b)(5))
Default grant for authenticated IAM users now only covers "read" (browsing
market data). Trade permission requires explicit role assignment to prevent
pre-KYC users from placing orders on the ATS.
2026-03-31 20:49:27 -07:00
zeekay 445d25465a fix: accept X-User-Id header and X-Account-Id fast path for per-user account scoping
resolveUserID now checks X-User-Id first (set by ATS injectAuthHeaders)
before falling back to X-Gateway-User-Id and X-Hanzo-User-Id.

resolveUserAccounts short-circuits on X-Account-Id + optional
X-Account-Provider headers, skipping the ListAccounts call when the
caller already knows the sub-account.
2026-03-31 16:16:36 -07:00
zeekay a1ad0aa1b0 fix: compliance init for CI, alpaca crypto snapshot test mock 2026-03-31 12:55:08 -07:00
zeekay 43d96a28e9 fix: bump compliance to v0.2.0, simplify CI 2026-03-30 20:39:35 -07:00
zeekay 596ddcdd1b fix: update compliance module checksum 2026-03-30 20:29:21 -07:00
zeekay 4f436df93a ci: add GitHub Actions — :main/:test/:dev image tags 2026-03-30 20:23:56 -07:00
zeekay 27ad8b7090 security: role-based permissions for IAM users in RequirePermission
IAM-authenticated users no longer get implicit admin access. RequirePermission
now checks X-User-Roles header for the required permission. Default IAM users
without explicit roles get read + trade only. Admin endpoints require explicit
admin role in JWT claims.

Adds hasRole() helper for comma-separated role string parsing.
2026-03-30 20:11:32 -07:00
zeekay 32ee53d6f5 fix: remove hardcoded WL origins — CORS from CORS_ALLOWED_ORIGINS env var 2026-03-30 18:43:13 -07:00
zeekay c01bbb0eab fix(ibkr): global exchange support — TSX, LSE, HKEX via contract search
resolveConid now uses POST /iserver/secdef/search for proper
multi-exchange symbol resolution. Supports TSX symbols (U.UN,
SPUT.TO), LSE (VOD.L), HKEX, etc. SMART routing auto-selects
best execution venue.
2026-03-30 18:28:17 -07:00
zeekay 0bb03de5bf feat: add Apex provider + futures/FX/bonds/margin interfaces
- FuturesProvider, FXProvider, FixedIncomeProvider, MarginProvider interfaces
- Apex Clearing provider (self-clearing, 1-4 leg options, futures, margin)
- 20 new types: FuturesContract, FXPair, Bond, AccountMargin, etc.
- Registered in envconfig (APEX_API_KEY, APEX_API_SECRET, APEX_SANDBOX)
- 17 providers total (Alpaca, Apex, IBKR, Tradier, CurrencyCloud, LMAX, etc.)
2026-03-30 16:11:00 -07:00
zeekay 5de9cbe333 feat: add options trading — Alpaca Level 3 multi-leg support
- OptionsProvider interface (7 methods): chain, expirations, quote,
  single-leg orders, multi-leg orders, exercise, positions
- Alpaca implementation: order_class "mleg", ratio_qty, position_intent
- Fix 3 critical bugs: mleg class, ratio_qty field, position_intent
- Add DoNotExercise + SetOptionsApprovalLevel endpoints
- HTTP handlers: 10 new routes under /v1/options/*
- Security: OCC symbol validation, input sanitization, audit logging
- Tests: 16 provider + handler tests passing
2026-03-30 15:25:47 -07:00
zeekay 760d8e710e fix: default ListOrders to status=all (Alpaca defaults to open only) 2025-12-24 22:00:00 -07:00
zeekay b9afd116a8 fix: set Account.ID from provider ID in Alpaca toUnified
Account.ID was empty causing SmartOrder to call
/v1/trading/accounts//orders (double slash, 404).
2025-12-24 21:46:11 -07:00
zeekay a798507a84 debug: log alpaca 4xx responses with URL 2025-12-24 21:37:48 -07:00
zeekay dcdde1d895 fix: auto-resolve account in SmartOrder when accounts map is empty
When the caller doesn't provide explicit provider→account mappings,
SmartOrder now auto-discovers the first available account for the
best provider. Fixes "no account configured" errors from ATS.
2025-12-24 21:15:47 -07:00
zeekay 8723d2fc14 feat: add Hyperliquid perpetuals DEX provider
Read-only integration with Hyperliquid API:
- Market data: snapshots, bars, trades, quotes via /info endpoint
- Account state: clearinghouse positions and margin
- Open orders query
- Order execution stubbed (needs wallet signing)
2025-11-15 14:23:41 -08:00
zeekay f1fd941892 fix: clean up dead code in auth middleware, fix RequirePermission bug
- Remove unreachable ATS proxy X-User-Id block (already handled above)
- Fix RequirePermission: was checking X-User-Id twice instead of
  X-User-Id || X-IAM-User-Id
- Change error message to "authentication required" for consistency
2025-12-24 19:09:01 -07:00
zeekay 03c7446a38 revert: restore Dockerfile + cloudbuild — broker is a deployed BD service 2025-12-24 18:45:12 -07:00
zeekay edbf521a7c chore: remove Dockerfile + cloudbuild — Go module, not a standalone service 2025-12-24 18:42:57 -07:00
zeekay 9ece9df4f9 chore: remove Dockerfile + cloudbuild — Go module consumed by ATS, not deployed standalone 2025-12-24 18:42:36 -07:00
zeekay 548f2afc6f fix: update go.sum for compliance v0.1.0 retag 2025-12-24 18:31:19 -07:00
zeekay 0ea4596279 fix: remove replace directive, fix Dockerfile for Cloud Build 2025-12-24 18:08:24 -07:00
zeekay 000872b610 security: SSN key mandatory, CORS env-gated, role mutation locked to super_admin
- SSN_HMAC_KEY: now required unconditionally (init panic) — no fallback
- CORS: localhost origins only allowed when BROKER_ENV != production
- Role mutation (POST/PATCH/DELETE /roles) restricted to super_admin or
  owner via requireSuperAdmin guard — prevents self-escalation (HIGH-3)
- Role list/get now requires roles:read RBAC guard
2025-12-24 17:45:51 -07:00
zeekay 4d2f28a2f7 security: harden compliance router — full RBAC, library delegation, audit logging
- Add RBAC guards to ALL read endpoints (pipelines, sessions, funds,
  esign, templates, dashboard, users, transactions, reports, settings,
  credentials, billing, envelope views) — previously 20+ GET routes
  had no permission checks
- Wire Jube client into amlHandler via RouterOption pattern
- Replace NewRouter variadic authStore param with proper RouterOption API
- Delegate seed roles to rbac.DefaultRoles() — fixes drift where seed
  was missing aml and applications modules
- Delegate modules list to rbac.ComplianceModules() — single source of truth
- Delegate onboarding helpers (newApplicationSteps, isTerminalStatus,
  markStepCompleted, markStepFailed) to compliance library
- SSN HMAC key: hard-fail in production if SSN_HMAC_KEY not set
- Add audit logging when super_admin RBAC bypass is used
- Credential management elevated to roles:admin (was unguarded)
2025-12-24 17:43:04 -07:00