The handbook

Every claim,verifiable in the source.

A walk-through of the product, the security model, and the data flow at every click. Written for engineers, security reviewers, MSPs, and the CISO signing the approval — anyone who needs to be satisfied that Meridian is safe to point at their Azure tenant.

Public source · no proprietary layer · read the code
01 · Introduction

What Meridian is

Meridian is a read-only visibility layer for your Azure estate. Sign in once, pick a subscription, and every inventory, cost, security, networking, monitoring, and change-tracking view is available under one shell. Every piece of data you see is fetched live from Azure the moment you land on the page — nothing is pre-crawled, nothing is stored on our side, nothing goes stale.

The word that matters most in that first sentence is read-only. Meridian does not have the technical ability to create, modify, or delete Azure resources. This is not a policy we enforce with review or hope — it is enforced by the code, and the enforcement is auditable in a few small files. The rest of this document explains exactly how.

Meridian is a static single-page app with a small set of stateless server-side functions. It carries no database, no queue, no analytics pipeline, no telemetry SDK, and no server-side storage of your Azure data. When you close the tab, the only thing left is the anonymous request log any hosting platform keeps for operational purposes.

02 · Audience

Who Meridian is for

Meridian is built for three overlapping audiences:

  • Cloud operators who spend half their day in the Azure Portal clicking through blades to check status, spend, and drift. Meridian collapses those clicks into one shell.
  • Managed service providers (MSPs) who manage multiple customer tenants. Meridian supports Azure Lighthouse and walks the full delegated-subscription list; every subscription is marked HOME or delegated.
  • Security and audit teams who need a read-only, auditable view of security posture — CIS control status, orphaned resources, drift since last review, WAF review, blast radius — without granting anyone Contributor-or-higher rights.

None of these audiences needs to install anything in their Azure. The only Azure-side prerequisite is the Reader role on each subscription being inspected.

03 · Sign-in

How you sign in

Meridian offers two ways to authenticate. Both are read-only.

Option A — Sign in with your Azure AD account

You authenticate through Microsoft's own device-code sign-in page (microsoft.com/devicelogin) using your normal Azure AD credentials. Meridian receives a delegated access token that can only do what you personally can do in Azure — no more, no less. If you have Reader on a subscription, Meridian can read it. If you don't, Meridian can't. Your MFA and Conditional Access policies apply as usual.

Option B — Bring a Service Principal

If your team already uses Service Principals for tooling, paste in the tenant, client ID, and client secret. Meridian uses the OAuth 2.0 client-credentials flow to mint an ARM token. The Service Principal only needs the Reader role.

Whichever method you pick, the credentials that reach Meridian's backend are stored inside an encrypted HttpOnly cookie set on your browser and never persisted anywhere else. The plaintext values never touch a log line, a database, or a filesystem.

04 · File mode

Analyze from a file (no tenant access)

Not every team can grant even read-only access on day one. For those cases Meridian has File mode: upload an exported ARM template or a Terraform state file and the same network and configuration analysis runs against it — no Azure connection, no credentials.

Parsed entirely in your browser
The file is read and analyzed client-side. It is never uploaded to any server, and File mode needs no Azure credentials at all. The parsed result lives only in your browser tab and clears when you leave.

Supported inputs:

  • Terraform state — a .tfstate file or terraform show -json output. Most accurate, because state holds fully-resolved values and real resource IDs.
  • Azure ARM JSON — an az resource list export, an ARM REST list, an exported template, or a single resource.

For deployment templates, Meridian evaluates the ARM expression language — parameters(), variables(), concat(), resourceId() and friends — so resource names and references resolve instead of showing raw [parameters('…')] strings.

Works from a file
Network topology and subnet reachability, segmentation score, VNet peering, route analysis, NSG rules, public exposure, IPAM, and core inventory (VMs, storage, SQL, Key Vault, public IPs, app gateways) — everything that is declared configuration.
Needs a live connection
Cost, right-sizing, metrics, and anomaly signals depend on billing and telemetry that isn't present in an infrastructure file, so those views are clearly disabled in File mode rather than shown with empty or invented numbers.

Throughout File mode a persistent banner marks the data as file-based — naming the file and stamping the “as of” time — so it is never mistaken for a live tenant view.

05 · Data flow

What happens when you click a view

When you open any inventory or cost view — say, Virtual Machines — the request flow is:

  1. 1. Browser → Meridian backend. Your browser makes a request to /api/arm/<subscription>/<path>. The session cookie is attached so the server can identify the signed-in user.
  2. 2. Cookie decrypt. The Function decrypts the cookie in-memory (AES-GCM, 256-bit key). It reads either the Service Principal credentials or the refresh token, then discards them from memory after the response returns.
  3. 3. Token acquisition. The function calls Azure AD to mint (or refresh) an ARM access token. Tokens are cached in a short-lived edge cache for their natural lifetime (~1 hour) so we don't hammer Azure AD.
  4. 4. Read-only ARM proxy. The Function rejects any request with a non-GET verb before it leaves the server. For allowed requests, it forwards a GET to management.azure.com with the freshly minted token.
  5. 5. Response → browser. The ARM response is streamed back to your browser as JSON. No copy is retained on our side.

The only outbound requests Meridian ever makes are to:

  • — login.microsoftonline.com (Azure AD token endpoints)
  • — management.azure.com (Azure Resource Manager)
  • — prices.azure.com (Microsoft's public Retail Prices API — no auth, no data sent)

There is no third-party analytics, no telemetry endpoint, no CDN script from an unrelated vendor. Every outbound host is a Microsoft property.

06 · Security

The read-only guarantee — four layers

The core promise is that Meridian cannot mutate your Azure. That promise rests on four independent defensive layers. All four must fail simultaneously for a write to happen — and by construction, the second and third layers are impossible to bypass at all.

Layer 1 — The ARM proxy is GET-only

Every call to Azure Resource Manager goes through a single server-side proxy function. That function begins with a hard check: any HTTP verb other than GET returns 405 Method Not Allowed before the token is ever attached. Since every ARM write operation requires POST, PUT, PATCH, or DELETE (per Azure's contract), no request that would mutate can ever leave our proxy.

Layer 2 — Resource Graph is query-only by design

Cross-subscription searches use Azure Resource Graph. Its underlying query language (Kusto / KQL) has no write primitives: no INSERT, no UPDATE, no DELETE. Microsoft's own documentation states this as an invariant. Even the Resource Graph endpoint URL is a query endpoint — there is no companion "write" API.

Layer 3 — No write client exists in the codebase

The Azure SDK packages that could perform write operations (@azure/arm-compute, @azure/arm-storage, etc.) are not imported anywhere. Every ARM call in the codebase is a raw fetch() through the GET-only proxy. If a future contributor added a write SDK, the diff would be immediately visible and could be rejected in code review.

Layer 4 — All persistence is browser-local

Drift snapshots, anomaly baselines, and your active-subscription selection all live in the browser's IndexedDB and localStorage. Deleting a snapshot removes an IndexedDB row on your device — Azure is untouched. There is no server copy to leak, corrupt, or exfiltrate, because there is no server copy.

07 · Data map

Where every piece of data lives

A full audit of what is stored where, for how long, and how it is protected. There is no other state.

DataLocationLifetimeProtection
Service Principal secret / refresh tokenEncrypted HttpOnly cookie (browser)4 hoursAES-GCM 256-bit; HttpOnly, Secure, SameSite=Lax; revocable via SESSION_EPOCH
Active subscriptionBrowser localStorageUntil you log outSame-origin isolation
Azure AD access tokenShort-lived edge cache~1 hour (token natural expiry)Keyed by SHA-256 of credentials; not exposed via API
VM retail pricesShort-lived edge cache24 hoursNon-sensitive public data
Drift snapshotsBrowser IndexedDB (your device)Until you clear site dataPer-user, per-device; never sent to a server
Anomaly baselines (rollup counts)Browser IndexedDB (your device)60 days (auto-pruned)Per-user, per-device; never sent to a server
Your Azure resource dataOnly in your browser's RAM, while the page is openDiscarded on tab closeNever persisted, never sent to a third party
The bottom line
There is no server-side database of any kind — no object store, no cache of your estate, no analytics warehouse. A copy of your Azure data that never exists is a copy that cannot leak, be subpoenaed, drift out of policy, or answer awkward data-residency questions. Meridian's smallest surface is the biggest security feature it has.
08 · Boundaries

What Meridian does not do

Explicit boundaries make the app easier to reason about. Meridian deliberately does not:

  • Write to Azure. No creates, no updates, no deletes, no policy assignments, no role assignments. See the four-layer guarantee.
  • Ship third-party analytics. No Google Analytics, no Segment, no PostHog, no LinkedIn pixel, no Facebook tag. The only network destinations are Microsoft's identity and management endpoints.
  • Retain your data on our servers. Snapshots and baselines live in your browser. Prices and tokens cached at the edge are anonymous and short-lived. Nothing about your estate is retained past the moment you close the tab.
  • Aggregate customer data. There is no shared training set, no cross-tenant model, no leaderboard. Your numbers are yours alone.
  • Call an LLM or external AI service by default. The intelligence signals (right-sizing verdict, drift risk, anomaly detection) are pure rule-based and statistical classifiers running in your browser. No inference is farmed out.
  • Require an agent in your environment. Nothing to install in Azure. Nothing to install on a bastion. Nothing running as a scheduled task.
09 · Intelligence

How the intelligence signals work

Three signals turn raw inventory into "here is what to act on." All three run entirely in your browser against data Meridian has already fetched. None involves a third-party service or a machine learning model over the network.

Right-sizing verdict

For every VM Azure Advisor recommends resizing, Meridian fetches the last 30 days of CPU metrics from Azure Monitor. A pure JS classifier grades the recommendation as high, medium, or low confidence based on p95, max, and busy-ratio thresholds. Trusted savings only include the high and medium items. Low-confidence recommendations — the ones where the metrics contradict Advisor — are struck through in the total.

Drift risk

Every change in a drift diff is scored RISKY, NOTABLE, or benign by a rules table. Storage suddenly public? RISKY. NSG opened to the Internet on a critical port? RISKY. Tag changed? benign. The rules are inspectable in the source and can be reviewed for your compliance baseline.

Anomaly detection

Meridian silently records a daily rollup of ~14 subscription metrics (VM count, orphan waste, risky NSG rules, storage that allows public access, etc.) into your browser's local storage. On subsequent loads, today's numbers are compared to the median of the last week's rollups and deviations are flagged. Because the baseline is per-device, no data ever leaves your machine.

No black box, no LLM guesswork — just proven techniques turned into answers your team can act on. Here is what that looks like in practice:

Spend forecast

You get a realistic idea of next month's bill before it lands, so a creeping spike shows up as a trend you can act on early.

Shortest attack path

Shows the easiest route an attacker could take to reach your crown jewels, so you know which single link to cut first.

Right-sizing

Recommends a size that comfortably handles real peaks without paying for capacity that sits idle.

Early drift alarm

Catches gradual problems — a slow memory leak, creeping cost — that fixed thresholds miss until it's too late.

Segmentation score

A single 0-100 health number for how well your network limits the blast radius if one subnet is compromised.

Reservation savings

Shows the real yearly money you'd save by committing — without pushing you to over-commit to capacity you won't use.

Real math you can trust
Every signal is a named, established technique that runs right in your browser on data already fetched — nothing leaves your tenant, and the exact method behind each view is named where you use it. No mystery scores, no vendor model, no data pooled across customers.
10 · Toolkit

The design & troubleshooting toolkit

Beyond the always-on views, Meridian ships a set of focused tools that answer the specific questions you ask when you're shipping a change or chasing an incident. Each one takes a question you'd normally solve by clicking through a dozen Portal blades and turns it into a single screen. All of them are read-only.

When you see…Reach for
Traffic can't reach (or leave) a VMConnectivity Troubleshooter
502 / backend shows unhealthyBackend Health Reasoner
App can't resolve a private endpointDNS & Private Link
It worked yesterdayChange Timeline
Is it my config or is it Azure?Resource Health
CPU / latency changed — but when?Metric Anomaly
The Azure bill jumpedCost Spike Detector
A user or app can't do an actionRBAC Access Resolver
Who can reach this Key Vault / Storage?Access Chain Analyzer
Is this IaC safe to deploy?IaC Visualizer
Before you deploy
IaC Visualizer
Open

Answers: What will this code actually build, and is it safe to apply?

  1. 1Paste Terraform, ARM, Bicep, or Kubernetes YAML — or click an example.
  2. 2Read the architecture diagram, grouped into resource-group / namespace containers.
  3. 3Fix the flagged risks (open secrets, public storage, weak TLS) before you apply.
Backend Health Reasoner
Open

Answers: Why is my load balancer or App Gateway backend unhealthy?

  1. 1Open the page — it reads every load balancer and gateway config.
  2. 2Scan the findings: empty backend pools, missing probes, unlinked rules.
  3. 3Fix the exact config each finding points to.
“Why can't it connect?”

The Connectivity Troubleshooter mirrors Azure's own IP Flow Verify. You choose a source, a port, and a direction, and it walks the packet along the same path Azure would — evaluating each network security group in priority order — and tells you the single rule that decides the outcome:

Internetthe client
→
Public IPmust exist
→
Subnet NSGrules by priority
→
NIC NSGDenyAllInBound
→
VMnever reached

In this example the packet is stopped at the NIC's NSG — the tool names the exact rule (DenyAllInBound) so you know precisely what to change. Reachable paths show every hop green.

Connectivity Troubleshooter
Open

Answers: Why can't traffic reach (or leave) my VM?

  1. 1Pick a VM, direction (inbound/outbound), protocol, and port.
  2. 2Click Trace path.
  3. 3The blocked hop names the deciding NSG rule — that's your fix.
DNS & Private Link
Open

Answers: Why can't the app resolve its private database or storage?

  1. 1Open the page — every private endpoint is listed.
  2. 2Look for a red 'No zone' badge next to an endpoint.
  3. 3Create the missing privatelink.* Private DNS zone.

The most common private-link failure isn't the connection — it's DNS. The endpoint is approved, but without its matching private DNS zone the client still resolves the public IP and times out:

Appasks for db name
→
No private zonethe gap
→
Public IPwrong answer
→
Timeoutconnection fails
Root-cause an incident
Change Timeline
Open

Answers: It worked yesterday — what changed?

  1. 1Choose a time window (24h / 7d / 30d).
  2. 2Filter to the resource that's misbehaving.
  3. 3The create/update/delete that broke it is near the top — with who did it.
Resource Health
Open

Answers: Is this my configuration, or is it Azure?

  1. 1Open the page — unhealthy resources sort to the top.
  2. 2Read the state Azure reports (Available / Degraded / Unavailable).
  3. 3A platform-initiated 'Unavailable' means the fault is Azure's, not yours.
Metric Anomaly
Open

Answers: When did this VM start behaving differently?

  1. 1Pick a VM, a metric (CPU, memory…), and a window.
  2. 2The dashed line marks the moment the baseline shifted.
  3. 3Cross-check that timestamp in the Change Timeline for the cause.
Cost Spike Detector
Open

Answers: When did the bill jump, and by how much?

  1. 1Open the page — it scans 90 days of real billed spend.
  2. 2Read the detected baseline-shift date and the biggest daily jumps.
  3. 3Open Cost → Cost Attribution for the per-resource breakdown.
Access & permissions
RBAC Access Resolver
Open

Answers: Why can't this user or app do that operation?

  1. 1Pick the principal (user, group, service principal, or managed identity).
  2. 2Type the operation to test, e.g. Microsoft.Storage/storageAccounts/read.
  3. 3Get an Allowed / Denied verdict and the role that grants it.
Access Chain Analyzer
Open

Answers: Who can actually reach this Key Vault or Storage account?

  1. 1Pick a sensitive resource.
  2. 2See every identity with a path — RBAC role or Key Vault access policy.
  3. 3Over-broad grants (Owner at subscription scope) are flagged for review.
Everything here is read-only
These tools only read — Azure GET calls, plus the read-only Resource Graph and Cost Management query engines. They diagnose and explain; they never change a thing in your cloud. Nothing that requires a write (or a write-shaped API call) is included.
11 · Architecture

Deployment architecture

A static single-page app plus a small set of stateless serverless functions on a managed edge platform — no always-on server, no VM or operating system to patch, and all traffic HTTPS end-to-end. That is the entire footprint.

12 · Audit checklist

Security review checklist for your CISO

A one-page summary a security reviewer can use to sign off on Meridian. Each question links to the section that answers it.

Can this app modify our Azure resources?

No. Four independent layers make writes architecturally impossible.

See details
What Azure permissions does it require?

Reader role on each subscription. Nothing higher, nothing broader.

See details
Where do our credentials live?

Encrypted with AES-GCM in an HttpOnly cookie on the user's browser. Never in logs, never in a database, never in a filesystem.

See details
What data leaves our tenant?

Only Azure Resource Manager responses, and only to render the page the user is viewing. Nothing is retained on our side.

See details
Are there third-party trackers, analytics, or telemetry?

No. Every outbound host is a Microsoft property (login.microsoftonline.com, management.azure.com, prices.azure.com).

See details
How is the session invalidated?

Cookies expire after 8 hours automatically, or immediately when the user clicks Logout.

See details
How is source code auditable?

The full source lives in a public Git repository. Every claim in this handbook can be verified by reading the code.

See details
What happens if we tear this down?

Delete the deployment. No Azure resource, no server-side data, and no external dependency remains.

See details
13 · FAQ

Common concerns, answered

How does this differ from just using the Azure Portal?+

The Portal shows one blade at a time. Meridian aggregates 22 views under one shell, adds live-priced cost intelligence, cross-subscription rollups, drift snapshots, and three intelligence signals — all read-only, all in one place.

Can we evaluate Meridian without giving it any Azure access?+

Yes — use File mode. Upload an exported ARM template or a Terraform state file (.tfstate / terraform show -json) and Meridian runs its network topology, subnet reachability, NSG/WAF and IPAM analysis entirely in your browser. Nothing is uploaded and no credentials are needed. Cost and metrics stay disabled because that data isn't in an infrastructure file.

Is there a hosted SaaS version, or must we self-host?+

The public hosted version lives at meridian.cloudcanvas.info. You can also deploy your own private instance in a few minutes — it's a static app plus stateless functions, so it runs on any modern edge or serverless platform.

How is authentication rotated?+

Sessions expire after 4 hours regardless of activity. To sign everyone out on demand, bump the SESSION_EPOCH environment variable — every previously-issued cookie fails validation on the next request. As a nuclear option, rotating SESSION_SECRET invalidates sessions and rotates the encryption key at the same time.

Can the app be air-gapped or run privately?+

Yes. The app is a static bundle plus stateless functions, both of which can be deployed to a private, internally-routed environment so only your users can reach it — provided the function environment can still reach the Azure endpoints it reads from.

What if a developer accidentally introduces a write path?+

It would show up as a diff in code review. The ARM proxy's GET-only check is a single small function, easy to spot. Introducing a write-capable Azure SDK is also a visible dependency change reviewers can catch.

What is the incident-response process if something goes wrong?+

Deployments are immutable and can be rolled back instantly from the hosting console. Because Meridian holds no server-side state, a rollback cannot corrupt any customer data. Revoking every session takes under a minute via the session controls.