most teams trust their fabric model as truth.
It is not.
Your DAX looks like analytics,
but architecturally it's a distributed decision
engine running without your intent.
That distinction matters.
Because once human authored logic starts deciding
what's visible, you're no longer enforcing access,
you're inferring it at runtime.
Here's the uncomfortable truth and the fix.
I'll walk through five repeatable failure modes
that make this inevitable,
then show the deterministic controls that stop it.
You'll leave knowing which decisions are illegal
to make in DAX,
and how to enforce your assumptions
that the control plane so your model can't drift.
Case one, RLS bypass via measures when total sleek.
Most organizations celebrate the first time
row level security works in testing.
The right rows disappear, the demo looks safe.
They are wrong, what RLS does is constrain base tables.
What your measures do next is an authorization system
of their own written by analysts,
executed by the engine,
and never reviewed by identity.
This is where total sleek.
You build a perfectly reasonable page,
a summary card for total sales,
a bar chart by region, and a KPI that flag
significant variance.
RLS filters the rows to east as intended,
but the measure isn't just summing a column,
it's iterating, revising filter context,
and sometimes reaching around your security boundary,
via calculate and surmix.
If one branch of logic evaluates a broader scope,
even briefly, you've created a side channel.
No alert fires.
The result looks like analytics.
Auditors later find an inference path
that reconstructs a restricted total by subtraction
or variance across visuals.
The thing most people miss,
sumics and calculate are policy engines in disguise.
They are not just math, calculate rewrite filter context.
Assume X loops through a table,
changing context row by row,
and invokes other measures inside that loop.
In other words, your aggregation
is a distributed decision program operating after RLS.
You did not disable RLS,
you described an alternate view of the world,
the engine is free to compute.
This clicked for me the first time,
an internal review asked a simple question.
Can a user with access to only East deduce West
if they can see any all up total anywhere?
The answer hinged on one measure,
it used calculate with all to normalize a benchmark.
That normalization effectively invited data
from outside the user's security scope,
producing a number that could be joined
with visible partitions to infer the rest.
The report never displayed West directly.
It didn't need to, the math exposed it.
Here's why this happens architecturally.
RLS is not the boundary.
Measure semantics are,
the tabular engine evaluates measures in filter context,
and your code can alter that context.
All all except remove filters cross filter,
treat us these functions reshape the decision graph.
You can craft a measure that computes across an entire table,
then present only one slice of it visually.
The numbers still carry the weight of the unfiltered scope,
that's conditional chaos.
A security model drifting from deterministic to probabilistic
through innocent looking logic.
Now here's the shortcut nobody teaches.
Treat authorization adjacent DAX as illegal.
If a measure changes visibility, rows, columns, or classification,
it is acting as an access control
that belongs to identity, not DAX.
If you remember nothing else, remember this.
DAX must never decide who can see data identity must.
Let me show you exactly how to recent test a measure.
Ask three questions.
Does any branch of this logic remove or bypass filters
on protected domains?
Look for all remove filters or filters
that reference sensitive dimensions?
Does the measure compare a scoped value
against an unscoped benchmark?
If yes, you've created a leakage path by subtraction.
Does the measure rely on totals that are not RLS scoped
identically to the visual?
Missmatched scope is an inference engine.
Once you nail that, everything else clicks.
You refactor measures, so benchmarks are computed upstream
and labeled.
You refuse normalization that crosses identity boundaries.
You ensure any global totals are computed
and stored in a domain where identity has already decided
who can query them.
Now here's where most people mess up.
They try to fix this with training.
They create a style guide.
They run a brown bag on safe DAX.
And then the model grows, velocity wins,
and one helpful exception sneaks in to just get the dashboard out.
That exception becomes a pattern.
Entropy accelerates.
You're back where you started with a smarter looking leak.
The deterministic stance is different.
You enforce the boundary outside DAX.
Entra handles authorization.
Per views, sensitivity labels, veto reuse.
They don't annotate it.
Data loss prevention blocks exfiltration parts
at the edges, exports notebooks, composite models,
shared data sets.
Capacity isolates blast radius,
so failures stay local and investigations stay bounded.
Identity compiles intent DAX consumes data.
They are not the same task.
Microstory, last quarter, a team
shipped a revenue view with RLS by region.
A variance to plan measure used remove filters
date to stabilize seasonality.
It looked harmless.
In order to swap the plan table for plan by region,
variance flipped into an inference tool.
Users could derive other regions planned
deltas by comparing my region to the stabilized total.
RLS was working, intent was not.
We removed the measure, pushed plan aggregation upstream,
and enforced a label that blocked any model
from introducing a cross-region benchmark
without a control plane approval.
The game changer nobody talks about is this.
Once you declare certain DAX patterns illegal,
you simplify the entire review surface.
You move from probabilistic assurance, looks fine in dev,
to deterministic enforceable rules, cannot exist in prod.
And boom, look at that result.
Total stop leaking, not because people got better at DAX,
but because DAX stopped being allowed
to act like an authorization engine.
Now that RLS works, calculated tables will still
fork your truth next quarter.
That's the next failure mode.
Case two, semantic model drift via calculated tables.
The second place organizations congratulate themselves
is when the source system is clean
and the star schema is approved.
They believe the model is anchored.
It is not.
The moment a calculated table lands in the semantic model,
you've created a parallel rulebook
that nobody upstream can see, govern or retire.
That distinction matters.
Here's the failure pattern.
A team needs a quick products and market slice
that joins today's catalog to last quarter's launch window
and a marketing eligibility flag.
Instead of asking the data platform
to publish a govern dimension, they write a calculated table
in the model.
Select columns, add columns, a filter here, a union there.
It loads instantly.
Visuals light up, velocity wins.
You now have a shadow dimension
that encodes business logic outside lineage
and outside labels.
That table becomes a joint partner
and quietly redefines reality.
What most teams miss is simple.
Calculated artifacts are entropy generators.
They duplicate structure in bed decisions
and break inheritance.
Sensitivity labels from purview
don't propagate into the calculated result
the way you assume.
Lineage shows a tidy arrow by its theater.
Lineage is evidence, not assurance.
It tells you where the data moved,
not whether your new definition state compliant with policy.
Over time, these tables accumulate canonical reference catalogs,
state helpers eligibility bridges, each one slightly different,
each one disagreeing by one edge case.
Drift stops being accidental.
It becomes structural.
This clicked for me when a model review surfaced
two numbers for eligible customers.
One came from the warehouse view, label, confidential.
The other came from a calculated table
that tweaked eligibility for a campaign.
Both were right for their authors.
Now there could be safely deleted.
The calculated one had bled into measures
in visuals across five workspaces through shared data set reuse.
We could not audit who could see what,
when, without replaying human intent,
spread across dozens of DAX expressions.
That is security that created by convenience.
Now here's where most people mess up.
They treat calculated tables as just in time modeling.
It's faster to build here.
It is faster.
It is also governance bypass.
The model becomes an authoring surface
for business rules that should have lived upstream,
where identity, labeling, and DLP can be to them.
When you compute the rule in the semantic layer,
you grant analysts the power to redefine classifications,
rewrite keys, or stitch domains
without the control plane ever seeing it.
You are not misconfiguring fabric.
You are omitting design.
Architecturally, this is why drift is inevitable.
The semantic model is a consumer.
It should bind to governed definitions.
When it produces definitions, it forks the truth.
Every fork dilutes enforcement.
Labels don't propagate deterministically across a table
synthesized from multiple inputs with mixed classifications.
Joins materialized in DAX don't inherit the same identity
boundaries that entra enforces at the source.
And because calculated tables feel harmless, just DAX, just data,
they slip past review.
These pathways accumulate.
The deterministic stance is ruthless.
Business definitions live upstream.
The model consumes never redefines.
If the warehouse lacks the construct, you added there.
If the domain team won't own it, you do not ship it.
That is not dogma.
It is boundary enforcement.
Upstream is where identity compiles intent, purview labels,
veto unsafe compositions, and DLP policies
can block downstream reuse.
If a control cannot stop a model from existing,
it is not governance.
Let me show you exactly how to test for drift.
Ask three questions.
Does this calculate a table encode a business definition
that exists or should exist upstream?
If yes, it's illegal and model logic.
Does a join or union across domains
with different sensitivity labels?
If yes, you've created a classification
override the label system can't see.
Does any downstream measure rely on this artifact
to scope visibility?
If yes, you've mixed authorization semantics
with analytics again.
Once you see that, everything else clicks.
You refactor, disallow calculated tables for domain logic,
restrict them to harmless scaffolding only under controlled
review or ban them entirely.
You root requests to data engineering
where labels, lineage, and identity live.
You codify this in publishing policy.
No publication when calculated artifacts of prohibited
categories exist.
Block at build replaces fix in review,
a micro story, a finance team needed active agreements
with a retailer-specific carve out.
They built a calculated table to filter out dormant SKUs
and applied a geographic exception for one chain.
It worked.
A month later, an audit flagged inconsistent counts
across regions.
The calculated artifact had been copied
into a gold workspace and shared as a golden data set.
Two truths existed, both certified.
We killed the table, pushed the definition
into the warehouse attached a highly confidential label
that prevented cross-tenant reuse
and added a DLP rule preventing export
for any model referencing that label.
The count stabilized, the blast radius stayed local
because capacity isolation kept finance models
off shared capacities.
The game changer nobody talks about is this.
Once you prohibit entire categories of calculated artifacts,
the model surface area shrinks to analytics.
Exceptions stop compounding.
Upstream definitions become the only pathway.
You gain something rare in BI, delete safety.
You can retire logic in one place
and know you didn't leave an undead copy in a thousand PBX files.
Even with perfect sources and no calculated tables,
teams will still point to lineage when decisions drift.
That's the next failure mode, lineage theater,
because arrows do not enforce policy.
Enforcement does case three, lineage theater,
pretty graphs, no guarantees.
After you ban calculated artifacts,
someone will hold up Fabric's lineage view
as proof you're safe.
The arrows look authoritative.
Sources flow to transformations, to lake houses,
to semantic models, to reports.
Confidence returns.
It should not.
Lineage is a narrative.
Enforcement is a control.
Those are not the same thing.
Here's the failure pattern.
A regulated data set enters one lake
with a confidential label.
A data flow refines it.
A warehouse table feeds a semantic model.
The lineage graph shows a clean path
from origin to consumption.
Meanwhile, an analyst connects a notebook to the model,
materializes a helper parkay for a side analysis
and re-imports it into a different workspace as benchmark.
The arrows don't render that detour
with the same weight or timing.
Sensitive data has cross boundaries
and the map still looks pretty.
The thing most teams miss is simple.
Lineage is evidence, not assurance.
It's post facto storytelling.
It can tell you where data moved.
It cannot tell you whether your policies were enforced
when it moved, whether labels persisted intact
or whether identity boundaries held
when logic fused domains.
If enforcement is optional, theater grows.
The graph gets denser.
Risk becomes decorative.
This clicked for me in a privacy review
where every box was green.
The lineage showed customer data sourced
from a governed lake house,
transformed by a certified data flow,
landing in a certified semantic model.
Perfect.
Except a top accounts table existed in the model,
created by importing a CSV exported
from a prior version of the same model.
The lineage omitted the export import
because it occurred through a user device
and a temporary workspace.
The arrow missed the policy violation.
The report did not.
Now here's where most people mess up.
They treat lineage as a guardrail.
It is not.
It is a dashboard.
You cannot prevent a car crash with a speedometer.
You can only measure the speed after you've chosen it.
The governance stance has to invert.
Labels and DLP veto unsafe flows in real time.
Lineage explains what happened later.
If a label can't stop a model from being published,
that label is decorative.
If DLP can't block a notebook
from writing a sensitive join to an ungoverned folder,
your edges are ornamental.
Architecturally, this is why guarantees fail.
Fabric connects heterogeneous planes,
control, data, compute.
Each has its own decision surface.
A lineage graph stitches metadata across them,
but not every hop is instrumented equally,
not every path is synchronous
and not every consumer is visible.
Notebooks, exports, composite models, shared data sets,
these are access planes masquerading as convenience.
The map can't enforce intent
because it doesn't own the enforcement points.
Per view does, entra does, DLP does.
If those are not configured to veto,
the arrows are just arrows.
Let me show you exactly how to treat lineage correctly.
Three rules.
Assume every arrow is a hypothesis.
Verify with enforcement sensitivity labels
must persist across the hop and block operations
when they don't.
Tested by attempting the prohibited action
and expecting a failure.
Treat off graph flows as the default threat.
Any export, notebook, write or cross workspace reuse
must encounter DLP at the boundary
and conditional access at identity.
If you can't force that check, you do not control the edge.
Use lineage for impact analysis, not comfort.
When a source changes, you trace who breaks.
When an incident hits, you reconstruct blast radius.
You do not assume safety because the graph looks clean.
A micro story.
A health analytics team proudly showed full lineage
from EMR extracts to a deidentified encounters model.
Labels looked correct and to end.
During a drill, we asked them to export a small slice
for a vendor model test.
The exports exceeded because the label policy annotated.
It didn't veto.
The CSV was re-imported as a synthetic benchmark
in a separate workspace.
Lineage showed a new node post hoc.
We flipped the policy, label blocks export for that classification,
notebooks, writing tables, inherit and propagate labels,
DLP intercepts cross workspace imports with confidential payloads
and conditional access forces compliant devices
for any lake house right.
The next export attempt failed closed.
The graph didn't change much.
The system did.
The game changer nobody talks about is this.
Once you stop treating lineage as a control,
your design changes.
You move decisions to the control plane,
labels define what?
DLP enforces how data leaves or persists.
Entra decides who.
Lineage becomes what it always was.
Evidence.
Useful.
Informative, but never a guarantee.
Case 4.
Share data set plus cross workspace access.
You fixed calculated tables.
You stopped trusting lineage.
Then someone proposes the golden data set.
One semantic model to rule them all
shared across workspaces for consistency.
It sounds efficient.
It is an access plane.
The moment you reuse a model across workspaces,
you erode the very boundaries you thought you were enforcing.
Here's the failure pattern.
Finance publishes a certified revenue core semantic model
in a controlled workspace.
Product, sales and ops build, thin reports against it
from their own workspaces.
To speed adoption and analyst adds a few convenience roles
in the shared model plus a couple of broadly scoped
intro groups so everyone who needs it gets in,
it works queries flow, dashboard ship.
Three months later, an audit asks a simple question.
List every user who could access Rose labeled highly confidential
for region X on the evening of June 5th.
You can't answer because identity scope now spans
multiple workspaces, each with separate sharing,
each with local report level filters,
and each with its own set of temporarily added users
that never got removed.
The golden dataset dissolved your boundary.
The thing most teams miss is simple.
Cross workspace reuse is not a convenience feature.
It's an access plane.
When you point a report in workspace B at a model in workspace A,
you didn't just reuse metrics.
You created a new path where users, service principles,
and groups in B can induce queries against A.
If inheritance semantics between the control plane,
workspaces, roles, sharing, and the data plane model permissions
are less, don't match perfectly, and they never do.
You've now got inferred trust replacing explicit authorization.
This clicked for me during a permissions review.
The shared model had tight RLS by region.
The consuming workspace had a power BI app
with build permission granted to a team group
that included contractors.
Contractors could not view the app content,
but build permission was enough to create a new report
that bound to the shared dataset,
publish it to a different workspace,
and request access there through a different owner
who assumed group membership implied vetting.
Intent dissolved across boundaries.
No breach, no alert.
Just architectural erosion.
Now here's where most people mess up,
that they try to manage shared data sets sprawl
with naming conventions and wikis.
They write who should use this on a confluence page
and hope it sticks, or they centralize ownership
in one admin who approves every access request.
It works until it doesn't, velocity wins,
and exceptions pile up as temporary.
Those exceptions are entropy generators.
Over time, your golden dataset becomes a federation
of implied contracts you never encoded.
Architecturally, this is why the boundary fails.
Workspaces are control plane containers.
Data sets are data plane objects, reports in other workspaces,
create new authorization contexts
that your original workspace never sees.
Even if RLS holds, the identity graph expands.
App audiences, build permissions, share links,
service principles, and cross tenant B2B guests.
And remember, the engine evaluates measures
under whatever filter context the consuming reports applies.
If that report introduces global benchmarks
or helper pages that compare scoped values to unscoped ones,
you just reintroduce the inference problem
from a different angle.
Now scattered across teams you don't manage.
The deterministic stance is uncompromising
and force boundaries at Entra Group and Service Principle Level.
No implicit reach through.
That means a few hard rules.
The only identities allowed to query a shared dataset
are explicitly enumerated Entra Groups
that you own, review, and recertify.
No nested everyone groups, no ad hoc shares, no email addresses.
Build permission is not a shortcut for trust.
If a user can build, they are in scope for query.
Treat, build as equivalent to, may execute arbitrary DAX
against this model.
If that's not acceptable, they don't get built.
Consuming workspace is do not extend authorization.
They project it.
If the consuming workspace contains users not
in the datasets approved groups, the connection fails closed.
No inherit from container semantics.
No app audience implies data access.
Let me show you exactly how to recent test
a shared dataset design.
Ask three questions.
Can any consuming workspace add a principle
who is not present in the datasets Entra Groups
and still induce queries?
If yes, you have reached through.
Does any consuming report introduce measures
that compare scoped values to all values
from the shared model?
If yes, you've reopened an inference channel.
Is there a service principle with build rights used
for automation?
If yes, confirm its app role is scoped
to the same groups enforced by RLS
or you've created a machine bypass.
A micro story.
A retailer standardised on a shared store performance model.
Marketing built thin reports in their workspace.
To drive a campaign, they granted
a vendor service principle build access
to bind data into a PowerPoint generator.
The principle wasn't in the models region groups.
RLS still filtered row visibility,
but the automation rendered a cross-region trend
by using measures that normalised against removed filters
store.
The vendor never saw individual stores.
They saw a decorated trend line that when compared
to their own regional data, allowed back calculation
of competitor deltas.
Nobody intended it.
Everyone assumed build wasn't view.
It was both.
The game changer nobody talks about is this.
Once you treat cross workspace reuse as an access plane,
you change the defaults.
Shared data sets live behind dedicated Android groups,
no nested membership, quarterly recertification.
Service principles are workload identities
with conditional access and kill switches.
Consuming workspaces get zero authority by default.
Build is gated by the same groups as view.
And when a team insists on a local convenience measure
that compares scope to unscoped, you don't argue style.
You block publication until that logic lives upstream
where identity has already decided who may see the result.
You are not misconfiguring power BI.
You are refusing to let convenience become your authorization
model, boundaries aren't labels or arrows.
Boundaries are identities evaluated at runtime
enforced by design.
Case five, Dex exception sprawl, the patchwork semantic layer,
you band calculated tables, you lockdown shared data sets,
the arrows no longer allow you.
Then the sprawl begins, not with a breach,
but with a favour, which we just need a one-off measure.
It chips, it works, it stays.
Six months later, the semantic layer is a quilt of exceptions.
Nobody can read, nobody can test, and nobody can retire.
Here's the failure pattern.
A report needs a clean profit margin
that excludes promo excuse.
Another team wants a net revenue
that smooths returns over a rolling window.
A third needs active customers with a carve-out
for trial periods.
Each request is reasonable.
Each becomes a local measure with a slightly different definition
and a slightly different escape hatch.
Review never happens because there's nothing
obviously malicious, just math.
Over time, those one-offs crystallize into patterns.
Helper measures that normalize across removed filters,
convenience flags that backdoor classification,
total versus my scope comparators
that reopen inference dynamic format strings
that encode sensitive state in visuals.
The model becomes an authorization patchwork
disguised as analytics.
The thing most teams miss is simple.
Exceptions are entropy generators
that never retire themselves.
Readability is not control.
A pretty measure name and a comments block
don't enforce anything.
Libraries without policy are accelerants.
The moment you centralize a helper measure
and publish it as reusable,
you've industrialized the exception.
A thousand reports can now invoke a logic path
that was never vetted by identity, labels, or DLP.
That is how semantic layers turn into decision engines
you didn't design.
This clicked for me during a deprecation exercise.
We tried to remove net revenue edgy,
created two years prior to handle a promotional anomaly.
It lived in four workspaces, had eight variations
and fed a KPI used by finance, marketing, and operations.
Each copy diverged subtly, different date windows,
different product filters, different fallback behaviors
when plant tables changed.
We couldn't kill any of them without breaking good reports.
We weren't refactoring DAX.
We were unwinding organizational folklore embedded in formulas.
Now here's where most people mess up.
They attempt to fight sprawl with linting and code reviews.
They add naming conventions, folder structures,
a helper table of standard measures, and a request form.
It slows entropy for a quarter.
Then velocity wins, a deadline arrives.
Someone copies a measure, tweaks one line, and ships.
Exceptions compound because your controls are advisory.
They don't fail closed.
Architecturally, this is why sprawl is inevitable
in a permissive system.
DAX is a functional language with powerful context manipulation.
It can represent authorization adjacent logic, succinctly,
and spread instantly via copy paste or shared libraries.
Without a policy compiler that forbids entire categories,
you can't prevent the same anti-pattern
from reappearing with a new name.
Every library you publish without a policy manifest
becomes a distribution channel for ambiguity.
Every temporary measure becomes a new model.
The deterministic stance is blunt, prohibit categories
of logic and DAX.
Ban authorization adjacent measures outright.
If a measure alters visibility in further cross-identity boundaries
rewrites business keys or overrides classification,
it cannot exist in the semantic layer.
You don't review it, you block it, you relocate the need upstream,
where identity labels and DLP can adjudicate.
And you drive the rest through libraries with policy manifests,
not just code.
A manifest declares the allowed filters, the sensitivity scope,
the identity assumptions, and the failure mode.
If the assumptions aren't met, the build fails,
not a warning, a veto.
Let me show you exactly how to reason test
for sprawl before it metastasizes three filters.
Name gravity.
If a measure's name invites reuse, net, adjusted,
normalized, assume it will spread, treated as policy,
not convenience.
Scope mismatch.
If any branch compares scoped values to unscoped totals,
it's an inference path in disguise.
Illegaled on classification distortion.
If dynamic format strings, icons, or SVG encode sensitive state
that are less or labels would otherwise hide,
you've created a leakage channel.
Ban it.
A micro story.
A sales ops team published pipeline adje
to exclude internal transfers from forecasts.
Marketing loved it, copied it, and added a brand filter,
finance forked it, switching to fiscal calendars.
Within weeks, three adjusted pipeline KPIs
disagreed by single digits in executive decks.
Nobody knew which was canonical,
and one variant used all date to stabilize seasonality,
reopening an inference path across regions.
We pulled the plug.
The adjustment moved upstream into the warehouse
with a highly confidential label.
The library got a manifest, allowed filters,
fiscal alignment, and a hard stop
if a report attempted remove filters over protected dimensions.
Build broke until they complied.
The disagreement disappeared, so did the side channel.
The game changer nobody talks about is this.
Once you outlaw whole families of DAX exceptions
and require manifest for reusable logic,
the semantic layer stops being a patchwork.
Measure return to analytics.
Policy returns to identity.
Sproul doesn't slow.
It fails to exist.
Illegal in DAX decisions that must fail closed.
Before we fix anything else, we have to draw the red lines,
not preferences, not best practices, illegal categories,
because ambiguity is where entropy grows
if a measure can change what's visible,
infer what's hidden, or rewrite what identity already decided
it cannot exist.
These are the decisions that must fail closed in DAX.
Prohibit visibility changes encoded in measures.
Anything that expands or contracts
who can see rows or columns directly or by proxy
is in access control.
That includes patterns that do the following.
Remove filters, unprotected dimensions,
using all, all except or remove filters.
Conditionally, mask values based on slices
when the slicer scope differs from identity scope.
Or fabricate helper totals that aggregate
outside the viewers are less.
Architecturally, these aren't aggregations.
They are alternate worlds.
If you need a global view, computed upstream
under identity and publish the result as a governed artifact.
DAX consumes visibility.
It never defines it.
Prohibit security context, inference,
via aggregates or conditional masking.
If a measure can compare my scoped value to an all-value,
you've built a subtraction engine.
If it can flip format strings, icons or SVGs
based on a hidden state you've encoded a covert channel,
the shortcut nobody teaches is simple.
Any comparator that crosses identity boundaries
is an inference tool in disguise.
The engine is happy to compute both sides.
Your RLS won't stop the math.
The only safe version is one where both operands
are produced upstream in a domain already decided
by Entra and Tag by Purview.
If that's not true, the measure is illegal.
Prohibit business key rewrites that bypass lineage
and labels calculation shortcuts
that stitch keys across domains,
concatenating region and month,
coalescing surrogate keys or reassigning unknowns
on the fly or classification operations.
They alter how data joins, which alters what rows exist.
Upstream is where keys are defined, stewarded and labeled.
In model rewrites create a side ledger,
your governance can't see.
That distinction matters.
If the business key needs a fix, fix it where lineage can prove it
and labels can veto it.
Prohibit data classification overrides
including format string tricks and SVG encoding
of sensitive states.
Dynamic format strings can leak confidential classifications,
colors for at-risk accounts, icons for blocked vendors,
suffixes that imply threshold crossings.
If a user can only see a subset of rows by RLS,
but the visual signals depend on totals
that include hidden rows,
you've turned visuals into a disclosure device.
The rule is blunt.
If a label would hide or restrict the underlying data,
the semantic layer may not represent that state indirectly.
Either compute a safe, labeled derivative upstream
or it does not render.
Prohibit cross domain joins that materialize identity leakage
paths, DAX patterns that treat as one domain into another
or that create virtual relationships across tables
with different sensitivity or identity scopes,
turn a report into a join engine, your control plane,
didn't authorize.
Even if each table is individually safe,
their intersection might not be.
If the join is legitimate, it belongs in the data plane
governed by labels, lineage and DLP,
where entra guards the perimeter and purview
can persist classification across the results.
And if you can't get that approval upstream,
the join is not allowed downstream.
Now, how do you enforce illegal in a language
that happily evaluates anything you write?
You don't rely on human review.
You fail builds by design.
You lint for band functions only as a proxy,
all remove filters, cross filter, knowing patterns
matter more than tokens.
You attach policy manifest to libraries,
allowed filters, permitted dimension sensitivity scope
and the identity assumptions each function relies on.
If a measure calls a library outside its declared scope,
the model fails to publish.
If a report references a label table
and includes an illegal comparator,
the pipeline rejects the artifact.
No warnings, no exceptions, closed by default.
This is where the separation of duties becomes operational.
Identity belongs to entra, groups, roles, app
and service principle boundaries.
Classification belongs to purview, labels that veto, not decorate.
Exfiltration control belongs to DLP, blocking exports,
notebook rights, composite model blends
and cross workspace imports when labels say no.
Blast radius belongs to capacity, isolating risk domain
so a mistake does not become an incident.
The semantic model sits last in the chain,
it visualizes approved reality.
It never invents its own, a quick sanity test
to keep your reviews short.
For any candidate measure, ask, does this logic introduce
a perspective the user's identity could not request directly?
Does it encode a business decision
that shifts row existence or meaning?
Does it compare my scope to all scope
across a protected dimension?
If any answer is yes, it's illegal in DAX.
Move the requirement upstream, where intent can be compiled,
labeled and enforced or don't ship it.
If you remember nothing else, remember this.
Analytics happens in DAX.
Authorization does not.
When that distinction holds, your model stops drifting.
When it blurs entropy wins.
Entra as authorization compiler, enforce assumptions at scale.
You cannot fix conditional chaos with friendly DAX.
You have to move the decision to a system
that treats authorization like code.
That system is entra.
Think of it as your authorization compiler.
You write intent once.
Who can act, wear and under which conditions,
and entra builds the graph of identities, roles,
and policies that the rest of fabric must obey.
Same inputs produce the same decisions.
No analyst help at runtime.
No drift.
Here's the uncomfortable truth.
If you don't compile intent before the model exists,
you are delegating access to the semantic layer.
It will accept the delegation.
It should not.
Start with non-negotiables.
Identities are not people.
They are actors.
Treat every consumer, human, app, service principal agent
as a first class identity.
Then set boundaries.
App identities only wear automation is necessary.
No shared secrets.
No one app for everything.
Each workload identity has a narrow scope, a revocation
path, and a kill switch.
If you can't disable it without breaking the world,
you build a backhoe, not a tool.
Group membership decides authorization, not workspace
is not names.
Entra groups are the only doorway into sensitive models.
Every group is owned, resertified,
and free of nested everyone recursion.
You grant groups to data sets.
You never grant individuals to reports as a shortcut.
Service principles live under conditional access.
Yes, machines need policies.
Device claims, locations, risk signals applied to workloads,
not just humans.
If the principle can run from anywhere with no friction,
you've built an exfiltration path with an API key.
This is the foundational mistake most teams make.
They try to describe data policy with DAX
when they never described actor policy with Entra.
Once you nail actor boundaries,
you start compiling your assumptions.
Conditional access is where most of your we thought
the network was the boundary beliefs go to die, replace them.
Treat conditional access as the runtime gate
for every path to data.
Block legacy protocols and non-compliant devices.
If a device can't attest, it can't query.
Not warn, not educate, but block.
This is where fail-closed lives in reality.
Risk adaptive decisions.
High-risk user or workload requires step-up MFA
or deny outright for sensitive scopes.
You're not punishing users.
You're preventing helpful automation
from becoming your breach.
App-enforced session controls.
Your builder population is the most dangerous.
Treat build permission like execute arbitrary DAX.
If they can build, they must be on a compliant device
in a trusted network and inside your monitored perimeter.
If they can't meet those conditions, they can't compile queries.
Entitlement management exists to drain
exceptions sprawl from identity.
Every temporary access story is an entropy generator
until you make it a package with an owner, an approver,
a time limit, and an automatic removal.
You encode the business reason in the package.
You don't encode it in a wiki.
Now connect the dots to the semantic layer.
The engine evaluates measures in whatever filter context
the report hands it.
Your job is to ensure only identities you compiled
can hand it any context at all.
Practically that means data sets never
accept build-of-view from outside enumerated
enter groups.
Consuming workspace is project access.
They do not extend it.
A user not in an approved group cannot induce a query,
even if they own the consuming workspace.
Service principles that drive refreshes exports
or embedding do not inherit human access.
They have their own groups, their own conditional access,
and their own approval flows.
Workload identities are not convenience tunnels.
They are bounded executors.
Cross tenant guests are identities.
They get the same packages, conditions, and aspirations.
If you can't express it in entra,
you can't express it with a share link either.
Here's the shortcut nobody teaches.
Your model access review should be primarily an identity review.
If you need a visual to understand who can see what,
when, you already lost.
The answer should be derivedable from group membership,
package grants, and conditional access policy.
If you can't produce that derivation,
the system is probabilistic.
Fix identity, then fix data.
Killswitch mindset.
Every actor must have a rapid testable path to revocation.
Humans leave, vendors change.
Apps misbehave if the only way to stop a runaway principle
is to find the person who knows the password.
You build a time bomb.
Validate Killswitch is quarterly.
Don't trust the toggle.
Press it.
The reason this works is boring, determinism.
Authorization compiled in entra produces
the same answer no matter how many reports, measures, or workspaces
try to reinterpret it.
You centralize who and underwater risk.
Pervue handles what?
DLP handles how it leaves.
And fabric consumes under those constraints.
You've inverted the entropy flow.
One micro story.
A shared customer profitability model
served finance and product.
Before entra hardening, two app registrations existed,
one for refresh, one for monthly export.
Both used broad permissions and ran from anywhere.
We replaced them with workload identities
scoped to one data set each, guarded by conditional access,
trusted network and compliant workload,
assigned via access packages with quarterly expiration
and backed by a Killswitch runbook.
When a vendor integration misfired
and started pulling confidential segments at 2am,
the Killswitch ended it in 30 seconds.
No debate, no slack war room.
Authority had been compiled already.
Identity sets the perimeter.
Next, you make decisions vetoable.
Pervue turns classification into a control, not a caption.
Pervue as veto, not decoration.
Identity compiles who and under what risk.
Now you need a system that says what the data is
and has the authority to say no.
That system is pervue.
Treat it as a veto engine, not a catalog.
If labels can't block their stickers,
if classification can't break a pipeline, it's theater.
Start with the uncomfortable truth.
Sensitivity labels have to be persistent, portable and punitive.
Persistent means the label survives hops.
Lake house to warehouse, warehouse to semantic model,
model to export.
Portable means tools read it the same way.
SQL endpoint, Spark, Power BI, notebooks.
Punitive means the label doesn't just describe a state,
it enforces it.
If highly confidential can be exported to CSV
because a user clicked really hard,
you don't have governance, you have captions.
Here's the practical stance.
Labels define the what in your architecture.
They are the contract that says this asset may not be reused
outside these constraints.
You bind that contract to actions.
In fabric terms, the enforcement points are everywhere.
Content leaves a controlled boundary.
Exports from reports, downloads from the service.
Notebook writes to folders, cross workspace imports,
composite model blends, data flow outputs.
If per view can't veto those edges based on label,
you've designed for drift.
Auto labeling is not a convenience feature, it's a backstop.
Classification has to meet velocity where it lives.
Parkes in one lake,
SQL tables in the warehouse, semantic model artifacts.
When patents match or lineage proves sensitive origin,
labels apply automatically.
But the important part isn't the automation.
It's what happens next.
The label must make specific operations impossible,
not unadvised, impossible.
The block is the point.
Propagation matters because hops are where intent dies.
You want label persistence across engines and transformations,
not a best-effort guess.
When a notebook materializes a table from a labeled source,
the result inherits the label.
When a semantic model references a label table,
the model itself accrues an effective classification
that limits publication and sharing.
When a report builds on that model,
the same effective classification follows.
And when someone tries the just-a-quick export,
move DLP reads the label and blocks the exit.
That chain is vetoed by design.
This is where lineage re-enters as evidence, not enforcement.
You use the graph to explain why a label exists
and where it came from.
You do not use the graph to decide
whether the label should have had teeth.
The graph helps the audit.
This model derived from two confidential sources,
therefore its effective classification is confidential,
therefore export and cross-tenant sharing are disallowed.
The block is already in place.
The story comes later.
Let's make it operational.
Define a small set of labels with behavior attached.
Public, internal, confidential, highly confidential.
For each declare allowed destinations and forbidden operations,
public can leave, internal cannot leave the tenant,
confidential cannot leave governed workspaces
and cannot be exported.
Highly confidential cannot be copied,
blended in composite models,
or written by notebooks outside a specific enclave.
Then why are the actions?
Report exports blocked for confidential and above,
paginated, CSV, Excel, PDF, no exceptions.
Notebook writes inheritance required.
If a write strips the label, the operation fails.
If a target path is outside an allowed enclave,
the write fails.
Cross workspace imports,
blocked when the source model's effective classification
exceeds the target workspace's policy.
The connection fails closed.
Composite models.
Blending label sources beyond policy is rejected
by the service at published time.
Not warned.
Rejected.
Data flows and pipelines, outputs inherit labels,
destinations that cannot guarantee persistence
are disallowed by policy.
This clicked for a client the day we turned a catalog
into a firewall.
They had confidential customer data in a lake house,
a certified semantic model,
and a recurring quarterly review
where a team exported a slice to verify a third party forecast.
It had to be Excel.
The label annotated the model.
It didn't veto the export.
A month later, the CSV lived on a vendor drive.
Nothing malicious, just gravity.
We changed nothing about their visuals.
We changed everything about their edges.
The label now blocked export at the report,
forced notebooks to inherit classification on write,
and required a governed enclave for any analytical data
product that touched that domain.
The next quarter, they didn't export.
They created a derived label table in the enclave
with a safe aggregation upstream,
then granted the vendor a reviewed package
to query their table through a supervised endpoint.
Same business outcome.
Zero leakage path.
Propagation also has to cover clever channels.
Dynamic format strings and SVGs can encode sensitive state.
If the underlying data is labeled,
the semantic layer must not be allowed
to render indirect signals that imply hidden categories.
Either compute a safe derivative upstream
and label that or suppress the signal.
Yes, that means some visuals get less flashy.
It also means your labels have meaning.
And here's the pattern most people miss.
Classification must block reuse, not just access.
A model labeled confidential shouldn't
be promotable to a golden share data set
if it's policy for Bitz Cross workspace reach.
The published action itself should fail.
If a label can't stop a model from existing
in a place where your identity guarantees don't hold,
it's decoration.
Type her view to DLP so how data leaves or persists
is enforced at the edges.
Type her view to enter so who matters when labels decide?
Then make it boring.
Fewer labels, clear behaviors, tested quarterly,
attempt the prohibited operation, expect failure.
If you see a prompt you built a suggestion,
if you see a warning you built a hope,
governance is neither, governance is a veto.
DLP guardrails at fabric power BI boundaries.
Identity compiles who and labels define what.
Now you need breaks at the edges.
Data loss prevention is where how data leaves or persists
stops being aspirational and becomes enforced in motion.
If DLP is advisory your system will drift.
If DLP vetoes, exfiltration attempts turn into dead ends,
not lessons learned.
Start where the leaks actually happen.
Uploads, exports, notebooks, composite models,
and shared data sets.
These are not feature lists.
They're escape routes.
You close them by wiring DLP to the exact operations
that move data across planes, then making the block
the default.
Uploads first.
Treat every inbound file, parquet, or CSV
as an untrusted carry on.
DLP scams on arrival into one lake folders and lake house tables,
ties detections to purview labels, and assigns effective policy.
If a file contains patterns that trigger, confidential,
or higher, it cannot land in a workspace
that lacks a matching policy boundary.
The import fails closed.
Not a banner, a refusal.
This prevents though, will clean it later pathway
that never gets cleaned.
Exports are the classic bleed.
You don't educate here.
You ban for protected classes.
Reports, CSV, Excel, PDF, paginated exports,
blocked when the effective classification
is confidential or above, downloads from the service,
blocked.
Analyze in Excel.
Blocked unless the label and group scope, match, and allow list.
If a business outcome requires a downstream handoff,
you create an upstream label derivative
in a governed enclave and ground supervise time-bound access
to that derivative.
The report never becomes a file.
Notebooks are powerful and dangerous
because they are programmable exits.
DLP wraps them at right.
Two rules.
Inheritance required and destination constrained.
Any right that drops a label fails.
Any attempt to write labeled output to a path
outside an approved enclave fails.
Spark, pandas, Escal, you don't care about the language.
You care that the result remains inside the boundary
with the same teeth it had before the code ran.
Couple this with conditional access.
So only compliant devices and trusted locations
can even open notebooks touching protected domains.
Composite models and shared datasets
present blended exits.
DLP must inspect the published path.
If a new composite attempts to mix a labeled source
that forbids blending with another source,
local import, external direct query,
or a different workspaces model, the published fails.
If a consuming workspace points at a shared dataset
whose effective classification exceeds
that workspaces allowed policy, the connection fails.
This is not a style opinion about model architecture.
It is a boundary rule.
You cannot create an ungoverned join
by sneaking it through a convenience feature.
Adaptive responses matter because velocity fights you.
You start in monitor for net new detections
to learn blast radius.
Then you warn for low sensitivity violations
to build muscle memory.
But you block early for protected domains.
When labels say confidential or higher,
you don't wait for culture.
You enforce culture.
Quarantine is your friend.
If an upload hits a high risk pattern
or a notebook write targets an untrusted path,
you shunt the artifact into a restricted workspace
where only stewards can recover it.
Education happens after containment, not instead of it.
Genii introduces exfiltration by chat.
Just pays the road to test the prompt.
DLP meets it at the browser and the tenant.
Block posting sensitive clipboard data
to unapproved AI domains and treat any fabric connector
to generative services as an egress channel subject
to labels and conditional access.
If the payload carries a protected classification,
the call fails.
If the session isn't compliant, the call fails.
Silence, not guidance.
Outcome orientation keeps you honest.
The goal is simple, models cannot outlive their security
intent.
If an artifact's label forbids export,
no feature produces a file.
If blending would dissolve a boundary,
no publish creates the composite.
If a notebook would synthesize a side table,
it writes only into the unclave under the same label.
Or not at all.
DLP is the mechanism that makes those sentences true in motion.
The uncomfortable truth, without DLP guardrails,
you're depending on human restraint
at precisely the moment's humans optimized for convenience.
With DLP, you shift the burden from memory to mechanics,
intent survives contact with deadlines.
Capacity isolation is containment, not tuning.
You've wired identity, labels, and DLP.
Good, now assume something still slips.
It will.
At that moment, performance knobs won't save you.
Boundaries will.
Capacity is not a speed slider.
It is a containment line, treated as a governance boundary
first, attuning parameter second.
Here's the failure pattern, a shared premium capacity host's
finance HR and product analytics, because it's convenient
and has headroom.
A rushed exception lands a prohibited comparator
in products workspace.
It ships.
Hours later, finance escalates in anomaly.
A vendor saw an aggregated trend that only
exists when products help her measure normalizes
against an unscoped total.
Nothing broke.
The breach was inference.
Incident response now spans every workspace
on that capacity, every app, every shared data set,
and every service principle with build.
You didn't just have a logic error.
You had an unbounded blast radius.
The thing most teams miss is simple.
Capacity's carry tendency semantics,
whether you acknowledge them or not.
CPU, memory, cues, cache, and background jobs
are shared surfaces.
So our administrators, service principles, and pipelines.
When you co-locate risk domains on the same capacity,
you fuse their fate.
A mistake in one becomes noise in another.
A kill switch for one becomes collateral damage for all.
Investigations wander across unrelated teams
because the telemetry isn't scoped to a fault domain
you can quarantine.
This clicked for me during a containment drill.
We simulated a DLP block bypass via a misscoped notebook
right.
The right happened in a mixed capacity
to freeze the path operations throttled the capacity.
That paused HR refreshes, killed marketing, export job,
and delayed finances close.
We stopped the leak by stopping the business.
That isn't resilience.
That's shared fragility.
The deterministic stance is blunt,
segregate by risk domain, not by department org chart,
and not by utilization graph.
Finance sits alone, HR sits alone,
regulated products sit alone, vendor facing sandboxes,
sit in a sacrificial capacity with aggressive policies
and easy kill switches.
Low risk self-service can share, but never
with anything that would trigger a regulatory disclosure
if leaked.
You are building fire compartments, not a bigger living room.
How do you operationalize capacity as containment
without turning into procurement theater?
Three rules.
Boundary first, efficiency second, start with a domain map.
Which data classes and identities must never cohabitate,
assign each to a dedicated capacity, even small excuse
if needed.
Then right size, you can always scale up.
You cannot retroactively isolate a blast radius.
No implicit cross-capacity trust.
If a shared data set in capacity A is consumed
by a report in capacity B, treat that as cross-boundary access,
enforce the same entra-groups, labels, and DLP checks
you'd require across tenants.
If the publishing workflow can't prove enforcement,
the connection fails.
Throttling as policy signal, not a performance bandaid.
When a team requests consolidation to save money,
deny if it erodes isolation.
When a capacity approaches limits,
scale within the domain or effect workloads
do not merge domains to balance load.
Throttling and queue limits are controls
that keep failure local, not levers to hide governance dead.
A micro story.
A healthcare client ran clinical analytics and marketing
dashboards on 1F64 because utilization was low.
A contractor's automation in marketing attempted
to export a model labeled highly confidential via a composite
blend.
DLP blocked the publish, but the automation
hammered retreats for an hour.
Capacity, memory pressure spiked, and clinical refreshes
started failing.
No data left the tenant, but operations
declared a severity one because clinicians lost dashboards
mid-round, we split capacities.
Clinical on a dedicated DLP hardened F64, marketing and self-service
moved to an F32 with stricter conditional access
and a short-killed switch runbook.
The next time automation misbehaved,
we killed marketing's capacity in 30 seconds.
Clinical state green.
The incident report was one page, not a novel.
Here's the shortcut, nobody teaches.
Capacity isolation is cheaper than incident response.
You trade a modest baseline cost for predictable containment,
faster investigations and fewer late night bridge calls.
You also gain clean telemetry, capacity scope logs, query
traces, and DLP events that map to a single domain owner.
That's how you answer who could see what when,
without spelanking across unrelated workspaces.
You are not tuning.
You are drawing lines that code, people, and emergencies
cannot casually cross.
When identity labels and DLP fail to catch an edge case,
and they will, capacity isolation,
make sure the blast is loud, local, and short.
That's the point.
The deterministic data governance playbook.
You don't fix conditional chaos with more guidance.
You replace ambiguity with structures that can't drift.
This playbook isn't a checklist.
It's a stance.
Identity compiles intent, labels veto, DLP enforces,
capacity contains, DAX visualizes only what those layers
already decided.
That's the operating model.
Principles first.
Four of them.
Identity first.
Label enforced.
DLP blocked.
Capacity contained.
Identity first means every actor is explicit and scoped.
Humans, apps, service principles, agents,
guarded by conditional access and kill switches.
Label enforced means purview classifications
are portable and punitive, not decorative.
DLP block means, exfiltration paths
fail closed by default.
Export, notebooks, cross workspace imports, composite blends.
Capacity contained means wrist domains never cohabitate.
Now draw the red lines.
Illegal index table.
Decisions that must fail closed.
Any measure that alters visibility removes
filters on protected domains.
Compare scope to unscoped values,
re-write keys or encode sensitive state
with format strings or SVG is an authorization decision.
That logic is illegal in the semantic layer.
Move it upstream or reject the build.
This simplifies review from is this safe?
To does this pattern exist?
The build pipeline answers.
Not the reviewer.
Next map where logic lives.
Upstream owns business definitions, keys, eligibility,
global totals, and any benchmark
that crosses identity boundaries.
They are computed where Entra has already decided
who may query them and where labels can veto reuse.
The semantic model consumes governed artifacts,
shapes, visuals, and expresses analytics
that never change who can see what.
Visuals tell a story.
They don't negotiate access.
If you need a comparator, you request an upstream,
labeled derivative with the same teeth as its inputs.
If you can't get it, you don't publish the story.
You need cadence, exceptions expire by default.
Access packages in Entra come with time limits
and recertifications.
Shared dataset groups re-certify quarterly.
Service principles rotate on a schedule
and validate kill switches in drills.
Libraries ship with policy manifests,
allowed filters, sensitivity scope, identity assumptions,
and prohibited functions.
If a measure violates the manifest publication fails,
this isn't linting.
This is a compiler error for governance.
Libraries require policy.
A helper measure without a manifest is an accelerant.
A reusable function with declared assumptions
becomes safe plumbing.
Your manifest answers four questions.
Which dimensions may this logic touch?
Which labels are compatible?
Which identity groups may use it?
What happens if a caller supplies an illegal filter?
The only acceptable answer to the last one is it fails.
Not warns, not logs, it fails.
You also need an audit posture that doesn't depend on heroics.
Who could see what when?
Must be derivable from Entra group membership,
conditional access logs, label policy,
DLP actions and capacity boundaries.
Lineage helps tell the story.
It never substitutes for the proof.
Proof that a user, not in an approved group,
cannot induce a query.
Proof that a label blocks export and cross workspace import.
Proof that a composite blend is rejected
when classifications conflict.
Test quarterly.
Press the kill switch.
Let's convert the five failures into repeatable findings.
RLS bypass via measures, audit for comparators crossing,
protected dimensions.
Banal remove filters or all except over identity scope tables,
require upstream benchmarks with labels,
finding phrased as, measure permits visibility altering
comparator, publication blocked,
semantic model drift via calculated tables,
scan for calculated artifacts encoding business definitions
or cross label joins, disallow in pipeline.
Finding calculated table redefines governed logic,
move upstream or reject, lineage theater, test vetoes at edges,
attempt export, notebook write, cross workspace import,
and composite blend with protected labels.
Findings are binary, blocked as designed
or veto missing policy gap, shared data set erosion,
enumerate principles through Entra, deny build view
outside approved groups, and prove consuming workspaces
cannot extend authorization.
Finding reach through detected connection
fails until groups align.
Tax exceptions, brawl, index measures by name, gravity, edge,
net, normalized, scope mismatch, and classification
distortion, require manifests, reject without one,
finding reusable logic, lags, manifest, illegal category.
Make the reviewers job mechanical.
Pipelines enforce manifests and illegal index rules.
Entra packages expire, purview labels block,
DLP closes exits, capacity isolates.
Reviewers confirm structure exists, they don't arbitrate taste.
A micro routine you can run tomorrow, pick one high risk model,
attach labels to inputs if missing.
Why a DLP on exports and notebook writes,
move one cross boundary benchmark upstream and label it,
replace one illegal comparator with that upstream artifact.
Restrict data set access to enumerated groups,
then intentionally attempt the prohibited actions,
export a labeled report, publish a composite blend,
connect from an unapproved workspace,
and run a notebook right to an untrusted path.
Expect four failures.
If any path you didn't enforce, you documented.
The playbooks pay off is boring predictability.
Once identity compiles labels, veto,
DLP enforcers and capacity contains
DAX stops being where governance goes to die.
It becomes what it should have been,
a language for analytics riding on top of intent
that was already decided.
That's not stricter, that's safer,
and radically simpler to live with.
Field assessment, convert failures to findings.
You don't fix this with training,
you fix it by turning vague concerns
into machine checkable findings.
Field assessment is not a workshop.
It's a hostile audit you run against your own estate
with the presumption of drift.
The output isn't advised.
It's a list of blocks, refactors and revocations.
Start with RLS bypass tests,
build two synthetic identities in Entra,
one fully entitled to a protected dimension,
one explicitly excluded, assign them to a test workspace bound
to a copy of the target model,
then within the model, seed a battery of inference probes,
measures that try the known bypasses,
scoped versus unscoped comparators on protected dimensions,
remove filters and all on identity scoped tables,
totals that invert the filter context with calculate,
format strings and SVG icons that flip based on hidden categories,
execute the same visuals as both identities.
If any delta appears between scoped and unscoped probes
that shouldn't exist, you have an inference path.
The finding is phrased as visibility altering comparator
detected, measure publication must be blocked
and upstream benchmark required.
No discussion of intent, you document the pattern
and attach the remediation.
Now scan for drift, calculated artifacts that fork truth.
You aren't hunting for clever decks, your classifying risk,
enumerate calculated tables and columns.
For each ask three questions automatically,
does it reference multiple domains with mixed labels?
Does it reshape keys or join paths that should exist upstream?
Does any downstream measure rely on it
to scope visibility or eligibility?
If any answer is yes, market is illegal and model logic.
Your pipeline should be able to fail builds
when these categories are present.
The finding reads, calculated artifact
and codes governed business logic, relocate upstream
or reject publication.
You're not punishing speed, you're removing
the authoring surface that makes governance optional.
Stress the lineage narrative with enforcement reality.
Pick one model labeled confidential or higher.
Attempt the prohibited actions at every edge.
Export CSV from a report, download the PBX if allowed,
write a labeled slice from a notebook to an unapproved folder.
Import the labeled artifact into a different workspace
via composite model.
For each expect failure, if a warning appears,
you record veto missing policy gap at edge X.
The action item isn't to update a wiki,
it's to wire purview and DLP so the operation is impossible.
After remediation, rerun the same actions and expect silence.
This converts pretty arrows into evidence
that blocks existed when it mattered.
Interrogate shared dataset reach through.
Build a matrix for each shared model.
Data set enter groups, RLS roles, app audiences,
build permissions, service principles
and all consuming workspaces.
Then try to induce a query from a principle present only
in a consuming workspace, not in the dataset groups.
If a query reaches the model, you've dissolved the boundary,
capture, cross workspace reach through detected,
require alignment to enumerated groups or fail connection.
Next, hunt for consuming reports that introduce scoped
versus all patterns against the shared model.
Flag them as illegal comparators and require upstream benchmarks
or removal.
This is not about naming the guilty.
It's about closing the access plane
that consistency quietly opened.
Inventory DAX exceptions sprawl, pass measure names
in bodies.
Name gravity catches the accelerants, adjusted, net, normalized
helper, global.
Scope analysis finds branches that compare scoped values
to remove filters over protected dimensions.
Classification checks detect dynamic strings or SVGs
that encode sensitive states, tag these as authorization
adjacent, then require policy manifests
for any reusable measure library.
The manifest states allow dimensions, compatible labels,
identity assumptions, and the failure mode
if assumptions aren't met.
If a published model references a library without a manifest,
the build fails.
Findings read reusable logic, lacks policy manifest,
publication rejected.
Your assessment needs identity in the loop.
Pull enter group membership and entitlement management
grants for every data set.
Verify recertification dates, ownership,
and nested group presence.
Kill any individual grants or public links to models.
Confirm conditional access policies
apply to build up populations and workload identities,
not just users.
Then press kill switches in a drill,
revoke a workload identity midrun,
and confirm queries die were expected without collateral damage
outside the intended capacity.
Findings here are binary.
Kills which validated or revocation path unclear, design omission.
Capacity is part of the test.
Move one high risk workspace to a dedicated capacity
temporarily.
Re-run export blocks, composite publish rejections,
and reach through attempts.
Confirm failures occur within the capacity boundary
and do not ripple.
Then intentionally cause a DLP quarantine
by uploading a labeled file into the wrong workspace.
The capacity hosting that workspace should
localize the incident.
If you can't keep the blast local,
you've treated capacity like a speed slider.
The finding reads containment insufficient,
segregate risk domains, close with the cadence.
Every finding maps to one or four levers.
Entra groups and packages,
purview labels and propagation DLP edge blocks capacity isolation.
You assign owners per lever and set deadlines.
Then you rerun the exact same hostile tests quarterly.
No new probes, no changing rules, same inputs,
same expected failures.
That's how you know the system stayed
deterministic long after the training slides expired.
Why training fails without architecture?
Most teams respond to entropy with training.
Lunch and learns, brown bags on better daxom in policy pages.
It feels responsible.
It is not.
You're trying to teach humans to do what the system refuses to enforce.
Memories the control plane.
That fails on schedule.
Start with cognition.
Human reasoning does not scale.
Under pressure, people optimize for delivery, not doctrine.
That's predictable, not malicious.
Libraries like DAXLIP exist because repetition
under deadline forces shortcuts into artifacts.
You did not improve practice.
You created accelerants without a veto,
those accelerants spread.
Best practice relies on recall at the worst possible time,
Friday night and of quarter.
Someone needs a comparator.
They remember a talk about all selected,
but not the part about protected dimensions.
They ship the version they can compile.
Training does not intercept that moment.
Controls do.
The system either evaluates identity
and labels before the measure exists
or it accepts whatever the author can imagine.
Tooling without veto is theater.
Dashboards that surface lineage,
stewards, endorsements, useful later.
A DAX formatter, a linter, a style guide, nice, advisory.
None of that converts intent into a failure state
the engine respects.
Culture talks.
Code runs.
When they disagree, code wins.
The reason is architectural, not motivational.
You're operating a distributed decision engine.
Measures reports notebooks, pipelines,
each a place where intent becomes action.
The only way to hold the line is to remove decision rights
from places that cannot express identity or classification
and place them where they can.
That means entra compiles actors,
purview labels, veto, DLP blocks, edges, capacity contains.
Training amplifies that design.
It cannot replace it.
This clicked for me during a remediation sprint
after a lessons learned week.
The team had just completed a DAX workshop.
Gorgeous slides, fresh notebooks.
Within two weeks, the same inference pattern
reappeared with a different function set.
The author knew the guidance.
They chose a different path because the build allowed it.
We didn't change the deck.
We changed the pipeline.
Illegal patterns failed publication.
The behavior ended without a single meeting.
Now here's where most people mess up.
They assume if developers just understood context transition,
calculate semantics, or RLS subtleties,
exceptions would vanish.
Knowledge is necessary.
It is not sufficient.
Complexity guarantees novelty.
Someone will invent a new bypass.
You cannot enumerate cleverness.
You can forbid classes of logic
and move the need upstream
where identity already decided who may see the result.
Deterministic governance converts advice
into machine enforced rules.
Don't export confidential becomes export operation fails.
Don't compare, scoped to unscoped across region
becomes publication rejected.
Don't let contractors execute arbitrary DAX becomes
conditional access, denies, build outside compliant posture.
The outcome is not dependent on memory.
The outcome is compiled.
Education still matters.
But only as user interface to the structure.
Teach what the system will allow, what it will block, and why.
Show the kill switches, the labels behaviors,
the edges that veto, make success easy and error
impossible.
That is the opposite of blame.
It is the design that keeps good people from having to be perfect.
A micro story.
A finance team spends six months socializing
and no exports policy.
Compliance signed it.
Everyone agreed.
Quarter close arrived.
An analyst exported anyway.
Not defiance.
Deadline.
We replace the poster with a block tied to label.
The next close nobody exported because nobody could.
The training stopped being a plea.
It became documentation for a system that already behaved.
You are not under investing in people.
You are overestimating what people can hold in their heads
when the clock is loud.
Make the architecture carry the weight.
Then teach the architecture objections.
Reframed the system laws.
We trust our analysts.
The system did not ask for their intentions.
It asked for code.
In a distributed decision engine, intent without enforcement is noise.
Law.
People optimize for delivery under pressure.
Therefore, any control that relies on memory is an entropy generator.
Encode trust as scope,
Entra groups, conditional access, expiring packages.
Everything else is storytelling you cannot audit.
Our lineage is complete.
Lineage is a map of movement.
It is not a break.
You can draw the arrows after the fact and still have no way to prove
that a labeled asset could not be exported, blended or reinterpreted by a comparator.
Law.
Lineage is evidence.
Not assurance.
Therefore, enforcement must live at the edges.
DLP blocks tied to labels, published time vetoes, and failed connections across boundaries.
If a diagram is the control, there is no control.
Shared data sets save time.
They do and they also create an access plane.
Time saved does not negate identity scope.
Law.
Convenience is not an authorization model.
Therefore, bill permission equals may execute arbitrary DAX.
And consuming workspace's project authorization never extended.
If any principle outside enumerated groups can induce a query, the connection fails.
Efficiency follows authority.
Not the other way around.
We tag everything.
Labels without veto are stickers.
Attack that cannot deny an export or killer composite is theater.
Law.
Classification is a gate.
Not a caption.
Law.
Dissallowed actions at every edge.
Exports.
Notebook rights.
Cross workspace imports.
Composite blends.
If a label can't stop the model from existing where it shouldn't, it does nothing.
Performance first.
Speed is irrelevant when errors propagate at line rate.
A fast breach is still a breach.
Law.
Capacity is containment.
Not tuning.
Therefore, segregation by risk domain.
Outranks.
Consolidation savings.
Throttling is a policy signal.
Not a comfort knob.
If isolation is sacrificed to utilization, investigations will be slow, noisy and inconclusive.
We'll train the team.
Training is necessary to explain the structure.
It is not the structure.
Law.
Advice cannot substitute for a veto.
Therefore illegal index patterns fail build period.
Developers can learn why.
They cannot override the compiler.
If the pipeline permits a known bypass, your curriculum becomes an accelerant.
RLS already protects us.
RLS constrains row visibility.
It does not constrain math.
A measure comparing scope to unscoped values can leak aggregate truth without ever showing a row.
Law, analytics and authorization are different categories.
Therefore, comparators that cross identity scoped dimensions are illegal index and must be
computed upstream under identity and labels.
If it needs global context, it does not belong in the semantic layer.
Exceptions are rare.
They are immortal.
If a temporary measure becomes a reference, then a standard, then folklore.
Law.
Exceptions do not retire themselves.
Therefore, libraries require manifests.
Measures with name, gravity are treated as policy and any authorization adjacent logic is banned, not reviewed.
If a rule depends on someone remembering to clean up, it will accumulate.
Our vendor needs build access.
Vendors are identities.
Workload identities are actors.
Law.
Every actor has a kill switch.
Therefore, service principles get dedicated groups, conditional access, time bound packages and a tested revocation path.
If you cannot stop an automation without collateral damage, you build an ex-filtration tunnel with a marketing name.
We can't block exports, the business needs excel.
The business needs outcomes not file formats.
Law.
Governance is outcome preserving and channel restricting.
Therefore, sensitive outcomes are produced as labeled derivatives in governed enclaves and accessed through supervised endpoints.
If a requirement collapses to we need CSV, it is a process smell, not a control argument.
Our environment is too complex for strict rules.
Complexity is precisely why you need deterministic rules.
Law.
Drift grows with surface area.
Therefore, you remove decision rights from surfaces that cannot express identity or classification and centralize them in entra, purview, DLP and capacity boundaries.
If your answer to scale is more discretion, you are manufacturing variants.
Blocking will slow us down. Early. It will make you faster later.
Law.
Blocks replace late incident response with early design decisions.
Therefore, published time rejections and edge vetoes move pain to planning, not production.
If your calendar prefers firefighting to architecture, you will keep paying the surge pricing.
Prove this matters.
Audit asks, who could see what when?
Law.
Proveability outranks plausibility.
Therefore, access is derivable from group membership, conditional access, label policy, DLP actions and capacity boundaries, without spelunking lineage diagrams.
If you cannot derive the answer from structure, you do not have governance.
You have faith. Operating rules you can enforce tomorrow.
Band classes of measures that alter visibility or classification.
Make it mechanical, a published time rule that rejects patterns with all removed filters, overprotected dimensions,
scoped verse, unscoped comparators, business key rewrites or dynamic format strings, encoding sensitive state.
The pipeline fails the artifact. You don't debate intent, you remove the surface.
Require entrust scoped identities for every consumer and agent.
No individual grants, no anonymous links.
Data sets accept build and view only from enumerated intragroups.
Service principles get dedicated groups, conditional access, time bound access packages and kills which runbooks tested quarterly.
Consuming workspace is project authorization, they never extend it.
Make per view labels a prerequisite for model publication.
Inputs without labels are blocked at ingestion.
Effective classification propagates to semantic models and reports, with attached behaviors,
confidential and above cannot be exported, blended in composites, or imported cross workspace.
Label inheritance is enforced, writes that drop labels fail.
Turn DLP to enforce at edges, no silent paths, wire blocks for report exports, service downloads,
notebook writes to unapproved paths, composite model publishers that cross classifications
and cross workspace imports violating policy.
Start in monitor for low risk, one briefly, then block decisively for protected domains.
Quarantine violations into steward only enclaves.
Isolate capacities by risk domain deny consolidation that erodes isolation.
Finance, HR, regulated product analytics and vendor sandboxes each get their own capacity.
Treat cross capacity data set consumption as a boundary crossing with the same entra label
and DLP checks as cross tenant, throttling is a policy signal, not a comfort knob,
attached policy manifests to reusable libraries, declare allowed filters,
compatible labels, identity assumptions and the failure mode reject.
Pipelines verify manifest adherence, violations hold publication,
measures with name gravity require manifests by default, validate kill switches,
pick one workload identity per capacity and revoke it mid run.
Confirm queries die locally without collateral blast, you'll feel slower week one,
you'll be faster forever after.
The takeaway is simple, analytics happens in DAX, authorization does not,
and only deterministic governance keeps that boundary intact.
If you want the manifest illegal in DAX rules and a step-by-step hostile assessment,
grab the playbook linked below.
Subscribe for the deep dive on wiring entrapackages, purview vetoes and DLP edge blocks,
then run the four failure tests this week.