@atlashub/smartstack-mcp 1.2.0 → 1.2.1

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.
package/README.md CHANGED
@@ -1,198 +1,154 @@
1
- # @smartstack/mcp-server
1
+ # @atlashub/smartstack-mcp
2
2
 
3
3
  MCP (Model Context Protocol) server for SmartStack/AtlasHub platform development.
4
4
 
5
- ## Features
5
+ ## Installation
6
6
 
7
- ### Tools
7
+ ### Option 1: Claude Code CLI (Recommended)
8
8
 
9
- | Tool | Description |
10
- |------|-------------|
11
- | `validate_conventions` | Validate AtlasHub conventions (SQL schemas, domain table prefixes, migration naming, service interfaces) |
12
- | `check_migrations` | Analyze EF Core migrations for conflicts and ordering issues |
13
- | `scaffold_extension` | Generate code for services, entities, controllers, or React components |
14
- | `api_docs` | Get API endpoint documentation from Swagger or code analysis |
9
+ ```bash
10
+ # Add SmartStack MCP (user-level, available in all projects)
11
+ claude mcp add smartstack -s user -e SMARTSTACK_PROJECT_PATH=C:/path/to/your/SmartStack.app -- npx -y @atlashub/smartstack-mcp
15
12
 
16
- ### Resources
13
+ # Or project-level (only for current project)
14
+ claude mcp add smartstack -e SMARTSTACK_PROJECT_PATH=C:/path/to/your/SmartStack.app -- npx -y @atlashub/smartstack-mcp
17
15
 
18
- | Resource URI | Description |
19
- |--------------|-------------|
20
- | `smartstack://conventions` | AtlasHub naming conventions and best practices |
21
- | `smartstack://project` | Current project information and structure |
22
- | `smartstack://api/{endpoint}` | API endpoint documentation |
23
- | `smartstack://schema/{table}` | Database schema information |
24
-
25
- ## Installation
16
+ # With global install (faster startup)
17
+ npm install -g @atlashub/smartstack-mcp
18
+ claude mcp add smartstack -s user -e SMARTSTACK_PROJECT_PATH=C:/path/to/your/SmartStack.app -- smartstack-mcp
19
+ ```
26
20
 
21
+ **Verify installation:**
27
22
  ```bash
28
- # Clone and install dependencies
29
- cd "D:\01 - projets\SmartStack.mcp\02-Develop"
30
- npm install
31
-
32
- # Build
33
- npm run build
23
+ claude mcp list
34
24
  ```
35
25
 
36
- ## Configuration
37
-
38
- ### Environment Variables
26
+ ### Option 2: Visual Studio Code (Extension Claude Code)
39
27
 
40
- | Variable | Description | Default |
41
- |----------|-------------|---------|
42
- | `SMARTSTACK_PROJECT_PATH` | Path to SmartStack.app project | `D:/SmartStack.app/features/Rework-to-package` |
43
- | `SMARTSTACK_API_URL` | SmartStack API URL | `https://localhost:7055` |
44
- | `SMARTSTACK_API_ENABLED` | Enable API integration | `true` |
45
- | `LOG_LEVEL` | Logging level (debug, info, warn, error) | `info` |
46
-
47
- ### Claude Desktop Configuration
48
-
49
- Add to your Claude Desktop config file (`claude_desktop_config.json`):
28
+ Create a `.mcp.json` file at the root of your project:
50
29
 
51
30
  ```json
52
31
  {
53
32
  "mcpServers": {
54
33
  "smartstack": {
55
- "command": "node",
56
- "args": ["D:/01 - projets/SmartStack.mcp/02-Develop/dist/index.js"],
34
+ "command": "npx",
35
+ "args": ["-y", "@atlashub/smartstack-mcp"],
57
36
  "env": {
58
- "SMARTSTACK_PROJECT_PATH": "D:/SmartStack.app/features/Rework-to-package",
59
- "SMARTSTACK_API_URL": "https://localhost:7055"
37
+ "SMARTSTACK_PROJECT_PATH": "C:/path/to/your/SmartStack.app"
60
38
  }
61
39
  }
62
40
  }
63
41
  }
64
42
  ```
65
43
 
66
- ### Claude Code Configuration
67
-
68
- Add to your `.claude/settings.json`:
44
+ Or with global install (faster startup):
69
45
 
70
46
  ```json
71
47
  {
72
48
  "mcpServers": {
73
49
  "smartstack": {
74
- "command": "node",
75
- "args": ["D:/01 - projets/SmartStack.mcp/02-Develop/dist/index.js"],
50
+ "command": "smartstack-mcp",
76
51
  "env": {
77
- "SMARTSTACK_PROJECT_PATH": "D:/SmartStack.app/features/Rework-to-package"
52
+ "SMARTSTACK_PROJECT_PATH": "C:/path/to/your/SmartStack.app"
78
53
  }
79
54
  }
80
55
  }
81
56
  }
82
57
  ```
83
58
 
84
- ## Usage Examples
59
+ **Steps:**
60
+ 1. Install the Claude Code extension in VS Code
61
+ 2. Create the `.mcp.json` file at project root
62
+ 3. Reload VS Code or the extension
63
+ 4. The MCP server will be available in Claude Code panel
85
64
 
86
- ### Validate Conventions
65
+ ### Option 3: Claude Desktop
87
66
 
88
- ```
89
- Use validate_conventions tool with checks: ["tables", "migrations", "services"]
90
- ```
67
+ Add to `claude_desktop_config.json`:
91
68
 
92
- ### Check Migrations
69
+ - **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
70
+ - **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
93
71
 
94
- ```
95
- Use check_migrations tool with compareBranch: "develop"
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "smartstack": {
76
+ "command": "npx",
77
+ "args": ["-y", "@atlashub/smartstack-mcp"],
78
+ "env": {
79
+ "SMARTSTACK_PROJECT_PATH": "C:/path/to/your/SmartStack.app"
80
+ }
81
+ }
82
+ }
83
+ }
96
84
  ```
97
85
 
98
- ### Scaffold a Service
86
+ ### Option 4: Manual Execution
99
87
 
100
- ```
101
- Use scaffold_extension tool with:
102
- - type: "service"
103
- - name: "UserProfile"
104
- - options: { methods: ["GetByIdAsync", "UpdateAsync"] }
88
+ ```bash
89
+ # Using npx (no install required)
90
+ SMARTSTACK_PROJECT_PATH=/path/to/project npx @atlashub/smartstack-mcp
91
+
92
+ # Or if installed globally
93
+ npm install -g @atlashub/smartstack-mcp
94
+ SMARTSTACK_PROJECT_PATH=/path/to/project smartstack-mcp
105
95
  ```
106
96
 
107
- ### Get API Documentation
97
+ ## Adding Context7 (Optional)
108
98
 
109
- ```
110
- Use api_docs tool with:
111
- - endpoint: "/api/users"
112
- - format: "markdown"
99
+ Context7 provides up-to-date documentation lookups for any library.
100
+
101
+ **Claude Code CLI:**
102
+ ```bash
103
+ claude mcp add context7 -s user -- npx -y @upstash/context7-mcp
113
104
  ```
114
105
 
115
- ## Development
106
+ **VS Code (.mcp.json):**
107
+ ```json
108
+ {
109
+ "mcpServers": {
110
+ "smartstack": {
111
+ "command": "npx",
112
+ "args": ["-y", "@atlashub/smartstack-mcp"],
113
+ "env": {
114
+ "SMARTSTACK_PROJECT_PATH": "C:/path/to/your/SmartStack.app"
115
+ }
116
+ },
117
+ "context7": {
118
+ "command": "npx",
119
+ "args": ["-y", "@upstash/context7-mcp"]
120
+ }
121
+ }
122
+ }
123
+ ```
116
124
 
117
- ```bash
118
- # Watch mode
119
- npm run dev
125
+ ## Configuration
120
126
 
121
- # Test with MCP Inspector
122
- npm run inspect
127
+ | Variable | Description | Required |
128
+ |----------|-------------|----------|
129
+ | `SMARTSTACK_PROJECT_PATH` | Path to your SmartStack.app project | Yes |
130
+ | `SMARTSTACK_API_URL` | SmartStack API URL | No |
131
+ | `LOG_LEVEL` | Logging level (debug, info, warn, error) | No |
123
132
 
124
- # Type check
125
- npm run typecheck
133
+ ## Features
126
134
 
127
- # Lint
128
- npm run lint
129
- ```
135
+ ### Tools
130
136
 
131
- ## Project Structure
137
+ | Tool | Description |
138
+ |------|-------------|
139
+ | `validate_conventions` | Validate AtlasHub conventions |
140
+ | `check_migrations` | Analyze EF Core migrations |
141
+ | `scaffold_extension` | Generate code scaffolding |
142
+ | `api_docs` | Get API documentation |
132
143
 
133
- ```
134
- src/
135
- ├── index.ts # Entry point
136
- ├── server.ts # MCP server configuration
137
- ├── config.ts # Configuration management
138
- ├── tools/ # MCP tool implementations
139
- │ ├── validate-conventions.ts
140
- │ ├── check-migrations.ts
141
- │ ├── scaffold-extension.ts
142
- │ └── api-docs.ts
143
- ├── resources/ # MCP resource implementations
144
- │ ├── conventions.ts
145
- │ ├── project-info.ts
146
- │ ├── api-endpoints.ts
147
- │ └── db-schema.ts
148
- ├── lib/ # Shared libraries
149
- │ ├── detector.ts # Project detection
150
- │ └── logger.ts # Logging utilities
151
- ├── types/ # TypeScript types
152
- │ └── index.ts
153
- └── utils/ # Utility functions
154
- ├── fs.ts # File system operations
155
- ├── git.ts # Git commands
156
- └── dotnet.ts # .NET CLI commands
157
- ```
144
+ ### Resources
158
145
 
159
- ## AtlasHub Conventions
160
-
161
- This MCP server enforces the following conventions:
162
-
163
- ### SQL Schemas
164
- - **`core`**: SmartStack platform tables
165
- - **`extensions`**: Client extension tables
166
-
167
- ### Table Prefixes (by domain)
168
- Tables use domain-specific prefixes within schemas:
169
- - `auth_*` - Authorization (Users, Roles, Permissions)
170
- - `nav_*` - Navigation (Contexts, Applications, Modules)
171
- - `usr_*` - User profiles (Profiles, Preferences)
172
- - `ai_*` - AI features (Providers, Models, Prompts)
173
- - `cfg_*` - Configuration (Settings)
174
- - `wkf_*` - Workflows (EmailTemplates, Workflows)
175
- - `support_*` - Support (Tickets, Comments)
176
- - `entra_*` - Entra sync (Groups, SyncState)
177
- - `ref_*` - References (Companies, Departments)
178
- - `loc_*` - Localization (Languages, Translations)
179
- - `lic_*` - Licensing (Licenses)
180
-
181
- Example: `.ToTable("auth_Users", "core")`
182
-
183
- ### Migration Naming
184
- Format: `YYYYMMDD_NNN_Description`
185
- - Example: `20260115_001_InitialSchema`
186
-
187
- ### Service Pattern
188
- - Interface: `I{Name}Service`
189
- - Implementation: `{Name}Service`
190
-
191
- ### Namespace Structure
192
- - Domain: `SmartStack.Domain`
193
- - Application: `SmartStack.Application`
194
- - Infrastructure: `SmartStack.Infrastructure`
195
- - API: `SmartStack.Api`
146
+ | Resource URI | Description |
147
+ |--------------|-------------|
148
+ | `smartstack://conventions` | Naming conventions |
149
+ | `smartstack://project` | Project information |
150
+ | `smartstack://api/{endpoint}` | API documentation |
151
+ | `smartstack://schema/{table}` | Database schema |
196
152
 
197
153
  ## License
198
154
 
package/dist/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- #!/usr/bin/env node
3
2
 
4
3
  // src/server.ts
5
4
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
@@ -149,7 +148,7 @@ var defaultConfig = {
149
148
  "loc_",
150
149
  "lic_"
151
150
  ],
152
- migrationFormat: "YYYYMMDD_NNN_{Description}",
151
+ migrationFormat: "{context}_v{version}_{sequence}_{Description}",
153
152
  namespaces: {
154
153
  domain: "SmartStack.Domain",
155
154
  application: "SmartStack.Application",
@@ -533,7 +532,7 @@ async function findControllerFiles(apiPath) {
533
532
  import path5 from "path";
534
533
  var validateConventionsTool = {
535
534
  name: "validate_conventions",
536
- description: "Validate AtlasHub/SmartStack conventions: SQL schemas (core/extensions), domain table prefixes (auth_, nav_, ai_, etc.), migration naming (YYYYMMDD_NNN_*), service interfaces (I*Service), namespace structure",
535
+ description: "Validate AtlasHub/SmartStack conventions: SQL schemas (core/extensions), domain table prefixes (auth_, nav_, ai_, etc.), migration naming ({context}_v{version}_{sequence}_*), service interfaces (I*Service), namespace structure",
537
536
  inputSchema: {
538
537
  type: "object",
539
538
  properties: {
@@ -675,7 +674,7 @@ async function validateMigrationNaming(structure, _config, result) {
675
674
  return;
676
675
  }
677
676
  const migrationFiles = await findFiles("*.cs", { cwd: structure.migrations });
678
- const migrationPattern = /^(\d{8})_(\d{3})_(.+)\.cs$/;
677
+ const migrationPattern = /^(\w+)_v(\d+\.\d+\.\d+)_(\d{3})_(.+)\.cs$/;
679
678
  const designerPattern = /\.Designer\.cs$/;
680
679
  for (const file of migrationFiles) {
681
680
  const fileName = path5.basename(file);
@@ -688,7 +687,7 @@ async function validateMigrationNaming(structure, _config, result) {
688
687
  category: "migrations",
689
688
  message: `Migration "${fileName}" does not follow naming convention`,
690
689
  file: path5.relative(structure.root, file),
691
- suggestion: `Expected format: YYYYMMDD_NNN_Description.cs (e.g., 20260115_001_InitialCreate.cs)`
690
+ suggestion: `Expected format: {context}_v{version}_{sequence}_{Description}.cs (e.g., core_v1.0.0_001_CreateAuthUsers.cs)`
692
691
  });
693
692
  }
694
693
  }
@@ -696,14 +695,18 @@ async function validateMigrationNaming(structure, _config, result) {
696
695
  for (let i = 1; i < orderedMigrations.length; i++) {
697
696
  const prev = orderedMigrations[i - 1];
698
697
  const curr = orderedMigrations[i];
699
- const prevDate = prev.substring(0, 8);
700
- const currDate = curr.substring(0, 8);
701
- if (currDate < prevDate) {
702
- result.warnings.push({
703
- type: "warning",
704
- category: "migrations",
705
- message: `Migration order issue: "${curr}" dated before "${prev}"`
706
- });
698
+ const prevMatch = migrationPattern.exec(prev);
699
+ const currMatch = migrationPattern.exec(curr);
700
+ if (prevMatch && currMatch) {
701
+ const prevVersion = prevMatch[2];
702
+ const currVersion = currMatch[2];
703
+ if (currVersion < prevVersion) {
704
+ result.warnings.push({
705
+ type: "warning",
706
+ category: "migrations",
707
+ message: `Migration order issue: "${curr}" (v${currVersion}) comes before "${prev}" (v${prevVersion})`
708
+ });
709
+ }
707
710
  }
708
711
  }
709
712
  }
@@ -871,7 +874,7 @@ async function handleCheckMigrations(args, config) {
871
874
  async function parseMigrations(migrationsPath, rootPath) {
872
875
  const files = await findFiles("*.cs", { cwd: migrationsPath });
873
876
  const migrations = [];
874
- const pattern = /^(\d{8})_(\d{3})_(.+)\.cs$/;
877
+ const pattern = /^(\w+)_v(\d+\.\d+\.\d+)_(\d{3})_(.+)\.cs$/;
875
878
  for (const file of files) {
876
879
  const fileName = path6.basename(file);
877
880
  if (fileName.includes(".Designer.") || fileName.includes("ModelSnapshot")) {
@@ -881,10 +884,13 @@ async function parseMigrations(migrationsPath, rootPath) {
881
884
  if (match) {
882
885
  migrations.push({
883
886
  name: fileName.replace(".cs", ""),
884
- timestamp: match[1],
885
- prefix: match[2],
886
- // Now this is the sequence number (NNN)
887
- description: match[3],
887
+ context: match[1],
888
+ // DbContext (core, extensions, etc.)
889
+ version: match[2],
890
+ // Semver version (1.0.0, 1.2.0, etc.)
891
+ sequence: match[3],
892
+ // Sequence number (001, 002, etc.)
893
+ description: match[4],
888
894
  file: path6.relative(rootPath, file),
889
895
  applied: true
890
896
  // We'd need DB connection to check this
@@ -892,8 +898,9 @@ async function parseMigrations(migrationsPath, rootPath) {
892
898
  } else {
893
899
  migrations.push({
894
900
  name: fileName.replace(".cs", ""),
895
- timestamp: "",
896
- prefix: "Unknown",
901
+ context: "Unknown",
902
+ version: "0.0.0",
903
+ sequence: "000",
897
904
  description: fileName.replace(".cs", ""),
898
905
  file: path6.relative(rootPath, file),
899
906
  applied: true
@@ -901,51 +908,63 @@ async function parseMigrations(migrationsPath, rootPath) {
901
908
  }
902
909
  }
903
910
  return migrations.sort((a, b) => {
904
- const dateCompare = a.timestamp.localeCompare(b.timestamp);
905
- if (dateCompare !== 0) return dateCompare;
906
- return a.prefix.localeCompare(b.prefix);
911
+ const versionCompare = compareVersions(a.version, b.version);
912
+ if (versionCompare !== 0) return versionCompare;
913
+ return a.sequence.localeCompare(b.sequence);
907
914
  });
908
915
  }
916
+ function compareVersions(a, b) {
917
+ const partsA = a.split(".").map(Number);
918
+ const partsB = b.split(".").map(Number);
919
+ for (let i = 0; i < 3; i++) {
920
+ if (partsA[i] > partsB[i]) return 1;
921
+ if (partsA[i] < partsB[i]) return -1;
922
+ }
923
+ return 0;
924
+ }
909
925
  function checkNamingConventions(result, _config) {
910
926
  for (const migration of result.migrations) {
911
- if (!migration.timestamp) {
927
+ if (migration.context === "Unknown") {
912
928
  result.conflicts.push({
913
929
  type: "naming",
914
930
  description: `Migration "${migration.name}" does not follow naming convention`,
915
931
  files: [migration.file],
916
- resolution: `Rename to format: YYYYMMDD_NNN_Description (e.g., 20260115_001_InitialCreate)`
932
+ resolution: `Rename to format: {context}_v{version}_{sequence}_{Description} (e.g., core_v1.0.0_001_CreateAuthUsers)`
917
933
  });
918
934
  }
919
- if (migration.prefix === "Unknown") {
935
+ if (migration.version === "0.0.0") {
920
936
  result.conflicts.push({
921
937
  type: "naming",
922
- description: `Migration "${migration.name}" missing sequence number`,
938
+ description: `Migration "${migration.name}" missing version number`,
923
939
  files: [migration.file],
924
- resolution: `Use format: YYYYMMDD_NNN_Description where NNN is a 3-digit sequence (001, 002, etc.)`
940
+ resolution: `Use format: {context}_v{version}_{sequence}_{Description} where version is semver (1.0.0, 1.2.0, etc.)`
925
941
  });
926
942
  }
927
943
  }
928
944
  }
929
945
  function checkChronologicalOrder(result) {
930
- const migrations = result.migrations.filter((m) => m.timestamp);
946
+ const migrations = result.migrations.filter((m) => m.context !== "Unknown");
931
947
  for (let i = 1; i < migrations.length; i++) {
932
948
  const prev = migrations[i - 1];
933
949
  const curr = migrations[i];
934
- if (curr.timestamp < prev.timestamp) {
935
- result.conflicts.push({
936
- type: "order",
937
- description: `Migration "${curr.name}" (${curr.timestamp}) is dated before "${prev.name}" (${prev.timestamp})`,
938
- files: [curr.file, prev.file],
939
- resolution: "Reorder migrations or update timestamps"
940
- });
941
- }
942
- if (curr.timestamp === prev.timestamp && curr.prefix === prev.prefix) {
943
- result.conflicts.push({
944
- type: "order",
945
- description: `Migrations "${curr.name}" and "${prev.name}" have same timestamp`,
946
- files: [curr.file, prev.file],
947
- resolution: "Use different sequence numbers (NNN) or different dates"
948
- });
950
+ if (curr.context === prev.context) {
951
+ const versionCompare = compareVersions(curr.version, prev.version);
952
+ if (versionCompare < 0) {
953
+ result.conflicts.push({
954
+ type: "order",
955
+ description: `Migration "${curr.name}" (v${curr.version}) is versioned before "${prev.name}" (v${prev.version})`,
956
+ files: [curr.file, prev.file],
957
+ resolution: "Reorder migrations or update version numbers"
958
+ });
959
+ }
960
+ if (curr.version === prev.version && curr.sequence === prev.sequence) {
961
+ result.conflicts.push({
962
+ type: "order",
963
+ description: `Migrations "${curr.name}" and "${prev.name}" have same version and sequence`,
964
+ files: [curr.file, prev.file],
965
+ resolution: "Use different sequence numbers (001, 002, etc.) for migrations in the same version"
966
+ });
967
+ }
949
968
  }
950
969
  }
951
970
  }
@@ -1000,7 +1019,7 @@ async function checkModelSnapshot(result, structure) {
1000
1019
  }
1001
1020
  const snapshotContent = await readText(snapshotFiles[0]);
1002
1021
  for (const migration of result.migrations) {
1003
- if (migration.timestamp && !snapshotContent.includes(migration.name)) {
1022
+ if (migration.context !== "Unknown" && !snapshotContent.includes(migration.name)) {
1004
1023
  result.conflicts.push({
1005
1024
  type: "dependency",
1006
1025
  description: `Migration "${migration.name}" not referenced in ModelSnapshot`,
@@ -1018,12 +1037,12 @@ function generateSuggestions(result) {
1018
1037
  }
1019
1038
  if (result.conflicts.some((c) => c.type === "naming")) {
1020
1039
  result.suggestions.push(
1021
- "Use convention: YYYYMMDD_NNN_Description for migration naming (e.g., 20260115_001_InitialCreate)"
1040
+ "Use convention: {context}_v{version}_{sequence}_{Description} for migration naming (e.g., core_v1.0.0_001_CreateAuthUsers)"
1022
1041
  );
1023
1042
  }
1024
1043
  if (result.conflicts.some((c) => c.type === "order")) {
1025
1044
  result.suggestions.push(
1026
- "Ensure migrations are created in chronological order to avoid conflicts"
1045
+ "Ensure migrations are created in version order to avoid conflicts"
1027
1046
  );
1028
1047
  }
1029
1048
  if (result.migrations.length > 20) {
@@ -1047,11 +1066,11 @@ function formatResult2(result, currentBranch, compareBranch) {
1047
1066
  lines.push("");
1048
1067
  lines.push("## Migrations");
1049
1068
  lines.push("");
1050
- lines.push("| Name | Timestamp | Prefix | Description |");
1051
- lines.push("|------|-----------|--------|-------------|");
1069
+ lines.push("| Name | Context | Version | Sequence | Description |");
1070
+ lines.push("|------|---------|---------|----------|-------------|");
1052
1071
  for (const migration of result.migrations) {
1053
1072
  lines.push(
1054
- `| ${migration.name} | ${migration.timestamp || "N/A"} | ${migration.prefix} | ${migration.description} |`
1073
+ `| ${migration.name} | ${migration.context} | ${migration.version} | ${migration.sequence} | ${migration.description} |`
1055
1074
  );
1056
1075
  }
1057
1076
  lines.push("");
@@ -1978,28 +1997,37 @@ Migrations MUST follow this naming pattern:
1978
1997
  ${migrationFormat}
1979
1998
  \`\`\`
1980
1999
 
2000
+ | Part | Description | Example |
2001
+ |------|-------------|---------|
2002
+ | \`{context}\` | DbContext name | \`core\`, \`extensions\` |
2003
+ | \`{version}\` | Semver version | \`v1.0.0\`, \`v1.2.0\` |
2004
+ | \`{sequence}\` | Order in version | \`001\`, \`002\` |
2005
+ | \`{Description}\` | Action (PascalCase) | \`CreateAuthUsers\` |
2006
+
1981
2007
  **Examples:**
1982
- - \`20260115_001_InitialSchema.cs\`
1983
- - \`20260120_002_AddUserProfiles.cs\`
1984
- - \`20260125_003_AddSupportTickets.cs\`
2008
+ - \`core_v1.0.0_001_InitialSchema.cs\`
2009
+ - \`core_v1.0.0_002_CreateAuthUsers.cs\`
2010
+ - \`core_v1.2.0_001_AddUserProfiles.cs\`
2011
+ - \`extensions_v1.0.0_001_AddClientFeatures.cs\`
1985
2012
 
1986
2013
  ### Creating Migrations
1987
2014
 
1988
2015
  \`\`\`bash
1989
2016
  # Create a new migration
1990
- dotnet ef migrations add 20260115_001_InitialSchema
2017
+ dotnet ef migrations add core_v1.0.0_001_InitialSchema
1991
2018
 
1992
2019
  # With context specified
1993
- dotnet ef migrations add 20260115_001_InitialSchema --context ApplicationDbContext
2020
+ dotnet ef migrations add core_v1.2.0_001_AddUserProfiles --context ApplicationDbContext
1994
2021
  \`\`\`
1995
2022
 
1996
2023
  ### Migration Rules
1997
2024
 
1998
2025
  1. **One migration per feature** - Group related changes in a single migration
1999
- 2. **Timestamps ensure order** - Use YYYYMMDD format for chronological sorting
2000
- 3. **Sequence numbers** - Use NNN (001, 002, etc.) for migrations on the same day
2001
- 4. **Descriptive names** - Use clear descriptions (InitialSchema, AddUserProfiles, etc.)
2002
- 5. **Schema must be specified** - All tables must specify their schema in ToTable()
2026
+ 2. **Version-based naming** - Use semver (v1.0.0, v1.2.0) to link migrations to releases
2027
+ 3. **Sequence numbers** - Use NNN (001, 002, etc.) for migrations in the same version
2028
+ 4. **Context prefix** - Use \`core_\` for platform tables, \`extensions_\` for client extensions
2029
+ 5. **Descriptive names** - Use clear PascalCase descriptions (CreateAuthUsers, AddUserProfiles, etc.)
2030
+ 6. **Schema must be specified** - All tables must specify their schema in ToTable()
2003
2031
 
2004
2032
  ---
2005
2033
 
@@ -2166,7 +2194,7 @@ public interface IUserServiceHooks
2166
2194
  | Platform schema | \`${schemas.platform}\` | \`.ToTable("auth_Users", "${schemas.platform}")\` |
2167
2195
  | Extensions schema | \`${schemas.extensions}\` | \`.ToTable("client_Custom", "${schemas.extensions}")\` |
2168
2196
  | Table prefixes | \`${tablePrefixes.slice(0, 5).join(", ")}\`, etc. | \`auth_Users\`, \`nav_Modules\` |
2169
- | Migration | \`YYYYMMDD_NNN_Description\` | \`20260115_001_InitialCreate\` |
2197
+ | Migration | \`{context}_v{version}_{seq}_{Desc}\` | \`core_v1.0.0_001_CreateAuthUsers\` |
2170
2198
  | Interface | \`I<Name>Service\` | \`IUserService\` |
2171
2199
  | Implementation | \`<Name>Service\` | \`UserService\` |
2172
2200
  | Domain namespace | \`${namespaces.domain}\` | - |