Context
PR #61 ships the broker's transport surface (mint-aws-creds, mint-oidc-jwt, OIDC discovery, audit log). The authentication half is still a stub — agentkeys-mock-server accepts any auth_token string and binds it to whatever wallet the caller claims. Anyone with broker.litentry.org can mint a session for any wallet.
This issue tracks the work to ship real auth using the dexs-backend pattern as the reference architecture.
Approach (Option A — port dexs-backend)
Per docs/research/option-a-port-dexs-backend.md, AgentKeys broker absorbs the essential code from dexs-k/dexs-backend — wallet-sig (walletloginlogic.go), email (emailloginlogic.go), Google OAuth (googleoauthcallbacklogic.go), and the pumpx_api callback surface that the Heima TEE worker calls into during omni_userLogin / omni_addWallet.
Heima TEE worker side: add CLIENT_ID_AGENTKEYS so AgentKeys gets its own OmniAccount namespace separate from wildmeta's. Per docs/research/option-a-port-dexs-backend.md §"Phase 0", this is ~250 LOC patch — clones the existing if params.client_id == CLIENT_ID_WILDMETA dispatch block.
Alternative architecture explored (deferred to a separate branch): see Option C issue #64.
Phases
Phase 0 — Heima TEE worker upstream patch
Coordinate with Litentry to land the multi-tenant patch:
Phase 1 — pumpx_api callback surface in agentkeys-broker
The TEE worker calls back into our broker for first-time-user bookkeeping:
Phase 2 — Front-of-house auth (port dexs-backend logic to Rust)
Phase 3 — Broker JWT validation
Phase 4 — Cleanup
Calendar estimate
8–13 weeks for one engineer, mostly Phase 1 + 2 (ports). Phase 0 calendar is gated on Litentry's review cycle — could be days, could be weeks.
Risks
- Litentry's review cycle for the multi-tenant patch is the main schedule risk. Mitigation: write the patch ourselves cleanly, run our own forked TEE worker if upstream lags.
- Inheriting dexs-backend's design baggage (HS256 JWTs, user_id INT identity model, password+TOTP path) — see Option A vs B comparison in docs/research/option-a-vs-b-port-vs-greenfield.md. If this becomes painful, escalate to Option C (separate branch).
Related
🤖 Generated with Claude Code
Context
PR #61 ships the broker's transport surface (mint-aws-creds, mint-oidc-jwt, OIDC discovery, audit log). The authentication half is still a stub —
agentkeys-mock-serveraccepts anyauth_tokenstring and binds it to whatever wallet the caller claims. Anyone withbroker.litentry.orgcan mint a session for any wallet.This issue tracks the work to ship real auth using the dexs-backend pattern as the reference architecture.
Approach (Option A — port dexs-backend)
Per docs/research/option-a-port-dexs-backend.md, AgentKeys broker absorbs the essential code from dexs-k/dexs-backend — wallet-sig (
walletloginlogic.go), email (emailloginlogic.go), Google OAuth (googleoauthcallbacklogic.go), and thepumpx_apicallback surface that the Heima TEE worker calls into duringomni_userLogin/omni_addWallet.Heima TEE worker side: add
CLIENT_ID_AGENTKEYSso AgentKeys gets its own OmniAccount namespace separate from wildmeta's. Per docs/research/option-a-port-dexs-backend.md §"Phase 0", this is ~250 LOC patch — clones the existingif params.client_id == CLIENT_ID_WILDMETAdispatch block.Alternative architecture explored (deferred to a separate branch): see Option C issue #64.
Phases
Phase 0 — Heima TEE worker upstream patch
Coordinate with Litentry to land the multi-tenant patch:
CLIENT_ID_AGENTKEYS = "agentkeys"inoe_core::auth::constantstee-worker/omni-executor/rpc-server/src/methods/omni/user_login.rs:73-104: changeif params.client_id == CLIENT_ID_WILDMETAto also acceptCLIENT_ID_AGENTKEYSwith a parallelagentkeys_apiHTTP-client config alongsidepumpx_apisubmit_user_op_with_auth.rsfor theWildmetaBackendECDSA-pubkey verification pathPhase 1 — pumpx_api callback surface in agentkeys-broker
The TEE worker calls back into our broker for first-time-user bookkeeping:
POST /v3/account/post_heima_login— user-record creation/update on first TEE loginPOST /add_wallet— wallet metadata recording (TEE has the seed; we hold the address)GET /get_account_user_id— email→OmniAccount lookup for the email-auth pathPOST /v1/account/check_hyper_agent_address— main↔agent wallet binding check (port the AgentKeys grant model into this endpoint's response)Phase 2 — Front-of-house auth (port dexs-backend logic to Rust)
walletloginlogic.go: EIP-191 message construction, 45-min timestamp window,k256ecrecover, JWT issuanceemailloginlogic.go+emailregisterlogic.go: code dispatch via existing AgentKeys SES setup, code storage with TTLgoogleoauthcallbacklogic.go: code-exchange + userinfo fetch + JWTagentkeys initcalls/wallet_login(or/email_login,/google_oauth_login) on the broker; stores the bearer in OS keychainPhase 3 — Broker JWT validation
BROKER_BACKEND_URLindirection (or repurpose asBROKER_TEE_ISSUER)agentkeys-mock-serverfrom the production path; keep in-tree as a--skip-startup-checkdev fixturePhase 4 — Cleanup
location = /session/createfrom setup-broker-host.sh's nginx config (no longer needed once CLI talks to TEE worker for login)agentkeys initinvocationCalendar estimate
8–13 weeks for one engineer, mostly Phase 1 + 2 (ports). Phase 0 calendar is gated on Litentry's review cycle — could be days, could be weeks.
Risks
Related
🤖 Generated with Claude Code