VantagePoint 365 — Microsoft 365 Auditing
{{ gateBrandInitial }}

{{ gateBrandName }}

{{ gateBrandTagline }}
{{ gateError }}
A 6-digit verification code was sent to your email address. Enter it below to complete sign-in.
Need access? Contact your service provider.
V

{{ gateTitle }}

{{ gateMessage }}
{{ gateError }}
MSP / Admin Portal
Onboarding activation key
Onboarding a new client needs an activation key issued by your provider. Each key activates one client and cannot be reused. If you do not have one, request it from your provider.
{{ onboardKeyError }}
Share this dashboard
Anyone with the link can view a snapshot of this dashboard as it looks now — no sign-in needed, and no live data. The link expires automatically and you can withdraw it at any time.
A link is already active. {{ shareExpiryText }} · {{ shareViewsText }}. Creating a new one replaces it and the old link stops working.
Copy this now — it is shown once and cannot be retrieved again.
V

{{ sharedName }}

Opening shared dashboard…

Link unavailable

{{ sharedError }}
Shared links expire, and can be withdrawn by whoever sent it. Ask them for a new one.
{{ sharedAsAt }} · this is a point-in-time snapshot, not a live view
{{ sw.title }}
{{ lg.label }} {{ lg.value }}
Shared securely via VantagePoint 365. This link expires and can be withdrawn at any time.
V

Portal Access Not Enabled

{{ mspDeniedMessage }}
V

No Active Subscription

Your organisation is connected, but no subscription is active on this portal yet.
Contact your service provider to activate it. Nothing needs to be reinstalled or reconnected — access is switched on from their side.
{{ mspPageTitle }}
⚠ {{ idleWarning }}
Client Site Locations
No client sites with coordinates yet — add some under Settings → Client Sites.
Total Clients
{{ mspTotalClients }}
Active Portals
{{ mspPortalEnabledCount }}
Paused Portals
{{ mspPortalOffCount }}
Client Sites
{{ mspTotalSites }}
Mapped Sites
{{ mspMappedSiteCount }}
Clients
Client Status Connected Contact Sites
{{ row.name }} {{ row.statusText }} {{ row.connected }} {{ row.contact }} {{ row.siteCount }}
All Clients
{{ mspClientPageInfo }}
No clients or sub-customers match this search.
{{ row.name }}
{{ row.statusText }}
🔄 Migration Analyser only — {{ row.migrationBadge }}
🔍 {{ row.subMatchNote }}
Users
{{ row.statUsers }}
Devices
{{ row.statDevices }}
Lic. used
{{ row.statLicenses }}
App-only permissions not yet granted — re-run admin consent to enable stats sync.
{{ row.statusNote }}
{{ mspClientPageLabel }}

{{ mspPAPanel.name }}

Portal login: {{ mspPAPanel.loginUrl }}
Loading portal users…
Portal Users
{{ pu.initial }}
{{ pu.displayName }} {{ pu.roleLabel }} {{ pu.authMethod }}
{{ pu.email }}
Profile & Auth Method
{{ pu.syncError }}
Role & Section Access
No portal users yet for this client.
{{ mspPAPanel.error }}
Add Portal User
Regional Preferences
One shared setting for the whole MSP console — controls the currency and date/time formatting shown in the Azure Infrastructure and M365 Cost Analyzers. Does not change what currency a figure was actually computed in, only how it's displayed.
Currency
Date Format
Timezone
Saved {{ regionalSavedAt }}
Only the owner can change this — everyone sees the current setting.
Weekly portfolio digest
One email to the owner each week listing which clients need attention: a score drop, new critical findings, high-severity alerts, risky configuration changes, or an assessment that has gone stale. Built only from data already recorded here (nothing is read from client tenants). It is off until you switch it on, and it waits for the next chosen day rather than sending straight away.
Weekly digest
Day it is sent
{{ pdigStatusLine }}
{{ pdigNote }}
{{ pdigPreviewSummary }}
{{ pr.name }} {{ pr.scoreText }}
{{ pr.reasonText }}
Select Client
MSP Administrators
{{ a.upn }}
Role: {{ a.role }}
Subscription summary
{{ mspSubSummary.clientName }}
Plan {{ mspSubSummary.tierLabel }}
Paid add-ons
{{ sa.label }} {{ sa.state }}
{{ mspSubSummary.noneText }}
{{ mspSubSummary.countText }}
{{ mspSubSummary.inactiveNote }}
Client Profile & White-Label
Client Portal Access
When enabled, this client's own users can sign in and see only their own tenant's data.
Subscription
The licence unlocks the Microsoft 365 audit, health score, reporting and network map. Without it this client signs in to a "no active subscription" notice and no data is served. The plan below decides which bundled features are included, and add-ons require an active licence.
Licensed — Microsoft 365 Audit
Plan
{{ mspProfilePlanNote }}
This client is currently unlicensed and cannot see any data. Any add-ons ticked below stay recorded but have no effect until the licence is active.
Admins see every SharePoint site
When ticked, this client's admins see the same SharePoint sites, storage and sharing numbers you see, instead of only the sites their own Microsoft account can open. Every other dashboard keeps using the admin's own sign-in, which already shows the full data there. It changes what they can see, not what they can do: licensing, add-ons, plans, admin management and billing stay with you. Read-only, off by default, and takes effect on their next page load.
Add-on: Secure Script Vault
Lets this client view decoded Intune script/remediation source code, with secrets hashed and a fresh MFA prompt required every time — plus a 1-minute idle auto-lock. Takes effect immediately.
⚠ One-time setup required in this client's own Entra tenant
Without this, the "fresh MFA" prompt can silently pass on a trusted session with no real MFA challenge. Have a Global Admin of this client's tenant (not your MSP tenant) do the following in entra.microsoft.com:
  1. Protection → Conditional Access → Authentication contexts → + New authentication context. ID must be c1. Name it anything recognizable (e.g. "Script content access"). Leave Publish to apps checked. Save.
  2. Conditional Access → Policies → + New policy. Users: whoever should use this feature. Target resources → switch to Authentication context → select c1. Grant: Require multifactor authentication. Session → Sign-in frequency: Every time (this is the setting that forces a real fresh MFA prompt, not just a password re-entry). Enable the policy. Save.
  3. Test: open a script in this app for that client and click "Verify Identity (MFA) to View" — it should demand MFA every time, not just once per session.
Full write-up: m365-portal project skill, "Runbook: onboarding a client for Secure Script Vault."
Add-on: Migration Analyser
Full pre-migration tenant readiness scan — executive health dashboard, consolidated findings across every service, and a 21-section Migration Readiness report. Read-only; no configuration changes. Takes effect immediately.
Add-on: Federation (Microsoft SSO)
Lets this client's Portal Users sign in with their own Microsoft account instead of a portal password. New portal users default to Microsoft sign-in once enabled; existing users can be switched either way from the Portal Users list below. Takes effect immediately.
Add-on: Network Map
Visual relationship diagram of this tenant's M365 environment — users, groups, SharePoint sites, Exchange mailboxes, Teams, and devices, and how they connect. Read-only view over data already collected; no new credentials needed. Takes effect immediately.
Add-on: AI Assistant
Chat that answers questions about this tenant from the same read-only data the portal shows. Available to this client's admins only (never viewers); you can always use it. Questions and answers are processed by Anthropic. Takes effect immediately.
Add-on: AI Consultant Plan
Consultant narrative plus a 30/60/90-day plan for this client, built from the assessment, Risk Radar, Secure Score, Copilot and Cost Analyzer data already stored. Your MSP admins can generate, edit and export it from Risk Radar; the client never sees a draft. Takes effect immediately.
Add-on: Cyber-Insurance Readiness
Maps this client's last assessment to the controls cyber-insurance applications ask about, lists what the client must verify themselves, and exports an evidence pack for the broker. Your MSP admins open it from Risk Radar. Takes effect immediately.
Add-on: Licence Simulator
Lets your MSP admins model licence changes for this client (reclaim idle seats, move users between plans, roll out Copilot) and see the cost and security impact before proposing it. Read-only: nothing is changed in the client's tenant. Opened from Risk Radar. Takes effect immediately.
Add-on: Alert Engine
Lets your MSP admins set rules for this client (new critical findings, Health Score or Secure Score drops, Microsoft incidents, devices offline) and see each alert once. Only you choose who gets emailed. Takes effect immediately.
Add-on: Compliance Mapping
Lets your MSP admins map this client's assessment to NIST CSF, ISO 27001, CIS Controls, Essential Eight and POPIA, and export an evidence pack. Evidence only, not a statement of compliance. Takes effect immediately.
Add-on: Config Drift
Adds a Config Drift tab inside this client's portal that records Conditional Access, admin role members, authentication methods, security defaults, guest settings and domains, and lists what changed between captures. Takes effect immediately.
Add-on: Audit-Log Retention
Adds an Audit Log tab inside this client's portal that keeps a copy of the client's Microsoft audit events for 1 to 7 years (Microsoft keeps them for 90 days to a year) and lets you search and export them. Collection starts from the day it is switched on; older events cannot be imported. Read-only: nothing is changed in the client's tenant. Takes effect immediately.
{{ mspEditAuditConsent.text }}
Send this link to a Global Administrator of the client. It opens Microsoft's own approval screen; only they can approve, and it changes nothing else in their tenant. Then press Check again.
Add-on: Access Review
Adds an Access Review tab inside this client's portal: a periodic review of administrator role members, guest accounts and applications with consent, where a person records keep, remove or not sure for each item and a reviewer signs the review off. Decisions and sign-offs are stored as evidence. Read-only: nothing is changed in the client's tenant. Takes effect immediately.
Add-on: Shadow IT
Adds a Shadow IT tab inside this client's portal: the third-party applications people have connected to their work account, rated by what they can reach, with a recorded approved / not approved decision per app. Read-only: nothing is changed in the client's tenant.
Add-on: Copilot ROI
Adds a Copilot ROI tab beside Copilot Readiness inside this client's portal: what the Copilot seats cost, how many are used, the spend on idle seats, and the break-even hours a week per active user. Read-only, built from the assessment the client already runs. Needs an active licence.
Add-on: Anomaly Detection
Adds an Anomaly Detection tab inside this client's portal: unusual sign-ins found in the client's own sign-in log (impossible travel, a new country, password spray, repeated failures then a success, Microsoft's own risk flags). Needs Entra ID P1 for the sign-in logs. Read-only: nothing is blocked or changed. Needs the client to be licensed.
Add-on: Lookalike Domains
Adds a Lookalike Domains tab inside this client's portal: look-alikes of the client's own verified domains (typos, look-alike characters, other endings) that exist in DNS, with mail records flagged. Read-only: nothing is changed anywhere. Needs the client to be licensed.
Add-on: Shadow AI
Adds a Shadow AI tab inside this client's portal: the AI tools people have connected to their work account, rated by what they can reach, with a recorded approved / not approved decision per tool. Sold separately from Shadow IT. Read-only: nothing is changed in the client's tenant.
Migration Analyser Only (not yet a full client)
This tenant only sees the Migration Analyser tab in their portal — no Entra/Exchange/Teams/etc. Checking this starts a 30-day active window; after that their portal login is blocked until you reactivate. Unchecking promotes them to a full client — enable other add-ons for them as usual afterward.
{{ mspEditTrialBadge }}
White-Label Branding
Portal Users
Portal users sign in with email + password via the client's branded portal URL (no Microsoft account required).
Federation add-on is enabled for this client — new users default to Microsoft sign-in. Switch any user back to password below if needed.
Login URL: {{ mspPortalLoginUrl }}
Set a Portal Slug above to generate the login URL.
{{ mspPortalUserError }}
{{ pu.displayName }} {{ pu.roleLabel }} {{ pu.authLabel }}
{{ pu.email }} · added {{ pu.createdAt }}
Role & Section Access
No portal users yet. Add one above.
Client Sites
{{ site.name }}
{{ site.address }} · {{ site.coords }}
Assistant API keys
Let an external assistant, such as Gideon, read audit and inventory data without signing in. Keys are read-only: they cannot change anything, and never see credentials, portal users or admin settings. Creating one asks you to re-verify with MFA.
Can read
No clients to choose from yet.
Re-verify your identity and the key is created straight after. {{ assistantKeyError }}
Key created for {{ assistantKeyIssuedName }}
Copy it now — it is shown once and cannot be retrieved again. Only a hash is stored.
Name Key Can read Created Expires Last used Status
{{ ak.name }} {{ ak.prefix }} {{ ak.scope }} {{ ak.created }} {{ ak.expires }} {{ ak.lastUsed }} {{ ak.status }}
No assistant keys yet.
Onboarding activation keys
Your admins need one of these to onboard a client — they cannot generate their own. Each key activates one client and is then spent. You can onboard without a key.
Copy this now — it is shown once and cannot be retrieved again. Only a hash is stored.
Note Issued Expires Status
{{ ok.note }} {{ ok.created }} {{ ok.expires }} {{ ok.status }}
Integrations & Add-ons
Third-party tools and sellable add-ons. Click an app to configure it and choose which client or sub-customer it applies to. Only you, as owner, can enable these.
{{ app.name }}
{{ app.description }}
{{ mspIntegHubSelectedApp.name }}
{{ mspIntegHubSelectedApp.description }}
⚠ Not inherited — enabling this for a client does not apply it to their sub-customers. Each tenant in the tree (client or sub-customer) needs its own separate toggle here.
Platform settings (all clients)
{{ aiCfgStatusLabel }}
{{ aiCfgProviderNote }}
Stored encrypted. It is never shown again after saving; only the last 4 characters are displayed.
Learning
Builds a general question bank shared by all clients (de-identified questions only, no client data) and saves per-client notes that only that client's chats use. Adds a small extra AI call per question. Off = nothing is saved or used.
{{ aiCfgError }}
{{ aiCfgSaved }}
General question bank
Questions admins have asked, rewritten so they name no client, tagged by topic, and merged when two ask the same thing. The Top 5 become the suggestions every client sees. Only you can see this list. Hide or delete anything you don't want used.
Nothing learned yet. The bank fills up as admins ask questions (live mode only).
{{ bq.question }}
{{ bq.meta }}
Apply to client
Select a client or sub-customer from the list to configure this integration for them.
{{ mspIntegHubNinjaItem.statusLabel }}
{{ mspIntegHubNinjaItem.error }}
Enable for this client
Takes effect immediately — server-side gated regardless of what the client's browser has cached.
⚠ One-time setup required in this client's own Entra tenant
Without this, the "fresh MFA" prompt can silently pass on a trusted session with no real MFA challenge. Have a Global Admin of this client's tenant (not your MSP tenant) do the following in entra.microsoft.com:
  1. Protection → Conditional Access → Authentication contexts → + New authentication context. ID must be c1. Name it anything recognizable (e.g. "Script content access"). Leave Publish to apps checked. Save.
  2. Conditional Access → Policies → + New policy. Users: whoever should use this feature. Target resources → switch to Authentication context → select c1. Grant: Require multifactor authentication. Session → Sign-in frequency: Every time. Enable the policy. Save.
  3. Test: open a script for this client and click "Verify Identity (MFA) to View" — it should demand MFA every time.
Full write-up: m365-portal project skill, "Runbook: onboarding a client for Secure Script Vault."
Enable for this client
Generates a per-tenant collector API key on first enable. Disabling stops the collector from writing new data immediately.
Collector API key
{{ mspIntegHubInfraKeyValue }}
Put this key in the SNMP discovery collector's config on the client's network, sent as the X-Infra-Api-Key header on every POST /api/infra/sync call. Rotating invalidates the old key immediately — update the collector's config to match.
Enable AI Consultant Plan for this client
Your MSP admins get the Consultant Plan button on this client's Risk Radar row. The client never sees drafts. Requires an active licence. Takes effect immediately.
⚠ Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients → Edit Profile, and the Consultant Plan switches on straight away.
Enable Licence Simulator for this client
Your MSP admins get the Licence Simulator button on this client's Risk Radar row. Requires an active licence. Takes effect immediately.
⚠ Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients → Edit Profile, and it switches on straight away.
Enable Alert Engine for this client
Your MSP admins get the Alerts button on this client's Risk Radar row. Rules are checked against data already recorded for the client, on each new assessment and once a day. Requires an active licence. Takes effect immediately.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Config Drift for this client
Adds a Config Drift tab inside this client's portal. A signed-in admin presses Capture now to record the configuration; the tab then lists what changed since the last capture. Requires an active licence. Takes effect immediately.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Audit-Log Retention for this client
Adds an Audit Log tab inside this client's portal and starts keeping a copy of their Microsoft audit events (retention 1 to 7 years, set per client). Requires an active licence, and the client's tenant must have consented to the audit-feed permission before collection can run. Takes effect immediately.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
{{ mspIntegHubAuditConsent.text }}
Send this link to a Global Administrator of the client. It opens Microsoft's own approval screen; only they can approve, and it changes nothing else in their tenant. Then press Check again.
Enable Access Review for this client
Adds an Access Review tab inside this client's portal. A signed-in admin loads the current administrator role members, guest accounts and applications with consent, records keep, remove or not sure for each, and signs the review off. Requires an active licence. Takes effect immediately.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Shadow IT for this client
Adds a Shadow IT tab inside this client's portal. A signed-in admin loads the applications people have connected with their work account (OAuth consent); each is rated by what it can reach and can be recorded as approved or not approved. Read-only: nothing is changed in the client's tenant.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Copilot ROI for this client
Adds a Copilot ROI tab beside Copilot Readiness inside this client's portal: seat spend, utilisation, spend on idle seats, cost per active user, and the hours a week each active user must save to break even. It reads the Copilot assessment already stored, so a signed-in admin runs Copilot Readiness first. Value figures are illustrative and only appear once an hourly rate is entered. Read-only: nothing is changed in the client's tenant.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Lookalike Domains for this client
Adds a Lookalike Domains tab inside this client's portal. A signed-in admin presses a button; the client's verified domains are read from Microsoft 365 and look-alikes of them (typos, look-alike characters, other endings, added words) are checked in DNS to see which exist. Works with no new Microsoft permission. Read-only: nothing is changed anywhere.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Anomaly Detection for this client
Adds an Anomaly Detection tab inside this client's portal. A signed-in admin presses a button; the client's recent sign-ins are read from Microsoft 365 and checked for unusual patterns (impossible travel, a new country, password spray, repeated failures then a success, Microsoft's own risk flags). Needs Entra ID P1 for the sign-in logs and no new Microsoft permission. Read-only: nothing is blocked, revoked or changed. A short AI note is written from counts only; no names leave the app.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Shadow AI for this client
Adds a Shadow AI tab inside this client's portal. A signed-in admin loads the AI tools people have connected with their work account (OAuth consent); each is rated by what it can reach and can be recorded as approved or not approved. Works without Shadow IT. Read-only: nothing is changed in the client's tenant.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Compliance Mapping for this client
Your MSP admins get the Compliance button on this client's Risk Radar row. It maps the last assessment to framework requirements and exports an evidence pack. Requires an active licence. Takes effect immediately.
Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients, Edit Profile, then this takes effect.
Enable Cyber-Insurance Readiness for this client
Your MSP admins get the Cyber-Insurance button on this client's Risk Radar row. Requires an active licence. Takes effect immediately.
⚠ Saved, but still OFF: this client is not licensed, and every add-on needs a licence underneath it. Tick the licence box in Clients → Edit Profile, and it switches on straight away.
Enable AI Assistant for this client
Their admins get an Ask AI button; viewers never do. Requires an active licence. Takes effect on their next page load.
Enable for this client
Each client has its own collector API key (generate it below; it is shown once). Disabling stops the collector from writing new data immediately.
Backend URL
{{ mspIntegHubBackendUrlDisplay }}
Collector API key
{{ mspIntegHubAdAuditKeyStatus }}
Copy this key now
It is shown once. The portal keeps only a one-way fingerprint of it, so it cannot be shown again; if you lose it, generate a new one.
{{ mspIntegHubAdAuditNewKey }}
On a domain controller, run the AD Audit installer (AdAuditCollector.msi) and enter this client's key, or run backend/collectors/ad-audit-collector/setup-ad-audit-collector.ps1 -ApiBaseUrl "{{ mspIntegHubBackendUrlPlain }}" -ApiKey "<this key>". Each client has its own key; it decides which client the data belongs to. Generating a new key stops the old one at once, so re-run the installer with the new key on the collector.
Allowed addresses
Optional. Leave empty to accept this key from anywhere. Otherwise only the addresses or ranges listed here (one per line, for example 203.0.113.5 or 198.51.100.0/24) can use it, so a stolen key is useless from anywhere else. Use the client's public (internet-facing) address, not the DC's local one. A wrong entry stops the collector at its next run; the lines below show the address that was turned away.
{{ mspIntegHubAdAuditAccessMsg }}
{{ mspIntegHubAdAuditLastSeenText }}
{{ mspIntegHubAdAuditRejectedText }}
Device Discovery
Turns on the Infrastructure tab for this client. The AD Audit collector above already self-reports each domain controller's real detail (BIOS, serial, RAM, disks, patch level) into it with the same key — no separate install. Enable this too if the client also wants their switches/UPS/routers discovered via the standalone SNMP collector (Network Discovery card, below).
Enable for this client
Takes effect immediately. Requires a service principal below before the first sync will return data.
Service principal credentials
✓ Credentials configured — supply new values below to replace them.
{{ mspIntegHubAzureError }}
{{ mspIntegHubAzureSyncResult }}
Create a service principal with Reader role scoped to the subscription — no write access needed. In the client's Azure tenant: Entra ID → App registrations → New registration, then Subscriptions → select subscription → Access control (IAM) → Add role assignment → Reader → assign to the new app.
Client Portfolio
Every client and sub-customer with its status and licence. Filter by add-on to see who has what; the full add-on breakdown for a client is under Manage (its Subscription summary).
{{ pfUi.summaryText }}
Loading portfolio…
{{ pfUi.errorText }}
{{ pfUi.emptyText }}
ClientStatusPlanConnectedSitesContact
{{ p.name }}
{{ p.parentText }}
{{ p.statusText }} {{ p.tierLabel }} {{ p.connected }} {{ p.sites }} {{ p.contact }}
Portfolio Risk Radar
Every client sorted by risk level, using their most recent assessment. Within a level, the highest risk score comes first. Clients with no assessment are shown as Not assessed, never as clean. Click a client to see each control.
{{ riskUi.summaryText }}
{{ riskUi.excludedText }}
Loading portfolio…
{{ riskUi.errorText }}
No clients in your scope yet.
ClientGrade ⓘRiskConformanceMust-pass controls ⓘCriticalAssessedWhy
{{ r.detailHeadline }} Measured against
Loading controls…
{{ r.gradeHeadline }}
{{ r.gradeReasons }}
{{ m.label }} {{ m.scoreText }} {{ m.weightText }} {{ m.note }}
A grade is your own rating from recorded data, not a certification. A failing must-pass control holds a client at C or lower. A measure that was never recorded is left out, not counted as zero.
{{ c.statusLabel }} {{ c.title }}{{ c.mustPassMark }} {{ c.driftText }} {{ c.detailText }}
{{ insUi.title }}
{{ insUi.subtitle }}
Loading readiness…
{{ insUi.errorText }}
{{ k.label }}
{{ k.value }}
{{ n.text }}
Gaps an insurer will ask about
{{ insUi.gapsNote }}
{{ c.statusLabel }} {{ c.area }} {{ c.question }}{{ c.criticalMark }}{{ c.ref }} {{ c.detailText }}
Verify
Verify {{ a.area }} {{ a.question }} {{ a.ref }}
Breach exposure {{ insUi.bxHeadline }}
{{ insUi.bxNote }}
{{ insUi.bxStaleText }}
{{ r.domain }} {{ r.statusLabel }} {{ r.detail }}
What to do about this
Steps for the client's administrator. This app only reads; it changes nothing in the client's tenant.
{{ a.phase }} {{ a.title }} {{ a.detail }}
Email domains to search (one per line or comma separated, up to {{ insUi.bxMaxDomains }}). Each must be verified in your Have I Been Pwned account.
{{ insUi.bxNotice }}
{{ insUi.bxError }}
Owner: breach exposure needs a paid Have I Been Pwned API key, which you purchase yourself at haveibeenpwned.com/API/Key (monthly subscription). You also verify each client's domain in your HIBP account at haveibeenpwned.com/DomainSearch before it can be searched.
Have I Been Pwned API key (owner only, kept encrypted, used for every client). {{ insUi.bxKeyStatus }}
{{ simUi.title }}
{{ simUi.subtitle }}
Loading licence data…
{{ simUi.errorText }}
{{ simUi.noDataText }}
{{ simUi.basisText }}
Move seats between plans
You choose which users move. This only prices it and flags what could be lost.
seat(s) from to
{{ simUi.notice }}
Saved scenarios
{{ sc.name }}
{{ k.label }}
{{ k.value }}
{{ ln.label }} {{ ln.seats }} seat(s) {{ ln.amount }} / month
⚠ {{ n.text }}
{{ w2.text }}
{{ cmpUi.title }}
{{ cmpUi.subtitle }}
Loading compliance evidence…
{{ cmpUi.errorText }}
{{ cmpUi.blurb }}
{{ k.label }}
{{ k.value }}
{{ n.text }}
Requirements to act on
{{ cmpUi.issuesNote }}
{{ q.statusLabel }} {{ q.title }} {{ e.text }}{{ e.fix }}
Not covered by this evidence
Microsoft 365 data cannot show these. They need other evidence (policy, people, physical, suppliers, recovery).
• {{ nc.text }}
{{ alertUi.title }}
{{ alertUi.subtitle }}
Loading alerts…
{{ alertUi.errorText }}
{{ alertUi.notice }}
{{ alertUi.eventsHeading }}
{{ alertUi.noEventsText }}
{{ ev.title }}
{{ ev.detail }}
{{ ev.meta }}
Rules
No rules yet. The recommended set adds one rule of each kind. Nothing is emailed until the owner adds recipients.
{{ ru.name }} · {{ ru.typeLabel }} · {{ ru.paramText }}
{{ ru.statusText }}
{{ ru.recipientsText }}
{{ alertUi.formTitle }}
{{ alertUi.formSourceText }}
Only the owner can choose who receives alert emails. Your rule will still appear in this alerts list.
{{ planUi.title }}
{{ planUi.subtitle }}
{{ planUi.loadingText }}
{{ planUi.errorText }}
No plan yet for this client. Generate one to start - it reads only data the portal has already stored and writes nothing to the client's tenant.
{{ k.label }}
{{ k.value }}
{{ k.note }}
{{ planUi.sourcesText }}
{{ planUi.noteText }}
Executive narrative
{{ planUi.sourceLabel }}
Markdown: "## " starts a heading, "- " a bullet. Edit freely - this is what the client reads.
{{ ph.label }} {{ ph.meta }}
{{ it.tagLabel }}{{ it.mustPassMark }}
{{ planUi.statusText }}
Standards baselines
The controls you require every client to meet. The built-in baseline cannot be changed; copy it to make your own, then assign it to clients from the radar above. Nothing here changes a client's tenant.
{{ b.name }}
{{ b.meta }}
{{ riskUi.editorTitle }}
{{ ec.title }} {{ ec.testId }}
{{ riskUi.editorError }}
Report a problem
Send these with the report so it can be found quickly:
• The client's name, and which page you were on
• What you clicked, and what happened instead
• The time it happened (with your time zone)
• Your role (owner, admin, viewer or client user)
• A screenshot, if you can take one
Never include a password, client secret or API key in a report. The portal never needs them to help you.
Quick answers
A client cannot sign in. Check the client is licensed (Clients, Edit Profile) and that the portal login is for the right client.
A tab is missing in a client's portal. Add-ons are off until the owner ticks them, and a client must be licensed first.
A check says "not checked". The check could not finish, for example because a service was busy. That is not the same as clear. Try again later.
Who can change add-ons? Only the owner. Admins can request one.
The page looks out of date. Reload it with Ctrl+F5 to pick up the newest version.
Create a client portal
Each client gets their own Vercel deployment, their own Neon database and their own Entra app registration — nothing shared with another client. The slug becomes those project names and can never be changed or reused, including after the client leaves.
{{ instanceError }}
Slug {{ instanceCreatedSlug }} is reserved. Nothing has been provisioned yet.
Run the Provision client instance workflow in GitHub Actions with this slug — leave dry run on for the first pass. When it finishes, this client will be provisioned but not yet able to sign in:
• {{ step.text }}
{{ setupHeading }}
{{ setupSubtitle }}
{{ setupPlatformWarning }}
{{ stage.mark }}
{{ stage.label }} {{ stage.actorLabel }}
{{ stage.action }}
{{ stage.detail }}
{{ stage.commandText }}
BEFORE YOU START
• {{ b.text }}
{{ g.n }}
{{ g.text }}
{{ g.note }}
HOW TO KNOW IT WORKED
{{ stage.guideVerify }}
Written up at length in {{ stage.guideDocs }}
{{ setupPickPrompt }}
{{ instancesHeading }}
No client instances yet. itsolve and staging are not listed here — they are your own environments, not clients.
{{ row.name }}
{{ row.slug }}
{{ row.statusLabel }} {{ row.url }} {{ row.created }} {{ row.note }}
Permanently delete {{ offboardName }}?
This deletes their Neon database and all of their data, their Vercel deployment and their Entra app registration. There is no undo. The slug is kept as a tombstone and can never be reused.
Type {{ offboardSlug }} to confirm.
{{ offboardError }}
{{ offboardDoneMessage }}
Offboarding from here records the decision and nothing else — no data is deleted until you run the Offboard client instance workflow, which refuses to run unless this screen has approved it first. Use its dry run to see exactly what will be deleted.
✦ AI Assistant
Read-only · answers use this client's data only
DEMO DATA
No earlier chats for this client.
Chats are deleted automatically after 3 days.
{{ cv.when }}
Notes the assistant uses for this client only. Learned from chats or added by an admin. Never shared with other clients.
Nothing learned yet for this client.
{{ kn.note }}
{{ kn.meta }}
Ask anything about this client's Microsoft 365 tenant, or ask for a report (e.g. "Show me all users without MFA").
Top 5 most asked
{{ m.text }}
{{ sg.text }}
{{ sg.text }}
{{ li.marker }}{{ sg.text }}
{{ bk.text }}
{{ th.text }}
{{ td.text }}
Sources: {{ m.sourcesLabel }}
{{ m.learnedLabel }}
{{ m.blockedLabel }}
📄
{{ m.reportTitle }}
{{ m.reportMeta }}
Looking up tenant data…
{{ aiChatError }}
From the knowledge base
From this client's knowledge
{{ sn.note }}
AI answers can be wrong. Check important findings in the portal before acting. {{ aiChatUsageLabel }}
⚠️ DEMO PORTAL — Pre-production Testing
All features from itsolve must be validated here before production deployment.
Deployment workflow: itsolve → 6dhppy (DEMO) → Production
⚠ {{ idleWarning }}

Microsoft 365 — Tenant View

Viewing: {{ activeClientBadgeName }}
Overview of Microsoft 365 services used in your organization. Entra data is live; other services show sample previews.
⚠
{{ outageAlertHeadline }}
{{ outageAlertDetail }}
View details ▾
Tenant Health Score
{{ healthScoreVersionNote }}
{{ healthScoreDateText }}
{{ healthScanAutoNote }}
{{ healthScoreEmptyText }}
{{ healthScoreValue }}/100
{{ healthScoreTrendText }}
{{ healthScoreChangeText }}
Weakest areas
{{ hc.label }}
{{ hc.score }}
{{ healthScoreCapNote }} {{ healthScoreCriticalsToggleLabel }}
Finding Area Why it matters
{{ cf.title }} {{ cf.category }} {{ cf.why }}
Sign-in Locations
{{ signinMapSummary }}
Locating…
All succeeded Had failures Risky sign-in
{{ signinMapEmptyText }}
{{ expandedCardLabel }}
Checking Microsoft 365 service status…
Microsoft 365 service status is unavailable right now (Service Health access may need to be re-consented for this tenant).
✓ No critical/high-impact Microsoft 365 outages reported for this tenant.
{{ a.badgeLabel }}
{{ a.service }} — {{ a.title }}
{{ a.statusText }} · Updated {{ a.updatedText }}
View in Admin Center ↗
Checking Microsoft 365 Message Center…
Microsoft 365 Message Center is unavailable right now (Message Center access may need to be re-consented for this tenant).
✓ No upcoming Microsoft changes need action or review for this tenant right now.
{{ c.badgeLabel }}
{{ c.title }}
{{ c.summary }}
{{ c.servicesText }} · {{ c.deadlineText }}
View in Message Center ↗

Global View — All Tenants

{{ globalSubtitle }}
Querying every onboarded tenant…
{{ g.label }}
{{ g.value }}
{{ g.note }}
{{ globalUnreadableTitle }}
{{ globalUnreadableHelp }}
Tenant UsersDevicesGroups LicencesAssignedStatus
{{ r.indent }}{{ r.name }} {{ r.users }} {{ r.devices }} {{ r.groups }} {{ r.licenseTotal }} {{ r.licenseAssigned }} {{ r.statusLabel }}
{{ globalPageInfo }}
{{ globalEmptyText }}

Sub-customers

Customers onboarded under {{ mspActiveClientName }}
Loading sub-customers…
No sub-customers onboarded yet. Use the button above to onboard one.
{{ row.name }}
{{ row.statusText }}
Connected {{ row.connected }}
{{ row.contact }}
Users
{{ row.statUsers }}
Devices
{{ row.statDevices }}
Lic. used
{{ row.statLicenses }}

Infrastructure Devices

On-prem switches, UPS, and routers reported in by the SNMP discovery collector.
Loading devices…
No devices reported yet. Configure the SNMP discovery collector with this client's API key (Integrations → Network Discovery) and run it against their network.
Status Name Type Vendor IP MAC Last Seen
{{ row.status }} {{ row.name }} {{ row.deviceType }} {{ row.vendor }} {{ row.ip }} {{ row.mac }} {{ row.lastSeen }}
OS / Platform
{{ row.osGuess }}
Uptime
{{ row.uptime }}
Contact
{{ row.contact }}
Location
{{ row.location }}
First Seen
{{ row.firstSeen }}
Discovered Via
{{ row.discoveredVia }}
sysObjectID
{{ row.sysObjectId }}
Interface
{{ row.ifSummary }}
Heartbeat
Saving…
System Description
{{ row.sysDescr }}
UPS Status
Status
{{ row.upsStatus }}
Battery
{{ row.upsBattery }}
Runtime Remaining
{{ row.upsRuntime }}
Load
{{ row.upsLoad }}
Matched to NinjaOne Demo data
Manufacturer/Model
{{ row.ninjaOneModel }}
Warranty
{{ row.ninjaOneWarranty }}
Uptime
{{ row.ninjaOneUptime }}
Last Login
{{ row.ninjaOneLastLogin }}
Patch Status
{{ row.ninjaOnePatchStatus }}
OS Version
{{ row.ninjaOneOsVersion }}
Assigned User
{{ row.ninjaOneAssignedUser }}
Loading full device detail…
{{ sec.heading }}
{{ fld.label }}
{{ fld.value }}
Endpoint Agent (self-reported)
Manufacturer/Model
{{ row.agentModel }}
Serial Number
{{ row.agentSerial }}
BIOS
{{ row.agentBios }}
CPU
{{ row.agentCpu }}
OS
{{ row.agentOs }}
Uptime
{{ row.agentUptime }}
Logged-in User
{{ row.agentLoggedInUser }}
RAM
{{ row.agentRam }}
Domain
{{ row.agentDomain }}
Timezone
{{ row.agentTimezone }}
Last Patch
{{ row.agentLastPatch }}
Storage
{{ row.agentDisks }}
Scan Now
This can't run remotely from here — nothing in the portal has a network path into this client's LAN. Paste this into an elevated PowerShell session on any machine with the agent installed to trigger its next sweep immediately instead of waiting for the scheduled interval.
Command
{{ scanNowCommand }}

Infrastructure Policy

How often the Devices list auto-refreshes to reflect the latest agent-reported status.
Custom:
Saving…
Saved — {{ infraPolicyCurrentLabel }}.
How long a device can go unreported before it's shown as offline. Applies to every device for this client unless a device has its own override (set from its row in the Devices tab).
Saving…
Saved — {{ infraPolicyHeartbeatCurrentLabel }}.
Subnets (CIDR) for the endpoint agent's network sweep. Any installed agent pulls this list automatically on its next run — no need to touch the machine again after saving here.
{{ infraPolicySubnetsError }}
Saving…
Saved — {{ infraPolicySubnetsSummary }}.

Azure Infrastructure

Subscriptions, resource groups, and resources synced from Azure Resource Manager via a read-only service principal.
Loading subscriptions…
No subscriptions synced yet. An owner needs to configure a service principal and run a sync under Integrations → Azure Infrastructure.
Loading resource summary…
{{ cat.label }}
{{ cat.count }}
{{ cat.legend }}

{{ azureSelectedCategory }}

{{ azureResourceCount }} resource(s)
Loading resources…
Name Type Resource Group Location Cost
{{ row.name }} {{ row.type }} {{ row.rg }} {{ row.location }} {{ row.costLabel }}
Cost over time — click a month
{{ mo.label }}
{{ mo.amount }}
No cost recorded for this resource in the current window.
Specs
{{ sp.label }}
{{ sp.value }}
Cost per resource
{{ rel.name }}
{{ rel.amount }}

Cost Analyser

Actual spend, from Azure Cost Management. Refreshed twice a day.
Demo data
Loading cost data…
{{ azureCostError }}
No cost data returned for this period.
{{ p.label }}
{{ p.amount }}
{{ p.why }}
By resource type
{{ row.label }}
{{ row.amount }}
{{ mo.label }}
{{ mo.amount }}
By location
{{ row.label }}
{{ row.amount }}
{{ mo.label }}
{{ mo.amount }}
By category (incl. bandwidth/egress)
{{ row.label }}
{{ row.amount }}
{{ mo.label }}
{{ mo.amount }}
By resource group
{{ row.label }}
{{ row.amount }}
Trend
{{ mo.label }}
{{ mo.amount }}
Resources in this group
{{ mem.name }} {{ mem.amount }}

Recommendations

Costed opportunities to reduce spend, drawn from current cost + resource data.
Checking for savings…
No savings opportunities found yet.
Opportunity Resource Cost Why
{{ sv.title }} {{ sv.resource }} {{ sv.amount }} {{ sv.why }}

Compliance

{{ azureComplianceCount }} finding(s)
Checking resource configuration…
No findings — every synced resource passed the checks run so far.
Finding Resource Why it matters
{{ f.sevLabel }}
{{ f.title }}
{{ f.resource }} {{ f.impact }}

Config Drift

{{ driftUi.subtitle }}
Loading…
{{ driftUi.errorText }}
{{ driftUi.notice }}
Nothing has been captured for this client yet. Press Capture now to record the configuration as the baseline. The first capture finds no changes; later ones are compared with it.
{{ driftUi.lastText }}
{{ driftUi.staleText }}
{{ ar.label }}: {{ ar.value }}
{{ driftUi.changesHeading }}
{{ driftUi.noChangesText }}
{{ ch.sevLabel }}
{{ ch.summary }}
{{ fl.text }}
{{ ch.meta }}
Not covered
"No changes" means no changes in the six areas above. It does not mean nothing changed in the tenant.
• {{ nc.text }}

Shadow AI

{{ shadowAiUi.subtitle }}
{{ shadowAiUi.errorText }}
{{ shadowAiUi.notice }}
{{ shadowAiUi.emptyPrompt }}
{{ shadowAiUi.loadedText }}
{{ pl.label }}: {{ pl.value }}
{{ src.text }}
{{ shadowAiUi.noneRecognisedText }}
{{ gr.heading }}
{{ gr.emptyText }}
{{ rw.riskLabel }}
{{ rw.title }}
{{ rw.subtitle }}
{{ rw.categoryLabel }} {{ rw.confidenceText }}
{{ rw.reasonsText }}
{{ rw.newScopesText }}
{{ rw.scopesText }}
{{ rw.appPermsText }}
{{ rw.statusLabel }} {{ rw.statusMeta }}
{{ rw.noteLabel }}: {{ rw.note }}
No longer holding consent
• {{ gn.text }}
{{ shadowAiUi.otherHeading }}
The known AI tool list is not complete. If one of these is an AI tool, mark it and it moves up to the list above.
{{ ot.title }}
{{ ot.subtitle }}
Not covered
• {{ nc.text }}

Lookalike Domains

{{ lookalikeUi.subtitle }}
{{ lookalikeUi.errorText }}
{{ lookalikeUi.notice }}
{{ lookalikeUi.emptyPrompt }}
{{ lookalikeUi.scanText }}
{{ pl.label }}: {{ pl.value }}
{{ wn.text }}
Email protection of the client's own domains
Not checked yet for this client. Press "Check again" to read SPF, DMARC and DKIM for their domains.
{{ em.domain }}
{{ em.overallLabel }} {{ em.checkedText }}
{{ pt.name }}
{{ pt.label }}
{{ pt.detail }}
What to fix
• {{ fx.text }}
• {{ en.text }}
Certificate logs
{{ lookalikeUi.ctKnownText }}
{{ lookalikeUi.ctBrandText }}
{{ lookalikeUi.ctOwnHeading }}
{{ co.name }} New
{{ co.text }}
{{ lookalikeUi.ctBrandHeading }}
{{ cb.domain }} New Certificate in the last 30 days
{{ cb.text }}
{{ cb.dnsText }}
• {{ cn.text }}
{{ lookalikeUi.noneFoundText }}
{{ gr.heading }}
{{ gr.emptyText }}
{{ rw.riskLabel }}
{{ rw.title }} New
{{ rw.asciiText }}
{{ rw.subtitle }}
{{ rw.reasonText }}
{{ rw.recordsText }}
{{ rw.seenText }}
{{ rw.ageLabel }} {{ rw.registrationText }}
{{ rw.certTagLabel }} {{ rw.certText }}
{{ rw.remHeadline }}
{{ st.n }}. {{ st.title }}
{{ st.detail }}
Contacts from the registry
{{ ct.label }}: {{ ct.value }}
{{ rw.remCaveat }}
{{ rw.statusLabel }} {{ rw.statusMeta }}
Note: {{ rw.note }}
No longer found in DNS
• {{ gn.text }}
Not covered
• {{ nc.text }}

Anomaly Detection

{{ anomalyUi.subtitle }}
{{ anomalyUi.errorText }}
{{ anomalyUi.notice }}
{{ anomalyUi.emptyPrompt }}
{{ anomalyUi.scanText }}
{{ pl.label }}: {{ pl.value }}
{{ wn.text }}
{{ anomalyUi.noteHeading }}
{{ anomalyUi.narrative }}
{{ anomalyUi.narrativeNote }}
What was checked
{{ ru.label }}
{{ ru.status }}
{{ ru.note }}
{{ anomalyUi.noneFoundText }}
{{ gr.heading }}
{{ gr.emptyText }}
{{ rw.sevLabel }}
{{ rw.title }}
{{ rw.ruleLabel }}
{{ rw.detail }}
• {{ ev.text }}
{{ rw.seenText }}
{{ rw.statusLabel }} {{ rw.statusMeta }}
Note: {{ rw.note }}
Not covered
• {{ nc.text }}

Shadow IT

{{ shadowUi.subtitle }}
{{ shadowUi.errorText }}
{{ shadowUi.notice }}
{{ shadowUi.emptyPrompt }}
{{ shadowUi.loadedText }}
{{ pl.label }}: {{ pl.value }}
{{ src.text }}
Can people approve apps themselves?
{{ shadowUi.consent.label }}
{{ shadowUi.consent.explanation }}
{{ shadowUi.consent.workflowText }}
{{ shadowUi.consent.policiesText }}
What to do (in the client's own admin center - this page changes nothing)
• {{ stp.text }}
{{ gr.heading }}
{{ gr.emptyText }}
{{ rw.riskLabel }}
{{ rw.title }}
{{ rw.subtitle }}
{{ rw.reasonsText }}
New {{ rw.firstSeenText }}
{{ rw.newScopesText }}
{{ rw.scopesText }}
{{ rw.appPermsText }}
{{ rw.statusLabel }} {{ rw.statusMeta }}
{{ rw.noteLabel }}: {{ rw.note }}
No longer holding consent
• {{ gn.text }}
Not covered
• {{ nc.text }}

Access Review

{{ accessUi.subtitle }}
Loading…
{{ accessUi.errorText }}
{{ accessUi.notice }}
{{ accessUi.lastSignoffText }}
{{ so.text }}
Press "Load current access" to read the administrator role members, guest accounts and applications with consent as they are right now. This reads from the client's tenant with your own sign-in and can take up to half a minute. Nothing is changed.
{{ accessUi.loadedText }}
{{ pl.label }}: {{ pl.value }}
{{ src.text }}
{{ gr.heading }}
{{ gr.emptyText }}
{{ rw.riskLabel }}
{{ rw.title }}
{{ rw.subtitle }}
{{ rw.flagsText }}
{{ rw.statusLabel }} {{ rw.statusMeta }}
Note: {{ rw.note }}
No longer present
Marked for removal in an earlier review, and no longer in the tenant.
• {{ rs.text }}
Sign off this review
A review can be signed off once every list was read and every item has a decision. Still open:
• {{ bl.text }}
Every list was read and every item has a decision. Signing off records who reviewed and when, with every item and decision, as evidence. It does not change anything in the client's tenant.
Not covered
• {{ nc.text }}

Audit Log

{{ auditUi.subtitle }}
Loading…
{{ auditUi.errorText }}
{{ auditUi.notice }}
{{ auditUi.headline }}
{{ auditUi.statsText }}
{{ auditUi.consentText }}
Keep events for {{ auditUi.retentionNote }}
Gaps in the record
• {{ gp.text }}
Recent collections
• {{ rn.text }}
Search
{{ auditUi.resultsText }}
{{ ev.time }}
{{ ev.user }}
{{ ev.operation }}
{{ ev.workload }} · {{ ev.result }}
{{ ev.target }}
{{ auditUi.noResultsText }}
Not covered
• {{ nc.text }}

Cost Analyzer

Estimated Microsoft 365 licence spend, priced from this tenant's own configured costs where set and Microsoft's published list price otherwise. Not pulled from an invoice - Graph has no billing API for M365 licensing, unlike Azure's real Cost Management data above.
This section is also available in the Report Builder as "M365 Cost Analyzer (spend + waste)" under Executive, for mixing into a larger client report.
Loading cost data…
No licensing data to price yet.
Only today's figure has been recorded so far - the 3/6/12-month windows below show this same number until real history accumulates. Microsoft 365 has no billing history API, so this app snapshots the estimate once a day and builds a genuine trend over time, the same way the Azure panel above would if its subscription were this new.
{{ p.label }}
{{ p.amount }}
{{ p.why }}
By licence (SKU)
No priced licences on this tenant.
{{ row.label }}
{{ row.amount }}
{{ d.label }} : {{ d.value }}
{{ d.label }} {{ d.value }}
By idle seats (waste)
No idle seats - every purchased licence is assigned.
{{ row.label }}
{{ row.amount }}
{{ d.label }} : {{ d.value }}
{{ d.label }} {{ d.value }}
By price source
No priced licences on this tenant.
{{ row.label }}
{{ row.amount }}
{{ d.label }} : {{ d.value }}
{{ d.label }} {{ d.value }}
By seat status
No purchased seats found.
{{ row.label }}
{{ row.amount }}
{{ d.label }} : {{ d.value }}
{{ d.label }} {{ d.value }}
{{ m365CostUnpricedSeats }} seat(s) have no published list price and no tenant-configured cost - excluded from every figure above, which therefore understates real spend.
Utilization & waste (per licence)
{{ m365CostWastedMonthly }}/mo idle
Seats this tenant is paying for that are not assigned to any user - counted per SKU, from the same purchased-vs-assigned figures Graph reports, using the same purchased-capacity filter as the spend total above (a free/viral grant is never "wasted spend", because it was never bought).
No idle seats found - every purchased licence is currently assigned to a user.
{{ w.label }}
{{ w.amount }}
{{ w.assignedOf }} · {{ w.priceNote }}
Fix: {{ w.recommendation }}
{{ m365CostBasis }}
{{ infraDeployModalTitle }}
This never runs anything remotely — it just generates a ready-to-run command. Paste it into an elevated PowerShell session on each target device below.
Waiting for identity re-verification…
{{ infraDeployModalError }}
Run this on each of these devices
• {{ dn }}
Command (removes the agent and its scheduled task)
Command (downloads and silently installs)
{{ infraDeployOneLiner }}
Same API key as this client's Network Discovery integration — every device that runs this reports into this client's own isolated device list only.

AD Audit

On-prem Active Directory security posture, inventory and change history, reported by scheduled collectors on a read-only domain account.

Data cleanup

Domains, users, groups, computers and devices that stopped reporting stay in the portal until they are removed. The portal removes them for you every day once they have been silent for the time set below (14 days unless you change it), and you can remove them here by hand at any time. Anything that still exists in Active Directory simply comes back on the next collector run, so removing it is safe. Change history is never removed automatically.
Loading…
{{ adCleanupErrorText }}
Domains that have reported
No domain has reported yet.
Domain Objects Last reported Status
{{ d.domain }} {{ d.objectsLabel }} {{ d.lastLabel }} {{ d.statusLabel }}
Remove {{ adCleanupConfirmDomain }} from the portal?
This deletes its inventory, posture assessment and run records for this client. It does not touch Active Directory. If a collector is still reporting this domain, it reappears on the next run.
Type the domain name to confirm
Automatic clean-up
Every day, remove anything not seen for {{ adCleanupAutoNote }}
{{ adCleanupPreviewText }}
{{ adCleanupNowHint }}
{{ adCleanupMessage }}
Domain
Loading the posture assessment…
{{ adPostureEmptyMessage }}
{{ adPostureFooter }}
Demo data Refreshing…
{{ adPosturePrivNote }}
{{ adPostureCoverageText }}
{{ k.label }}
{{ k.count }}
{{ k.legend }}
{{ gl.label }}{{ gl.value }}

By area

Click an area to filter the findings below.
{{ cat.name }}
{{ cat.scoreLabel }}
{{ cat.worstLabel }}

Remediation plan

Most dangerous first. Click an item to open it.
{{ ph.phase }} {{ ph.window }} · {{ ph.countLabel }}
{{ pi.sevLabel }} {{ pi.title }}
{{ ph.moreLabel }}
No findings from the checks that ran.

Score trend

{{ adPostureTrendNote }}

Findings

{{ adPostureFindingsShownLabel }}
Area: {{ adPostureCategoryFilterLabel }}
No findings match these filters.
What we saw: {{ pf.summary }}
Why it matters: {{ pf.impact }}
What to do: {{ pf.recommendation }}
{{ pr.text }}
{{ pf.moreLabel }}
Read-only Who changed what, when, and from where, built from the domain controllers' security logs. Nothing here can change Active Directory. Demo data
Loading activity…
{{ adActivityErrorText }}

Search

{{ af.label }}

{{ b.title }}

{{ b.subtitle }}
{{ b.note }}
{{ st.label }}
{{ st.value }}
{{ st.sub }}
{{ fg.title }}
{{ fi.label }} {{ fi.value }}
{{ br.label }}
{{ br.valueLabel }}
{{ ck.statusLabel }}
{{ ck.label }}
{{ ck.detail }}
{{ b.emptyText }}
What we saw: {{ pf.summary }}
Why it matters: {{ pf.impact }}
What to do: {{ pf.recommendation }}
{{ pr.text }}
{{ pf.moreLabel }}
{{ cd.title }}
{{ cd.description }}
Run report →
{{ b.pagerLabel }}
{{ b.emptyText }}
No rows match the search.
{{ col.label }}
{{ cl.text }}
{{ dl.label }} {{ dl.value }}
{{ rw.chipsLabel }}
{{ ch.text }}
Why this is listed
{{ rk.sevLabel }} {{ rk.label }}. {{ rk.explain }}
Domain
Loading…
No data synced yet. An owner needs to enable this add-on and run the collector — see Integrations → AD Audit.
Last synced: {{ adAuditLastSyncLabel }} — domain {{ adAuditLastDomain }}
Demo data {{ adAuditFreshnessText }}
{{ c.label }}
{{ c.count }}
{{ c.legend }}

Discovered Devices

{{ adAuditDiscoveredDeviceRows.length }} device(s) Enable Device Discovery (Integrations → AD Audit) for full detail — BIOS, serial, RAM, disks, patch level.
Status Name Type Vendor IP Last Seen
{{ dd.status }} {{ dd.name }} {{ dd.deviceType }} {{ dd.vendor }} {{ dd.ip }} {{ dd.lastSeen }}

{{ adAuditSelectedTypeLabel }}

{{ adAuditObjectRows.length }} object(s)
Loading…
No objects of this type were returned by the last collector run.
This list merges Active Directory and Entra ID, matched on hostname. Domain joined / Hybrid joined come from AD (hybrid = the device wrote its Entra registration certificate to its AD object); Entra joined / Entra registered come from Graph's trustType and have no AD computer object at all. Rows marked "AD only" or "Entra only" exist on one side only — usually a renamed or stale object, worth a look. Workgroup machines appear in neither directory. "User" is AD's Managed By attribute or the Entra registered owner, not the last person to sign in.
Name UPN Details Login user Last seen
{{ o.expandArrow }}{{ o.name }} {{ o.domainTag }} {{ o.upn }} {{ o.detailLine }} {{ o.loginLabel }} {{ o.lastSeenLabel }} Back after removal
Loading…
No objects directly in this OU.
{{ m.name }} {{ m.typeLabel }} {{ m.detailLine }}
Linked computer
{{ o.shareDetail.computer }}
IP address
{{ o.shareDetail.ipAddress }}
Path
{{ o.shareDetail.path }}
GPO
{{ o.shareDetail.gpoLabel }}
Audit: {{ o.shareDetail.auditSummary }}
Share permissions
No explicit share permissions recorded.
{{ sp.principal }} {{ sp.right }} {{ sp.type }}
NTFS permissions
No NTFS permission data recorded.
{{ np.principal }} {{ np.rights }} {{ np.inheritedLabel }}
GPO status
{{ o.gpoDetail.enabledLabel }}
Computer config
{{ o.gpoDetail.computerConfigLabel }}
User config
{{ o.gpoDetail.userConfigLabel }}
Last modified
{{ o.gpoDetail.modifiedLabel }}
Linked to
Not linked to any OU, domain, or site.
{{ lnk.text }}
Assigned to (security filtering)
No security filtering recorded — applies to Authenticated Users by default.
{{ flt.text }}
Excluded (explicit deny)
No explicit exclusions — nothing has a Deny on Apply Group Policy.
{{ exc.text }}
Computer configuration — settings summary
No computer-side settings configured (or Computer config is disabled).
  • {{ cs.text }}
User configuration — settings summary
No user-side settings configured (or User config is disabled).
  • {{ us.text }}
Linked computer
{{ o.printerDetail.computer }}
Share path
\\{{ o.printerDetail.computer }}\{{ o.printerDetail.shareName }}
IP address
{{ o.printerDetail.ipAddress }}
Driver
{{ o.printerDetail.driverName }}
Port
{{ o.printerDetail.portName }}
Linked GPO(s)
Not deployed by any GPO printer connection — matched by share path against every synced GPO's printer settings.
{{ gp.text }}
Who has access
No permission data recorded for this printer.
Principal Permission Type
{{ pp.principal }} {{ pp.permission }} {{ pp.type }}
Type
{{ o.groupDetail.categoryLabel }}
Privileged
{{ o.groupDetail.privilegedLabel }}
Mail-enabled
{{ o.groupDetail.mailEnabledLabel }}
Primary address
{{ o.groupDetail.mail }}
Alias
{{ o.groupDetail.mailNickname }}
Linked to external address
{{ o.groupDetail.externalLabel }}
Proxy addresses / aliases
None recorded.
{{ px.text }}
Members ({{ o.groupDetail.memberCount }})
No members.
{{ mb.text }}
List truncated at 200 — memberCount above reflects the true total.
Has access to (from collected ACLs)
No matching file share, printer, or GPO permission found for this group.
{{ ag.text }}
No additional properties recorded for this object.
{{ g.label }}
{{ g.value }}
No findings.
Severity Finding Resource Why it matters
{{ f.severityLabel }} {{ f.title }} {{ f.resource }} {{ f.impact }}
No changes detected yet — this fills in once the collector has run more than once.
When Type Object Change
{{ ch.whenLabel }} {{ ch.changeLabel }} {{ ch.objectName }} {{ ch.detail }}
No events reported yet.
When Event ID Level Computer Message
{{ e.whenLabel }} {{ e.eventId }} {{ e.level }} {{ e.computer }} {{ e.message }}

Network Map — O365

How this tenant's users, groups, SharePoint sites, Exchange mailboxes, Teams, and devices connect — built from data already collected, no new setup.
Network Map — O365 (PDF Preview)
Loading tenant relationships…
{{ networkMapGraphError }}
{{ networkMapToolbarSummary }}
Show:
Click a category to expand it · drag any node to rearrange · scroll to zoom {{ networkMapFreshness }}
Hover colour: {{ st.label }}
{{ networkMapSelectedNodeLabel }}
{{ networkMapSelectedNodeType }}
{{ networkMapSelectedNodeDetail }}
{{ row.label }} {{ row.value }}
No further detail returned for this item.
{{ note }}

Designer — {{ designerBoardLabel }}

Only this tab's diagram — switch sub-tabs for a separate one.
Only the O365 and Onprem tabs (and any device matched into them from Infrastructure/AD Audit) reflect real, currently-connected data. Use this canvas to sketch out topology you haven't wired up real discovery for yet, or to annotate around real data with things that have no discovery source at all (ISP link, a firewall with no SNMP access, etc). Shapes with a dashed amber outline were dropped in by the Onprem auto-seed's network sketch (Internet/Firewall/Router/VPN/Switch/hardware) — they're not part of the real AD tree either, just a starting layout to build the rest of the picture around.
Line: {{ designerStatusText }}
{{ designerError }}
Open 🧰 Toolbox above to drop a shape on the canvas · drag shapes to arrange · Connect then click two shapes to link them · scroll to zoom · Save stores this diagram against this client.
Network Map — Designer (PDF Preview)

Network Map — Hybrid

Merges the O365 map with on-prem AD and Azure-hosted infrastructure for tenants that aren't cloud-only.
Showing the diagram published from this tab's Designer. Click a category to expand its real members · open Designer to edit or unpublish.
No read-only Hybrid view yet — but the Designer works
Open Designer above and it starts as both real maps side by side: this tenant's O365 relationship map on the left, its on-prem AD tree on the right, joined by a dashed Hybrid identity link. Both halves are real data from the O365 and Onpremise tabs — expand a category to pull in its members, then add whatever has no discovery source from the toolbox.
Still planned for a read-only view here: Azure-hosted resources incl. domain controllers (Azure Infrastructure add-on) as a third zone.

Network Map — Onpremise

Domain controllers, member computers, OUs, users and groups from this client's Active Directory, via the AD Audit add-on's collector.
Network Map — Onprem (PDF Preview)
Loading Active Directory inventory…
{{ networkMapOnpremGraphError }}
No AD Audit data yet
Deploy the collector from the Integrations tab (AD Audit card) — this map fills in automatically after its first sync from the domain.
{{ networkMapOnpremToolbarSummary }}
Show:
Click a category to expand it · drag any node to rearrange · scroll to zoom
Hover colour: {{ st.label }}
{{ networkMapOnpremGroupFilterSummary }}
{{ grp.checkMark }} {{ grp.label }}
{{ networkMapSelectedNodeLabel }}
{{ networkMapSelectedNodeType }}
{{ row.label }} {{ row.value }}
ℹ️ {{ note }}

Network Map — Platform

Device fleet from the NinjaOne integration, laid out as part of this client's network map.
Not built yet
Planned source: this client's NinjaOne device inventory (real or demo-mode), rendered as its own zone or overlaid on matching M365 devices.

Audit Log

Security & compliance trail — sign-ins, MFA, permission and role changes, client lifecycle
Loading audit log…
{{ auditLogTotalCount }} of {{ auditLogRawCount }} loaded entries (up to 300)
No audit entries match this search and time range.
Time User Tenant Category Event
{{ row.time }} {{ row.actor }} {{ row.tenantId }} {{ row.categoryLabel }} {{ row.summary }}
{{ auditLogPageInfo }}

{{ tenantOverviewFields.name }} — Tenant Overview

Basic tenant information, licensing, and identity topology (cloud-only vs hybrid).
Loading tenant overview…
Could not read organization details for this tenant (Directory.Read.All).
Basic Information
Name
{{ tenantOverviewFields.name }}
Users
{{ tenantOverviewFields.users }}
Tenant ID
{{ tenantOverviewFields.tenantId }}
Groups
{{ tenantOverviewFields.groups }}
Primary domain
{{ tenantOverviewFields.primaryDomain }}
Applications
{{ tenantOverviewFields.applications }}
Licence
{{ tenantOverviewFields.license }}
Devices
{{ tenantOverviewFields.devices }}
Identity & Sync
Identity type
{{ tenantOverviewFields.syncType }}
Last on-premises sync
{{ tenantOverviewFields.lastSync }}
Tenant created
{{ tenantOverviewFields.created }}
Country
{{ tenantOverviewFields.country }}
Preferred language
{{ tenantOverviewFields.preferredLanguage }}
Technical contact(s)
{{ tenantOverviewFields.technicalContacts }}

Tenant Analyser

Copilot Readiness
Assess this tenant's readiness for Microsoft 365 Copilot — read-only, nothing in the tenant is changed.
Tenant: {{ copilotUi.tenantLabel }}
PDF Preview
Ready to assess
Reads users, licences, Microsoft 365 activity, Conditional Access and tenant sharing settings through Microsoft Graph, then scores each user for Copilot readiness. This is a read-only scan and can take up to a minute on a large tenant.
Assessing tenant… reading users, licences, activity and security configuration.
{{ copilotUi.errorText }}
{{ copilotUi.namesNote }}
Top Copilot Candidates
{{ copilotUi.candidateCount }}
Users
{{ lg.label }}
Ready or nearly-ready users, by department. {{ copilotUi.licensedCount }} already licensed.
Estimated Productivity
+{{ copilotUi.hoursPerUser }}
hours / week
saved per user (assumption)
{{ copilotUi.roiBasis }}
Key Recommendations
{{ copilotUi.recommendationCount }}
Actions
{{ lg.label }}
{{ copilotUi.unverifiedNote }}
Top Candidates for Copilot Rollout
Adoption score is based on Microsoft 365 activity over the last 30 days. Click a row for the full readiness view.
{{ copilotUi.rowCountLabel }}
{{ h.label }}{{ h.arrow }}
{{ row.name }}
{{ row.upn }}
{{ row.jobTitle }} {{ row.apps }} {{ row.department }} {{ row.readinessLabel }}
{{ row.scoreLabel }}
{{ row.scoreCaption }}
Department Users Candidates Blocked Licensed Avg adoption
{{ d.department }} {{ d.users }} {{ d.candidates }} {{ d.blocked }} {{ d.licensed }} {{ d.avgScore }}
{{ copilotUi.pageInfo }}
Readiness Findings
Security, Data Governance and Technical Readiness checks. "Not verifiable" means the data could not be read with current permissions — it is never treated as a pass.
{{ copilotUi.findingCountLabel }}
{{ f.statusLabel }}
{{ f.title }}
{{ f.category }} · {{ f.severity }}
{{ f.arrow }}
{{ f.detail }}
Remediation: {{ f.remediation }}
Source: {{ f.source }}
{{ copilotUi.intelStamp }}
{{ copilotUi.intelWarningText }}
Value of one hour of staff time ({{ copilotUi.roiCurrency }})
Hours saved per active user per week (optional)
Saved
AI & Copilot analytics were not returned for this assessment. Press Refresh Assessment to run it again.
{{ copilotUi.intelCountLabel }}
{{ blk.title }}
{{ blk.note }}
{{ cd.label }}
{{ cd.value }}
{{ cd.sub }}
{{ bar.label }}{{ bar.text }}
{{ hd.label }}{{ hd.arrow }}
{{ cell.text }}
{{ blk.pageInfo }}
{{ li2.tag }} {{ li2.title }}
{{ li2.text }}
{{ li2.meta }}

Tenant Analyser

Migration Analyser

Full pre-migration tenant readiness scan — read-only, no configuration changes.
Continuous Alerts
Emails the recipients below when a Migration Analyser scan turns up a finding that wasn't present on the previous scan. Cadence follows how often scans run here, not a fixed schedule.
Saved {{ alertSettingsSavedAt }}
{{ alertTestResult }}
"Send Test Alert" emails the saved recipients immediately, regardless of whether any finding has actually changed — use it to confirm delivery without waiting for a real change.
Ready to scan
Pulls every category this tenant's Microsoft 365 environment has data for — Entra, Security, Exchange, Teams, SharePoint, OneDrive, Intune, and Purview — and builds a scored readiness assessment. Some categories load lazily elsewhere in the app; running a scan here loads anything not already loaded.
Scanning tenant…
{{ migrationScanCurrentLabel }}
{{ stg.icon }} {{ stg.label }}
Last scanned: {{ migrationScanTimestamp }} · {{ alertCheckResultLabel }}
Executive Health Dashboard
{{ hc.label }}
{{ hc.score }}
{{ hc.detail }}
Category Snapshot
Category Key Metric Findings Score
▸{{ cr.label }} {{ cr.metric }} {{ cr.findingsLabel }} {{ cr.score }}/100
{{ sec.heading }}
{{ tc }}
{{ tc3.text }}
{{ f.label }}
{{ f.value }}
{{ f.severityLabel }} {{ f.categoryLabel }} {{ f.title }} ›
No findings at this severity level.

Distribution Lists / Public Folders

Synced out-of-band via Exchange Online PowerShell — not reachable through Microsoft Graph. Last synced: {{ exchangeDistributionSyncedAt }}
Loading distribution lists…
No distribution lists synced yet — the scheduled Exchange Online sync job hasn't run, or this tenant has none.
Name Type Members Owners Hidden from GAL
{{ dl.displayName }}
{{ dl.primarySmtp }}
{{ dl.groupType }} {{ dl.memberCount }} {{ dl.ownersLabel }} {{ dl.hiddenLabel }}
Loading public folders…
No public folders synced yet — the scheduled Exchange Online sync job hasn't run, or this tenant has none enabled (public folders are a legacy feature many tenants no longer use).
Path Mail-Enabled Item Count Size
{{ pf.path }}
{{ pf.primarySmtp }}
{{ pf.mailEnabledLabel }} {{ pf.itemCount }} {{ pf.totalItemSize }}

NinjaOne — Devices

Read-only device inventory from your NinjaOne RMM — monitoring only.
Loading devices…
Couldn't load device stats — check that the NinjaOne connection is still valid.
{{ ninjaOneDonut.total }}
Total Devices
{{ ninjaOneTotal }}
Online {{ ninjaOneOnline }}
Offline {{ ninjaOneOffline }}
OS Lifecycle
Approaching EOL {{ ninjaOneApproachingEolCount }}
End of Life {{ ninjaOneEolCount }}
By Operating System — click to view devices
{{ row.label }}{{ row.count }}
By Device Type — click to view devices
{{ row.label }}{{ row.count }}
By Category — click to view devices
{{ row.label }}{{ row.count }}
{{ ninjaOneFilterLabel }}
{{ ninjaOneTotalCount }} devices
No devices match this search.
Name Type OS Status Last Contact IP
{{ row.name }} {{ row.nodeClass }} {{ row.osName }} {{ row.statusLabel }} {{ row.lastContact }} {{ row.ipAddress }}
{{ ninjaOnePageInfo }}
Maester-style security checks against your NinjaOne fleet. Mock data — real results populate once a live client is connected.
Loading recommendations…
No recommendations available.
{{ rec.severityLabel }} {{ rec.statusLabel }} {{ rec.testId }}
{{ rec.title }}
{{ rec.description }}
Affected: {{ rec.affectedLabel }}
Fleet-wide software inventory, aggregated across all NinjaOne-managed devices. Mock data — real values populate once a live client is connected.
Loading apps…
No apps match this search.
App Installs Versions Devices
{{ app.name }} {{ app.installCount }} {{ app.versionsLabel }} {{ app.devicesLabel }}

My Clients

Clients you have onboarded to the portal
Loading clients…
Share this consent link with your client:
{{ portalOnboardUrl }}
No clients onboarded yet. Use the button above to onboard one.
{{ row.name }}
Connected {{ row.connected }}

Permissions — {{ portalPermTenantName }}

Manage what each portal user at {{ portalPermTenantName }} can access
Loading users…
No portal users yet for {{ portalPermTenantName }}.
{{ pu.initial }}
{{ pu.displayName }}
{{ pu.email }}
{{ pu.roleLabel }}
Section Access

{{ report.title }}

{{ report.description }}
{{ card.title }}
{{ card.value }}
{{ card.pct }}%
{{ lic.name }}
{{ card.legend }}
Manage Cards
{{ card.statusLabel }}
Unsaved changes — click Save so this survives a refresh.
Loading…
{{ report.rowCount }} records
{{ col.label }}{{ col.arrow }}
{{ cell.text }}
{{ report.pageInfo }}
{{ report.overviewDashboard.recsEmptyText }}
{{ ri.severityLabel }} {{ ri.count }} {{ ri.title }} ▶
Finding
{{ ri.detail }}
Impact
{{ ri.impact }}
Remediation
{{ ri.fix }}

{{ dashboardsHeaderTitle }}

{{ dashboardsHeaderSubtitle }}
Choose a Dashboard Template
{{ d.name }}
{{ d.widgetCountLabel }}
No dashboards yet — click "+ New Dashboard" to build one.
{{ w.title }}
{{ w.donutTotal }}
No widgets yet — click "+ Add Widget" to pick a metric.

{{ reportsHeaderTitle }}

{{ reportsHeaderSubtitle }}
Choose a Report Template
50 templates across every service
{{ grp.group }}
No templates match "{{ reportTemplateSearch }}"
PDF Preview
{{ r.name }}
{{ r.sectionCountLabel }}
No saved reports yet — click New Report to build one.
Company branding
Accent color:
{{ scg.label }}
Report filters {{ reportWideFilterSummary }}
{{ rs.title }}
{{ fc.label }}
No preset filters left for this section.
Custom Rule
{{ rs.customRule.fieldLabel }}
{{ rs.customRule.fieldLabel }} {{ rs.customRule.opLabel }}
·
{{ lg.label }}
{{ col.label }}{{ col.arrow }}
{{ cell.text }}
No sections yet — click "+ Add Section" to pick data to include.
Recommendations
No custom recommendations added yet — these are consultant-written notes, separate from each service's auto-generated findings.
{{ cr.title }} ({{ cr.severityLabel }})
{{ cr.text }}
{{ activeReportBranding.title }}
{{ activeReportBranding.subtitle }}
{{ rs2.title }}
{{ rs2.filterSummary }}
{{ lg2.label }}
{{ col.label }}{{ col.arrow }}
{{ cell.text }}
Recommendations
{{ cr2.title }} ({{ cr2.severityLabel }})
{{ cr2.text }}
{{ listPanel.title }}
{{ listPanel.count }} records
{{ detailPanel.initials }}
{{ detailPanel.title }}
{{ detailPanel.subtitle }}
{{ chip.text }}
{{ sec.heading }}
{{ pt.label }}
{{ lg.label }}
{{ tc }}
{{ tc2.text }}
{{ f.label }}
{{ f.value }}