create-forgeon 0.3.16 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/package.json +1 -1
  2. package/src/cli/add-options.test.mjs +5 -2
  3. package/src/cli/options.test.mjs +1 -0
  4. package/src/cli/prompt-select.test.mjs +1 -0
  5. package/src/core/docs.test.mjs +1 -0
  6. package/src/core/scaffold.test.mjs +1 -0
  7. package/src/core/validate.test.mjs +1 -0
  8. package/src/modules/accounts.mjs +416 -0
  9. package/src/modules/db-prisma.mjs +5 -9
  10. package/src/modules/dependencies.test.mjs +71 -29
  11. package/src/modules/executor.mjs +3 -2
  12. package/src/modules/executor.test.mjs +521 -477
  13. package/src/modules/files-access.mjs +9 -7
  14. package/src/modules/files-image.mjs +9 -7
  15. package/src/modules/files-local.mjs +15 -6
  16. package/src/modules/files-quotas.mjs +8 -6
  17. package/src/modules/files-s3.mjs +17 -6
  18. package/src/modules/files.mjs +21 -21
  19. package/src/modules/idempotency.test.mjs +13 -7
  20. package/src/modules/probes.test.mjs +4 -2
  21. package/src/modules/queue.mjs +9 -6
  22. package/src/modules/rate-limit.mjs +14 -10
  23. package/src/modules/rbac.mjs +12 -11
  24. package/src/modules/registry.mjs +22 -35
  25. package/src/modules/scheduler.mjs +9 -6
  26. package/src/modules/shared/files-runtime-wiring.mjs +81 -0
  27. package/src/modules/shared/patch-utils.mjs +29 -1
  28. package/src/modules/sync-integrations.mjs +102 -422
  29. package/src/modules/sync-integrations.test.mjs +32 -111
  30. package/src/run-add-module.test.mjs +1 -0
  31. package/templates/base/scripts/forgeon-sync-integrations.mjs +65 -325
  32. package/templates/module-fragments/{jwt-auth → accounts}/00_title.md +2 -1
  33. package/templates/module-fragments/{jwt-auth → accounts}/10_overview.md +5 -5
  34. package/templates/module-fragments/accounts/20_scope.md +29 -0
  35. package/templates/module-fragments/accounts/90_status_implemented.md +8 -0
  36. package/templates/module-fragments/accounts/90_status_planned.md +7 -0
  37. package/templates/module-fragments/rbac/30_what_it_adds.md +3 -2
  38. package/templates/module-fragments/rbac/40_how_it_works.md +2 -1
  39. package/templates/module-fragments/rbac/50_how_to_use.md +2 -1
  40. package/templates/module-fragments/swagger/20_scope.md +2 -1
  41. package/templates/module-presets/accounts/apps/api/prisma/migrations/0002_accounts_core/migration.sql +97 -0
  42. package/templates/module-presets/accounts/apps/api/src/accounts/forgeon-accounts-db-prisma.module.ts +17 -0
  43. package/templates/module-presets/accounts/apps/api/src/accounts/prisma-accounts-persistence.store.ts +332 -0
  44. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/package.json +5 -5
  45. package/templates/module-presets/accounts/packages/accounts-api/src/accounts-email.port.ts +13 -0
  46. package/templates/module-presets/accounts/packages/accounts-api/src/accounts-persistence.port.ts +67 -0
  47. package/templates/module-presets/accounts/packages/accounts-api/src/accounts-rbac.port.ts +14 -0
  48. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-config.loader.ts +7 -7
  49. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-config.service.ts +7 -7
  50. package/templates/module-presets/accounts/packages/accounts-api/src/auth-core.service.ts +318 -0
  51. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-env.schema.ts +4 -4
  52. package/templates/module-presets/accounts/packages/accounts-api/src/auth-jwt.service.ts +58 -0
  53. package/templates/module-presets/accounts/packages/accounts-api/src/auth-password.service.ts +21 -0
  54. package/templates/module-presets/accounts/packages/accounts-api/src/auth.controller.ts +93 -0
  55. package/templates/module-presets/accounts/packages/accounts-api/src/auth.service.ts +48 -0
  56. package/templates/module-presets/accounts/packages/accounts-api/src/auth.types.ts +17 -0
  57. package/templates/module-presets/accounts/packages/accounts-api/src/dto/change-password.dto.ts +13 -0
  58. package/templates/module-presets/accounts/packages/accounts-api/src/dto/confirm-password-reset.dto.ts +12 -0
  59. package/templates/module-presets/accounts/packages/accounts-api/src/dto/index.ts +10 -0
  60. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/dto/login.dto.ts +1 -1
  61. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/dto/refresh.dto.ts +1 -1
  62. package/templates/module-presets/accounts/packages/accounts-api/src/dto/register.dto.ts +23 -0
  63. package/templates/module-presets/accounts/packages/accounts-api/src/dto/request-password-reset.dto.ts +7 -0
  64. package/templates/module-presets/accounts/packages/accounts-api/src/dto/update-user-profile.dto.ts +16 -0
  65. package/templates/module-presets/accounts/packages/accounts-api/src/dto/update-user-settings.dto.ts +16 -0
  66. package/templates/module-presets/accounts/packages/accounts-api/src/dto/update-user.dto.ts +8 -0
  67. package/templates/module-presets/accounts/packages/accounts-api/src/dto/verify-email.dto.ts +8 -0
  68. package/templates/module-presets/accounts/packages/accounts-api/src/forgeon-accounts.module.ts +82 -0
  69. package/templates/module-presets/accounts/packages/accounts-api/src/index.ts +24 -0
  70. package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/jwt.strategy.ts +3 -3
  71. package/templates/module-presets/accounts/packages/accounts-api/src/owner-access.guard.ts +39 -0
  72. package/templates/module-presets/accounts/packages/accounts-api/src/users-config.ts +13 -0
  73. package/templates/module-presets/accounts/packages/accounts-api/src/users.controller.ts +65 -0
  74. package/templates/module-presets/accounts/packages/accounts-api/src/users.service.ts +87 -0
  75. package/templates/module-presets/accounts/packages/accounts-api/src/users.types.ts +65 -0
  76. package/templates/module-presets/{jwt-auth/packages/auth-contracts → accounts/packages/accounts-contracts}/package.json +1 -1
  77. package/templates/module-presets/accounts/packages/accounts-contracts/src/index.ts +119 -0
  78. package/templates/module-presets/db-prisma/apps/api/prisma/seed.ts +40 -19
  79. package/templates/module-presets/files/apps/api/src/files/forgeon-files-db-prisma.module.ts +17 -0
  80. package/templates/module-presets/files/apps/api/src/files/prisma-files-persistence.store.ts +164 -0
  81. package/templates/module-presets/files/packages/files/package.json +1 -2
  82. package/templates/module-presets/files/packages/files/src/files.ports.ts +107 -0
  83. package/templates/module-presets/files/packages/files/src/files.service.ts +81 -395
  84. package/templates/module-presets/files/packages/files/src/forgeon-files.module.ts +126 -2
  85. package/templates/module-presets/files/packages/files/src/index.ts +2 -1
  86. package/templates/module-presets/files-local/packages/files-local/src/forgeon-files-local-storage.module.ts +18 -0
  87. package/templates/module-presets/files-local/packages/files-local/src/index.ts +2 -0
  88. package/templates/module-presets/files-local/packages/files-local/src/local-files-storage.adapter.ts +53 -0
  89. package/templates/module-presets/files-s3/packages/files-s3/src/forgeon-files-s3-storage.module.ts +18 -0
  90. package/templates/module-presets/files-s3/packages/files-s3/src/index.ts +2 -0
  91. package/templates/module-presets/files-s3/packages/files-s3/src/s3-files-storage.adapter.ts +130 -0
  92. package/src/modules/jwt-auth.mjs +0 -271
  93. package/templates/module-fragments/jwt-auth/20_scope.md +0 -19
  94. package/templates/module-fragments/jwt-auth/90_status_implemented.md +0 -8
  95. package/templates/module-fragments/jwt-auth/90_status_planned.md +0 -3
  96. package/templates/module-presets/jwt-auth/apps/api/prisma/migrations/0002_auth_refresh_token_hash/migration.sql +0 -3
  97. package/templates/module-presets/jwt-auth/apps/api/src/auth/prisma-auth-refresh-token.store.ts +0 -36
  98. package/templates/module-presets/jwt-auth/packages/auth-api/src/auth-refresh-token.store.ts +0 -23
  99. package/templates/module-presets/jwt-auth/packages/auth-api/src/auth.controller.ts +0 -71
  100. package/templates/module-presets/jwt-auth/packages/auth-api/src/auth.service.ts +0 -175
  101. package/templates/module-presets/jwt-auth/packages/auth-api/src/auth.types.ts +0 -6
  102. package/templates/module-presets/jwt-auth/packages/auth-api/src/dto/index.ts +0 -2
  103. package/templates/module-presets/jwt-auth/packages/auth-api/src/forgeon-auth.module.ts +0 -47
  104. package/templates/module-presets/jwt-auth/packages/auth-api/src/index.ts +0 -12
  105. package/templates/module-presets/jwt-auth/packages/auth-contracts/src/index.ts +0 -47
  106. /package/templates/module-presets/{jwt-auth/packages/auth-api/src/jwt-auth.guard.ts → accounts/packages/accounts-api/src/access-token.guard.ts} +0 -0
  107. /package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/src/auth-config.module.ts +0 -0
  108. /package/templates/module-presets/{jwt-auth/packages/auth-api → accounts/packages/accounts-api}/tsconfig.json +0 -0
  109. /package/templates/module-presets/{jwt-auth/packages/auth-contracts → accounts/packages/accounts-contracts}/tsconfig.json +0 -0
@@ -1,4 +1,4 @@
1
- import fs from 'node:fs';
1
+ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { copyRecursive, writeJson } from '../utils/fs.mjs';
4
4
  import {
@@ -65,10 +65,10 @@ function patchAppModule(targetRoot) {
65
65
  content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesAccessModule,');
66
66
  } else if (content.includes(' ForgeonI18nModule.register({')) {
67
67
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesAccessModule,');
68
- } else if (content.includes(' ForgeonAuthModule.register({')) {
69
- content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonFilesAccessModule,');
70
- } else if (content.includes(' ForgeonAuthModule.register(),')) {
71
- content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonFilesAccessModule,');
68
+ } else if (content.includes(' ForgeonAccountsModule.register({')) {
69
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonFilesAccessModule,');
70
+ } else if (content.includes(' ForgeonAccountsModule.register(),')) {
71
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonFilesAccessModule,');
72
72
  } else if (content.includes(' DbPrismaModule,')) {
73
73
  content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesAccessModule,');
74
74
  } else if (content.includes(' ForgeonLoggerModule,')) {
@@ -274,7 +274,7 @@ function patchApiDockerfile(targetRoot) {
274
274
  'COPY packages/files/package.json packages/files/package.json',
275
275
  'COPY packages/files-local/package.json packages/files-local/package.json',
276
276
  'COPY packages/files-s3/package.json packages/files-s3/package.json',
277
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
277
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
278
278
  'COPY packages/rbac/package.json packages/rbac/package.json',
279
279
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
280
280
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -294,7 +294,7 @@ function patchApiDockerfile(targetRoot) {
294
294
  'COPY packages/files packages/files',
295
295
  'COPY packages/files-local packages/files-local',
296
296
  'COPY packages/files-s3 packages/files-s3',
297
- 'COPY packages/auth-api packages/auth-api',
297
+ 'COPY packages/accounts-api packages/accounts-api',
298
298
  'COPY packages/rbac packages/rbac',
299
299
  'COPY packages/rate-limit packages/rate-limit',
300
300
  'COPY packages/logger packages/logger',
@@ -373,3 +373,5 @@ export function applyFilesAccessModule({ packageRoot, targetRoot }) {
373
373
  patchApiDockerfile(targetRoot);
374
374
  patchReadme(targetRoot);
375
375
  }
376
+
377
+
@@ -1,4 +1,4 @@
1
- import fs from 'node:fs';
1
+ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { copyRecursive, writeJson } from '../utils/fs.mjs';
4
4
  import {
@@ -95,10 +95,10 @@ function patchAppModule(targetRoot) {
95
95
  if (!content.includes(' ForgeonFilesImageModule,')) {
96
96
  if (content.includes(' ForgeonI18nModule.register({')) {
97
97
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesImageModule,');
98
- } else if (content.includes(' ForgeonAuthModule.register({')) {
99
- content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonFilesImageModule,');
100
- } else if (content.includes(' ForgeonAuthModule.register(),')) {
101
- content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonFilesImageModule,');
98
+ } else if (content.includes(' ForgeonAccountsModule.register({')) {
99
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonFilesImageModule,');
100
+ } else if (content.includes(' ForgeonAccountsModule.register(),')) {
101
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonFilesImageModule,');
102
102
  } else if (content.includes(' ForgeonFilesModule,')) {
103
103
  content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesImageModule,');
104
104
  } else if (content.includes(' DbPrismaModule,')) {
@@ -342,7 +342,7 @@ function patchApiDockerfile(targetRoot) {
342
342
  'COPY packages/files/package.json packages/files/package.json',
343
343
  'COPY packages/files-local/package.json packages/files-local/package.json',
344
344
  'COPY packages/files-s3/package.json packages/files-s3/package.json',
345
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
345
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
346
346
  'COPY packages/rbac/package.json packages/rbac/package.json',
347
347
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
348
348
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -364,7 +364,7 @@ function patchApiDockerfile(targetRoot) {
364
364
  'COPY packages/files packages/files',
365
365
  'COPY packages/files-local packages/files-local',
366
366
  'COPY packages/files-s3 packages/files-s3',
367
- 'COPY packages/auth-api packages/auth-api',
367
+ 'COPY packages/accounts-api packages/accounts-api',
368
368
  'COPY packages/rbac packages/rbac',
369
369
  'COPY packages/rate-limit packages/rate-limit',
370
370
  'COPY packages/logger packages/logger',
@@ -508,3 +508,5 @@ export function applyFilesImageModule({ packageRoot, targetRoot }) {
508
508
  'FILES_IMAGE_ALLOWED_MIME_TYPES=image/jpeg,image/png,image/webp',
509
509
  ]);
510
510
  }
511
+
512
+
@@ -9,8 +9,10 @@ import {
9
9
  ensureLineBefore,
10
10
  ensureLoadItem,
11
11
  ensureValidatorSchema,
12
+ ensureNamedImportSpecifier,
12
13
  upsertEnvLines,
13
14
  } from './shared/patch-utils.mjs';
15
+ import { resolveFilesStorageRuntimeModule, upsertFilesModuleRegistration } from './shared/files-runtime-wiring.mjs';
14
16
 
15
17
  function copyFromPreset(packageRoot, targetRoot, relativePath) {
16
18
  const source = path.join(packageRoot, 'templates', 'module-presets', 'files-local', relativePath);
@@ -40,16 +42,18 @@ function patchAppModule(targetRoot) {
40
42
  }
41
43
 
42
44
  let content = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
43
- content = ensureImportLine(
44
- content,
45
- "import { filesLocalConfig, filesLocalEnvSchemaZod, FilesLocalConfigModule } from '@forgeon/files-local';",
46
- );
45
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'filesLocalConfig');
46
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'filesLocalEnvSchemaZod');
47
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'FilesLocalConfigModule');
48
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'ForgeonFilesLocalStorageModule');
47
49
  content = ensureLoadItem(content, 'filesLocalConfig');
48
50
  content = ensureValidatorSchema(content, 'filesLocalEnvSchemaZod');
49
51
 
50
52
  if (!content.includes(' FilesLocalConfigModule,')) {
51
53
  if (content.includes(' ForgeonFilesModule,')) {
52
54
  content = ensureLineAfter(content, ' ForgeonFilesModule,', ' FilesLocalConfigModule,');
55
+ } else if (content.includes(' ForgeonFilesModule.register({')) {
56
+ content = ensureLineBefore(content, ' ForgeonFilesModule.register({', ' FilesLocalConfigModule,');
53
57
  } else if (content.includes(' ForgeonI18nModule.register({')) {
54
58
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' FilesLocalConfigModule,');
55
59
  } else if (content.includes(' DbPrismaModule,')) {
@@ -61,6 +65,10 @@ function patchAppModule(targetRoot) {
61
65
  }
62
66
  }
63
67
 
68
+ if (content.includes('ForgeonFilesModule')) {
69
+ content = upsertFilesModuleRegistration(content, resolveFilesStorageRuntimeModule(targetRoot));
70
+ }
71
+
64
72
  fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
65
73
  }
66
74
 
@@ -74,7 +82,7 @@ function patchApiDockerfile(targetRoot) {
74
82
 
75
83
  const packageAnchors = [
76
84
  'COPY packages/files/package.json packages/files/package.json',
77
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
85
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
78
86
  'COPY packages/rbac/package.json packages/rbac/package.json',
79
87
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
80
88
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -92,7 +100,7 @@ function patchApiDockerfile(targetRoot) {
92
100
 
93
101
  const sourceAnchors = [
94
102
  'COPY packages/files packages/files',
95
- 'COPY packages/auth-api packages/auth-api',
103
+ 'COPY packages/accounts-api packages/accounts-api',
96
104
  'COPY packages/rbac packages/rbac',
97
105
  'COPY packages/rate-limit packages/rate-limit',
98
106
  'COPY packages/logger packages/logger',
@@ -219,3 +227,4 @@ export function applyFilesLocalModule({ packageRoot, targetRoot }) {
219
227
  'FILES_LOCAL_ROOT=storage/uploads',
220
228
  ]);
221
229
  }
230
+
@@ -75,10 +75,10 @@ function patchAppModule(targetRoot) {
75
75
  content = ensureLineAfter(content, ' ForgeonFilesModule,', ' ForgeonFilesQuotasModule,');
76
76
  } else if (content.includes(' ForgeonI18nModule.register({')) {
77
77
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesQuotasModule,');
78
- } else if (content.includes(' ForgeonAuthModule.register({')) {
79
- content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonFilesQuotasModule,');
80
- } else if (content.includes(' ForgeonAuthModule.register(),')) {
81
- content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonFilesQuotasModule,');
78
+ } else if (content.includes(' ForgeonAccountsModule.register({')) {
79
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonFilesQuotasModule,');
80
+ } else if (content.includes(' ForgeonAccountsModule.register(),')) {
81
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonFilesQuotasModule,');
82
82
  } else if (content.includes(' DbPrismaModule,')) {
83
83
  content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesQuotasModule,');
84
84
  } else if (content.includes(' ForgeonLoggerModule,')) {
@@ -241,7 +241,7 @@ function patchApiDockerfile(targetRoot) {
241
241
  'COPY packages/files/package.json packages/files/package.json',
242
242
  'COPY packages/files-local/package.json packages/files-local/package.json',
243
243
  'COPY packages/files-s3/package.json packages/files-s3/package.json',
244
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
244
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
245
245
  'COPY packages/rbac/package.json packages/rbac/package.json',
246
246
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
247
247
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -262,7 +262,7 @@ function patchApiDockerfile(targetRoot) {
262
262
  'COPY packages/files packages/files',
263
263
  'COPY packages/files-local packages/files-local',
264
264
  'COPY packages/files-s3 packages/files-s3',
265
- 'COPY packages/auth-api packages/auth-api',
265
+ 'COPY packages/accounts-api packages/accounts-api',
266
266
  'COPY packages/rbac packages/rbac',
267
267
  'COPY packages/rate-limit packages/rate-limit',
268
268
  'COPY packages/logger packages/logger',
@@ -380,3 +380,5 @@ export function applyFilesQuotasModule({ packageRoot, targetRoot }) {
380
380
  ]);
381
381
  }
382
382
 
383
+
384
+
@@ -9,8 +9,10 @@ import {
9
9
  ensureLineBefore,
10
10
  ensureLoadItem,
11
11
  ensureValidatorSchema,
12
+ ensureNamedImportSpecifier,
12
13
  upsertEnvLines,
13
14
  } from './shared/patch-utils.mjs';
15
+ import { resolveFilesStorageRuntimeModule, upsertFilesModuleRegistration } from './shared/files-runtime-wiring.mjs';
14
16
 
15
17
  function copyFromPreset(packageRoot, targetRoot, relativePath) {
16
18
  const source = path.join(packageRoot, 'templates', 'module-presets', 'files-s3', relativePath);
@@ -40,16 +42,18 @@ function patchAppModule(targetRoot) {
40
42
  }
41
43
 
42
44
  let content = fs.readFileSync(filePath, 'utf8').replace(/\r\n/g, '\n');
43
- content = ensureImportLine(
44
- content,
45
- "import { filesS3Config, filesS3EnvSchemaZod, FilesS3ConfigModule } from '@forgeon/files-s3';",
46
- );
45
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'filesS3Config');
46
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'filesS3EnvSchemaZod');
47
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'FilesS3ConfigModule');
48
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'ForgeonFilesS3StorageModule');
47
49
  content = ensureLoadItem(content, 'filesS3Config');
48
50
  content = ensureValidatorSchema(content, 'filesS3EnvSchemaZod');
49
51
 
50
52
  if (!content.includes(' FilesS3ConfigModule,')) {
51
53
  if (content.includes(' ForgeonFilesModule,')) {
52
54
  content = ensureLineAfter(content, ' ForgeonFilesModule,', ' FilesS3ConfigModule,');
55
+ } else if (content.includes(' ForgeonFilesModule.register({')) {
56
+ content = ensureLineBefore(content, ' ForgeonFilesModule.register({', ' FilesS3ConfigModule,');
53
57
  } else if (content.includes(' ForgeonI18nModule.register({')) {
54
58
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' FilesS3ConfigModule,');
55
59
  } else if (content.includes(' DbPrismaModule,')) {
@@ -61,6 +65,10 @@ function patchAppModule(targetRoot) {
61
65
  }
62
66
  }
63
67
 
68
+ if (content.includes('ForgeonFilesModule')) {
69
+ content = upsertFilesModuleRegistration(content, resolveFilesStorageRuntimeModule(targetRoot));
70
+ }
71
+
64
72
  fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
65
73
  }
66
74
 
@@ -75,7 +83,7 @@ function patchApiDockerfile(targetRoot) {
75
83
  const packageAnchors = [
76
84
  'COPY packages/files/package.json packages/files/package.json',
77
85
  'COPY packages/files-local/package.json packages/files-local/package.json',
78
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
86
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
79
87
  'COPY packages/rbac/package.json packages/rbac/package.json',
80
88
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
81
89
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -94,7 +102,7 @@ function patchApiDockerfile(targetRoot) {
94
102
  const sourceAnchors = [
95
103
  'COPY packages/files packages/files',
96
104
  'COPY packages/files-local packages/files-local',
97
- 'COPY packages/auth-api packages/auth-api',
105
+ 'COPY packages/accounts-api packages/accounts-api',
98
106
  'COPY packages/rbac packages/rbac',
99
107
  'COPY packages/rate-limit packages/rate-limit',
100
108
  'COPY packages/logger packages/logger',
@@ -263,4 +271,7 @@ export function applyFilesS3Module({ packageRoot, targetRoot }) {
263
271
 
264
272
  setEnvValue(path.join(targetRoot, 'apps', 'api', '.env.example'), 'FILES_STORAGE_DRIVER', 's3');
265
273
  setEnvValue(path.join(targetRoot, 'infra', 'docker', '.env.example'), 'FILES_STORAGE_DRIVER', 's3');
274
+
275
+ patchAppModule(targetRoot);
266
276
  }
277
+
@@ -11,9 +11,11 @@ import {
11
11
  ensureLoadItem,
12
12
  ensureNestCommonImport,
13
13
  ensureValidatorSchema,
14
+ ensureNamedImportSpecifier,
14
15
  upsertEnvLines,
15
16
  } from './shared/patch-utils.mjs';
16
17
  import { ensureWebProbeDefinition, resolveProbeTargets } from './shared/probes.mjs';
18
+ import { resolveFilesStorageRuntimeModule, upsertFilesModuleRegistration } from './shared/files-runtime-wiring.mjs';
17
19
 
18
20
  function copyFromPreset(packageRoot, targetRoot, relativePath) {
19
21
  const source = path.join(packageRoot, 'templates', 'module-presets', 'files', relativePath);
@@ -168,27 +170,22 @@ function patchAppModule(targetRoot) {
168
170
  content,
169
171
  "import { filesConfig, filesEnvSchema, ForgeonFilesModule } from '@forgeon/files';",
170
172
  );
171
- content = ensureLoadItem(content, 'filesConfig');
172
- content = ensureValidatorSchema(content, 'filesEnvSchema');
173
+ content = ensureImportLine(
174
+ content,
175
+ "import { ForgeonFilesDbPrismaModule } from './files/forgeon-files-db-prisma.module';",
176
+ );
173
177
 
174
- if (!content.includes(' ForgeonFilesModule,')) {
175
- if (content.includes(' ForgeonI18nModule.register({')) {
176
- content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonFilesModule,');
177
- } else if (content.includes(' ForgeonAuthModule.register({')) {
178
- content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonFilesModule,');
179
- } else if (content.includes(' ForgeonAuthModule.register(),')) {
180
- content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonFilesModule,');
181
- } else if (content.includes(' DbPrismaModule,')) {
182
- content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonFilesModule,');
183
- } else if (content.includes(' ForgeonLoggerModule,')) {
184
- content = ensureLineAfter(content, ' ForgeonLoggerModule,', ' ForgeonFilesModule,');
185
- } else if (content.includes(' ForgeonSwaggerModule,')) {
186
- content = ensureLineAfter(content, ' ForgeonSwaggerModule,', ' ForgeonFilesModule,');
187
- } else {
188
- content = ensureLineAfter(content, ' CoreErrorsModule,', ' ForgeonFilesModule,');
189
- }
178
+ if (fs.existsSync(path.join(targetRoot, 'packages', 'files-local', 'package.json'))) {
179
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-local', 'ForgeonFilesLocalStorageModule');
180
+ }
181
+ if (fs.existsSync(path.join(targetRoot, 'packages', 'files-s3', 'package.json'))) {
182
+ content = ensureNamedImportSpecifier(content, '@forgeon/files-s3', 'ForgeonFilesS3StorageModule');
190
183
  }
191
184
 
185
+ content = ensureLoadItem(content, 'filesConfig');
186
+ content = ensureValidatorSchema(content, 'filesEnvSchema');
187
+ content = upsertFilesModuleRegistration(content, resolveFilesStorageRuntimeModule(targetRoot));
188
+
192
189
  fs.writeFileSync(filePath, `${content.trimEnd()}\n`, 'utf8');
193
190
  }
194
191
 
@@ -201,7 +198,7 @@ function patchApiDockerfile(targetRoot) {
201
198
  let content = fs.readFileSync(dockerfilePath, 'utf8').replace(/\r\n/g, '\n');
202
199
 
203
200
  const packageAnchors = [
204
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
201
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
205
202
  'COPY packages/rbac/package.json packages/rbac/package.json',
206
203
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
207
204
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -214,7 +211,7 @@ function patchApiDockerfile(targetRoot) {
214
211
  content = ensureLineAfter(content, packageAnchor, 'COPY packages/files/package.json packages/files/package.json');
215
212
 
216
213
  const sourceAnchors = [
217
- 'COPY packages/auth-api packages/auth-api',
214
+ 'COPY packages/accounts-api packages/accounts-api',
218
215
  'COPY packages/rbac packages/rbac',
219
216
  'COPY packages/rate-limit packages/rate-limit',
220
217
  'COPY packages/logger packages/logger',
@@ -344,7 +341,7 @@ function patchCompose(targetRoot) {
344
341
  let content = fs.readFileSync(composePath, 'utf8').replace(/\r\n/g, '\n');
345
342
  if (!content.includes('FILES_ENABLED: ${FILES_ENABLED}')) {
346
343
  const anchors = [
347
- /^(\s+AUTH_DEMO_PASSWORD:.*)$/m,
344
+ /^(\s+AUTH_ARGON2_PARALLELISM:.*)$/m,
348
345
  /^(\s+THROTTLE_TRUST_PROXY:.*)$/m,
349
346
  /^(\s+LOGGER_LEVEL:.*)$/m,
350
347
  /^(\s+SWAGGER_ENABLED:.*)$/m,
@@ -428,6 +425,7 @@ Key env:
428
425
 
429
426
  export function applyFilesModule({ packageRoot, targetRoot }) {
430
427
  copyFromPreset(packageRoot, targetRoot, path.join('packages', 'files'));
428
+ copyFromPreset(packageRoot, targetRoot, path.join('apps', 'api', 'src', 'files'));
431
429
  const probeTargets = resolveProbeTargets({ targetRoot, moduleId: 'files' });
432
430
 
433
431
 
@@ -456,3 +454,5 @@ export function applyFilesModule({ packageRoot, targetRoot }) {
456
454
  'FILES_ALLOWED_MIME_PREFIXES=image/,application/pdf,text/',
457
455
  ]);
458
456
  }
457
+
458
+
@@ -1,4 +1,4 @@
1
- import { describe, it } from 'node:test';
1
+ import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import fs from 'node:fs';
4
4
  import os from 'node:os';
@@ -81,19 +81,25 @@ describe('addModule idempotency', () => {
81
81
  },
82
82
  },
83
83
  {
84
- name: 'jwt-auth',
85
- moduleId: 'jwt-auth',
86
- dbPrismaEnabled: false,
84
+ name: 'accounts',
85
+ moduleId: 'accounts',
86
+ dbPrismaEnabled: true,
87
87
  setup: [],
88
88
  verify(projectRoot) {
89
- assert.equal(fs.existsSync(path.join(projectRoot, 'packages', 'auth-api', 'package.json')), true);
89
+ assert.equal(fs.existsSync(path.join(projectRoot, 'packages', 'accounts-api', 'package.json')), true);
90
+ assert.equal(
91
+ fs.existsSync(
92
+ path.join(projectRoot, 'apps', 'api', 'src', 'accounts', 'prisma-accounts-persistence.store.ts'),
93
+ ),
94
+ true,
95
+ );
90
96
  assert.match(
91
97
  readFile(path.join(projectRoot, 'apps', 'api', 'src', 'health', 'health.controller.ts')),
92
98
  /@Get\('auth'\)/,
93
99
  );
94
- assert.doesNotMatch(
100
+ assert.match(
95
101
  readFile(path.join(projectRoot, 'apps', 'api', 'src', 'app.module.ts')),
96
- /PrismaAuthRefreshTokenStore/,
102
+ /ForgeonAccountsModule\.register\(/,
97
103
  );
98
104
  },
99
105
  },
@@ -1,4 +1,4 @@
1
- import { describe, it } from 'node:test';
1
+ import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert/strict';
3
3
  import fs from 'node:fs';
4
4
  import os from 'node:os';
@@ -188,7 +188,7 @@ describe('probe wiring', () => {
188
188
  addModule({ moduleId: 'queue', targetRoot: projectRoot, packageRoot });
189
189
  addModule({ moduleId: 'scheduler', targetRoot: projectRoot, packageRoot });
190
190
  addModule({ moduleId: 'db-prisma', targetRoot: projectRoot, packageRoot });
191
- addModule({ moduleId: 'jwt-auth', targetRoot: projectRoot, packageRoot });
191
+ addModule({ moduleId: 'accounts', targetRoot: projectRoot, packageRoot });
192
192
  addModule({ moduleId: 'rate-limit', targetRoot: projectRoot, packageRoot });
193
193
 
194
194
  assert.deepEqual(readManagedProbeIds(projectRoot), ['db', 'auth', 'rate-limit', 'queue', 'scheduler']);
@@ -200,3 +200,5 @@ describe('probe wiring', () => {
200
200
 
201
201
 
202
202
 
203
+
204
+
@@ -1,4 +1,4 @@
1
- import fs from 'node:fs';
1
+ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { copyRecursive, writeJson } from '../utils/fs.mjs';
4
4
  import {
@@ -40,8 +40,8 @@ function patchAppModule(targetRoot) {
40
40
  moduleLine: ' ForgeonQueueModule,',
41
41
  beforeAnchors: [
42
42
  ' ForgeonI18nModule.register({',
43
- ' ForgeonAuthModule.register({',
44
- ' ForgeonAuthModule.register(),',
43
+ ' ForgeonAccountsModule.register({',
44
+ ' ForgeonAccountsModule.register(),',
45
45
  ],
46
46
  afterAnchors: [
47
47
  ' DbPrismaModule,',
@@ -89,7 +89,7 @@ function patchApiDockerfile(targetRoot) {
89
89
  'COPY packages/files-s3/package.json packages/files-s3/package.json',
90
90
  'COPY packages/files-local/package.json packages/files-local/package.json',
91
91
  'COPY packages/files/package.json packages/files/package.json',
92
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
92
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
93
93
  'COPY packages/rbac/package.json packages/rbac/package.json',
94
94
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
95
95
  'COPY packages/logger/package.json packages/logger/package.json',
@@ -108,7 +108,7 @@ function patchApiDockerfile(targetRoot) {
108
108
  'COPY packages/files-s3 packages/files-s3',
109
109
  'COPY packages/files-local packages/files-local',
110
110
  'COPY packages/files packages/files',
111
- 'COPY packages/auth-api packages/auth-api',
111
+ 'COPY packages/accounts-api packages/accounts-api',
112
112
  'COPY packages/rbac packages/rbac',
113
113
  'COPY packages/rate-limit packages/rate-limit',
114
114
  'COPY packages/logger packages/logger',
@@ -224,7 +224,7 @@ function patchCompose(targetRoot) {
224
224
  /^(\s+FILES_S3_MAX_ATTEMPTS:.*)$/m,
225
225
  /^(\s+FILES_LOCAL_ROOT:.*)$/m,
226
226
  /^(\s+FILES_PUBLIC_BASE_PATH:.*)$/m,
227
- /^(\s+AUTH_DEMO_PASSWORD:.*)$/m,
227
+ /^(\s+AUTH_ARGON2_PARALLELISM:.*)$/m,
228
228
  /^(\s+THROTTLE_TRUST_PROXY:.*)$/m,
229
229
  /^(\s+LOGGER_REQUEST_ID_HEADER:.*)$/m,
230
230
  /^(\s+SWAGGER_DOCS_PATH:.*)$/m,
@@ -323,3 +323,6 @@ export function applyQueueModule({ packageRoot, targetRoot }) {
323
323
  'QUEUE_DEFAULT_BACKOFF_MS=1000',
324
324
  ]);
325
325
  }
326
+
327
+
328
+
@@ -1,4 +1,4 @@
1
- import fs from 'node:fs';
1
+ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { copyRecursive, writeJson } from '../utils/fs.mjs';
4
4
  import {
@@ -50,11 +50,11 @@ function patchAppModule(targetRoot) {
50
50
  "import { ForgeonRateLimitModule, rateLimitConfig, rateLimitEnvSchema } from '@forgeon/rate-limit';",
51
51
  );
52
52
  } else if (
53
- content.includes("import { authConfig, authEnvSchema, ForgeonAuthModule } from '@forgeon/auth-api';")
53
+ content.includes("import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';")
54
54
  ) {
55
55
  content = ensureLineAfter(
56
56
  content,
57
- "import { authConfig, authEnvSchema, ForgeonAuthModule } from '@forgeon/auth-api';",
57
+ "import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';",
58
58
  "import { ForgeonRateLimitModule, rateLimitConfig, rateLimitEnvSchema } from '@forgeon/rate-limit';",
59
59
  );
60
60
  } else if (
@@ -96,10 +96,10 @@ function patchAppModule(targetRoot) {
96
96
  if (!content.includes(' ForgeonRateLimitModule,')) {
97
97
  if (content.includes(' ForgeonI18nModule.register({')) {
98
98
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonRateLimitModule,');
99
- } else if (content.includes(' ForgeonAuthModule.register({')) {
100
- content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonRateLimitModule,');
101
- } else if (content.includes(' ForgeonAuthModule.register(),')) {
102
- content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonRateLimitModule,');
99
+ } else if (content.includes(' ForgeonAccountsModule.register({')) {
100
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonRateLimitModule,');
101
+ } else if (content.includes(' ForgeonAccountsModule.register(),')) {
102
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register(),', ' ForgeonRateLimitModule,');
103
103
  } else if (content.includes(' DbPrismaModule,')) {
104
104
  content = ensureLineAfter(content, ' DbPrismaModule,', ' ForgeonRateLimitModule,');
105
105
  } else if (content.includes(' ForgeonLoggerModule,')) {
@@ -166,7 +166,7 @@ function patchApiDockerfile(targetRoot) {
166
166
 
167
167
  let content = fs.readFileSync(dockerfilePath, 'utf8').replace(/\r\n/g, '\n');
168
168
  const packageAnchors = [
169
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
169
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
170
170
  'COPY packages/logger/package.json packages/logger/package.json',
171
171
  'COPY packages/swagger/package.json packages/swagger/package.json',
172
172
  'COPY packages/i18n/package.json packages/i18n/package.json',
@@ -181,7 +181,7 @@ function patchApiDockerfile(targetRoot) {
181
181
  );
182
182
 
183
183
  const sourceAnchors = [
184
- 'COPY packages/auth-api packages/auth-api',
184
+ 'COPY packages/accounts-api packages/accounts-api',
185
185
  'COPY packages/logger packages/logger',
186
186
  'COPY packages/swagger packages/swagger',
187
187
  'COPY packages/i18n packages/i18n',
@@ -209,7 +209,7 @@ function patchCompose(targetRoot) {
209
209
  let content = fs.readFileSync(composePath, 'utf8').replace(/\r\n/g, '\n');
210
210
  if (!content.includes('THROTTLE_ENABLED: ${THROTTLE_ENABLED}')) {
211
211
  const anchors = [
212
- /^(\s+AUTH_DEMO_PASSWORD:.*)$/m,
212
+ /^(\s+AUTH_ARGON2_PARALLELISM:.*)$/m,
213
213
  /^(\s+JWT_ACCESS_SECRET:.*)$/m,
214
214
  /^(\s+LOGGER_LEVEL:.*)$/m,
215
215
  /^(\s+SWAGGER_ENABLED:.*)$/m,
@@ -303,3 +303,7 @@ export function applyRateLimitModule({ packageRoot, targetRoot }) {
303
303
  'THROTTLE_TRUST_PROXY=false',
304
304
  ]);
305
305
  }
306
+
307
+
308
+
309
+
@@ -48,11 +48,11 @@ function patchAppModule(targetRoot) {
48
48
  "import { ForgeonRbacModule } from '@forgeon/rbac';",
49
49
  );
50
50
  } else if (
51
- content.includes("import { authConfig, authEnvSchema, ForgeonAuthModule } from '@forgeon/auth-api';")
51
+ content.includes("import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';")
52
52
  ) {
53
53
  content = ensureLineAfter(
54
54
  content,
55
- "import { authConfig, authEnvSchema, ForgeonAuthModule } from '@forgeon/auth-api';",
55
+ "import { authConfig, authEnvSchema, ForgeonAccountsModule, UsersModule } from '@forgeon/accounts-api';",
56
56
  "import { ForgeonRbacModule } from '@forgeon/rbac';",
57
57
  );
58
58
  } else if (
@@ -99,10 +99,8 @@ function patchAppModule(targetRoot) {
99
99
  if (!content.includes(' ForgeonRbacModule,')) {
100
100
  if (content.includes(' ForgeonI18nModule.register({')) {
101
101
  content = ensureLineBefore(content, ' ForgeonI18nModule.register({', ' ForgeonRbacModule,');
102
- } else if (content.includes(' ForgeonAuthModule.register({')) {
103
- content = ensureLineBefore(content, ' ForgeonAuthModule.register({', ' ForgeonRbacModule,');
104
- } else if (content.includes(' ForgeonAuthModule.register(),')) {
105
- content = ensureLineBefore(content, ' ForgeonAuthModule.register(),', ' ForgeonRbacModule,');
102
+ } else if (content.includes(' ForgeonAccountsModule.register({')) {
103
+ content = ensureLineBefore(content, ' ForgeonAccountsModule.register({', ' ForgeonRbacModule,');
106
104
  } else if (content.includes(' ForgeonRateLimitModule,')) {
107
105
  content = ensureLineAfter(content, ' ForgeonRateLimitModule,', ' ForgeonRbacModule,');
108
106
  } else if (content.includes(' DbPrismaModule,')) {
@@ -192,7 +190,7 @@ function patchApiDockerfile(targetRoot) {
192
190
 
193
191
  let content = fs.readFileSync(dockerfilePath, 'utf8').replace(/\r\n/g, '\n');
194
192
  const packageAnchors = [
195
- 'COPY packages/auth-api/package.json packages/auth-api/package.json',
193
+ 'COPY packages/accounts-api/package.json packages/accounts-api/package.json',
196
194
  'COPY packages/rate-limit/package.json packages/rate-limit/package.json',
197
195
  'COPY packages/logger/package.json packages/logger/package.json',
198
196
  'COPY packages/swagger/package.json packages/swagger/package.json',
@@ -204,7 +202,7 @@ function patchApiDockerfile(targetRoot) {
204
202
  content = ensureLineAfter(content, packageAnchor, 'COPY packages/rbac/package.json packages/rbac/package.json');
205
203
 
206
204
  const sourceAnchors = [
207
- 'COPY packages/auth-api packages/auth-api',
205
+ 'COPY packages/accounts-api packages/accounts-api',
208
206
  'COPY packages/rate-limit packages/rate-limit',
209
207
  'COPY packages/logger packages/logger',
210
208
  'COPY packages/swagger packages/swagger',
@@ -240,7 +238,7 @@ function patchReadme(targetRoot) {
240
238
 
241
239
  The rbac add-module provides a minimal authorization layer for role and permission checks.
242
240
 
243
- It installs independently. \`jwt-auth\` is optional and only extends demo JWT claims through integration sync.
241
+ It installs independently. \`accounts\` is optional and only prepares auth claims compatibility through integration sync.
244
242
 
245
243
  What it adds:
246
244
  - \`@Roles(...)\` and \`@Permissions(...)\` decorators
@@ -260,8 +258,8 @@ How to verify:
260
258
  - the same route without that header should return \`403\`
261
259
 
262
260
  Optional integration:
263
- - if \`jwt-auth\` is installed too, run \`pnpm forgeon:sync-integrations\`
264
- - that enables demo JWT permissions for the same RBAC probe flow
261
+ - if \`accounts\` is installed too, run \`pnpm forgeon:sync-integrations\`
262
+ - that prepares accounts auth claims types for optional RBAC compatibility without changing the base accounts schema
265
263
 
266
264
  Current scope:
267
265
  - no policy engine
@@ -288,3 +286,6 @@ export function applyRbacModule({ packageRoot, targetRoot }) {
288
286
  patchApiDockerfile(targetRoot);
289
287
  patchReadme(targetRoot);
290
288
  }
289
+
290
+
291
+