Viska-Autoresearch — Consolidated Deployment Report
Date: 2026-05-25 Arc: 4-track parallel research, constellation-hermes coordinator Client: Viska (Pantheon fleet) Decision class: stage-1 architecture lock-in, stage-2 readiness gate
Executive summary
Ship stage-1 Viska-autoresearch as: Nous Forge inference API + thin agent loop on Railway CPU + OpenRouter for non-Nous LLM calls + Plutus-CC scheduled sessions as supervisor gate + additive research.* schema on existing viska-research Supabase + Envoy sidecar egress allowlist + 15-item must-have security checklist. Pattern B (Supervisor) with Pattern C namespacing as schema substrate. Stage-1 marginal cost ~$23–155/mo inference + ~$100/mo Plutus review tokens. No broker credentials stage 1. Stage-2 trigger (broker creds) requires Railway Enterprise + per-order approval gate + 30-day Plutus catch-rate calibration — pre-decide.
Critical findings driving these picks:
- Railway has NO GPU instances (their own docs, three pages). Self-hosting Hermes-3/4 on Railway is not deployable today. Stage-2 self-host path = Runpod/Modal/Together/Lambda.
- viska-research Supabase already exists (proteus-owned, SOC2-verified 2026-04-08, post-RLS-remediation). New work is purely additive in
researchschema — must not perturbpublicnamespace. - Operator-visible trust asymmetry is load-bearing. Plutus CC sessions produce STATE.md / chronicle / devlog artifacts; Nous loops do not. Pattern A (peer) flattens this asymmetry and orphans interpretation onto every reader.
- The "lethal trifecta" (PII + untrusted input + outbound LLM API) is the real Railway risk, not Railway-platform itself. Dual-LLM pattern + PII tokenization + egress proxy form the must-have triad. Railway is shippable with these; not shippable without.
- OpenRouter > direct OpenAI for non-Nous calls. 5.5% fee dominated by uptime aggregation, model pinning, per-request data-policy filter (zero-retention provider selection), single credential surface.
Stage-1 architecture (locked candidates)
| Plane | Choice | Justification source |
|---|---|---|
| Nous inference | Nous Portal API (inference-api.nousresearch.com), OpenAI-compatible |
T1 §exec + matrix |
| Non-Nous LLM routing | OpenRouter with model-pinning + data-policy filter | T1 §OpenAI vs OpenRouter |
| Agent loop runtime | Railway CPU containers (Pro tier) for both Nous-agent-loop AND Plutus-CC dispatch surface | T1 + T3 |
| Shared KB | viska-research Supabase, new research schema, force-RLS on every table |
T2 §schema + §migration |
| Vector layer | pgvector HNSW(cosine), 1024-dim on research.research_artifacts.embedding |
T2 §pgvector |
| Topology | Pattern B Supervisor with writer-namespaced staging→approved promotion | T4 §recommended |
| Egress | Envoy sidecar inside Railway project, allowlist-default-deny | T3 §egress |
| Secrets | Railway sealed variables stage 1; Hades-deposited project-scoped LLM API keys, 30d rotation | T3 §secrets |
| Audit | Three layers — Railway workspace audit (polled to bucket) + Supabase pgAudit + app-level agent_actions on separate Supabase |
T3 §audit |
| PII handling | Opaque-token redaction before context assembly, detokenize at output validation | T3 §PII |
| Kill-switch | Soft = Slack /viska pause nous → governance flag table. Hard = Hades revokes writer credential |
T4 §dispatch |
Cross-track decisions — alignment + tensions
Alignment
- T3 dual-LLM pattern ↔ T4 supervisor pattern. T3's must-have #1 (quarantined LLM ingests external content, privileged LLM consumes summaries) maps directly to T4's executor split (Plutus owns ingestion + classifier-summarizer; Nous reasons over summarized layer). Same defense, viewed from two angles.
- T1 OpenRouter ↔ T3 must-have #4 (ZDR tier). OpenRouter's per-request data-policy filter satisfies the ZDR requirement; route only to zero-retention providers when prompts contain
<<CLI_*>>/<<ACC_*>>tokens. - T2 force-RLS schema ↔ T4 writer-namespaced KB. T2's
writer_classcheck constraint + per-policy enforcement satisfies T4's "every writer writes only its own rows" invariant.
Tensions (require operator pick)
-
Status-column (T2) vs status-namespace (T4). - T2 designed
research.signalswithstatus text check in ('active','superseded','expired','revoked')— single table, status filtered inpublic.viska_signals_activeview. - T4 designedsignals/candidate/*+signals/approved/*+signals/rejected/*as separate namespaces with promotion = explicit row in approved table. - Both are valid. Status-column = simpler schema, view-mediated query. Status-namespace = cleaner RLS (different table = different policy), promotion is an audit-friendly INSERT. - Recommendation: Hybrid. Singleresearch.signalstable per T2, but RLS policy gates UPDATEs tostatus='active'on Plutus only (Nous can only INSERT withstatus='candidate', which becomes the canonical staging state). Adds two CHECK constraints, preserves T2's query views, satisfies T4's promotion-audit pattern. Addreviewed_by,review_session_id,verdict_excerpt,verdict_decision text check in ('approved','rejected')columns to the same table. Promotion = UPDATE settingstatus='active'+ filling verdict columns. -
Embedding model. T2 lists three candidates (
text-embedding-3-small@1024,voyage-3-lite,bge-large-en-v1.5). T1 doesn't pick. Voyage is finance-tuned + cheapest; OpenAI simplest; bge self-hosted (no per-token but ops overhead). - Recommendation: Voyage-3-lite stage 1 (cost + finance tuning), revisit if data-residency forces self-host. -
Stage-1 LLM provider for the Plutus reviewer judge. T3 must-have #4 (ZDR) bounds this. T1 OpenRouter recommendation covers it via data-policy filter. But T4 has Plutus running as CC sessions which use Claude — Anthropic's ZDR tier (zero-data-retention) is contracted, not on-demand. Confirm Anthropic ZDR is active on the Pantheon Anthropic account before Plutus reads any PII-bearing artifact. If not active, route Plutus's review LLM calls through OpenRouter with data-policy filter set to zero-retention providers.
Cost envelope (stage 1, monthly)
| Line | Light volume (5M tok/day) | Heavy (50M tok/day) |
|---|---|---|
| Nous Forge (Hermes-4-70B input-heavy) | $23 | $230 |
| Non-Nous LLM via OpenRouter (Claude/GPT-5.4 mix) | $50–150 | $300–800 |
| Plutus CC review tokens (Claude, ~5–15min cron) | $50–100 | $150–300 |
| Railway (Pro $20/mo + agent + Envoy sidecar + Mastra existing) | $50–80 | $80–150 |
| Embedding (Voyage-3-lite, ~0.5M tok/day) | $10 | $80 |
| Supabase (viska-research, existing — no delta) | $0 | $25 |
| Stage-1 total | $183–363 | $865–1,585 |
Stage-2 (broker creds) adds Railway Enterprise (commit-spend tier, ~$1k+/mo floor), per-order signing infra, audit-evidence pipeline — at least $1.5–2.5k/mo delta before broker-execution costs.
Security stance (T3 condensed)
Verdict: Stage-1 shippable with all 15 must-have items. Stage-2 NOT shippable without explicit operator-approved hardening delta.
Must-have triad (do not ship without): - Dual-LLM pattern (quarantined ingestion model + privileged synthesis model, no tool access on quarantined side) - Envoy egress sidecar with allowlist-default-deny (highest-value single control) - PII tokenization before context assembly + detokenize at output validation
Other 12 must-haves: Supabase least-privilege roles + RLS, ZDR LLM tier, sealed variables, research-fetch domain allowlist, append-only audit on separate Supabase, SSRF guard, content sanitization, loop iteration cap + drift abort, CI dep audit gate, SBOM per deploy, private networking, HIPAA BAA if jurisdiction warrants.
Full checklist + threat model in T3-security-posture.md.
Topology (T4 condensed)
[OPERATOR]
│
[SLACK]
│
[MASTRA agent] (Railway CPU, KB-readonly except own audit)
│ realtime sub on *_approved/*
▼
┌───────────────────────────────────────────────────────────────────┐
│ KB (viska-research Supabase, research.* schema) │
│ raw/ · signals/{candidate→approved} · strategies/{draft→approved}│
│ backtests/ · reports/ · governance/{flags,incidents,metrics} │
│ nous_run_queue/ · nous_traces/ · audit_log/ · slack_threads/ │
└───────▲──────────────▲──────────────▲────────────────────────────┘
│ │ promote │
│ candidates │ (Plutus-only)│
[NOUS agent loop] [PLUTUS CC scheduled sessions] [INGESTION jobs]
Railway CPU (operator-visible reviewer) Plutus-cron
Nous Forge API ingestion · review · synthesis · raw/* writer
staging-only writer backtest · report · governance
│
[HADES] (out-of-band credential plane)
Trust boundaries: - A: Autonomous — Nous + staging namespaces - B: Supervised — Plutus + approved namespaces + governance - C: External surface — Slack + Mastra, KB-readonly - D: Credential plane — Hades
Full failure-mode handoff table + dispatch protocol in T4-topology.md.
OpenAI vs OpenRouter decision (T1 condensed)
Pick: OpenRouter. 5.5% credit fee, dominated by: - Single credential surface (1 key vs N vendor accounts) - Automatic provider failover on outage (uptime aggregation — critical for unsupervised loop over open positions even if no execution stage 1) - Per-request data-policy filter — refuse providers that retain/train (required for PII tokens + IP prompts) - Model pinning by explicit ID (catches silent vendor model swaps) - Unified per-model/per-key audit dashboard
Reserve direct OpenAI access only if a model OpenRouter cannot route is needed (e.g. fine-tuned org-private models). Nous goes direct — Nous Portal is cheapest first-party.
Critical operator decisions (gate before implementation)
| # | Decision | Source | Default if no answer |
|---|---|---|---|
| D1 | EU data residency required for Viska? | T1 OQ1 | Assume no stage 1; OpenRouter US providers. If yes → OpenRouter Enterprise EU tier mandatory. |
| D2 | Embedding model. Voyage-3-lite / OpenAI-3-small / self-hosted bge | T2 OQ1 | Voyage-3-lite (finance-tuned + cheapest) |
| D3 | Anthropic ZDR active on Pantheon account? | T3 OQ5 + must-have #4 | If unknown → route Plutus review LLM through OpenRouter ZDR-filtered |
| D4 | Stage-2 trigger criteria for broker creds. | T1 OQ5 + T4 OQ5 | Proposed: 30 days Plutus catch-rate ≤5% false-approval vs operator override |
| D5 | Plutus review cron cadence. | T4 OQ1 | 5–15 min off-hours, 1–2 min market-hours, operator budget ratification needed |
| D6 | Status-column vs status-namespace on research.signals |
T2/T4 tension | Hybrid — single table + RLS-gated status UPDATE per recommendation above |
| D7 | Container runtime / IMDS exposure on Railway | T3 OQ1, OQ2 | Operator queries Railway Trust Center; affects TM-5 + TM-7 design |
| D8 | Nous rate-limit tier. Default 180 RPM / Ultra 1600 RPM | T1 OQ3 | Default tier stage 1; reassess at heavy-volume cutover |
Implementation order (proposed)
Stage 1 — research deployment (no execution):
- Pre-deploy: Operator picks D1–D8. Hades deposits sealed credentials (Nous Forge key, OpenRouter key, Voyage key, Supabase JWTs for 3 writers).
- KB migration A (T2 §migration step 2): create
researchschema + 5 tables + RLS + views, single migration, force-RLS on every table. - Egress sidecar: Deploy Envoy sibling service on Railway with allowlist config.
- Nous-agent loop deploy: Railway CPU service,
nous_writerJWT, points to Envoy egress. Smoke loop into staging tables only. - Plutus integration: Extend existing Plutus CC scheduled sessions with new poll-and-review skill. Promotion writes only.
- Mastra view switch: Add 3 curated views to Mastra's PostgREST query set, realtime subscription on approved namespaces.
- Governance daemon: Plutus-owned cron writing
governance/metrics/*, flag-table SSOT. - Audit + monitoring: App-level
agent_actionson separate Supabase + Railway audit log export cron. - Soft launch: Operator-only Slack channel for 7-14 days. Calibrate Plutus catch-rate.
- Stage-1 GA: End-client Slack access. Stage-2 broker integration backlog opens.
Stage 2 (broker creds) is a separate arc — re-research before opening.
Open work items (post-report)
Files Hermes will commit to research/viska-autoresearch-2026-05-25/:
REPORT.md(this file)T1-nous-deployment.mdT2-kb-integration.mdT3-security-posture.mdT4-topology.md
Follow-up tasks (file in Hermes backlog after operator green-light on D1–D8):
- TASK A — Plutus skill spec for "Nous candidate review" (poll cadence, checklist, prompt template, rejection criteria). Plutus repo.
- TASK B — Envoy sidecar config + Railway deploy template. Hephaistos or Plutus (whichever owns ops layer).
- TASK C —
research.*schema migration SQL + RLS policies + views + RPC. Proteus repo (DB-owner). - TASK D — Mastra side: 3 view subscriptions + RPC binding + Slack alert templates. Mastra repo.
- TASK E — Nous agent loop scaffold (token-budget guard, queue-claim discipline, staging-only writer). New repo or fold into existing Plutus stack — decide stage-1 hosting.
- TASK F — Hades deposit plan: Nous Forge key, OpenRouter key, Voyage key, 3 Supabase JWTs (mastra_reader, nous_writer, plutus_writer), separate audit-Supabase service key.
- TASK G — Audit pipeline: separate Supabase project for
agent_actions, Railway audit export cron, reconciliation cron. - TASK H — Pre-stage-2: broker-touching service deployment target (Railway Enterprise vs off-Railway single-tenant); per-order signing protocol; reg-AI compliance check.
Sources rolled up
T1 — Nous Portal docs, Forge announcement, Hermes-4 model card, Railway GPU-absence docs (3 pages), OpenRouter docs, OpenAI pricing.
T2 — Pantheon SSOT fleet_services queries, Aion RAG (5 pages, RLS-remediation precedent), Supabase RLS + vector docs.
T3 — Railway compliance/networking/variables/static-IP docs, OWASP LLM Top 10 (2025), Unit42 IDPI in-the-wild (Mar 2026), EchoLeak arXiv, Simon Willison "lethal trifecta," MITRE ATLAS, Railway 2025-10-28 incident.
T4 — Aion (Plutus war-room + Mastra-backend pages), Karpathy auto-research patterns, T1/T3 cross-refs.
Per-track full citation list in each track file.
Coordinator notes
- T2 surfaced viska-research as a pre-existing Pantheon-registered service (operator may not have known). Schema is additive; zero perturbation to current Mastra/dashboard reads.
- T1 caught Railway-has-no-GPU early — invalidated naive "self-host on Railway GPU" plan in the original brief.
- T4 chose Pattern B explicitly because Plutus CC already provides operator-visible reviewer surface (chronicle + devlog + STATE.md). Without Plutus's surface, the choice would change.
- T3 reaches stage-1-shippable verdict only with all 15 must-haves. Skipping any of them moves verdict to not-shippable.
- One unresolved tension across tracks (T2 vs T4 namespace design) — recommended hybrid in §cross-track-decisions.