Optimization in the IRIS browser and API

How IRIS proxies optimize requests to DIONYSUS, what the browser sends, and how production auth differs from local dev.

Two URLs, one capability

LayerTypical pathNotes
IRIS (BFF)POST /api/optimizeWhat the browser calls. Session cookies + server-side forwarding.
DIONYSUS (service)POST /api/v1/portfolios/optimizeCanonical service route; OpenAPI documents request/response models.

Retail users should stay on IRIS. Integrators and operators may hit DIONYSUS directly only with the right auth and network policy (Cloud Run often requires IAM + OIDC ID token with audience = service URL).

What the browser payload should contain

Conceptually, the body matches PortfolioRequest: at minimum name, total_capital (≥ $1,000 validated server-side), and risk_settings (fractions 0–1 for max risk and position size in the API contract).

Legacy field names

Some UIs historically sent portfolio_name or portfolio_capital. IRIS may normalize those to name / total_capital before forwarding—if your integration still uses legacy keys, confirm against the current OpenAPI spec.

Risk percentages vs fractions

Onboarding flows sometimes collect whole-number percents (e.g. “2.5” meaning 2.5%). The API expects fractions (0.025). IRIS includes heuristic normalization for certain paths so advanced screens do not silently send 100× too large a risk budget. If numbers look wildly off, verify whether you are in percent vs fraction mode in the UI before filing a bug.

Investor profile and constraint packs

Structured flows may attach:

Authentication: local vs production

  • Local IRIS — You are logged in with Firebase session; the Flask app forwards your identity to backends.
  • Production — IRIS on App Engine (or similar) often calls Cloud Run services with Google OIDC ID tokens (audience = target service URL) in addition to end-user context headers. Anonymous public calls to DIONYSUS are not the supported model.

Do not paste service URLs into a browser expecting a JSON form without auth—you will get 403/401 by design.

Timeouts and heavy portfolios

Optimization can be CPU- and IO-heavy (batch Firestore reads, parallel scoring). If the UI times out while the server still runs, you may see 504 or empty responses. Retry once, then wait and check whether a portfolio was partially created (support can correlate trace_id from logs). Widen client timeouts only if your platform team approves—blind retries can duplicate work.

After optimize succeeds

IRIS typically navigates you to portfolio detail or a review step. Allocated vs remaining capital on the response should match what you see after Firestore sync; if not, refresh and check /status for ATLAS/Firestore health.

Developers

Progress is saved in this browser. Cloud sync requires PUBLIC_IRIS_API_BASE, IRIS CORS allowlist, and window.__trinityIdToken.