@atlashub/smartstack-cli 3.36.0 → 3.38.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 (219) hide show
  1. package/dist/index.js +16 -24
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +201 -256
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +3 -2
  6. package/scripts/extract-api-endpoints.ts +325 -0
  7. package/scripts/extract-business-rules.ts +440 -0
  8. package/scripts/generate-doc-with-mock-ui.ts +804 -0
  9. package/scripts/health-check.sh +168 -0
  10. package/scripts/postinstall.js +18 -0
  11. package/templates/agents/ba-reader.md +9 -9
  12. package/templates/agents/ba-writer.md +12 -15
  13. package/templates/agents/code-reviewer.md +1 -1
  14. package/templates/agents/docs-context-reader.md +1 -1
  15. package/templates/agents/gitflow/merge.md +0 -4
  16. package/templates/agents/gitflow/pr.md +0 -4
  17. package/templates/agents/gitflow/start.md +30 -5
  18. package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +20 -20
  19. package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +16 -24
  20. package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +2 -2
  21. package/templates/skills/_resources/mcp-validate-documentation-spec.md +3 -3
  22. package/templates/skills/_shared.md +15 -17
  23. package/templates/skills/ai-prompt/SKILL.md +1 -1
  24. package/templates/skills/ai-prompt/steps/step-00-init.md +47 -0
  25. package/templates/skills/apex/SKILL.md +3 -4
  26. package/templates/skills/apex/_shared.md +10 -20
  27. package/templates/skills/apex/references/analysis-methods.md +141 -0
  28. package/templates/skills/apex/references/challenge-questions.md +1 -21
  29. package/templates/skills/apex/references/core-seed-data.md +35 -57
  30. package/templates/skills/apex/references/examine-build-validation.md +87 -0
  31. package/templates/skills/apex/references/execution-frontend-gates.md +177 -0
  32. package/templates/skills/apex/references/execution-frontend-patterns.md +105 -0
  33. package/templates/skills/apex/references/execution-layer1-rules.md +96 -0
  34. package/templates/skills/apex/references/initialization-challenge-flow.md +110 -0
  35. package/templates/skills/apex/references/planning-layer-mapping.md +151 -0
  36. package/templates/skills/apex/references/post-checks.md +145 -40
  37. package/templates/skills/apex/references/smartstack-api.md +35 -51
  38. package/templates/skills/apex/references/smartstack-frontend.md +17 -17
  39. package/templates/skills/apex/references/smartstack-layers.md +38 -62
  40. package/templates/skills/apex/steps/step-00-init.md +14 -26
  41. package/templates/skills/apex/steps/step-01-analyze.md +10 -143
  42. package/templates/skills/apex/steps/step-02-plan.md +10 -92
  43. package/templates/skills/apex/steps/step-03-execute.md +47 -249
  44. package/templates/skills/apex/steps/step-04-examine.md +14 -78
  45. package/templates/skills/apex/steps/step-05-deep-review.md +2 -2
  46. package/templates/skills/apex/steps/step-08-run-tests.md +2 -0
  47. package/templates/skills/application/SKILL.md +6 -7
  48. package/templates/skills/application/references/backend-controller-hierarchy.md +16 -16
  49. package/templates/skills/application/references/backend-seeding-and-dto-output.md +83 -0
  50. package/templates/skills/application/references/backend-table-prefix-mapping.md +79 -0
  51. package/templates/skills/application/references/backend-verification.md +1 -1
  52. package/templates/skills/application/references/frontend-i18n-and-output.md +67 -0
  53. package/templates/skills/application/references/frontend-route-naming.md +117 -0
  54. package/templates/skills/application/references/frontend-route-wiring-app-tsx.md +107 -0
  55. package/templates/skills/application/references/frontend-verification.md +12 -12
  56. package/templates/skills/application/references/init-parameter-detection.md +120 -0
  57. package/templates/skills/application/references/migration-checklist-troubleshooting.md +100 -0
  58. package/templates/skills/application/references/nav-fallback-procedure.md +5 -6
  59. package/templates/skills/application/references/provider-template.md +2 -6
  60. package/templates/skills/application/references/roles-client-project-handling.md +55 -0
  61. package/templates/skills/application/references/roles-fallback-procedure.md +149 -0
  62. package/templates/skills/application/references/test-coverage-requirements.md +213 -0
  63. package/templates/skills/application/references/test-frontend.md +3 -3
  64. package/templates/skills/application/steps/step-00-init.md +11 -141
  65. package/templates/skills/application/steps/step-01-navigation.md +3 -3
  66. package/templates/skills/application/steps/step-02-permissions.md +4 -4
  67. package/templates/skills/application/steps/step-03-roles.md +18 -175
  68. package/templates/skills/application/steps/step-03b-provider.md +1 -2
  69. package/templates/skills/application/steps/step-04-backend.md +19 -110
  70. package/templates/skills/application/steps/step-05-frontend.md +17 -143
  71. package/templates/skills/application/steps/step-06-migration.md +12 -60
  72. package/templates/skills/application/steps/step-07-tests.md +9 -76
  73. package/templates/skills/application/templates-backend.md +29 -27
  74. package/templates/skills/application/templates-frontend.md +48 -48
  75. package/templates/skills/application/templates-seed.md +57 -131
  76. package/templates/skills/business-analyse/SKILL.md +27 -30
  77. package/templates/skills/business-analyse/_architecture.md +6 -6
  78. package/templates/skills/business-analyse/_shared.md +60 -88
  79. package/templates/skills/business-analyse/questionnaire/04-data.md +3 -3
  80. package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
  81. package/templates/skills/business-analyse/questionnaire/13-cross-module.md +1 -1
  82. package/templates/skills/business-analyse/react/application-viewer.md +12 -12
  83. package/templates/skills/business-analyse/react/components.md +8 -12
  84. package/templates/skills/business-analyse/react/schema.md +11 -11
  85. package/templates/skills/business-analyse/references/agent-module-prompt.md +2 -3
  86. package/templates/skills/business-analyse/references/analysis-semantic-checks.md +190 -0
  87. package/templates/skills/business-analyse/references/cache-warming-strategy.md +2 -2
  88. package/templates/skills/business-analyse/references/cadrage-challenge-patterns.md +41 -0
  89. package/templates/skills/business-analyse/references/cadrage-coverage-matrix.md +74 -0
  90. package/templates/skills/business-analyse/references/cadrage-shared-modules.md +69 -0
  91. package/templates/skills/business-analyse/references/cadrage-structure-cards.md +1 -1
  92. package/templates/skills/business-analyse/references/compilation-structure-cards.md +297 -0
  93. package/templates/skills/business-analyse/references/consolidation-structural-checks.md +2 -2
  94. package/templates/skills/business-analyse/references/deploy-modes.md +5 -5
  95. package/templates/skills/business-analyse/references/detection-strategies.md +7 -7
  96. package/templates/skills/business-analyse/references/handoff-file-templates.md +14 -22
  97. package/templates/skills/business-analyse/references/handoff-mappings.md +4 -4
  98. package/templates/skills/business-analyse/references/handoff-seeddata-generation.md +312 -0
  99. package/templates/skills/business-analyse/references/init-schema-deployment.md +3 -3
  100. package/templates/skills/business-analyse/references/naming-conventions.md +22 -24
  101. package/templates/skills/business-analyse/references/prd-generation.md +2 -2
  102. package/templates/skills/business-analyse/references/review-data-mapping.md +2 -2
  103. package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
  104. package/templates/skills/business-analyse/references/spec-auto-inference.md +3 -3
  105. package/templates/skills/business-analyse/references/team-orchestration.md +49 -6
  106. package/templates/skills/business-analyse/references/ui-dashboard-spec.md +1 -1
  107. package/templates/skills/business-analyse/references/ui-resource-cards.md +18 -18
  108. package/templates/skills/business-analyse/references/validate-incremental-html.md +2 -2
  109. package/templates/skills/business-analyse/references/validation-checklist.md +2 -2
  110. package/templates/skills/business-analyse/schemas/application-schema.json +4 -5
  111. package/templates/skills/business-analyse/schemas/project-schema.json +1 -6
  112. package/templates/skills/business-analyse/schemas/sections/metadata-schema.json +2 -3
  113. package/templates/skills/business-analyse/schemas/sections/specification-schema.json +4 -4
  114. package/templates/skills/business-analyse/steps/step-00-init.md +8 -17
  115. package/templates/skills/business-analyse/steps/step-01-cadrage.md +35 -198
  116. package/templates/skills/business-analyse/steps/step-01b-applications.md +16 -20
  117. package/templates/skills/business-analyse/steps/step-02-decomposition.md +1 -1
  118. package/templates/skills/business-analyse/steps/step-03a1-setup.md +4 -4
  119. package/templates/skills/business-analyse/steps/step-03a2-analysis.md +1 -1
  120. package/templates/skills/business-analyse/steps/step-03b-ui.md +4 -4
  121. package/templates/skills/business-analyse/steps/step-03c-compile.md +66 -140
  122. package/templates/skills/business-analyse/steps/step-03d-validate.md +2 -2
  123. package/templates/skills/business-analyse/steps/step-04a-collect.md +2 -2
  124. package/templates/skills/business-analyse/steps/step-04b-analyze.md +42 -160
  125. package/templates/skills/business-analyse/steps/step-04c-decide.md +1 -1
  126. package/templates/skills/business-analyse/steps/step-05a-handoff.md +74 -104
  127. package/templates/skills/business-analyse/steps/step-05b-deploy.md +13 -11
  128. package/templates/skills/business-analyse/steps/step-06-review.md +3 -3
  129. package/templates/skills/business-analyse/templates/tpl-frd.md +13 -13
  130. package/templates/skills/business-analyse/templates/tpl-handoff.md +12 -12
  131. package/templates/skills/business-analyse/templates-frd.md +25 -25
  132. package/templates/skills/business-analyse/templates-react.md +15 -21
  133. package/templates/skills/controller/SKILL.md +1 -1
  134. package/templates/skills/controller/postman-templates.md +1 -1
  135. package/templates/skills/controller/references/controller-code-templates.md +2 -2
  136. package/templates/skills/controller/references/mcp-scaffold-workflow.md +209 -0
  137. package/templates/skills/controller/references/permission-sync-templates.md +13 -16
  138. package/templates/skills/controller/steps/step-00-init.md +11 -11
  139. package/templates/skills/controller/steps/step-03-generate.md +64 -103
  140. package/templates/skills/controller/templates.md +67 -71
  141. package/templates/skills/debug/SKILL.md +13 -218
  142. package/templates/skills/debug/steps/step-00-init.md +57 -0
  143. package/templates/skills/debug/steps/step-01-analyze.md +219 -0
  144. package/templates/skills/debug/steps/step-02-resolve.md +85 -0
  145. package/templates/skills/documentation/SKILL.md +49 -345
  146. package/templates/skills/documentation/data-schema.md +11 -8
  147. package/templates/skills/documentation/steps/step-00-init.md +70 -0
  148. package/templates/skills/documentation/steps/step-01-scan.md +113 -0
  149. package/templates/skills/documentation/steps/step-02-generate.md +231 -0
  150. package/templates/skills/documentation/steps/step-03-validate.md +238 -0
  151. package/templates/skills/documentation/templates.md +480 -322
  152. package/templates/skills/efcore/references/both-contexts.md +32 -0
  153. package/templates/skills/efcore/references/database-operations.md +67 -0
  154. package/templates/skills/efcore/references/destructive-operations.md +38 -0
  155. package/templates/skills/efcore/references/reset-operations.md +81 -0
  156. package/templates/skills/efcore/references/seed-methods.md +86 -0
  157. package/templates/skills/efcore/references/shared-init-functions.md +250 -0
  158. package/templates/skills/efcore/references/sql-objects-injection.md +61 -0
  159. package/templates/skills/efcore/references/troubleshooting.md +81 -0
  160. package/templates/skills/efcore/steps/db/step-deploy.md +1 -32
  161. package/templates/skills/efcore/steps/db/step-reset.md +7 -103
  162. package/templates/skills/efcore/steps/db/step-seed.md +10 -132
  163. package/templates/skills/efcore/steps/db/step-status.md +5 -44
  164. package/templates/skills/efcore/steps/migration/step-03-validate.md +8 -62
  165. package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +1 -57
  166. package/templates/skills/efcore/steps/shared/step-00-init.md +11 -254
  167. package/templates/skills/efcore/steps/squash/step-03-create.md +1 -58
  168. package/templates/skills/feature-full/SKILL.md +1 -1
  169. package/templates/skills/feature-full/steps/step-00-init.md +57 -0
  170. package/templates/skills/feature-full/steps/step-01-implementation.md +1 -1
  171. package/templates/skills/gitflow/SKILL.md +1 -1
  172. package/templates/skills/gitflow/_shared.md +23 -0
  173. package/templates/skills/gitflow/references/commit-message-generation.md +58 -0
  174. package/templates/skills/gitflow/references/commit-migration-validation.md +49 -0
  175. package/templates/skills/gitflow/references/finish-cleanup.md +51 -0
  176. package/templates/skills/gitflow/references/finish-version-bumping.md +45 -0
  177. package/templates/skills/gitflow/references/init-environment-detection.md +41 -0
  178. package/templates/skills/gitflow/references/init-questions.md +185 -0
  179. package/templates/skills/gitflow/references/init-structure-creation.md +71 -0
  180. package/templates/skills/gitflow/references/init-version-detection.md +21 -0
  181. package/templates/skills/gitflow/references/init-workspace-detection.md +43 -0
  182. package/templates/skills/gitflow/references/merge-ci-status.md +36 -0
  183. package/templates/skills/gitflow/references/merge-execution.md +62 -0
  184. package/templates/skills/gitflow/references/merge-pr-context.md +76 -0
  185. package/templates/skills/gitflow/references/pr-build-checks.md +60 -0
  186. package/templates/skills/gitflow/references/pr-generation.md +58 -0
  187. package/templates/skills/gitflow/references/start-branch-normalization.md +28 -0
  188. package/templates/skills/gitflow/references/start-worktree-creation.md +50 -0
  189. package/templates/skills/gitflow/references/sync-push-verify.md +44 -0
  190. package/templates/skills/gitflow/references/sync-rebase-conflicts.md +38 -0
  191. package/templates/skills/gitflow/steps/step-commit.md +12 -91
  192. package/templates/skills/gitflow/steps/step-finish.md +15 -159
  193. package/templates/skills/gitflow/steps/step-init.md +24 -326
  194. package/templates/skills/gitflow/steps/step-merge.md +17 -176
  195. package/templates/skills/gitflow/steps/step-pr.md +10 -116
  196. package/templates/skills/gitflow/steps/step-start.md +16 -109
  197. package/templates/skills/gitflow/steps/step-sync.md +6 -69
  198. package/templates/skills/ralph-loop/SKILL.md +6 -0
  199. package/templates/skills/ralph-loop/references/category-completeness.md +185 -0
  200. package/templates/skills/ralph-loop/references/compact-loop.md +1 -1
  201. package/templates/skills/ralph-loop/references/init-resume-recovery.md +127 -0
  202. package/templates/skills/ralph-loop/references/module-transition.md +151 -0
  203. package/templates/skills/ralph-loop/references/multi-module-queue.md +171 -0
  204. package/templates/skills/ralph-loop/references/parallel-execution.md +246 -0
  205. package/templates/skills/ralph-loop/references/task-transform-legacy.md +6 -9
  206. package/templates/skills/ralph-loop/references/team-orchestration.md +45 -3
  207. package/templates/skills/ralph-loop/steps/step-00-init.md +36 -109
  208. package/templates/skills/ralph-loop/steps/step-01-task.md +15 -163
  209. package/templates/skills/ralph-loop/steps/step-02-execute.md +8 -154
  210. package/templates/skills/ralph-loop/steps/step-04-check.md +21 -73
  211. package/templates/skills/review-code/references/owasp-api-top10.md +5 -5
  212. package/templates/skills/review-code/references/smartstack-conventions.md +11 -11
  213. package/templates/skills/validate-feature/references/api-smoke-tests.md +140 -0
  214. package/templates/skills/validate-feature/references/db-validation-checks.md +180 -0
  215. package/templates/skills/validate-feature/steps/step-01-compile.md +5 -2
  216. package/templates/skills/validate-feature/steps/step-04-api-smoke.md +34 -145
  217. package/templates/skills/validate-feature/steps/step-05-db-validation.md +74 -260
  218. package/templates/skills/workflow/SKILL.md +1 -1
  219. 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"),
@@ -27191,7 +27191,7 @@ async function validateControllerRoutes(structure, _config, result) {
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 should have at least 2 levels: "application.module" (e.g., "administration.users")'
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")] 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,21 @@ 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: "", 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]) : "";
34442
34432
  let domainPath = "";
34443
- if (segments.length >= 3) {
34444
- domainPath = path10.join(context, application, module);
34445
- } else if (segments.length === 2) {
34446
- domainPath = path10.join(context, module);
34433
+ if (segments.length >= 2) {
34434
+ domainPath = path10.join(application, module);
34447
34435
  } else if (segments.length === 1) {
34448
- domainPath = context;
34436
+ domainPath = application;
34449
34437
  }
34450
34438
  const infraPath = domainPath;
34451
- const controllerArea = context;
34452
- return { context, application, module, domainPath, infraPath, controllerArea };
34439
+ const controllerArea = application;
34440
+ return { application, module, domainPath, infraPath, controllerArea };
34453
34441
  }
34454
34442
  async function handleScaffoldExtension(args, config2) {
34455
34443
  const input = ScaffoldExtensionInputSchema.parse(args);
@@ -34596,7 +34584,7 @@ async function scaffoldFeature(name, options, structure, config2, result, dryRun
34596
34584
  result.instructions.push(`${withRepository ? withValidation ? "6" : "5" : withValidation ? "5" : "4"}. Run migration: \`dotnet ef database update --context ${dbContextName}\``);
34597
34585
  if (!skipComponent) {
34598
34586
  const featureHierarchy = resolveHierarchy(options?.navRoute);
34599
- const featureComponentPath = featureHierarchy.context && featureHierarchy.module ? `@/components/${featureHierarchy.context.toLowerCase()}/${featureHierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
34587
+ const featureComponentPath = featureHierarchy.application && featureHierarchy.module ? `@/components/${featureHierarchy.application.toLowerCase()}/${featureHierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
34600
34588
  result.instructions.push(`Import component: \`import { ${name} } from '${featureComponentPath}';\``);
34601
34589
  }
34602
34590
  }
@@ -35413,12 +35401,12 @@ public class {{name}}Controller : ControllerBase
35413
35401
  result.instructions.push("");
35414
35402
  result.instructions.push("NavRoute resolves API routes from Navigation entities in the database.");
35415
35403
  result.instructions.push("Ensure the navigation path exists (seed data required):");
35416
- result.instructions.push(` Context > Application > Module matching "${navRoute}"`);
35404
+ result.instructions.push(` Application > Module matching "${navRoute}"`);
35417
35405
  } else {
35418
35406
  result.instructions.push("Controller created with traditional routing.");
35419
35407
  result.instructions.push("");
35420
35408
  result.instructions.push("\u26A0\uFE0F Consider using NavRoute for navigation-based routing:");
35421
- result.instructions.push(` [NavRoute("context.application.module")]`);
35409
+ result.instructions.push(` [NavRoute("application.module")]`);
35422
35410
  result.instructions.push("");
35423
35411
  result.instructions.push("API endpoints (with traditional routing):");
35424
35412
  result.instructions.push(` GET /api/${name.toLowerCase()}`);
@@ -35583,7 +35571,7 @@ export function use{{name}}(options: Use{{name}}Options = {}) {
35583
35571
  const projectRoot = config2.smartstack.projectPath;
35584
35572
  const webPath = structure.web || path10.join(projectRoot, "web");
35585
35573
  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;
35574
+ const componentsPath = options?.outputPath ? options.outputPath : hierarchy.application && hierarchy.module ? path10.join(componentsBase, hierarchy.application.toLowerCase(), hierarchy.module.toLowerCase()) : componentsBase;
35587
35575
  const hooksPath = path10.join(webPath, "src", "hooks");
35588
35576
  const componentFilePath = path10.join(componentsPath, `${name}.tsx`);
35589
35577
  const hookFilePath = path10.join(hooksPath, `use${name}.ts`);
@@ -35598,7 +35586,7 @@ export function use{{name}}(options: Use{{name}}Options = {}) {
35598
35586
  result.files.push({ path: componentFilePath, content: componentContent, type: "created" });
35599
35587
  result.files.push({ path: hookFilePath, content: hookContent, type: "created" });
35600
35588
  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}`;
35589
+ const componentImportPath = hierarchy.application && hierarchy.module ? `@/components/${hierarchy.application.toLowerCase()}/${hierarchy.module.toLowerCase()}/${name}` : `./components/${name}`;
35602
35590
  result.instructions.push(`import { ${name} } from '${componentImportPath}';`);
35603
35591
  result.instructions.push(`import { use${name} } from '@/hooks/use${name}';`);
35604
35592
  result.instructions.push("");
@@ -35614,7 +35602,7 @@ export function use{{name}}(options: Use{{name}}Options = {}) {
35614
35602
  result.instructions.push('import { EntityLookup } from "@/components/ui/EntityLookup";');
35615
35603
  result.instructions.push("");
35616
35604
  result.instructions.push("<EntityLookup");
35617
- result.instructions.push(' apiEndpoint="/api/{context}/{app}/{related-entity}"');
35605
+ result.instructions.push(' apiEndpoint="/api/{app}/{related-entity}"');
35618
35606
  result.instructions.push(" value={formData.relatedEntityId}");
35619
35607
  result.instructions.push(' onChange={(id) => handleChange("relatedEntityId", id)}');
35620
35608
  result.instructions.push(' label="Related Entity"');
@@ -36482,7 +36470,7 @@ var init_scaffold_extension = __esm({
36482
36470
  },
36483
36471
  navRoute: {
36484
36472
  type: "string",
36485
- description: 'Navigation route path for controller (e.g., "platform.administration.users"). Required for controllers.'
36473
+ description: 'Navigation route path for controller (e.g., "administration.users"). Required for controllers.'
36486
36474
  },
36487
36475
  navRouteSuffix: {
36488
36476
  type: "string",
@@ -53028,16 +53016,16 @@ async function handleGeneratePermissions(args, config2) {
53028
53016
  function generatePermissionsForNavRoute(navRoute, customActions, includeStandardActions, includeWildcard = true) {
53029
53017
  const permissions = [];
53030
53018
  const parts = navRoute.split(".");
53031
- const context = parts[0];
53032
- if (parts.length < 3) {
53033
- throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: context.application.module`);
53019
+ const application = parts[0];
53020
+ if (parts.length < 2) {
53021
+ throw new Error(`Invalid NavRoute format: ${navRoute}. Expected format: application.module`);
53034
53022
  }
53035
53023
  if (includeWildcard) {
53036
53024
  permissions.push({
53037
53025
  code: `${navRoute}.*`,
53038
53026
  name: formatPermissionName(navRoute, "Full Access"),
53039
53027
  description: `Full ${parts[parts.length - 1]} management`,
53040
- category: context
53028
+ category: application
53041
53029
  });
53042
53030
  }
53043
53031
  for (const customAction of customActions) {
@@ -53057,7 +53045,7 @@ function generatePermissionsForNavRoute(navRoute, customActions, includeStandard
53057
53045
  code,
53058
53046
  name,
53059
53047
  description,
53060
- category: context
53048
+ category: application
53061
53049
  });
53062
53050
  }
53063
53051
  return permissions;
@@ -53138,14 +53126,12 @@ function formatPermissionName(navRoute, action) {
53138
53126
  }
53139
53127
  function formatPermissionDescription(navRoute, action) {
53140
53128
  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);
53129
+ const application = parts[0];
53130
+ const module = parts[1];
53145
53131
  const applicationName = application.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53146
53132
  const moduleName = module.split(/[-_]/).map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
53147
53133
  const actionVerb = getActionVerb(action);
53148
- return `${actionVerb} ${moduleName} in ${contextName} > ${applicationName}`;
53134
+ return `${actionVerb} ${moduleName} in ${applicationName}`;
53149
53135
  }
53150
53136
  function getActionVerb(action) {
53151
53137
  const verbs = {
@@ -53200,7 +53186,7 @@ function getUniqueNavRouteCount(permissions) {
53200
53186
  }
53201
53187
  function generateHasDataCode(permissions, navRoute) {
53202
53188
  const parts = navRoute.split(".");
53203
- const moduleName = parts.length >= 3 ? parts[parts.length - 1] : "custom";
53189
+ const moduleName = parts.length >= 2 ? parts[parts.length - 1] : "custom";
53204
53190
  const moduleVarName = `${moduleName}ModuleId`;
53205
53191
  let code = "```csharp\n";
53206
53192
  code += `// 1. Add module ID variable (get from NavigationModuleSeedData.cs)
@@ -53289,13 +53275,13 @@ IMPORTANT: This tool does NOT generate migrations with raw SQL (forbidden by Sma
53289
53275
  Instead, it outputs HasData() code that must be manually added to the Configuration file.
53290
53276
 
53291
53277
  Example:
53292
- navRoute: "platform.administration.entra"
53278
+ navRoute: "administration.entra"
53293
53279
  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
53280
+ - administration.entra.*
53281
+ - administration.entra.read
53282
+ - administration.entra.create
53283
+ - administration.entra.update
53284
+ - administration.entra.delete
53299
53285
 
53300
53286
  After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <MigrationName>`,
53301
53287
  inputSchema: {
@@ -53303,7 +53289,7 @@ After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <Migra
53303
53289
  properties: {
53304
53290
  navRoute: {
53305
53291
  type: "string",
53306
- description: 'NavRoute path (e.g., "platform.administration.entra"). If not provided, scans all controllers.'
53292
+ description: 'NavRoute path (e.g., "administration.entra"). If not provided, scans all controllers.'
53307
53293
  },
53308
53294
  actions: {
53309
53295
  type: "array",
@@ -53318,7 +53304,7 @@ After adding to PermissionConfiguration.cs, run: dotnet ef migrations add <Migra
53318
53304
  includeWildcard: {
53319
53305
  type: "boolean",
53320
53306
  default: true,
53321
- description: "Include wildcard permission (e.g., personal.myspace.tenants.*)"
53307
+ description: "Include wildcard permission (e.g., myspace.tenants.*)"
53322
53308
  }
53323
53309
  }
53324
53310
  }
@@ -57383,7 +57369,7 @@ Creates:
57383
57369
  - Integration with navRoutes.generated.ts registry
57384
57370
 
57385
57371
  Example:
57386
- scaffold_api_client navRoute="platform.administration.users" name="User"
57372
+ scaffold_api_client navRoute="administration.users" name="User"
57387
57373
 
57388
57374
  The generated client automatically resolves the API path from the NavRoute registry,
57389
57375
  ensuring frontend routes stay synchronized with backend NavRoute attributes.`,
@@ -57396,7 +57382,7 @@ ensuring frontend routes stay synchronized with backend NavRoute attributes.`,
57396
57382
  },
57397
57383
  navRoute: {
57398
57384
  type: "string",
57399
- description: 'NavRoute path (e.g., "platform.administration.users")'
57385
+ description: 'NavRoute path (e.g., "administration.users")'
57400
57386
  },
57401
57387
  name: {
57402
57388
  type: "string",
@@ -57493,9 +57479,9 @@ async function scaffoldRoutes(input, config2) {
57493
57479
  result.instructions.push("**Detect App.tsx pattern first**, then follow the matching instructions:");
57494
57480
  result.instructions.push("");
57495
57481
  const routeTree = buildRouteTree(navRoutes);
57496
- result.instructions.push("### Pattern A: mergeRoutes (if App.tsx uses `contextRoutes: ContextRouteExtensions`)");
57482
+ result.instructions.push("### Pattern A: mergeRoutes (applicationRoutes pattern)");
57497
57483
  result.instructions.push("");
57498
- result.instructions.push("Add routes to `contextRoutes.{context}[]` with **RELATIVE** paths (no leading `/`):");
57484
+ result.instructions.push("Add routes to `applicationRoutes.{application}[]` with **RELATIVE** paths (no leading `/`):");
57499
57485
  result.instructions.push("");
57500
57486
  result.instructions.push("**IMPORTANT:** Pages are lazy-loaded. Use `<Suspense fallback={<PageLoader />}>` wrapper.");
57501
57487
  result.instructions.push("");
@@ -57504,9 +57490,9 @@ async function scaffoldRoutes(input, config2) {
57504
57490
  result.instructions.push("import { PageLoader } from '@/components/ui/PageLoader';");
57505
57491
  result.instructions.push("");
57506
57492
  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) {
57493
+ for (const [_app, modules] of Object.entries(routeTree)) {
57494
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57495
+ for (const route of moduleRoutes) {
57510
57496
  const pageEntry = pageFiles.get(route.navRoute);
57511
57497
  if (pageEntry) {
57512
57498
  for (const entry of pageEntry) {
@@ -57528,11 +57514,11 @@ async function scaffoldRoutes(input, config2) {
57528
57514
  }
57529
57515
  }
57530
57516
  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) {
57517
+ result.instructions.push("const applicationRoutes = {");
57518
+ for (const [app, modules] of Object.entries(routeTree)) {
57519
+ result.instructions.push(` '${app}': [`);
57520
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57521
+ for (const route of moduleRoutes) {
57536
57522
  const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
57537
57523
  const pageEntry = pageFiles.get(route.navRoute);
57538
57524
  const component = pageEntry?.[0]?.componentName || `${route.navRoute.split(".").map(capitalize).join("")}Page`;
@@ -57545,20 +57531,19 @@ async function scaffoldRoutes(input, config2) {
57545
57531
  result.instructions.push("```");
57546
57532
  result.instructions.push("");
57547
57533
  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
57534
  result.instructions.push("");
57550
- result.instructions.push('### Pattern B: JSX Routes (if App.tsx uses `<Route path="/{context}" element={<{Layout} />}>`)');
57535
+ result.instructions.push('### Pattern B: JSX Routes (if App.tsx uses `<Route path="/{application}" element={<{Layout} />}>`)');
57551
57536
  result.instructions.push("");
57552
57537
  result.instructions.push("Insert `<Route>` children INSIDE the appropriate Layout wrapper.");
57553
57538
  result.instructions.push("**IMPORTANT:** Use `<Suspense fallback={<PageLoader />}>` for lazy-loaded pages.");
57554
57539
  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} />}>\`):`);
57540
+ for (const [app, modules] of Object.entries(routeTree)) {
57541
+ const layoutName = getLayoutName(app);
57542
+ result.instructions.push(`#### ${capitalize(app)} application (inside \`<Route path="/${app}" element={<${layoutName} />}>\`):`);
57558
57543
  result.instructions.push("");
57559
57544
  result.instructions.push("```tsx");
57560
- for (const [, modules] of Object.entries(applications)) {
57561
- for (const route of modules) {
57545
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57546
+ for (const route of moduleRoutes) {
57562
57547
  const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
57563
57548
  const pageEntry = pageFiles.get(route.navRoute);
57564
57549
  const component = pageEntry?.[0]?.componentName || `${route.navRoute.split(".").map(capitalize).join("")}Page`;
@@ -57580,10 +57565,10 @@ async function scaffoldRoutes(input, config2) {
57580
57565
  result.files.push({ path: routerFile, content: routerContent, type: "created" });
57581
57566
  if (includeLayouts) {
57582
57567
  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`);
57568
+ const applications = [...new Set(navRoutes.map((r) => r.navRoute.split(".")[0]))];
57569
+ for (const application of applications) {
57570
+ const layoutContent = generateLayout(application);
57571
+ const layoutFile = path19.join(layoutsPath, `${capitalize(application)}Layout.tsx`);
57587
57572
  if (!dryRun) {
57588
57573
  await ensureDirectory(layoutsPath);
57589
57574
  await writeText(layoutFile, layoutContent);
@@ -57644,8 +57629,8 @@ async function discoverNavRoutes(structure, scope, warnings) {
57644
57629
  if (navRouteMatch) {
57645
57630
  const navRoute = navRouteMatch[1];
57646
57631
  const suffix = navRouteMatch[2];
57647
- const context = navRoute.split(".")[0];
57648
- if (scope !== "all" && context !== scope) {
57632
+ const application = navRoute.split(".")[0];
57633
+ if (scope !== "all" && application !== scope) {
57649
57634
  continue;
57650
57635
  }
57651
57636
  const controllerMatch = path19.basename(file).match(/(.+)Controller\.cs$/);
@@ -57738,28 +57723,28 @@ function generateNavRouteRegistry(routes) {
57738
57723
  lines.push("}");
57739
57724
  lines.push("");
57740
57725
  lines.push("/**");
57741
- lines.push(" * Get all routes for a context");
57726
+ lines.push(" * Get all routes for an application");
57742
57727
  lines.push(" */");
57743
- lines.push("export function getRoutesByContext(context: string): NavRoute[] {");
57744
- lines.push(" return Object.values(ROUTES).filter(r => r.navRoute.startsWith(`${context}.`));");
57728
+ lines.push("export function getRoutesByApplication(application: string): NavRoute[] {");
57729
+ lines.push(" return Object.values(ROUTES).filter(r => r.navRoute.startsWith(`${application}.`));");
57745
57730
  lines.push("}");
57746
57731
  lines.push("");
57747
57732
  lines.push("/**");
57748
57733
  lines.push(" * Get web route with optional tenant slug prefix");
57749
57734
  lines.push(" *");
57750
- lines.push(" * @param navRoute - NavRoute path (e.g., 'platform.administration.users')");
57735
+ lines.push(" * @param navRoute - NavRoute path (e.g., 'administration.users')");
57751
57736
  lines.push(" * @param options - Configuration for URL building");
57752
57737
  lines.push(" * @returns Web route path, optionally prefixed with /t/{slug}");
57753
57738
  lines.push(" *");
57754
57739
  lines.push(" * @example");
57755
57740
  lines.push(" * // Single-tenant mode or no tenant");
57756
- lines.push(" * getWebRoute('platform.administration.users', { isSingleTenant: true })");
57757
- lines.push(" * // Returns: '/platform/administration/users'");
57741
+ lines.push(" * getWebRoute('administration.users', { isSingleTenant: true })");
57742
+ lines.push(" * // Returns: '/administration/users'");
57758
57743
  lines.push(" *");
57759
57744
  lines.push(" * @example");
57760
57745
  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'");
57746
+ lines.push(" * getWebRoute('administration.users', { slug: 'acme', isSingleTenant: false })");
57747
+ lines.push(" * // Returns: '/t/acme/administration/users'");
57763
57748
  lines.push(" */");
57764
57749
  lines.push("export function getWebRoute(");
57765
57750
  lines.push(" navRoute: string,");
@@ -57804,9 +57789,9 @@ function generateRouterConfig(routes, includeGuards) {
57804
57789
  if (includeGuards) {
57805
57790
  lines.push("import { ProtectedRoute, PermissionGuard } from './guards';");
57806
57791
  }
57807
- const contexts = Object.keys(routeTree);
57808
- for (const context of contexts) {
57809
- const name = `${capitalize(context)}Layout`;
57792
+ const applications = Object.keys(routeTree);
57793
+ for (const app of applications) {
57794
+ const name = `${capitalize(app)}Layout`;
57810
57795
  lines.push(`const ${name} = lazy(() => import('../layouts/${name}').then(m => ({ default: m.${name} })));`);
57811
57796
  }
57812
57797
  lines.push("");
@@ -57817,37 +57802,32 @@ function generateRouterConfig(routes, includeGuards) {
57817
57802
  }
57818
57803
  lines.push("");
57819
57804
  lines.push("const routes: RouteObject[] = [");
57820
- for (const [context, applications] of Object.entries(routeTree)) {
57805
+ for (const [app, modules] of Object.entries(routeTree)) {
57821
57806
  lines.push(" {");
57822
- lines.push(` path: '${context}',`);
57823
- lines.push(` element: <Suspense fallback={<PageLoader />}><${capitalize(context)}Layout /></Suspense>,`);
57807
+ lines.push(` path: '${app}',`);
57808
+ lines.push(` element: <Suspense fallback={<PageLoader />}><${capitalize(app)}Layout /></Suspense>,`);
57824
57809
  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("/");
57810
+ for (const [, moduleRoutes] of Object.entries(modules)) {
57811
+ for (const route of moduleRoutes) {
57812
+ const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
57831
57813
  const pageName = route.navRoute.split(".").map(capitalize).join("");
57832
57814
  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(" },");
57815
+ lines.push(" {");
57816
+ lines.push(` path: '${modulePath || ""}',`);
57817
+ lines.push(` element: (`);
57818
+ lines.push(` <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}>`);
57819
+ lines.push(` {/* <${pageName}Page /> */}`);
57820
+ lines.push(` <div>TODO: ${pageName}Page</div>`);
57821
+ lines.push(` </PermissionGuard>`);
57822
+ lines.push(` ),`);
57823
+ lines.push(" },");
57842
57824
  } else {
57843
- lines.push(" {");
57844
- lines.push(` path: '${modulePath || ""}',`);
57845
- lines.push(` element: <div>TODO: ${pageName}Page</div>,`);
57846
- lines.push(" },");
57825
+ lines.push(" {");
57826
+ lines.push(` path: '${modulePath || ""}',`);
57827
+ lines.push(` element: <div>TODO: ${pageName}Page</div>,`);
57828
+ lines.push(" },");
57847
57829
  }
57848
57830
  }
57849
- lines.push(" ],");
57850
- lines.push(" },");
57851
57831
  }
57852
57832
  lines.push(" ],");
57853
57833
  lines.push(" },");
@@ -57864,44 +57844,44 @@ function buildRouteTree(routes) {
57864
57844
  const tree = {};
57865
57845
  for (const route of routes) {
57866
57846
  const parts = route.navRoute.split(".");
57867
- const context = parts[0];
57868
- const app = parts[1] || "default";
57869
- if (!tree[context]) {
57870
- tree[context] = {};
57847
+ const app = parts[0];
57848
+ const module = parts[1] || "default";
57849
+ if (!tree[app]) {
57850
+ tree[app] = {};
57871
57851
  }
57872
- if (!tree[context][app]) {
57873
- tree[context][app] = [];
57852
+ if (!tree[app][module]) {
57853
+ tree[app][module] = [];
57874
57854
  }
57875
- tree[context][app].push(route);
57855
+ tree[app][module].push(route);
57876
57856
  }
57877
57857
  return tree;
57878
57858
  }
57879
- function generateLayout(context) {
57880
- const contextCapitalized = capitalize(context);
57859
+ function generateLayout(application) {
57860
+ const appCapitalized = capitalize(application);
57881
57861
  return `/**
57882
- * ${contextCapitalized} Layout
57862
+ * ${appCapitalized} Layout
57883
57863
  *
57884
57864
  * Auto-generated by SmartStack MCP - Customize as needed
57885
57865
  */
57886
57866
 
57887
57867
  import React from 'react';
57888
57868
  import { Outlet, Link, useLocation } from 'react-router-dom';
57889
- import { ROUTES, getRoutesByContext } from '../routes/navRoutes.generated';
57869
+ import { ROUTES, getRoutesByApplication } from '../routes/navRoutes.generated';
57890
57870
 
57891
- export const ${contextCapitalized}Layout: React.FC = () => {
57871
+ export const ${appCapitalized}Layout: React.FC = () => {
57892
57872
  const location = useLocation();
57893
- const contextRoutes = getRoutesByContext('${context}');
57873
+ const appRoutes = getRoutesByApplication('${application}');
57894
57874
 
57895
57875
  return (
57896
57876
  <div className="flex h-screen bg-gray-100">
57897
57877
  {/* Sidebar */}
57898
57878
  <aside className="w-64 bg-white shadow-sm">
57899
57879
  <div className="p-4 border-b">
57900
- <h1 className="text-xl font-semibold text-gray-900">${contextCapitalized}</h1>
57880
+ <h1 className="text-xl font-semibold text-gray-900">${appCapitalized}</h1>
57901
57881
  </div>
57902
57882
  <nav className="p-4">
57903
57883
  <ul className="space-y-2">
57904
- {contextRoutes.map((route) => (
57884
+ {appRoutes.map((route) => (
57905
57885
  <li key={route.navRoute}>
57906
57886
  <Link
57907
57887
  to={route.web}
@@ -57929,7 +57909,7 @@ export const ${contextCapitalized}Layout: React.FC = () => {
57929
57909
  );
57930
57910
  };
57931
57911
 
57932
- export default ${contextCapitalized}Layout;
57912
+ export default ${appCapitalized}Layout;
57933
57913
  `;
57934
57914
  }
57935
57915
  function generateRouteGuards() {
@@ -58011,17 +57991,16 @@ async function discoverPageFiles(webPath, routes) {
58011
57991
  const pageMap = /* @__PURE__ */ new Map();
58012
57992
  for (const route of routes) {
58013
57993
  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);
57994
+ const app = capitalize(parts[0]);
57995
+ const moduleParts = parts.slice(1).map(capitalize);
58017
57996
  const moduleDir = moduleParts.join("/");
58018
- const pagesDir = path19.join(webPath, "src", "pages", context, app, moduleDir || "");
57997
+ const pagesDir = path19.join(webPath, "src", "pages", app, moduleDir || "");
58019
57998
  try {
58020
57999
  const pageFiles = await glob("*Page.tsx", { cwd: pagesDir, absolute: false });
58021
58000
  if (pageFiles.length > 0) {
58022
58001
  const entries = pageFiles.map((f) => {
58023
58002
  const componentName = f.replace(".tsx", "");
58024
- const importPath = `@/pages/${context}/${app}/${moduleDir ? moduleDir + "/" : ""}${componentName}`;
58003
+ const importPath = `@/pages/${app}/${moduleDir ? moduleDir + "/" : ""}${componentName}`;
58025
58004
  return { importPath, componentName };
58026
58005
  });
58027
58006
  pageMap.set(route.navRoute, entries);
@@ -58042,12 +58021,12 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
58042
58021
  ' * Run `scaffold_routes` with outputFormat: "clientRoutes" to regenerate.',
58043
58022
  " *",
58044
58023
  " * 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.",
58024
+ " * They are NOT standalone - they are children of the application layout routes.",
58046
58025
  " * Routes must be added in BOTH the standard block and the tenant-prefixed block.",
58047
58026
  " */",
58048
58027
  "",
58049
58028
  "import type { RouteObject } from 'react-router-dom';",
58050
- "import type { ContextRouteExtensions } from '@atlashub/smartstack';",
58029
+ "import type { ApplicationRouteExtensions } from '@atlashub/smartstack';",
58051
58030
  "import { lazy, Suspense } from 'react';",
58052
58031
  "import { Navigate } from 'react-router-dom';",
58053
58032
  "import { PageLoader } from '@/components/ui/PageLoader';"
@@ -58078,108 +58057,76 @@ function generateClientRoutesConfig(routes, pageFiles, includeGuards) {
58078
58057
  }
58079
58058
  }
58080
58059
  lines.push("");
58081
- for (const [context, applications] of Object.entries(routeTree)) {
58082
- const contextUpper = capitalize(context);
58083
- const layoutName = getLayoutName(context);
58060
+ for (const [app, modules] of Object.entries(routeTree)) {
58061
+ const appUpper = capitalize(app);
58062
+ const layoutName = getLayoutName(app);
58084
58063
  lines.push("/**");
58085
- lines.push(` * Routes for ${contextUpper} context`);
58086
- lines.push(` * Add these as children of <Route path="/${context}" element={<${layoutName} />}>`);
58064
+ lines.push(` * Routes for ${appUpper} application`);
58065
+ lines.push(` * Add these as children of <Route path="/${app}" element={<${layoutName} />}>`);
58087
58066
  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(` },`);
58067
+ lines.push(`export const ${app}Routes: RouteObject[] = [`);
58068
+ for (const [, moduleRoutes] of Object.entries(modules)) {
58069
+ for (const route of moduleRoutes) {
58070
+ const modulePath = route.navRoute.split(".").slice(1).map(toKebabCase).join("/");
58071
+ const pageName = route.navRoute.split(".").map(capitalize).join("") + "Page";
58072
+ const pageEntry = pageFiles.get(route.navRoute);
58073
+ const component = pageEntry?.[0]?.componentName || pageName;
58074
+ const hasRealPage = pageFiles.has(route.navRoute);
58075
+ if (includeGuards && route.permissions.length > 0) {
58076
+ lines.push(` {`);
58077
+ lines.push(` path: '${modulePath}',`);
58078
+ if (hasRealPage) {
58079
+ lines.push(` element: <Suspense fallback={<PageLoader />}><PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><${component} /></PermissionGuard></Suspense>,`);
58136
58080
  } 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(` },`);
58081
+ lines.push(` element: <PermissionGuard permissions={ROUTES['${route.navRoute}'].permissions}><div>TODO: ${component}</div></PermissionGuard>,`);
58141
58082
  }
58083
+ lines.push(` },`);
58084
+ } else {
58085
+ lines.push(` {`);
58086
+ lines.push(` path: '${modulePath}',`);
58087
+ lines.push(` element: ${hasRealPage ? `<Suspense fallback={<PageLoader />}><${component} /></Suspense>` : `<div>TODO: ${component}</div>`},`);
58088
+ lines.push(` },`);
58142
58089
  }
58143
58090
  }
58144
58091
  }
58145
58092
  lines.push("];");
58146
58093
  lines.push("");
58147
58094
  }
58148
- const contexts = Object.keys(routeTree);
58149
- lines.push("/** All generated routes grouped by context */");
58095
+ const appKeys = Object.keys(routeTree);
58096
+ lines.push("/** All generated routes grouped by application */");
58150
58097
  lines.push("export const generatedRoutes = {");
58151
- for (const context of contexts) {
58152
- lines.push(` ${context}: ${context}Routes,`);
58098
+ for (const app of appKeys) {
58099
+ lines.push(` ${app}: ${app}Routes,`);
58153
58100
  }
58154
58101
  lines.push("};");
58155
58102
  lines.push("");
58156
58103
  lines.push("/**");
58157
- lines.push(" * Context route extensions for mergeRoutes() pattern.");
58158
- lines.push(" * Import and spread into your App.tsx contextRoutes:");
58104
+ lines.push(" * Application route extensions for mergeRoutes() pattern.");
58105
+ lines.push(" * Import and spread into your App.tsx applicationRoutes:");
58159
58106
  lines.push(" *");
58160
58107
  lines.push(" * ```tsx");
58161
- lines.push(" * import { contextRouteExtensions } from './routes/clientRoutes.generated';");
58162
- lines.push(" * const contextRoutes: ContextRouteExtensions = {");
58163
- lines.push(" * ...contextRouteExtensions,");
58108
+ lines.push(" * import { applicationRouteExtensions } from './routes/clientRoutes.generated';");
58109
+ lines.push(" * const applicationRoutes = {");
58110
+ lines.push(" * ...applicationRouteExtensions,");
58164
58111
  lines.push(" * // your additional routes...");
58165
58112
  lines.push(" * };");
58166
58113
  lines.push(" * ```");
58167
58114
  lines.push(" */");
58168
- lines.push("export const contextRouteExtensions: ContextRouteExtensions = {");
58169
- for (const context of contexts) {
58170
- lines.push(` ${context}: ${context}Routes,`);
58115
+ lines.push("export const applicationRouteExtensions: Record<string, RouteObject[]> = {");
58116
+ for (const app of appKeys) {
58117
+ lines.push(` ${app}: ${app}Routes,`);
58171
58118
  }
58172
58119
  lines.push("};");
58173
58120
  lines.push("");
58174
58121
  return lines.join("\n");
58175
58122
  }
58176
- function getLayoutName(context) {
58123
+ function getLayoutName(application) {
58177
58124
  const layoutMap = {
58178
- platform: "AdminLayout",
58179
- business: "BusinessLayout",
58180
- personal: "UserLayout"
58125
+ administration: "AdminLayout",
58126
+ support: "SupportLayout",
58127
+ myspace: "UserLayout"
58181
58128
  };
58182
- return layoutMap[context] || `${capitalize(context)}Layout`;
58129
+ return layoutMap[application] || `${capitalize(application)}Layout`;
58183
58130
  }
58184
58131
  function toKebabCase(segment) {
58185
58132
  return segment.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
@@ -58243,7 +58190,7 @@ Creates:
58243
58190
  Example:
58244
58191
  scaffold_routes source="controllers" scope="all"
58245
58192
 
58246
- Scans backend controllers for [NavRoute("context.application.module")] attributes
58193
+ Scans backend controllers for [NavRoute("application.module")] attributes
58247
58194
  and generates corresponding frontend routing infrastructure.`,
58248
58195
  inputSchema: {
58249
58196
  type: "object",
@@ -58260,9 +58207,8 @@ and generates corresponding frontend routing infrastructure.`,
58260
58207
  },
58261
58208
  scope: {
58262
58209
  type: "string",
58263
- enum: ["all", "platform", "business", "extensions"],
58264
58210
  default: "all",
58265
- description: "Scope of routes to generate"
58211
+ description: 'Scope of routes to generate. Use "all" or a specific application name (e.g., "administration")'
58266
58212
  },
58267
58213
  options: {
58268
58214
  type: "object",
@@ -58715,7 +58661,7 @@ function formatResult6(result, _input) {
58715
58661
  lines.push('scaffold_routes source="controllers"');
58716
58662
  lines.push("");
58717
58663
  lines.push("# Generate API client for a specific NavRoute");
58718
- lines.push('scaffold_api_client navRoute="platform.administration.users" name="User"');
58664
+ lines.push('scaffold_api_client navRoute="administration.users" name="User"');
58719
58665
  lines.push("```");
58720
58666
  return lines.join("\n");
58721
58667
  }
@@ -58974,7 +58920,7 @@ function generateTypesFile() {
58974
58920
  export interface ExtensionConfig {
58975
58921
  /**
58976
58922
  * Page component overrides
58977
- * Key: NavRoute path (e.g., 'platform.administration.users')
58923
+ * Key: NavRoute path (e.g., 'administration.users')
58978
58924
  * Value: React component to render instead of the default page
58979
58925
  */
58980
58926
  pages?: Record<string, ComponentType<PageProps>>;
@@ -59426,28 +59372,28 @@ export function ExtendablePage({ pageKey, defaultComponent: DefaultComponent, pa
59426
59372
  }
59427
59373
 
59428
59374
  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',
59375
+ USERS_LIST: 'administration.users',
59376
+ USERS_DETAIL: 'administration.users.detail',
59377
+ ROLES_LIST: 'administration.permissions.roles',
59378
+ ROLES_DETAIL: 'administration.permissions.roles.detail',
59379
+ PERMISSIONS_LIST: 'administration.permissions.permissions',
59380
+ PERMISSIONS_DETAIL: 'administration.permissions.permissions.detail',
59381
+ ASSIGNMENTS: 'administration.permissions.assignments',
59382
+ AI_DASHBOARD: 'administration.ai.dashboard',
59383
+ AI_PROMPTS_LIST: 'administration.ai.prompts',
59384
+ AI_PROMPTS_DETAIL: 'administration.ai.prompts.detail',
59385
+ WORKFLOWS_LIST: 'administration.workflows.list',
59386
+ WORKFLOWS_DETAIL: 'administration.workflows.detail',
59387
+ EMAIL_TEMPLATES_LIST: 'administration.workflows.email-templates',
59388
+ EMAIL_TEMPLATES_DETAIL: 'administration.workflows.email-templates.detail',
59389
+ TICKETS_LIST: 'support.tickets',
59390
+ TICKETS_DETAIL: 'support.tickets.detail',
59391
+ SUPPORT_DASHBOARD: 'support.dashboard',
59392
+ USER_PROFILE: 'myspace.profile',
59393
+ USER_PREFERENCES: 'myspace.preferences',
59394
+ USER_DASHBOARD: 'myspace.dashboard',
59395
+ MY_TICKETS_LIST: 'support-client.my-tickets',
59396
+ MY_TICKETS_DETAIL: 'support-client.my-tickets.detail',
59451
59397
  } as const;
59452
59398
 
59453
59399
  export type PageKey = typeof PAGE_KEYS[keyof typeof PAGE_KEYS];
@@ -60857,7 +60803,7 @@ async function checkAuthorization(structure, result) {
60857
60803
  message: `Controller ${controllerName} missing authorization attribute`,
60858
60804
  file: path23.relative(structure.root, file),
60859
60805
  line: lineNumber,
60860
- suggestion: 'Add [NavRoute("context.application.module")] or [Authorize] attribute to the controller class',
60806
+ suggestion: 'Add [NavRoute("application.module")] or [Authorize] attribute to the controller class',
60861
60807
  cweId: "CWE-862"
60862
60808
  });
60863
60809
  }
@@ -64764,7 +64710,7 @@ Tables are organized by domain using prefixes:
64764
64710
  | Prefix | Domain | Example Tables |
64765
64711
  |--------|--------|----------------|
64766
64712
  | \`auth_\` | Authorization | auth_Users, auth_Roles, auth_Permissions |
64767
- | \`nav_\` | Navigation | nav_Contexts, nav_Applications, nav_Modules |
64713
+ | \`nav_\` | Navigation | nav_Applications, nav_Modules, nav_Sections |
64768
64714
  | \`usr_\` | User profiles | usr_Profiles, usr_Preferences |
64769
64715
  | \`ai_\` | AI features | ai_Providers, ai_Models, ai_Prompts |
64770
64716
  | \`cfg_\` | Configuration | cfg_Settings |
@@ -64798,7 +64744,7 @@ In addition to the platform prefixes above, client applications define their own
64798
64744
 
64799
64745
  ### Navigation Scope System
64800
64746
 
64801
- All navigation data (Context, Application, Module, Section) uses a **Scope** field to distinguish system data from client extensions:
64747
+ All navigation data (Application, Module, Section) uses a **Scope** field to distinguish system data from client extensions:
64802
64748
 
64803
64749
  | Scope | Usage | Description | Example Code |
64804
64750
  |-------|-------|-------------|--------------|
@@ -64807,19 +64753,18 @@ All navigation data (Context, Application, Module, Section) uses a **Scope** fie
64807
64753
  | \`${scopeTypes[2]}\` | Partner modules | Provided by certified partners | \`partner_integration\` |
64808
64754
  | \`${scopeTypes[3]}\` | Community modules | Open-source community contributions | \`community_tool\` |
64809
64755
 
64810
- **Navigation Hierarchy (4 levels):**
64756
+ **Navigation Hierarchy (3 levels):**
64811
64757
 
64812
64758
  \`\`\`
64813
- Context \u2192 Application \u2192 Module \u2192 Section
64759
+ Application \u2192 Module \u2192 Section
64814
64760
  \`\`\`
64815
64761
 
64816
64762
  **Examples for each level:**
64817
64763
 
64818
64764
  | Level | Core Example | Extension Example |
64819
64765
  |-------|--------------|-------------------|
64820
- | Context | Code: \`platform\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`business\`<br/>Scope: \`${scopeTypes[1]}\` |
64821
64766
  | 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]}\` |
64767
+ | Module | Code: \`users\`<br/>Route: \`administration.users\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`inventory\`<br/>Route: \`operations.inventory\`<br/>Scope: \`${scopeTypes[1]}\` |
64823
64768
  | Section | Code: \`management\`<br/>Scope: \`${scopeTypes[0]}\` | Code: \`reports\`<br/>Scope: \`${scopeTypes[1]}\` |
64824
64769
 
64825
64770
  **Rules:**
@@ -64844,18 +64789,18 @@ Permissions and Roles also use the **Scope** field for the same categorization:
64844
64789
  Permissions inherit their Scope from the module's NavRoute:
64845
64790
 
64846
64791
  \`\`\`
64847
- NavRoute: "platform.administration.users"
64792
+ NavRoute: "administration.users"
64848
64793
  Module Scope: Core
64849
64794
  \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)
64795
+ - administration.users.read (Core)
64796
+ - administration.users.create (Core)
64797
+ - administration.users.update (Core)
64798
+ - administration.users.delete (Core)
64854
64799
  \`\`\`
64855
64800
 
64856
64801
  **Detection Rules:**
64857
- - Routes starting with \`platform.*\` or \`business.*\` (system contexts) \u2192 \`${scopeTypes[0]}\`
64858
- - Routes from Extension contexts \u2192 \`${scopeTypes[1]}\`
64802
+ - Routes for platform applications (administration, support, etc.) \u2192 \`${scopeTypes[0]}\`
64803
+ - Routes for client/custom applications \u2192 \`${scopeTypes[1]}\`
64859
64804
  - Partner-provided routes \u2192 \`${scopeTypes[2]}\`
64860
64805
  - Community routes \u2192 \`${scopeTypes[3]}\`
64861
64806
 
@@ -65638,7 +65583,7 @@ All tenant-related tables use the \`tenant_\` prefix:
65638
65583
 
65639
65584
  ### Layout Standards
65640
65585
 
65641
- All context layouts MUST follow the AdminLayout pattern for consistent user experience.
65586
+ All application layouts MUST follow the AdminLayout pattern for consistent user experience.
65642
65587
 
65643
65588
  #### Standard Structure
65644
65589
 
@@ -65760,8 +65705,8 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65760
65705
  // In your page component
65761
65706
  <Breadcrumb
65762
65707
  items={[
65763
- { label: t('nav.administration'), href: '/platform/administration' },
65764
- { label: t('nav.users'), href: '/platform/administration/users' },
65708
+ { label: t('nav.administration'), href: '/administration' },
65709
+ { label: t('nav.users'), href: '/administration/users' },
65765
65710
  { label: user.fullName } // Last item = current page (no href)
65766
65711
  ]}
65767
65712
  />
@@ -65771,7 +65716,7 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65771
65716
 
65772
65717
  | Rule | Description |
65773
65718
  |------|-------------|
65774
- | First item | Context/Application level with Home icon (auto-added if no icon) |
65719
+ | First item | Application level with Home icon (auto-added if no icon) |
65775
65720
  | Intermediate items | Clickable links to parent pages |
65776
65721
  | Last item | Current page name, no href, bold text |
65777
65722
  | Labels | Use i18n translation keys from \`navigation.json\` |
@@ -65780,7 +65725,7 @@ import { Breadcrumb } from '@/components/ui/Breadcrumb';
65780
65725
  #### Hierarchy Pattern
65781
65726
 
65782
65727
  \`\`\`
65783
- Context > Application > Module > [Section] > [Entity Name]
65728
+ Application > Module > [Section] > [Entity Name]
65784
65729
  \`\`\`
65785
65730
 
65786
65731
  **Examples:**