nestjs-ddd-cli 3.2.1 → 3.3.0

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 (214) hide show
  1. package/README.md +118 -9
  2. package/ddd.schema.json +11 -1
  3. package/dist/commands/doctor-enhanced.d.ts +1 -0
  4. package/dist/commands/doctor-enhanced.js +94 -79
  5. package/dist/commands/doctor-enhanced.js.map +1 -1
  6. package/dist/commands/doctor.d.ts +9 -0
  7. package/dist/commands/doctor.js +68 -21
  8. package/dist/commands/doctor.js.map +1 -1
  9. package/dist/commands/generate-all.js +238 -176
  10. package/dist/commands/generate-all.js.map +1 -1
  11. package/dist/commands/generate-controller.d.ts +1 -0
  12. package/dist/commands/generate-controller.js +71 -0
  13. package/dist/commands/generate-controller.js.map +1 -0
  14. package/dist/commands/generate-domain-service.d.ts +1 -1
  15. package/dist/commands/generate-domain-service.js +6 -4
  16. package/dist/commands/generate-domain-service.js.map +1 -1
  17. package/dist/commands/generate-dto.d.ts +4 -0
  18. package/dist/commands/generate-dto.js +162 -0
  19. package/dist/commands/generate-dto.js.map +1 -0
  20. package/dist/commands/generate-entity.js +44 -35
  21. package/dist/commands/generate-entity.js.map +1 -1
  22. package/dist/commands/generate-event.js +10 -4
  23. package/dist/commands/generate-event.js.map +1 -1
  24. package/dist/commands/generate-migration-deployment.d.ts +15 -0
  25. package/dist/commands/generate-migration-deployment.js +326 -0
  26. package/dist/commands/generate-migration-deployment.js.map +1 -0
  27. package/dist/commands/generate-migration-deployment.spec.d.ts +1 -0
  28. package/dist/commands/generate-migration-deployment.spec.js +337 -0
  29. package/dist/commands/generate-migration-deployment.spec.js.map +1 -0
  30. package/dist/commands/generate-module.js +41 -31
  31. package/dist/commands/generate-module.js.map +1 -1
  32. package/dist/commands/generate-query.js +23 -4
  33. package/dist/commands/generate-query.js.map +1 -1
  34. package/dist/commands/generate-repository.d.ts +1 -1
  35. package/dist/commands/generate-repository.js +17 -34
  36. package/dist/commands/generate-repository.js.map +1 -1
  37. package/dist/commands/generate-service.js +19 -4
  38. package/dist/commands/generate-service.js.map +1 -1
  39. package/dist/commands/generate-usecase.js +12 -31
  40. package/dist/commands/generate-usecase.js.map +1 -1
  41. package/dist/commands/generate-value-object.js +3 -14
  42. package/dist/commands/generate-value-object.js.map +1 -1
  43. package/dist/commands/init-project.d.ts +3 -0
  44. package/dist/commands/init-project.js +19 -9
  45. package/dist/commands/init-project.js.map +1 -1
  46. package/dist/commands/interactive-scaffold.js +10 -0
  47. package/dist/commands/interactive-scaffold.js.map +1 -1
  48. package/dist/commands/migration.d.ts +3 -0
  49. package/dist/commands/migration.js +83 -48
  50. package/dist/commands/migration.js.map +1 -1
  51. package/dist/commands/recipe.d.ts +2 -0
  52. package/dist/commands/recipe.js +282 -91
  53. package/dist/commands/recipe.js.map +1 -1
  54. package/dist/commands/recipes/banklink-connector-contract.recipe.d.ts +1 -0
  55. package/dist/commands/recipes/banklink-connector-contract.recipe.js +161 -0
  56. package/dist/commands/recipes/banklink-connector-contract.recipe.js.map +1 -0
  57. package/dist/commands/recipes/bounded-json-http.recipe.d.ts +2 -0
  58. package/dist/commands/recipes/bounded-json-http.recipe.js +53 -0
  59. package/dist/commands/recipes/bounded-json-http.recipe.js.map +1 -0
  60. package/dist/commands/recipes/business-reference-identifiers.recipe.d.ts +1 -0
  61. package/dist/commands/recipes/business-reference-identifiers.recipe.js +223 -0
  62. package/dist/commands/recipes/business-reference-identifiers.recipe.js.map +1 -0
  63. package/dist/commands/recipes/event-backbone.recipe.d.ts +1 -0
  64. package/dist/commands/recipes/event-backbone.recipe.js +1118 -0
  65. package/dist/commands/recipes/event-backbone.recipe.js.map +1 -0
  66. package/dist/commands/recipes/external-projection-worker.recipe.d.ts +6 -0
  67. package/dist/commands/recipes/external-projection-worker.recipe.js +211 -0
  68. package/dist/commands/recipes/external-projection-worker.recipe.js.map +1 -0
  69. package/dist/commands/recipes/index.d.ts +12 -0
  70. package/dist/commands/recipes/index.js +12 -0
  71. package/dist/commands/recipes/index.js.map +1 -1
  72. package/dist/commands/recipes/jest-cjs-compat.recipe.d.ts +3 -0
  73. package/dist/commands/recipes/jest-cjs-compat.recipe.js +130 -0
  74. package/dist/commands/recipes/jest-cjs-compat.recipe.js.map +1 -0
  75. package/dist/commands/recipes/joi-env.recipe.d.ts +1 -0
  76. package/dist/commands/recipes/joi-env.recipe.js +301 -0
  77. package/dist/commands/recipes/joi-env.recipe.js.map +1 -0
  78. package/dist/commands/recipes/kafka-consumer.recipe.d.ts +1 -0
  79. package/dist/commands/recipes/kafka-consumer.recipe.js +65 -0
  80. package/dist/commands/recipes/kafka-consumer.recipe.js.map +1 -0
  81. package/dist/commands/recipes/oauth2-client-credentials.recipe.d.ts +1 -0
  82. package/dist/commands/recipes/oauth2-client-credentials.recipe.js +60 -0
  83. package/dist/commands/recipes/oauth2-client-credentials.recipe.js.map +1 -0
  84. package/dist/commands/recipes/oauth2-token-introspection.recipe.d.ts +1 -0
  85. package/dist/commands/recipes/oauth2-token-introspection.recipe.js +67 -0
  86. package/dist/commands/recipes/oauth2-token-introspection.recipe.js.map +1 -0
  87. package/dist/commands/recipes/oidc-bff-session.recipe.d.ts +1 -0
  88. package/dist/commands/recipes/oidc-bff-session.recipe.js +57 -0
  89. package/dist/commands/recipes/oidc-bff-session.recipe.js.map +1 -0
  90. package/dist/commands/recipes/oidc-dashboard.recipe.d.ts +1 -0
  91. package/dist/commands/recipes/oidc-dashboard.recipe.js +463 -0
  92. package/dist/commands/recipes/oidc-dashboard.recipe.js.map +1 -0
  93. package/dist/commands/recipes/oidc-resource-server.recipe.d.ts +1 -0
  94. package/dist/commands/recipes/oidc-resource-server.recipe.js +85 -0
  95. package/dist/commands/recipes/oidc-resource-server.recipe.js.map +1 -0
  96. package/dist/commands/recipes/platform-context.recipe.d.ts +1 -0
  97. package/dist/commands/recipes/platform-context.recipe.js +229 -0
  98. package/dist/commands/recipes/platform-context.recipe.js.map +1 -0
  99. package/dist/commands/recipes/platform-parc-authorization.recipe.d.ts +1 -0
  100. package/dist/commands/recipes/platform-parc-authorization.recipe.js +339 -0
  101. package/dist/commands/recipes/platform-parc-authorization.recipe.js.map +1 -0
  102. package/dist/commands/recipes/platform-parc-bound-authorization.recipe.d.ts +1 -0
  103. package/dist/commands/recipes/platform-parc-bound-authorization.recipe.js +56 -0
  104. package/dist/commands/recipes/platform-parc-bound-authorization.recipe.js.map +1 -0
  105. package/dist/commands/recipes/platform-service-access-request-context.recipe.d.ts +1 -0
  106. package/dist/commands/recipes/platform-service-access-request-context.recipe.js +103 -0
  107. package/dist/commands/recipes/platform-service-access-request-context.recipe.js.map +1 -0
  108. package/dist/commands/recipes/platform-service-runtime.recipe.d.ts +1 -0
  109. package/dist/commands/recipes/platform-service-runtime.recipe.js +415 -0
  110. package/dist/commands/recipes/platform-service-runtime.recipe.js.map +1 -0
  111. package/dist/index.js +82 -11
  112. package/dist/index.js.map +1 -1
  113. package/dist/templates/ai-context/CLAUDE.md.hbs +54 -3
  114. package/dist/templates/ai-context/conventions.md.hbs +20 -8
  115. package/dist/templates/command/create-command.hbs +8 -3
  116. package/dist/templates/command/delete-command.hbs +1 -1
  117. package/dist/templates/command/update-command.hbs +1 -1
  118. package/dist/templates/controller/application-controller.hbs +7 -0
  119. package/dist/templates/controller/controller.hbs +6 -0
  120. package/dist/templates/dto/create-dto.hbs +17 -5
  121. package/dist/templates/dto/filter-dto.hbs +1 -1
  122. package/dist/templates/dto/response-dto.hbs +1 -1
  123. package/dist/templates/entity/entity.hbs +4 -0
  124. package/dist/templates/mapper/mapper.hbs +6 -2
  125. package/dist/templates/orm-entity/orm-entity.hbs +9 -1
  126. package/dist/templates/prisma/prisma-mapper.hbs +6 -0
  127. package/dist/templates/prisma/prisma-repository.hbs +57 -5
  128. package/dist/templates/prisma/prisma-schema.hbs +2 -0
  129. package/dist/templates/query/get-all.query.hbs +10 -2
  130. package/dist/templates/recipes/bounded-json-http/README.md.hbs +36 -0
  131. package/dist/templates/recipes/external-projection-worker/README.md.hbs +157 -0
  132. package/dist/templates/recipes/external-projection-worker/canonical-json.ts.hbs +123 -0
  133. package/dist/templates/recipes/external-projection-worker/enqueuer.ts.hbs +167 -0
  134. package/dist/templates/recipes/external-projection-worker/index.ts.hbs +6 -0
  135. package/dist/templates/recipes/external-projection-worker/migration.ts.hbs +88 -0
  136. package/dist/templates/recipes/external-projection-worker/module.ts.hbs +36 -0
  137. package/dist/templates/recipes/external-projection-worker/store.ts.hbs +354 -0
  138. package/dist/templates/recipes/external-projection-worker/types.ts.hbs +134 -0
  139. package/dist/templates/recipes/external-projection-worker/worker.ts.hbs +296 -0
  140. package/dist/templates/recipes/kafka-consumer/README.md.hbs +50 -0
  141. package/dist/templates/recipes/kafka-consumer/kafka-consumer.ts.hbs +135 -0
  142. package/dist/templates/recipes/kafka-consumer/migration.ts.hbs +17 -0
  143. package/dist/templates/recipes/oauth2-client-credentials/README.md.hbs +40 -0
  144. package/dist/templates/recipes/oauth2-client-credentials/client.spec.ts.hbs +234 -0
  145. package/dist/templates/recipes/oauth2-client-credentials/client.ts.hbs +210 -0
  146. package/dist/templates/recipes/oauth2-client-credentials/index.ts.hbs +2 -0
  147. package/dist/templates/recipes/oauth2-client-credentials/module.ts.hbs +58 -0
  148. package/dist/templates/recipes/oauth2-token-introspection/README.md.hbs +158 -0
  149. package/dist/templates/recipes/oauth2-token-introspection/client.spec.ts.hbs +350 -0
  150. package/dist/templates/recipes/oauth2-token-introspection/client.ts.hbs +241 -0
  151. package/dist/templates/recipes/oauth2-token-introspection/http-client.spec.ts.hbs +411 -0
  152. package/dist/templates/recipes/oauth2-token-introspection/http-client.ts.hbs +343 -0
  153. package/dist/templates/recipes/oauth2-token-introspection/index.ts.hbs +3 -0
  154. package/dist/templates/recipes/oauth2-token-introspection/module.ts.hbs +58 -0
  155. package/dist/templates/recipes/oidc-bff-session/README.md.hbs +96 -0
  156. package/dist/templates/recipes/oidc-bff-session/client.test.ts.hbs +663 -0
  157. package/dist/templates/recipes/oidc-bff-session/client.ts.hbs +635 -0
  158. package/dist/templates/recipes/oidc-bff-session/index.ts.hbs +3 -0
  159. package/dist/templates/recipes/oidc-bff-session/store.integration.test.ts.hbs +480 -0
  160. package/dist/templates/recipes/oidc-bff-session/store.test.ts.hbs +87 -0
  161. package/dist/templates/recipes/oidc-bff-session/store.ts.hbs +549 -0
  162. package/dist/templates/recipes/oidc-bff-session/valkey.test.ts.hbs +158 -0
  163. package/dist/templates/recipes/oidc-bff-session/valkey.ts.hbs +148 -0
  164. package/dist/templates/recipes/oidc-resource-server/README.md.hbs +74 -0
  165. package/dist/templates/recipes/oidc-resource-server/index.ts.hbs +2 -0
  166. package/dist/templates/recipes/oidc-resource-server/module.ts.hbs +51 -0
  167. package/dist/templates/recipes/oidc-resource-server/verifier.spec.ts.hbs +186 -0
  168. package/dist/templates/recipes/oidc-resource-server/verifier.ts.hbs +440 -0
  169. package/dist/templates/recipes/platform-parc-bound-authorization/README.md.hbs +92 -0
  170. package/dist/templates/recipes/platform-parc-bound-authorization/client.ts.hbs +142 -0
  171. package/dist/templates/recipes/platform-service-access-request-context/docs.md.hbs +61 -0
  172. package/dist/templates/recipes/platform-service-access-request-context/env.example.hbs +7 -0
  173. package/dist/templates/recipes/platform-service-access-request-context/index.ts.hbs +7 -0
  174. package/dist/templates/recipes/platform-service-access-request-context/request-context-headers.ts.hbs +61 -0
  175. package/dist/templates/recipes/platform-service-access-request-context/request-context-introspection.parser.ts.hbs +132 -0
  176. package/dist/templates/recipes/platform-service-access-request-context/request-context-introspection.types.ts.hbs +40 -0
  177. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.client.ts.hbs +45 -0
  178. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.config.ts.hbs +142 -0
  179. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.guard.ts.hbs +77 -0
  180. package/dist/templates/recipes/platform-service-access-request-context/service-access-request-context.module.ts.hbs +17 -0
  181. package/dist/templates/repository/repository.hbs +43 -5
  182. package/dist/templates/resolver/graphql-input.hbs +23 -6
  183. package/dist/templates/resolver/resolver.hbs +4 -0
  184. package/dist/templates/service/domain-service.hbs +2 -2
  185. package/dist/templates/test/controller.spec.hbs +5 -1
  186. package/dist/templates/test/prisma-repository.spec.hbs +192 -0
  187. package/dist/templates/test/repository.spec.hbs +41 -2
  188. package/dist/templates/test/usecase.spec.hbs +24 -5
  189. package/dist/templates/usecase/application-usecase.hbs +17 -0
  190. package/dist/templates/usecase/create-usecase.hbs +34 -3
  191. package/dist/templates/usecase/update-usecase.hbs +15 -1
  192. package/dist/utils/config.utils.d.ts +2 -0
  193. package/dist/utils/config.utils.js +14 -2
  194. package/dist/utils/config.utils.js.map +1 -1
  195. package/dist/utils/dependency.utils.d.ts +18 -2
  196. package/dist/utils/dependency.utils.js +144 -15
  197. package/dist/utils/dependency.utils.js.map +1 -1
  198. package/dist/utils/field.utils.d.ts +6 -0
  199. package/dist/utils/field.utils.js +78 -24
  200. package/dist/utils/field.utils.js.map +1 -1
  201. package/dist/utils/field.utils.spec.d.ts +1 -0
  202. package/dist/utils/field.utils.spec.js +38 -0
  203. package/dist/utils/field.utils.spec.js.map +1 -0
  204. package/dist/utils/file.utils.d.ts +39 -3
  205. package/dist/utils/file.utils.js +150 -13
  206. package/dist/utils/file.utils.js.map +1 -1
  207. package/dist/utils/naming.utils.js +5 -4
  208. package/dist/utils/naming.utils.js.map +1 -1
  209. package/dist/utils/static-recipe.utils.d.ts +4 -0
  210. package/dist/utils/static-recipe.utils.js +148 -0
  211. package/dist/utils/static-recipe.utils.js.map +1 -0
  212. package/dist/utils/template-engine.utils.js +83 -68
  213. package/dist/utils/template-engine.utils.js.map +1 -1
  214. package/package.json +20 -11
@@ -0,0 +1,463 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.applyOidcDashboardRecipe = applyOidcDashboardRecipe;
40
+ const path = __importStar(require("path"));
41
+ const chalk_1 = __importDefault(require("chalk"));
42
+ const file_utils_1 = require("../../utils/file.utils");
43
+ const platform_context_recipe_1 = require("./platform-context.recipe");
44
+ async function applyOidcDashboardRecipe(basePath) {
45
+ await (0, platform_context_recipe_1.applyPlatformContextRecipe)(basePath);
46
+ const authPath = path.join(basePath, 'src/shared/auth/oidc-dashboard');
47
+ const docsPath = path.join(basePath, 'docs/auth');
48
+ await (0, file_utils_1.ensureDir)(authPath);
49
+ await (0, file_utils_1.ensureDir)(docsPath);
50
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'oidc-dashboard.config.ts'), configContent);
51
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'oidc-principal.ts'), principalContent);
52
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'oidc-access-mapping.ts'), mappingContent);
53
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'oidc-token-verifier.service.ts'), verifierContent);
54
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'canonical-platform-principal.resolver.ts'), resolverContent);
55
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'oidc-dashboard.guard.ts'), guardContent);
56
+ await (0, file_utils_1.writeFile)(path.join(authPath, 'index.ts'), indexContent);
57
+ await (0, file_utils_1.writeFile)(path.join(docsPath, 'oidc-dashboard.md'), docsContent);
58
+ const envExamplePath = path.join(basePath, '.env.example');
59
+ const fallbackExamplePath = path.join(basePath, '.env.oidc-dashboard.example');
60
+ const targetExamplePath = (await (0, file_utils_1.fileExists)(envExamplePath))
61
+ ? fallbackExamplePath
62
+ : envExamplePath;
63
+ await (0, file_utils_1.writeFile)(targetExamplePath, envExampleContent);
64
+ console.log(chalk_1.default.green(' ✓ Platform request context contract'));
65
+ console.log(chalk_1.default.green(' ✓ OIDC dashboard config contract'));
66
+ console.log(chalk_1.default.green(' ✓ Canonical platform principal resolver hook'));
67
+ console.log(chalk_1.default.green(' ✓ Role/group mapping hook'));
68
+ console.log(chalk_1.default.green(' ✓ JWKS-backed bearer token verifier'));
69
+ console.log(chalk_1.default.green(' ✓ NestJS dashboard/API guard with platform context'));
70
+ console.log(chalk_1.default.green(' ✓ Laravel/Filament and Next/Node integration notes'));
71
+ console.log(chalk_1.default.yellow(' Keep dashboard RBAC local or PARC-backed; OIDC proves identity, not product authorization.'));
72
+ }
73
+ const configContent = `export interface OidcDashboardConfig {
74
+ issuerUrl: string;
75
+ clientId: string;
76
+ clientSecret?: string;
77
+ callbackUrl: string;
78
+ postLogoutRedirectUrl?: string;
79
+ scopes: string[];
80
+ adminEmails: string[];
81
+ allowedEmailDomains: string[];
82
+ roleClaim: string;
83
+ groupClaim: string;
84
+ audience?: string;
85
+ jwksUrl?: string;
86
+ }
87
+
88
+ function listFromEnv(value: string | undefined, fallback: string[] = []): string[] {
89
+ if (!value) {
90
+ return fallback;
91
+ }
92
+
93
+ return value
94
+ .split(",")
95
+ .map((item) => item.trim())
96
+ .filter(Boolean);
97
+ }
98
+
99
+ export function oidcDashboardConfigFromEnv(): OidcDashboardConfig {
100
+ const issuerUrl = process.env.OIDC_ISSUER_URL;
101
+ const clientId = process.env.OIDC_CLIENT_ID;
102
+ const callbackUrl = process.env.OIDC_CALLBACK_URL;
103
+
104
+ if (!issuerUrl || !clientId || !callbackUrl) {
105
+ throw new Error(
106
+ "OIDC_ISSUER_URL, OIDC_CLIENT_ID, and OIDC_CALLBACK_URL are required for dashboard SSO",
107
+ );
108
+ }
109
+
110
+ return {
111
+ issuerUrl: issuerUrl.replace(/\\/+$/, ""),
112
+ clientId,
113
+ clientSecret: process.env.OIDC_CLIENT_SECRET,
114
+ callbackUrl,
115
+ postLogoutRedirectUrl: process.env.OIDC_POST_LOGOUT_REDIRECT_URL,
116
+ scopes: listFromEnv(process.env.OIDC_SCOPES, ["openid", "profile", "email"]),
117
+ adminEmails: listFromEnv(process.env.OIDC_ADMIN_EMAILS).map((email) =>
118
+ email.toLowerCase(),
119
+ ),
120
+ allowedEmailDomains: listFromEnv(process.env.OIDC_ALLOWED_EMAIL_DOMAINS).map(
121
+ (domain) => domain.toLowerCase(),
122
+ ),
123
+ roleClaim: process.env.OIDC_ROLE_CLAIM ?? "roles",
124
+ groupClaim: process.env.OIDC_GROUP_CLAIM ?? "groups",
125
+ audience: process.env.OIDC_AUDIENCE ?? clientId,
126
+ jwksUrl: process.env.OIDC_JWKS_URL || undefined,
127
+ };
128
+ }
129
+ `;
130
+ const principalContent = `export interface OidcDashboardPrincipal {
131
+ subject: string;
132
+ email?: string;
133
+ emailVerified?: boolean;
134
+ name?: string;
135
+ roles: string[];
136
+ groups: string[];
137
+ claims: Record<string, unknown>;
138
+ }
139
+ `;
140
+ const mappingContent = `export interface OidcDashboardAccessMappingInput {
141
+ subject: string;
142
+ email?: string;
143
+ claims: Record<string, unknown>;
144
+ roleClaim: string;
145
+ groupClaim: string;
146
+ }
147
+
148
+ export interface OidcDashboardAccessMapping {
149
+ roles: string[];
150
+ groups: string[];
151
+ }
152
+
153
+ export type OidcDashboardAccessMappingHook = (
154
+ input: OidcDashboardAccessMappingInput,
155
+ ) => OidcDashboardAccessMapping | Promise<OidcDashboardAccessMapping>;
156
+
157
+ export const defaultOidcDashboardAccessMapping: OidcDashboardAccessMappingHook = (
158
+ input,
159
+ ) => ({
160
+ roles: oidcClaimValues(input.claims, input.roleClaim),
161
+ groups: oidcClaimValues(input.claims, input.groupClaim),
162
+ });
163
+
164
+ export function oidcClaimValues(
165
+ claims: Record<string, unknown>,
166
+ claimName: string,
167
+ ): string[] {
168
+ const value = claims[claimName];
169
+ return uniqueStringList(stringListFromClaimValue(value));
170
+ }
171
+
172
+ function stringListFromClaimValue(value: unknown): string[] {
173
+ if (Array.isArray(value)) {
174
+ return value.filter((item): item is string => typeof item === "string");
175
+ }
176
+
177
+ if (typeof value === "string") {
178
+ return value.split(/[\\s,]+/);
179
+ }
180
+
181
+ if (value && typeof value === "object") {
182
+ return Object.entries(value as Record<string, unknown>)
183
+ .filter(([, nestedValue]) => Boolean(nestedValue))
184
+ .map(([key]) => key);
185
+ }
186
+
187
+ return [];
188
+ }
189
+
190
+ function uniqueStringList(values: string[]): string[] {
191
+ return [...new Set(values.map((value) => value.trim()).filter(Boolean))];
192
+ }
193
+ `;
194
+ const verifierContent = `import { Injectable, UnauthorizedException } from "@nestjs/common";
195
+ import { createRemoteJWKSet, jwtVerify } from "jose";
196
+ import { defaultOidcDashboardAccessMapping } from "./oidc-access-mapping";
197
+ import {
198
+ OidcDashboardConfig,
199
+ oidcDashboardConfigFromEnv,
200
+ } from "./oidc-dashboard.config";
201
+ import { OidcDashboardPrincipal } from "./oidc-principal";
202
+
203
+ @Injectable()
204
+ export class OidcTokenVerifierService {
205
+ private readonly config: OidcDashboardConfig;
206
+ private readonly jwks: ReturnType<typeof createRemoteJWKSet>;
207
+
208
+ constructor() {
209
+ this.config = oidcDashboardConfigFromEnv();
210
+ this.jwks = createRemoteJWKSet(
211
+ new URL(this.config.jwksUrl ?? this.config.issuerUrl + "/oauth/v2/keys"),
212
+ );
213
+ }
214
+
215
+ async verifyBearerToken(token: string): Promise<OidcDashboardPrincipal> {
216
+ try {
217
+ const { payload } = await jwtVerify(token, this.jwks, {
218
+ issuer: this.config.issuerUrl,
219
+ audience: this.config.audience,
220
+ });
221
+
222
+ const subject = String(payload.sub);
223
+ const email = typeof payload.email === "string" ? payload.email : undefined;
224
+ const claims = payload as Record<string, unknown>;
225
+ const access = await defaultOidcDashboardAccessMapping({
226
+ subject,
227
+ email,
228
+ claims,
229
+ roleClaim: this.config.roleClaim,
230
+ groupClaim: this.config.groupClaim,
231
+ });
232
+
233
+ if (email && !this.emailAllowed(email)) {
234
+ throw new UnauthorizedException("OIDC email domain is not allowed");
235
+ }
236
+
237
+ return {
238
+ subject,
239
+ email,
240
+ emailVerified:
241
+ typeof payload.email_verified === "boolean"
242
+ ? payload.email_verified
243
+ : undefined,
244
+ name: typeof payload.name === "string" ? payload.name : undefined,
245
+ roles: access.roles,
246
+ groups: access.groups,
247
+ claims,
248
+ };
249
+ } catch (error) {
250
+ if (error instanceof UnauthorizedException) {
251
+ throw error;
252
+ }
253
+ throw new UnauthorizedException("Invalid OIDC bearer token");
254
+ }
255
+ }
256
+
257
+ private emailAllowed(email: string): boolean {
258
+ if (this.config.adminEmails.includes(email.toLowerCase())) {
259
+ return true;
260
+ }
261
+
262
+ if (this.config.allowedEmailDomains.length === 0) {
263
+ return true;
264
+ }
265
+
266
+ const domain = email.split("@").pop()?.toLowerCase();
267
+ return Boolean(domain && this.config.allowedEmailDomains.includes(domain));
268
+ }
269
+ }
270
+ `;
271
+ const resolverContent = `import { UnauthorizedException } from "@nestjs/common";
272
+ import { VerifiedPlatformPrincipal } from "../../platform-context/platform-context.types";
273
+ import { OidcDashboardPrincipal } from "./oidc-principal";
274
+
275
+ export const CANONICAL_PLATFORM_PRINCIPAL_RESOLVER = Symbol(
276
+ "CANONICAL_PLATFORM_PRINCIPAL_RESOLVER",
277
+ );
278
+
279
+ export interface CanonicalPlatformPrincipalResolver {
280
+ resolve(
281
+ principal: OidcDashboardPrincipal,
282
+ ): VerifiedPlatformPrincipal | Promise<VerifiedPlatformPrincipal>;
283
+ }
284
+
285
+ export const defaultCanonicalPlatformPrincipalResolver: CanonicalPlatformPrincipalResolver =
286
+ {
287
+ resolve() {
288
+ throw new UnauthorizedException(
289
+ "Canonical platform principal mapping is not configured",
290
+ );
291
+ },
292
+ };
293
+ `;
294
+ const guardContent = `import {
295
+ CanActivate,
296
+ ExecutionContext,
297
+ Inject,
298
+ Injectable,
299
+ UnauthorizedException,
300
+ } from "@nestjs/common";
301
+ import { Request } from "express";
302
+ import { createPlatformRequestContext } from "../../platform-context/platform-context.factory";
303
+ import { PlatformRequestContext } from "../../platform-context/platform-context.types";
304
+ import {
305
+ CANONICAL_PLATFORM_PRINCIPAL_RESOLVER,
306
+ CanonicalPlatformPrincipalResolver,
307
+ } from "./canonical-platform-principal.resolver";
308
+ import { OidcTokenVerifierService } from "./oidc-token-verifier.service";
309
+
310
+ export interface RequestWithOidcPrincipal extends Request {
311
+ oidcPrincipal?: Awaited<
312
+ ReturnType<OidcTokenVerifierService["verifyBearerToken"]>
313
+ >;
314
+ platformContext?: PlatformRequestContext;
315
+ }
316
+
317
+ @Injectable()
318
+ export class OidcDashboardGuard implements CanActivate {
319
+ constructor(
320
+ private readonly verifier: OidcTokenVerifierService,
321
+ @Inject(CANONICAL_PLATFORM_PRINCIPAL_RESOLVER)
322
+ private readonly principalResolver: CanonicalPlatformPrincipalResolver,
323
+ ) {}
324
+
325
+ async canActivate(context: ExecutionContext): Promise<boolean> {
326
+ const request = context.switchToHttp().getRequest<RequestWithOidcPrincipal>();
327
+ const token = this.extractBearerToken(request.headers.authorization);
328
+
329
+ const oidcPrincipal = await this.verifier.verifyBearerToken(token);
330
+ request.oidcPrincipal = oidcPrincipal;
331
+
332
+ const verifiedPrincipal = await this.principalResolver.resolve(oidcPrincipal);
333
+ request.platformContext = createPlatformRequestContext({
334
+ principal: verifiedPrincipal,
335
+ });
336
+
337
+ return true;
338
+ }
339
+
340
+ private extractBearerToken(authorization?: string): string {
341
+ const [scheme, token] = authorization?.split(" ") ?? [];
342
+ if (scheme !== "Bearer" || !token) {
343
+ throw new UnauthorizedException("Bearer token is required");
344
+ }
345
+ return token;
346
+ }
347
+ }
348
+ `;
349
+ const indexContent = `export * from "./oidc-dashboard.config";
350
+ export * from "./oidc-principal";
351
+ export * from "./oidc-access-mapping";
352
+ export * from "./oidc-token-verifier.service";
353
+ export * from "./canonical-platform-principal.resolver";
354
+ export * from "./oidc-dashboard.guard";
355
+ `;
356
+ const docsContent = `# OIDC Dashboard Integration
357
+
358
+ Use this recipe for internal dashboards, operator portals, and admin APIs that
359
+ delegate authentication to an OIDC broker such as ZITADEL.
360
+
361
+ ## Ownership Boundary
362
+
363
+ - OIDC authenticates the human or machine session.
364
+ - The service maps the OIDC subject and email to a local operator record.
365
+ - Product authorization stays local or PARC-backed. Do not grant access merely
366
+ because a user can authenticate with the broker.
367
+ - Identity Manager remains the canonical identity profile service. VerifyHQ
368
+ remains verification evidence. Service Access remains service/client
369
+ enrollment and discovery.
370
+
371
+ ## NestJS API/Dashboard Pattern
372
+
373
+ 1. Configure env values from \`.env.oidc-dashboard.example\`.
374
+ 2. Register \`OidcTokenVerifierService\` as a provider.
375
+ 3. Provide \`CANONICAL_PLATFORM_PRINCIPAL_RESOLVER\` with an implementation that
376
+ maps the verified OIDC principal to \`VerifiedPlatformPrincipal\` through
377
+ Identity Manager and Business Entity. Do not set \`actor.subjectId\` to the
378
+ OIDC \`sub\` automatically; canonical subjects come from platform identity
379
+ services after broker verification.
380
+ 4. Apply \`OidcDashboardGuard\` to dashboard/admin API controllers. The guard
381
+ verifies the bearer token, resolves the canonical principal, builds
382
+ \`platformContext\` with \`createPlatformRequestContext\`, and attaches it to
383
+ the request. Do not read actor, business, or application identity from custom
384
+ headers or query parameters.
385
+ 5. Before privileged mutations, require both Service Access capability grants and
386
+ PARC action checks. Record Service Access and PARC decision references in the owner
387
+ audit trail.
388
+ 6. On first successful login, map broker identity to your local operator record
389
+ or ask PARC for roles/permissions.
390
+ 7. Keep the OIDC client secret in Vault, External Secrets, or the deployment
391
+ secret store. Never commit it.
392
+ 8. Set \`OIDC_JWKS_URL\` only when the broker does not expose keys at the
393
+ default ZITADEL-compatible \`/oauth/v2/keys\` path.
394
+
395
+ ## Environment Contract
396
+
397
+ - \`OIDC_ISSUER_URL\`: OIDC issuer URL, for example \`https://auth.example.com\`.
398
+ - \`OIDC_CLIENT_ID\`: dashboard/application client ID.
399
+ - \`OIDC_CLIENT_SECRET\`: secret loaded from the environment secret store.
400
+ - \`OIDC_CALLBACK_URL\`: exact redirect URI registered on the OIDC client.
401
+ - \`OIDC_SCOPES\`: comma-separated scopes, usually \`openid,profile,email\`.
402
+ - \`OIDC_ALLOWED_EMAIL_DOMAINS\`: comma-separated allow-list for staff/operator
403
+ domains. Leave empty only when the dashboard has a stronger local allow-list.
404
+ - \`OIDC_ROLE_CLAIM\`: token claim used for roles. Defaults to \`roles\`.
405
+ - \`OIDC_GROUP_CLAIM\`: token claim used for groups. Defaults to \`groups\`.
406
+
407
+ ## Role And Group Mapping Hook
408
+
409
+ \`oidc-access-mapping.ts\` is intentionally framework-neutral. Use
410
+ \`defaultOidcDashboardAccessMapping\` as the safe default, then wrap or replace
411
+ it when a dashboard needs to map broker roles/groups to local roles, tenant
412
+ access, or PARC permissions. Keep this mapping after token verification and
413
+ before local session creation.
414
+
415
+ ## Laravel/Filament Pattern
416
+
417
+ Laravel dashboards should use Socialite with an OpenID Connect provider.
418
+ Filament panels can either:
419
+
420
+ - use a Filament Socialite plugin when the panel wants provider buttons and
421
+ allow-list callbacks; or
422
+ - use a custom Socialite controller when tenant/PARC assignment is more complex.
423
+
424
+ The same rule applies: Socialite proves who logged in; the dashboard still needs
425
+ local/PARC authorization before showing resources.
426
+
427
+ ## Next.js/Node Pattern
428
+
429
+ Next.js dashboards should use Auth.js/NextAuth or \`openid-client\` with the
430
+ same issuer, client, callback URL, and scopes from the environment contract. In
431
+ the sign-in callback, enforce \`OIDC_ALLOWED_EMAIL_DOMAINS\`, then call the same
432
+ role/group mapping hook before writing the local session. Plain Node services
433
+ that receive bearer tokens can reuse the generated \`jose\` verifier pattern and
434
+ map roles/groups before applying route permissions.
435
+
436
+ ## Required Redirect Shape
437
+
438
+ Create one OIDC application per dashboard/environment. The redirect URI must
439
+ match the app exactly, for example:
440
+
441
+ \`\`\`text
442
+ https://dashboard.example.com/auth/oidc/callback
443
+ \`\`\`
444
+
445
+ For private/VPN-only staging surfaces, HTTP can be acceptable inside the private
446
+ network when the edge already terminates transport securely elsewhere, but
447
+ production dashboards should use HTTPS.
448
+ `;
449
+ const envExampleContent = `# OIDC dashboard SSO
450
+ OIDC_ISSUER_URL=https://auth.example.com
451
+ OIDC_CLIENT_ID=replace-me
452
+ OIDC_CLIENT_SECRET=replace-me
453
+ OIDC_CALLBACK_URL=https://dashboard.example.com/auth/oidc/callback
454
+ OIDC_POST_LOGOUT_REDIRECT_URL=https://dashboard.example.com
455
+ OIDC_SCOPES=openid,profile,email
456
+ OIDC_AUDIENCE=replace-me
457
+ OIDC_JWKS_URL=
458
+ OIDC_ROLE_CLAIM=roles
459
+ OIDC_GROUP_CLAIM=groups
460
+ OIDC_ADMIN_EMAILS=admin@example.com
461
+ OIDC_ALLOWED_EMAIL_DOMAINS=example.com
462
+ `;
463
+ //# sourceMappingURL=oidc-dashboard.recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-dashboard.recipe.js","sourceRoot":"","sources":["../../../src/commands/recipes/oidc-dashboard.recipe.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function applyOidcResourceServerRecipe(basePath: string, dryRun?: boolean): Promise<void>;
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.applyOidcResourceServerRecipe = applyOidcResourceServerRecipe;
37
+ const path = __importStar(require("node:path"));
38
+ const fs = __importStar(require("fs-extra"));
39
+ const file_utils_1 = require("../../utils/file.utils");
40
+ const files = [
41
+ ['verifier.ts.hbs', 'src/shared/auth/oidc-resource-server/oidc-access-token-verifier.ts'],
42
+ [
43
+ 'verifier.spec.ts.hbs',
44
+ 'src/shared/auth/oidc-resource-server/oidc-access-token-verifier.spec.ts',
45
+ ],
46
+ ['module.ts.hbs', 'src/shared/auth/oidc-resource-server/oidc-resource-server.module.ts'],
47
+ ['index.ts.hbs', 'src/shared/auth/oidc-resource-server/index.ts'],
48
+ ['README.md.hbs', 'docs/auth/oidc-resource-server.md'],
49
+ ];
50
+ async function assertTarget(root, file) {
51
+ let cursor = file.target;
52
+ while (cursor !== root) {
53
+ if (await fs.pathExists(cursor)) {
54
+ const stat = await fs.lstat(cursor);
55
+ if (stat.isSymbolicLink())
56
+ throw new Error(`Refusing symlink recipe target: ${cursor}`);
57
+ }
58
+ cursor = path.dirname(cursor);
59
+ }
60
+ if ((await fs.pathExists(file.target)) &&
61
+ (await fs.readFile(file.target, 'utf8')) !== file.content) {
62
+ throw new Error(`OIDC resource recipe target already differs: ${file.target}`);
63
+ }
64
+ }
65
+ async function applyOidcResourceServerRecipe(basePath, dryRun = false) {
66
+ const root = path.resolve(basePath);
67
+ const templateRoot = path.join(__dirname, '../../templates/recipes/oidc-resource-server');
68
+ const planned = await Promise.all(files.map(async ([source, target]) => ({
69
+ target: path.join(root, target),
70
+ content: await (0, file_utils_1.readTemplate)(path.join(templateRoot, source)),
71
+ })));
72
+ // Check every target before creating any directory or writing any file.
73
+ for (const file of planned) {
74
+ await assertTarget(root, file);
75
+ }
76
+ for (const file of planned) {
77
+ if (dryRun)
78
+ console.log(`Would generate: ${file.target}`);
79
+ else if (!(await fs.pathExists(file.target))) {
80
+ await fs.ensureDir(path.dirname(file.target));
81
+ await fs.writeFile(file.target, file.content, { flag: 'wx' });
82
+ }
83
+ }
84
+ }
85
+ //# sourceMappingURL=oidc-resource-server.recipe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"oidc-resource-server.recipe.js","sourceRoot":"","sources":["../../../src/commands/recipes/oidc-resource-server.recipe.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,sEAuBC;AA1DD,gDAAkC;AAClC,6CAA+B;AAC/B,uDAAsD;AAEtD,MAAM,KAAK,GAAG;IACZ,CAAC,iBAAiB,EAAE,oEAAoE,CAAC;IACzF;QACE,sBAAsB;QACtB,yEAAyE;KAC1E;IACD,CAAC,eAAe,EAAE,qEAAqE,CAAC;IACxF,CAAC,cAAc,EAAE,+CAA+C,CAAC;IACjE,CAAC,eAAe,EAAE,mCAAmC,CAAC;CAC9C,CAAC;AAEX,KAAK,UAAU,YAAY,CACzB,IAAY,EACZ,IAAyC;IAEzC,IAAI,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACzB,OAAO,MAAM,KAAK,IAAI,EAAE,CAAC;QACvB,IAAI,MAAM,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpC,IAAI,IAAI,CAAC,cAAc,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,mCAAmC,MAAM,EAAE,CAAC,CAAC;QAC1F,CAAC;QACD,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAChC,CAAC;IACD,IACE,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC,OAAO,EACzD,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACjF,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,6BAA6B,CACjD,QAAgB,EAChB,MAAM,GAAG,KAAK;IAEd,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,8CAA8C,CAAC,CAAC;IAC1F,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;QAC/B,OAAO,EAAE,MAAM,IAAA,yBAAY,EAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;KAC7D,CAAC,CAAC,CACJ,CAAC;IACF,wEAAwE;IACxE,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACjC,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,MAAM;YAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;aACrD,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;YAC7C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC9C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export declare function applyPlatformContextRecipe(basePath: string): Promise<void>;