Thanks to visit codestin.com
Credit goes to github.com

Skip to content

feat(compliance): audit gating checks, worker tenant wiring, typed session organizationId - #231

Merged
RohinBhargava merged 1 commit into
mainfrom
rohin/compliance-gating-checks
Aug 2, 2026
Merged

feat(compliance): audit gating checks, worker tenant wiring, typed session organizationId#231
RohinBhargava merged 1 commit into
mainfrom
rohin/compliance-gating-checks

Conversation

@RohinBhargava

@RohinBhargava RohinBhargava commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Answers "do compliance checks verify the tenant/RLS/retention abstractions are actually wired?" — previously no; the audit was a data inventory (entities, routes, secrets, residency) with no wiring verification. Now it gates setup:

Audit: local checks (offline, deterministic, in --json as localFindings)

  • tenant-isolation-wiring: every project owning persistence entities must call setupTenantFilter and setupRls in each runtime entrypoint (server.ts and worker.ts)
  • retention-wiring / erasure-wiring: entities declaring retention or holding classified data require RetentionService / ComplianceDataService registrations
  • possible-misclassification: fields classified none whose names match PII/PHI/PCI keyword lists (camelCase/snake_case word-splitting with joined pairs — first_name, cardNumber, dateOfBirth match; name, externalId, billingProvider don't)

The gap the wiring check immediately caught

Worker entrypoints never wired tenant isolation: server.ts templates call setupTenantFilter/setupRls but worker.ts (template + sample-worker) did not — background jobs touched tenant-scoped tables with no isolation active, silently, since the tenant filter is fail-open. Both are now wired (guarded by is_database_enabled, mirroring server.ts).

Related fixes

  • init worker now skips compliance.controller.ts/compliance.routes.ts when IAM isn't configured (parity with init service) — previously a database worker in a no-IAM app failed typecheck resolving the IAM-gated JWKS_PUBLIC_KEY_URL token
  • [email protected]: ForklaunchBaseSession types organizationId as a first-party session claim; the scaffolded controller's (req.session as Record<string, unknown>)?.organizationId cast is now req.session?.organizationId

Test plan

  • cargo test: 333 passed (new: keyword classifier cases, wiring-gate detection, fs-level check integration)
  • Live validation on a fresh scaffold: audit reports 0 findings on a correctly wired app; flags both missing setup calls when stripped from server.ts; flags a contactEmail field classified none as possible PII
  • Fresh init worker -t database in a no-IAM app now typechecks clean (was TS2339)
  • sample-worker builds with the wiring change; framework core 371 tests pass with the session type change

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added offline compliance checks for tenant isolation, retention services, and sensitive data classifications.
    • Compliance reports now include local findings with severity indicators and clear all-clear messaging.
    • Worker templates automatically configure tenant filtering and row-level security when database support is enabled.
    • Sessions now support an optional organization identifier.
  • Bug Fixes

    • Improved generated worker projects when IAM is not configured by excluding irrelevant compliance templates.
    • Improved request handling when session information is unavailable.

…ers, typed session organizationId

- compliance audit now runs offline local checks: every project owning
  persistence entities must wire setupTenantFilter/setupRls in each
  runtime entrypoint (server.ts and worker.ts), register
  RetentionService when entities declare retention, and register
  ComplianceDataService when entities hold classified data; results
  print in a Local checks section and serialize as localFindings
- sensitive-field heuristics: fields classified 'none' whose names
  match PII/PHI/PCI keyword lists (word-split camelCase/snake_case
  matching to limit false positives) are surfaced for review
- worker template and sample-worker now wire setupTenantFilter/setupRls
  in worker.ts, closing the gap where background jobs queried
  tenant-scoped tables with no isolation layer active
- init worker skips compliance.controller/routes when IAM is not
  configured (parity with init service; the controller resolves the
  IAM-gated JWKS_PUBLIC_KEY_URL token and failed typecheck otherwise)
- core: ForklaunchBaseSession types organizationId as a first-party
  session claim, removing the Record<string, unknown> cast from the
  scaffolded controller tenant scoping (published as [email protected])

Co-Authored-By: Claude Fable 5 <[email protected]>
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds tenant-aware worker initialization, typed organization session claims, offline compliance checks, and local finding output in compliance reports and audit command paths.

Changes

Tenant Isolation and Compliance

Layer / File(s) Summary
Session contract and controller access
framework/core/src/http/types/apiDefinition.types.ts, framework/core/package.json, cli/src/templates/router/api/controllers/{{camel_case_name}}.controller.ts
The HTTP session types now include optional organizationId. The controller reads the claim directly. The core package version changes to 1.5.10.
Worker tenant isolation wiring
cli/src/templates/project/worker/worker.ts, blueprint/sample-worker/worker.ts, cli/src/init/worker.rs
Database-enabled workers resolve the ORM and configure tenant filtering and row-level security before event processing. Worker generation excludes compliance routes when IAM is not configured.
Offline compliance scanning
cli/src/compliance/checks.rs, cli/src/compliance/mod.rs
The CLI scans project files for missing tenant gates, missing retention or erasure services, and sensitive fields classified as none. Findings are typed, sorted, and tested.
Compliance finding reporting
cli/src/compliance/audit.rs
Local findings are stored as localFindings and displayed for both platform-upload success and local-only fallback paths.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AuditCommand
  participant LocalChecks
  participant ModulesDirectory
  participant ComplianceReport
  participant Terminal
  AuditCommand->>LocalChecks: Run local compliance checks
  LocalChecks->>ModulesDirectory: Scan project files
  LocalChecks-->>AuditCommand: Return sorted findings
  AuditCommand->>ComplianceReport: Store localFindings
  AuditCommand->>Terminal: Print formatted results
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main compliance checks, worker tenant wiring, and typed session organizationId changes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rohin/compliance-gating-checks

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Biome (2.5.5)
cli/src/templates/project/worker/worker.ts

File contains syntax errors that prevent linting: Line 6: Private names are only allowed on the left side of a 'in' expression; Line 7: unterminated regex literal; Line 8: Illegal use of an import declaration not at the top level; Line 9: Private names are only allowed on the left side of a 'in' expression; Line 9: Expected an identifier but instead found '{'.; Line 9: Illegal use of an import declaration not at the top level; Line 9: Expected a semicolon or an implicit semicolon after a statement, but found none; Line 9: Invalid regex flag; Line 9: Invalid regex flag; Line 9: Invalid regex flag; Line 9: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{camel_case_name'.; Line 9: unterminated string literal; Line 16: Private names are only allowed on the left side of a 'in' expression; Line 22: unterminated regex literal; Line 23: Expected a property, or a signature but instead found '{pascal_case_name'.; Line 23: expected , but instead found }; Line 23: expected , but instead found EventRecord; Line 44: Expected a property, or a signature but instead found '{pascal_case_name'.; Line 44: expected , but instead found }; Line 44: expected , but instead found EventRecord; Line 60: expected } but instead the file ends

cli/src/templates/router/api/controllers/{{camel_case_name}}.controller.ts

File contains syntax errors that prevent linting: Line 1: Expected an identifier but instead found '{'.; Line 1: Private names are only allowed on the left side of a 'in' expression; Line 1: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{/is_iam_configured'.; Line 1: Expected a statement but instead found '}schemaValidator } from '@{{app_name}}/core''.; Line 2: Private names are only allowed on the left side of a 'in' expression; Line 3: Expected an identifier but instead found '{'.; Line 3: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{pascal_case_name'.; Line 3: Expected a statement but instead found '}ResponseMapper } from '../../domain/mappers/{{camel_case_name}}.mappers''.; Line 4: unterminated regex literal; Line 5: Expected a statement but instead found '^with_mappers'.; Line 6: Expected an identifier but instead found '{'.; Line 6: Illegal use of an import declaration not at the top

... [truncated 6138 characters] ...

ad found {; Line 92: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{/is_worker'.; Line 92: expected , but instead found }; Line 93: expected , but instead found {; Line 93: expected , but instead found {; Line 93: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{/is_worker'.; Line 93: expected , but instead found }; Line 94: Expected an identifier but instead found '{'.; Line 94: Expected a property, a shorthand property, a getter, a setter, or a method but instead found '{camel_case_name'.; Line 94: expected , but instead found }; Line 94: expected , but instead found (; Line 97: Expected a statement but instead found ')'.; Line 98: expected } but instead the file ends


Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
blueprint/sample-worker/worker.ts (1)

5-7: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Reorder the new imports to match the import-layer guideline.

Move the local-persistence import (./persistence/entities/sampleWorkerRecord.entity) before the same-directory import (./bootstrapper). The current order places a same-directory import ahead of a local-persistence import.

🔧 Suggested import order
 import { setupRls, setupTenantFilter } from '`@forklaunch/core/persistence`';
-import { ci, tokens } from './bootstrapper';
 import { type SampleWorkerEventRecord } from './persistence/entities/sampleWorkerRecord.entity';
+import { ci, tokens } from './bootstrapper';

As per coding guidelines, "Organize imports in 7 layers: Node built-ins, external dependencies, Forklaunch framework packages, cross-module imports, local persistence, local domain, and same directory."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@blueprint/sample-worker/worker.ts` around lines 5 - 7, Reorder the imports so
the local persistence type import from sampleWorkerRecord.entity appears before
the same-directory bootstrapper import, while leaving the external and framework
imports unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@blueprint/sample-worker/worker.ts`:
- Around line 5-7: Reorder the imports so the local persistence type import from
sampleWorkerRecord.entity appears before the same-directory bootstrapper import,
while leaving the external and framework imports unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15ddd0ea-006b-48b3-8e8d-4785027e8984

📥 Commits

Reviewing files that changed from the base of the PR and between cfed5d1 and f11fb38.

📒 Files selected for processing (9)
  • blueprint/sample-worker/worker.ts
  • cli/src/compliance/audit.rs
  • cli/src/compliance/checks.rs
  • cli/src/compliance/mod.rs
  • cli/src/init/worker.rs
  • cli/src/templates/project/worker/worker.ts
  • cli/src/templates/router/api/controllers/{{camel_case_name}}.controller.ts
  • framework/core/package.json
  • framework/core/src/http/types/apiDefinition.types.ts

@RohinBhargava
RohinBhargava merged commit f4b3ab9 into main Aug 2, 2026
15 checks passed
@RohinBhargava
RohinBhargava deleted the rohin/compliance-gating-checks branch August 2, 2026 02:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant