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

Skip to content

feat: Compliance as Code - #124

Merged
RohinBhargava merged 27 commits into
mainfrom
rohin/compliance-security
Mar 26, 2026
Merged

feat: Compliance as Code#124
RohinBhargava merged 27 commits into
mainfrom
rohin/compliance-security

Conversation

@RohinBhargava

@RohinBhargava RohinBhargava commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • New Features

    • Added comprehensive compliance framework with field-level encryption for sensitive data (PHI, PCI).
    • Implemented GDPR support with user data erasure and export capabilities.
    • Added tenant isolation filtering and Row-Level Security for multi-tenant applications.
    • Introduced rate limiting, audit logging, and WebSocket security with channel management.
  • Improvements

    • Enhanced API endpoint access control with explicit public/protected/internal/authenticated levels.
    • Updated persistence layer with improved compliance metadata and retention policy support.
    • Expanded entity support for data retention and anonymization policies.
  • Chores

    • Major dependency updates to framework and blueprint packages (v1.0+).
    • Upgraded TypeScript to v6.0 and supporting tools.
    • Added GitHub Actions CI/CD and Dependabot configuration templates.

@coderabbitai

coderabbitai Bot commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This pull request introduces a comprehensive compliance framework across the ForkLaunch ecosystem. It migrates all entity definitions from MikroORM's property builders to compliance-aware builders, implements field-level encryption for sensitive data, adds retention policies with enforcement capabilities, introduces audit logging and rate limiting, and implements GDPR compliance endpoints. Access control levels are added to all routes, and new CLI commands enable compliance auditing and reporting.

Changes

Cohort / File(s) Summary
Entity Migration to Compliance Framework
blueprint/billing-*/persistence/entities/*, blueprint/iam-*/persistence/entities/*, framework/core/persistence/*, blueprint/sample-worker/persistence/entities/*
All entity definitions switched from MikroORM defineEntity/p builders to defineComplianceEntity/fp builders; all properties now include explicit `.compliance('none'
Compliance Infrastructure
framework/core/src/persistence/complianceTypes.ts, framework/core/src/persistence/compliancePropertyBuilder.ts, framework/core/src/persistence/defineComplianceEntity.ts
New compliance type system with ComplianceLevel enum, compliance field registry, fp property builder proxy wrapping MikroORM's p, retention policy types with ISO-8601 duration parsing, and entity compliance validation.
Encryption & Event Subscription
framework/core/src/encryption/fieldEncryptor.ts, framework/core/src/persistence/complianceEventSubscriber.ts, framework/core/src/persistence/tenantFilter.ts, framework/core/src/persistence/rls.ts
New AES-256-GCM field encryptor with per-tenant key derivation; MikroORM event subscriber enforcing field encryption on beforeCreate/beforeUpdate and decryption on onLoad; tenant isolation filter for multi-tenancy; PostgreSQL RLS event subscriber for additional row-level security.
Route Access Control
blueprint/billing-base/api/controllers/*, blueprint/billing-stripe/api/controllers/*, blueprint/iam-base/api/controllers/*, blueprint/iam-better-auth/api/controllers/*, blueprint/sample-worker/api/controllers/*, framework/e2e-tests/servers/*
All route handlers augmented with access metadata field ('public', 'protected', 'internal'); access levels enforce required authentication and authorization configuration; validation logic added to routerSharedLogic.ts.
Audit & Rate Limiting Services
framework/core/src/http/telemetry/auditLogger.ts, framework/core/src/http/rateLimit/rateLimiter.ts, framework/core/src/http/middleware/request/tenantContext.middleware.ts
New audit logger emitting OpenTelemetry events with structured fields; rate limiter with configurable read/write windows and TTL cache backing; tenant context middleware resolving and setting tenant filter parameters.
Retention Enforcement
framework/core/src/services/retentionService.ts, cli/src/templates/project/service/scripts/enforce-retention.ts
Retention service implementing batch-based deletion/anonymization enforcement against registered retention policies; one-shot CLI script for running enforcement with dry-run support.
Compliance Endpoints
blueprint/billing-base/api/controllers/compliance.controller.ts, blueprint/iam-base/api/controllers/compliance.controller.ts
GDPR erase/export endpoints accepting userId, filtering entities by compliance classification, removing sensitive records or exporting PII/PHI/PCI fields; cascading calls to peer systems (IAM from billing, etc.).
CLI Compliance Audit
cli/src/compliance/audit.rs, cli/src/compliance/mod.rs
New top-level compliance command with audit subcommand; audit loads manifest compliance metadata and OpenAPI route specs, generates point-in-time compliance report with entity classifications, route access levels, and risk/DPIA metadata; supports local JSON/stdout output and optional platform API upload.
Manifest & CLI Infrastructure
cli/src/core/manifest.rs, cli/src/core/ast/infrastructure/compliance.rs, cli/src/core/validate.rs, cli/src/sync/all.rs
Extended manifest config with [compliance] section containing entities, secrets, data_residency, and retention maps; new AST scanner for .entity.ts files extracting entity compliance classifications and retention policies; validation enforcing known compliance levels.
GitHub Configuration Templates
cli/src/templates/github/ci.yml, cli/src/templates/github/dependabot.yml, cli/src/templates/github/BRANCH_PROTECTION.md, .github/dependabot.yml
New GitHub Actions workflow template for CI (lint/build/test), Dependabot config for npm/cargo/GitHub Actions, and branch protection guide; root-level .github/dependabot.yml enabling automated dependency updates for framework/blueprint/cli/actions.
Package Updates
blueprint/*/package.json, framework/*/package.json, cli/Cargo.toml (implied via constants), blueprint/implementations/*/package.json
Version bumps: @forklaunch/* packages from ^0.x to ^1.1.0, MikroORM 7.0.47.0.5, TypeScript ^5.9.3^6.0.2, dev tooling (typedoc, typescript-eslint, vitest) incremented; build script changed to tsgo -b and clean script now removes tsconfig.tsbuildinfo.
Test Coverage
framework/core/__test__/compliance.test.ts, framework/core/__test__/compliance.typetest.ts, framework/core/__test__/complianceEventSubscriber.test.ts, framework/core/__test__/fieldEncryptor.test.ts, framework/core/__test__/rateLimiter.test.ts, framework/core/__test__/tenantContext.test.ts, framework/core/__test__/tenantFilter.test.ts, framework/ws/src/__tests__/channels.test.ts
New comprehensive test suites covering compliance metadata registration, field encryption/decryption, event subscriber behavior, rate limiting, tenant filtering, and WebSocket channel management.
Documentation
COMPLIANCE_COVERAGE.md, COMPLIANCE_GAPS_PLAN.md, compliance-coverage.html
New compliance reporting documents: coverage summary (41 requirements across HIPAA/SOC2/PCI/GDPR with 32 fully addressed), execution plan for Phase 2 gaps (GDPR endpoints, CI gating, data-flow diagrams, risk scoring, DPIA generation), and HTML-rendered compliance report.
WebSocket Security
framework/ws/src/wsSession.ts, framework/ws/src/secureWebSocketServer.ts, framework/ws/src/channels.ts
New WebSocket session/security/channel infrastructure: session context interface with user/tenant/roles/permissions, secure server with handshake authentication and session revalidation, channel manager for scoped message broadcasting with permission checks.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Router
    participant TenantMiddleware
    participant ComplianceSubscriber
    participant FieldEncryptor
    participant Database

    Client->>Router: POST /api/users (access: 'protected')
    Router->>TenantMiddleware: setTenantContext
    TenantMiddleware->>Router: Set tenant filter params
    Router->>ComplianceSubscriber: beforeCreate event
    ComplianceSubscriber->>FieldEncryptor: encrypt phi/pci fields
    FieldEncryptor->>FieldEncryptor: Derive tenant key from tenantId
    FieldEncryptor->>ComplianceSubscriber: Return v1:encrypted
    ComplianceSubscriber->>Database: em.create() with encrypted fields
    Database->>Database: Store with tenant filter active
    Database-->>Client: 201 Created
Loading
sequenceDiagram
    participant CLI
    participant ManifestScanner
    participant EntityComplianceScanner
    participant Manifest
    participant AuditCommand
    participant OpenAPI

    CLI->>AuditCommand: forklaunch compliance audit
    AuditCommand->>Manifest: Load manifest.toml
    AuditCommand->>EntityComplianceScanner: Scan entity compliance
    EntityComplianceScanner->>EntityComplianceScanner: Parse .entity.ts AST
    EntityComplianceScanner-->>AuditCommand: {entity→{field→level}}
    AuditCommand->>OpenAPI: Scan openapi.json files
    OpenAPI-->>AuditCommand: {route→{method, access}}
    AuditCommand->>AuditCommand: Build ComplianceReport
    AuditCommand-->>CLI: JSON/HTML/Upload to platform
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

This PR introduces a pervasive compliance framework touching framework core, all blueprint modules, CLI infrastructure, and test suites. Changes are heterogeneous (entity migrations, new services, encryption, routing, retention, auditing) and logic-dense (encryption key derivation, compliance metadata extraction, retention batch processing). Review requires understanding the new compliance architecture, validating migration consistency across 50+ entity files, and assessing correctness of encryption/retention/filtering implementations.

Possibly related PRs

  • chore: mikroorm v7 migration #122: Overlapping persistence/entity migrations affecting MikroORM configuration and entity definition patterns; both PRs modify the same entity files and mapping infrastructure.
  • fix: NPM updates cause broken types #119: CLI infrastructure changes including package constants and project script generation; both PRs update cli/src/core/package_json/* and template-based script scaffolding.

Poem

🐰 Compliance hops into the frame,
With encryption and retention aflame,
Entities now tagged with care,
PHI and PCI protected with flair,
The framework bounds with new acclaim! 🔐✨

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rohin/compliance-security

@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.

Actionable comments posted: 5

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
blueprint/iam-base/api/controllers/user.controller.ts (1)

190-201: ⚠️ Potential issue | 🟡 Minor

Inconsistent field name and permissions for write operations.

The update and delete handlers use allowedRoles: PLATFORM_READ_PERMISSIONS (lines 200, 252, 306, 363), while read operations use allowedPermissions: PLATFORM_READ_PERMISSIONS (lines 120, 159). This creates two issues:

  1. Inconsistent field names (allowedRoles vs allowedPermissions)
  2. Using read permissions for write operations is semantically incorrect

Update and delete should use allowedPermissions: PLATFORM_WRITE_PERMISSIONS to match the permission model used elsewhere and to properly express the required access level.

Suggested fix
     auth: {
       sessionSchema: {
         organizationId: string
       },
       jwt: {
         jwksPublicKeyUrl: JWKS_PUBLIC_KEY_URL
       },
       decodeResource: decodeResourceWithOrganizationId,
-      allowedRoles: PLATFORM_READ_PERMISSIONS
+      allowedPermissions: PLATFORM_WRITE_PERMISSIONS
     },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/iam-base/api/controllers/user.controller.ts` around lines 190 -
201, The auth config on the update and delete handlers uses the wrong field name
and permission constant; locate the auth object in the user controller handlers
(the blocks that include decodeResourceWithOrganizationId and jwksPublicKeyUrl)
and replace allowedRoles: PLATFORM_READ_PERMISSIONS with allowedPermissions:
PLATFORM_WRITE_PERMISSIONS so the handlers use the same allowedPermissions field
as reads but with the correct write-level permission constant.
🟡 Minor comments (29)
framework/bunrun/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Fix malformed changelog bullet text.

Line 7 has an unmatched trailing quote (patch working"), which reads like an accidental typo in release notes.

✍️ Proposed fix
-- patch working"
+- patch working
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/bunrun/CHANGELOG.md` at line 7, The changelog contains a stray
trailing quote in the bullet text "patch working\"" on line with the diff; open
framework/bunrun/CHANGELOG.md, locate the bullet text "patch working\"" and
remove the unmatched trailing quote so the entry reads consistently (e.g., "-
patch working" or "- patch: working") and ensure the bullet formatting matches
other entries in the file.
framework/infrastructure/redis/CHANGELOG.md-7-10 (1)

7-10: ⚠️ Potential issue | 🟡 Minor

Clean up malformed and duplicated changelog bullets.

Line 7 has a stray quote, and Lines 81-83 duplicate the same dependency heading.

✏️ Proposed cleanup
-- patch working"
+- patch working
@@
 - fix compliance brands
 - Updated dependencies
-- Updated dependencies
   - `@forklaunch/common`@1.0.5
   - `@forklaunch/core`@1.0.5

Also applies to: 81-84

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/infrastructure/redis/CHANGELOG.md` around lines 7 - 10, Remove the
stray quotation mark from the malformed bullet "- patch working"" and normalize
the bullet to "- patch working" in CHANGELOG.md; then locate the duplicated
dependency heading block that repeats "@forklaunch/[email protected]" /
"@forklaunch/[email protected]" (the duplicate block around the second occurrence) and
remove the redundant copy so each dependency entry appears only once, ensuring
consistent bullet indentation and formatting for the remaining entries.
framework/internal/CHANGELOG.md-7-10 (1)

7-10: ⚠️ Potential issue | 🟡 Minor

Resolve malformed and duplicated changelog entries.

Line 7 has a trailing ", and Lines 81-82 repeat the same dependency heading.

✏️ Proposed cleanup
-- patch working"
+- patch working
@@
 - fix compliance brands
 - Updated dependencies
-- Updated dependencies
   - `@forklaunch/validator`@1.0.5
   - `@forklaunch/common`@1.0.5

Also applies to: 81-84

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/internal/CHANGELOG.md` around lines 7 - 10, Remove the stray
trailing double-quote in the "patch working"" entry and normalize the changelog
entries so the dependency block is properly formatted (remove the lone quote and
ensure the "Updated dependencies" heading appears only once); also deduplicate
the repeated dependency heading/entries around the later block (the duplicated
"@forklaunch/[email protected]" and "@forklaunch/[email protected]" listing) so each
dependency appears a single time under one "Updated dependencies" heading.
framework/ws/CHANGELOG.md-7-11 (1)

7-11: ⚠️ Potential issue | 🟡 Minor

Please correct malformed and duplicate changelog bullets.

Line 7 has a trailing quote, and Lines 89-90 duplicate - Updated dependencies.

✏️ Proposed cleanup
-- patch working"
+- patch working
@@
 - fix compliance brands
 - Updated dependencies
-- Updated dependencies
   - `@forklaunch/validator`@1.0.5
   - `@forklaunch/common`@1.0.5
   - `@forklaunch/core`@1.0.5

Also applies to: 89-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/ws/CHANGELOG.md` around lines 7 - 11, Remove the stray trailing
quote from the "patch working" bullet and normalize the bullet formatting, then
remove the duplicated "- Updated dependencies" header (and consolidate its
listed packages) so each dependency update appears once; locate the bullets in
CHANGELOG.md around the "patch working" entry and the repeated "- Updated
dependencies" sections (including the one around lines 89-93) and edit them to
ensure no duplicate headers and consistent hyphenation/indentation.
framework/express/CHANGELOG.md-7-11 (1)

7-11: ⚠️ Potential issue | 🟡 Minor

Fix malformed and duplicated changelog items.

Line 7 includes a trailing ", and Lines 89-90 repeat - Updated dependencies.

✏️ Proposed cleanup
-- patch working"
+- patch working
@@
 - fix compliance brands
 - Updated dependencies
-- Updated dependencies
   - `@forklaunch/validator`@1.0.5
   - `@forklaunch/common`@1.0.5
   - `@forklaunch/core`@1.0.5

Also applies to: 89-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/express/CHANGELOG.md` around lines 7 - 11, Fix the malformed
changelog entry "- patch working\"" by removing the stray trailing quote and
correct the duplicated " - Updated dependencies" section by merging or removing
the repeated block (ensure the dependency list contains a single "Updated
dependencies" header followed by the three package lines
`@forklaunch/validator`@1.0.13, `@forklaunch/common`@1.0.13,
`@forklaunch/core`@1.0.13); update the corresponding duplicate lines around the
second occurrence (the repeated "- Updated dependencies" and its package lines)
so the CHANGELOG has one consistent, correctly formatted dependencies update
entry.
framework/testing/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Fix the malformed patch note text.

Line 7 has a trailing quote in patch working".

✏️ Proposed cleanup
-- patch working"
+- patch working
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/testing/CHANGELOG.md` at line 7, Fix the malformed changelog entry:
remove the stray trailing double-quote from the text "patch working\"" on the
changelog line (so it reads patch working or wrap it properly in quotes if
intended), ensuring the line no longer contains the extraneous quote character.
framework/common/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Correct the typo in the patch note text.

Line 7 has an extra trailing quote, which should be removed.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/common/CHANGELOG.md` at line 7, Remove the stray trailing double
quote from the patch note text that currently reads "patch working\" in
CHANGELOG.md; edit the line in the file so it reads patch working without the
extra quote to correct the typo.
framework/universal-sdk/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Fix malformed changelog bullet text.

Line 7 has an extra trailing quote (patch working"), which makes the release note look accidental.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/universal-sdk/CHANGELOG.md` at line 7, Remove the stray trailing
double-quote from the malformed changelog bullet in CHANGELOG.md (the line
currently reading `patch working"`), updating it to a valid bullet (e.g., `patch
working`) so the release note text is no longer accidentally quoted; ensure the
file uses consistent bullet formatting as other entries.
framework/universal-sdk/CHANGELOG.md-73-75 (1)

73-75: ⚠️ Potential issue | 🟡 Minor

Remove duplicated “Updated dependencies” bullet.

Lines 73-75 repeat the same bullet label, which creates noisy release notes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/universal-sdk/CHANGELOG.md` around lines 73 - 75, Remove the
duplicated "Updated dependencies" bullet in CHANGELOG.md so the release notes
only show a single "Updated dependencies" header followed by the sub-item "-
`@forklaunch/common`@1.0.5"; specifically delete the extra top-level "Updated
dependencies" line and ensure the remaining header correctly precedes the
dependency list.
blueprint/interfaces/iam/package.json-34-34 (1)

34-34: ⚠️ Potential issue | 🟡 Minor

Correct the lockfile path in cleanup script.

Line 34 uses pnpm.lock.yaml; this should be pnpm-lock.yaml for pnpm lockfile cleanup.

Suggested patch
-    "clean": "rm -rf lib tsconfig.tsbuildinfo pnpm.lock.yaml node_modules",
+    "clean": "rm -rf lib tsconfig.tsbuildinfo pnpm-lock.yaml node_modules",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/interfaces/iam/package.json` at line 34, The cleanup script named
"clean" in package.json references the wrong pnpm lockfile name; update the
script value for "clean" to remove pnpm-lock.yaml (hyphenated) instead of
pnpm.lock.yaml. Locate the "clean" script entry in package.json and replace the
token "pnpm.lock.yaml" with "pnpm-lock.yaml" so the rm command targets the
correct pnpm lockfile name.
blueprint/interfaces/billing/package.json-35-35 (1)

35-35: ⚠️ Potential issue | 🟡 Minor

Fix lockfile name in clean script.

Line 35 uses pnpm.lock.yaml, but pnpm’s lockfile is pnpm-lock.yaml. Current script won’t remove the intended file.

Suggested patch
-    "clean": "rm -rf lib tsconfig.tsbuildinfo pnpm.lock.yaml node_modules",
+    "clean": "rm -rf lib tsconfig.tsbuildinfo pnpm-lock.yaml node_modules",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/interfaces/billing/package.json` at line 35, The "clean" script in
package.json currently targets the wrong lockfile name ("pnpm.lock.yaml");
update the "clean" npm script value (the "clean" entry) to remove
"pnpm-lock.yaml" instead of "pnpm.lock.yaml" so the command deletes the actual
pnpm lockfile.
framework/hyper-express/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Typographical error: extra quotation mark.

The changelog entry has a trailing quotation mark that appears unintentional.

✏️ Suggested fix
-- patch working"
+- patch working
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/hyper-express/CHANGELOG.md` at line 7, The changelog line contains
an extra trailing quotation mark in the entry "- patch working\"", so remove the
stray quote to make the line "- patch working" (locate and edit the line in
CHANGELOG.md that currently reads with the trailing quote and delete the extra
character).
framework/testing/package.json-56-59 (1)

56-59: ⚠️ Potential issue | 🟡 Minor

Peer dependency version mismatch with devDependency.

The peerDependencies specifies vitest: "^3.0.0" while devDependencies uses vitest: "^4.1.1". This mismatch could cause confusion for consumers. Consider updating the peer dependency to ^4.0.0 to align with the version used for development and testing.

💡 Suggested fix
   "peerDependencies": {
-    "vitest": "^3.0.0"
+    "vitest": "^4.0.0"
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/testing/package.json` around lines 56 - 59, The peerDependencies
entry for "vitest" is pinned to "^3.0.0" while devDependencies uses "vitest":
"^4.1.1", causing a version mismatch; update the peerDependencies "vitest" range
to "^4.0.0" (or a compatible ^4.x range) so consumers and the development
environment align, ensuring the change is made where the "peerDependencies"
object lists "vitest" and confirmed against the "devDependencies" entry.
framework/hyper-express/CHANGELOG.md-97-99 (1)

97-99: ⚠️ Potential issue | 🟡 Minor

Duplicate "Updated dependencies" bullet.

There are two consecutive "Updated dependencies" entries which appears to be a copy-paste error.

✏️ Suggested fix
 - entity rework
 - fix compliance brands
-- Updated dependencies
 - Updated dependencies
   - `@forklaunch/validator`@1.0.5
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/hyper-express/CHANGELOG.md` around lines 97 - 99, Remove the
duplicate "Updated dependencies" bullet: keep a single "Updated dependencies"
entry and nest the package line "- `@forklaunch/validator`@1.0.5" under it,
deleting the redundant second "Updated dependencies" line so the changelog only
lists that heading once.
framework/infrastructure/S3/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Fix release-note typos/duplication in new changelog entries.

Line 7 has a stray trailing quote, and Line 82 duplicates the “Updated dependencies” bullet.

Suggested patch
-- patch working"
+- patch working
...
-- Updated dependencies
 - Updated dependencies
   - `@forklaunch/common`@1.0.5
   - `@forklaunch/core`@1.0.5

Also applies to: 82-82

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/infrastructure/S3/CHANGELOG.md` at line 7, Remove the stray
trailing quote from the changelog entry that currently reads 'patch working"'
(fix the string to 'patch working' or the intended text) and delete the
duplicated "Updated dependencies" bullet that appears later in the file (the
duplicate at the second occurrence of that bullet, around the entry referenced
as line 82). Ensure only one correctly-worded "Updated dependencies" bullet
remains and that no extra quotation marks remain in other entries.
blueprint/implementations/iam/base/package.json-63-63 (1)

63-63: ⚠️ Potential issue | 🟡 Minor

Inconsistent @typescript/native-preview version across packages.

This package uses 7.0.0-dev.20260320.1 while framework/core and framework/express use 7.0.0-dev.20260301.1. Consider aligning versions across all packages to avoid potential build inconsistencies.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/implementations/iam/base/package.json` at line 63, The
`@typescript/native-preview` dev dependency in package.json is out of sync with
other packages; update the version string for "@typescript/native-preview" in
blueprint/implementations/iam/base/package.json to match the canonical version
used by framework/core and framework/express (change "7.0.0-dev.20260320.1" to
"7.0.0-dev.20260301.1" or vice versa depending on the desired canonical
version), ensure only one agreed version is used across all package.json files,
and run a quick install/build to verify no compatibility errors; locate the
dependency by the key "@typescript/native-preview" in package.json to make the
change.
blueprint/implementations/billing/stripe/package.json-70-70 (1)

70-70: ⚠️ Potential issue | 🟡 Minor

Same @typescript/native-preview version inconsistency.

This package also uses 7.0.0-dev.20260320.1, differing from framework/core and framework/express. See the comment on blueprint/implementations/iam/base/package.json for the same issue.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/implementations/billing/stripe/package.json` at line 70, The
`@typescript/native-preview` dependency in this package.json is pinned to
7.0.0-dev.20260320.1 which differs from the version used in the other packages;
update the "@typescript/native-preview" entry in this package's package.json to
match the exact version used by framework/core and framework/express
package.json entries, then refresh the lockfile (npm/yarn/pnpm) so all packages
use a consistent version; verify no other package.json files still differ (see
the IAM/base package.json comment for the same inconsistency).
framework/validator/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Fix typo in changelog entry.

The entry - patch working" appears to have an extra trailing quote and inconsistent capitalization compared to other entries.

📝 Suggested fix
-- patch working"
+- Patch working
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/validator/CHANGELOG.md` at line 7, Replace the malformed changelog
entry by locating the string "- patch working\"" and removing the stray trailing
quote and fixing capitalization to match other entries (change to "- Patch
working"); update the line in CHANGELOG.md accordingly so it reads exactly "-
Patch working".
framework/validator/CHANGELOG.md-73-75 (1)

73-75: ⚠️ Potential issue | 🟡 Minor

Remove duplicate "Updated dependencies" entry.

There are two consecutive "Updated dependencies" bullet points, which appears to be a copy/paste error.

📝 Suggested fix
 - entity rework
 - fix compliance brands
 - Updated dependencies
-- Updated dependencies
   - `@forklaunch/common`@1.0.5
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/validator/CHANGELOG.md` around lines 73 - 75, Remove the duplicate
"Updated dependencies" bullet in the CHANGELOG entry: keep a single "Updated
dependencies" heading and ensure the sub-bullet "- `@forklaunch/common`@1.0.5"
remains under it; update the block in CHANGELOG.md so there is only one "Updated
dependencies" line followed by the dependency list.
framework/core/package.json-129-129 (1)

129-129: ⚠️ Potential issue | 🟡 Minor

Update @typescript/native-preview to a current version.

The version was changed to 7.0.0-dev.20260301.1 (March 1, 2026), which is 19 days older than the previous 7.0.0-dev.20260320.1 and does not appear in recent npm releases. Current available versions are dated March 15–24, 2026. Either use 7.0.0-dev.20260320.1 or a newer version from the available releases.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/package.json` at line 129, Update the
`@typescript/native-preview` dependency in package.json: replace the pinned
version "7.0.0-dev.20260301.1" with a current release (e.g.,
"7.0.0-dev.20260320.1" or any newer version from the March 15–24, 2026 releases)
so the project uses a valid, up-to-date package; ensure the change is made to
the dependency entry for "@typescript/native-preview" and run your package
manager to verify the lockfile and install.
framework/core/CHANGELOG.md-7-7 (1)

7-7: ⚠️ Potential issue | 🟡 Minor

Fix typo in changelog entry.

The text patch working" appears to have a stray quotation mark and unclear phrasing.

📝 Suggested fix
-- patch working"
+- Patch working
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/CHANGELOG.md` at line 7, The changelog entry contains a stray
quotation mark in the line containing the text 'patch working"'; remove the
trailing quote and clarify the phrasing to a proper changelog entry (e.g.,
capitalize and add punctuation or a descriptor like "Patch: working" or "Patch -
working") so the line reads cleanly without the extra character and conveys
intent clearly.
framework/core/CHANGELOG.md-81-82 (1)

81-82: ⚠️ Potential issue | 🟡 Minor

Remove duplicate "Updated dependencies" entry.

There are two consecutive - Updated dependencies bullets in the 1.0.5 section.

📝 Suggested fix
 - entity rework
 - fix compliance brands
-- Updated dependencies
 - Updated dependencies
   - `@forklaunch/validator`@1.0.5
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/CHANGELOG.md` around lines 81 - 82, In the 1.0.5 changelog
section there are two identical bullets "- Updated dependencies"; remove the
duplicate so only a single "- Updated dependencies" entry remains in the 1.0.5
section (ensure you edit the CHANGELOG.md entry for version label "1.0.5" and
delete the extra "- Updated dependencies" line).
blueprint/billing-stripe/persistence/entities/checkoutSession.entity.ts-21-21 (1)

21-21: ⚠️ Potential issue | 🟡 Minor

Inconsistency: uri field missing unique() and nullable() modifiers.

The base CheckoutSession entity in blueprint/billing-base/persistence/entities/checkoutSession.entity.ts (lines 7-24 in relevant snippets) defines uri as:

uri: fp.string().unique().nullable().compliance('none')

However, this Stripe-specific implementation defines it as:

uri: fp.string().compliance('none')

This inconsistency could cause database schema mismatches or constraint violations.

🔧 Suggested fix
-    uri: fp.string().compliance('none'),
+    uri: fp.string().unique().nullable().compliance('none'),
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/billing-stripe/persistence/entities/checkoutSession.entity.ts` at
line 21, The `uri` field in the Stripe-specific CheckoutSession entity is
missing the `unique()` and `nullable()` modifiers which creates a schema
mismatch with the base CheckoutSession entity; update the `uri` definition in
checkoutSession.entity.ts (the `uri: fp.string().compliance('none')` line) to
include `.unique().nullable()` in the fp.string() chain so it matches the base
entity's `uri` signature.
blueprint/iam-better-auth/persistence/entities/invitation.entity.ts-9-10 (1)

9-10: ⚠️ Potential issue | 🟡 Minor

Change email field compliance to 'pii'.

The email field should be classified as .compliance('pii'), not 'none'. The framework's own test cases and documentation consistently use compliance('pii') for email fields (see framework/core/__test__/compliance.typetest.ts and compliancePropertyBuilder.ts), and email addresses are universally recognized as PII. This should be updated to align with both the framework pattern and data protection requirements.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/iam-better-auth/persistence/entities/invitation.entity.ts` around
lines 9 - 10, The email field currently uses fp.string().compliance('none');
change it to fp.string().compliance('pii') so the invitation entity aligns with
framework tests and PII handling; locate the email property in the Invitation
entity (next to organizationId: fp.string().compliance('none')) and replace the
compliance('none') call with compliance('pii') while leaving other validators
unchanged.
blueprint/iam-base/persistence/entities/organization.entity.ts-15-15 (1)

15-15: ⚠️ Potential issue | 🟡 Minor

Document the compliance classification for providerFields or update if necessary.

The providerFields field is marked as compliance('none'), but this pattern appears across the codebase in billing entities that store actual Stripe objects (BillingPortal.Session, Subscription, Product, etc.). Currently, the Organization entity stores only null values, so there's no immediate risk. However, the codebase lacks documentation explaining why external provider data is classified as 'none'.

Either document the design rationale (e.g., provider compliance responsibility is delegated to the service like Stripe), or verify whether 'pci' or 'pii' classification should be applied consistently if real provider data will be stored here in the future.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/iam-base/persistence/entities/organization.entity.ts` at line 15,
The providerFields property on the Organization entity is annotated with
compliance('none') but lacks justification; update the Organization entity's
providerFields documentation or classification: either add a clear comment near
providerFields explaining the design decision that external provider data is not
stored here (or that provider systems like Stripe are responsible for
compliance), or change the compliance annotation to the appropriate level (e.g.,
'pii' or 'pci') if you intend to persist real provider objects; locate the field
named providerFields in organization.entity.ts and modify the inline comment or
the fp.json().nullable().compliance('none') call accordingly to reflect the
chosen policy.
docs/COMPLIANCE_FRAMEWORK_PLAN.md-873-881 (1)

873-881: ⚠️ Potential issue | 🟡 Minor

Example shows different method chain order than actual implementation.

The example shows .compliance('none') called before .primary() and .onCreate():

id: fp.uuid().compliance('none').primary().onCreate(() => v4()),

But the actual implementation in blueprint/core/persistence/sql.base.properties.ts (per relevant snippets) uses:

id: fp.uuid().primary().onCreate(() => v4()).compliance('none'),

While both may work if the Proxy properly propagates compliance through the chain, the documentation should match the actual implementation to avoid confusion.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/COMPLIANCE_FRAMEWORK_PLAN.md` around lines 873 - 881, The docs example
for sqlBaseProperties shows
fp.uuid().compliance('none').primary().onCreate(...), but the real
implementation uses fp.uuid().primary().onCreate(() => v4()).compliance('none');
update the example in docs/COMPLIANCE_FRAMEWORK_PLAN.md so the id, createdAt,
and updatedAt property chains match the actual implementation ordering (e.g.,
call .primary() and .onCreate()/.onUpdate() before .compliance('none')) and keep
the same function symbols (sqlBaseProperties, fp.uuid(), createdAt, updatedAt)
so the example aligns exactly with
blueprint/core/persistence/sql.base.properties.ts.
docs/PLATFORM_HANDOFF.md-76-80 (1)

76-80: ⚠️ Potential issue | 🟡 Minor

Potential incorrect compliance classification for taxId.

The example shows taxId = "pci", but PCI DSS specifically covers cardholder data (credit card numbers, CVV, etc.), not tax identification numbers. Tax IDs would typically be classified as "pii" (personally identifiable information) rather than "pci".

Suggested fix
 [compliance.entities.Organization]
 id = "none"
 name = "none"
-taxId = "pci"
+taxId = "pii"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/PLATFORM_HANDOFF.md` around lines 76 - 80, The example in
compliance.entities.Organization sets taxId = "pci" which is incorrect; change
the classification for the taxId field from "pci" to "pii" (or another
appropriate PII category) so the taxId is correctly labeled as personally
identifiable information; update the example entry (the taxId attribute) to
taxId = "pii" and keep the rest of the Organization example unchanged.
docs/COMPLIANCE_FRAMEWORK_PLAN.md-798-803 (1)

798-803: ⚠️ Potential issue | 🟡 Minor

Same taxId classification issue as PLATFORM_HANDOFF.md.

Tax IDs are typically PII, not PCI. PCI DSS specifically covers cardholder data.

Suggested fix
 [compliance.entities.Organization]
 ...
-taxId = "pci"
+taxId = "pii"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/COMPLIANCE_FRAMEWORK_PLAN.md` around lines 798 - 803, Update the
classification for the taxId field from PCI to PII in the manifest and any
related documentation: locate the TOML table [compliance.entities.User] under
the "Store classification in manifest" section and change taxId's value to "pii"
(and ensure any other occurrences in PLATFORM_HANDOFF.md or similar docs reflect
the same change), keeping email/name classifications as-is so tax IDs are
correctly treated as PII rather than PCI.
framework/core/src/encryption/fieldEncryptor.ts-78-78 (1)

78-78: ⚠️ Potential issue | 🟡 Minor

Empty tenantId defaults to shared key derivation.

When tenantId is omitted or empty, deriveKey(tenantId ?? '') derives the same key for all callers. This could inadvertently allow cross-tenant decryption if compliance fields are encrypted without proper tenant context. Consider throwing EncryptionRequiredError when tenantId is missing for compliance-sensitive operations, or document this behavior explicitly.

Also applies to: 117-117

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/src/encryption/fieldEncryptor.ts` at line 78, The current call
to deriveKey(tenantId ?? '') allows empty tenantId to fall back to a shared key;
change this by validating tenantId before key derivation and either throw an
EncryptionRequiredError when tenantId is missing for compliance-sensitive
operations (e.g., in the methods that call deriveKey such as the encrypt/decrypt
flows where tenant context is required) or explicitly document that empty
tenantId will use a shared key; specifically, update the code paths that call
deriveKey(tenantId ?? '') to check if tenantId is falsy and throw
EncryptionRequiredError (or use documented fallback logic) so cross-tenant
decryption cannot occur unintentionally.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bf1d8fa7-c098-42e6-b187-dbd06f37c12b

📥 Commits

Reviewing files that changed from the base of the PR and between e405948 and 452e99b.

⛔ Files ignored due to path filters (3)
  • blueprint/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • framework/core/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • framework/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (180)
  • blueprint/billing-base/api/controllers/billingPortal.controller.ts
  • blueprint/billing-base/api/controllers/checkoutSession.controller.ts
  • blueprint/billing-base/api/controllers/paymentLink.controller.ts
  • blueprint/billing-base/api/controllers/plan.controller.ts
  • blueprint/billing-base/api/controllers/subscription.controller.ts
  • blueprint/billing-base/package.json
  • blueprint/billing-base/persistence/entities/billingPortal.entity.ts
  • blueprint/billing-base/persistence/entities/billingProvider.entity.ts
  • blueprint/billing-base/persistence/entities/checkoutSession.entity.ts
  • blueprint/billing-base/persistence/entities/paymentLink.entity.ts
  • blueprint/billing-base/persistence/entities/plan.entity.ts
  • blueprint/billing-base/persistence/entities/subscription.entity.ts
  • blueprint/billing-stripe/api/controllers/billingPortal.controller.ts
  • blueprint/billing-stripe/api/controllers/checkoutSession.controller.ts
  • blueprint/billing-stripe/api/controllers/paymentLink.controller.ts
  • blueprint/billing-stripe/api/controllers/plan.controller.ts
  • blueprint/billing-stripe/api/controllers/subscription.controller.ts
  • blueprint/billing-stripe/api/controllers/webhook.controller.ts
  • blueprint/billing-stripe/package.json
  • blueprint/billing-stripe/persistence/entities/billingPortal.entity.ts
  • blueprint/billing-stripe/persistence/entities/checkoutSession.entity.ts
  • blueprint/billing-stripe/persistence/entities/paymentLink.entity.ts
  • blueprint/billing-stripe/persistence/entities/plan.entity.ts
  • blueprint/billing-stripe/persistence/entities/stripeWebhookEvent.entity.ts
  • blueprint/billing-stripe/persistence/entities/subscription.entity.ts
  • blueprint/client-sdk/package.json
  • blueprint/core/package.json
  • blueprint/core/persistence/nosql.base.properties.ts
  • blueprint/core/persistence/sql.base.properties.ts
  • blueprint/iam-base/api/controllers/discovery.controller.ts
  • blueprint/iam-base/api/controllers/organization.controller.ts
  • blueprint/iam-base/api/controllers/permission.controller.ts
  • blueprint/iam-base/api/controllers/role.controller.ts
  • blueprint/iam-base/api/controllers/user.controller.ts
  • blueprint/iam-base/package.json
  • blueprint/iam-base/persistence/entities/organization.entity.ts
  • blueprint/iam-base/persistence/entities/permission.entity.ts
  • blueprint/iam-base/persistence/entities/role.entity.ts
  • blueprint/iam-base/persistence/entities/user.entity.ts
  • blueprint/iam-better-auth/api/controllers/discovery.controller.ts
  • blueprint/iam-better-auth/api/controllers/user.controller.ts
  • blueprint/iam-better-auth/package.json
  • blueprint/iam-better-auth/persistence/entities/account.entity.ts
  • blueprint/iam-better-auth/persistence/entities/invitation.entity.ts
  • blueprint/iam-better-auth/persistence/entities/jwks.entity.ts
  • blueprint/iam-better-auth/persistence/entities/member.entity.ts
  • blueprint/iam-better-auth/persistence/entities/organization.entity.ts
  • blueprint/iam-better-auth/persistence/entities/organizationRole.entity.ts
  • blueprint/iam-better-auth/persistence/entities/session.entity.ts
  • blueprint/iam-better-auth/persistence/entities/team.entity.ts
  • blueprint/iam-better-auth/persistence/entities/teamMember.entity.ts
  • blueprint/iam-better-auth/persistence/entities/user.entity.ts
  • blueprint/iam-better-auth/persistence/entities/verification.entity.ts
  • blueprint/implementations/billing/base/CHANGELOG.md
  • blueprint/implementations/billing/base/package.json
  • blueprint/implementations/billing/base/persistence/entities/index.ts
  • blueprint/implementations/billing/stripe/CHANGELOG.md
  • blueprint/implementations/billing/stripe/package.json
  • blueprint/implementations/billing/stripe/persistence/entities/index.ts
  • blueprint/implementations/billing/stripe/services/webhook.service.ts
  • blueprint/implementations/iam/base/CHANGELOG.md
  • blueprint/implementations/iam/base/package.json
  • blueprint/implementations/iam/base/persistence/entities/index.ts
  • blueprint/implementations/worker/bullmq/CHANGELOG.md
  • blueprint/implementations/worker/bullmq/package.json
  • blueprint/implementations/worker/database/CHANGELOG.md
  • blueprint/implementations/worker/database/package.json
  • blueprint/implementations/worker/kafka/CHANGELOG.md
  • blueprint/implementations/worker/kafka/package.json
  • blueprint/implementations/worker/redis/CHANGELOG.md
  • blueprint/implementations/worker/redis/package.json
  • blueprint/interfaces/billing/CHANGELOG.md
  • blueprint/interfaces/billing/package.json
  • blueprint/interfaces/iam/CHANGELOG.md
  • blueprint/interfaces/iam/package.json
  • blueprint/interfaces/worker/CHANGELOG.md
  • blueprint/interfaces/worker/package.json
  • blueprint/monitoring/package.json
  • blueprint/package.json
  • blueprint/sample-worker/api/controllers/sampleWorker.controller.ts
  • blueprint/sample-worker/package.json
  • blueprint/sample-worker/persistence/entities/sampleWorkerRecord.entity.ts
  • blueprint/tsconfig.base.json
  • cli/src/compliance/audit.rs
  • cli/src/compliance/mod.rs
  • cli/src/core/env_defaults.rs
  • cli/src/core/env_scope.rs
  • cli/src/core/manifest.rs
  • cli/src/core/package_json/package_json_constants.rs
  • cli/src/init/application.rs
  • cli/src/init/library.rs
  • cli/src/init/module.rs
  • cli/src/init/service.rs
  • cli/src/init/worker.rs
  • cli/src/main.rs
  • cli/src/release/create.rs
  • cli/src/templates/router/persistence/entities/{{camel_case_name}}Record.entity.ts
  • docs/COMPLIANCE_FRAMEWORK_PLAN.md
  • docs/PLATFORM_HANDOFF.md
  • framework/bunrun/CHANGELOG.md
  • framework/bunrun/package.json
  • framework/common/CHANGELOG.md
  • framework/common/package.json
  • framework/core/CHANGELOG.md
  • framework/core/__test__/auditLogger.test.ts
  • framework/core/__test__/baseEntity.partialUpdate.integration.test.ts
  • framework/core/__test__/compliance.test.ts
  • framework/core/__test__/compliance.typetest.ts
  • framework/core/__test__/complianceEventSubscriber.test.ts
  • framework/core/__test__/configInjector.test.ts
  • framework/core/__test__/contractDetails.types.test.ts
  • framework/core/__test__/expressLikeRouterInstantiation.test.ts
  • framework/core/__test__/fieldEncryptor.test.ts
  • framework/core/__test__/http.middleware.test.ts
  • framework/core/__test__/mcpGenerator.test.ts
  • framework/core/__test__/openApiV3Generator.test.ts
  • framework/core/__test__/rateLimiter.test.ts
  • framework/core/__test__/rls.test.ts
  • framework/core/__test__/secretsAccessor.test.ts
  • framework/core/__test__/tenantContext.test.ts
  • framework/core/__test__/tenantFilter.test.ts
  • framework/core/package.json
  • framework/core/src/encryption/fieldEncryptor.ts
  • framework/core/src/encryption/index.ts
  • framework/core/src/http/index.ts
  • framework/core/src/http/middleware/request/tenantContext.middleware.ts
  • framework/core/src/http/rateLimit/index.ts
  • framework/core/src/http/rateLimit/rateLimiter.ts
  • framework/core/src/http/router/routerSharedLogic.ts
  • framework/core/src/http/telemetry/auditLogger.ts
  • framework/core/src/http/types/contractDetails.types.ts
  • framework/core/src/persistence/complianceEventSubscriber.ts
  • framework/core/src/persistence/compliancePropertyBuilder.ts
  • framework/core/src/persistence/complianceTypes.ts
  • framework/core/src/persistence/defineComplianceEntity.ts
  • framework/core/src/persistence/index.ts
  • framework/core/src/persistence/rls.ts
  • framework/core/src/persistence/tenantFilter.ts
  • framework/core/src/secrets/index.ts
  • framework/core/src/secrets/secretsAccessor.ts
  • framework/core/tsconfig.json
  • framework/e2e-tests/package.json
  • framework/e2e-tests/servers/express-typebox.ts
  • framework/e2e-tests/servers/express-zod-cluster.ts
  • framework/e2e-tests/servers/express-zod-raw.ts
  • framework/e2e-tests/servers/express-zod.ts
  • framework/e2e-tests/servers/hyper-express-typebox.ts
  • framework/e2e-tests/servers/hyper-express-zod-cluster.ts
  • framework/e2e-tests/servers/hyper-express-zod.ts
  • framework/e2e-tests/servers/vanilla-express-router.ts
  • framework/express/CHANGELOG.md
  • framework/express/__test__/port.test.ts
  • framework/express/__test__/typebox.forklaunch.express.test.ts
  • framework/express/__test__/zod.forklaunch.express.test.ts
  • framework/express/package.json
  • framework/hyper-express/CHANGELOG.md
  • framework/hyper-express/__test__/port.test.ts
  • framework/hyper-express/__test__/typebox.forklaunch.hyperExpress.test.ts
  • framework/hyper-express/__test__/zod.forklaunch.hyperExpress.test.ts
  • framework/hyper-express/package.json
  • framework/infrastructure/S3/CHANGELOG.md
  • framework/infrastructure/S3/package.json
  • framework/infrastructure/redis/CHANGELOG.md
  • framework/infrastructure/redis/package.json
  • framework/internal/CHANGELOG.md
  • framework/internal/package.json
  • framework/package.json
  • framework/testing/CHANGELOG.md
  • framework/testing/package.json
  • framework/tsconfig.base.json
  • framework/universal-sdk/CHANGELOG.md
  • framework/universal-sdk/package.json
  • framework/validator/CHANGELOG.md
  • framework/validator/package.json
  • framework/ws/CHANGELOG.md
  • framework/ws/package.json
  • framework/ws/src/__tests__/channels.test.ts
  • framework/ws/src/channels.ts
  • framework/ws/src/secureWebSocketServer.ts
  • framework/ws/src/wsSession.ts

Comment thread blueprint/iam-better-auth/persistence/entities/account.entity.ts Outdated
Comment thread blueprint/iam-better-auth/persistence/entities/jwks.entity.ts Outdated
Comment thread blueprint/implementations/billing/stripe/persistence/entities/index.ts Outdated
Comment thread framework/core/src/http/router/routerSharedLogic.ts
Comment thread framework/ws/src/channels.ts

@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.

Actionable comments posted: 13

🧹 Nitpick comments (4)
COMPLIANCE_COVERAGE.md (2)

283-289: Summary counts are accurate but structure needs fixing.

The summary table correctly counts 41 total requirements (23 + 1 + 11 + 6 = 41), but the presentation would be clearer after fixing the duplicate section heading issue (line 266). Once items are properly consolidated, the counts will remain accurate but the document structure will be more intuitive.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@COMPLIANCE_COVERAGE.md` around lines 283 - 289, The document contains a
duplicate section heading that splits the summary table and confuses structure;
locate the duplicate heading near the summary table (the table starting with the
"Category | Count | Details" row) and remove the redundant heading so the
summary table and its explanatory text are consolidated under a single correct
section heading, then confirm the aggregated counts (23, 1, 11, 6) still sum to
41 and adjust any surrounding paragraph references or TOC entries to point to
the single consolidated section (ensure references to the summary table or its
title use the same heading text).

53-53: Minor grammar issue flagged by static analysis.

The sentence fragment "Cannot be disabled" should be rephrased for grammatical correctness as "It cannot be disabled" or "This cannot be disabled."

✏️ Proposed fix
-**How:** Every HTTP request and WebSocket event automatically logged via OTEL collector, tagged `log.type: 'audit'` for Loki routing. Entries include: timestamp, userId, tenantId, route, method, SHA-256 body hash (never plaintext), status, duration. Compliance fields redacted. Auth failures, rate limit hits, RBAC denials, super-admin bypasses all logged with specific event types. Cannot be disabled — baked into middleware pipeline.
+**How:** Every HTTP request and WebSocket event automatically logged via OTEL collector, tagged `log.type: 'audit'` for Loki routing. Entries include: timestamp, userId, tenantId, route, method, SHA-256 body hash (never plaintext), status, duration. Compliance fields redacted. Auth failures, rate limit hits, RBAC denials, super-admin bypasses all logged with specific event types. This cannot be disabled — baked into middleware pipeline.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@COMPLIANCE_COVERAGE.md` at line 53, Edit the sentence fragment "Cannot be
disabled" in COMPLIANCE_COVERAGE.md to a grammatically complete form such as
"This cannot be disabled" (or "It cannot be disabled") so the sentence reads
correctly in the paragraph describing automatic logging via the OTEL collector;
just replace that fragment in the same paragraph that begins "Every HTTP request
and WebSocket event automatically logged via OTEL collector..." to maintain tone
and clarity.
blueprint/billing-base/api/controllers/compliance.controller.ts (1)

1-5: Reorder imports to match the repo layering.

@mikro-orm/core is an external dependency, so it should be grouped above the @forklaunch/* imports.

As per coding guidelines, "Organize imports in 7 layers: (1) Node built-ins with node: prefix, (2) External dependencies, (3) Forklaunch framework packages, (4) Cross-module imports, (5) Local persistence, (6) Local domain, (7) Same directory"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/billing-base/api/controllers/compliance.controller.ts` around lines
1 - 5, Reorder the import statements so external dependencies come before the
`@forklaunch` framework packages: move the EntityManager import from
`@mikro-orm/core` above the `@forklaunch/`* imports; keep the rest of the symbols
unchanged (handlers, schemaValidator, string, generateHmacAuthHeaders,
getEntityComplianceFields, ci, tokens) and preserve their exact names—just
adjust grouping so external imports (EntityManager) are in the external layer
and `@forklaunch/`* imports follow in the framework layer per repo layering rules.
blueprint/iam-base/api/controllers/compliance.controller.ts (1)

1-4: Reorder imports to match the repo layering.

@mikro-orm/core is an external dependency, so it should be grouped above the @forklaunch/* imports.

As per coding guidelines, "Organize imports in 7 layers: (1) Node built-ins with node: prefix, (2) External dependencies, (3) Forklaunch framework packages, (4) Cross-module imports, (5) Local persistence, (6) Local domain, (7) Same directory"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/iam-base/api/controllers/compliance.controller.ts` around lines 1 -
4, Reorder the import statements so external dependencies come before internal
packages: move the EntityManager import from '@mikro-orm/core' above the
'@forklaunch/*' imports, keeping the specific symbols (EntityManager, handlers,
schemaValidator, string, getEntityComplianceFields, ci, tokens) intact; the
final order should place '@mikro-orm/core' first, then
'@forklaunch/blueprint-core' and '@forklaunch/core/persistence', and finally the
relative '../../bootstrapper' import to match the repo's 7-layer import
convention.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@blueprint/billing-base/api/controllers/compliance.controller.ts`:
- Around line 41-53: The OpenAPI/response schemas in compliance.controller.ts
declare a 404 response that never occurs at runtime; either implement the
missing empty-result branch to return 404 when both billing and iam produce no
records (add logic in the relevant handler(s) to check if
billing.entitiesAffected.length === 0 && iam.entitiesAffected.length === 0 and
return a 404 with the appropriate payload) or remove the 404 entries from the
responses objects so the spec matches behavior; update all response blocks in
the file where 404 is declared (the three responses blocks shown) to keep schema
and runtime consistent.
- Around line 168-178: The code currently swallows errors from em.find via
catch(() => []) and calls em.flush() per-entity, causing hidden failures and
partial commits; change to let em.find errors surface (remove the catch) or
explicitly catch and handle/log & return an error response so broken queries/DB
failures are not treated as empty results, collect all entities to delete (using
metadata.class ?? metadata.className and the result of em.find), call em.remove
for each record but perform a single em.flush() after processing all entities
(instead of per-entity flush) so deletes are committed atomically, and update
recordsDeleted/entitiesAffected handling to reflect true failures by propagating
or returning an explicit partial-failure result rather than silently skipping.

In `@blueprint/iam-base/api/controllers/compliance.controller.ts`:
- Around line 147-154: The current logic masks all em.find errors by catching
and returning [] for the variable records (in the block using
metadata.class/metadata.className and userId), which hides DB/query failures;
instead, first check whether the relation is queryable (e.g., whether metadata
indicates the relation exists or the target entity supports queries) before
calling em.find, and only skip the lookup returning [] when the relation is
explicitly unsupported; for all other cases let em.find throw so errors surface.
Update both places that use em.find with $or lookup (the entityName !== 'User'
branch and the similar block at lines 187-194) to perform an explicit
relation/existence check (using metadata or the entityName) and remove the
blanket .catch(() => []) so unexpected DB/query errors are not swallowed.
- Around line 156-160: The current erase pass calls em.flush() inside the
per-entity loop, causing partial commits; change it to perform removals without
flushing per-entity (keep entitiesAffected.push, recordsDeleted +=, and call
em.remove(r) for each record) and then perform a single await em.flush() once
after all entities are processed, or better wrap the whole erase pass in a DB
transaction (e.g., em.begin/ em.commit or em.transactional) so that if any step
fails you can rollback and avoid partial erasure; update the code around
entitiesAffected, recordsDeleted, records.forEach, em.remove and em.flush
accordingly.

In `@blueprint/implementations/billing/stripe/services/webhook.service.ts`:
- Around line 114-121: resolvePartyType can return undefined when this.partyEnum
has no keys; add a guard in resolvePartyType that checks
Object.keys(this.partyEnum) (or Object.values) and if empty either throw a clear
error (e.g., "Missing partyEnum on <className>") or return a documented safe
fallback value, so the function never returns undefined; update the
implementation around resolvePartyType to perform this check and surface a
descriptive error (or explicit fallback) referencing this.partyEnum and the
method name.

In `@cli/src/compliance/audit.rs`:
- Around line 96-103: The mapping currently sets FieldReport.encrypted by
checking classification strings ("phi" or "pci"), which incorrectly assumes all
PHI/PCI are encrypted; instead read the actual encryption status from the source
data and set FieldReport.encrypted from that boolean (or add an encrypted flag
to the fields value if it doesn't exist). Update the closure that builds
FieldReport (the .map(|(field_name, classification)| ... ) block) to use the
true encryption indicator (e.g., fields should be (field_name, (classification,
encrypted)) or similar) and assign encrypted: encrypted_flag rather than
encrypted: classification == "phi" || classification == "pci"; ensure
FieldReport's construction uses the real metadata field and adjust upstream
types where needed.
- Line 113: The audit currently always scans src/modules/*/openapi.json by
calling collect_routes_from_openapi(&app_root); update the logic to read the
project's configured modules path (the persisted choice created by
init/application.rs) and pass that path into collect_routes_from_openapi so it
scans either "src/modules" or "modules" as configured; find usages of
collect_routes_from_openapi (including the call at
collect_routes_from_openapi(&app_root) and the similar block around lines
673-683) and replace them to derive modules_path from the project config (or the
same helper that init/application.rs persists) and call
collect_routes_from_openapi(&app_root.join(modules_path)) so OpenAPI discovery
honors the configured modules path.
- Around line 130-159: The code currently calls upload_to_platform() and then
proceeds to write or print either the platform_response or the local report,
allowing a failed platform_response to be silently ignored; change this to fail
fast by checking platform_response and returning an error when it is Err before
proceeding to output logic (both the output-file branch that reads
matches.get_one::<String>("output") and the json_output branch). Specifically,
after calling upload_to_platform(), if platform_response.is_err() then propagate
a contextual error (or use the ? operator on upload_to_platform) so that
functions like upload_to_platform, the platform_response variable, and the
output handling paths do not continue with a partial report and instead return
Err immediately. Ensure the same fail-fast change is applied to the other
identical output-printing block later in the function.

In `@cli/src/templates/github/ci.yml`:
- Around line 19-21: The Bun branch of the CI template currently runs package
scripts as "bun lint", "bun build", and "bun test" which invoke Bun's
bundler/test runner instead of package.json scripts; update the template so when
{{`#is_bun`}} is true it uses "bun run <script>" (e.g., "bun run lint", "bun run
build", "bun run test") instead of plain "bun <script>"—adjust the three run
lines surrounding the {{`#is_node`}}{{/is_node}}{{`#is_bun`}}{{/is_bun}}
conditionals to render "pnpm <script>" for Node and "bun run <script>" for Bun
so package.json scripts are executed.

In `@COMPLIANCE_COVERAGE.md`:
- Around line 266-278: Consolidate the duplicate "Not Addressed — Business
Action Required" section by moving the "41. Data Processing Agreements (GDPR)"
block into the first "Not Addressed — Business Action Required" group as item
"30" (ensure its heading and content remain intact), remove the second duplicate
section header, and renumber the following "Known Gaps — Addressable by
Engineering" items so they become items 31–41; update any internal references or
numbering in the document to reflect the new sequence and ensure the MD024
duplicate-heading warning is resolved.
- Line 5: The sentence "ForkLaunch (framework + platform) addresses every
technical control required by HIPAA, SOC 2, PCI DSS, and GDPR..." overstates
coverage and contradicts the report; update that specific sentence in
COMPLIANCE_COVERAGE.md (the line starting with "ForkLaunch (framework +
platform) addresses every technical control required") to a precise, accurate
claim such as "addresses most technical controls required" or the exact count
"addresses 23 of 34 technical controls required", ensuring the revised wording
reflects the report's findings about the 11 technical gaps (items 30-40) and the
partial item (item 24).

In `@COMPLIANCE_GAPS_PLAN.md`:
- Around line 61-64: The documentation references ".github/branch-protection.md"
but the generator uses ".github/BRANCH_PROTECTION.md", causing a casing
mismatch; update the generator's filename string (the branch-protection file
constant or literal in github_configs.rs used by the "forklaunch init
application" scaffolding) so it writes ".github/branch-protection.md" (or
alternatively make the docs match the generator) and ensure the same exact
filename literal is used wherever the branch-protection file is created or
referenced.

---

Nitpick comments:
In `@blueprint/billing-base/api/controllers/compliance.controller.ts`:
- Around line 1-5: Reorder the import statements so external dependencies come
before the `@forklaunch` framework packages: move the EntityManager import from
`@mikro-orm/core` above the `@forklaunch/`* imports; keep the rest of the symbols
unchanged (handlers, schemaValidator, string, generateHmacAuthHeaders,
getEntityComplianceFields, ci, tokens) and preserve their exact names—just
adjust grouping so external imports (EntityManager) are in the external layer
and `@forklaunch/`* imports follow in the framework layer per repo layering rules.

In `@blueprint/iam-base/api/controllers/compliance.controller.ts`:
- Around line 1-4: Reorder the import statements so external dependencies come
before internal packages: move the EntityManager import from '@mikro-orm/core'
above the '@forklaunch/*' imports, keeping the specific symbols (EntityManager,
handlers, schemaValidator, string, getEntityComplianceFields, ci, tokens)
intact; the final order should place '@mikro-orm/core' first, then
'@forklaunch/blueprint-core' and '@forklaunch/core/persistence', and finally the
relative '../../bootstrapper' import to match the repo's 7-layer import
convention.

In `@COMPLIANCE_COVERAGE.md`:
- Around line 283-289: The document contains a duplicate section heading that
splits the summary table and confuses structure; locate the duplicate heading
near the summary table (the table starting with the "Category | Count | Details"
row) and remove the redundant heading so the summary table and its explanatory
text are consolidated under a single correct section heading, then confirm the
aggregated counts (23, 1, 11, 6) still sum to 41 and adjust any surrounding
paragraph references or TOC entries to point to the single consolidated section
(ensure references to the summary table or its title use the same heading text).
- Line 53: Edit the sentence fragment "Cannot be disabled" in
COMPLIANCE_COVERAGE.md to a grammatically complete form such as "This cannot be
disabled" (or "It cannot be disabled") so the sentence reads correctly in the
paragraph describing automatic logging via the OTEL collector; just replace that
fragment in the same paragraph that begins "Every HTTP request and WebSocket
event automatically logged via OTEL collector..." to maintain tone and clarity.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: be7cf65f-f05b-425b-9b4f-ef7feb79d8e5

📥 Commits

Reviewing files that changed from the base of the PR and between 452e99b and 36f774c.

📒 Files selected for processing (22)
  • .github/dependabot.yml
  • COMPLIANCE_COVERAGE.md
  • COMPLIANCE_GAPS_PLAN.md
  • blueprint/billing-base/api/controllers/compliance.controller.ts
  • blueprint/billing-base/api/controllers/index.ts
  • blueprint/billing-stripe/registrations.ts
  • blueprint/iam-base/api/controllers/compliance.controller.ts
  • blueprint/iam-base/api/controllers/index.ts
  • blueprint/iam-better-auth/auth.ts
  • blueprint/implementations/billing/stripe/CHANGELOG.md
  • blueprint/implementations/billing/stripe/package.json
  • blueprint/implementations/billing/stripe/services/webhook.service.ts
  • cli/src/compliance/audit.rs
  • cli/src/core.rs
  • cli/src/core/github_configs.rs
  • cli/src/core/package_json/package_json_constants.rs
  • cli/src/init/application.rs
  • cli/src/templates/github/BRANCH_PROTECTION.md
  • cli/src/templates/github/ci.yml
  • cli/src/templates/github/dependabot.yml
  • cli/src/templates/router/api/controllers/{{camel_case_name}}.controller.ts
  • compliance-coverage.html
✅ Files skipped from review due to trivial changes (9)
  • blueprint/iam-base/api/controllers/index.ts
  • blueprint/billing-base/api/controllers/index.ts
  • .github/dependabot.yml
  • cli/src/templates/github/dependabot.yml
  • blueprint/implementations/billing/stripe/CHANGELOG.md
  • blueprint/implementations/billing/stripe/package.json
  • compliance-coverage.html
  • cli/src/core.rs
  • cli/src/core/package_json/package_json_constants.rs

Comment thread blueprint/billing-base/api/controllers/compliance.controller.ts Outdated
Comment thread blueprint/billing-base/api/controllers/compliance.controller.ts
Comment thread blueprint/billing-base/api/controllers/compliance.controller.ts Outdated
Comment thread blueprint/iam-base/api/controllers/compliance.controller.ts Outdated
Comment thread blueprint/iam-base/api/controllers/compliance.controller.ts Outdated
Comment thread cli/src/compliance/audit.rs
Comment thread cli/src/templates/github/ci.yml Outdated
Comment thread COMPLIANCE_COVERAGE.md Outdated
Comment thread COMPLIANCE_COVERAGE.md Outdated
Comment thread COMPLIANCE_GAPS_PLAN.md

@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.

Actionable comments posted: 9

🧹 Nitpick comments (6)
framework/ws/src/channels.ts (2)

136-150: Consider including delivery count in the audit entry.

The delivered count is already computed but not recorded in the audit log. For compliance auditing, knowing how many recipients received a broadcast can be valuable.

💡 Optional enhancement

You could extend the audit entry (if the schema supports it) or encode it in an existing field:

     if (this.auditLogger) {
       this.auditLogger.append({
         timestamp: new Date().toISOString(),
         userId: null,
         tenantId: senderTenantId,
-        route: `ws:channel:${channel}`,
+        route: `ws:channel:${channel}:delivered:${delivered}`,
         method: 'BROADCAST',

Alternatively, if AuditEntry can be extended, a dedicated metadata or recipientCount field would be cleaner.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/ws/src/channels.ts` around lines 136 - 150, The audit log currently
omits the computed delivered count; update the block that calls
this.auditLogger.append (in the broadcast path where `delivered` is computed) to
include the recipient count—either by adding a new field like `recipientCount`
or embedding it in `metadata`/`bodyHash` per your AuditEntry schema (reference:
`this.auditLogger.append`, `delivered`, `channel`, `senderTenantId`); ensure the
appended object includes the delivered value so the audit entry records how many
recipients received the broadcast.

129-134: Wrap individual send() calls to prevent one failure from aborting the broadcast.

A race exists between the readyState check and send()—if the socket closes in between, send() throws and halts delivery to remaining connections. Catching per-connection errors keeps the broadcast resilient.

♻️ Suggested fix
       // Deliver if connection is open
       if (tracked.ws.readyState === 1 /* WebSocket.OPEN */) {
-        tracked.ws.send(payload);
-        delivered++;
+        try {
+          tracked.ws.send(payload);
+          delivered++;
+        } catch {
+          // Connection may have closed between readyState check and send
+        }
       }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/ws/src/channels.ts` around lines 129 - 134, The broadcast loop
checks tracked.ws.readyState then calls tracked.ws.send(payload), but a race can
cause send() to throw and abort the loop; wrap each tracked.ws.send call in a
try/catch inside the loop (around the readyState check + send) so a failing send
only logs/ignores that connection and continues delivering to others, and update
delivered only on successful sends (referencing tracked.ws.readyState,
tracked.ws.send, and the delivered counter).
cli/src/core/ast/transformations/transform_base_entity_ts.rs (1)

20-20: Add a regression test for the new base retention-field exclusion.

Line 20 changes migration behavior, but there’s no explicit test that retentionAnonymizedAt is treated as base (not copied as user-defined). Please lock this down with a dedicated assertion to prevent future regressions.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/ast/transformations/transform_base_entity_ts.rs` at line 20, Add
a regression test that verifies the new base property exclusion treats
"retentionAnonymizedAt" as a base field (not a user-defined field) when running
the migration/transformation that uses BASE_PROPERTY_NAMES in
transform_base_entity_ts.rs; specifically, create a test that constructs an
entity with a user-defined "retentionAnonymizedAt" and asserts after running the
transformation function (the code path that references BASE_PROPERTY_NAMES) that
"retentionAnonymizedAt" was excluded from the copied/user-defined properties and
instead handled as a base property, failing if it is present in the output's
user-defined property list.
framework/core/src/http/guards/hasPermissionChecks.ts (2)

2-7: Use shared isRecord guard for consistency

This manual object/null check should use the shared type guard to keep validation style consistent across the codebase.

Proposed refactor
+import { isRecord } from '@forklaunch/common';
+
 export function hasPermissionChecks(maybePermissionedAuth: unknown) {
-  if (
-    typeof maybePermissionedAuth !== 'object' ||
-    maybePermissionedAuth === null
-  ) {
+  if (!isRecord(maybePermissionedAuth)) {
     return false;
   }

As per coding guidelines, "Import and use utility functions from @forklaunch/common: camelCase, hashString, safeStringify, safeParse, deepCloneWithoutUndefined, stripUndefinedProperties, sortObjectKeys, and type guards like isRecord, isTrue, isNever".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/src/http/guards/hasPermissionChecks.ts` around lines 2 - 7,
Replace the manual object/null check in hasPermissionChecks that tests
maybePermissionedAuth with the shared type guard isRecord from
`@forklaunch/common`: import isRecord and use isRecord(maybePermissionedAuth) in
place of the current typeof/null check so the guard is consistent with other
helpers (keep the same control flow and return false behavior when the guard
fails).

9-19: Consider stricter validation for malformed permission keys

The current OR logic accepts objects where one permission key is valid while another is present but malformed (e.g., allowedPermissions: "invalid" with forbiddenPermissions: new Set(['x'])). While this scenario isn't covered by existing tests and malformed keys represent a development-time configuration error, consider adding explicit validation to reject partially invalid configs. A simpler approach than the proposed fix would be to validate only present keys:

  const hasAllowedPermissions =
    'allowedPermissions' in maybePermissionedAuth &&
    maybePermissionedAuth.allowedPermissions instanceof Set &&
    maybePermissionedAuth.allowedPermissions.size > 0;

  const hasForbiddenPermissions =
    'forbiddenPermissions' in maybePermissionedAuth &&
    maybePermissionedAuth.forbiddenPermissions instanceof Set &&
    maybePermissionedAuth.forbiddenPermissions.size > 0;

-  return hasAllowedPermissions || hasForbiddenPermissions;
+  const hasInvalidAllowed =
+    'allowedPermissions' in maybePermissionedAuth &&
+    !(maybePermissionedAuth.allowedPermissions instanceof Set &&
+      maybePermissionedAuth.allowedPermissions.size > 0);
+
+  const hasInvalidForbidden =
+    'forbiddenPermissions' in maybePermissionedAuth &&
+    !(maybePermissionedAuth.forbiddenPermissions instanceof Set &&
+      maybePermissionedAuth.forbiddenPermissions.size > 0);
+
+  return (hasAllowedPermissions || hasForbiddenPermissions) && !hasInvalidAllowed && !hasInvalidForbidden;

Note that hasRoleChecks uses the same OR pattern, so consider applying the same fix there.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/src/http/guards/hasPermissionChecks.ts` around lines 9 - 19,
The check currently accepts the object if either allowedPermissions or
forbiddenPermissions looks valid even if the other is present but malformed;
update validation in hasPermissionChecks so that for each permission key that
exists on maybePermissionedAuth you explicitly validate its type (instanceof
Set) and size (>0) and treat any present-but-malformed key as a failure (return
false), then return true only if at least one present key is valid; apply the
same pattern to hasRoleChecks for symmetry and reference the existing symbols
maybePermissionedAuth, hasAllowedPermissions, hasForbiddenPermissions, and
hasRoleChecks when making the change.
framework/core/src/services/retentionService.ts (1)

31-38: Rename this file to retention.service.ts.

The new service path diverges from the repo's service naming convention. Renaming it now avoids spreading a non-standard import path through the framework.

As per coding guidelines, "Services as .service.ts".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/core/src/services/retentionService.ts` around lines 31 - 38, Rename
the file containing the RetentionService class to retention.service.ts and
update all imports to the new module name; locate the class RetentionService
(and its DEFAULT_BATCH_SIZE and constructor) in the current retentionService.ts
file and rename the filename only (no code changes), then search the repo for
any imports referencing "retentionService" and update them to
"retention.service" (and update any barrel exports or index files that re-export
RetentionService) so TypeScript imports and build remain consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/src/compliance/audit.rs`:
- Around line 93-95: The audit currently builds report.entities only from
compliance.entities, omitting entities that are retention-only (no classified
fields) so their retention policy is lost; update the logic in audit.rs to also
include entities defined in the manifest that have a retention policy but no
classified fields by iterating over the manifest entity list (or by merging
compliance.entities with manifest entries) and creating an EntityReport for each
retention-only entity (populate the retention fields and minimal metadata)
before collecting into report.entities and the platform payload; apply the same
change to the second loop handling lines ~105-113 so retention-only entities are
consistently included.
- Around line 692-694: The code currently ignores errors from
parse_openapi_routes (e.g., the block using if let Ok(spec_routes) =
parse_openapi_routes(&spec_path) { routes.extend(spec_routes); }) which silently
drops invalid OpenAPI specs; change this to surface failures instead of
swallowing them: call parse_openapi_routes(&spec_path), match on the Result, and
on Err either log/emit a clear error that includes spec_path and the parse error
or return/propagate an Err from the surrounding function so the audit fails
fast; do the same replacement for the other occurrence (the similar if-let at
701-703) so any parse failures are reported rather than ignored.

In `@cli/src/core/manifest.rs`:
- Around line 136-158: The manifest currently allows arbitrary strings in
ComplianceManifestConfig::entities so misspelled classifications silently pass;
update the manifest parsing/deserialize path to validate each classification
value for every entry in entities against an explicit allowed set
{"none","pii","phi","pci"} and return a parse/validation error on any unknown
value. Implement this either by adding a custom Deserialize/deserialize_with for
ComplianceManifestConfig (or for the entities map) or by adding a validation
step immediately after deserialization (where the manifest is loaded) that
iterates ComplianceManifestConfig::entities and errors on invalid classification
strings, referencing the ComplianceManifestConfig::entities field and the
allowed-classifications set in the error message.

In `@cli/src/templates/project/service/server.ts`:
- Around line 115-128: The retention setInterval block (using
retentionService.enforce(), RETENTION_INTERVAL_MS and openTelemetryCollector)
must not run unmanaged in every API replica; either move this logic into a
singleton worker/CLI entrypoint or protect it with distributed locking/leader
election so only one process runs enforcement, and convert the interval into a
self-scheduling loop that awaits retentionService.enforce() to avoid overlapping
runs; if you must keep it here, capture the timer handle returned by
setInterval, call clearInterval during graceful shutdown (and/or timer.unref()),
and add an in-flight guard (e.g., a boolean) to prevent concurrent enforce()
calls.

In `@framework/core/src/persistence/complianceTypes.ts`:
- Around line 69-73: RetentionDuration currently emits ISO strings for
months/years that parseDuration collapses into fixed day counts, causing
incorrect cutoffs around month-ends and leap years; change the flow to preserve
calendar units: keep RetentionDuration.months(n) and .years(n) as
'P{n}M'/'P{n}Y', update parseDuration() to return a unit-aware structure (e.g. {
amount: number, unit: 'D'|'M'|'Y' }) instead of converting months/years to days,
and modify any cutoff computation that consumes parseDuration() to use
calendar-aware arithmetic (use a reliable date library or implement
addMonths/addYears logic) so cutoffs are computed by subtracting months/years
from the anchor date rather than subtracting an equivalent day count.

In `@framework/core/src/services/retentionService.ts`:
- Around line 149-165: The dry-run branch in RetentionService.enforce currently
only tallies the first batch (records, batchSize) then breaks, underreporting
multi-batch results; change the dryRun handling to compute totals for the whole
filter instead of breaking after the first page—e.g., call the ORM count method
(em.count(entityClass, filter)) or loop pages advancing with a cursor (without
performing deletes/anonymizations) to accumulate stats for all matching rows,
and then log/update stats.deleted or stats.anonymized accordingly; keep the rest
of the enforce logic unchanged.
- Around line 128-133: The current piiFieldNames computation naively collects
all non-'none' fields for anonymization and later sets them to null, which will
break for non-nullable columns; update the logic in retentionService.ts
(symbols: piiFieldNames, policy.action, getEntityComplianceFields, entityName)
to first inspect each field's nullability/allowed redaction value (from the
entity compliance metadata returned by getEntityComplianceFields) and only
include fields that are nullable or have an explicit per-field redaction value;
for non-nullable fields either skip them or map them to their configured
redaction value so the flush won't fail; apply the same validation/mapping
change to the other anonymize collection block referenced around lines 173-179.

In `@framework/ws/src/channels.ts`:
- Around line 172-180: The JSDoc above arraysEqual is incorrect; replace the
permission-check comment with a concise description that arraysEqual compares
two string arrays for equality irrespective of element order (it checks lengths,
sorts copies, and compares elements). Update the comment to reference
arraysEqual and describe its behavior and return value (boolean indicating
equality ignoring order).

---

Nitpick comments:
In `@cli/src/core/ast/transformations/transform_base_entity_ts.rs`:
- Line 20: Add a regression test that verifies the new base property exclusion
treats "retentionAnonymizedAt" as a base field (not a user-defined field) when
running the migration/transformation that uses BASE_PROPERTY_NAMES in
transform_base_entity_ts.rs; specifically, create a test that constructs an
entity with a user-defined "retentionAnonymizedAt" and asserts after running the
transformation function (the code path that references BASE_PROPERTY_NAMES) that
"retentionAnonymizedAt" was excluded from the copied/user-defined properties and
instead handled as a base property, failing if it is present in the output's
user-defined property list.

In `@framework/core/src/http/guards/hasPermissionChecks.ts`:
- Around line 2-7: Replace the manual object/null check in hasPermissionChecks
that tests maybePermissionedAuth with the shared type guard isRecord from
`@forklaunch/common`: import isRecord and use isRecord(maybePermissionedAuth) in
place of the current typeof/null check so the guard is consistent with other
helpers (keep the same control flow and return false behavior when the guard
fails).
- Around line 9-19: The check currently accepts the object if either
allowedPermissions or forbiddenPermissions looks valid even if the other is
present but malformed; update validation in hasPermissionChecks so that for each
permission key that exists on maybePermissionedAuth you explicitly validate its
type (instanceof Set) and size (>0) and treat any present-but-malformed key as a
failure (return false), then return true only if at least one present key is
valid; apply the same pattern to hasRoleChecks for symmetry and reference the
existing symbols maybePermissionedAuth, hasAllowedPermissions,
hasForbiddenPermissions, and hasRoleChecks when making the change.

In `@framework/core/src/services/retentionService.ts`:
- Around line 31-38: Rename the file containing the RetentionService class to
retention.service.ts and update all imports to the new module name; locate the
class RetentionService (and its DEFAULT_BATCH_SIZE and constructor) in the
current retentionService.ts file and rename the filename only (no code changes),
then search the repo for any imports referencing "retentionService" and update
them to "retention.service" (and update any barrel exports or index files that
re-export RetentionService) so TypeScript imports and build remain consistent.

In `@framework/ws/src/channels.ts`:
- Around line 136-150: The audit log currently omits the computed delivered
count; update the block that calls this.auditLogger.append (in the broadcast
path where `delivered` is computed) to include the recipient count—either by
adding a new field like `recipientCount` or embedding it in
`metadata`/`bodyHash` per your AuditEntry schema (reference:
`this.auditLogger.append`, `delivered`, `channel`, `senderTenantId`); ensure the
appended object includes the delivered value so the audit entry records how many
recipients received the broadcast.
- Around line 129-134: The broadcast loop checks tracked.ws.readyState then
calls tracked.ws.send(payload), but a race can cause send() to throw and abort
the loop; wrap each tracked.ws.send call in a try/catch inside the loop (around
the readyState check + send) so a failing send only logs/ignores that connection
and continues delivering to others, and update delivered only on successful
sends (referencing tracked.ws.readyState, tracked.ws.send, and the delivered
counter).

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: abaee06a-a03e-442c-86a8-914cdf927c80

📥 Commits

Reviewing files that changed from the base of the PR and between 36f774c and 3bafdaf.

📒 Files selected for processing (18)
  • blueprint/core/persistence/nosql.base.properties.ts
  • blueprint/core/persistence/sql.base.properties.ts
  • blueprint/iam-better-auth/persistence/entities/account.entity.ts
  • blueprint/iam-better-auth/persistence/entities/jwks.entity.ts
  • blueprint/implementations/billing/stripe/persistence/entities/index.ts
  • cli/src/compliance/audit.rs
  • cli/src/core/ast/transformations/transform_base_entity_ts.rs
  • cli/src/core/manifest.rs
  • cli/src/templates/project/service/registrations.ts
  • cli/src/templates/project/service/server.ts
  • compliance-coverage.html
  • framework/core/src/http/guards/hasPermissionChecks.ts
  • framework/core/src/persistence/complianceTypes.ts
  • framework/core/src/persistence/defineComplianceEntity.ts
  • framework/core/src/persistence/index.ts
  • framework/core/src/services/index.ts
  • framework/core/src/services/retentionService.ts
  • framework/ws/src/channels.ts
✅ Files skipped from review due to trivial changes (1)
  • compliance-coverage.html
🚧 Files skipped from review as they are similar to previous changes (5)
  • blueprint/core/persistence/sql.base.properties.ts
  • blueprint/iam-better-auth/persistence/entities/jwks.entity.ts
  • blueprint/core/persistence/nosql.base.properties.ts
  • blueprint/iam-better-auth/persistence/entities/account.entity.ts
  • framework/core/src/persistence/defineComplianceEntity.ts

Comment thread cli/src/compliance/audit.rs Outdated
Comment thread cli/src/compliance/audit.rs
Comment thread cli/src/core/ast/transformations/transform_base_entity_ts.rs
Comment thread cli/src/core/manifest.rs
Comment thread cli/src/templates/project/service/server.ts Outdated
Comment thread framework/core/src/persistence/complianceTypes.ts
Comment thread framework/core/src/services/retentionService.ts Outdated
Comment thread framework/core/src/services/retentionService.ts Outdated
Comment thread framework/ws/src/channels.ts

@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.

Actionable comments posted: 3

🧹 Nitpick comments (4)
framework/testing/CHANGELOG.md (1)

7-92: Make new changelog entries more specific and user-actionable.

Several added items are too vague (for example: “refinement”, “inconsistent state”, “patch working”). Consider including affected module + user impact to make release notes useful for consumers.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@framework/testing/CHANGELOG.md` around lines 7 - 92, The changelog contains
vague entries (e.g., "refinement", "inconsistent state", "patch working") under
headings like "## 1.0.13" through "## 1.0.0"; replace each vague bullet with a
concise, actionable entry that names the affected module or file (e.g.,
"entity-branding", "mikroorm integration", "retention policy"), describes the
concrete user-visible change or bugfix, and notes any migration or action
required by consumers (e.g., "Users must update config X" or "no action
required"); update entries such as the bullets under "## 1.0.13", "## 1.0.11",
and "## 1.0.7" to follow this pattern so release notes are specific and
actionable.
blueprint/iam-base/package.json (1)

20-20: Don’t delete the lockfile from clean.

pnpm.lock.yaml is dependency state, not build output. Including it here turns a routine cleanup into a dependency reset if this package is ever used outside the workspace.

♻️ Suggested fix
-    "clean": "rm -rf dist tsconfig.tsbuildinfo pnpm.lock.yaml node_modules",
+    "clean": "rm -rf dist tsconfig.tsbuildinfo node_modules",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/iam-base/package.json` at line 20, The clean script in package.json
currently removes pnpm.lock.yaml which should not be treated as build output;
update the "clean" npm script (the value for the "clean" key) to stop deleting
pnpm.lock.yaml so it only removes build artifacts (e.g., keep rm -rf dist
tsconfig.tsbuildinfo node_modules but remove pnpm.lock.yaml from the list) to
avoid resetting dependency state.
blueprint/billing-stripe/package.json (1)

19-19: Don’t delete the lockfile from clean.

pnpm.lock.yaml is dependency state, not build output. Including it here turns a routine cleanup into a dependency reset if this package is ever used outside the workspace.

♻️ Suggested fix
-    "clean": "rm -rf dist tsconfig.tsbuildinfo pnpm.lock.yaml node_modules",
+    "clean": "rm -rf dist tsconfig.tsbuildinfo node_modules",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/billing-stripe/package.json` at line 19, The "clean" npm script in
package.json currently removes pnpm.lock.yaml (dependency lockfile) which should
not be deleted; update the "clean" script to stop removing pnpm.lock.yaml and
only delete build/output artifacts (e.g., keep "clean" removing dist,
tsconfig.tsbuildinfo, node_modules if desired) so the lockfile remains intact;
locate the "clean" script entry in package.json and remove pnpm.lock.yaml from
that command.
blueprint/billing-base/package.json (1)

20-20: Don’t delete the lockfile from clean.

pnpm.lock.yaml is dependency state, not build output. Including it here turns a routine cleanup into a dependency reset if this package is ever used outside the workspace.

♻️ Suggested fix
-    "clean": "rm -rf dist tsconfig.tsbuildinfo pnpm.lock.yaml node_modules",
+    "clean": "rm -rf dist tsconfig.tsbuildinfo node_modules",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@blueprint/billing-base/package.json` at line 20, The clean script in
package.json currently removes the workspace lockfile (pnpm.lock.yaml), which
should not be treated as build output; update the "clean" npm script (the
"clean" property) to stop deleting pnpm.lock.yaml (keep removing dist,
tsconfig.tsbuildinfo, node_modules only) so cleaning won’t reset dependencies or
affect other workspace packages.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@framework/express/CHANGELOG.md`:
- Line 20: Remove the stray trailing double-quote in the changelog bullet that
currently reads "patch working"; edit the CHANGELOG.md entry so the bullet is a
well-formed line (e.g., change 'patch working"' to 'patch working' or reword the
bullet for clarity) and save the file so the release notes no longer contain the
accidental quote.
- Around line 102-104: The changelog entry for version 1.0.5 contains a
duplicated heading "- Updated dependencies"; remove the redundant line so only a
single "- Updated dependencies" remains and retain the sub-bullet "-
`@forklaunch/validator`@1.0.5" under it to avoid duplicate changelog output.

In `@framework/testing/CHANGELOG.md`:
- Line 13: Fix the malformed changelog entry that contains an unmatched trailing
quote by editing the line that currently reads `- patch working"` in
CHANGELOG.md and removing the stray double-quote so it becomes `- patch working`
(or adjust wording/quoting to match surrounding entries); ensure the line's
punctuation/format matches other changelog items.

---

Nitpick comments:
In `@blueprint/billing-base/package.json`:
- Line 20: The clean script in package.json currently removes the workspace
lockfile (pnpm.lock.yaml), which should not be treated as build output; update
the "clean" npm script (the "clean" property) to stop deleting pnpm.lock.yaml
(keep removing dist, tsconfig.tsbuildinfo, node_modules only) so cleaning won’t
reset dependencies or affect other workspace packages.

In `@blueprint/billing-stripe/package.json`:
- Line 19: The "clean" npm script in package.json currently removes
pnpm.lock.yaml (dependency lockfile) which should not be deleted; update the
"clean" script to stop removing pnpm.lock.yaml and only delete build/output
artifacts (e.g., keep "clean" removing dist, tsconfig.tsbuildinfo, node_modules
if desired) so the lockfile remains intact; locate the "clean" script entry in
package.json and remove pnpm.lock.yaml from that command.

In `@blueprint/iam-base/package.json`:
- Line 20: The clean script in package.json currently removes pnpm.lock.yaml
which should not be treated as build output; update the "clean" npm script (the
value for the "clean" key) to stop deleting pnpm.lock.yaml so it only removes
build artifacts (e.g., keep rm -rf dist tsconfig.tsbuildinfo node_modules but
remove pnpm.lock.yaml from the list) to avoid resetting dependency state.

In `@framework/testing/CHANGELOG.md`:
- Around line 7-92: The changelog contains vague entries (e.g., "refinement",
"inconsistent state", "patch working") under headings like "## 1.0.13" through
"## 1.0.0"; replace each vague bullet with a concise, actionable entry that
names the affected module or file (e.g., "entity-branding", "mikroorm
integration", "retention policy"), describes the concrete user-visible change or
bugfix, and notes any migration or action required by consumers (e.g., "Users
must update config X" or "no action required"); update entries such as the
bullets under "## 1.0.13", "## 1.0.11", and "## 1.0.7" to follow this pattern so
release notes are specific and actionable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b84b3a1d-e24c-4f74-90dc-8f8d2f7706df

📥 Commits

Reviewing files that changed from the base of the PR and between 3bafdaf and be8c669.

⛔ Files ignored due to path filters (2)
  • blueprint/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • framework/pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (54)
  • blueprint/billing-base/package.json
  • blueprint/billing-stripe/package.json
  • blueprint/core/package.json
  • blueprint/iam-base/package.json
  • blueprint/iam-better-auth/package.json
  • blueprint/implementations/billing/base/CHANGELOG.md
  • blueprint/implementations/billing/base/package.json
  • blueprint/implementations/billing/stripe/CHANGELOG.md
  • blueprint/implementations/billing/stripe/package.json
  • blueprint/implementations/iam/base/CHANGELOG.md
  • blueprint/implementations/iam/base/package.json
  • blueprint/implementations/worker/bullmq/CHANGELOG.md
  • blueprint/implementations/worker/bullmq/package.json
  • blueprint/implementations/worker/database/CHANGELOG.md
  • blueprint/implementations/worker/database/package.json
  • blueprint/implementations/worker/kafka/CHANGELOG.md
  • blueprint/implementations/worker/kafka/package.json
  • blueprint/implementations/worker/redis/CHANGELOG.md
  • blueprint/implementations/worker/redis/package.json
  • blueprint/interfaces/billing/CHANGELOG.md
  • blueprint/interfaces/billing/package.json
  • blueprint/interfaces/iam/CHANGELOG.md
  • blueprint/interfaces/iam/package.json
  • blueprint/interfaces/worker/CHANGELOG.md
  • blueprint/interfaces/worker/package.json
  • blueprint/monitoring/package.json
  • blueprint/package.json
  • blueprint/sample-worker/package.json
  • cli/src/core/package_json/package_json_constants.rs
  • framework/bunrun/CHANGELOG.md
  • framework/bunrun/package.json
  • framework/common/CHANGELOG.md
  • framework/common/package.json
  • framework/core/CHANGELOG.md
  • framework/core/package.json
  • framework/e2e-tests/package.json
  • framework/express/CHANGELOG.md
  • framework/express/package.json
  • framework/hyper-express/CHANGELOG.md
  • framework/hyper-express/package.json
  • framework/infrastructure/S3/CHANGELOG.md
  • framework/infrastructure/S3/package.json
  • framework/infrastructure/redis/CHANGELOG.md
  • framework/infrastructure/redis/package.json
  • framework/internal/CHANGELOG.md
  • framework/internal/package.json
  • framework/testing/CHANGELOG.md
  • framework/testing/package.json
  • framework/universal-sdk/CHANGELOG.md
  • framework/universal-sdk/package.json
  • framework/validator/CHANGELOG.md
  • framework/validator/package.json
  • framework/ws/CHANGELOG.md
  • framework/ws/package.json
✅ Files skipped from review due to trivial changes (30)
  • blueprint/implementations/iam/base/CHANGELOG.md
  • framework/e2e-tests/package.json
  • blueprint/interfaces/billing/CHANGELOG.md
  • blueprint/interfaces/iam/CHANGELOG.md
  • blueprint/interfaces/worker/CHANGELOG.md
  • blueprint/implementations/billing/base/CHANGELOG.md
  • blueprint/implementations/worker/kafka/CHANGELOG.md
  • framework/bunrun/CHANGELOG.md
  • framework/universal-sdk/CHANGELOG.md
  • framework/bunrun/package.json
  • framework/universal-sdk/package.json
  • framework/hyper-express/package.json
  • framework/validator/package.json
  • blueprint/interfaces/billing/package.json
  • blueprint/interfaces/iam/package.json
  • framework/ws/package.json
  • blueprint/implementations/iam/base/package.json
  • framework/internal/package.json
  • blueprint/implementations/worker/database/package.json
  • framework/common/package.json
  • blueprint/implementations/worker/kafka/package.json
  • framework/infrastructure/redis/package.json
  • blueprint/implementations/billing/stripe/package.json
  • framework/internal/CHANGELOG.md
  • framework/ws/CHANGELOG.md
  • blueprint/implementations/worker/database/CHANGELOG.md
  • framework/infrastructure/S3/package.json
  • framework/core/CHANGELOG.md
  • framework/testing/package.json
  • cli/src/core/package_json/package_json_constants.rs
🚧 Files skipped from review as they are similar to previous changes (18)
  • blueprint/monitoring/package.json
  • blueprint/implementations/worker/redis/CHANGELOG.md
  • blueprint/core/package.json
  • blueprint/package.json
  • blueprint/implementations/worker/bullmq/CHANGELOG.md
  • framework/express/package.json
  • blueprint/iam-better-auth/package.json
  • framework/hyper-express/CHANGELOG.md
  • blueprint/sample-worker/package.json
  • blueprint/implementations/worker/bullmq/package.json
  • framework/validator/CHANGELOG.md
  • framework/core/package.json
  • framework/infrastructure/redis/CHANGELOG.md
  • framework/infrastructure/S3/CHANGELOG.md
  • blueprint/implementations/worker/redis/package.json
  • blueprint/implementations/billing/stripe/CHANGELOG.md
  • blueprint/implementations/billing/base/package.json
  • framework/common/CHANGELOG.md

Comment thread framework/express/CHANGELOG.md
Comment thread framework/express/CHANGELOG.md
Comment thread framework/testing/CHANGELOG.md

@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.

Actionable comments posted: 3

🧹 Nitpick comments (3)
COMPLIANCE_GAPS_PLAN.md (1)

175-181: Consider adding language specifier to code block.

The fenced code block on line 175 lacks a language identifier. While this doesn't affect functionality, adding a specifier (e.g., text or plaintext) improves rendering and satisfies markdown linters.

💡 Suggested fix
-```
+```text
 Step 1: GDPR module (erase + export)         [CLI: Rust]     depends on: nothing
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@COMPLIANCE_GAPS_PLAN.md` around lines 175 - 181, The fenced code block
containing the checklist lines starting with "Step 1: GDPR module (erase +
export) ..." should include a language specifier to satisfy markdown linters and
improve rendering; update the opening fence from ``` to ```text (or
```plaintext) so the block reads like "```text" and keep the block contents
unchanged (the lines listing Step 1 through Step 5) to ensure correct formatting
and lint compliance.
cli/src/core/ast/infrastructure/compliance.rs (2)

603-605: Simplify redundant file extension check.

The .d.ts check is redundant since .d.ts files never end with .entity.ts. The current logic works correctly but is slightly confusing.

♻️ Proposed simplification
-        if !file_name.ends_with(".entity.ts") || file_name.ends_with(".d.ts") {
+        if !file_name.ends_with(".entity.ts") {
             continue;
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/ast/infrastructure/compliance.rs` around lines 603 - 605, The
if-condition that filters files is more complex than necessary: remove the
redundant ".d.ts" check and only keep the check for ".entity.ts" by changing the
condition that currently uses file_name.ends_with(".entity.ts") ||
file_name.ends_with(".d.ts") to a single negative check on
file_name.ends_with(".entity.ts") (i.e., if !file_name.ends_with(".entity.ts") {
continue; }) so the logic reads clearly; update the if block around the
file_name variable in compliance.rs accordingly.

158-171: Consider supporting additional TypeScript extensions.

resolve_ts_file only resolves .ts files. If entity base properties are ever placed in .tsx or .mts files, they won't be resolved. This is likely fine given the entity file conventions, but worth noting.

♻️ Optional enhancement for broader compatibility
 fn resolve_ts_file(base: &Path) -> Option<PathBuf> {
     if base.is_file() {
         return Some(base.to_path_buf());
     }
     let with_ext = base.with_extension("ts");
     if with_ext.is_file() {
         return Some(with_ext);
     }
+    let with_tsx = base.with_extension("tsx");
+    if with_tsx.is_file() {
+        return Some(with_tsx);
+    }
     let index = base.join("index.ts");
     if index.is_file() {
         return Some(index);
     }
     None
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/ast/infrastructure/compliance.rs` around lines 158 - 171,
resolve_ts_file currently only checks for ".ts"; update it to try multiple
TypeScript extensions (e.g., "ts", "tsx", "mts", "cts") when resolving a file or
its index. Implement a small loop over the extensions (instead of a single
with_extension("ts") call) to test base.with_extension(ext) and
base.join("index." + ext) so resolve_ts_file returns the first existing PathBuf
for any supported TS extension; keep the existing behavior of returning
Some(path) when base is already a file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/src/init/service.rs`:
- Line 364: The retention_enforce script is being added unconditionally via
retention_enforce:
Some(project_retention_enforce_script(&manifest_data.runtime.parse()?)), which
will fail for services without a database because tokens.RetentionService is
only registered when is_database_enabled is true; update the code that
constructs the service manifest to only include the retention_enforce entry when
is_database_enabled is true (i.e., wrap or conditionally push retention_enforce
using the same is_database_enabled flag that controls RetentionService
registration), referencing the retention_enforce key and
project_retention_enforce_script(...) call so the script is only added for
services where RetentionService is available.

In `@cli/src/templates/github/ci.yml`:
- Around line 13-18: The YAML template block with the Handlebars conditionals
({{`#is_node`}}...{{/is_node}} and {{`#is_bun`}}...{{/is_bun}}) currently nests the
`run:` steps under the `uses:`/`with:` mapping, producing invalid YAML when
is_node is true; update the template so each CI step is its own list item: keep
the `- uses: actions/setup-node@v4` and its `with:` indented together inside the
{{`#is_node`}} block, but move `- run: npm install -g pnpm` and `- run: pnpm
install` out to be sibling list items (still wrapped by
{{`#is_node`}}...{{/is_node}}), and do the same for the bun block around `uses:
oven-sh/setup-bun@v2` and `- run: bun install`, ensuring no `run:` lines are
nested under a `with:` mapping.

In `@cli/src/templates/project/service/scripts/enforce-retention.ts`:
- Around line 12-15: The script unconditionally calls
ci.resolve(tokens.RetentionService) which will throw if RetentionService isn't
registered; wrap that resolution in a guard (either check registration if the
container exposes a has/isRegistered method or use a try/catch around
ci.resolve(tokens.RetentionService)), and if the service is not available log a
clear message and exit/return gracefully instead of letting the script crash;
update the resolution of retentionService (and keep otel resolution as-is) so
the script handles absence of RetentionService without throwing.

---

Nitpick comments:
In `@cli/src/core/ast/infrastructure/compliance.rs`:
- Around line 603-605: The if-condition that filters files is more complex than
necessary: remove the redundant ".d.ts" check and only keep the check for
".entity.ts" by changing the condition that currently uses
file_name.ends_with(".entity.ts") || file_name.ends_with(".d.ts") to a single
negative check on file_name.ends_with(".entity.ts") (i.e., if
!file_name.ends_with(".entity.ts") { continue; }) so the logic reads clearly;
update the if block around the file_name variable in compliance.rs accordingly.
- Around line 158-171: resolve_ts_file currently only checks for ".ts"; update
it to try multiple TypeScript extensions (e.g., "ts", "tsx", "mts", "cts") when
resolving a file or its index. Implement a small loop over the extensions
(instead of a single with_extension("ts") call) to test base.with_extension(ext)
and base.join("index." + ext) so resolve_ts_file returns the first existing
PathBuf for any supported TS extension; keep the existing behavior of returning
Some(path) when base is already a file.

In `@COMPLIANCE_GAPS_PLAN.md`:
- Around line 175-181: The fenced code block containing the checklist lines
starting with "Step 1: GDPR module (erase + export) ..." should include a
language specifier to satisfy markdown linters and improve rendering; update the
opening fence from ``` to ```text (or ```plaintext) so the block reads like
"```text" and keep the block contents unchanged (the lines listing Step 1
through Step 5) to ensure correct formatting and lint compliance.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ffb48034-ef3c-4a3a-b616-4a0ece100eab

📥 Commits

Reviewing files that changed from the base of the PR and between be8c669 and 38f33ac.

📒 Files selected for processing (22)
  • COMPLIANCE_COVERAGE.md
  • COMPLIANCE_GAPS_PLAN.md
  • blueprint/billing-base/api/controllers/compliance.controller.ts
  • blueprint/billing-stripe/registrations.ts
  • blueprint/iam-base/api/controllers/compliance.controller.ts
  • blueprint/iam-base/sdk.ts
  • cli/src/compliance/audit.rs
  • cli/src/core/ast/infrastructure.rs
  • cli/src/core/ast/infrastructure/compliance.rs
  • cli/src/core/ast/transformations/transform_base_entity_ts.rs
  • cli/src/core/package_json/package_json_constants.rs
  • cli/src/core/package_json/project_package_json.rs
  • cli/src/core/validate.rs
  • cli/src/init/service.rs
  • cli/src/sync/all.rs
  • cli/src/templates/github/ci.yml
  • cli/src/templates/project/service/scripts/enforce-retention.ts
  • cli/src/templates/router/domain/types/{{camel_case_name}}EventRecord.types.ts
  • framework/core/src/persistence/complianceTypes.ts
  • framework/core/src/persistence/index.ts
  • framework/core/src/services/retentionService.ts
  • framework/ws/src/channels.ts
✅ Files skipped from review due to trivial changes (2)
  • cli/src/core/ast/infrastructure.rs
  • COMPLIANCE_COVERAGE.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • blueprint/billing-stripe/registrations.ts
  • cli/src/core/ast/transformations/transform_base_entity_ts.rs
  • blueprint/iam-base/api/controllers/compliance.controller.ts
  • framework/ws/src/channels.ts
  • blueprint/billing-base/api/controllers/compliance.controller.ts

Comment thread cli/src/init/service.rs Outdated
Comment thread cli/src/templates/github/ci.yml
Comment thread cli/src/templates/project/service/scripts/enforce-retention.ts
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