Skip to content

feat(api): AIN-182 Phase 3 · tenant_routing_policies + GET/PUT#53

Merged
hizrianraz merged 1 commit into
mainfrom
feat/ain-182-phase3-routing-policy-backend
May 19, 2026
Merged

feat(api): AIN-182 Phase 3 · tenant_routing_policies + GET/PUT#53
hizrianraz merged 1 commit into
mainfrom
feat/ain-182-phase3-routing-policy-backend

Conversation

@hizrianraz
Copy link
Copy Markdown
Contributor

Backend half of AIN-182 §Phase 3 §7. New tenant_routing_policies table + GET/PUT endpoints.

  • Migration 20260519_0021: tenant_id PK + FK CASCADE, active_policy enum, weights NUMERIC(4,3), fallback fields, DB CHECK weight-sum-to-1.0 ±0.001 (D26 lock) + penalty bounds [0,100]
  • GET /v1/routing-policy → row OR implicit Balanced default. compliance_veto_locked always true (Discipline fix(audit): honest cap + cursor for /v1/audit/public and /v1/audit/{id} #12)
  • PUT /v1/routing-policy → upsert via ON CONFLICT. Pydantic model_validator enforces weight sum client-side; DB CHECK is final guard
  • OpenAPI contract test extended

Closes part of AIN-182 Phase 3. Pre-commit gates all green.

New per-tenant routing-policy state surface backing the dashboard
/settings/routing-policy editor (AIN-182 §Phase 3 §7).

Migration 20260519_0021 adds tenant_routing_policies (PK on
tenant_id, FK CASCADE). Columns: active_policy enum, quality/cost/
latency_weight NUMERIC(4,3), fallback_enabled bool,
fallback_penalty_pct NUMERIC(5,2). DB CHECK enforces weight sum
= 1.0 ±0.001 (D26) and penalty bounds [0, 100].

Endpoints:
- GET /v1/routing-policy → row OR implicit Balanced default.
  compliance_veto_locked always true (Discipline #12).
- PUT /v1/routing-policy → upsert via ON CONFLICT. Pydantic
  model_validator enforces weight-sum-to-1.0; DB CHECK is the
  final guard. CHECK breach → 400.

Closes part of AIN-182 Phase 3.
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 19, 2026

AIN-182 🔴 Dashboard 6 missing pages from D-153 spec — Glance, Agent detail, Inference detail, Templates gallery, Template editor, Routing policy

Severity: 🔴 URGENT — 6 of 8 spec'd dashboard pages NOT BUILT

Filed 2026-05-18 PM after AIN-153 audit revealed Aule shipped 2 pages with empty-state data and marked parent Done. Reverted to In Progress.

This ticket consolidates the 6 missing dashboard pages from the canonical spec into a single epic-child for parallel execution.

Canonical spec reference

🎨 Marketing + Dashboard Design (Ampersend + Unicorn) §Part 2

Missing pages (build these in order)

Phase 1 — Critical-path pages (no payment dependency)

1. / Glance dashboard

Spec: Marketing+Dashboard Design §Part 2 Page 1.

  • Balance + this-month spend cards (top row)
  • Top agent + top model cards (using model_id from leaderboard materialized view)
  • Live activity feed (last 50 inferences across all agents, click → inference detail)
  • Bottom nav: Agents / Templates / Wallet / Audit / Routing / Settings
  • Real data from /v1/stats/tenant (parallel to AIN-154 /v1/stats/public for marketing)

Acceptance:

  • Wallet balance reads from wallets table per tenant
  • This-month spend computed from inferences.cost_usd sum where created_at >= date_trunc('month', now())
  • Top-agent ranked by inferences this month
  • Top-model ranked by inferences across all tenant agents this month
  • Live feed updates via polling or SSE (no fake data)
  • Click row → /inferences/

2. /agents/<id> Agent detail

Spec: §Part 2 Page 2.

  • Hero: agent name + framework + model + identity + status
  • Embedded Wallet card (balance, caps, topup/edit/pause buttons — wired to wallets table per D7)
  • Today's workflows list (4 most recent)
  • Templates in use list (joined via agents.template_id)
  • Footer: Settings / Audit chain / Suspend / Revoke

Acceptance:

  • Agent metadata reads from agents table
  • framework rendered as opaque string (D-153 Universal Control Plane lock)
  • Wallet card shows real per-agent balance + caps
  • Workflows list joins workflows table where agent_id = <id>
  • Templates list joins templates where agents.template_id = templates.id OR templates applied via separate agent_templates join table (Aule design call)
  • Suspend/Revoke buttons fire POST /v1/agents/<id>/suspend (501 acceptable if endpoint pending)

3. Re-IA /agents/<id>/workflows/<wid> (currently at /workflows/[id])

Aule shipped this at flat /workflows/[id] per PR web#39. Spec requires nested /agents/<id>/workflows/<wid> IA.

Decision: Keep flat as alias, add nested as canonical. Both routes render same component. Redirect flat → nested for clean URLs.

Acceptance:

  • /agents/<id>/workflows/<wid> route exists
  • /workflows/<id> 308 redirects to /agents/<agent_id>/workflows/<wid> (resolve agent_id from workflow_id)
  • Real workflow data renders (Phase B2 data shim that Aule deferred)
  • Task list shows ordered tasks with model attribution
  • Each task row clickable → /inferences/
  • Audit chain link clickable → /audit/

4. /inferences/<id> Inference detail

Spec: §Part 2 Page 7.

  • Model + provider + tokens + latency + cost + status
  • Routing decision block (Q/R/C/L scores + policy + rationale)
  • Audit event seq + hash + "Verify with curl" button
  • Prompt (expandable, collapsed by default)
  • Response (expandable, collapsed by default)

Acceptance:

  • Reads from inferences table
  • Routing rationale reads from audit_events where event_type = 'routing.decided' matched by trace_id
  • "Verify with curl" button copies curl https://api.ainfera.ai/v1/audit/<seq> to clipboard
  • Prompt/response rendered with safe markdown + truncation
  • No PII leaked to wrong tenant (RLS enforced)

Phase 2 — Template surfaces (D10 + D11 locks)

5. /templates Gallery

Spec: §Part 2 Page 4.

  • "By Ainfera" section (system templates where tenant_id IS NULL)
  • "By you" section (tenant's own templates)
  • 6 Ainfera templates seeded per D-153-B Lock B (Aule seeds in Phase 1 per his commitment):
    • inference-frontier
    • inference-fast
    • inference-cost-light
    • inference-embedding
    • routing-balanced
    • routing-quality-first
  • "+ New template" button → /templates/new
  • "Import from JSON" button → file upload modal

Acceptance:

  • 6 system templates seeded via migration
  • Tenant-private templates render in "By you" section
  • Template card shows: name, workflow tasks summary, est cost range, est latency
  • "Use this template" button → "Apply to agent" modal
  • "Clone & customize" button → /templates/new with prefill

6. /templates/<id>/edit Template editor

Spec: §Part 2 Page 5.

  • Name + description + visibility (Private/Workspace/Public per D10)
  • Ordered task list with model class picker (D11 — reasoning-frontier / fast-reasoning / cost-light / embedding)
  • HITL rules section
  • Estimated cost + latency calculated client-side
  • Save / Save & apply to agent / Export JSON / Cancel

Acceptance:

  • Tasks editable inline
  • Model class dropdown (NOT specific model — D11)
  • Priority dropdown (cost/balanced/quality)
  • Tools optional input (linear.list_issues, etc.)
  • Save updates templates table
  • "Save & apply to agent" modal → picks agent → updates agents.template_id

Phase 3 — Routing surface

7. /settings/routing-policy Routing policy editor

Spec: §Part 2 Page 8.

  • Active policy selector (Balanced / Cost-first / Quality-first / Latency-first / Strict / Custom)
  • Weight sliders (Quality / Cost / Latency, sum=1.0 ±0.001 per D26)
  • Compliance veto indicator (locked, can't be modified per Discipline fix(audit): honest cap + cursor for /v1/audit/public and /v1/audit/{id} #12)
  • Fallback enabled toggle + penalty %
  • Recent decisions summary (anonymized counts: primary / fallback / strict 402)
  • Apply / Reset to defaults

Acceptance:

Pages NOT in this ticket (payment lane deferred)

Path Status
/agents/<id>/wallet DEFER — payment lane per AIN-179
/wallet DEFER — payment lane per AIN-179

These ship after AIN-129 CDP signup + USDC settlement live.

Cross-cutting requirements

  • Keyboard shortcuts implemented per spec (⌘K palette, j/k, g+a/t/w/r/i, Esc, ⌘/)
  • Mobile read-only verified per D12 (edit buttons hidden ≤768px viewport)
  • Brand v1.3 tokens (bg #070B14, ink #E8EDF5, accent #4D95E8, IBM Plex Sans 500 -0.022em)
  • No layout shifts (skeletons render at correct size before data loads)
  • Live counters smooth count-up animation (400ms)
  • New activity rows fade-in (200ms) with subtle slide-down (-8px)
  • Hover transitions 120ms

Acceptance gates (this epic-child)

  • All 6 pages built per spec
  • All page data wired (no empty-state placeholders)
  • Browser smoke on prod app.ainfera.ai for each page
  • Mobile smoke at 375px viewport (read-only verified)
  • Keyboard shortcuts smoke (⌘K palette works)
  • 6 Ainfera templates seeded via migration
  • Aule author override on all commits per Discipline docs(adr): ADR-012/013/014 — AA integration roadmap #4
  • PR opens off feat/ain-182-dashboard-6-missing-pages branch
  • AIN-153 parent moves to Done after this ships

Connection

Founder authorization

Per "Hard revert to In Progress and force the missing work" (2026-05-18 session 3.5 PM).

Review in Linear

@cursor
Copy link
Copy Markdown

cursor Bot commented May 19, 2026

You have used all Bugbot PR reviews included in your free trial for your GitHub account on this workspace.

To continue using Bugbot reviews, enable Bugbot for your team in the Cursor dashboard.

@hizrianraz hizrianraz merged commit 1b0f5dd into main May 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant