The query language

Questions a graph
can’t answer.

RQL re-runs the real authorization decision at query time — every SCP, every condition, every role chain, live. So you can ask counterfactuals, compose evaluations, and segment by your own tags. Here are the questions a pre-computed graph structurally can’t return.

§ — Seven questions a pre-computed graph can’t return

01 — Counterfactual conditions

Who could read this bucket if MFA were switched off?

who-can(
    action: "s3:GetObject"
    resource: var:critical-buckets
    env: {"aws:multifactorauthpresent": "false"}
)

Why a graph can’t answer this

A graph records each condition as met-or-unmet at the instant it was scanned. To answer “what if MFA were absent?” it has to re-ingest the account with the condition flipped. RQL takes the condition as a parameter — any of AWS’s 50+ global keys, no re-scan.

What a graph tool does instead

Re-ingest with the condition flipped — or wait for a vendor rule built for that exact case.

02 — Assume vs. verify

Assuming TLS is always enforced, who on the admin team can still reach the audit bucket?

who-can(
    among: users where self.Tags has (self.Key == "team" & self.Value == "admin")
    action: "s3:GetObject"
    resource: var:audit-bucket
    always-ok-vars: ["aws:securetransport"]
    env: {"aws:multifactorauthpresent": "true"}
)

Why a graph can’t answer this

env pins a condition to a value; always-ok-vars drops a condition from the question entirely — what you assume and what you test, side by side in one expression. A graph stores every condition as a single fixed fact.

What a graph tool does instead

Treat every condition as fixed at scan time — no way to separate an assumption from a test.

03 — Composition across evaluations

Who is admin in effect, but not admin on paper?

admin-in-effect = users where self.Entitlements.Abilities includes "iam-admin"
admin-on-paper  = users where self.Groups has (self ~/admin/i)

admin-in-effect where self not in admin-on-paper

Why a graph can’t answer this

Each line is its own live authorization evaluation; the last line subtracts one result set from the other. Effective-admins minus declared-admins is, by definition, your shadow admins. A graph filters one node at a time — it can’t compose two evaluations into a third.

What a graph tool does instead

Run both queries, export both lists, and diff them in a spreadsheet.

04 — Segmentation as data

Can anything tagged app-A reach app-B’s buckets — and app-C tomorrow, with no new rule?

app-a-users  = users where self.Tags has (self.Key == "application" & self.Value == "app-a")
app-b-buckets = buckets where self.Tags has (self.Key == "application" & self.Value == "app-b")

who-can(
    among: app-a-users
    action: "s3:GetObject"
    resource: app-b-buckets
)

Why a graph can’t answer this

Your tag scheme is data the query reads, not configuration we ship. Add a tenant or application tomorrow and the query is unchanged — only the rows it returns change. On a graph, every new tag pair is a rule someone has to author first.

What a graph tool does instead

Author a custom rule for each tag pair, every time the scheme grows.

05 — Tenant isolation, evaluated

Could anyone read another tenant’s rows in our pooled DynamoDB table?

foreign-tenant-id = "tenant-b"

who-can(
    action: "dynamodb:GetItem"
    resource: var:multi-tenant-table
    env: {"dynamodb:leadingkeys": foreign-tenant-id}
)

Why a graph can’t answer this

In a pooled SaaS architecture the entire tenant boundary lives inside a condition — dynamodb:LeadingKeys, s3:ExistingObjectTag, kms:EncryptionContext. A graph records that a condition exists; it can’t evaluate it for a concrete tenant value. RQL passes the foreign tenant as context, and the answer has to come back empty — for every pair you ask about.

What a graph tool does instead

Label the edge “conditional access” and leave the per-tenant verdict to a manual policy read.

06 — Your definition of toxic

Which roles a service can assume also hold a privilege-escalation path?

service-bound = roles where self.AssumeRoleStatement has (
    self.Effect == "Allow" & self.Principal includes "Service"
)

service-bound where self.Entitlements.Sequences.size() > 0
    map { Name, Arn, sequences: self.Entitlements.Sequences }

Why a graph can’t answer this

A structural match on the trust-policy tree AND a computed-entitlement predicate, in one expression. That’s your organization’s definition of a toxic combination — not a vendor research team’s opinion of one. A graph fires on pre-built combos; a new one is a feature request.

What a graph tool does instead

File a feature request and wait for the vendor to ship the rule.

07 — Evaluate what doesn’t exist yetVirtual Roles

What would this vendor’s role reach — before we deploy it?

proposed-vendor = roles where self.Name == var:proposed-vendor-name

who-can(
    among: proposed-vendor
    action: "s3:GetObject"
    resource: var:critical-resources
)

Why a graph can’t answer this

A graph reflects only what it scanned — a role that doesn’t exist isn’t in it. Define a proposed role in Whocan and every query evaluates it as a first-class entity, so you assess a vendor’s blast radius before you sign, not after.

What a graph tool does instead

Deploy the role, wait for the next scan, evaluate, then tear it back down.

§ — Examples

A taste of the library.

Grouped by pillar. Each one runs as-is against your real environment, or saves as a continuous monitor — and the library keeps growing.

Access Review

Exhaustive inventory of who has access to what, for periodic or continuous access review (NIS2 Art. 21, ISO 27001:2022 A.5.18).

Data Protection (GDPR)

Who can access the resources where personal data lives (GDPR Art. 5, 25, 32).

Attack Path Analysis

Discover privilege escalation chains and transitive access before attackers do.

AI Agents & Non-Human Identities

Bedrock agents, service roles, CI runners — non-human identities now outnumber humans. And Bedrock supports no resource-based policies: access is decided entirely on the identity side, the exact chain who-can computes.

Data Perimeter

Validate the identity, network, and resource perimeter controls.

Application Segmentation

Verify workload isolation: application A's principals should not access application B's resources.

Least Privilege

Find over-provisioned identities and reduce blast radius.

Conformity (NIS2 / ISO 27001 / SOC 2)

Queries mapped to specific compliance requirements.

DORA (EU financial entities)

Digital Operational Resilience Act — in application since January 2025 for banks, insurers, investment firms, and crypto-asset providers. Each query maps to a specific article and produces evidence a supervisor can reproduce.

Network Security

Security groups, network ACLs, and VPC configuration.

Identity Center

Assessment of Identity Center users, groups, and permission sets.

Continuous Monitoring

Queries designed to be saved as monitors. Each represents an access invariant — an alarm fires when the result set changes. Any query in this library can be saved the same way.

Ask these on your environment

15 minutes to deploy. The full library — and your own questions — answered against your real cloud.