Stackable Docs Hub

Stackable

Stackable

Your catalog knows the answer. Nobody asks it.

Based on my talk at data2day 2026 in Cologne: why data catalogs mostly sit on the sidelines, and what happens when access control starts asking them for information.

Part 1 of 2. Part 2 covers what happened after the talk: a car ride, a fork of the demo with Entropy Data, and a different answer to the question of where access rules should live.

Your catalog marks this column as PII. Trino reads it anyway.

That’s how I opened my data2day talk, and I suspect most of the room had been there: someone, quite possibly a data steward with better things to do, carefully tagged customer_name as sensitive in the metadata catalog. The tag is correct. It looks great in the UI. And it has exactly zero influence on who gets to read the column.

This post is about closing that gap, and about what we built in the Stackable Data Platform (SDP) to do it.

Two catalogs, two blind spots

„Catalog“ is one of those words that means something different to everyone in the room. For this story, two kinds matter.

The technical catalog (the Apache Hive Metastore, or these days an Iceberg REST catalog like Lakekeeper, Apache Polaris or Databricks Unity Catalog) sits right in the access path. Every query asks it where the table lives and which snapshot is current. It knows everything about files and nothing about meaning.

The metadata catalog (OpenMetadata, DataHub and friends) knows what the data means: who owns it, how it’s classified, where it came from. It sits next to the access path, beautifully documented, but mostly it gets no say in who accesses what.

So one catalog gets asked all the time and has no clue, and the other one has all the clues and doesn’t get asked.

Why that’s a problem

The usual fix is to copy the knowledge over. An engineer writes the sensitive columns into the access policy, by name. It works for a handful of tables. Then the next PII column shows up, and it’s another policy change, another review, another deploy. The fact that a column is sensitive now lives in two places, and those two places drift apart.

The second problem is sneakier: metadata rots because nothing depends on it. A catalog entry can say „Owner: Team CRM“ long after Team CRM was reorganised out of existence, and „Classification: internal“ long after someone added customer addresses. Nothing breaks when the catalog is wrong, so nobody notices and nobody fixes it.

Both problems have the same root. The catalog is passive. It describes and documents, but it doesn’t take part in any decision.

Let access control ask the catalog

In theory, the fix is simple: when someone queries a table, the access control asks the catalog about that table and decides based on the answer.

In SDP, access decisions are made by the Open Policy Agent (OPA). Trino asks OPA before every query: may this user read this table, and should any columns be masked? OPA already has a helper for the „who“ part, the User Info Fetcher (UIF), which looks up the user’s groups in the identity provider. We built its counterpart for the „what“ part: the Resource Info Fetcher (RIF). It runs next to OPA and looks the table up in the metadata catalog you already have, returning owners and tags (per table and per column).

The Resource Info Fetcher will be released in Stackable’s 26.11 release and initially support DataHub as a metadata backend. Additional backends will follow shortly, with OpenMetadata being the first contender.

It can be called from within Rego rules in a similar fashion to the User Info Fetcher, but to retrieve data about resources such as tables or topics instead.

This lets you author policies not around resource names, but around table attributes like „sensitive“, „public“, „eu“ or „us“.

So what used to be this:

allow if {
    input.table.name in {"customers", "salaries"}
    "finance" in input.user.groups
}

now becomes this:

allow if {
    "sensitive" in input.table.tags
    "finance" in input.user.groups
}

It doesn’t look vastly different at first glance, but the details matter: the tag rule applies to anything that is tagged in your metadata catalog, so you won’t have to change it often. Compare that to a rule full of table names, which you’ll probably be editing all the time.

And you can now also enforce that metadata is entered before a table can be read at all:

# No owner in the catalog? No access.
deny if count(info.owners) == 0

„No owner, no access“ also fixes the rotting-metadata problem from above in a slightly brutal way: the moment the owner field matters, people start filling it in.

What it looks like

My data2day talk came with a live demo that showed this in practice.

I ran a SQL query that read data from an untagged table in Trino. It succeeded.

I then played data steward and tagged customer_name as PII in OpenMetadata. About ten seconds later (that’s the cache we configured), the same query that had shown names a moment earlier returned this:

Stackable Cockpit, the web UI of our platform, as demo-user: customer_name is MASKED

The result: no policy change, no review, no deploy. A user in the PII group still sees clear text, and removing the tag unmasks the column just as quickly. The people who know the data decide, in the tool they already use.

What it costs

None of this is without consequence, and as so often, there are no right or wrong answers, it all depends on your use case:

  • The catalog joins the critical path. If it’s down, access stops (or opens up, depending on how you build it; our demo stays closed).
  • Freshness vs. speed. Without a cache, every query waits for the catalog. With one, changes take a few seconds to arrive. Pick the number based on how quickly a revoked classification has to bite.
  • Tags become permissions. Whoever can classify data can now grant or revoke access. Your catalog permissions just became security-relevant, and your catalog audit log quietly turned into an access audit log. In a regulated setting – finance, public sector, healthcare – that cuts both ways: a clean who-could-see-what trail is exactly what auditors ask for, and now you own it.

The last point especially is worth thinking through, because you now potentially have more people able to grant access to data if you’re not careful.

Where this could go

Roadmap: planned, not decided, no date.

The Resource Info Fetcher reads what somebody typed into a catalog. But a data platform also runs the data: it knows which tables exist, where their files sit and who queries them. That lets it see things no single catalog can, like two tables pointing at the same files, one with a policy and one without. We’re working on making that kind of knowledge available in standard formats. It’s meant to sit next to your catalog, which stays where it is.

And we’re not the only ones heading this way. Databricks Unity Catalog offers attribute-based access rules built on tags, and Snowflake offers tag-based masking policies. The shared idea is that classification controls access. What’s different in our case is that it’s open: it’s built on OPA, which SDP uses across its products, and the Resource Info Fetcher is designed for more than one catalog (OpenMetadata, DataHub). And that edge lasts only as long as their approaches stay tied to their own stack: the day they open up to other catalogs and engines, it disappears.

Over to you

I ended the talk with a question, so here it is again:

Should a data platform hold classifications itself, or read yours?

We don’t run comments here (spam, sadly), so if you’ve got an opinion or want to discuss the topic, send it my way: LinkedIn or email.

And if you’ve got an opinion on that, come along to my colleague Lars Francke’s and my tech talk on 2026-11-25: stackable.tech/newcockpit.

In part 2: after the talk, Simon Harrer of Entropy Data hitched a ride with me to the next event and forked the demo on the way: Entropy Data instead of OpenMetadata, and OPA asking Entropy Data whether access is granted.

Comments are closed.