Fine-grained data access control for jOOQ

Protect sensitive data at the row and column level, without changing a line of your application code.

The Problem

Fine-grained data access control is essential. Most implementations get it wrong.

  1. Scattered & Hardcoded

    Access checks are buried across your codebase. Every new feature, every refactor is another place to forget a permission check.

  2. Blacklist Thinking

    Most apps block specific access rather than requiring explicit grants. One forgotten check = one security hole.

  3. Invisible to Auditors

    Only developers know what access rules exist. Compliance reviews require code archaeology.

How Regelwerk Works

Regelwerk sits between your jOOQ queries and the database. It rewrites SQL at runtime based on declarative rules, so your application code never changes.

Your App
jOOQ
Regelwerk
Rules
Database
Your query
SELECT *
FROM customers
What executes
SELECT name, '***' AS balance, advisor_id, branch
FROM customers
Added by Regelwerk: WHERE advisor_id = 'john.doe'
AND branch = 'zurich'

As a jOOQ ExecuteListener, Regelwerk intercepts every query. Rules add WHERE clauses, mask columns, and validate writes before the query reaches the database.

Key Capabilities

Row-Level Security

Control exactly which rows each user can read, update, or delete via automatic SQL WHERE clause injection.

Column-Level Masking

Hide or anonymize sensitive columns per user or role with expression-based value replacement.

Full CRUD Protection

INSERT and UPDATE statements are validated within the transaction boundary and rolled back on violation. Users can't escalate privileges by writing rows they shouldn't own.

Context-Aware Rules

Rules adapt based on user identity, role, use-case, and dynamic runtime variables like department or location.

Why Regelwerk

Deny by Default

No rule means no access. Period. Unlike blacklist approaches, you can't accidentally leave a door open. Every data access requires an explicit grant, so a forgotten rule blocks access instead of quietly allowing it.

Zero Code Intrusion

Regelwerk integrates at the jOOQ configuration level. Your business logic has zero dependency on Regelwerk, not even an import statement. You can add, remove, or reconfigure it without touching application code.

Rules, Not Code

Access policies are declarative configuration, not scattered if-statements. Change permissions in hours, not sprints. Security officers, auditors, and data owners can read and verify the rules without opening an IDE.

Battle-Tested

Born from 15+ years of real-world data access control in security-critical domains like e-banking and e-CRM. Now rebuilt as a modern jOOQ extension with support for PostgreSQL, Oracle, MySQL, and more.

Who Benefits

Developers

Stop writing permission checks. Focus on business logic. Regelwerk handles data access control transparently, with no new dependencies in your application code.

Security & Compliance

All access rules are visible in one place, readable without reading code. Every data access is logged with the user and context behind it.

Data Owners

Take back control over who sees your data. Access rules are configuration, not code, so you can change them without waiting for the next release.

Use Cases

Real-World Rule Examples

Regelwerk handles complex, real-world access scenarios with simple, declarative rules.

regelwerk.xml
<rule xsi:type="v3:rule">
  <name>Advisor sees own team's customers</name>
  <accessTypeRef>read</accessTypeRef>
  <roleRef>ADVISOR</roleRef>
  <tableRef>PUBLIC.CUSTOMER</tableRef>
  <selectionAccessRef>own-team-customers</selectionAccessRef>
</rule>

<selectionAccess xsi:type="v3:selectionAccess">
  <name>own-team-customers</name>
  <clause>
      IN (SELECT customer_id FROM contract
      WHERE team_id = ${regelwerkTeam})
  </clause>
  <selector>${$}.id</selector>
</selectionAccess>
regelwerk.xml
<rule xsi:type="v3:rule">
  <name>Mask salary for EMPLOYEE role</name>
  <accessTypeRef>read</accessTypeRef>
  <roleRef>EMPLOYEE</roleRef>
  <tableRef>PUBLIC.EMPLOYEE_CONTRACT</tableRef>
  <projectionAccessRef>mask-salary</projectionAccessRef>
</rule>

<projectionAccess xsi:type="v3:projectionAccess">
  <name>mask-salary</name>
  <columnAccess xsi:type="v3:columnAccess">
    <columnName>SALARY</columnName>
    <readExpression>'***'</readExpression>
  </columnAccess>
</projectionAccess>
regelwerk.xml
<rule xsi:type="v3:rule">
  <name>Claims specialists can create claims</name>
  <accessTypeRef>create</accessTypeRef>
  <roleRef>CLAIMS_SPECIALIST</roleRef>
  <tableRef>PUBLIC.INSURANCE_CLAIM</tableRef>
  <selectionAccessRef>all</selectionAccessRef>
</rule>

<!-- No create rule exists for other roles.
     Deny by default: without an explicit grant,
     any INSERT on INSURANCE_CLAIM is blocked. -->
Tooling

Regelwerk Studio

Build and review access logic without writing code.

Regelwerk Studio rule editor showing authorities, rules, tables, and selections in a column-based layout

Integration in 3 Steps

Set it up once. The execution context resolves the current user on each query, so your queries and business logic stay the same.

  1. Define your rules in XML or programmatically
  2. Provide an execution context that reads the current user per request (e.g. from a JWT)
  3. Attach it to your jOOQ configuration
// 1. Define your rules
RuleProvider rules = new RegelwerkXmlRuleProvider(
    () -> getClass().getResourceAsStream("/regelwerk.xml"));

// 2. Resolve the current user per request (e.g. from a JWT claim)
ExecutionContext ctx = new JwtAwareExecutionContext();

// 3. Attach to your jOOQ Configuration once at startup.
DSLContext dsl = DSL.using(connection, SQLDialect.POSTGRES)
    .configuration()
    .set(RegelwerkListenerFactory.create(rawDsl, rules, ctx))
    .dsl();

// From here on, Regelwerk rewrites queries using the request's user and roles
dsl.select().from(CUSTOMERS).fetch(); // ← rules applied transparently

Ready to protect your data?

Add Regelwerk to your jOOQ project. Existing queries stay untouched.

Maven
<dependency>
  <groupId>com.inventage.regelwerk.jooq</groupId>
  <artifactId>regelwerk.jooq</artifactId>
</dependency>
See Integration

Or get in touch directly

Please enter your name.
Please enter a valid email address.