HOW-TO GUIDE17 min read

Superset Row-Level Security for AI-Enabled Customer Portals

A practical guide to applying Superset row-level security to agent-mediated customer analytics, with a worked access test and operational failure checks.

P
The PADISO TeamPublished 17 Jun 2026

Prerequisites

Before changing a Superset deployment, establish where the authorization decision will happen and which identity it will use. This guide focuses on customer-facing analytics where an AI agent helps a signed-in customer explore data. The agent may interpret a request or help select a metric; it must not become a substitute for the access boundary that determines which customer records can be queried.

You will need a Superset environment representative of production, a test account for each access pattern, and a non-production dataset containing records for at least two tenants. You also need a clear record of how the application identifies a customer and how that identity reaches the server-side component that requests analytics. Do not use production customer data to prove isolation.

Prepare a small access matrix before implementation. Include a tenant administrator, a regular customer user, and an application operator if operators have a different view. For each, write down permitted tenant identifiers, permitted datasets, and whether cross-tenant aggregate results are allowed. An empty or ambiguous entry is a design issue, not a reason to grant broader access temporarily.

This guide assumes that the application backend, not a browser-held secret or an unconstrained agent, mediates requests to the analytics system. If customers can query the warehouse directly, Superset’s application-level filtering alone is not a complete boundary. Decide separately what protections exist at the data source and how direct query paths will be restricted.

Important: Superset RLS applies clauses to generated queries for configured datasets and subjects. Validate SQL Lab and API access separately; embedding is not authorization. Superset security documentation

1. Draw the request path before adding an agent

Start with a sequence that identifies the caller at every hop. A typical proposed design is: the customer signs in to your product, the product backend validates that session, the backend derives the tenant identity from trusted application state, and an analytics request is made under a deliberately constrained identity. The agent can help formulate the request, but it should not be the component that chooses or asserts the tenant boundary.

That separation is important because a language model may receive tenant names, account IDs, or other text in a prompt. Such text can be mistaken, manipulated, stale, or simply inconsistent with the authenticated session. Treat the request’s tenant scope as server-controlled context. Treat model-generated metric names, filters, and natural-language summaries as inputs to validate, not as proof of authorization.

The implementation should answer three questions explicitly: who authenticated the customer, which server-side value represents the customer’s tenant, and which layer enforces that tenant restriction when the data query runs? If different teams answer these questions differently, pause implementation and reconcile the design. A hidden dashboard filter or a prompt instruction such as “only show this customer’s data” is not a dependable substitute for an enforced query constraint.

flowchart TD
  accDescr: Workflow stages and decisions: Customer request, Backend validates session, Resolve trusted tenant, Validate metric and filters, Superset query applies RLS, Check result scope, Return scoped answer, Block and investigate. The adjacent text explains the conditions and exceptions.
  accTitle: Superset Row-Level Security for AI-Enabled Customer Portals workflow
    A["Customer request"] --> B["Backend validates session"]
    B --> C["Resolve trusted tenant"]
    C --> D["Validate metric and filters"]
    D --> E["Superset query applies RLS"]
    E --> F["Check result scope"]
    F --> G["Return scoped answer"]
    F -.->|"Mismatch or error"| H["Block and investigate"]

Accessible description: The customer request reaches a backend that validates the session and resolves a trusted tenant. The backend validates the requested metric and filters before Superset applies RLS. Results are checked for scope; a mismatch or error is blocked and investigated instead of being returned.

The diagram describes a design, not an automatic Superset feature. In particular, the final result-scope check is an application-level control you must design and test. If it cannot be implemented reliably for the data shape, do not imply that a generated answer is tenant-safe merely because a dashboard uses RLS.

2. Define the tenant identity and data contract

Choose one canonical tenant key for the analytics data path. In the hypothetical example used below, the key is tenant_id, represented as a stable string such as northwind-042. A display name like “Northwind” is not a safe join key: names can be duplicated, renamed, or typed differently. Keep the canonical key consistent across fact tables, relevant dimensions, and the authorization mapping used by the backend.

Write down the data contract for each dataset the agent may request. For a usage dashboard, the contract might identify usage_events.tenant_id, usage_events.event_date, usage_events.product_area, and usage_events.event_count; it would also say whether each field is filterable, whether any value is sensitive, and what grain a returned row represents. This is not a substitute for RLS. It helps prevent the agent from requesting an unsupported metric or combining fields in a way that yields misleading results.

Check joins carefully. A fact table may carry a tenant key while a shared dimension does not. If a query can traverse from a tenant-scoped fact into a dimension with tenant-specific attributes, confirm that the join cannot reintroduce records belonging to another tenant. Where a relationship is ambiguous, prefer a data model that makes the tenant boundary explicit rather than relying on the agent to choose a safe join.

Define how the application maps its authenticated customer to the canonical tenant key. The mapping should come from trusted server-side identity or application data, not from a free-form prompt, a URL parameter accepted without validation, or a model-produced tool argument. Record what happens when the mapping is missing, disabled, or inconsistent: the request should fail closed, not fall back to a broad scope.

3. Configure the Superset RLS boundary for the intended datasets

List every dataset the customer-facing experience can query, including datasets used indirectly by charts or saved analytics. For each one, establish whether its rows have a usable tenant key and which RLS rule or rules are intended to constrain access. Superset’s security documentation describes the generated-query scope of RLS; use it as the product reference, and verify the behavior for your configuration rather than inferring that one protected chart covers every route.

Avoid treating a dashboard as the security unit. The customer-facing interface may show a single dashboard, but an agent-mediated experience can create requests that do not follow the same chart path. Make an inventory of datasets reachable through the intended interaction and test them individually. If the dataset inventory is unknown, the boundary is not yet testable.

For a straightforward tenant-scoped dataset, define the intended policy in plain language before translating it into the Superset configuration: “A customer request can return rows only for the tenant bound to the authenticated application session.” Compare that sentence with the actual dataset, roles or subjects, and query paths in your deployment. Have a second engineer review the relationship between the intended population and the configured filter.

Do not use an unrestricted internal role as a shortcut for external traffic. If internal operators genuinely need broader analytics, keep that access path distinct from the customer request path and test it as a separate identity. Broad access can be operationally necessary; sharing it with a customer-facing request makes the isolation claim much harder to establish.

Warning: A tenant value supplied by an agent is not trusted identity. The backend must bind the request to the authenticated customer, and a missing or unrecognized binding should stop the query.

4. Put the agent behind a constrained request interface

Give the agent a narrow request contract instead of open-ended authority to construct arbitrary analytics access. A proposed contract could contain a metric identifier, a date interval, and a small set of approved grouping or filter values. For example: metric = active_users, from = 2026-08-01, to = 2026-08-31, and product_area = reporting. The backend should validate those values against its own allowed definitions before sending a query onward.

Keep tenant scope out of model authority. The backend can attach the canonical tenant key after validating the customer session, while the agent supplies only the question-derived metric and optional filters. If the tool interface requires a tenant field, treat it as an assertion to compare with the server-resolved tenant, not as a value to trust. A mismatch should be rejected and recorded for investigation.

Separate request understanding from query execution. The model may turn “How many people used reporting last month?” into a candidate metric and date range. Application code should validate the dates, metric definition, filter values, and tenant binding. Only then should a controlled analytics request proceed. This separation makes it possible to change the model without changing the authorization rule.

Business metric consistency is a related but distinct design problem. If multiple agents, dashboards, or application features need the same definition of “active user,” use a deliberate shared metric contract rather than asking each prompt to recreate it. For a deeper treatment of consistent agent-facing business definitions, see A Semantic Layer for Agents: Keep Business Metrics Consistent. That topic complements tenant authorization; it does not replace it.

5. Validate the embedding and server-side credential path

If the customer experience embeds Superset content, treat embedding configuration and authorization as separate concerns. Superset’s embedding documentation states that the host backend obtains guest tokens, allowed origins and the feature flag must be configured, and service credentials must not be exposed in the browser. Review the embedding documentation for the relevant setup details.

Trace how the browser receives an embedded view and what the host backend uses to request it. Inspect browser-visible network traffic and delivered application assets for secrets that belong only on the server. The browser should not receive a service credential simply because it needs to display analytics. Configure the permitted origin narrowly for the application environments that actually host the experience, then verify the deployed configuration rather than assuming a local setting carried forward.

A valid embedded view does not establish that the signed-in customer is entitled to every result it can display. Test the identity and data scope independently from the visual embed. Include attempts to alter client-side parameters, reuse a session across two test tenants, and request an identifier belonging to the other tenant. The expected behavior is determined by the authorization design, not by whether the dashboard renders successfully.

If the application uses an embedded dashboard and a separate agent query path, test both. A customer who cannot see a chart may still reach another exposed query surface if it is configured separately. Conversely, a constrained agent request does not prove an embedded dashboard is scoped. Keep a route-to-dataset map so the team can identify which control protects each path.

6. Run a worked tenant-isolation test

Use a non-production fixture with deliberately distinguishable records. The following is a hypothetical example, not a report of an executed test. Create two tenants, northwind-042 and redgum-017, and a small usage table with these fields: event_id, tenant_id, event_date, product_area, and event_count. Give Northwind two August records for Reporting with counts 12 and 8; give Redgum a record for the same period and product area with count 91.

Define the test request as: “For August 2026, how many Reporting events were recorded for my account?” Authenticate as a Northwind test customer. The server should resolve the session to northwind-042; the agent can propose the metric and date interval but cannot replace that tenant binding. The expected aggregate for this illustrative fixture is 20, assuming the metric is the sum of event_count and the date interval includes both August records.

Now run the same request while authenticated as the Redgum test customer. The expected illustrative aggregate is 91. Then add a hostile or simply conflicting request that explicitly asks to use northwind-042 while the session is Redgum. The backend should reject or disregard the conflicting tenant argument according to the documented contract; it must not return Northwind’s records to the Redgum session.

The test should cover more than the final number. Inspect the effective query or a suitable server-side trace in a safe test environment and confirm that the tenant constraint applies to the intended dataset. Verify the returned rows or aggregate scope before the model turns the result into prose. If the response only contains a total, the test must still establish that the total was calculated from the expected tenant’s rows, rather than infer correctness from a plausible number.

Add negative cases: an unknown tenant mapping, a missing tenant binding, an invalid metric, a date interval outside the accepted rules, and an agent-supplied tenant that conflicts with the authenticated session. Define the expected result for each before running the tests. For identity or policy failures, the acceptance condition should be no customer data returned. For invalid metric input, the acceptance condition should be a rejected request or a controlled clarification, not a broader fallback query.

Test case Authenticated tenant Requested scope Expected outcome
Baseline A northwind-042 August Reporting total Illustrative total 20; no Redgum rows
Baseline B redgum-017 August Reporting total Illustrative total 91; no Northwind rows
Conflicting tenant redgum-017 Agent asks for northwind-042 Reject or ignore conflict; no Northwind data
Missing mapping Unresolved Any metric No customer data returned
Unsupported metric Either test tenant Unknown metric name Reject or request clarification

The figures are deliberately small so a reviewer can verify them by hand. In a realistic test, add enough rows to exercise joins, null tenant keys, multiple product areas, and the date boundaries used by the application. Keep the fixture deterministic so a later policy change can be compared against the same expected output.

7. Test every relevant query path, not just the happy path

Build a path inventory that includes the embedded view, the agent’s analytics request, any application endpoint that returns chart data, and any analyst or SQL interface accessible to the same user. Superset explicitly calls for separate validation of SQL Lab and API access in relation to RLS; do not assume a successful dashboard test demonstrates those paths are constrained. The security reference is the starting point for that distinction.

For each path, run one allowed request and at least one cross-tenant denial case. Use the same pair of fixture tenants so differences are easy to diagnose. Where a path is not available to customer identities by design, confirm that the access is actually denied rather than relying on a policy document that says it should be unavailable.

Exercise query variations that commonly change data scope: a different date range, a group-by field, a filter with multiple values, and a metric that joins another dataset. The purpose is not to create an unbounded test suite. It is to find out whether the tenant condition remains present when query shape changes. Record both the expected result and the evidence reviewers can inspect, such as a test response, a controlled query trace, or a denial event.

Test pagination and empty-result behavior as well. A result page that is correctly scoped does not prove the next page is scoped if the application reconstructs the query differently. An empty result should remain empty; it should not trigger a fallback request with a broader filter simply to produce a more helpful answer. Treat “no data for this period” as a valid outcome.

8. Make failures visible and recoverable

Plan for ordinary identity and data failures: an account is deactivated, a tenant mapping is delayed after a customer change, a dataset loses its tenant key in a model update, or a query returns a result that fails the application’s scope check. Decide which component stops the request, what the customer sees, and what support staff can inspect without exposing another tenant’s information.

Prefer a clear denial or a neutral retry message over a partially generated answer from an incomplete result. If the query fails after the agent has already drafted a response, discard that draft rather than allowing it to imply a successful lookup. If result validation cannot establish the expected tenant scope, block the result. A timeout or malformed response is not evidence that the data was safe.

Log enough to investigate without unnecessarily copying customer records into logs. A useful event can identify the authenticated application subject, resolved tenant key, requested metric identifier, query path, policy outcome, and a correlation identifier. Decide which of these fields are acceptable in your environment and apply the same care to agent traces as to ordinary application logs. Avoid logging full result rows merely to make troubleshooting convenient.

Use a controlled release sequence for policy changes. First apply the change in a test environment and rerun the fixture cases. Then have a reviewer inspect the changed dataset coverage and negative tests. In production, monitor for policy denials, scope-check failures, and unusual changes in result size. If a failure appears, disable the affected customer-facing query path or revert the change according to your normal release process; do not temporarily widen access to restore a dashboard.

A practical failure timeline helps clarify ownership. At 10:00, a schema change removes tenant_id from a joined view. At 10:05, the next agent request cannot demonstrate tenant scope. The system should stop that response, emit a useful operational event, and direct the user to a neutral error state. The analytics owner investigates the changed dataset; the application owner confirms that no fallback route returned data. This hypothetical timeline is an acceptance design, not a claim about a particular deployment.

9. Review the decision boundary when the product changes

Revisit the access design whenever the product adds a dataset, a new agent tool, a new embedded dashboard, a cross-tenant internal report, or a different customer identity flow. These changes can alter the set of reachable data even if the existing RLS rule itself remains unchanged. Keep the dataset inventory and path map close to the release process so reviewers can see the effect of a new feature.

Be especially cautious with support and operator workflows. A support user may need to inspect a customer’s account with consent or under an internal process, but that is a separate access purpose from the customer’s own session. Define an explicit operator path, test the transition into it, and make sure the customer-facing agent cannot silently inherit it. Do not solve operational convenience by giving every agent request the operator’s broader scope.

If the system needs cross-customer aggregate metrics, decide whether those aggregates are appropriate to expose and which identity and data path can produce them. A summary that contains no direct customer identifier may still reveal sensitive information when a group is small or a filter is narrow. Treat the aggregate use case as its own data contract and test its boundaries rather than assuming that aggregation inherently removes access concerns.

Deployment choices matter to operating the service, but they do not answer the tenant-policy question. If you are implementing the runtime, the Apache Superset Helm Chart: A Production values.yaml discusses a related deployment concern. For a product decision about analytics platforms, Apache Superset vs Metabase: Which Breaks First at Scale addresses a separate comparison; neither replaces testing your specific authorization paths.

10. Use the worksheet as a release gate

Complete this compact worksheet for each customer-facing analytics capability. It is designed to fit into a change review, not to replace detailed architecture documentation. Write concrete names and outcomes; answers such as “handled by the agent” or “secure by default” do not identify an enforceable boundary.

Review item Record before release
Customer identity source Which authenticated application identity is validated?
Canonical tenant key Which stable key is resolved server-side?
Reachable datasets Which datasets can this interaction query directly or indirectly?
RLS coverage Which intended policy constrains each dataset and subject?
Agent authority Which metric and filter values may the agent propose?
Tenant binding How does the backend prevent a prompt or tool argument replacing tenant scope?
Other query paths How were embedding, API, SQL Lab, or other applicable routes checked?
Positive test What result is expected for each fixture tenant?
Negative test Which conflicting or missing identity case proves denial?
Failure response What happens when identity, policy, or result validation is uncertain?
Release evidence Where are the test outcome and reviewer decision recorded?

For a printable summary, copy the worksheet into the change ticket and attach the fixture definition, expected outputs, and concise test evidence. Mark each row complete only when the named behavior has been checked in the relevant environment. If a route is not applicable, state why it is unavailable to the customer identity and how that unavailability was verified.

A release should not proceed while the canonical tenant mapping is ambiguous, an accessible dataset lacks a defined tenant boundary, or a negative test returns another tenant’s data. Those are blockers, not follow-up cleanup. Less critical gaps—such as an incomplete operator runbook—can have an owner and due date, but the customer data boundary needs evidence before exposure.

Implementation help and next step

If your team is preparing customer-facing embedded analytics, use this guide to frame a review of identity flow, dataset coverage, and the negative tests that matter for your product. Bring the access matrix, dataset inventory, and a small two-tenant fixture to that discussion. The most useful implementation decision is often not a more elaborate prompt; it is making tenant identity and query scope explicit enough that the application can reject an unsafe request.

Summary: the implementation sequence

  1. Map the customer request path and identify the server-side authorization decision.
  2. Define a canonical tenant key and a dataset-level data contract.
  3. Configure and review RLS for every dataset reachable through the customer experience.
  4. Keep agent-generated metric and filter proposals separate from trusted tenant identity.
  5. Validate embedding setup independently from authorization, keeping service credentials server-side.
  6. Prove the behavior with a two-tenant fixture, positive results, and conflicting-identity tests.
  7. Check relevant API, SQL, embedded, and application query paths separately.
  8. Fail closed when identity or result scope cannot be established, and retain useful, proportionate operational evidence.

The core acceptance criterion is straightforward: a customer’s request may produce useful analytics only when the authenticated application identity, the resolved tenant, the dataset policy, and the returned result agree. A fluent answer is not proof. A passing cross-tenant denial test, repeated for the paths the product actually exposes, is the practical evidence that the design is doing its job.

WANT TO TALK THROUGH YOUR SITUATION?

Talk it through with us. Thirty minutes, no slides.

P
Written by the PADISO TeamSydney-based technology leaders who build what they advise on. Seven years of fractional CTO, architecture and AI work for enterprise, government and private equity.

Keep reading

All posts →

Let's talk.

Tell us what you are weighing up, whether it is a build, a roadmap or a deal. You will leave the call knowing your next step.

Book a 30-min callhi@padiso.co