Skip to content

[VW-265] Seed changes and context enrichment#138

Merged
0xcad merged 7 commits into
mainfrom
VW-265
May 22, 2026
Merged

[VW-265] Seed changes and context enrichment#138
0xcad merged 7 commits into
mainfrom
VW-265

Conversation

@0xcad
Copy link
Copy Markdown
Collaborator

@0xcad 0xcad commented May 22, 2026

  • bumped model from haiku to opus 4.6
  • get-recommendations-context tool now has network topology, clinical workflows, and device utilization windows
  • Added "last updated" column to asset dashboard to make it even more obvious which assets are new from BF

Summary by CodeRabbit

  • New Features

    • Network Flow visualization in asset details (Sankey) showing device connections and protocols
    • Added “Last Updated” column to asset dashboard
    • Chat recommendations now include network topology, clinical workflows, and device utilization windows; agent asks clarifying questions when utilization is missing
    • Workflows can be serialized for UI rendering; workflows and memories are seeded
  • Improvements

    • Asset markdown shows a compact daily “Utilization Schedule”; vulnerability/remediation texts no longer truncated
  • Chores

    • Example environment file includes new network flow config entries
  • Tools

    • Added a debug script to print recommendations context

Review Change Stack

@vercel
Copy link
Copy Markdown

vercel Bot commented May 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
viper Ready Ready Preview, Comment May 22, 2026 4:56pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
viper-demo Ignored Ignored May 22, 2026 4:56pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Warning

Rate limit exceeded

@0xcad has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 13 minutes and 24 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 29dd5058-b001-4784-84d6-6845d52a5bda

📥 Commits

Reviewing files that changed from the base of the PR and between 32df28a and b4bb9dd.

📒 Files selected for processing (11)
  • prisma/flow.json
  • prisma/seed.ts
  • scripts/print-recommendations-context.ts
  • src/features/assets/components/asset-drawer.tsx
  • src/features/assets/components/dashboard-columns.tsx
  • src/features/chat/utils.ts
  • src/features/chat/viper-agent/agents/give-recommendations.ts
  • src/features/chat/viper-agent/tools/get-recommendations-context.ts
  • src/features/network/server/router.ts
  • src/features/workflows/server/routers.ts
  • src/features/workflows/utils.ts
📝 Walkthrough

Walkthrough

Integrates external network topology (schemas, TRPC proxy, per-asset 1‑hop subgraphs), renders Sankey network flows in the asset drawer, extends recommendation context with workflows/network/utilization, switches agent model/prompt, refactors workflow serialization, and performs a large seed/data overhaul including workflows and memories.

Changes

Network Flow Integration and Recommendations Context Enhancement

Layer / File(s) Summary
Network topology schemas and sample snapshot
src/features/network/types.ts, prisma/flow.json, .env.example
Adds Zod schemas and TS types for topology and enriched flow responses; includes a sample topology snapshot and new NETWORK_FLOW_URL/NETWORK_FLOW_TOKEN env placeholders.
Network topology TRPC router and endpoints
src/features/network/server/router.ts, src/trpc/routers/_app.ts
Implements server fetch helper (timeout, optional bearer token, validation) and TRPC procedures getFlow and getFlowForAsset that return full topology or enriched 1‑hop subgraphs.
Network flow visualization in asset drawer
src/features/assets/components/asset-drawer.tsx
Adds NetworkFlowSection which queries flow subgraphs via TRPC and renders an interactive Sankey diagram with protocol nodes and IP hover tooltips.
Recommendations context: workflows, network, utilization
src/features/chat/viper-agent/tools/get-recommendations-context.ts, src/features/workflows/utils.ts
Extends context tool to concurrently fetch Prisma workflows and external topology, validate/render device utilization into buckets, serialize workflows, and append these sections to generated markdown; generateContextMarkdown signature updated.
Agent model switch and expanded prompt guidance
src/features/chat/viper-agent/agents/give-recommendations.ts
Switches agent LLM to Claude Opus 4.6, reorganizes imports, and updates the prompt to prefer utilization-derived patch windows and to call ask_user_questions when utilization is missing; documents new context sections.
Workflow serialization utilities
src/features/workflows/utils.ts, src/features/workflows/server/routers.ts
Introduces serializeWorkflow() to produce a React Flow-friendly serialized workflow; router delegates workflow payload construction to this utility.

Seed Data Overhaul and Markdown Rendering

Layer / File(s) Summary
Seed data models and workflow/memory seeding
prisma/seed.ts
Overhauls seed dataset with radiology device groups, assets, CVEs, remediations; supports vulnerability→multiple CPEs; persists asset utilization and optional id; refactors artifact/remediation wrapper logic; adds seedMemories() and seedWorkflows(); extends DB clearing to delete memory records.
Asset and vulnerability markdown + dashboard column
src/features/chat/utils.ts, src/features/assets/components/dashboard-columns.tsx
Adds per-day utilization schedule rendering and untruncated vulnerability/remediation fields; removes asset "Network Segment" line; adds a "Last Updated" dashboard column showing relative timestamps.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant NetworkRouter
  participant Upstream
  participant Prisma
  Client->>NetworkRouter: getFlowForAsset(assetId)
  NetworkRouter->>Upstream: fetch topology (NETWORK_FLOW_URL, optional token, timeout)
  Upstream-->>NetworkRouter: topology JSON
  alt focal asset exists
    NetworkRouter->>NetworkRouter: compute 1-hop connections & neighbor IDs
    NetworkRouter->>Prisma: findMany assets by neighbor IDs
    Prisma-->>NetworkRouter: asset metadata
    NetworkRouter-->>Client: { in_flow: true, focal_asset_id, assets, connections }
  else focal asset missing
    NetworkRouter-->>Client: { in_flow: false }
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • timrcm
  • t-a-y-l-o-r
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.18% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main changes: seed data overhaul and context enrichment with network topology, workflows, and utilization data.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch VW-265

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (1)
scripts/print-recommendations-context.ts (1)

2-3: ⚡ Quick win

Add the server-side module marker.

This is a server-side TypeScript entrypoint and should include the server-only directive at module top.

Proposed fix
 #!/usr/bin/env tsx
+import "server-only";
 import { getRecommendationsContext } from "`@/features/chat/viper-agent/tools/get-recommendations-context`";
 import prisma from "`@/lib/db`";

As per coding guidelines: **/*.{ts,tsx}: Mark server-side files with 'server-only' directive and client components with 'use client' directive.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/print-recommendations-context.ts` around lines 2 - 3, This module
imports getRecommendationsContext and prisma but is a server-side entrypoint and
missing the server-only directive; add the server-side module marker
("server-only") as the first line of the file so the module is treated as
server-only and keeps server-only imports like getRecommendationsContext and
prisma valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/print-recommendations-context.ts`:
- Around line 5-7: The script's Prisma client may not be disconnected if an
exception occurs in main; modify the async function main() so its body is
wrapped in a try/finally where prisma.$disconnect() is called in finally
(ensuring disconnection on both success and error), and add a top-level .catch
on main() (or a surrounding try/catch when invoking main) to log the error and
exit appropriately; update any other similar invocations (lines referenced) to
follow the same try/finally + top-level catch pattern, referencing the main
function and prisma.$disconnect() to locate the changes.
- Around line 10-14: The code currently bypasses type safety by double-casting
getRecommendationsContext to unknown and forcing a handler signature; instead
declare a narrow handler type (e.g., RecommendationsContextHandler) matching the
real handler signature (args: Record<string, never>, ctx: { network?: { state?:
{ data?: { userId?: string; userRole?: string } } } }) => Promise<string>, cast
getRecommendationsContext to an object with an optional handler property of that
type (e.g., getRecommendationsContext as { handler?:
RecommendationsContextHandler }), perform a runtime guard that throws if
tool.handler is not a function, and then call tool.handler({}, { network: {
state: { data: { userId: user.id, userRole: "hospital administration" } } } })
so the call is both type-safe and verified at runtime.

In `@src/features/assets/components/asset-drawer.tsx`:
- Around line 241-263: Guard against unknown proto or peer lookups when building
Sankey links: before creating each link from protoToPeer, verify
protoSet.indexOf(proto) !== -1 and peers.findIndex(a => a.id === peerId) !== -1
(i.e. that protoIdx(proto) and peerIdx(peerId) would be valid), and skip entries
where either lookup is missing; similarly ensure items from focalToProto use a
proto that exists in protoSet. Update the mapping that builds links (the
protoToPeer and focalToProto -> links sections, referencing protoIdx, peerIdx,
protoSet, peers, mapped, focalToProto, and protoToPeer) to filter out or ignore
entries with unknown proto or peer IDs so no invalid Sankey targets are emitted.

In `@src/features/chat/utils.ts`:
- Around line 99-127: The rendering currently iterates only the keys present in
dayData so missing hours are omitted; change the hours loop to iterate the full
0–23 range (or build hours as [0..23]) and for each hour call
utilizationBucket(dayData[String(hour)] ?? 0) so absent keys are treated as
0/Offline, thereby generating segments that include offline windows; update the
variable references used in the diff (data, dayData, UTILIZATION_DAY_NAMES,
utilizationBucket, segments) and keep the same segment-merging logic so
contiguous absent hours collapse into Offline ranges.

In `@src/features/chat/viper-agent/agents/give-recommendations.ts`:
- Around line 29-31: The MODEL constant uses anthropic(...) with an unsupported
model id "claude-opus-4-6"; update the model string in the MODEL definition to a
supported Anthropic id (for example a claude-3 or claude-2 family id such as
"claude-3-opus-*" or "claude-2.*") while keeping the existing defaultParameters
key, or alternatively update the pinned `@inngest/agent-kit` SDK to a version that
supports "claude-opus-4-6". Target the MODEL constant and the anthropic(...)
call when making this change.

In `@src/features/chat/viper-agent/tools/get-recommendations-context.ts`:
- Around line 132-147: generateWorkflowsMarkdown currently embeds entire
serialized workflows (via serializeWorkflow and shortId) which can create huge
prompt payloads; limit the amount of data by truncating/capping: restrict the
number of workflows included (e.g., take first N), and when embedding serialized
JSON only include a whitelist of small fields or truncate long arrays/strings
(e.g., topology/utilization lists) and append a "...(truncated)" marker; apply
the same bounding logic to the other serialization helpers referenced in the
review (the blocks around lines 339-368 and 403) so networks/utilization lists
are similarly capped before JSON.stringify is added to the markdown.

In `@src/features/network/types.ts`:
- Around line 16-17: The ipv4_address and ipv6_address fields on
networkInterfaceSchema currently allow any string; replace their definitions to
use Zod's IP validators (e.g., for IPv4: use z.string().ip({ version: "ipv4"
}).optional().nullable(), and for IPv6: use z.string().ip({ version: "ipv6"
}).optional().nullable()) so malformed addresses fail validation; update the
properties named ipv4_address and ipv6_address in networkInterfaceSchema
accordingly.

In `@src/features/workflows/utils.ts`:
- Around line 12-24: serializeWorkflow currently returns { id, name,
description, nodes } but callers (e.g., workflowToMermaidJSON) expect
serialized.edges; fix serializeWorkflow to also serialize and return an edges
array by mapping WorkflowWithRelations.edges into the SerializedEdge shape used
elsewhere (mirror how nodes are built from workflow.nodes), then include edges
in the returned object so serialized.edges exists for workflowToMermaidJSON;
update references to WorkflowWithRelations, serializeWorkflow, workflow.nodes
and workflow.edges accordingly.

---

Nitpick comments:
In `@scripts/print-recommendations-context.ts`:
- Around line 2-3: This module imports getRecommendationsContext and prisma but
is a server-side entrypoint and missing the server-only directive; add the
server-side module marker ("server-only") as the first line of the file so the
module is treated as server-only and keeps server-only imports like
getRecommendationsContext and prisma valid.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8d7fa853-2e73-420a-ab7e-40e0d11a3e03

📥 Commits

Reviewing files that changed from the base of the PR and between d1d9da0 and afa9317.

📒 Files selected for processing (14)
  • .env.example
  • prisma/flow.json
  • prisma/seed.ts
  • scripts/print-recommendations-context.ts
  • src/features/assets/components/asset-drawer.tsx
  • src/features/assets/components/dashboard-columns.tsx
  • src/features/chat/utils.ts
  • src/features/chat/viper-agent/agents/give-recommendations.ts
  • src/features/chat/viper-agent/tools/get-recommendations-context.ts
  • src/features/network/server/router.ts
  • src/features/network/types.ts
  • src/features/workflows/server/routers.ts
  • src/features/workflows/utils.ts
  • src/trpc/routers/_app.ts

Comment thread scripts/print-recommendations-context.ts Outdated
Comment thread scripts/print-recommendations-context.ts Outdated
Comment thread src/features/assets/components/asset-drawer.tsx
Comment thread src/features/chat/utils.ts
Comment on lines +29 to +31
const MODEL = anthropic({
model: "claude-opus-4-6",
defaultParameters: { max_tokens: 4096 },
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

For @inngest/agent-kitv0.13.2, what are the supported Anthropic model IDs and valid anthropic() configuration keys? Specifically, isanthropic({ model: "claude-opus-4-6", defaultParameters: { max_tokens: 4096 } }) valid?

💡 Result:

For @inngest/agent-kit v0.13.2, the supported Anthropic model IDs (as listed in the AgentKit Anthropic model reference) are: - claude-3-5-haiku-latest [1] - claude-3-5-haiku-20241022 [1] - claude-3-5-sonnet-latest [1] - claude-3-5-sonnet-20241022 [1] - claude-3-5-sonnet-20240620 [1] - claude-3-opus-latest [1] - claude-3-opus-20240229 [1] - claude-3-sonnet-20240229 [1] - claude-3-haiku-20240307 [1] - claude-2.1 [1] - claude-2.0 [1] - claude-instant-1.2 [1] Valid anthropic configuration keys (i.e., the options accepted by AgentKit’s anthropic configuration object) are [1]: - model (string, required) [1] - apiKey (string; defaults to ANTHROPIC_API_KEY) [1] - baseUrl (string; default https://api.anthropic.com/v1/) [1] - betaHeaders (string[]) [1] - defaultParameters (object, required) [1] - And within defaultParameters, AgentKit explicitly requires defaultParameters.max_tokens [1] - The docs also show defaultParameters being used for other Anthropic generation parameters like temperature [1] Is anthropic({ model: "claude-opus-4-6", defaultParameters: { max_tokens: 4096 } }) valid? No, not according to AgentKit’s supported Anthropic model ID list for the anthropic helper, because "claude-opus-4-6" is not among the model IDs AgentKit lists as available [1]. Even though the shape of your configuration matches what the docs describe (model + defaultParameters with max_tokens) [1], AgentKit would not consider that model ID supported based on its reference list [1].

Citations:


Fix Anthropic model-id for the pinned @inngest/agent-kit version (config key is fine)

In src/features/chat/viper-agent/agents/give-recommendations.ts (lines 29-31), defaultParameters.max_tokens is a supported anthropic() key for @inngest/agent-kit v0.13.2, but model: "claude-opus-4-6" is not among the supported Anthropic model IDs in that version’s reference (claude-3-opus-*, claude-3-5-*, claude-2.*, etc. only). Replace the model id with one of the supported values (or adjust the pinned SDK if you need claude-opus-4-6).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/chat/viper-agent/agents/give-recommendations.ts` around lines 29
- 31, The MODEL constant uses anthropic(...) with an unsupported model id
"claude-opus-4-6"; update the model string in the MODEL definition to a
supported Anthropic id (for example a claude-3 or claude-2 family id such as
"claude-3-opus-*" or "claude-2.*") while keeping the existing defaultParameters
key, or alternatively update the pinned `@inngest/agent-kit` SDK to a version that
supports "claude-opus-4-6". Target the MODEL constant and the anthropic(...)
call when making this change.

Comment on lines +132 to +147
function generateWorkflowsMarkdown(workflows: WorkflowWithRelations[]): string {
if (workflows.length === 0) return "_No clinical workflows defined._";

return workflows
.map((wf) => {
const serialized = serializeWorkflow(wf);
const lines = [`### ${serialized.name} (${shortId(serialized.id)})`];
if (serialized.description) {
lines.push(`\n${serialized.description}`);
}
lines.push(
`\n\`\`\`json\n${JSON.stringify(serialized, null, 2)}\n\`\`\``,
);
return lines.join("\n");
})
.join("\n\n");
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Bound the added workflow/network/utilization markdown to avoid oversized context payloads.

The new sections append full serialized workflows plus full topology/utilization lists without caps. On larger datasets, this can bloat prompt context and degrade response reliability.

Suggested patch
+const MAX_WORKFLOWS_IN_CONTEXT = 20;
+const MAX_CONNECTIONS_IN_CONTEXT = 200;
+const MAX_UTILIZATION_ASSETS_IN_CONTEXT = 100;
+
 function generateWorkflowsMarkdown(workflows: WorkflowWithRelations[]): string {
   if (workflows.length === 0) return "_No clinical workflows defined._";
 
-  return workflows
+  const shown = workflows.slice(0, MAX_WORKFLOWS_IN_CONTEXT);
+  const body = shown
     .map((wf) => {
       const serialized = serializeWorkflow(wf);
       const lines = [`### ${serialized.name} (${shortId(serialized.id)})`];
       if (serialized.description) {
         lines.push(`\n${serialized.description}`);
@@
     })
-    .join("\n\n");
+    .join("\n\n");
+  const remaining = workflows.length - shown.length;
+  return remaining > 0
+    ? `${body}\n\n_…${remaining} additional workflows omitted for brevity._`
+    : body;
 }
@@
-  const connections = topology.connections ?? [];
+  const connections = (topology.connections ?? []).slice(
+    0,
+    MAX_CONNECTIONS_IN_CONTEXT,
+  );
@@
-  for (const asset of assets) {
+  for (const asset of assets.slice(0, MAX_UTILIZATION_ASSETS_IN_CONTEXT)) {

Also applies to: 339-368, 403-403

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/chat/viper-agent/tools/get-recommendations-context.ts` around
lines 132 - 147, generateWorkflowsMarkdown currently embeds entire serialized
workflows (via serializeWorkflow and shortId) which can create huge prompt
payloads; limit the amount of data by truncating/capping: restrict the number of
workflows included (e.g., take first N), and when embedding serialized JSON only
include a whitelist of small fields or truncate long arrays/strings (e.g.,
topology/utilization lists) and append a "...(truncated)" marker; apply the same
bounding logic to the other serialization helpers referenced in the review (the
blocks around lines 339-368 and 403) so networks/utilization lists are similarly
capped before JSON.stringify is added to the markdown.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now I think this is fine, I want to make sure we have all workflows present, and a lot of this tool will be rewritten after using it to test what we should spend engineering effort on next

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xcad, understood — keeping it unbounded makes sense while you're using this to explore what's worth investing in. Would you like me to open a follow-up issue to track the context payload bounding work for when the tool gets rewritten?

(ᵔᴥᵔ)


🧠 Learnings used
Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 107
File: src/features/advisories/server/routers.ts:96-103
Timestamp: 2026-04-02T18:16:00.222Z
Learning: When reviewing TypeScript code that uses Zod v4 with Prisma-generated const enum objects, do not suggest replacing enum usage with `z.nativeEnum()`. In this project, `z.nativeEnum()` is deprecated under Zod v4—use the idiomatic pattern `z.enum(PrismaEnumObject)` (e.g., `z.enum(MyPrismaConstEnum)`), and treat direct `z.enum(PrismaEnumObject)` as the correct approach.

Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 107
File: src/features/advisories/server/routers.ts:96-103
Timestamp: 2026-04-02T18:16:00.223Z
Learning: When writing Zod schemas in this repository (PATCH-UPGRADE/viper), do not use `z.nativeEnum()`. The project uses Zod v4 where `z.nativeEnum()` is deprecated; prefer `z.enum(PrismaEnumObject)` as the idiomatic pattern, including for Prisma-generated const enum objects (e.g., `IssueStatus`). Review Zod code to ensure enums are validated with `z.enum(...)` rather than `z.nativeEnum(...)`.

Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 130
File: src/features/chat/viper-agent/tools/get-recommendations-context.ts:203-205
Timestamp: 2026-05-18T16:33:45.705Z
Learning: In PATCH-UPGRADE/viper, treat `Asset`, `Vulnerability`, and `Remediation` records as shared/global resources. Their `userId` field is audit/attribution only and is not intended to enforce access-control scoping. Therefore, during review, do NOT flag cross-tenant data-leakage concerns for unscoped `prisma.asset.findMany`, `prisma.vulnerability.findMany`, or `prisma.remediation.findMany` queries on these models when no tenant scoping is expected. Only raise data-leakage flags when a query involves tenant-scoped resources/models (i.e., where tenant filtering is required), not these explicitly global ones.

Comment on lines +16 to +17
ipv4_address: z.string().nullable().optional(),
ipv6_address: z.string().nullable().optional(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Show the relevant section of the file
sed -n '1,120p' src/features/network/types.ts | nl -ba | sed -n '1,120p' > /tmp/types_head.txt
sed -n '1,60p' src/features/network/types.ts | nl -ba | sed -n '1,60p' > /tmp/types_top.txt
sed -n '10,40p' src/features/network/types.ts | nl -ba | sed -n '1,40p' > /tmp/types_10_40.txt

# 2) Find Zod import/version
rg -n "from ['\"]zod['\"]|require\(['\"]zod['\"]\)|zod" src/features/network/types.ts package.json pnpm-lock.yaml yarn.lock package-lock.json 2>/dev/null || true

# 3) Determine Zod version from lockfile/package.json
if [ -f package.json ]; then
  cat package.json > /tmp/package.json.txt
fi

# Try to read version from lockfiles (best-effort)
if [ -f pnpm-lock.yaml ]; then
  rg -n "zod@" pnpm-lock.yaml | head -n 20 > /tmp/zod_versions_lock.txt || true
fi
if [ -f package-lock.json ]; then
  rg -n "\"zod\"" package-lock.json | head -n 20 > /tmp/zod_versions_lock_npm.txt || true
fi
if [ -f yarn.lock ]; then
  rg -n "zod@" yarn.lock | head -n 20 > /tmp/zod_versions_lock_yarn.txt || true
fi

# 4) Print the captured outputs
echo "=== types.ts (lines 1-40) ==="
cat /tmp/types_10_40.txt
echo "=== package.json ==="
[ -f /tmp/package.json.txt ] && sed -n '1,160p' /tmp/package.json.txt || echo "No package.json found"
echo "=== zod references in relevant files ==="
ls -1 src/features/network/types.ts 2>/dev/null || true
echo "Search results: (may be empty)"
cat /tmp/zod_versions_lock.txt 2>/dev/null || true
cat /tmp/zod_versions_lock_npm.txt 2>/dev/null || true
cat /tmp/zod_versions_lock_yarn.txt 2>/dev/null || true

Repository: PATCH-UPGRADE/viper

Length of output: 106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Helpers: line-numbered views without `nl`
ln_view() { awk '{printf "%6d\t%s\n", NR, $0}' "$1" | sed -n "${2},${3}p"; }

# 1) Verify file exists + show relevant lines
echo "=== File existence ==="
ls -la src/features/network/types.ts || true

echo "=== types.ts lines 1-80 ==="
ln_view src/features/network/types.ts 1 80

echo "=== types.ts lines 10-30 ==="
ln_view src/features/network/types.ts 10 30

# 2) Find Zod import + usage
echo "=== Zod import/usage search (types.ts) ==="
rg -n "import .*zod|from ['\"]zod['\"]|require\(['\"]zod['\"]\)|\bz\.ipv[46]\b|\bzod\b" src/features/network/types.ts || true

# 3) Determine Zod version from package/lockfiles (best-effort)
echo "=== dependency files ==="
ls -ლა package.json pnpm-lock.yaml yarn.lock package-lock.json 2>/dev/null || true

if [ -f package.json ]; then
  echo "=== package.json (first 200 lines) ==="
  sed -n '1,200p' package.json
fi

# Grep lockfiles for zod version strings (best-effort)
for f in pnpm-lock.yaml package-lock.json yarn.lock; do
  if [ -f "$f" ]; then
    echo "=== Searching $f for zod ==="
    rg -n "zod" "$f" | head -n 30 || true
  fi
done

Repository: PATCH-UPGRADE/viper

Length of output: 10681


🌐 Web query:

Zod v4.1.11 z.ipv4 z.ipv6 methods availability

💡 Result:

In Zod v4, the z.ipv4() and z.ipv6() methods are available as top-level functions on the z module [1][2][3]. Key details regarding IP validation in Zod v4: 1. Method Availability: The previous approach of using z.string().ip() has been replaced by explicit, top-level validators: z.ipv4() and z.ipv6() [1][2]. While the old z.string().ip() method may still exist in some contexts as a deprecated feature, the official recommendation is to use the new, more tree-shakable top-level functions [2]. 2. Usage: You can use these methods directly to validate strings [3]. If you need to accept either an IPv4 or an IPv6 address, you can combine them using z.union() [1][4]: const ipSchema = z.union([z.ipv4, z.ipv6]); 3. Additional Validation: Zod v4 also provides top-level methods for CIDR block validation: z.cidrv4() and z.cidrv6() [5][2][3]. These changes improve performance and allow for better tree-shaking by removing the need to chain methods off z.string() [2].

Citations:


Harden IPv4/IPv6 address validation in networkInterfaceSchema.

ipv4_address and ipv6_address are currently z.string()..., so malformed addresses can pass validation at the contract boundary. Use Zod’s dedicated IPv4/IPv6 validators instead.

Suggested patch
-  ipv4_address: z.string().nullable().optional(),
-  ipv6_address: z.string().nullable().optional(),
+  ipv4_address: z.ipv4().nullable().optional(),
+  ipv6_address: z.ipv6().nullable().optional(),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ipv4_address: z.string().nullable().optional(),
ipv6_address: z.string().nullable().optional(),
ipv4_address: z.ipv4().nullable().optional(),
ipv6_address: z.ipv6().nullable().optional(),
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/network/types.ts` around lines 16 - 17, The ipv4_address and
ipv6_address fields on networkInterfaceSchema currently allow any string;
replace their definitions to use Zod's IP validators (e.g., for IPv4: use
z.string().ip({ version: "ipv4" }).optional().nullable(), and for IPv6: use
z.string().ip({ version: "ipv6" }).optional().nullable()) so malformed addresses
fail validation; update the properties named ipv4_address and ipv6_address in
networkInterfaceSchema accordingly.

Comment thread src/features/workflows/utils.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/features/chat/viper-agent/tools/get-recommendations-context.ts`:
- Around line 138-145: The code is stripping dependency edges by destructuring
out edges into _edges and building withoutEdges, losing workflow dependency
data; update the logic in get-recommendations-context (where serialized is
handled and withoutEdges is created) to include the edges property in the JSON
payload for the "Clinical Workflows" context (i.e., do not remove edges or merge
serialized.edges back into withoutEdges) so the output JSON.stringify contains
the full node + edges structure required by the model to represent dependencies,
CVSS, patch status and life_safety flags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9646a321-48ea-4dc1-be15-f9dc5c4e9060

📥 Commits

Reviewing files that changed from the base of the PR and between afa9317 and 72b077c.

📒 Files selected for processing (5)
  • scripts/print-recommendations-context.ts
  • src/features/assets/components/asset-drawer.tsx
  • src/features/chat/utils.ts
  • src/features/chat/viper-agent/tools/get-recommendations-context.ts
  • src/features/workflows/utils.ts

Comment on lines +138 to +145
const { edges: _edges, ...withoutEdges } = serialized;
const lines = [`### ${serialized.name} (${shortId(serialized.id)})`];
if (serialized.description) {
lines.push(`\n${serialized.description}`);
}
lines.push(
`\n\`\`\`json\n${JSON.stringify(withoutEdges, null, 2)}\n\`\`\``,
);
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot May 22, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t drop workflow dependency edges from context payload.

Line 138 and Line 144 remove edges from serialized workflows, which strips dependency structure from the “Clinical Workflows” context section.

Suggested patch
-      const { edges: _edges, ...withoutEdges } = serialized;
+      const workflowForContext = {
+        ...serialized,
+        edges: serialized.edges.map((e) => ({
+          source: e.source,
+          target: e.target,
+          sourceHandle: e.sourceHandle ?? null,
+          targetHandle: e.targetHandle ?? null,
+        })),
+      };
@@
-        `\n\`\`\`json\n${JSON.stringify(withoutEdges, null, 2)}\n\`\`\``,
+        `\n\`\`\`json\n${JSON.stringify(workflowForContext, null, 2)}\n\`\`\``,
       );

As per coding guidelines src/features/**/*.{ts,tsx}: “Model hospital systems as nodes representing clinical functions with edges for dependencies, including CVSS scores, patch status, and life_safety flags”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/chat/viper-agent/tools/get-recommendations-context.ts` around
lines 138 - 145, The code is stripping dependency edges by destructuring out
edges into _edges and building withoutEdges, losing workflow dependency data;
update the logic in get-recommendations-context (where serialized is handled and
withoutEdges is created) to include the edges property in the JSON payload for
the "Clinical Workflows" context (i.e., do not remove edges or merge
serialized.edges back into withoutEdges) so the output JSON.stringify contains
the full node + edges structure required by the model to represent dependencies,
CVSS, patch status and life_safety flags.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dropped edges because nodes are pretty much these very iterative steps, step 1, step 2, etc, and are enumerated in order. having edges to link step 1 to step 2 in the model context is a waste of tokens -- writing this for humans, not the rabbit

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@0xcad — That makes sense. If the workflow nodes are already ordered sequential steps, the edges are structurally redundant and stripping them is the right call for token efficiency. Acknowledged!

(ↂ_ↂ) 🐇


✏️ Learnings added
Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 138
File: src/features/chat/viper-agent/tools/get-recommendations-context.ts:138-145
Timestamp: 2026-05-22T15:43:42.654Z
Learning: In PATCH-UPGRADE/viper, workflow nodes in the `generateWorkflowsMarkdown` function (in `src/features/chat/viper-agent/tools/get-recommendations-context.ts`) are sequential steps (step 1, step 2, etc.) enumerated in order. Edges are intentionally stripped from the serialized workflow JSON sent to the LLM context to avoid wasting tokens — the ordering alone implies the dependencies. Do not flag the omission of edges in the Clinical Workflows context section as a bug or missing data.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 107
File: src/features/advisories/server/routers.ts:96-103
Timestamp: 2026-04-02T18:16:00.222Z
Learning: When reviewing TypeScript code that uses Zod v4 with Prisma-generated const enum objects, do not suggest replacing enum usage with `z.nativeEnum()`. In this project, `z.nativeEnum()` is deprecated under Zod v4—use the idiomatic pattern `z.enum(PrismaEnumObject)` (e.g., `z.enum(MyPrismaConstEnum)`), and treat direct `z.enum(PrismaEnumObject)` as the correct approach.

Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 107
File: src/features/advisories/server/routers.ts:96-103
Timestamp: 2026-04-02T18:16:00.223Z
Learning: When writing Zod schemas in this repository (PATCH-UPGRADE/viper), do not use `z.nativeEnum()`. The project uses Zod v4 where `z.nativeEnum()` is deprecated; prefer `z.enum(PrismaEnumObject)` as the idiomatic pattern, including for Prisma-generated const enum objects (e.g., `IssueStatus`). Review Zod code to ensure enums are validated with `z.enum(...)` rather than `z.nativeEnum(...)`.

Learnt from: 0xcad
Repo: PATCH-UPGRADE/viper PR: 130
File: src/features/chat/viper-agent/tools/get-recommendations-context.ts:203-205
Timestamp: 2026-05-18T16:33:45.705Z
Learning: In PATCH-UPGRADE/viper, treat `Asset`, `Vulnerability`, and `Remediation` records as shared/global resources. Their `userId` field is audit/attribution only and is not intended to enforce access-control scoping. Therefore, during review, do NOT flag cross-tenant data-leakage concerns for unscoped `prisma.asset.findMany`, `prisma.vulnerability.findMany`, or `prisma.remediation.findMany` queries on these models when no tenant scoping is expected. Only raise data-leakage flags when a query involves tenant-scoped resources/models (i.e., where tenant filtering is required), not these explicitly global ones.

@0xcad 0xcad changed the title [VW-265] TODO: babysit this PR a bit more [VW-265] Seed changes and context enrichment May 22, 2026
Comment thread prisma/flow.json
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should disappear with main rebase if VW-269 gets approved

Comment thread prisma/seed.ts
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big overhaul of seed.ts file, to try to more realistically model a rural hospital's imaging department (used for the demo narrative), rather than just throw random devices/vulnerabilities into our db

Also seeded workflows and memories for AI agent

I will, barring being hit by bus or something, modify this seed.ts file later to make it even more realistic for our hackathon challenge set scenario, but for now this is a good spot

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug script used to return tool call output, I just use this for token counting

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe I have to rebase off of main, once VW-269 gets merged in, to get this to disappear? But this was added in VW-269 (stacked git branches)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new updated at column makes it more obvious which assets were recently added from BF

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Add network topology data to AI context
  • Add device utilization data to AI context
  • Add serialized hospital workflow data to AI context

For now, all of these are pre-seeded in the db. We have ideas on how to eventually get these from a real hospital network/environment, but let's just give it to an AI and see if we can do anything useful with this first

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should disappear with main rebase if VW-269 gets approved

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should disappear with main rebase if VW-269 gets approved

Comment thread src/trpc/routers/_app.ts
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should disappear with main rebase if VW-269 gets approved

Comment thread .env.example
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should disappear with main rebase if VW-269 gets approved

@0xcad 0xcad merged commit 135361f into main May 22, 2026
7 checks passed
@0xcad 0xcad deleted the VW-265 branch May 22, 2026 17:21
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.

2 participants