Skip to content

test: add userAttributes shorthand in mask.sql test cases#10668

Open
paveltiunov wants to merge 4 commits intomasterfrom
cursor/user-attributes-mask-sql-test-9abc
Open

test: add userAttributes shorthand in mask.sql test cases#10668
paveltiunov wants to merge 4 commits intomasterfrom
cursor/user-attributes-mask-sql-test-9abc

Conversation

@paveltiunov
Copy link
Copy Markdown
Member

@paveltiunov paveltiunov commented Apr 10, 2026

Check List

  • Tests have been run in packages where changes have been made if available
  • Linter has been run for changed code
  • Tests for the changes have been added if not covered yet
  • Docs have been added / updated if required

Description of Changes Made

This PR adds test coverage for the userAttributes shorthand in mask.sql, fixes mask SQL join dependency collection in Tesseract, and adds tests for CUBE context in mask SQL.

Fixes

Tesseract: Include mask SQL in join dependency collection

DimensionSymbol.get_dependencies() and get_cube_refs() now include dependencies and cube references from mask_sql, not just the main member_sql. Same for MeasureSymbol. This ensures that when a mask SQL expression references members from another cube, those references are included in join hint collection, preventing missing joins.

Files changed:

  • rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/dimension_symbol.rs
  • rust/cubesqlplanner/cubesqlplanner/src/planner/sql_evaluator/symbols/measure_symbol.rs

Tests

Unit tests (packages/cubejs-schema-compiler/test/unit/transpilers.test.ts):

  • userAttributes shorthand in mask.sql should transpile to SECURITY_CONTEXT
  • mask.sql with CUBE reference should resolve correctly — Verifies ${CUBE}.column resolves to proper table-qualified SQL in masked queries

Smoke RBAC fixtures (packages/cubejs-testing/birdbox-fixtures/rbac/model/cubes/security_context_test.js):

  • sc_ua_mask_test — Cube using userAttributes.tenantId shorthand in mask SQL
  • sc_cube_mask_test — Cube using ${CUBE}.product_id * -1 as mask SQL

Smoke RBAC tests (packages/cubejs-testing/test/smoke-rbac.test.ts):

Non-Tesseract (12 tests):

  • userAttributes shorthand in mask sql (SQL + REST)
  • CUBE context in mask sql (SQL + REST)
  • Existing security context tests (8 tests)

Tesseract-enabled with CUBESQL_SQL_PUSH_DOWN=true (4 tests):

  • userAttributes shorthand in mask sql (SQL + REST)
  • CUBE context in mask sql (SQL + REST)

Test Results

  • Unit tests: All 16 transpiler tests pass
  • Smoke RBAC tests: All 16 matched tests pass (12 non-Tesseract + 4 Tesseract)
Open in Web Open in Cursor 

Add unit test in transpilers.test.ts verifying that userAttributes shorthand
in mask.sql is transpiled to SECURITY_CONTEXT.cubeCloud.userAttributes.

Add sc_ua_mask_test cube definition using userAttributes shorthand in mask.sql
with access policy masking.

Add smoke tests (SQL API and REST API) to verify the mask SQL with
userAttributes shorthand works end-to-end.

Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
@github-actions github-actions bot added the javascript Pull requests that update Javascript code label Apr 10, 2026
@claude
Copy link
Copy Markdown

claude bot commented Apr 10, 2026

Claude finished @paveltiunov's task in 1m 32s —— View job


Code Review: userAttributes shorthand in mask.sql tests

  • Read PR diff and changed files
  • Review unit test changes
  • Review smoke RBAC fixture changes
  • Review smoke RBAC test changes
  • Post comprehensive review

Overall: This PR looks good. The tests are well-structured, follow existing patterns in the codebase, and provide meaningful coverage for the userAttributes shorthand in mask.sql. Here's the detailed review:


Unit Test (transpilers.test.ts)

The new test at line 356 follows the exact same pattern as the existing userAttributes shorthand test for dimension sql (line 337). The approach of verifying the transpiled output contains SECURITY_CONTEXT.cubeCloud.userAttributes is consistent and correct.

One minor observation: the test accesses mask.sql via (cubeEvaluator.cubeFromPath('Test').dimensions.masked_dim as any).mask.sql — the as any cast suggests the type definition for dimensions doesn't include mask in its type signature. This is fine for a test, just noting it.

Smoke RBAC Fixture (security_context_test.js)

The sc_ua_mask_test cube is well-constructed:

  • Uses sql_table instead of raw SQL (appropriate since it doesn't need WHERE clause filtering)
  • The mask.sql definition CAST(${userAttributes.tenantId} AS INTEGER) correctly uses the shorthand syntax being tested
  • The access policy with memberLevel: { includes: [] } + memberMasking: { includes: '*' } is the correct pattern to force all members through masking — this matches the existing pattern in customers.yaml
  • Includes id as primary key and product_id as an additional dimension, which is appropriate for the table structure

Smoke RBAC Tests (smoke-rbac.test.ts)

SQL API test (line 824): Queries via SELECT * FROM sc_ua_mask_test LIMIT 5 and verifies each row's masked_price equals 1. The assertion is correct — the sc_test user has tenantId: '1' in securityContext.cubeCloud.userAttributes (confirmed in cube.js:199), and CAST('1' AS INTEGER) = 1.

REST API test (line 899): Queries via scClient.load() with the SC_TEST_TOKEN that contains the same tenantId: '1'. The assertions mirror the SQL API test appropriately.

Both tests are placed in the correct describe blocks alongside the other SECURITY_CONTEXT.cubeCloud feature tests.

Suggestions (non-blocking)

  1. REST API assertion type check: The REST test asserts expect(row['sc_ua_mask_test.masked_price']).toBe(1). Since REST API responses may return numeric values as strings depending on the serialization, consider whether .toBe('1') or a more flexible assertion might be needed. That said, this follows the same pattern as existing masking tests in this file, so it's likely fine.

  2. Negative test case: A future enhancement could test that when tenantId is a different value (e.g., '42'), the masked price reflects that value instead. This would confirm the mask is truly dynamic. Not required for this PR.

Summary

Clean PR that adds good test coverage across three levels (unit, SQL API smoke, REST API smoke) for the userAttributes shorthand in mask.sql. The tests are consistent with existing patterns, assertions are correct, and the fixture is well-structured. LGTM.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 10, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.80%. Comparing base (04eed5d) to head (bbf6d22).
⚠️ Report is 5 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master   #10668       +/-   ##
===========================================
+ Coverage   57.92%   78.80%   +20.88%     
===========================================
  Files         215      465      +250     
  Lines       16642    91903    +75261     
  Branches     3346     3346               
===========================================
+ Hits         9640    72427    +62787     
- Misses       6513    18987    +12474     
  Partials      489      489               
Flag Coverage Δ
cube-backend 57.99% <ø> (+0.07%) ⬆️
cubesql 83.40% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

…UBE context

- Tesseract: Include mask_sql dependencies and cube refs in
  DimensionSymbol.get_dependencies() and get_cube_refs(), and
  MeasureSymbol.get_dependencies() and get_cube_refs(). This ensures
  join hints are collected from mask SQL references.

- Transpiler: Ensure mask.sql always has CUBE as a default parameter
  in the arrow function, even when not explicitly referenced. This
  provides consistent CUBE context for mask SQL expressions.

- YamlCompiler: Pass ensureCubeParam flag for mask.sql fields so
  YAML-defined masks also get default CUBE context.

- Tests: Add unit tests for CUBE default parameter in mask.sql and
  CUBE reference resolution in masked queries. Add smoke RBAC tests
  for CUBE context in mask SQL via SQL API and REST API.

Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
@github-actions github-actions bot added the rust Pull requests that update Rust code label Apr 11, 2026
cursoragent and others added 2 commits April 11, 2026 19:09
…and CUBE context in mask SQL

Add a new 'Cube RBAC Engine [Tesseract]' describe block that runs
with CUBESQL_SQL_PUSH_DOWN=true to exercise the Tesseract/native SQL
planner path for mask SQL features.

Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
…level fixes

Transpilation already correctly handles CUBE context for mask.sql -
when mask.sql references cube members or CUBE explicitly, the transpiler
adds CUBE as a parameter. The default CUBE context issue is in the
evaluation path, not transpilation.

Reverted:
- CubePropContextTranspiler: removed maskSqlPattern, ensureCubeParam
- YamlCompiler: removed ensureCubeParam plumbing
- Removed 'mask.sql should always have CUBE as default parameter' test

Kept:
- Tesseract mask_sql dependency collection fixes (dimension + measure)
- mask.sql with CUBE reference resolution test
- All smoke tests (non-Tesseract and Tesseract)

Co-authored-by: Pavel Tiunov <pavel.tiunov@gmail.com>
@paveltiunov paveltiunov marked this pull request as ready for review April 11, 2026 20:48
@paveltiunov paveltiunov requested review from a team as code owners April 11, 2026 20:48
@claude
Copy link
Copy Markdown

claude bot commented Apr 11, 2026

Claude finished @paveltiunov's task in 2m 38s —— View job


Code Review: userAttributes shorthand in mask.sql tests

  • Read PR diff and all changed files
  • Review Rust changes (dimension_symbol.rs, measure_symbol.rs)
  • Review unit test changes (transpilers.test.ts)
  • Review smoke RBAC fixture changes (security_context_test.js)
  • Review smoke RBAC test changes (smoke-rbac.test.ts)
  • Post comprehensive review

Overall: LGTM. The bug fix is correct, and the tests are well-structured with good coverage across unit, SQL API, and REST API levels. A few observations below, mostly non-blocking.


Rust Fix: mask SQL in join dependency collection

The core fix in dimension_symbol.rs:236-241 and measure_symbol.rs:335-337 is correct — get_dependencies() and get_cube_refs() now collect from mask_sql, ensuring cross-cube mask SQL references produce proper join hints.

Potential gap — iter_sql_calls() and apply_to_deps() do not include mask_sql:

  • iter_sql_calls() (dimension_symbol.rs:232-234, measure_symbol.rs:311-318) is used by MemberSymbol::validate_cube_refs() to validate SQL references. Since mask_sql isn't included, cube references in mask SQL won't be validated. This may be intentional (the measure version has a //FIXME note about backward compatibility for similar exclusions), but it's worth confirming.

  • apply_to_deps() (dimension_symbol.rs:223-230, measure_symbol.rs:285-309) transforms symbol dependencies recursively. If mask_sql references a dependency that needs transformation (e.g., in multi-stage queries), it won't be updated. Not immediately dangerous since mask SQL typically references simple columns or security context, but could be a latent issue for more complex mask expressions.

Minor style nit: The get_cube_refs implementation uses refs.extend(mask.get_cube_refs()) which allocates an intermediate Vec. The extract_cube_refs pattern (used by Case in measure_symbol.rs:353) avoids this:

// Current (allocates intermediate vec):
refs.extend(mask.get_cube_refs());

// Consistent with nearby Case pattern:
mask.extract_cube_refs(&mut refs);

Not a blocker — just a consistency observation.


Unit Tests (transpilers.test.ts)

Clean and well-structured:

  • userAttributes shorthand in mask.sql (line 356): Correctly mirrors the existing dimension sql shorthand test pattern. The as any cast at line 378 is fine for test code.

  • CUBE reference in mask.sql (line 382): Goes beyond transpilation to build actual SQL via PostgresQuery and verifies table-qualified output ("test".secret_val). Good end-to-end verification at the unit level.


Smoke RBAC Fixtures (security_context_test.js)

Both new cubes are well-constructed:

  • sc_ua_mask_testCAST(${userAttributes.tenantId} AS INTEGER) correctly tests the shorthand transpilation in an integration context.
  • sc_cube_mask_test${CUBE}.product_id * -1 tests CUBE context resolution, and the sql: ${CUBE}.product_id on the dimension itself ensures the unmasked path also uses CUBE context. Good symmetry.
  • Access policies use the correct memberLevel: { includes: [] } + memberMasking: { includes: '*' } pattern to force masking.

Smoke RBAC Tests (smoke-rbac.test.ts)

Non-Tesseract tests (lines 824-935): Assertions are correct — sc_test user has tenantId: '1', so CAST('1' AS INTEGER) = 1 for the mask price, and product_id * -1 should always be negative (assuming product_id > 0, which holds for the ecom dataset).

Tesseract tests (lines 1033-1152): Clean parallel structure with CUBESQL_SQL_PUSH_DOWN: 'true'. The SC_TEST_TOKEN at line 1105 is duplicated from the non-Tesseract block (line 851). This is a minor DRY concern — could be extracted to module scope since both blocks use the identical token payload. Non-blocking since the duplication is small and keeping tokens close to their describe blocks aids readability.

Port sharing: All describe blocks share PG_PORT = 5656. This is safe since Jest runs top-level describe blocks sequentially within a file, but it's worth being aware of if these tests are ever parallelized.


Summary

Area Verdict
Rust fix correctness ✅ Correct
iter_sql_calls / apply_to_deps completeness ⚠️ Worth confirming (non-blocking)
Unit tests ✅ Clean, follows patterns
Smoke fixtures ✅ Well-constructed
Smoke tests ✅ Correct assertions
Test coverage ✅ 3-level coverage (unit + SQL API + REST API) for both Tesseract and non-Tesseract

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript Pull requests that update Javascript code rust Pull requests that update Rust code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants