@atlashub/smartstack-cli 3.25.0 → 3.27.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 (27) hide show
  1. package/dist/index.js +3 -0
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +11 -5
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -2
  6. package/templates/skills/apex/SKILL.md +26 -5
  7. package/templates/skills/apex/_shared.md +3 -3
  8. package/templates/skills/apex/references/agent-teams-protocol.md +8 -8
  9. package/templates/skills/apex/references/challenge-questions.md +165 -0
  10. package/templates/skills/apex/{steps/step-04-validate.md → references/post-checks.md} +82 -214
  11. package/templates/skills/apex/references/smartstack-api.md +91 -14
  12. package/templates/skills/apex/references/smartstack-layers.md +16 -4
  13. package/templates/skills/apex/steps/step-00-init.md +84 -56
  14. package/templates/skills/apex/steps/step-01-analyze.md +73 -87
  15. package/templates/skills/apex/steps/step-03-execute.md +2 -2
  16. package/templates/skills/apex/steps/step-04-examine.md +198 -0
  17. package/templates/skills/apex/steps/{step-05-examine.md → step-05-deep-review.md} +6 -6
  18. package/templates/skills/apex/steps/step-06-resolve.md +2 -2
  19. package/templates/skills/business-analyse/SKILL.md +28 -0
  20. package/templates/skills/business-analyse/references/agent-module-prompt.md +255 -0
  21. package/templates/skills/business-analyse/references/agent-pooling-best-practices.md +26 -10
  22. package/templates/skills/business-analyse/references/team-orchestration.md +437 -0
  23. package/templates/skills/business-analyse/steps/step-02-decomposition.md +31 -4
  24. package/templates/skills/business-analyse/steps/step-03a1-setup.md +21 -0
  25. package/templates/skills/business-analyse/steps/step-03d-validate.md +84 -0
  26. package/templates/skills/ralph-loop/references/core-seed-data.md +45 -10
  27. package/templates/skills/ralph-loop/steps/step-02-execute.md +47 -0
@@ -75,11 +75,20 @@ From `seedDataCore.navigationApplications[0]` in feature.json (generated by BA s
75
75
 
76
76
  ### GUID Generation Rule
77
77
 
78
+ > **CRITICAL — NavigationContext IDs are NEVER generated as deterministic GUIDs.**
79
+ > Contexts (`business`, `platform`, `personal`) are pre-seeded by SmartStack core with hardcoded GUIDs.
80
+ > The `contextId` parameter in `GetApplicationEntry(Guid contextId)` is resolved at runtime
81
+ > by querying `db.NavigationContexts.FirstOrDefaultAsync(c => c.Code == "business", ct)`.
82
+ > **FORBIDDEN:** `GenerateDeterministicGuid("nav:business")` or any ContextId constant in SeedConstants.
83
+
78
84
  ```csharp
79
- // Deterministic GUID from context + application code
85
+ // Deterministic GUID for APPLICATION (not context contexts are pre-seeded by SmartStack core)
80
86
  public static readonly Guid ApplicationId =
81
87
  GenerateDeterministicGuid("navigation-application-{contextCode}.{appCode}");
82
88
  // Example: GenerateDeterministicGuid("navigation-application-business.humanresources")
89
+ //
90
+ // FORBIDDEN — Context IDs must NOT be generated:
91
+ // public static readonly Guid BusinessContextId = GenerateDeterministicGuid("nav:business"); // WRONG!
83
92
  ```
84
93
 
85
94
  ### Template
@@ -723,20 +732,33 @@ If MCP `generate_permissions` fails, use the template above directly with values
723
732
 
724
733
  Creates the 4 standard application-scoped roles: Admin, Manager, Contributor, Viewer.
725
734
 
735
+ > **CRITICAL — SmartStack core MAY already provide system roles (admin, manager, contributor, viewer).**
736
+ > If system roles already exist in `auth_Roles`, do NOT create duplicates.
737
+ > `SeedRolesAsync()` MUST check existence by Code, not just by ApplicationId.
738
+ > **For RolePermission mappings:** ALWAYS look up roles by Code at runtime (in `SeedRolePermissionsAsync()`).
739
+ > **FORBIDDEN:** Using `GenerateRoleGuid()`, `DeterministicGuid("role:admin")`, or any hardcoded role GUID
740
+ > when creating RolePermission entries. The role GUIDs may differ from what's in the database.
741
+
726
742
  **CRITICAL:** This file is created **ONCE per application** (not per module).
727
- Without these roles, role-permission mappings in `SeedRolePermissionsAsync()` will fail silently.
728
743
 
729
744
  ### GUID Generation Rule
730
745
 
746
+ > **WARNING:** These deterministic GUIDs are ONLY used for role creation (if roles don't already exist).
747
+ > They MUST NEVER be used for RolePermission mapping — always look up roles by Code at runtime.
748
+
731
749
  ```csharp
732
750
  // Deterministic GUID from application ID + role type
751
+ // WARNING: Only for role creation. NEVER use these GUIDs for RolePermission mapping.
752
+ // RolePermissions MUST resolve roles by Code at runtime (see SeedRolePermissionsAsync).
733
753
  private static Guid GenerateRoleGuid(string roleType)
734
754
  {
735
755
  using var sha256 = System.Security.Cryptography.SHA256.Create();
736
756
  var hash = sha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes($"role-{ApplicationId}-{roleType}"));
737
757
  return new Guid(hash.Take(16).ToArray());
738
758
  }
739
- // roleType values: "admin", "manager", "contributor", "viewer"
759
+ // FORBIDDEN in RolePermission mapping:
760
+ // var roleId = GenerateRoleGuid("admin"); // WRONG — GUID may not match DB
761
+ // var roleId = DeterministicGuid("role:admin"); // WRONG — use Code lookup instead
740
762
  ```
741
763
 
742
764
  ### Template
@@ -841,6 +863,11 @@ public class ApplicationRoleSeedEntry
841
863
 
842
864
  **File:** `Infrastructure/Persistence/Seeding/Data/{ModulePascal}/RolesSeedData.cs`
843
865
 
866
+ > **CRITICAL:** This file uses `RoleCode` (string), NOT role GUIDs.
867
+ > Roles are resolved by Code at runtime in `SeedRolePermissionsAsync()`.
868
+ > **FORBIDDEN:** `DeterministicGuid("role:admin")`, `GenerateRoleGuid("admin")`, or any hardcoded Guid for roles.
869
+ > SmartStack core pre-seeds system roles — their IDs are NOT deterministic from the client perspective.
870
+
844
871
  ### Context-Based Role Mapping
845
872
 
846
873
  | Context | Admin | Manager | Contributor | Viewer |
@@ -1019,15 +1046,17 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1019
1046
 
1020
1047
  public async Task SeedRolesAsync(ICoreDbContext context, CancellationToken ct)
1021
1048
  {
1022
- // Check idempotence
1023
- var applicationId = ApplicationRolesSeedData.ApplicationId;
1024
- var exists = await context.Roles
1025
- .AnyAsync(r => r.ApplicationId == applicationId, ct);
1026
- if (exists) return;
1049
+ // Check idempotence — verify by Code (roles may already exist from SmartStack core)
1050
+ var existingRoleCodes = await context.Roles
1051
+ .Where(r => r.Code == "admin" || r.Code == "manager" || r.Code == "contributor" || r.Code == "viewer")
1052
+ .Select(r => r.Code)
1053
+ .ToListAsync(ct);
1027
1054
 
1028
- // Create application-scoped roles (Admin, Manager, Contributor, Viewer)
1055
+ // Only create roles that don't already exist (SmartStack core may pre-seed system roles)
1029
1056
  foreach (var entry in ApplicationRolesSeedData.GetRoleEntries())
1030
1057
  {
1058
+ if (existingRoleCodes.Contains(entry.Code)) continue; // Skip if already exists
1059
+
1031
1060
  var role = Role.Create(
1032
1061
  entry.Code,
1033
1062
  entry.Name,
@@ -1072,7 +1101,9 @@ public class {AppPascalName}SeedDataProvider : IClientSeedDataProvider
1072
1101
  .AnyAsync(rp => rp.Permission!.Path.StartsWith("{contextCode}.{appCode}."), ct);
1073
1102
  if (exists) return;
1074
1103
 
1075
- // Resolve roles by Code
1104
+ // CRITICAL: Resolve roles by Code from DB — NEVER use deterministic GUIDs.
1105
+ // System roles (admin, manager, contributor, viewer) are pre-seeded by SmartStack core
1106
+ // with their own IDs that do NOT match DeterministicGuid("role:admin").
1076
1107
  var roles = await context.Roles
1077
1108
  .Where(r => r.ApplicationId != null || r.IsSystem)
1078
1109
  .ToListAsync(ct);
@@ -1159,6 +1190,8 @@ Before marking the task as completed, verify ALL:
1159
1190
  **Application-Level (FIRST — before modules):**
1160
1191
  - [ ] `NavigationApplicationSeedData.cs` created (once per application, at `Infrastructure/Persistence/Seeding/Data/`)
1161
1192
  - [ ] Application GUID is deterministic (SHA256 of `"navigation-application-{contextCode}.{appCode}"`)
1193
+ - [ ] **NO ContextId constant in SeedConstants** — Context IDs are pre-seeded by SmartStack core (hardcoded GUIDs, NOT deterministic)
1194
+ - [ ] **SeedDataProvider queries context by code at runtime:** `db.NavigationContexts.FirstOrDefaultAsync(c => c.Code == "{contextCode}", ct)`
1162
1195
  - [ ] Application translations created (4 languages: fr, en, it, de, EntityType = Application)
1163
1196
  - [ ] `IClientSeedDataProvider.SeedNavigationAsync()` uses `NavigationApplicationSeedData` (NO hardcoded `{appLabel_en}` / `{appIcon}` placeholders)
1164
1197
  - [ ] `ApplicationRolesSeedData.ApplicationId` references `NavigationApplicationSeedData.ApplicationId` (NO `{ApplicationGuid}` placeholder)
@@ -1172,6 +1205,8 @@ Before marking the task as completed, verify ALL:
1172
1205
  - [ ] `Permissions.cs` constants match seed data paths
1173
1206
  - [ ] MCP `generate_permissions` called (or fallback used)
1174
1207
  - [ ] Role-permission mappings assigned (Admin, Manager, Contributor, Viewer)
1208
+ - [ ] **RolePermission mappings use Code-based lookup** — NEVER `DeterministicGuid("role:admin")` or `GenerateRoleGuid()`
1209
+ - [ ] **SeedRolesAsync checks existence by Code** — SmartStack core may pre-seed system roles
1175
1210
  - [ ] `IClientSeedDataProvider` generated with 4 methods (Navigation, Roles, Permissions, RolePermissions)
1176
1211
  - [ ] Execution order: Navigation (application → modules → sections → resources) → Roles → Permissions → RolePermissions
1177
1212
  - [ ] Each Seed method is idempotent (checks existence before inserting)
@@ -373,6 +373,53 @@ if [ -n "$FR_I18N_FILES" ]; then
373
373
  done
374
374
  fi
375
375
 
376
+ # POST-CHECK: SeedConstants must NOT contain ContextId (pre-seeded by SmartStack core)
377
+ SEED_CONST_FILES=$(find src/ -path "*/Seeding/*" -name "SeedConstants.cs" 2>/dev/null)
378
+ if [ -n "$SEED_CONST_FILES" ]; then
379
+ BAD_CTX=$(grep -Pn 'ContextId\s*=' $SEED_CONST_FILES 2>/dev/null)
380
+ if [ -n "$BAD_CTX" ]; then
381
+ echo "BLOCKING: SeedConstants must NOT contain a ContextId constant"
382
+ echo "Context IDs are pre-seeded by SmartStack core — look up by code at runtime"
383
+ echo "$BAD_CTX"
384
+ exit 1
385
+ fi
386
+ fi
387
+ SEED_ALL_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
388
+ if [ -n "$SEED_ALL_FILES" ]; then
389
+ BAD_CTX_GUID=$(grep -Pn 'DeterministicGuid\("nav:(business|platform|personal)"\)' $SEED_ALL_FILES 2>/dev/null)
390
+ if [ -n "$BAD_CTX_GUID" ]; then
391
+ echo "BLOCKING: Deterministic GUID for NavigationContext detected"
392
+ echo "Fix: Look up context by code at runtime in SeedDataProvider.SeedNavigationAsync()"
393
+ echo "$BAD_CTX_GUID"
394
+ exit 1
395
+ fi
396
+ fi
397
+
398
+ # POST-CHECK: RolePermission seed data must NOT use deterministic role GUIDs
399
+ SEED_ALL_FILES=$(find src/ -path "*/Seeding/Data/*" -name "*.cs" 2>/dev/null)
400
+ SEED_CONST_FILES=$(find src/ -path "*/Seeding/*" -name "SeedConstants.cs" 2>/dev/null)
401
+ if [ -n "$SEED_ALL_FILES" ]; then
402
+ BAD_ROLE_GUID=$(grep -Pn 'DeterministicGuid\("role:' $SEED_ALL_FILES $SEED_CONST_FILES 2>/dev/null)
403
+ if [ -n "$BAD_ROLE_GUID" ]; then
404
+ echo "BLOCKING: Deterministic GUID for role detected"
405
+ echo "System roles are pre-seeded by SmartStack core — look up by Code at runtime"
406
+ echo "$BAD_ROLE_GUID"
407
+ exit 1
408
+ fi
409
+ fi
410
+
411
+ # POST-CHECK: Services must NOT use TenantId!.Value (crashes with 500 instead of 401)
412
+ SERVICE_FILES=$(find src/ -path "*/Services/*" -name "*Service.cs" ! -name "I*Service.cs" 2>/dev/null)
413
+ if [ -n "$SERVICE_FILES" ]; then
414
+ BAD_PATTERN=$(grep -Pn 'TenantId!\s*\.Value|TenantId!\s*\.ToString|\.TenantId!' $SERVICE_FILES 2>/dev/null)
415
+ if [ -n "$BAD_PATTERN" ]; then
416
+ echo "BLOCKING: TenantId!.Value causes 500 when tenant context is missing"
417
+ echo "Fix: var tenantId = _currentTenant.TenantId ?? throw new UnauthorizedAccessException(\"Tenant context is required\");"
418
+ echo "$BAD_PATTERN"
419
+ exit 1
420
+ fi
421
+ fi
422
+
376
423
  # POST-CHECK: IAuditableEntity + Validator pairing
377
424
  ENTITY_FILES=$(find src/ -path "*/Domain/Entities/Business/*" -name "*.cs" 2>/dev/null)
378
425
  if [ -n "$ENTITY_FILES" ]; then