# Prisma Phase 2 — Voice Path Attribution Discovery Time-boxed discovery notes for "voice is on this tunnel" / per-handset attribution. Phase 1 (runtime waninterface status, overlay tunnels, app DPI by `path_type`) ships without these. ## Confirmed Phase 1 surfaces (pan.dev + code) | Need | Endpoint | Notes | |------|----------|-------| | Circuit runtime status | `GET /sdwan/v2.1/api/sites/{siteId}/waninterfaces/{wiId}/status` | Wired in `getWanInterfaceStatus` | | Overlay tunnels | `POST /sdwan/v2.0/api/topology/links/query` with `query_params.{source\|target}_site_id.{in\|eq}` | Preferred — includes status, peer names, vpnlinks[] | | Anynet fallback | `POST /sdwan/v4.0/api/anynetlinks/query` with `query_params.ep{1\|2}_site_id.{eq\|in}` | Config rows; no runtime status | | Voice DPI by path_type | `getAppMetric` with `filter.path_type=[VPN]` etc. | AppPerf* only; AppAudioMos omits path_type | | Alarm → tunnel id | `info.vpn_reasons[].vpn_link_id` | `extractVpnLinkIdsFromAlarmInfo` | ## Live-tenant corrections (2026-07-28 / store 1005) | Issue | Fix | |-------|-----| | `limit: { count: N }` → 400 "expected int" | Topology/anynet `limit` is a bare int | | `query: { site_id: [...] }` silently ignored | Use `query_params: { field: { eq\|in: … } }` (array under query_params → 400) | | 100 tunnels all `peer — unknown` | Site-scoped topology query; resolve peer opposite local site; renderer collapses all-unknown | | `vpnlinks` have no site fields | Prefer topology links; anynet via ep1/ep2; never unscoped vpnlinks dump | | Pairing down volume | Prefer public-anynet; rank down/unknown first; cap ≤12; renderer shows ≤6 | | Cascading 429s | Path-type breakout gated by `PRISMA_VOICE_PATH_TYPE_BREAKOUT`; status GETs capped | Probe recipes: ```bash node scripts/prismaProbe.js wi-status node scripts/prismaProbe.js tunnels node scripts/prismaProbe.js app-by-path-type --metric loss node scripts/prismaProbe.js try-shapes app-by-path ``` ## Phase 2a candidates (probe before implementing further) 1. **App metrics + `filter.path`** (waninterface id) — already supported in `getAppMetric({ pathIds })` behind `PRISMA_VOICE_PATH_ATTRIBUTION=1`. Confirm live tenant accepts the filter (SCHEMA_CHECK_FAIL risk). 2. **Flow / session / app-path details** — SCM UI "Application Path Details" HAR may reveal monitor endpoints that bind RTP to a specific path. Candidates: topology query v3.6, object_stats, app/wan contexts. 3. **Join keys to Webex** — need client IP, subnet, or device id in Prisma flow records to map to Meraki/Webex handset inventory. **Not confirmed.** ## Phase 2c status `attributeVoicePathToEndpoint()` in `services/callReport/voicePathAttribution.js` returns `null` until a join key is confirmed. Path-level / path_type-level annotation is live via `annotateWanWithPath()`. ## Confidence language | Level | Meaning | |-------|---------| | `site` | Site-wide DPI only (`siteLevelApprox: true`) | | `path_type` | One path_type uniquely worse in window | | `path` | One waninterface uniquely worse (`byPath`) | | `endpoint` | Per-handset — **not available** without flow join keys |