{
  "version": "Notebook/1.0",
  "items": [
    {
      "type": 9,
      "content": {
        "version": "KqlParameterItem/1.0",
        "parameters": [
          {
            "id": "7b05a598-5120-43f4-bf5d-576c2a7ff28d",
            "version": "KqlParameterItem/1.0",
            "name": "TimeRange",
            "type": 4,
            "isRequired": true,
            "value": {
              "durationMs": 86400000
            },
            "typeSettings": {
              "selectableValues": [
                {
                  "durationMs": 3600000
                },
                {
                  "durationMs": 14400000
                },
                {
                  "durationMs": 43200000
                },
                {
                  "durationMs": 86400000
                },
                {
                  "durationMs": 172800000
                },
                {
                  "durationMs": 604800000
                },
                {
                  "durationMs": 2592000000
                }
              ]
            }
          }
        ],
        "style": "pills",
        "queryType": 0,
        "resourceType": "microsoft.operationalinsights/workspaces"
      },
      "name": "parameters"
    },
    {
      "type": 1,
      "content": {
        "json": "<div style=\"display:flex;align-items:center;padding:8px 0 16px 0;border-bottom:1px solid #1e293b\"><svg width=\"40\" height=\"40\" style=\"margin-right:14px;flex-shrink:0;fill:#3b82f6\" xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 512 512\"><path d=\"M65.6 127.7c35.3 0 63.9-28.6 63.9-63.9S100.9 0 65.6 0 1.8 28.6 1.8 63.9s28.6 63.8 63.8 63.8\" opacity=\".2\"/><path d=\"M65.6 318.1c35.3 0 63.9-28.6 63.9-63.9s-28.6-63.9-63.9-63.9S1.8 219 1.8 254.2s28.6 63.9 63.8 63.9\"/><path d=\"M65.6 512c35.3 0 63.9-28.6 63.9-63.9s-28.6-63.9-63.9-63.9-63.8 28.7-63.8 63.9S30.4 512 65.6 512\" opacity=\".2\"/><path d=\"M257.2 318.1c35.3 0 63.9-28.6 63.9-63.9s-28.6-63.9-63.9-63.9-63.9 28.6-63.9 63.9 28.6 63.9 63.9 63.9m0 193.9c35.3 0 63.9-28.6 63.9-63.9s-28.6-63.9-63.9-63.9-63.9 28.6-63.9 63.9 28.6 63.9 63.9 63.9\"/><path d=\"M257.2 127.7c35.3 0 63.9-28.6 63.9-63.9S292.5 0 257.2 0s-63.9 28.6-63.9 63.9 28.6 63.8 63.9 63.8m189.2 0c35.3 0 63.9-28.6 63.9-63.9S481.6 0 446.4 0c-35.3 0-63.9 28.6-63.9 63.9s28.6 63.8 63.9 63.8\" opacity=\".2\"/><path d=\"M446.4 318.1c35.3 0 63.9-28.6 63.9-63.9s-28.6-63.9-63.9-63.9-63.9 28.6-63.9 63.9 28.6 63.9 63.9 63.9\"/><path d=\"M446.4 512c35.3 0 63.9-28.6 63.9-63.9s-28.6-63.9-63.9-63.9-63.9 28.6-63.9 63.9 28.6 63.9 63.9 63.9\" opacity=\".2\"/></svg><div><div style=\"font-size:22px;font-weight:600;letter-spacing:-0.5px\">Tailscale Operations (Standard)</div><div style=\"font-size:13px;color:#94a3b8;margin-top:2px\">Single-pane visibility into your Tailscale tailnet on Personal (Free), Starter and Standard tiers: who, what, when, where, and what changed. Scope every panel with the time range below; the Investigate tab adds Actor and Device pickers for drilldown. Premium-tier panels (network flow logs, posture integrations) live in the separate <strong>Tailscale Operations (Premium)</strong> workbook.</div></div></div>"
      },
      "name": "header"
    },
    {
      "type": 11,
      "content": {
        "version": "LinkItem/1.0",
        "style": "tabs",
        "links": [
          {
            "id": "9794e9fd-916b-494d-8e72-af63d2f4c6c7",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Overview",
            "subTarget": "overview",
            "style": "link"
          },
          {
            "id": "71cf49db-33c5-4d4b-920a-2ec0c6a258dc",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Investigate",
            "subTarget": "investigate",
            "style": "link"
          },
          {
            "id": "5c56bb37-2053-47a0-b6fd-9539768c144d",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Hunts",
            "subTarget": "hunts",
            "style": "link"
          },
          {
            "id": "d2004ded-07f8-446a-a720-f0a63d1d9dda",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Identity",
            "subTarget": "identity",
            "style": "link"
          },
          {
            "id": "f23b3e14-1511-4a29-bf5e-bd65e55dbb40",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Devices",
            "subTarget": "devices",
            "style": "link"
          },
          {
            "id": "724f8352-e21b-45a6-9029-39dc92693c05",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Credentials",
            "subTarget": "credentials",
            "style": "link"
          },
          {
            "id": "8400ec64-e118-44e0-ae29-84afe94b8e0e",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Admin Audit",
            "subTarget": "audit",
            "style": "link"
          },
          {
            "id": "b7e04861-edfa-4426-b6be-f1481ca569b6",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Network & DNS",
            "subTarget": "network",
            "style": "link"
          },
          {
            "id": "cfbc96e4-8585-4d89-8f65-8344c8cc6eb2",
            "cellValue": "selectedTab",
            "linkTarget": "parameter",
            "linkLabel": "Pipeline Health",
            "subTarget": "pipeline",
            "style": "link"
          }
        ]
      },
      "name": "tabs"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Tailnet at a glance</div>"
            },
            "name": "div-tailnet-at-a-glance-04e62b"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let DEV = Tailscale_Devices_CL | summarize arg_max(TimeGenerated, *) by DeviceId;\nlet USR = Tailscale_Users_CL   | summarize arg_max(TimeGenerated, *) by UserId;\nlet KEY = Tailscale_Keys_CL    | summarize arg_max(TimeGenerated, *) by KeyId;\nunion\n  (DEV | summarize V=toreal(count())                                            | extend Metric=\"Devices\",         Order=1),\n  (DEV | where Authorized == true                                               | summarize V=toreal(count()) | extend Metric=\"Authorized\",      Order=2),\n  (DEV | where UpdateAvailable == true                                          | summarize V=toreal(count()) | extend Metric=\"Updates Available\", Order=3),\n  (DEV | where SshEnabled == true                                               | summarize V=toreal(count()) | extend Metric=\"SSH-Enabled\",     Order=4),\n  (USR | summarize V=toreal(count())                                            | extend Metric=\"Users\",           Order=5),\n  (USR | where Role =~ \"admin\" or Role =~ \"owner\" or Role =~ \"network-admin\"    | summarize V=toreal(count()) | extend Metric=\"Admins\",          Order=6),\n  (KEY | where isnull(Revoked) and (isnull(Expires) or Expires > now())         | summarize V=toreal(count()) | extend Metric=\"Active Keys\",     Order=7),\n  (Tailscale_Audit_CL | where TimeGenerated {TimeRange} | summarize V=toreal(count()) | extend Metric=\"Audit Events ({TimeRange:label})\", Order=8)\n| order by Order asc | project Metric, Value=V",
              "size": 3,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "tiles",
              "tileSettings": {
                "titleContent": {
                  "columnMatch": "Metric",
                  "formatter": 1
                },
                "leftContent": {
                  "columnMatch": "Value",
                  "formatter": 12,
                  "formatOptions": {
                    "palette": "auto"
                  }
                },
                "showBorder": false
              }
            },
            "name": "q-4e9d7cff"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Audit activity over time</div>"
            },
            "name": "div-audit-activity-over--546688"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| summarize EventCount = count() by bin(TimeGenerated, 1h), Action\n| order by TimeGenerated asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "timechart",
              "title": "Audit events by action",
              "noDataMessage": "No audit events in the selected window. Widen the time range; remember the Tailscale audit poll runs every ~30 min.",
              "noDataMessageStyle": 5
            },
            "name": "q-effcd498"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Who's doing what</div>"
            },
            "name": "div-who's-doing-what-52144e"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend Actor=tostring(coalesce(Actor.loginName, Actor.displayName, Actor.type))\n| where isnotempty(Actor)\n| summarize Events=count(), DistinctActions=dcount(Action), LastSeen=max(TimeGenerated) by Actor\n| order by Events desc | take 15",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Top actors (by event count)",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Events",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "blue"
                    }
                  },
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              }
            },
            "name": "q-34c77fa9",
            "customWidth": "50"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend TargetType=tostring(Target.type)\n| where isnotempty(TargetType)\n| summarize Events=count() by TargetType\n| order by Events desc | take 15",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Activity by target type"
            },
            "name": "q-4b3b709d",
            "customWidth": "50"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Recent admin events</div>"
            },
            "name": "div-recent-admin-events-87c9e0"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend Actor=tostring(coalesce(Actor.loginName, Actor.displayName, Actor.type))\n| extend TargetType=tostring(Target.type), TargetName=tostring(coalesce(Target.name, Target.id))\n| project TimeGenerated, Action, Actor, TargetType, TargetName, Origin\n| order by TimeGenerated desc | take 30",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Most recent 30 audit events",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              }
            },
            "name": "q-5e7d6306"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "overview"
      },
      "name": "group-overview"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 9,
            "content": {
              "version": "KqlParameterItem/1.0",
              "parameters": [
                {
                  "id": "b83a25c1-da18-49a2-a444-6517f13d891c",
                  "version": "KqlParameterItem/1.0",
                  "name": "SelectedActor",
                  "label": "Actor",
                  "type": 2,
                  "isRequired": false,
                  "query": "let opts = Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| where isnotempty(ActorLogin)\n| summarize Events=count() by ActorLogin\n| project value=ActorLogin, label=strcat(ActorLogin, \" (\", tostring(Events), \" events)\");\n(print value=\"__ALL__\", label=\"(All actors)\")\n| union opts",
                  "typeSettings": {
                    "showDefault": false
                  },
                  "queryType": 0,
                  "resourceType": "microsoft.operationalinsights/workspaces",
                  "value": "__ALL__"
                }
              ],
              "style": "pills",
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces"
            },
            "name": "investigate-picker-actor"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Actor activity timeline</div>"
            },
            "name": "div-actor-activity-timel-5ec305"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| where \"{SelectedActor}\" == \"__ALL__\" or ActorLogin == \"{SelectedActor}\"\n| summarize Events=count() by bin(TimeGenerated, 1h), Action\n| order by TimeGenerated asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "timechart",
              "title": "Actions over time -- actor: {SelectedActor:label}",
              "noDataMessage": "Select an actor from the Actor dropdown above, or leave on 'All' to see total activity.",
              "noDataMessageStyle": 5
            },
            "name": "q-32d40848"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| where \"{SelectedActor}\" == \"__ALL__\" or ActorLogin == \"{SelectedActor}\"\n| extend TargetType=tostring(Target.type), TargetName=tostring(coalesce(Target.name, Target.id))\n| project TimeGenerated, ActorLogin, Action, TargetType, TargetName, Origin\n| order by TimeGenerated desc | take 100",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Recent events for actor: {SelectedActor:label}",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No events for this actor in the selected window.",
              "noDataMessageStyle": 5
            },
            "name": "q-a742f6fd"
          },
          {
            "type": 9,
            "content": {
              "version": "KqlParameterItem/1.0",
              "parameters": [
                {
                  "id": "a9cf7907-f201-4725-a072-a8bd34bef74e",
                  "version": "KqlParameterItem/1.0",
                  "name": "SelectedDevice",
                  "label": "Device",
                  "type": 2,
                  "isRequired": false,
                  "query": "let opts = Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| order by LastSeen desc | take 100\n| project value=DeviceName, label=strcat(coalesce(DeviceName, Hostname), \" (\", User, \")\");\n(print value=\"__ALL__\", label=\"(All devices)\")\n| union opts",
                  "typeSettings": {
                    "showDefault": false
                  },
                  "queryType": 0,
                  "resourceType": "microsoft.operationalinsights/workspaces",
                  "value": "__ALL__"
                }
              ],
              "style": "pills",
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces"
            },
            "name": "investigate-picker-device"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Selected device timeline</div>"
            },
            "name": "div-selected-device-time-00bead"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| where \"{SelectedDevice}\" == \"__ALL__\" or DeviceName == \"{SelectedDevice}\"\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| extend OnlineNow = ClientConnectivity.endpoints != \"\" or ConnectedToControl == true\n| project DeviceName, Hostname, User, Os, ClientVersion, UpdateAvailable, Authorized, IsExternal, SshEnabled, LastSeen, Expires, KeyExpiryDisabled, OnlineNow, Addresses, Tags, AdvertisedRoutes",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Summary for device: {SelectedDevice:label}",
              "noDataMessage": "Select a device from the Device dropdown above. Defaults to 'All'.",
              "noDataMessageStyle": 5
            },
            "name": "q-11094dc8"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend TargetType=tostring(Target.type), TargetName=tostring(Target.name), TargetId=tostring(Target.id)\n| where (\"{SelectedDevice}\" == \"__ALL__\" and TargetType == \"NODE\") or TargetName == \"{SelectedDevice}\"\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| project TimeGenerated, Action, ActorLogin, TargetName, TargetId, Origin\n| order by TimeGenerated desc | take 100",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Audit events touching device: {SelectedDevice:label}",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No audit events recorded against the selected device in this window. Tailscale tags device events with Target.type=NODE; the audit feed only emits NODE events on create/update/delete, so quiet devices stay quiet here.",
              "noDataMessageStyle": 5
            },
            "name": "q-ead106ce"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "investigate"
      },
      "name": "group-investigate"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">First-seen actors in the last 24h</div>"
            },
            "name": "div-first-seen-actors-in-ce38d9"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let recent = Tailscale_Audit_CL | where TimeGenerated > ago(24h) | extend A=tostring(coalesce(Actor.loginName, Actor.displayName)) | summarize FirstSeen24h=min(TimeGenerated), Events=count() by A;\nlet historical = Tailscale_Audit_CL | where TimeGenerated between(ago(30d) .. ago(24h)) | extend A=tostring(coalesce(Actor.loginName, Actor.displayName)) | distinct A;\nrecent | join kind=leftanti historical on A | where isnotempty(A) | project FirstSeen24h, Actor=A, Events | order by Events desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Actors who have NEVER appeared before (30d baseline)",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "FirstSeen24h",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Events",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "orange"
                    }
                  }
                ]
              },
              "noDataMessage": "Every actor seen in the last 24h has appeared at least once in the prior 30d. Healthy state.",
              "noDataMessageStyle": 1
            },
            "name": "q-9ba7b85e"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Off-hours configuration changes</div>"
            },
            "name": "div-off-hours-configurat-3c3787"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend Hour=hourofday(TimeGenerated), DayOfWeek=dayofweek(TimeGenerated)/1d\n| where Hour < 7 or Hour > 19 or DayOfWeek in (0, 6)\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| extend TargetType=tostring(Target.type)\n| where Action !in (\"LOGIN\", \"LOGOUT\")\n| project TimeGenerated, ActorLogin, Action, TargetType, Origin\n| order by TimeGenerated desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Admin actions outside 07:00-19:00 weekdays",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No off-hours admin changes recorded - healthy state for an organisation working business hours.",
              "noDataMessageStyle": 1
            },
            "name": "q-721ee490"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Devices with key expiry disabled</div>"
            },
            "name": "div-devices-with-key-exp-dfe9c1"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where KeyExpiryDisabled == true\n| project DeviceName, Hostname, User, Os, ClientVersion, LastSeen, Authorized, Tags\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices that will never re-authenticate (high-risk drift)",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No devices have key expiry disabled - good. Disabling key expiry creates devices that never re-auth, drifting from policy.",
              "noDataMessageStyle": 1
            },
            "name": "q-8a8e2fb5"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Auth keys with no expiry</div>"
            },
            "name": "div-auth-keys-with-no-ex-b11207"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Keys_CL\n| summarize arg_max(TimeGenerated, *) by KeyId\n| where isnull(Revoked) and (isnull(Expires) or ExpirySeconds == 0)\n| project KeyId, Description, UserId, KeyType, Created, Capabilities\n| order by Created desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Active keys that never expire",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Created",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No never-expiring auth keys - rotation hygiene is good.",
              "noDataMessageStyle": 1
            },
            "name": "q-1372740c"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Devices running outdated clients</div>"
            },
            "name": "div-devices-running-outd-bcd077"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where UpdateAvailable == true\n| project DeviceName, Hostname, User, Os, ClientVersion, LastSeen, Tags\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices flagged update-available by Tailscale",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "All devices on current client - nothing to patch.",
              "noDataMessageStyle": 1
            },
            "name": "q-ecebf1f7"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Dormant devices (LastSeen > 30 days)</div>"
            },
            "name": "div-dormant-devices-(las-761156"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where LastSeen < ago(30d)\n| extend DaysIdle = toint((now() - LastSeen) / 1d)\n| project DeviceName, Hostname, User, Os, ClientVersion, LastSeen, DaysIdle, Authorized, Tags\n| order by DaysIdle desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices idle 30+ days - candidates for retirement",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "DaysIdle",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright"
                    }
                  }
                ]
              },
              "noDataMessage": "No devices idle 30+ days - inventory is fresh.",
              "noDataMessageStyle": 1
            },
            "name": "q-fb6c1fcc"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Subnet route exposure</div>"
            },
            "name": "div-subnet-route-exposur-289c42"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where array_length(AdvertisedRoutes) > 0 or array_length(EnabledRoutes) > 0\n| extend Routes = tostring(EnabledRoutes), Advertised = tostring(AdvertisedRoutes)\n| project DeviceName, Hostname, User, Os, Advertised, Routes, LastSeen, SshEnabled, Authorized\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices advertising or running subnet routes / exit-node duty",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No devices advertising subnet routes. Pure mesh topology.",
              "noDataMessageStyle": 1
            },
            "name": "q-9533b081"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Devices with SSH enabled</div>"
            },
            "name": "div-devices-with-ssh-ena-285238"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where SshEnabled == true\n| project DeviceName, Hostname, User, Os, ClientVersion, LastSeen, Authorized, Tags\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices with Tailscale SSH enabled (Tailscale-managed remote-shell access)",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No devices have Tailscale SSH enabled - no SSH-via-Tailscale risk surface.",
              "noDataMessageStyle": 1
            },
            "name": "q-735368fb"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "hunts"
      },
      "name": "group-hunts"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">User inventory snapshot</div>"
            },
            "name": "div-user-inventory-snaps-9dc96c"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let U = Tailscale_Users_CL | summarize arg_max(TimeGenerated, *) by UserId;\nunion\n  (U | summarize V=toreal(count())                                                | extend Metric=\"Total users\",        Order=1),\n  (U | where Role in~ (\"admin\",\"owner\",\"network-admin\",\"it-admin\",\"billing-admin\") | summarize V=toreal(count()) | extend Metric=\"Admin-tier users\",  Order=2),\n  (U | where Status =~ \"active\"                                                   | summarize V=toreal(count()) | extend Metric=\"Active\",            Order=3),\n  (U | where CurrentlyConnected == true                                           | summarize V=toreal(count()) | extend Metric=\"Connected now\",     Order=4),\n  (U | where Status =~ \"idle\" or LastSeen < ago(30d)                              | summarize V=toreal(count()) | extend Metric=\"Idle / dormant\",    Order=5),\n  (U | where UserType =~ \"shared\"                                                 | summarize V=toreal(count()) | extend Metric=\"Shared (external)\", Order=6)\n| order by Order asc | project Metric, Value=V",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "tiles",
              "tileSettings": {
                "titleContent": {
                  "columnMatch": "Metric",
                  "formatter": 1
                },
                "leftContent": {
                  "columnMatch": "Value",
                  "formatter": 12,
                  "formatOptions": {
                    "palette": "auto"
                  }
                },
                "showBorder": false
              }
            },
            "name": "q-5689d9e8"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Distribution</div>"
            },
            "name": "div-distribution-de67ec"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Users_CL\n| summarize arg_max(TimeGenerated, *) by UserId\n| summarize Count=count() by Role\n| order by Count desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Users by role"
            },
            "name": "q-0c47912a",
            "customWidth": "33"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Users_CL\n| summarize arg_max(TimeGenerated, *) by UserId\n| summarize Count=count() by Status\n| order by Count desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Users by status"
            },
            "name": "q-e8c20a69",
            "customWidth": "33"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Users_CL\n| summarize arg_max(TimeGenerated, *) by UserId\n| summarize Count=count() by UserType\n| order by Count desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Users by type (member / shared)"
            },
            "name": "q-2c51776d",
            "customWidth": "33"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Activity heatmap</div>"
            },
            "name": "div-activity-heatmap-ca6a21"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Users_CL\n| summarize arg_max(TimeGenerated, *) by UserId\n| extend DaysSinceLogin = toint((now() - LastSeen) / 1d)\n| extend Bucket = case(\n    DaysSinceLogin < 1, \"Today\",\n    DaysSinceLogin < 7, \"This week\",\n    DaysSinceLogin < 30, \"This month\",\n    DaysSinceLogin < 90, \"Past quarter\",\n    \"90+ days\")\n| summarize Users=count() by Bucket\n| order by case(Bucket==\"Today\",1, Bucket==\"This week\",2, Bucket==\"This month\",3, Bucket==\"Past quarter\",4, 5) asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "barchart",
              "title": "Users by recency of last login"
            },
            "name": "q-350e118d"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Full user list</div>"
            },
            "name": "div-full-user-list-136aac"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Users_CL\n| summarize arg_max(TimeGenerated, *) by UserId\n| project DisplayName, LoginName, Role, Status, UserType, DeviceCount, CurrentlyConnected, Created, LastSeen\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "All users (latest snapshot per user ID)",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Created",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Role",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "Status",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "DeviceCount",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "blue"
                    }
                  }
                ]
              }
            },
            "name": "q-cee23d3c"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Orphaned users (active but no devices)</div>"
            },
            "name": "div-orphaned-users-(acti-56d6f8"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Users_CL\n| summarize arg_max(TimeGenerated, *) by UserId\n| where Status =~ \"active\" and DeviceCount == 0\n| project DisplayName, LoginName, Role, UserType, Created, LastSeen\n| order by Created desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Active accounts with zero devices - candidates for offboarding review",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Created",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "Every active account has at least one device - good hygiene.",
              "noDataMessageStyle": 1
            },
            "name": "q-83fcd942"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Role escalation history</div>"
            },
            "name": "div-role-escalation-hist-bd8df4"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| where Action == \"USER_ROLE_UPDATE\" or Action == \"USER_ROLES_ASSIGNED\" or Action contains \"ROLE\"\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| extend TargetName=tostring(coalesce(Target.name, Target.id))\n| extend FromRole=tostring(Old.role), ToRole=tostring(New.role)\n| project TimeGenerated, ActorLogin, Action, TargetName, FromRole, ToRole, Origin\n| order by TimeGenerated desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Recent role changes",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "ToRole",
                    "formatter": 1
                  }
                ]
              },
              "noDataMessage": "No role changes in this window.",
              "noDataMessageStyle": 1
            },
            "name": "q-f6c8358a"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "identity"
      },
      "name": "group-identity"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Device fleet snapshot</div>"
            },
            "name": "div-device-fleet-snapsho-939675"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let D = Tailscale_Devices_CL | summarize arg_max(TimeGenerated, *) by DeviceId;\nunion\n  (D | summarize V=toreal(count())                              | extend Metric=\"Total devices\",       Order=1),\n  (D | where Authorized == true                                 | summarize V=toreal(count()) | extend Metric=\"Authorized\",          Order=2),\n  (D | where IsExternal == true                                 | summarize V=toreal(count()) | extend Metric=\"External (shared)\",   Order=3),\n  (D | where UpdateAvailable == true                            | summarize V=toreal(count()) | extend Metric=\"Updates available\",   Order=4),\n  (D | where SshEnabled == true                                 | summarize V=toreal(count()) | extend Metric=\"SSH-enabled\",         Order=5),\n  (D | where KeyExpiryDisabled == true                          | summarize V=toreal(count()) | extend Metric=\"No key expiry\",       Order=6),\n  (D | where array_length(AdvertisedRoutes) > 0                 | summarize V=toreal(count()) | extend Metric=\"Subnet/exit-node\",    Order=7),\n  (D | where LastSeen < ago(30d)                                | summarize V=toreal(count()) | extend Metric=\"Stale (30+ days)\",    Order=8)\n| order by Order asc | project Metric, Value=V",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "tiles",
              "tileSettings": {
                "titleContent": {
                  "columnMatch": "Metric",
                  "formatter": 1
                },
                "leftContent": {
                  "columnMatch": "Value",
                  "formatter": 12,
                  "formatOptions": {
                    "palette": "auto"
                  }
                },
                "showBorder": false
              }
            },
            "name": "q-366964fc"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Distribution</div>"
            },
            "name": "div-distribution-396d03"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| summarize Count=count() by Os\n| order by Count desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Devices by OS"
            },
            "name": "q-0c8f5988",
            "customWidth": "33"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| summarize Count=count() by ClientVersion\n| order by Count desc | take 10",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "barchart",
              "title": "Top 10 client versions"
            },
            "name": "q-af1c45cd",
            "customWidth": "33"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| mv-expand Tag = Tags to typeof(string)\n| summarize Devices=dcount(DeviceId) by Tag=iff(isempty(Tag), \"(untagged)\", Tag)\n| order by Devices desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Devices by tag"
            },
            "name": "q-c3a0ef5b",
            "customWidth": "33"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Devices needing attention</div>"
            },
            "name": "div-devices-needing-atte-f04a47"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where UpdateAvailable == true or KeyExpiryDisabled == true or LastSeen < ago(30d) or Authorized == false\n| extend Issues = strcat_array(pack_array(\n    iff(UpdateAvailable == true, \"needs-update\", \"\"),\n    iff(KeyExpiryDisabled == true, \"key-never-expires\", \"\"),\n    iff(LastSeen < ago(30d), \"stale\", \"\"),\n    iff(Authorized == false, \"unauthorized\", \"\")), \",\")\n| extend Issues = trim(\",\", trim_start(\",\", trim_end(\",\", replace_string(Issues, \",,\", \",\"))))\n| project DeviceName, Hostname, User, Os, ClientVersion, LastSeen, Issues\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices flagged with one or more issues",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Issues",
                    "formatter": 1
                  }
                ]
              },
              "noDataMessage": "No devices need attention - all updated, fresh, authorized, and key-rotating.",
              "noDataMessageStyle": 1
            },
            "name": "q-dc5db84c"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Full device inventory</div>"
            },
            "name": "div-full-device-inventor-b70642"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| project DeviceName, Hostname, User, Os, ClientVersion, UpdateAvailable, Authorized, IsExternal, SshEnabled, LastSeen, KeyExpiryDisabled, Tags, AdvertisedRoutes\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "All devices (latest snapshot per device ID)",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Os",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "ClientVersion",
                    "formatter": 1
                  }
                ]
              }
            },
            "name": "q-7f7e7a9a"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Subnet routers / exit nodes</div>"
            },
            "name": "div-subnet-routers-/-exi-b082d6"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where array_length(AdvertisedRoutes) > 0\n| extend AdvertisedSummary = tostring(AdvertisedRoutes), EnabledSummary = tostring(EnabledRoutes)\n| project DeviceName, Hostname, User, Os, AdvertisedSummary, EnabledSummary, LastSeen, Authorized\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Devices advertising subnet routes or exit-node capability",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No subnet routers in this tailnet - pure mesh topology.",
              "noDataMessageStyle": 1
            },
            "name": "q-5004df25"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "devices"
      },
      "name": "group-devices"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Credentials snapshot</div>"
            },
            "name": "div-credentials-snapshot-fd464a"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "let K = Tailscale_Keys_CL | summarize arg_max(TimeGenerated, *) by KeyId;\nunion\n  (K | summarize V=toreal(count())                                     | extend Metric=\"Total keys\",          Order=1),\n  (K | where isnull(Revoked) and (isnull(Expires) or Expires > now())  | summarize V=toreal(count()) | extend Metric=\"Active\",              Order=2),\n  (K | where isnotnull(Revoked)                                        | summarize V=toreal(count()) | extend Metric=\"Revoked\",             Order=3),\n  (K | where Expires < now() and isnull(Revoked)                       | summarize V=toreal(count()) | extend Metric=\"Expired\",             Order=4),\n  (K | where isnull(Revoked) and Expires between(now() .. ago(-7d))    | summarize V=toreal(count()) | extend Metric=\"Expiring in 7d\",      Order=5),\n  (K | where isnull(Revoked) and (isnull(Expires) or ExpirySeconds==0) | summarize V=toreal(count()) | extend Metric=\"Never expire\",        Order=6),\n  (K | where KeyType =~ \"auth\"                                         | summarize V=toreal(count()) | extend Metric=\"Auth keys\",           Order=7),\n  (K | where KeyType =~ \"api\" or KeyType contains \"oauth\"              | summarize V=toreal(count()) | extend Metric=\"API / OAuth\",         Order=8)\n| order by Order asc | project Metric, Value=V",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "tiles",
              "tileSettings": {
                "titleContent": {
                  "columnMatch": "Metric",
                  "formatter": 1
                },
                "leftContent": {
                  "columnMatch": "Value",
                  "formatter": 12,
                  "formatOptions": {
                    "palette": "auto"
                  }
                },
                "showBorder": false
              }
            },
            "name": "q-79398bc0"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Distribution</div>"
            },
            "name": "div-distribution-15f665"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Keys_CL\n| summarize arg_max(TimeGenerated, *) by KeyId\n| summarize Count=count() by KeyType\n| order by Count desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "piechart",
              "title": "Keys by type"
            },
            "name": "q-23e6618b",
            "customWidth": "50"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Keys_CL\n| summarize arg_max(TimeGenerated, *) by KeyId\n| where isnull(Revoked)\n| extend Bucket = case(\n    isnull(Expires) or ExpirySeconds == 0, \"Never\",\n    Expires < now(), \"Already expired\",\n    Expires < ago(-1d), \"<24h\",\n    Expires < ago(-7d), \"1-7d\",\n    Expires < ago(-30d), \"8-30d\",\n    Expires < ago(-90d), \"31-90d\",\n    \"90+d\")\n| summarize Keys=count() by Bucket\n| order by case(Bucket==\"Already expired\",1, Bucket==\"<24h\",2, Bucket==\"1-7d\",3, Bucket==\"8-30d\",4, Bucket==\"31-90d\",5, Bucket==\"90+d\",6, Bucket==\"Never\",7, 8) asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "barchart",
              "title": "Active key expiry distribution"
            },
            "name": "q-7484d1a0",
            "customWidth": "50"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Active credential register</div>"
            },
            "name": "div-active-credential-re-c27539"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Keys_CL\n| summarize arg_max(TimeGenerated, *) by KeyId\n| where isnull(Revoked)\n| extend ExpiryStatus = case(\n    isnull(Expires) or ExpirySeconds == 0, \"Never expires\",\n    Expires < now(), \"Expired\",\n    Expires < ago(-7d), \"Expires in 7d\",\n    Expires < ago(-30d), \"Expires in 30d\",\n    \"OK\")\n| project KeyId, KeyType, Description, UserId, Created, Expires, ExpiryStatus, Capabilities\n| order by Created desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "All active credentials with computed expiry status",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Created",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Expires",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "ExpiryStatus",
                    "formatter": 1
                  },
                  {
                    "columnMatch": "KeyType",
                    "formatter": 1
                  }
                ]
              }
            },
            "name": "q-4b27a750"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Credential CRUD events</div>"
            },
            "name": "div-credential-crud-even-e455b0"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| where Action contains \"API_KEY\" or Action contains \"AUTH_KEY\" or Action contains \"OAUTH\" or Action contains \"KEY_CREATE\" or Action contains \"KEY_REVOKE\"\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| extend TargetId=tostring(Target.id), TargetType=tostring(Target.type)\n| project TimeGenerated, Action, ActorLogin, TargetType, TargetId, Origin\n| order by TimeGenerated desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Recent credential create / revoke / rotate events",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No credential CRUD activity in this window.",
              "noDataMessageStyle": 1
            },
            "name": "q-777693bd"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "credentials"
      },
      "name": "group-credentials"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Audit volume</div>"
            },
            "name": "div-audit-volume-de29a2"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| summarize Events=count() by bin(TimeGenerated, 1h)\n| order by TimeGenerated asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "timechart",
              "title": "Audit events per hour",
              "noDataMessage": "No audit events in this window.",
              "noDataMessageStyle": 5
            },
            "name": "q-f5eee265"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Action heatmap by hour of day</div>"
            },
            "name": "div-action-heatmap-by-ho-c8bd5e"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend Hour=hourofday(TimeGenerated)\n| summarize Events=count() by Hour, Action\n| order by Hour asc, Events desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "categoricalbar",
              "title": "When are admin actions happening?"
            },
            "name": "q-c6f45d95"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Actor / Action heatmap</div>"
            },
            "name": "div-actor-/-action-heatm-d820ba"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| where isnotempty(ActorLogin)\n| summarize Events=count() by ActorLogin, Action\n| order by Events desc | take 100",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Who is firing which action",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "Events",
                    "formatter": 4,
                    "formatOptions": {
                      "palette": "blue"
                    }
                  }
                ]
              },
              "noDataMessage": "No audit events in this window.",
              "noDataMessageStyle": 5
            },
            "name": "q-06c13b3b"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Recent activity</div>"
            },
            "name": "div-recent-activity-63b210"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| extend TargetType=tostring(Target.type), TargetName=tostring(coalesce(Target.name, Target.id))\n| project TimeGenerated, Action, ActorLogin, TargetType, TargetName, Origin, EventGroupID\n| order by TimeGenerated desc | take 100",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Last 100 audit events",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Action",
                    "formatter": 1
                  }
                ]
              },
              "noDataMessage": "No audit events in this window.",
              "noDataMessageStyle": 5
            },
            "name": "q-07a25a40"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "audit"
      },
      "name": "group-audit"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">DNS configuration (current state)</div>"
            },
            "name": "div-dns-configuration-(c-5f2e1e"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Dns_CL\n| summarize arg_max(TimeGenerated, *) by ConfigType\n| project ConfigType, Nameservers, MagicDNS, SearchPaths, LastSnapshot=TimeGenerated\n| order by ConfigType asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "MagicDNS, nameservers, search paths",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSnapshot",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "ConfigType",
                    "formatter": 1
                  }
                ]
              },
              "noDataMessage": "No DNS snapshots in the workspace yet. DNS polls runs at ~30 min cadence.",
              "noDataMessageStyle": 5
            },
            "name": "q-d6a6a358"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Tailnet settings (current)</div>"
            },
            "name": "div-tailnet-settings-(cu-e03b16"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Settings_CL\n| summarize arg_max(TimeGenerated, *) by TenantId\n| project DevicesApprovalOn, DevicesAutoUpdatesOn, DevicesKeyDurationDays, UsersApprovalOn, NetworkFlowLoggingOn, RegionalRoutingOn, PostureIdentityCollectionOn, UsersRoleAllowedToJoinExternalTailnets, LastSnapshot=TimeGenerated",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Tailnet policy gates",
              "noDataMessage": "No settings snapshot yet.",
              "noDataMessageStyle": 5
            },
            "name": "q-0622cfc3"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">DNS change history</div>"
            },
            "name": "div-dns-change-history-9dd376"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| extend TargetProperty=tostring(Target.property)\n| where Action contains \"DNS\" or TargetProperty has_any (\"DNS_NAMESERVERS\", \"DNS_SPLIT_DNS\", \"MAGICDNS\", \"DNS_SEARCH_PATHS\")\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| project TimeGenerated, ActorLogin, Action, TargetProperty, Origin\n| order by TimeGenerated desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Recent DNS-related admin changes",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No DNS changes in this window.",
              "noDataMessageStyle": 1
            },
            "name": "q-a132ff6a"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">ACL policy changes</div>"
            },
            "name": "div-acl-policy-changes-ff0e68"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Audit_CL\n| where TimeGenerated {TimeRange}\n| where Action == \"ACL_UPDATE\" or Action contains \"ACL\"\n| extend ActorLogin=tostring(coalesce(Actor.loginName, Actor.displayName))\n| project TimeGenerated, ActorLogin, Action, Origin, EventGroupID\n| order by TimeGenerated desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Recent ACL / policy file modifications",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No ACL changes in this window.",
              "noDataMessageStyle": 1
            },
            "name": "q-94818c53"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Subnet routes & exit nodes</div>"
            },
            "name": "div-subnet-routes-and-ex-eef47f"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "Tailscale_Devices_CL\n| summarize arg_max(TimeGenerated, *) by DeviceId\n| where array_length(EnabledRoutes) > 0\n| project DeviceName, User, Os, EnabledRoutes=tostring(EnabledRoutes), AdvertisedRoutes=tostring(AdvertisedRoutes), LastSeen\n| order by LastSeen desc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Routes currently being served from devices",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastSeen",
                    "formatter": 6
                  }
                ]
              },
              "noDataMessage": "No subnet routers active in this tailnet.",
              "noDataMessageStyle": 1
            },
            "name": "q-61a792cd"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "network"
      },
      "name": "group-network"
    },
    {
      "type": 12,
      "content": {
        "version": "NotebookGroup/1.0",
        "groupType": "editable",
        "items": [
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Ingest rate per table</div>"
            },
            "name": "div-ingest-rate-per-tabl-24e5f6"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "union withsource=Table Tailscale_Audit_CL, Tailscale_Devices_CL, Tailscale_Users_CL, Tailscale_Keys_CL, Tailscale_Dns_CL, Tailscale_Settings_CL\n| where TimeGenerated > ago(24h)\n| summarize Rows=count() by Table, bin(TimeGenerated, 1h)\n| order by TimeGenerated asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "timechart",
              "title": "Rows ingested per Tailscale table per hour (last 24h)",
              "noDataMessage": "No Tailscale data ingested in the last 24h - check the connector card under Sentinel Data Connectors.",
              "noDataMessageStyle": 5
            },
            "name": "q-c6fd0143"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Last poll time per table</div>"
            },
            "name": "div-last-poll-time-per-t-49b051"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "union withsource=Table Tailscale_Audit_CL, Tailscale_Devices_CL, Tailscale_Users_CL, Tailscale_Keys_CL, Tailscale_Dns_CL, Tailscale_Settings_CL\n| summarize LastRow=max(TimeGenerated), TotalRows=count() by Table\n| extend MinutesAgo=toint((now() - LastRow) / 1m)\n| extend Status=case(MinutesAgo < 60, \"Fresh\", MinutesAgo < 360, \"Recent\", MinutesAgo < 1440, \"Stale\", \"Very Stale\")\n| project Table, LastRow, MinutesAgo, TotalRows, Status\n| order by MinutesAgo asc",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Per-table freshness",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "LastRow",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "MinutesAgo",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "redBright"
                    }
                  },
                  {
                    "columnMatch": "TotalRows",
                    "formatter": 8,
                    "formatOptions": {
                      "palette": "blue"
                    }
                  },
                  {
                    "columnMatch": "Status",
                    "formatter": 1
                  }
                ]
              }
            },
            "name": "q-a02e37a8"
          },
          {
            "type": 1,
            "content": {
              "json": "<div style=\"border-left:4px solid #3b82f6;padding:8px 12px;margin:16px 0 8px 0;background:rgba(59,130,246,0.05);font-size:14px;font-weight:600;letter-spacing:0.3px;text-transform:uppercase;color:#94a3b8\">Log Analytics operational events</div>"
            },
            "name": "div-log-analytics-operat-630749"
          },
          {
            "type": 3,
            "content": {
              "version": "KqlItem/1.0",
              "query": "_LogOperation\n| where TimeGenerated > ago(24h)\n| where _ResourceId contains \"tailscale\" or Detail contains \"Tailscale_\"\n| project TimeGenerated, Operation, Level, Detail\n| order by TimeGenerated desc | take 100",
              "size": 0,
              "queryType": 0,
              "resourceType": "microsoft.operationalinsights/workspaces",
              "visualization": "table",
              "title": "Log Analytics operational events touching Tailscale tables",
              "gridSettings": {
                "formatters": [
                  {
                    "columnMatch": "TimeGenerated",
                    "formatter": 6
                  },
                  {
                    "columnMatch": "Level",
                    "formatter": 1
                  }
                ]
              },
              "noDataMessage": "No operational issues recorded in the last 24h.",
              "noDataMessageStyle": 1
            },
            "name": "q-b492f150"
          }
        ]
      },
      "conditionalVisibility": {
        "parameterName": "selectedTab",
        "comparison": "isEqualTo",
        "value": "pipeline"
      },
      "name": "group-pipeline"
    },
    {
      "type": 1,
      "content": {
        "json": "<div style=\"margin-top:32px;padding-top:16px;border-top:1px solid #1e293b;color:#64748b;font-size:12px\"><strong>Tailscale Operations (Standard) (CCF)</strong> - Microsoft Sentinel content from the Tailscale (CCF) solution, Standard-tier surface. Tables polled from the Tailscale REST API: audit, devices, users, keys, dns, settings. Filter every panel via the time range above; the Investigate tab adds Actor and Device pickers for drilldown. For network flow logs and posture integrations, install the companion <strong>Tailscale Operations (Premium)</strong> workbook on a Premium / Enterprise tailnet.</div>"
      },
      "name": "footer"
    }
  ],
  "fallbackResourceIds": [
    "Azure Monitor"
  ],
  "fromTemplateId": "sentinel-Tailscale-CCF",
  "$schema": "https://github.com/Microsoft/Application-Insights-Workbooks/blob/master/schema/workbook.json"
}