@atlashub/smartstack-cli 3.37.0 → 3.39.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 (228) hide show
  1. package/dist/index.js +16 -24
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +235 -265
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/scripts/extract-api-endpoints.ts +5 -5
  7. package/scripts/generate-doc-with-mock-ui.ts +10 -17
  8. package/templates/agents/ba-reader.md +9 -9
  9. package/templates/agents/ba-writer.md +12 -15
  10. package/templates/agents/code-reviewer.md +1 -1
  11. package/templates/agents/docs-context-reader.md +1 -1
  12. package/templates/agents/efcore/scan.md +3 -1
  13. package/templates/agents/gitflow/commit.md +74 -0
  14. package/templates/agents/gitflow/finish.md +5 -2
  15. package/templates/agents/gitflow/init-clone.md +3 -3
  16. package/templates/agents/gitflow/init-validate.md +3 -2
  17. package/templates/agents/gitflow/merge.md +5 -4
  18. package/templates/agents/gitflow/pr.md +5 -4
  19. package/templates/agents/gitflow/start.md +37 -5
  20. package/templates/hooks/hooks.json +11 -0
  21. package/templates/hooks/wsl-dotnet-cleanup.sh +24 -0
  22. package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +20 -20
  23. package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +16 -24
  24. package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +2 -2
  25. package/templates/skills/_resources/mcp-validate-documentation-spec.md +3 -3
  26. package/templates/skills/_shared.md +15 -17
  27. package/templates/skills/ai-prompt/SKILL.md +1 -1
  28. package/templates/skills/ai-prompt/steps/step-00-init.md +47 -0
  29. package/templates/skills/apex/SKILL.md +3 -4
  30. package/templates/skills/apex/_shared.md +10 -20
  31. package/templates/skills/apex/references/analysis-methods.md +141 -0
  32. package/templates/skills/apex/references/challenge-questions.md +1 -21
  33. package/templates/skills/apex/references/core-seed-data.md +35 -58
  34. package/templates/skills/apex/references/examine-build-validation.md +82 -0
  35. package/templates/skills/apex/references/execution-frontend-gates.md +177 -0
  36. package/templates/skills/apex/references/execution-frontend-patterns.md +105 -0
  37. package/templates/skills/apex/references/execution-layer1-rules.md +96 -0
  38. package/templates/skills/apex/references/initialization-challenge-flow.md +110 -0
  39. package/templates/skills/apex/references/planning-layer-mapping.md +151 -0
  40. package/templates/skills/apex/references/post-checks.md +145 -40
  41. package/templates/skills/apex/references/smartstack-api.md +35 -51
  42. package/templates/skills/apex/references/smartstack-frontend.md +18 -18
  43. package/templates/skills/apex/references/smartstack-layers.md +38 -62
  44. package/templates/skills/apex/steps/step-00-init.md +14 -26
  45. package/templates/skills/apex/steps/step-01-analyze.md +10 -143
  46. package/templates/skills/apex/steps/step-02-plan.md +10 -92
  47. package/templates/skills/apex/steps/step-03-execute.md +45 -252
  48. package/templates/skills/apex/steps/step-04-examine.md +14 -78
  49. package/templates/skills/apex/steps/step-05-deep-review.md +2 -2
  50. package/templates/skills/apex/steps/step-08-run-tests.md +1 -0
  51. package/templates/skills/application/SKILL.md +241 -242
  52. package/templates/skills/application/references/backend-controller-hierarchy.md +16 -16
  53. package/templates/skills/application/references/backend-seeding-and-dto-output.md +83 -0
  54. package/templates/skills/application/references/backend-table-prefix-mapping.md +79 -0
  55. package/templates/skills/application/references/backend-verification.md +1 -1
  56. package/templates/skills/application/references/frontend-i18n-and-output.md +67 -0
  57. package/templates/skills/application/references/frontend-route-naming.md +117 -0
  58. package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +107 -0
  59. package/templates/skills/application/references/frontend-verification.md +12 -12
  60. package/templates/skills/application/references/init-parameter-detection.md +121 -0
  61. package/templates/skills/application/references/migration-checklist-troubleshooting.md +100 -0
  62. package/templates/skills/application/references/nav-fallback-procedure.md +199 -200
  63. package/templates/skills/application/references/provider-template.md +2 -6
  64. package/templates/skills/application/references/roles-client-project-handling.md +55 -0
  65. package/templates/skills/application/references/roles-fallback-procedure.md +149 -0
  66. package/templates/skills/application/references/test-coverage-requirements.md +213 -0
  67. package/templates/skills/application/references/test-frontend.md +3 -3
  68. package/templates/skills/application/steps/step-00-init.md +130 -260
  69. package/templates/skills/application/steps/step-01-navigation.md +170 -170
  70. package/templates/skills/application/steps/step-02-permissions.md +196 -196
  71. package/templates/skills/application/steps/step-03-roles.md +182 -339
  72. package/templates/skills/application/steps/step-03b-provider.md +133 -134
  73. package/templates/skills/application/steps/step-04-backend.md +174 -265
  74. package/templates/skills/application/steps/step-05-frontend.md +18 -144
  75. package/templates/skills/application/steps/step-06-migration.md +12 -60
  76. package/templates/skills/application/steps/step-07-tests.md +9 -76
  77. package/templates/skills/application/templates-backend.md +29 -27
  78. package/templates/skills/application/templates-frontend.md +49 -49
  79. package/templates/skills/application/templates-seed.md +57 -131
  80. package/templates/skills/business-analyse/SKILL.md +27 -30
  81. package/templates/skills/business-analyse/_architecture.md +6 -6
  82. package/templates/skills/business-analyse/_shared.md +60 -88
  83. package/templates/skills/business-analyse/questionnaire/04-data.md +3 -3
  84. package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
  85. package/templates/skills/business-analyse/questionnaire/13-cross-module.md +1 -1
  86. package/templates/skills/business-analyse/react/application-viewer.md +12 -12
  87. package/templates/skills/business-analyse/react/components.md +8 -12
  88. package/templates/skills/business-analyse/react/schema.md +836 -836
  89. package/templates/skills/business-analyse/references/agent-module-prompt.md +2 -3
  90. package/templates/skills/business-analyse/references/analysis-semantic-checks.md +190 -0
  91. package/templates/skills/business-analyse/references/cache-warming-strategy.md +2 -2
  92. package/templates/skills/business-analyse/references/cadrage-challenge-patterns.md +41 -0
  93. package/templates/skills/business-analyse/references/cadrage-coverage-matrix.md +74 -0
  94. package/templates/skills/business-analyse/references/cadrage-shared-modules.md +69 -0
  95. package/templates/skills/business-analyse/references/cadrage-structure-cards.md +1 -1
  96. package/templates/skills/business-analyse/references/compilation-structure-cards.md +297 -0
  97. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +2 -2
  98. package/templates/skills/business-analyse/references/deploy-modes.md +5 -5
  99. package/templates/skills/business-analyse/references/detection-strategies.md +7 -7
  100. package/templates/skills/business-analyse/references/handoff-file-templates.md +14 -22
  101. package/templates/skills/business-analyse/references/handoff-mappings.md +4 -4
  102. package/templates/skills/business-analyse/references/handoff-seeddata-generation.md +312 -0
  103. package/templates/skills/business-analyse/references/init-schema-deployment.md +3 -3
  104. package/templates/skills/business-analyse/references/naming-conventions.md +22 -24
  105. package/templates/skills/business-analyse/references/prd-generation.md +2 -2
  106. package/templates/skills/business-analyse/references/review-data-mapping.md +2 -2
  107. package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
  108. package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
  109. package/templates/skills/business-analyse/references/team-orchestration.md +49 -6
  110. package/templates/skills/business-analyse/references/ui-dashboard-spec.md +1 -1
  111. package/templates/skills/business-analyse/references/ui-resource-cards.md +18 -18
  112. package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -2
  113. package/templates/skills/business-analyse/references/validation-checklist.md +2 -2
  114. package/templates/skills/business-analyse/schemas/application-schema.json +4 -5
  115. package/templates/skills/business-analyse/schemas/project-schema.json +1 -6
  116. package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -3
  117. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +4 -4
  118. package/templates/skills/business-analyse/steps/step-00-init.md +8 -17
  119. package/templates/skills/business-analyse/steps/step-01-cadrage.md +35 -198
  120. package/templates/skills/business-analyse/steps/step-01b-applications.md +16 -20
  121. package/templates/skills/business-analyse/steps/step-02-decomposition.md +1 -1
  122. package/templates/skills/business-analyse/steps/step-03a1-setup.md +4 -4
  123. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +1 -1
  124. package/templates/skills/business-analyse/steps/step-03b-ui.md +4 -4
  125. package/templates/skills/business-analyse/steps/step-03c-compile.md +66 -140
  126. package/templates/skills/business-analyse/steps/step-03d-validate.md +2 -2
  127. package/templates/skills/business-analyse/steps/step-04a-collect.md +2 -2
  128. package/templates/skills/business-analyse/steps/step-04b-analyze.md +42 -160
  129. package/templates/skills/business-analyse/steps/step-04c-decide.md +1 -1
  130. package/templates/skills/business-analyse/steps/step-05a-handoff.md +74 -104
  131. package/templates/skills/business-analyse/steps/step-05b-deploy.md +13 -11
  132. package/templates/skills/business-analyse/steps/step-06-review.md +3 -3
  133. package/templates/skills/business-analyse/templates/tpl-frd.md +13 -13
  134. package/templates/skills/business-analyse/templates/tpl-handoff.md +12 -12
  135. package/templates/skills/business-analyse/templates/tpl-progress.md +1 -1
  136. package/templates/skills/business-analyse/templates-frd.md +25 -25
  137. package/templates/skills/business-analyse/templates-react.md +15 -21
  138. package/templates/skills/controller/SKILL.md +1 -1
  139. package/templates/skills/controller/postman-templates.md +1 -1
  140. package/templates/skills/controller/references/controller-code-templates.md +2 -2
  141. package/templates/skills/controller/references/mcp-scaffold-workflow.md +209 -0
  142. package/templates/skills/controller/references/permission-sync-templates.md +13 -16
  143. package/templates/skills/controller/steps/step-00-init.md +11 -11
  144. package/templates/skills/controller/steps/step-03-generate.md +64 -103
  145. package/templates/skills/controller/templates.md +67 -71
  146. package/templates/skills/debug/SKILL.md +13 -218
  147. package/templates/skills/debug/steps/step-00-init.md +57 -0
  148. package/templates/skills/debug/steps/step-01-analyze.md +219 -0
  149. package/templates/skills/debug/steps/step-02-resolve.md +85 -0
  150. package/templates/skills/documentation/SKILL.md +49 -345
  151. package/templates/skills/documentation/data-schema.md +11 -8
  152. package/templates/skills/documentation/steps/step-00-init.md +70 -0
  153. package/templates/skills/documentation/steps/step-01-scan.md +113 -0
  154. package/templates/skills/documentation/steps/step-02-generate.md +231 -0
  155. package/templates/skills/documentation/steps/step-03-validate.md +238 -0
  156. package/templates/skills/documentation/templates.md +480 -322
  157. package/templates/skills/efcore/SKILL.md +1 -1
  158. package/templates/skills/efcore/references/both-contexts.md +32 -0
  159. package/templates/skills/efcore/references/database-operations.md +67 -0
  160. package/templates/skills/efcore/references/destructive-operations.md +38 -0
  161. package/templates/skills/efcore/references/reset-operations.md +81 -0
  162. package/templates/skills/efcore/references/seed-methods.md +86 -0
  163. package/templates/skills/efcore/references/shared-init-functions.md +250 -0
  164. package/templates/skills/efcore/references/sql-objects-injection.md +61 -0
  165. package/templates/skills/efcore/references/troubleshooting.md +81 -0
  166. package/templates/skills/efcore/steps/db/step-deploy.md +1 -32
  167. package/templates/skills/efcore/steps/db/step-reset.md +7 -103
  168. package/templates/skills/efcore/steps/db/step-seed.md +10 -132
  169. package/templates/skills/efcore/steps/db/step-status.md +5 -44
  170. package/templates/skills/efcore/steps/migration/step-02-create.md +1 -14
  171. package/templates/skills/efcore/steps/migration/step-03-validate.md +8 -62
  172. package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +1 -57
  173. package/templates/skills/efcore/steps/shared/step-00-init.md +11 -254
  174. package/templates/skills/efcore/steps/squash/step-03-create.md +1 -58
  175. package/templates/skills/feature-full/SKILL.md +1 -1
  176. package/templates/skills/feature-full/steps/step-00-init.md +57 -0
  177. package/templates/skills/feature-full/steps/step-01-implementation.md +1 -1
  178. package/templates/skills/gitflow/SKILL.md +28 -5
  179. package/templates/skills/gitflow/_shared.md +109 -12
  180. package/templates/skills/gitflow/phases/abort.md +4 -0
  181. package/templates/skills/gitflow/phases/cleanup.md +4 -0
  182. package/templates/skills/gitflow/references/commit-message-generation.md +58 -0
  183. package/templates/skills/gitflow/references/commit-migration-validation.md +49 -0
  184. package/templates/skills/gitflow/references/finish-cleanup.md +55 -0
  185. package/templates/skills/gitflow/references/finish-version-bumping.md +45 -0
  186. package/templates/skills/gitflow/references/init-environment-detection.md +41 -0
  187. package/templates/skills/gitflow/references/init-questions.md +185 -0
  188. package/templates/skills/gitflow/references/init-structure-creation.md +75 -0
  189. package/templates/skills/gitflow/references/init-version-detection.md +21 -0
  190. package/templates/skills/gitflow/references/init-workspace-detection.md +43 -0
  191. package/templates/skills/gitflow/references/merge-ci-status.md +36 -0
  192. package/templates/skills/gitflow/references/merge-execution.md +62 -0
  193. package/templates/skills/gitflow/references/merge-pr-context.md +76 -0
  194. package/templates/skills/gitflow/references/pr-build-checks.md +60 -0
  195. package/templates/skills/gitflow/references/pr-generation.md +58 -0
  196. package/templates/skills/gitflow/references/start-branch-normalization.md +28 -0
  197. package/templates/skills/gitflow/references/start-worktree-creation.md +50 -0
  198. package/templates/skills/gitflow/references/sync-push-verify.md +44 -0
  199. package/templates/skills/gitflow/references/sync-rebase-conflicts.md +38 -0
  200. package/templates/skills/gitflow/steps/step-commit.md +12 -91
  201. package/templates/skills/gitflow/steps/step-finish.md +15 -159
  202. package/templates/skills/gitflow/steps/step-init.md +24 -326
  203. package/templates/skills/gitflow/steps/step-merge.md +17 -176
  204. package/templates/skills/gitflow/steps/step-pr.md +10 -116
  205. package/templates/skills/gitflow/steps/step-start.md +16 -109
  206. package/templates/skills/gitflow/steps/step-sync.md +6 -69
  207. package/templates/skills/ralph-loop/SKILL.md +6 -0
  208. package/templates/skills/ralph-loop/references/category-completeness.md +185 -0
  209. package/templates/skills/ralph-loop/references/compact-loop.md +1 -1
  210. package/templates/skills/ralph-loop/references/init-resume-recovery.md +127 -0
  211. package/templates/skills/ralph-loop/references/module-transition.md +151 -0
  212. package/templates/skills/ralph-loop/references/multi-module-queue.md +171 -0
  213. package/templates/skills/ralph-loop/references/parallel-execution.md +246 -0
  214. package/templates/skills/ralph-loop/references/task-transform-legacy.md +6 -9
  215. package/templates/skills/ralph-loop/references/team-orchestration.md +45 -3
  216. package/templates/skills/ralph-loop/steps/step-00-init.md +36 -109
  217. package/templates/skills/ralph-loop/steps/step-01-task.md +15 -163
  218. package/templates/skills/ralph-loop/steps/step-02-execute.md +8 -154
  219. package/templates/skills/ralph-loop/steps/step-04-check.md +20 -73
  220. package/templates/skills/review-code/references/owasp-api-top10.md +5 -5
  221. package/templates/skills/review-code/references/smartstack-conventions.md +568 -568
  222. package/templates/skills/validate-feature/references/api-smoke-tests.md +140 -0
  223. package/templates/skills/validate-feature/references/db-validation-checks.md +180 -0
  224. package/templates/skills/validate-feature/steps/step-01-compile.md +1 -3
  225. package/templates/skills/validate-feature/steps/step-04-api-smoke.md +34 -145
  226. package/templates/skills/validate-feature/steps/step-05-db-validation.md +74 -260
  227. package/templates/skills/workflow/SKILL.md +1 -1
  228. package/templates/skills/workflow/steps/step-00-init.md +57 -0
@@ -25916,7 +25916,7 @@ var init_types3 = __esm({
25916
25916
  withValidation: external_exports.boolean().optional().describe("For feature type: generate FluentValidation validators"),
25917
25917
  withRepository: external_exports.boolean().optional().describe("For feature type: generate repository pattern"),
25918
25918
  entityProperties: external_exports.array(EntityPropertySchema).optional().describe("Entity properties for DTO/Validator generation"),
25919
- navRoute: external_exports.string().optional().describe('Navigation route path for controller (e.g., "platform.administration.users"). Required for controllers.'),
25919
+ navRoute: external_exports.string().optional().describe('Navigation route path for controller (e.g., "administration.users"). Required for controllers.'),
25920
25920
  navRouteSuffix: external_exports.string().optional().describe('Optional suffix for NavRoute (e.g., "dashboard" for sub-resources)'),
25921
25921
  withHierarchyFunction: external_exports.boolean().optional().describe("For entity type with self-reference (ParentId): generate TVF SQL script for hierarchy traversal"),
25922
25922
  hierarchyDirection: external_exports.enum(["ancestors", "descendants", "both"]).optional().describe("Direction for hierarchy traversal function (default: both)")
@@ -25933,7 +25933,7 @@ var init_types3 = __esm({
25933
25933
  version: external_exports.string().optional().describe('Semver version (e.g., "1.0.0", "1.2.0"). If not provided, uses latest from existing migrations.')
25934
25934
  });
25935
25935
  GeneratePermissionsInputSchema = external_exports.object({
25936
- navRoute: external_exports.string().optional().describe('NavRoute path (e.g., "platform.administration.entra"). If not provided, scans all controllers.'),
25936
+ navRoute: external_exports.string().optional().describe('NavRoute path (e.g., "administration.entra"). If not provided, scans all controllers.'),
25937
25937
  actions: external_exports.array(external_exports.string()).optional().describe("Custom actions to generate (default: read, create, update, delete)"),
25938
25938
  includeStandardActions: external_exports.boolean().default(true).describe("Include standard CRUD actions (read, create, update, delete)"),
25939
25939
  generateMigration: external_exports.boolean().default(true).describe("Generate EF Core migration to seed permissions in database"),
@@ -26014,7 +26014,7 @@ var init_types3 = __esm({
26014
26014
  });
26015
26015
  ScaffoldApiClientInputSchema = external_exports.object({
26016
26016
  path: external_exports.string().optional().describe("Path to SmartStack project root (defaults to configured project path)"),
26017
- navRoute: external_exports.string().min(1).describe('NavRoute path (e.g., "platform.administration.users")'),
26017
+ navRoute: external_exports.string().min(1).describe('NavRoute path (e.g., "administration.users")'),
26018
26018
  name: external_exports.string().min(1).describe('Entity name in PascalCase (e.g., "User", "Order")'),
26019
26019
  methods: external_exports.array(external_exports.enum(["getAll", "getById", "create", "update", "delete", "search", "export"])).default(["getAll", "getById", "create", "update", "delete"]).describe("API methods to generate"),
26020
26020
  options: external_exports.object({
@@ -26027,7 +26027,7 @@ var init_types3 = __esm({
26027
26027
  ScaffoldRoutesInputSchema = external_exports.object({
26028
26028
  path: external_exports.string().optional().describe("Path to SmartStack project root (defaults to configured project path)"),
26029
26029
  source: external_exports.enum(["controllers", "navigation", "manual"]).default("controllers").describe("Source for route discovery: controllers (scan NavRoute attributes), navigation (from DB), manual (from config)"),
26030
- scope: external_exports.enum(["all", "platform", "business", "extensions"]).default("all").describe("Scope of routes to generate"),
26030
+ scope: external_exports.string().default("all").describe('Scope of routes to generate. Use "all" or a specific application name (e.g., "administration")'),
26031
26031
  options: external_exports.object({
26032
26032
  outputPath: external_exports.string().optional().describe("Custom output path"),
26033
26033
  includeLayouts: external_exports.boolean().default(true).describe("Generate layout components"),
@@ -27185,13 +27185,13 @@ async function validateControllerRoutes(structure, _config, result) {
27185
27185
  if (navRouteMatch) {
27186
27186
  const routePath = navRouteMatch[1];
27187
27187
  const parts = routePath.split(".");
27188
- if (parts.length < 2) {
27189
- result.warnings.push({
27190
- type: "warning",
27188
+ if (parts.length < 3) {
27189
+ result.errors.push({
27190
+ type: "error",
27191
27191
  category: "controllers",
27192
27192
  message: `Controller "${fileName}" has NavRoute with insufficient depth: "${routePath}"`,
27193
27193
  file: path8.relative(structure.root, file),
27194
- suggestion: 'NavRoute should have at least 2 levels: "context.application" (e.g., "platform.administration")'
27194
+ suggestion: 'NavRoute must have at least 3 levels: "application.module.section" (e.g., "administration.users.management")'
27195
27195
  });
27196
27196
  }
27197
27197
  const hasUppercase = parts.some((part) => part !== part.toLowerCase());
@@ -27201,7 +27201,7 @@ async function validateControllerRoutes(structure, _config, result) {
27201
27201
  category: "controllers",
27202
27202
  message: `Controller "${fileName}" has NavRoute with uppercase characters: "${routePath}"`,
27203
27203
  file: path8.relative(structure.root, file),
27204
- suggestion: 'NavRoute paths must be lowercase (e.g., "platform.administration.users")'
27204
+ suggestion: 'NavRoute paths must be lowercase (e.g., "administration.users")'
27205
27205
  });
27206
27206
  }
27207
27207
  const routeAttrMatch = content.match(/\[Route\s*\(\s*"([^"]+)"\s*\)\]/);
@@ -27222,7 +27222,7 @@ async function validateControllerRoutes(structure, _config, result) {
27222
27222
  category: "controllers",
27223
27223
  message: `Controller "${fileName}" uses hardcoded Route instead of NavRoute`,
27224
27224
  file: path8.relative(structure.root, file),
27225
- suggestion: 'Use [NavRoute("context.application.module")] for navigation-based routing'
27225
+ suggestion: 'Use [NavRoute("application.module.section")] for navigation-based routing'
27226
27226
  });
27227
27227
  }
27228
27228
  }
@@ -27975,15 +27975,6 @@ async function validateFeatureJson(structure, _config, result) {
27975
27975
  suggestion: 'Rename "lastModified" to "updatedAt" for schema compliance'
27976
27976
  });
27977
27977
  }
27978
- if (data.metadata?.context && data.metadata.context !== "business" && relPath.includes("Business")) {
27979
- result.warnings.push({
27980
- type: "warning",
27981
- category: "feature-json",
27982
- message: `feature.json context is "${data.metadata.context}" but file is in Business directory`,
27983
- file: relPath,
27984
- suggestion: 'Use context: "business" for business domain features'
27985
- });
27986
- }
27987
27978
  if (data.metadata?.analysisMode && data.metadata.analysisMode !== "interactive") {
27988
27979
  result.errors.push({
27989
27980
  type: "error",
@@ -34432,24 +34423,24 @@ var require_lib = __commonJS({
34432
34423
  import path10 from "path";
34433
34424
  function resolveHierarchy(navRoute) {
34434
34425
  if (!navRoute) {
34435
- return { context: "", application: "", module: "", domainPath: "", infraPath: "", controllerArea: "" };
34426
+ return { application: "", module: "", section: "", domainPath: "", infraPath: "", controllerArea: "" };
34436
34427
  }
34437
34428
  const segments = navRoute.split(".");
34438
34429
  const toPascal = (s) => s.split("-").map((p) => p.charAt(0).toUpperCase() + p.slice(1)).join("");
34439
- const context = segments[0] ? toPascal(segments[0]) : "";
34440
- const application = segments[1] ? toPascal(segments[1]) : "";
34441
- const module = segments[2] ? toPascal(segments[2]) : segments[1] ? toPascal(segments[1]) : "";
34430
+ const application = segments[0] ? toPascal(segments[0]) : "";
34431
+ const module = segments[1] ? toPascal(segments[1]) : "";
34432
+ const section = segments[2] ? toPascal(segments[2]) : "";
34442
34433
  let domainPath = "";
34443
34434
  if (segments.length >= 3) {
34444
- domainPath = path10.join(context, application, module);
34445
- } else if (segments.length === 2) {
34446
- domainPath = path10.join(context, module);
34435
+ domainPath = path10.join(application, module, section);
34436
+ } else if (segments.length >= 2) {
34437
+ domainPath = path10.join(application, module);
34447
34438
  } else if (segments.length === 1) {
34448
- domainPath = context;
34439
+ domainPath = application;
34449
34440
  }
34450
34441
  const infraPath = domainPath;
34451
- const controllerArea = context;
34452
- return { context, application, module, domainPath, infraPath, controllerArea };
34442
+ const controllerArea = application;
34443
+ return { application, module, section, domainPath, infraPath, controllerArea };
34453
34444
  }
34454
34445
  async function handleScaffoldExtension(args, config2) {
34455
34446
  const input = ScaffoldExtensionInputSchema.parse(args);
@@ -34596,7 +34587,7 @@ async function scaffoldFeature(name, options, structure, config2, result, dryRun
34596
34587
  result.instructions.push(`${withRepository ? withValidation ? "6" : "5" : withValidation ? "5" : "4"}. Run migration: \`dotnet ef database update --context ${dbContextName}\``);
34597
34588
  if (!skipComponent) {
34598
34589
  const featureHierarchy = resolveHierarchy(options?.navRoute);
34599
- const featureComponentPath = featureHierarchy.context && featureHierarchy.module ? `@/components/${featureHierarchy.context.toLowerCase()}/${featureHierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
34590
+ const featureComponentPath = featureHierarchy.application && featureHierarchy.module ? `@/components/${featureHierarchy.application.toLowerCase()}/${featureHierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
34600
34591
  result.instructions.push(`Import component: \`import { ${name} } from '${featureComponentPath}';\``);
34601
34592
  }
34602
34593
  }
@@ -35413,12 +35404,12 @@ public class {{name}}Controller : ControllerBase
35413
35404
  result.instructions.push("");
35414
35405
  result.instructions.push("NavRoute resolves API routes from Navigation entities in the database.");
35415
35406
  result.instructions.push("Ensure the navigation path exists (seed data required):");
35416
- result.instructions.push(` Context > Application > Module matching "${navRoute}"`);
35407
+ result.instructions.push(` Application > Module > Section matching "${navRoute}"`);
35417
35408
  } else {
35418
35409
  result.instructions.push("Controller created with traditional routing.");
35419
35410
  result.instructions.push("");
35420
35411
  result.instructions.push("\u26A0\uFE0F Consider using NavRoute for navigation-based routing:");
35421
- result.instructions.push(` [NavRoute("context.application.module")]`);
35412
+ result.instructions.push(` [NavRoute("application.module.section")]`);
35422
35413
  result.instructions.push("");
35423
35414
  result.instructions.push("API endpoints (with traditional routing):");
35424
35415
  result.instructions.push(` GET /api/${name.toLowerCase()}`);
@@ -35583,7 +35574,7 @@ export function use{{name}}(options: Use{{name}}Options = {}) {
35583
35574
  const projectRoot = config2.smartstack.projectPath;
35584
35575
  const webPath = structure.web || path10.join(projectRoot, "web");
35585
35576
  const componentsBase = path10.join(webPath, "src", "components");
35586
- const componentsPath = options?.outputPath ? options.outputPath : hierarchy.context && hierarchy.module ? path10.join(componentsBase, hierarchy.context.toLowerCase(), hierarchy.module.toLowerCase()) : componentsBase;
35577
+ const componentsPath = options?.outputPath ? options.outputPath : hierarchy.application && hierarchy.module ? path10.join(componentsBase, hierarchy.application.toLowerCase(), hierarchy.module.toLowerCase()) : componentsBase;
35587
35578
  const hooksPath = path10.join(webPath, "src", "hooks");
35588
35579
  const componentFilePath = path10.join(componentsPath, `${name}.tsx`);
35589
35580
  const hookFilePath = path10.join(hooksPath, `use${name}.ts`);
@@ -35598,7 +35589,7 @@ export function use{{name}}(options: Use{{name}}Options = {}) {
35598
35589
  result.files.push({ path: componentFilePath, content: componentContent, type: "created" });
35599
35590
  result.files.push({ path: hookFilePath, content: hookContent, type: "created" });
35600
35591
  result.instructions.push("Import and use the component:");
35601
- const componentImportPath = hierarchy.context && hierarchy.module ? `@/components/${hierarchy.context.toLowerCase()}/${hierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
35592
+ const componentImportPath = hierarchy.application && hierarchy.module ? `@/components/${hierarchy.application.toLowerCase()}/${hierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
35602
35593
  result.instructions.push(`import { ${name} } from '${componentImportPath}';`);
35603
35594
  result.instructions.push(`import { use${name} } from '@/hooks/use${name}';`);
35604
35595
  result.instructions.push("");
@@ -35614,7 +35605,7 @@ export function use{{name}}(options: Use{{name}}Options = {}) {
35614
35605
  result.instructions.push('import { EntityLookup } from "@/components/ui/EntityLookup";');
35615
35606
  result.instructions.push("");
35616
35607
  result.instructions.push("<EntityLookup");
35617
- result.instructions.push(' apiEndpoint="/api/{context}/{app}/{related-entity}"');
35608
+ result.instructions.push(' apiEndpoint="/api/{app}/{related-entity}"');
35618
35609
  result.instructions.push(" value={formData.relatedEntityId}");
35619
35610
  result.instructions.push(' onChange={(id) => handleChange("relatedEntityId", id)}');
35620
35611
  result.instructions.push(' label="Related Entity"');
@@ -36482,7 +36473,7 @@ var init_scaffold_extension = __esm({
36482
36473
  },
36483
36474
  navRoute: {
36484
36475
  type: "string",
36485
- description: 'Navigation route path for controller (e.g., "platform.administration.users"). Required for controllers.'
36476
+ description: 'Navigation route path for controller (e.g., "administration.users.management"). Minimum 3 levels: application.module.section. Optional 4th: resource.'
36486
36477
  },
36487
36478
  navRouteSuffix: {
36488
36479
  type: "string",
@@ -53028,16 +53019,16 @@ async function handleGeneratePermissions(args, config2) {
53028
53019
  function generatePermissionsForNavRoute(navRoute, customActions, includeStandardActions, includeWildcard = true) {
53029
53020
  const permissions = [];
53030
53021
  const parts = navRoute.split(".");
53031
- const context = parts[0];
53022
+ const application = parts[0];
53032
53023
  if (parts.length < 3) {
53033
- throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: context.application.module`);
53024
+ throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: application.module.section (minimum 3 levels, optional 4th: resource)`);
53034
53025
  }
53035
53026
  if (includeWildcard) {
53036
53027
  permissions.push({
53037
53028
  code: `${navRoute}.*`,
53038
53029
  name: formatPermissionName(navRoute, "Full Access"),
53039
53030
  description: `Full ${parts[parts.length - 1]} management`,
53040
- category: context
53031
+ category: application
53041
53032
  });
53042
53033
  }
53043
53034
  for (const customAction of customActions) {
@@ -53057,7 +53048,7 @@ function generatePermissionsForNavRoute(navRoute, customActions, includeStandard
53057
53048
  code,
53058
53049
  name,
53059
53050
  description,
53060
- category: context
53051
+ category: application
53061
53052
  });
53062
53053
  }
53063
53054
  return permissions;
@@ -53138,14 +53129,23 @@ function formatPermissionName(navRoute, action) {
53138
53129
  }
53139
53130
  function formatPermissionDescription(navRoute, action) {
53140
53131
  const parts = navRoute.split(".");
53141
- const context = parts[0];
53142
- const application = parts[1];
53143
- const module = parts[2];
53144
- const contextName = context.charAt(0).toUpperCase() + context.slice(1);
53145
- const applicationName = application.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53146
- const moduleName = module.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53132
+ const application = parts[0];
53133
+ const module = parts[1];
53134
+ const section = parts[2];
53135
+ const toTitleCase = (s) => s.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53136
+ const applicationName = toTitleCase(application);
53137
+ const moduleName = toTitleCase(module);
53147
53138
  const actionVerb = getActionVerb(action);
53148
- return `${actionVerb} ${moduleName} in ${contextName} > ${applicationName}`;
53139
+ if (parts.length >= 4) {
53140
+ const sectionName = toTitleCase(section);
53141
+ const resourceName = toTitleCase(parts[parts.length - 1]);
53142
+ return `${actionVerb} ${resourceName} in ${applicationName} > ${moduleName} > ${sectionName}`;
53143
+ }
53144
+ if (section) {
53145
+ const sectionName = toTitleCase(section);
53146
+ return `${actionVerb} ${sectionName} in ${applicationName} > ${moduleName}`;
53147
+ }
53148
+ return `${actionVerb} ${moduleName} in ${applicationName}`;
53149
53149
  }
53150
53150
  function getActionVerb(action) {
53151
53151
  const verbs = {
@@ -53200,12 +53200,27 @@ function getUniqueNavRouteCount(permissions) {
53200
53200
  }
53201
53201
  function generateHasDataCode(permissions, navRoute) {
53202
53202
  const parts = navRoute.split(".");
53203
- const moduleName = parts.length >= 3 ? parts[parts.length - 1] : "custom";
53204
- const moduleVarName = `${moduleName}ModuleId`;
53203
+ const lastSegment = parts[parts.length - 1];
53204
+ const depth = parts.length;
53205
+ let permissionLevel;
53206
+ let fkProperty;
53207
+ let fkVarName;
53208
+ let seedDataSource;
53209
+ if (depth >= 4) {
53210
+ permissionLevel = "PermissionLevel.Resource";
53211
+ fkProperty = "ResourceId";
53212
+ fkVarName = `${lastSegment}ResourceId`;
53213
+ seedDataSource = "NavigationResourceSeedData.cs";
53214
+ } else {
53215
+ permissionLevel = "PermissionLevel.Section";
53216
+ fkProperty = "SectionId";
53217
+ fkVarName = `${lastSegment}SectionId`;
53218
+ seedDataSource = "NavigationSectionSeedData.cs";
53219
+ }
53205
53220
  let code = "```csharp\n";
53206
- code += `// 1. Add module ID variable (get from NavigationModuleSeedData.cs)
53221
+ code += `// 1. Add ${fkProperty} variable (get from ${seedDataSource})
53207
53222
  `;
53208
- code += `var ${moduleVarName} = Guid.Parse("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); // TODO: Replace with actual ID
53223
+ code += `var ${fkVarName} = Guid.Parse("XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX"); // TODO: Replace with actual ID
53209
53224
 
53210
53225
  `;
53211
53226
  code += `// 2. Add these entries to the HasData() return array:
@@ -53215,11 +53230,11 @@ function generateHasDataCode(permissions, navRoute) {
53215
53230
  const action = perm.code.split(".").pop();
53216
53231
  const guidPlaceholder = generatePlaceholderGuid();
53217
53232
  if (isWildcard) {
53218
- code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = PermissionLevel.Module, IsWildcard = true, ModuleId = ${moduleVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53233
+ code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = ${permissionLevel}, IsWildcard = true, ${fkProperty} = ${fkVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53219
53234
  `;
53220
53235
  } else {
53221
53236
  const actionEnum = getActionEnum(action || "read");
53222
- code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = PermissionLevel.Module, Action = PermissionAction.${actionEnum}, IsWildcard = false, ModuleId = ${moduleVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53237
+ code += `new { Id = Guid.Parse("${guidPlaceholder}"), Path = "${perm.code}", Level = ${permissionLevel}, Action = PermissionAction.${actionEnum}, IsWildcard = false, ${fkProperty} = ${fkVarName}, Description = "${perm.description}", CreatedAt = seedDate },
53223
53238
  `;
53224
53239
  }
53225
53240
  }
@@ -53289,13 +53304,13 @@ IMPORTANT: This tool does NOT generate migrations with raw SQL (forbidden by Sma
53289
53304
  Instead, it outputs HasData() code that must be manually added to the Configuration file.
53290
53305
 
53291
53306
  Example:
53292
- navRoute: "platform.administration.entra"
53307
+ navRoute: "administration.entra"
53293
53308
  Outputs HasData() code for:
53294
- - platform.administration.entra.*
53295
- - platform.administration.entra.read
53296
- - platform.administration.entra.create
53297
- - platform.administration.entra.update
53298
- - platform.administration.entra.delete
53309
+ - administration.entra.*
53310
+ - administration.entra.read
53311
+ - administration.entra.create
53312
+ - administration.entra.update
53313
+ - administration.entra.delete
53299
53314
 
53300
53315
  After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <MigrationName>`,
53301
53316
  inputSchema: {
@@ -53303,7 +53318,7 @@ After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <Migra
53303
53318
  properties: {
53304
53319
  navRoute: {
53305
53320
  type: "string",
53306
- description: 'NavRoute path (e.g., "platform.administration.entra"). If not provided, scans all controllers.'
53321
+ description: 'NavRoute path (e.g., "administration.entra"). If not provided, scans all controllers.'
53307
53322
  },
53308
53323
  actions: {
53309
53324
  type: "array",
@@ -53318,7 +53333,7 @@ After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <Migra
53318
53333
  includeWildcard: {
53319
53334
  type: "boolean",
53320
53335
  default: true,
53321
- description: "Include wildcard permission (e.g., personal.myspace.tenants.*)"
53336
+ description: "Include wildcard permission (e.g., myspace.tenants.*)"
53322
53337
  }
53323
53338
  }
53324
53339
  }
@@ -57383,7 +57398,7 @@ Creates:
57383
57398
  - Integration with navRoutes.generated.ts registry
57384
57399
 
57385
57400
  Example:
57386
- scaffold_api_client navRoute="platform.administration.users" name="User"
57401
+ scaffold_api_client navRoute="administration.users" name="User"
57387
57402
 
57388
57403
  The generated client automatically resolves the API path from the NavRoute registry,
57389
57404
  ensuring frontend routes stay synchronized with backend NavRoute attributes.`,
@@ -57396,7 +57411,7 @@ ensuring frontend routes stay synchronized with backend NavRoute attributes.`,
57396
57411
  },
57397
57412
  navRoute: {
57398
57413
  type: "string",
57399
- description: 'NavRoute path (e.g., "platform.administration.users")'
57414
+ description: 'NavRoute path (e.g., "administration.users")'
57400
57415
  },
57401
57416
  name: {
57402
57417
  type: "string",
@@ -57493,9 +57508,9 @@ async function scaffoldRoutes(input, config2) {
57493
57508
  result.instructions.push("**Detect App.tsx pattern first**, then follow the matching instructions:");
57494
57509
  result.instructions.push("");
57495
57510
  const routeTree = buildRouteTree(navRoutes);
57496
- result.instructions.push("### Pattern A: mergeRoutes (if App.tsx uses `contextRoutes: ContextRouteExtensions`)");
57511
+ result.instructions.push("### Pattern A: mergeRoutes (applicationRoutes pattern)");
57497
57512
  result.instructions.push("");
57498
- result.instructions.push("Add routes to `contextRoutes.{context}[]` with **RELATIVE** paths (no leading `/`):");
57513
+ result.instructions.push("Add routes to `applicationRoutes.{application}[]` with **RELATIVE** paths (no leading `/`):");
57499
57514
  result.instructions.push("");
57500
57515
  result.instructions.push("**IMPORTANT:** Pages are lazy-loaded. Use `<Suspense fallback={<PageLoader />}>` wrapper.");
57501
57516
  result.instructions.push("");
@@ -57504,9 +57519,9 @@ async function scaffoldRoutes(input, config2) {
57504
57519
  result.instructions.push("import { PageLoader } from '@/components/ui/PageLoader';");
57505
57520
  result.instructions.push("");
57506
57521
  const importedComponents = /* @__PURE__ */ new Set();
57507
- for (const [_context, applications] of Object.entries(routeTree)) {
57508
- for (const [, modules] of Object.entries(applications)) {
57509
- for (const route of modules) {
57522
+ for (const [_app, modules] of Object.entries(routeTree)) {
57523
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57524
+ for (const route of moduleRoutes) {
57510
57525
  const pageEntry = pageFiles.get(route.navRoute);
57511
57526
  if (pageEntry) {
57512
57527
  for (const entry of pageEntry) {
@@ -57528,11 +57543,11 @@ async function scaffoldRoutes(input, config2) {
57528
57543
  }
57529
57544
  }
57530
57545
  result.instructions.push("");
57531
- result.instructions.push("const contextRoutes: ContextRouteExtensions = {");
57532
- for (const [context, applications] of Object.entries(routeTree)) {
57533
- result.instructions.push(` ${context}: [`);
57534
- for (const [, modules] of Object.entries(applications)) {
57535
- for (const route of modules) {
57546
+ result.instructions.push("const applicationRoutes = {");
57547
+ for (const [app, modules] of Object.entries(routeTree)) {
57548
+ result.instructions.push(` '${app}': [`);
57549
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57550
+ for (const route of moduleRoutes) {
57536
57551
  const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
57537
57552
  const pageEntry = pageFiles.get(route.navRoute);
57538
57553
  const component = pageEntry?.[0]?.componentName || `${route.navRoute.split(".").map(capitalize).join("")}Page`;
@@ -57545,20 +57560,19 @@ async function scaffoldRoutes(input, config2) {
57545
57560
  result.instructions.push("```");
57546
57561
  result.instructions.push("");
57547
57562
  result.instructions.push("Routes are automatically injected into BOTH standard and tenant-prefixed trees by `mergeRoutes()`.");
57548
- result.instructions.push("**DO NOT** add business/platform/personal routes to `clientRoutes[]` \u2014 that array is only for routes outside SmartStack contexts.");
57549
57563
  result.instructions.push("");
57550
- result.instructions.push('### Pattern B: JSX Routes (if App.tsx uses `<Route path="/{context}" element={<{Layout} />}>`)');
57564
+ result.instructions.push('### Pattern B: JSX Routes (if App.tsx uses `<Route path="/{application}" element={<{Layout} />}>`)');
57551
57565
  result.instructions.push("");
57552
57566
  result.instructions.push("Insert `<Route>` children INSIDE the appropriate Layout wrapper.");
57553
57567
  result.instructions.push("**IMPORTANT:** Use `<Suspense fallback={<PageLoader />}>` for lazy-loaded pages.");
57554
57568
  result.instructions.push("");
57555
- for (const [context, applications] of Object.entries(routeTree)) {
57556
- const layoutName = getLayoutName(context);
57557
- result.instructions.push(`#### ${capitalize(context)} context (inside \`<Route path="/${context}" element={<${layoutName} />}>\`):`);
57569
+ for (const [app, modules] of Object.entries(routeTree)) {
57570
+ const layoutName = getLayoutName(app);
57571
+ result.instructions.push(`#### ${capitalize(app)} application (inside \`<Route path="/${app}" element={<${layoutName} />}>\`):`);
57558
57572
  result.instructions.push("");
57559
57573
  result.instructions.push("```tsx");
57560
- for (const [, modules] of Object.entries(applications)) {
57561
- for (const route of modules) {
57574
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57575
+ for (const route of moduleRoutes) {
57562
57576
  const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
57563
57577
  const pageEntry = pageFiles.get(route.navRoute);
57564
57578
  const component = pageEntry?.[0]?.componentName || `${route.navRoute.split(".").map(capitalize).join("")}Page`;
@@ -57580,10 +57594,10 @@ async function scaffoldRoutes(input, config2) {
57580
57594
  result.files.push({ path: routerFile, content: routerContent, type: "created" });
57581
57595
  if (includeLayouts) {
57582
57596
  const layoutsPath = path19.join(webPath, "src", "layouts");
57583
- const contexts = [...new Set(navRoutes.map((r) => r.navRoute.split(".")[0]))];
57584
- for (const context of contexts) {
57585
- const layoutContent = generateLayout(context);
57586
- const layoutFile = path19.join(layoutsPath, `${capitalize(context)}Layout.tsx`);
57597
+ const applications = [...new Set(navRoutes.map((r) => r.navRoute.split(".")[0]))];
57598
+ for (const application of applications) {
57599
+ const layoutContent = generateLayout(application);
57600
+ const layoutFile = path19.join(layoutsPath, `${capitalize(application)}Layout.tsx`);
57587
57601
  if (!dryRun) {
57588
57602
  await ensureDirectory(layoutsPath);
57589
57603
  await writeText(layoutFile, layoutContent);
@@ -57644,8 +57658,8 @@ async function discoverNavRoutes(structure, scope, warnings) {
57644
57658
  if (navRouteMatch) {
57645
57659
  const navRoute = navRouteMatch[1];
57646
57660
  const suffix = navRouteMatch[2];
57647
- const context = navRoute.split(".")[0];
57648
- if (scope !== "all" && context !== scope) {
57661
+ const application = navRoute.split(".")[0];
57662
+ if (scope !== "all" && application !== scope) {
57649
57663
  continue;
57650
57664
  }
57651
57665
  const controllerMatch = path19.basename(file).match(/(.+)Controller\.cs$/);
@@ -57738,28 +57752,28 @@ function generateNavRouteRegistry(routes) {
57738
57752
  lines.push("}");
57739
57753
  lines.push("");
57740
57754
  lines.push("/**");
57741
- lines.push(" * Get all routes for a context");
57755
+ lines.push(" * Get all routes for an application");
57742
57756
  lines.push(" */");
57743
- lines.push("export function getRoutesByContext(context: string): NavRoute[] {");
57744
- lines.push(" return Object.values(ROUTES).filter(r => r.navRoute.startsWith(`${context}.`));");
57757
+ lines.push("export function getRoutesByApplication(application: string): NavRoute[] {");
57758
+ lines.push(" return Object.values(ROUTES).filter(r => r.navRoute.startsWith(`${application}.`));");
57745
57759
  lines.push("}");
57746
57760
  lines.push("");
57747
57761
  lines.push("/**");
57748
57762
  lines.push(" * Get web route with optional tenant slug prefix");
57749
57763
  lines.push(" *");
57750
- lines.push(" * @param navRoute - NavRoute path (e.g., 'platform.administration.users')");
57764
+ lines.push(" * @param navRoute - NavRoute path (e.g., 'administration.users')");
57751
57765
  lines.push(" * @param options - Configuration for URL building");
57752
57766
  lines.push(" * @returns Web route path, optionally prefixed with /t/{slug}");
57753
57767
  lines.push(" *");
57754
57768
  lines.push(" * @example");
57755
57769
  lines.push(" * // Single-tenant mode or no tenant");
57756
- lines.push(" * getWebRoute('platform.administration.users', { isSingleTenant: true })");
57757
- lines.push(" * // Returns: '/platform/administration/users'");
57770
+ lines.push(" * getWebRoute('administration.users', { isSingleTenant: true })");
57771
+ lines.push(" * // Returns: '/administration/users'");
57758
57772
  lines.push(" *");
57759
57773
  lines.push(" * @example");
57760
57774
  lines.push(" * // Multi-tenant mode with slug");
57761
- lines.push(" * getWebRoute('platform.administration.users', { slug: 'acme', isSingleTenant: false })");
57762
- lines.push(" * // Returns: '/t/acme/platform/administration/users'");
57775
+ lines.push(" * getWebRoute('administration.users', { slug: 'acme', isSingleTenant: false })");
57776
+ lines.push(" * // Returns: '/t/acme/administration/users'");
57763
57777
  lines.push(" */");
57764
57778
  lines.push("export function getWebRoute(");
57765
57779
  lines.push(" navRoute: string,");
@@ -57804,9 +57818,9 @@ function generateRouterConfig(routes, includeGuards) {
57804
57818
  if (includeGuards) {
57805
57819
  lines.push("import { ProtectedRoute, PermissionGuard } from './guards';");
57806
57820
  }
57807
- const contexts = Object.keys(routeTree);
57808
- for (const context of contexts) {
57809
- const name = `${capitalize(context)}Layout`;
57821
+ const applications = Object.keys(routeTree);
57822
+ for (const app of applications) {
57823
+ const name = `${capitalize(app)}Layout`;
57810
57824
  lines.push(`const ${name} = lazy(() => import('../layouts/${name}').then(m => ({ default: m.${name} })));`);
57811
57825
  }
57812
57826
  lines.push("");
@@ -57817,37 +57831,32 @@ function generateRouterConfig(routes, includeGuards) {
57817
57831
  }
57818
57832
  lines.push("");
57819
57833
  lines.push("const routes: RouteObject[] = [");
57820
- for (const [context, applications] of Object.entries(routeTree)) {
57834
+ for (const [app, modules] of Object.entries(routeTree)) {
57821
57835
  lines.push(" {");
57822
- lines.push(` path: '${context}',`);
57823
- lines.push(` element: <Suspense fallback={<PageLoader />}><${capitalize(context)}Layout /></Suspense>,`);
57836
+ lines.push(` path: '${app}',`);
57837
+ lines.push(` element: <Suspense fallback={<PageLoader />}><${capitalize(app)}Layout /></Suspense>,`);
57824
57838
  lines.push(" children: [");
57825
- for (const [app, modules] of Object.entries(applications)) {
57826
- lines.push(" {");
57827
- lines.push(` path: '${app}',`);
57828
- lines.push(" children: [");
57829
- for (const route of modules) {
57830
- const modulePath = route.navRoute.split(".").slice(2).map(toKebabCase).join("/");
57839
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57840
+ for (const route of moduleRoutes) {
57841
+ const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
57831
57842
  const pageName = route.navRoute.split(".").map(capitalize).join("");
57832
57843
  if (includeGuards && route.permissions.length > 0) {
57833
- lines.push(" {");
57834
- lines.push(` path: '${modulePath || ""}',`);
57835
- lines.push(` element: (`);
57836
- lines.push(` <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}>`);
57837
- lines.push(` {/* <${pageName}Page /> */}`);
57838
- lines.push(` <div>TODO: ${pageName}Page</div>`);
57839
- lines.push(` </PermissionGuard>`);
57840
- lines.push(` ),`);
57841
- lines.push(" },");
57844
+ lines.push(" {");
57845
+ lines.push(` path: '${modulePath || ""}',`);
57846
+ lines.push(` element: (`);
57847
+ lines.push(` <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}>`);
57848
+ lines.push(` {/* <${pageName}Page /> */}`);
57849
+ lines.push(` <div>TODO: ${pageName}Page</div>`);
57850
+ lines.push(` </PermissionGuard>`);
57851
+ lines.push(` ),`);
57852
+ lines.push(" },");
57842
57853
  } else {
57843
- lines.push(" {");
57844
- lines.push(` path: '${modulePath || ""}',`);
57845
- lines.push(` element: <div>TODO: ${pageName}Page</div>,`);
57846
- lines.push(" },");
57854
+ lines.push(" {");
57855
+ lines.push(` path: '${modulePath || ""}',`);
57856
+ lines.push(` element: <div>TODO: ${pageName}Page</div>,`);
57857
+ lines.push(" },");
57847
57858
  }
57848
57859
  }
57849
- lines.push(" ],");
57850
- lines.push(" },");
57851
57860
  }
57852
57861
  lines.push(" ],");
57853
57862
  lines.push(" },");
@@ -57864,44 +57873,44 @@ function buildRouteTree(routes) {
57864
57873
  const tree = {};
57865
57874
  for (const route of routes) {
57866
57875
  const parts = route.navRoute.split(".");
57867
- const context = parts[0];
57868
- const app = parts[1] || "default";
57869
- if (!tree[context]) {
57870
- tree[context] = {};
57876
+ const app = parts[0];
57877
+ const module = parts[1] || "default";
57878
+ if (!tree[app]) {
57879
+ tree[app] = {};
57871
57880
  }
57872
- if (!tree[context][app]) {
57873
- tree[context][app] = [];
57881
+ if (!tree[app][module]) {
57882
+ tree[app][module] = [];
57874
57883
  }
57875
- tree[context][app].push(route);
57884
+ tree[app][module].push(route);
57876
57885
  }
57877
57886
  return tree;
57878
57887
  }
57879
- function generateLayout(context) {
57880
- const contextCapitalized = capitalize(context);
57888
+ function generateLayout(application) {
57889
+ const appCapitalized = capitalize(application);
57881
57890
  return `/**
57882
- * ${contextCapitalized} Layout
57891
+ * ${appCapitalized} Layout
57883
57892
  *
57884
57893
  * Auto-generated by SmartStack MCP - Customize as needed
57885
57894
  */
57886
57895
 
57887
57896
  import React from 'react';
57888
57897
  import { Outlet, Link, useLocation } from 'react-router-dom';
57889
- import { ROUTES, getRoutesByContext } from '../routes/navRoutes.generated';
57898
+ import { ROUTES, getRoutesByApplication } from '../routes/navRoutes.generated';
57890
57899
 
57891
- export const ${contextCapitalized}Layout: React.FC = () => {
57900
+ export const ${appCapitalized}Layout: React.FC = () => {
57892
57901
  const location = useLocation();
57893
- const contextRoutes = getRoutesByContext('${context}');
57902
+ const appRoutes = getRoutesByApplication('${application}');
57894
57903
 
57895
57904
  return (
57896
57905
  <div className="flex h-screen bg-gray-100">
57897
57906
  {/* Sidebar */}
57898
57907
  <aside className="w-64 bg-white shadow-sm">
57899
57908
  <div className="p-4 border-b">
57900
- <h1 className="text-xl font-semibold text-gray-900">${contextCapitalized}</h1>
57909
+ <h1 className="text-xl font-semibold text-gray-900">${appCapitalized}</h1>
57901
57910
  </div>
57902
57911
  <nav className="p-4">
57903
57912
  <ul className="space-y-2">
57904
- {contextRoutes.map((route) => (
57913
+ {appRoutes.map((route) => (
57905
57914
  <li key={route.navRoute}>
57906
57915
  <Link
57907
57916
  to={route.web}
@@ -57929,7 +57938,7 @@ export const ${contextCapitalized}Layout: React.FC = () => {
57929
57938
  );
57930
57939
  };
57931
57940
 
57932
- export default ${contextCapitalized}Layout;
57941
+ export default ${appCapitalized}Layout;
57933
57942
  `;
57934
57943
  }
57935
57944
  function generateRouteGuards() {
@@ -58011,17 +58020,16 @@ async function discoverPageFiles(webPath, routes) {
58011
58020
  const pageMap = /* @__PURE__ */ new Map();
58012
58021
  for (const route of routes) {
58013
58022
  const parts = route.navRoute.split(".");
58014
- const context = capitalize(parts[0]);
58015
- const app = capitalize(parts[1] || "default");
58016
- const moduleParts = parts.slice(2).map(capitalize);
58023
+ const app = capitalize(parts[0]);
58024
+ const moduleParts = parts.slice(1).map(capitalize);
58017
58025
  const moduleDir = moduleParts.join("/");
58018
- const pagesDir = path19.join(webPath, "src", "pages", context, app, moduleDir || "");
58026
+ const pagesDir = path19.join(webPath, "src", "pages", app, moduleDir || "");
58019
58027
  try {
58020
58028
  const pageFiles = await glob("*Page.tsx", { cwd: pagesDir, absolute: false });
58021
58029
  if (pageFiles.length > 0) {
58022
58030
  const entries = pageFiles.map((f) => {
58023
58031
  const componentName = f.replace(".tsx", "");
58024
- const importPath = `@/pages/${context}/${app}/${moduleDir ? moduleDir + "/" : ""}${componentName}`;
58032
+ const importPath = `@/pages/${app}/${moduleDir ? moduleDir + "/" : ""}${componentName}`;
58025
58033
  return { importPath, componentName };
58026
58034
  });
58027
58035
  pageMap.set(route.navRoute, entries);
@@ -58042,12 +58050,12 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
58042
58050
  ' * Run `scaffold_routes` with outputFormat: "clientRoutes" to regenerate.',
58043
58051
  " *",
58044
58052
  " * These routes must be added INSIDE the appropriate Layout wrapper in App.tsx.",
58045
- " * They are NOT standalone - they are children of the context layout routes.",
58053
+ " * They are NOT standalone - they are children of the application layout routes.",
58046
58054
  " * Routes must be added in BOTH the standard block and the tenant-prefixed block.",
58047
58055
  " */",
58048
58056
  "",
58049
58057
  "import type { RouteObject } from 'react-router-dom';",
58050
- "import type { ContextRouteExtensions } from '@atlashub/smartstack';",
58058
+ "import type { ApplicationRouteExtensions } from '@atlashub/smartstack';",
58051
58059
  "import { lazy, Suspense } from 'react';",
58052
58060
  "import { Navigate } from 'react-router-dom';",
58053
58061
  "import { PageLoader } from '@/components/ui/PageLoader';"
@@ -58078,108 +58086,71 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
58078
58086
  }
58079
58087
  }
58080
58088
  lines.push("");
58081
- for (const [context, applications] of Object.entries(routeTree)) {
58082
- const contextUpper = capitalize(context);
58083
- const layoutName = getLayoutName(context);
58089
+ for (const [app, modules] of Object.entries(routeTree)) {
58090
+ const appUpper = capitalize(app);
58091
+ const layoutName = getLayoutName(app);
58084
58092
  lines.push("/**");
58085
- lines.push(` * Routes for ${contextUpper} context`);
58086
- lines.push(` * Add these as children of <Route path="/${context}" element={<${layoutName} />}>`);
58093
+ lines.push(` * Routes for ${appUpper} application`);
58094
+ lines.push(` * Add these as children of <Route path="/${app}" element={<${layoutName} />}>`);
58087
58095
  lines.push(" */");
58088
- lines.push(`export const ${context}Routes: RouteObject[] = [`);
58089
- for (const [app, modules] of Object.entries(applications)) {
58090
- if (modules.length > 1) {
58091
- lines.push(" {");
58092
- lines.push(` path: '${app}',`);
58093
- lines.push(" children: [");
58094
- const firstModulePath = modules[0].navRoute.split(".").slice(2).map(toKebabCase).join("/");
58095
- lines.push(` { index: true, element: <Navigate to="${firstModulePath}" replace /> },`);
58096
- for (const route of modules) {
58097
- const modulePath = route.navRoute.split(".").slice(2).map(toKebabCase).join("/");
58098
- const pageName = route.navRoute.split(".").map(capitalize).join("") + "Page";
58099
- const pageEntry = pageFiles.get(route.navRoute);
58100
- const component = pageEntry?.[0]?.componentName || pageName;
58101
- const hasRealPage = pageFiles.has(route.navRoute);
58102
- if (includeGuards && route.permissions.length > 0) {
58103
- lines.push(` {`);
58104
- lines.push(` path: '${modulePath}',`);
58105
- if (hasRealPage) {
58106
- lines.push(` element: <Suspense fallback={<PageLoader />}><PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><${component} /></PermissionGuard></Suspense>,`);
58107
- } else {
58108
- lines.push(` element: <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><div>TODO: ${component}</div></PermissionGuard>,`);
58109
- }
58110
- lines.push(` },`);
58111
- } else {
58112
- lines.push(` {`);
58113
- lines.push(` path: '${modulePath}',`);
58114
- lines.push(` element: ${hasRealPage ? `<Suspense fallback={<PageLoader />}><${component} /></Suspense>` : `<div>TODO: ${component}</div>`},`);
58115
- lines.push(` },`);
58116
- }
58117
- }
58118
- lines.push(" ],");
58119
- lines.push(" },");
58120
- } else {
58121
- for (const route of modules) {
58122
- const fullPath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
58123
- const pageName = route.navRoute.split(".").map(capitalize).join("") + "Page";
58124
- const pageEntry = pageFiles.get(route.navRoute);
58125
- const component = pageEntry?.[0]?.componentName || pageName;
58126
- const hasRealPage = pageFiles.has(route.navRoute);
58127
- if (includeGuards && route.permissions.length > 0) {
58128
- lines.push(` {`);
58129
- lines.push(` path: '${fullPath}',`);
58130
- if (hasRealPage) {
58131
- lines.push(` element: <Suspense fallback={<PageLoader />}><PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><${component} /></PermissionGuard></Suspense>,`);
58132
- } else {
58133
- lines.push(` element: <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><div>TODO: ${component}</div></PermissionGuard>,`);
58134
- }
58135
- lines.push(` },`);
58096
+ lines.push(`export const ${app}Routes: RouteObject[] = [`);
58097
+ for (const [, moduleRoutes] of Object.entries(modules)) {
58098
+ for (const route of moduleRoutes) {
58099
+ const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
58100
+ const pageName = route.navRoute.split(".").map(capitalize).join("") + "Page";
58101
+ const pageEntry = pageFiles.get(route.navRoute);
58102
+ const component = pageEntry?.[0]?.componentName || pageName;
58103
+ const hasRealPage = pageFiles.has(route.navRoute);
58104
+ if (includeGuards && route.permissions.length > 0) {
58105
+ lines.push(` {`);
58106
+ lines.push(` path: '${modulePath}',`);
58107
+ if (hasRealPage) {
58108
+ lines.push(` element: <Suspense fallback={<PageLoader />}><PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><${component} /></PermissionGuard></Suspense>,`);
58136
58109
  } else {
58137
- lines.push(` {`);
58138
- lines.push(` path: '${fullPath}',`);
58139
- lines.push(` element: ${hasRealPage ? `<Suspense fallback={<PageLoader />}><${component} /></Suspense>` : `<div>TODO: ${component}</div>`},`);
58140
- lines.push(` },`);
58110
+ lines.push(` element: <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><div>TODO: ${component}</div></PermissionGuard>,`);
58141
58111
  }
58112
+ lines.push(` },`);
58113
+ } else {
58114
+ lines.push(` {`);
58115
+ lines.push(` path: '${modulePath}',`);
58116
+ lines.push(` element: ${hasRealPage ? `<Suspense fallback={<PageLoader />}><${component} /></Suspense>` : `<div>TODO: ${component}</div>`},`);
58117
+ lines.push(` },`);
58142
58118
  }
58143
58119
  }
58144
58120
  }
58145
58121
  lines.push("];");
58146
58122
  lines.push("");
58147
58123
  }
58148
- const contexts = Object.keys(routeTree);
58149
- lines.push("/** All generated routes grouped by context */");
58124
+ const appKeys = Object.keys(routeTree);
58125
+ lines.push("/** All generated routes grouped by application */");
58150
58126
  lines.push("export const generatedRoutes = {");
58151
- for (const context of contexts) {
58152
- lines.push(` ${context}: ${context}Routes,`);
58127
+ for (const app of appKeys) {
58128
+ lines.push(` ${app}: ${app}Routes,`);
58153
58129
  }
58154
58130
  lines.push("};");
58155
58131
  lines.push("");
58156
58132
  lines.push("/**");
58157
- lines.push(" * Context route extensions for mergeRoutes() pattern.");
58158
- lines.push(" * Import and spread into your App.tsx contextRoutes:");
58133
+ lines.push(" * Application route extensions for mergeRoutes() pattern.");
58134
+ lines.push(" * Import and spread into your App.tsx applicationRoutes:");
58159
58135
  lines.push(" *");
58160
58136
  lines.push(" * ```tsx");
58161
- lines.push(" * import { contextRouteExtensions } from './routes/clientRoutes.generated';");
58162
- lines.push(" * const contextRoutes: ContextRouteExtensions = {");
58163
- lines.push(" * ...contextRouteExtensions,");
58137
+ lines.push(" * import { applicationRouteExtensions } from './routes/clientRoutes.generated';");
58138
+ lines.push(" * const applicationRoutes = {");
58139
+ lines.push(" * ...applicationRouteExtensions,");
58164
58140
  lines.push(" * // your additional routes...");
58165
58141
  lines.push(" * };");
58166
58142
  lines.push(" * ```");
58167
58143
  lines.push(" */");
58168
- lines.push("export const contextRouteExtensions: ContextRouteExtensions = {");
58169
- for (const context of contexts) {
58170
- lines.push(` ${context}: ${context}Routes,`);
58144
+ lines.push("export const applicationRouteExtensions: Record<string, RouteObject[]> = {");
58145
+ for (const app of appKeys) {
58146
+ lines.push(` ${app}: ${app}Routes,`);
58171
58147
  }
58172
58148
  lines.push("};");
58173
58149
  lines.push("");
58174
58150
  return lines.join("\n");
58175
58151
  }
58176
- function getLayoutName(context) {
58177
- const layoutMap = {
58178
- platform: "AdminLayout",
58179
- business: "BusinessLayout",
58180
- personal: "UserLayout"
58181
- };
58182
- return layoutMap[context] || `${capitalize(context)}Layout`;
58152
+ function getLayoutName(_application) {
58153
+ return "AppLayout";
58183
58154
  }
58184
58155
  function toKebabCase(segment) {
58185
58156
  return segment.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
@@ -58243,7 +58214,7 @@ Creates:
58243
58214
  Example:
58244
58215
  scaffold_routes source="controllers" scope="all"
58245
58216
 
58246
- Scans backend controllers for [NavRoute("context.application.module")] attributes
58217
+ Scans backend controllers for [NavRoute("application.module.section")] attributes
58247
58218
  and generates corresponding frontend routing infrastructure.`,
58248
58219
  inputSchema: {
58249
58220
  type: "object",
@@ -58260,9 +58231,8 @@ and generates corresponding frontend routing infrastructure.`,
58260
58231
  },
58261
58232
  scope: {
58262
58233
  type: "string",
58263
- enum: ["all", "platform", "business", "extensions"],
58264
58234
  default: "all",
58265
- description: "Scope of routes to generate"
58235
+ description: 'Scope of routes to generate. Use "all" or a specific application name (e.g., "administration")'
58266
58236
  },
58267
58237
  options: {
58268
58238
  type: "object",
@@ -58715,7 +58685,7 @@ function formatResult6(result, _input) {
58715
58685
  lines.push('scaffold_routes source="controllers"');
58716
58686
  lines.push("");
58717
58687
  lines.push("# Generate API client for a specific NavRoute");
58718
- lines.push('scaffold_api_client navRoute="platform.administration.users" name="User"');
58688
+ lines.push('scaffold_api_client navRoute="administration.users" name="User"');
58719
58689
  lines.push("```");
58720
58690
  return lines.join("\n");
58721
58691
  }
@@ -58974,7 +58944,7 @@ function generateTypesFile() {
58974
58944
  export interface ExtensionConfig {
58975
58945
  /**
58976
58946
  * Page component overrides
58977
- * Key: NavRoute path (e.g., 'platform.administration.users')
58947
+ * Key: NavRoute path (e.g., 'administration.users')
58978
58948
  * Value: React component to render instead of the default page
58979
58949
  */
58980
58950
  pages?: Record<string, ComponentType<PageProps>>;
@@ -59426,28 +59396,28 @@ export function ExtendablePage({ pageKey, defaultComponent: DefaultComponent, pa
59426
59396
  }
59427
59397
 
59428
59398
  export const PAGE_KEYS = {
59429
- USERS_LIST: 'platform.administration.users',
59430
- USERS_DETAIL: 'platform.administration.users.detail',
59431
- ROLES_LIST: 'platform.administration.permissions.roles',
59432
- ROLES_DETAIL: 'platform.administration.permissions.roles.detail',
59433
- PERMISSIONS_LIST: 'platform.administration.permissions.permissions',
59434
- PERMISSIONS_DETAIL: 'platform.administration.permissions.permissions.detail',
59435
- ASSIGNMENTS: 'platform.administration.permissions.assignments',
59436
- AI_DASHBOARD: 'platform.administration.ai.dashboard',
59437
- AI_PROMPTS_LIST: 'platform.administration.ai.prompts',
59438
- AI_PROMPTS_DETAIL: 'platform.administration.ai.prompts.detail',
59439
- WORKFLOWS_LIST: 'platform.administration.workflows.list',
59440
- WORKFLOWS_DETAIL: 'platform.administration.workflows.detail',
59441
- EMAIL_TEMPLATES_LIST: 'platform.administration.workflows.email-templates',
59442
- EMAIL_TEMPLATES_DETAIL: 'platform.administration.workflows.email-templates.detail',
59443
- TICKETS_LIST: 'platform.support.tickets',
59444
- TICKETS_DETAIL: 'platform.support.tickets.detail',
59445
- SUPPORT_DASHBOARD: 'platform.support.dashboard',
59446
- USER_PROFILE: 'personal.myspace.profile',
59447
- USER_PREFERENCES: 'personal.myspace.preferences',
59448
- USER_DASHBOARD: 'personal.myspace.dashboard',
59449
- MY_TICKETS_LIST: 'business.support-client.my-tickets',
59450
- MY_TICKETS_DETAIL: 'business.support-client.my-tickets.detail',
59399
+ USERS_LIST: 'administration.users',
59400
+ USERS_DETAIL: 'administration.users.detail',
59401
+ ROLES_LIST: 'administration.permissions.roles',
59402
+ ROLES_DETAIL: 'administration.permissions.roles.detail',
59403
+ PERMISSIONS_LIST: 'administration.permissions.permissions',
59404
+ PERMISSIONS_DETAIL: 'administration.permissions.permissions.detail',
59405
+ ASSIGNMENTS: 'administration.permissions.assignments',
59406
+ AI_DASHBOARD: 'administration.ai.dashboard',
59407
+ AI_PROMPTS_LIST: 'administration.ai.prompts',
59408
+ AI_PROMPTS_DETAIL: 'administration.ai.prompts.detail',
59409
+ WORKFLOWS_LIST: 'administration.workflows.list',
59410
+ WORKFLOWS_DETAIL: 'administration.workflows.detail',
59411
+ EMAIL_TEMPLATES_LIST: 'administration.workflows.email-templates',
59412
+ EMAIL_TEMPLATES_DETAIL: 'administration.workflows.email-templates.detail',
59413
+ TICKETS_LIST: 'support.tickets',
59414
+ TICKETS_DETAIL: 'support.tickets.detail',
59415
+ SUPPORT_DASHBOARD: 'support.dashboard',
59416
+ USER_PROFILE: 'myspace.profile',
59417
+ USER_PREFERENCES: 'myspace.preferences',
59418
+ USER_DASHBOARD: 'myspace.dashboard',
59419
+ MY_TICKETS_LIST: 'support-client.my-tickets',
59420
+ MY_TICKETS_DETAIL: 'support-client.my-tickets.detail',
59451
59421
  } as const;
59452
59422
 
59453
59423
  export type PageKey = typeof PAGE_KEYS[keyof typeof PAGE_KEYS];
@@ -60857,7 +60827,7 @@ async function checkAuthorization(structure, result) {
60857
60827
  message: `Controller ${controllerName} missing authorization attribute`,
60858
60828
  file: path23.relative(structure.root, file),
60859
60829
  line: lineNumber,
60860
- suggestion: 'Add [NavRoute("context.application.module")] or [Authorize] attribute to the controller class',
60830
+ suggestion: 'Add [NavRoute("application.module.section")] or [Authorize] attribute to the controller class',
60861
60831
  cweId: "CWE-862"
60862
60832
  });
60863
60833
  }
@@ -64764,7 +64734,7 @@ Tables are organized by domain using prefixes:
64764
64734
  | Prefix | Domain | Example Tables |
64765
64735
  |--------|--------|----------------|
64766
64736
  | \`auth_\` | Authorization | auth_Users, auth_Roles, auth_Permissions |
64767
- | \`nav_\` | Navigation | nav_Contexts, nav_Applications, nav_Modules |
64737
+ | \`nav_\` | Navigation | nav_Applications, nav_Modules, nav_Sections, nav_Resources |
64768
64738
  | \`usr_\` | User profiles | usr_Profiles, usr_Preferences |
64769
64739
  | \`ai_\` | AI features | ai_Providers, ai_Models, ai_Prompts |
64770
64740
  | \`cfg_\` | Configuration | cfg_Settings |
@@ -64798,7 +64768,7 @@ In addition to the platform prefixes above, client applications define their own
64798
64768
 
64799
64769
  ### Navigation Scope System
64800
64770
 
64801
- All navigation data (Context, Application, Module, Section) uses a **Scope** field to distinguish system data from client extensions:
64771
+ All navigation data (Application, Module, Section, Resource) uses a **Scope** field to distinguish system data from client extensions:
64802
64772
 
64803
64773
  | Scope | Usage | Description | Example Code |
64804
64774
  |-------|-------|-------------|--------------|
@@ -64810,17 +64780,17 @@ All navigation data (Context, Application, Module, Section) uses a **Scope** fie
64810
64780
  **Navigation Hierarchy (4 levels):**
64811
64781
 
64812
64782
  \`\`\`
64813
- Context \u2192 Application \u2192 Module \u2192 Section
64783
+ Application \u2192 Module \u2192 Section \u2192 Resource (optional)
64814
64784
  \`\`\`
64815
64785
 
64816
64786
  **Examples for each level:**
64817
64787
 
64818
64788
  | Level | Core Example | Extension Example |
64819
64789
  |-------|--------------|-------------------|
64820
- | Context | Code: \`platform\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`business\`<br/>Scope: \`${scopeTypes[1]}\` |
64821
64790
  | Application | Code: \`administration\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`custom_app\`<br/>Scope: \`${scopeTypes[1]}\` |
64822
- | Module | Code: \`users\`<br/>Route: \`platform.administration.users\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`inventory\`<br/>Route: \`business.operations.inventory\`<br/>Scope: \`${scopeTypes[1]}\` |
64791
+ | Module | Code: \`users\`<br/>Route: \`administration.users.management\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`inventory\`<br/>Route: \`operations.inventory.list\`<br/>Scope: \`${scopeTypes[1]}\` |
64823
64792
  | Section | Code: \`management\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`reports\`<br/>Scope: \`${scopeTypes[1]}\` |
64793
+ | Resource (optional) | Code: \`dashboard\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`analytics\`<br/>Scope: \`${scopeTypes[1]}\` |
64824
64794
 
64825
64795
  **Rules:**
64826
64796
  1. \`${scopeTypes[0]}\` modules are **protected** - clients cannot create or modify them
@@ -64844,18 +64814,18 @@ Permissions and Roles also use the **Scope** field for the same categorization:
64844
64814
  Permissions inherit their Scope from the module's NavRoute:
64845
64815
 
64846
64816
  \`\`\`
64847
- NavRoute: "platform.administration.users"
64817
+ NavRoute: "administration.users"
64848
64818
  Module Scope: Core
64849
64819
  \u2192 Permissions Scope: Core
64850
- - platform.administration.users.read (Core)
64851
- - platform.administration.users.create (Core)
64852
- - platform.administration.users.update (Core)
64853
- - platform.administration.users.delete (Core)
64820
+ - administration.users.read (Core)
64821
+ - administration.users.create (Core)
64822
+ - administration.users.update (Core)
64823
+ - administration.users.delete (Core)
64854
64824
  \`\`\`
64855
64825
 
64856
64826
  **Detection Rules:**
64857
- - Routes starting with \`platform.*\` or \`business.*\` (system contexts) \u2192 \`${scopeTypes[0]}\`
64858
- - Routes from Extension contexts \u2192 \`${scopeTypes[1]}\`
64827
+ - Routes for platform applications (administration, support, etc.) \u2192 \`${scopeTypes[0]}\`
64828
+ - Routes for client/custom applications \u2192 \`${scopeTypes[1]}\`
64859
64829
  - Partner-provided routes \u2192 \`${scopeTypes[2]}\`
64860
64830
  - Community routes \u2192 \`${scopeTypes[3]}\`
64861
64831
 
@@ -65638,7 +65608,7 @@ All tenant-related tables use the \`tenant_\` prefix:
65638
65608
 
65639
65609
  ### Layout Standards
65640
65610
 
65641
- All context layouts MUST follow the AdminLayout pattern for consistent user experience.
65611
+ All applications use the unified AppLayout for consistent user experience.
65642
65612
 
65643
65613
  #### Standard Structure
65644
65614
 
@@ -65760,8 +65730,8 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65760
65730
  // In your page component
65761
65731
  <Breadcrumb
65762
65732
  items={[
65763
- { label: t('nav.administration'), href: '/platform/administration' },
65764
- { label: t('nav.users'), href: '/platform/administration/users' },
65733
+ { label: t('nav.administration'), href: '/administration' },
65734
+ { label: t('nav.users'), href: '/administration/users' },
65765
65735
  { label: user.fullName } // Last item = current page (no href)
65766
65736
  ]}
65767
65737
  />
@@ -65771,7 +65741,7 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65771
65741
 
65772
65742
  | Rule | Description |
65773
65743
  |------|-------------|
65774
- | First item | Context/Application level with Home icon (auto-added if no icon) |
65744
+ | First item | Application level with Home icon (auto-added if no icon) |
65775
65745
  | Intermediate items | Clickable links to parent pages |
65776
65746
  | Last item | Current page name, no href, bold text |
65777
65747
  | Labels | Use i18n translation keys from \`navigation.json\` |
@@ -65780,7 +65750,7 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65780
65750
  #### Hierarchy Pattern
65781
65751
 
65782
65752
  \`\`\`
65783
- Context > Application > Module > [Section] > [Entity Name]
65753
+ Application > Module > [Section] > [Resource] > [Entity Name]
65784
65754
  \`\`\`
65785
65755
 
65786
65756
  **Examples:**