feat: Compliance as Code - #124
Conversation
|
Note Reviews pausedIt 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 Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis 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
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
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
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
Poem
✨ Finishing Touches🧪 Generate unit tests (beta)
|
There was a problem hiding this comment.
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 | 🟡 MinorInconsistent 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 useallowedPermissions: PLATFORM_READ_PERMISSIONS(lines 120, 159). This creates two issues:
- Inconsistent field names (
allowedRolesvsallowedPermissions)- Using read permissions for write operations is semantically incorrect
Update and delete should use
allowedPermissions: PLATFORM_WRITE_PERMISSIONSto 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 | 🟡 MinorFix 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 | 🟡 MinorClean 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.5Also 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 | 🟡 MinorResolve 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.5Also 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 | 🟡 MinorPlease 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.5Also 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 | 🟡 MinorFix 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.5Also 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 | 🟡 MinorFix 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 | 🟡 MinorCorrect 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 | 🟡 MinorFix 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 | 🟡 MinorRemove 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 | 🟡 MinorCorrect the lockfile path in cleanup script.
Line 34 uses
pnpm.lock.yaml; this should bepnpm-lock.yamlfor 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 | 🟡 MinorFix lockfile name in clean script.
Line 35 uses
pnpm.lock.yaml, but pnpm’s lockfile ispnpm-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 | 🟡 MinorTypographical 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 | 🟡 MinorPeer dependency version mismatch with devDependency.
The
peerDependenciesspecifiesvitest: "^3.0.0"whiledevDependenciesusesvitest: "^4.1.1". This mismatch could cause confusion for consumers. Consider updating the peer dependency to^4.0.0to 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 | 🟡 MinorDuplicate "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 | 🟡 MinorFix 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.5Also 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 | 🟡 MinorInconsistent
@typescript/native-previewversion across packages.This package uses
7.0.0-dev.20260320.1whileframework/coreandframework/expressuse7.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 | 🟡 MinorSame
@typescript/native-previewversion inconsistency.This package also uses
7.0.0-dev.20260320.1, differing fromframework/coreandframework/express. See the comment onblueprint/implementations/iam/base/package.jsonfor 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 | 🟡 MinorFix 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 | 🟡 MinorRemove 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 | 🟡 MinorUpdate
@typescript/native-previewto a current version.The version was changed to
7.0.0-dev.20260301.1(March 1, 2026), which is 19 days older than the previous7.0.0-dev.20260320.1and does not appear in recent npm releases. Current available versions are dated March 15–24, 2026. Either use7.0.0-dev.20260320.1or 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 | 🟡 MinorFix 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 | 🟡 MinorRemove duplicate "Updated dependencies" entry.
There are two consecutive
- Updated dependenciesbullets 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 | 🟡 MinorInconsistency:
urifield missingunique()andnullable()modifiers.The base
CheckoutSessionentity inblueprint/billing-base/persistence/entities/checkoutSession.entity.ts(lines 7-24 in relevant snippets) definesurias: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 | 🟡 MinorChange
'pii'.The email field should be classified as
.compliance('pii'), not'none'. The framework's own test cases and documentation consistently usecompliance('pii')for email fields (seeframework/core/__test__/compliance.typetest.tsandcompliancePropertyBuilder.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 | 🟡 MinorDocument the compliance classification for
providerFieldsor update if necessary.The
providerFieldsfield is marked ascompliance('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 onlynullvalues, 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 | 🟡 MinorExample 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 | 🟡 MinorPotential 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 | 🟡 MinorSame
taxIdclassification 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 | 🟡 MinorEmpty
tenantIddefaults to shared key derivation.When
tenantIdis 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 throwingEncryptionRequiredErrorwhentenantIdis 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
⛔ Files ignored due to path filters (3)
blueprint/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlframework/core/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlframework/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (180)
blueprint/billing-base/api/controllers/billingPortal.controller.tsblueprint/billing-base/api/controllers/checkoutSession.controller.tsblueprint/billing-base/api/controllers/paymentLink.controller.tsblueprint/billing-base/api/controllers/plan.controller.tsblueprint/billing-base/api/controllers/subscription.controller.tsblueprint/billing-base/package.jsonblueprint/billing-base/persistence/entities/billingPortal.entity.tsblueprint/billing-base/persistence/entities/billingProvider.entity.tsblueprint/billing-base/persistence/entities/checkoutSession.entity.tsblueprint/billing-base/persistence/entities/paymentLink.entity.tsblueprint/billing-base/persistence/entities/plan.entity.tsblueprint/billing-base/persistence/entities/subscription.entity.tsblueprint/billing-stripe/api/controllers/billingPortal.controller.tsblueprint/billing-stripe/api/controllers/checkoutSession.controller.tsblueprint/billing-stripe/api/controllers/paymentLink.controller.tsblueprint/billing-stripe/api/controllers/plan.controller.tsblueprint/billing-stripe/api/controllers/subscription.controller.tsblueprint/billing-stripe/api/controllers/webhook.controller.tsblueprint/billing-stripe/package.jsonblueprint/billing-stripe/persistence/entities/billingPortal.entity.tsblueprint/billing-stripe/persistence/entities/checkoutSession.entity.tsblueprint/billing-stripe/persistence/entities/paymentLink.entity.tsblueprint/billing-stripe/persistence/entities/plan.entity.tsblueprint/billing-stripe/persistence/entities/stripeWebhookEvent.entity.tsblueprint/billing-stripe/persistence/entities/subscription.entity.tsblueprint/client-sdk/package.jsonblueprint/core/package.jsonblueprint/core/persistence/nosql.base.properties.tsblueprint/core/persistence/sql.base.properties.tsblueprint/iam-base/api/controllers/discovery.controller.tsblueprint/iam-base/api/controllers/organization.controller.tsblueprint/iam-base/api/controllers/permission.controller.tsblueprint/iam-base/api/controllers/role.controller.tsblueprint/iam-base/api/controllers/user.controller.tsblueprint/iam-base/package.jsonblueprint/iam-base/persistence/entities/organization.entity.tsblueprint/iam-base/persistence/entities/permission.entity.tsblueprint/iam-base/persistence/entities/role.entity.tsblueprint/iam-base/persistence/entities/user.entity.tsblueprint/iam-better-auth/api/controllers/discovery.controller.tsblueprint/iam-better-auth/api/controllers/user.controller.tsblueprint/iam-better-auth/package.jsonblueprint/iam-better-auth/persistence/entities/account.entity.tsblueprint/iam-better-auth/persistence/entities/invitation.entity.tsblueprint/iam-better-auth/persistence/entities/jwks.entity.tsblueprint/iam-better-auth/persistence/entities/member.entity.tsblueprint/iam-better-auth/persistence/entities/organization.entity.tsblueprint/iam-better-auth/persistence/entities/organizationRole.entity.tsblueprint/iam-better-auth/persistence/entities/session.entity.tsblueprint/iam-better-auth/persistence/entities/team.entity.tsblueprint/iam-better-auth/persistence/entities/teamMember.entity.tsblueprint/iam-better-auth/persistence/entities/user.entity.tsblueprint/iam-better-auth/persistence/entities/verification.entity.tsblueprint/implementations/billing/base/CHANGELOG.mdblueprint/implementations/billing/base/package.jsonblueprint/implementations/billing/base/persistence/entities/index.tsblueprint/implementations/billing/stripe/CHANGELOG.mdblueprint/implementations/billing/stripe/package.jsonblueprint/implementations/billing/stripe/persistence/entities/index.tsblueprint/implementations/billing/stripe/services/webhook.service.tsblueprint/implementations/iam/base/CHANGELOG.mdblueprint/implementations/iam/base/package.jsonblueprint/implementations/iam/base/persistence/entities/index.tsblueprint/implementations/worker/bullmq/CHANGELOG.mdblueprint/implementations/worker/bullmq/package.jsonblueprint/implementations/worker/database/CHANGELOG.mdblueprint/implementations/worker/database/package.jsonblueprint/implementations/worker/kafka/CHANGELOG.mdblueprint/implementations/worker/kafka/package.jsonblueprint/implementations/worker/redis/CHANGELOG.mdblueprint/implementations/worker/redis/package.jsonblueprint/interfaces/billing/CHANGELOG.mdblueprint/interfaces/billing/package.jsonblueprint/interfaces/iam/CHANGELOG.mdblueprint/interfaces/iam/package.jsonblueprint/interfaces/worker/CHANGELOG.mdblueprint/interfaces/worker/package.jsonblueprint/monitoring/package.jsonblueprint/package.jsonblueprint/sample-worker/api/controllers/sampleWorker.controller.tsblueprint/sample-worker/package.jsonblueprint/sample-worker/persistence/entities/sampleWorkerRecord.entity.tsblueprint/tsconfig.base.jsoncli/src/compliance/audit.rscli/src/compliance/mod.rscli/src/core/env_defaults.rscli/src/core/env_scope.rscli/src/core/manifest.rscli/src/core/package_json/package_json_constants.rscli/src/init/application.rscli/src/init/library.rscli/src/init/module.rscli/src/init/service.rscli/src/init/worker.rscli/src/main.rscli/src/release/create.rscli/src/templates/router/persistence/entities/{{camel_case_name}}Record.entity.tsdocs/COMPLIANCE_FRAMEWORK_PLAN.mddocs/PLATFORM_HANDOFF.mdframework/bunrun/CHANGELOG.mdframework/bunrun/package.jsonframework/common/CHANGELOG.mdframework/common/package.jsonframework/core/CHANGELOG.mdframework/core/__test__/auditLogger.test.tsframework/core/__test__/baseEntity.partialUpdate.integration.test.tsframework/core/__test__/compliance.test.tsframework/core/__test__/compliance.typetest.tsframework/core/__test__/complianceEventSubscriber.test.tsframework/core/__test__/configInjector.test.tsframework/core/__test__/contractDetails.types.test.tsframework/core/__test__/expressLikeRouterInstantiation.test.tsframework/core/__test__/fieldEncryptor.test.tsframework/core/__test__/http.middleware.test.tsframework/core/__test__/mcpGenerator.test.tsframework/core/__test__/openApiV3Generator.test.tsframework/core/__test__/rateLimiter.test.tsframework/core/__test__/rls.test.tsframework/core/__test__/secretsAccessor.test.tsframework/core/__test__/tenantContext.test.tsframework/core/__test__/tenantFilter.test.tsframework/core/package.jsonframework/core/src/encryption/fieldEncryptor.tsframework/core/src/encryption/index.tsframework/core/src/http/index.tsframework/core/src/http/middleware/request/tenantContext.middleware.tsframework/core/src/http/rateLimit/index.tsframework/core/src/http/rateLimit/rateLimiter.tsframework/core/src/http/router/routerSharedLogic.tsframework/core/src/http/telemetry/auditLogger.tsframework/core/src/http/types/contractDetails.types.tsframework/core/src/persistence/complianceEventSubscriber.tsframework/core/src/persistence/compliancePropertyBuilder.tsframework/core/src/persistence/complianceTypes.tsframework/core/src/persistence/defineComplianceEntity.tsframework/core/src/persistence/index.tsframework/core/src/persistence/rls.tsframework/core/src/persistence/tenantFilter.tsframework/core/src/secrets/index.tsframework/core/src/secrets/secretsAccessor.tsframework/core/tsconfig.jsonframework/e2e-tests/package.jsonframework/e2e-tests/servers/express-typebox.tsframework/e2e-tests/servers/express-zod-cluster.tsframework/e2e-tests/servers/express-zod-raw.tsframework/e2e-tests/servers/express-zod.tsframework/e2e-tests/servers/hyper-express-typebox.tsframework/e2e-tests/servers/hyper-express-zod-cluster.tsframework/e2e-tests/servers/hyper-express-zod.tsframework/e2e-tests/servers/vanilla-express-router.tsframework/express/CHANGELOG.mdframework/express/__test__/port.test.tsframework/express/__test__/typebox.forklaunch.express.test.tsframework/express/__test__/zod.forklaunch.express.test.tsframework/express/package.jsonframework/hyper-express/CHANGELOG.mdframework/hyper-express/__test__/port.test.tsframework/hyper-express/__test__/typebox.forklaunch.hyperExpress.test.tsframework/hyper-express/__test__/zod.forklaunch.hyperExpress.test.tsframework/hyper-express/package.jsonframework/infrastructure/S3/CHANGELOG.mdframework/infrastructure/S3/package.jsonframework/infrastructure/redis/CHANGELOG.mdframework/infrastructure/redis/package.jsonframework/internal/CHANGELOG.mdframework/internal/package.jsonframework/package.jsonframework/testing/CHANGELOG.mdframework/testing/package.jsonframework/tsconfig.base.jsonframework/universal-sdk/CHANGELOG.mdframework/universal-sdk/package.jsonframework/validator/CHANGELOG.mdframework/validator/package.jsonframework/ws/CHANGELOG.mdframework/ws/package.jsonframework/ws/src/__tests__/channels.test.tsframework/ws/src/channels.tsframework/ws/src/secureWebSocketServer.tsframework/ws/src/wsSession.ts
There was a problem hiding this comment.
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/coreis 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/coreis 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
📒 Files selected for processing (22)
.github/dependabot.ymlCOMPLIANCE_COVERAGE.mdCOMPLIANCE_GAPS_PLAN.mdblueprint/billing-base/api/controllers/compliance.controller.tsblueprint/billing-base/api/controllers/index.tsblueprint/billing-stripe/registrations.tsblueprint/iam-base/api/controllers/compliance.controller.tsblueprint/iam-base/api/controllers/index.tsblueprint/iam-better-auth/auth.tsblueprint/implementations/billing/stripe/CHANGELOG.mdblueprint/implementations/billing/stripe/package.jsonblueprint/implementations/billing/stripe/services/webhook.service.tscli/src/compliance/audit.rscli/src/core.rscli/src/core/github_configs.rscli/src/core/package_json/package_json_constants.rscli/src/init/application.rscli/src/templates/github/BRANCH_PROTECTION.mdcli/src/templates/github/ci.ymlcli/src/templates/github/dependabot.ymlcli/src/templates/router/api/controllers/{{camel_case_name}}.controller.tscompliance-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
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (6)
framework/ws/src/channels.ts (2)
136-150: Consider including delivery count in the audit entry.The
deliveredcount 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
AuditEntrycan be extended, a dedicatedmetadataorrecipientCountfield 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 individualsend()calls to prevent one failure from aborting the broadcast.A race exists between the
readyStatecheck andsend()—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
retentionAnonymizedAtis 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 sharedisRecordguard for consistencyThis 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 keysThe current OR logic accepts objects where one permission key is valid while another is present but malformed (e.g.,
allowedPermissions: "invalid"withforbiddenPermissions: 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
hasRoleChecksuses 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 toretention.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
📒 Files selected for processing (18)
blueprint/core/persistence/nosql.base.properties.tsblueprint/core/persistence/sql.base.properties.tsblueprint/iam-better-auth/persistence/entities/account.entity.tsblueprint/iam-better-auth/persistence/entities/jwks.entity.tsblueprint/implementations/billing/stripe/persistence/entities/index.tscli/src/compliance/audit.rscli/src/core/ast/transformations/transform_base_entity_ts.rscli/src/core/manifest.rscli/src/templates/project/service/registrations.tscli/src/templates/project/service/server.tscompliance-coverage.htmlframework/core/src/http/guards/hasPermissionChecks.tsframework/core/src/persistence/complianceTypes.tsframework/core/src/persistence/defineComplianceEntity.tsframework/core/src/persistence/index.tsframework/core/src/services/index.tsframework/core/src/services/retentionService.tsframework/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
There was a problem hiding this comment.
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 fromclean.
pnpm.lock.yamlis 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 fromclean.
pnpm.lock.yamlis 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 fromclean.
pnpm.lock.yamlis 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
⛔ Files ignored due to path filters (2)
blueprint/pnpm-lock.yamlis excluded by!**/pnpm-lock.yamlframework/pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (54)
blueprint/billing-base/package.jsonblueprint/billing-stripe/package.jsonblueprint/core/package.jsonblueprint/iam-base/package.jsonblueprint/iam-better-auth/package.jsonblueprint/implementations/billing/base/CHANGELOG.mdblueprint/implementations/billing/base/package.jsonblueprint/implementations/billing/stripe/CHANGELOG.mdblueprint/implementations/billing/stripe/package.jsonblueprint/implementations/iam/base/CHANGELOG.mdblueprint/implementations/iam/base/package.jsonblueprint/implementations/worker/bullmq/CHANGELOG.mdblueprint/implementations/worker/bullmq/package.jsonblueprint/implementations/worker/database/CHANGELOG.mdblueprint/implementations/worker/database/package.jsonblueprint/implementations/worker/kafka/CHANGELOG.mdblueprint/implementations/worker/kafka/package.jsonblueprint/implementations/worker/redis/CHANGELOG.mdblueprint/implementations/worker/redis/package.jsonblueprint/interfaces/billing/CHANGELOG.mdblueprint/interfaces/billing/package.jsonblueprint/interfaces/iam/CHANGELOG.mdblueprint/interfaces/iam/package.jsonblueprint/interfaces/worker/CHANGELOG.mdblueprint/interfaces/worker/package.jsonblueprint/monitoring/package.jsonblueprint/package.jsonblueprint/sample-worker/package.jsoncli/src/core/package_json/package_json_constants.rsframework/bunrun/CHANGELOG.mdframework/bunrun/package.jsonframework/common/CHANGELOG.mdframework/common/package.jsonframework/core/CHANGELOG.mdframework/core/package.jsonframework/e2e-tests/package.jsonframework/express/CHANGELOG.mdframework/express/package.jsonframework/hyper-express/CHANGELOG.mdframework/hyper-express/package.jsonframework/infrastructure/S3/CHANGELOG.mdframework/infrastructure/S3/package.jsonframework/infrastructure/redis/CHANGELOG.mdframework/infrastructure/redis/package.jsonframework/internal/CHANGELOG.mdframework/internal/package.jsonframework/testing/CHANGELOG.mdframework/testing/package.jsonframework/universal-sdk/CHANGELOG.mdframework/universal-sdk/package.jsonframework/validator/CHANGELOG.mdframework/validator/package.jsonframework/ws/CHANGELOG.mdframework/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
There was a problem hiding this comment.
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.,
textorplaintext) 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.tscheck is redundant since.d.tsfiles 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_fileonly resolves.tsfiles. If entity base properties are ever placed in.tsxor.mtsfiles, 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
📒 Files selected for processing (22)
COMPLIANCE_COVERAGE.mdCOMPLIANCE_GAPS_PLAN.mdblueprint/billing-base/api/controllers/compliance.controller.tsblueprint/billing-stripe/registrations.tsblueprint/iam-base/api/controllers/compliance.controller.tsblueprint/iam-base/sdk.tscli/src/compliance/audit.rscli/src/core/ast/infrastructure.rscli/src/core/ast/infrastructure/compliance.rscli/src/core/ast/transformations/transform_base_entity_ts.rscli/src/core/package_json/package_json_constants.rscli/src/core/package_json/project_package_json.rscli/src/core/validate.rscli/src/init/service.rscli/src/sync/all.rscli/src/templates/github/ci.ymlcli/src/templates/project/service/scripts/enforce-retention.tscli/src/templates/router/domain/types/{{camel_case_name}}EventRecord.types.tsframework/core/src/persistence/complianceTypes.tsframework/core/src/persistence/index.tsframework/core/src/services/retentionService.tsframework/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
Summary by CodeRabbit
New Features
Improvements
Chores