@stackwright-pro/mcp 0.2.0-alpha.85 → 0.2.0-alpha.90

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/dist/server.mjs CHANGED
@@ -3379,6 +3379,26 @@ var PHASE_ARTIFACT_SCHEMA = {
3379
3379
  null,
3380
3380
  2
3381
3381
  ),
3382
+ scaffold: JSON.stringify(
3383
+ {
3384
+ version: "1.0",
3385
+ generatedBy: "stackwright-pro-scaffold-otter",
3386
+ // REQUIRED: appRouterFiles is a required key — NOT 'files' (see swp-k3mb)
3387
+ appRouterFiles: [
3388
+ "app/layout.tsx",
3389
+ "app/_components/page-client.tsx",
3390
+ "app/page.tsx",
3391
+ "app/[...slug]/page.tsx",
3392
+ "app/_components/providers.tsx",
3393
+ "app/not-found.tsx"
3394
+ ],
3395
+ title: "<title from stackwright.yml>",
3396
+ hasCollectionEndpoints: false,
3397
+ hasAuthConfig: true
3398
+ },
3399
+ null,
3400
+ 2
3401
+ ),
3382
3402
  api: JSON.stringify(
3383
3403
  {
3384
3404
  version: "1.0",
@@ -3451,7 +3471,8 @@ var PHASE_ARTIFACT_SCHEMA = {
3451
3471
  {
3452
3472
  version: "1.0",
3453
3473
  generatedBy: "stackwright-pro-workflow-otter",
3454
- workflowConfig: {
3474
+ // Root key is `workflow` — NOT `workflowConfig` (see swp-k7cl)
3475
+ workflow: {
3455
3476
  id: "procurement-approval",
3456
3477
  route: "/procurement",
3457
3478
  files: ["workflows/procurement-approval.yml"],
@@ -3632,12 +3653,22 @@ function handleValidateArtifact(input) {
3632
3653
  }
3633
3654
  const PHASE_ZOD_VALIDATORS = {
3634
3655
  workflow: (artifact2) => {
3635
- const workflowConfig = artifact2["workflowConfig"];
3636
- if (!workflowConfig) return { success: true };
3637
- const result = WorkflowFileSchema.safeParse(workflowConfig);
3638
- if (!result.success) {
3639
- const issues = result.error.issues.slice(0, 3).map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
3640
- return { success: false, error: { message: issues } };
3656
+ const workflowData = artifact2["workflow"];
3657
+ if (!workflowData) {
3658
+ if (artifact2["workflowConfig"]) {
3659
+ console.warn(
3660
+ '[pipeline] DEPRECATED: workflow artifact uses "workflowConfig" key; rename to "workflow"'
3661
+ );
3662
+ return { success: true };
3663
+ }
3664
+ return { success: true };
3665
+ }
3666
+ if (typeof workflowData === "object" && workflowData !== null && "workflow" in workflowData) {
3667
+ const result = WorkflowFileSchema.safeParse(workflowData);
3668
+ if (!result.success) {
3669
+ const issues = result.error.issues.slice(0, 3).map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
3670
+ return { success: false, error: { message: issues } };
3671
+ }
3641
3672
  }
3642
3673
  return { success: true };
3643
3674
  },
@@ -4015,9 +4046,13 @@ function checkPageOwnership(cwd, slug, callerOtter) {
4015
4046
  contentTypes: existing.contentTypes
4016
4047
  };
4017
4048
  }
4049
+ var NEXTJS_BRACKET_SEGMENT_RE = /\[\[\.{3}[a-zA-Z_][a-zA-Z0-9_]*\]\]|\[\.{3}[a-zA-Z_][a-zA-Z0-9_]*\]|\[[a-zA-Z_][a-zA-Z0-9_]*\]/g;
4050
+ function stripNextjsBracketSegments(path3) {
4051
+ return path3.replace(NEXTJS_BRACKET_SEGMENT_RE, "");
4052
+ }
4018
4053
  function checkPathAllowed(callerOtter, filePath) {
4019
4054
  const normalized = normalize(filePath);
4020
- if (normalized.includes("..")) {
4055
+ if (stripNextjsBracketSegments(normalized).includes("..")) {
4021
4056
  return { allowed: false, error: 'Path traversal detected: ".." segments are not allowed' };
4022
4057
  }
4023
4058
  if (isAbsolute(normalized)) {
@@ -4913,7 +4948,7 @@ async function configureAuthHandler(params, cwd) {
4913
4948
  const detectedVersion = params.nextMajorVersion ?? detectNextMajorVersion(cwd);
4914
4949
  const useProxy = (detectedVersion ?? 0) >= 16;
4915
4950
  const conventionFile = useProxy ? "proxy.ts" : "middleware.ts";
4916
- if (method === "none") {
4951
+ if (method === "none" && !devOnly) {
4917
4952
  return {
4918
4953
  content: [
4919
4954
  {
@@ -4926,16 +4961,19 @@ async function configureAuthHandler(params, cwd) {
4926
4961
  rbacDefaultRole: defaultRole,
4927
4962
  protectedRoutesCount: protectedRoutes.length,
4928
4963
  filesWritten: [],
4929
- securityWarning: null
4964
+ securityWarning: null,
4965
+ autoUpgradeWarning: null
4930
4966
  })
4931
4967
  }
4932
4968
  ]
4933
4969
  };
4934
4970
  }
4971
+ const effectiveMethod = method === "none" ? "oidc" : method;
4972
+ const autoUpgradeWarning = method === "none" ? "method: 'none' + devOnly: true was automatically upgraded to method: 'oidc' + devOnly: true. In DEV_ONLY_MODE, pass method: 'oidc' + devOnly: true directly (swp-5tmy)." : null;
4935
4973
  const filesWritten = [];
4936
4974
  try {
4937
4975
  const authFileContent = devOnly ? useProxy ? generateDevOnlyProxyContent(
4938
- method,
4976
+ effectiveMethod,
4939
4977
  params,
4940
4978
  roles,
4941
4979
  defaultRole,
@@ -4944,7 +4982,7 @@ async function configureAuthHandler(params, cwd) {
4944
4982
  auditRetentionDays,
4945
4983
  protectedRoutes
4946
4984
  ) : generateDevOnlyMiddlewareContent(
4947
- method,
4985
+ effectiveMethod,
4948
4986
  params,
4949
4987
  roles,
4950
4988
  defaultRole,
@@ -4953,7 +4991,7 @@ async function configureAuthHandler(params, cwd) {
4953
4991
  auditRetentionDays,
4954
4992
  protectedRoutes
4955
4993
  ) : useProxy ? generateProxyContent(
4956
- method,
4994
+ effectiveMethod,
4957
4995
  params,
4958
4996
  roles,
4959
4997
  defaultRole,
@@ -4962,7 +5000,7 @@ async function configureAuthHandler(params, cwd) {
4962
5000
  auditRetentionDays,
4963
5001
  protectedRoutes
4964
5002
  ) : generateMiddlewareContent(
4965
- method,
5003
+ effectiveMethod,
4966
5004
  params,
4967
5005
  roles,
4968
5006
  defaultRole,
@@ -4990,7 +5028,7 @@ async function configureAuthHandler(params, cwd) {
4990
5028
  }
4991
5029
  if (!devOnly) {
4992
5030
  try {
4993
- const envBlock = generateEnvBlock(method, params);
5031
+ const envBlock = generateEnvBlock(effectiveMethod, params);
4994
5032
  const envPath = join6(cwd, ".env.example");
4995
5033
  if (existsSync7(envPath)) {
4996
5034
  const existing = readFileSync6(envPath, "utf8");
@@ -5060,7 +5098,7 @@ async function configureAuthHandler(params, cwd) {
5060
5098
  }
5061
5099
  try {
5062
5100
  const authYaml = devOnly ? generateDevOnlyYamlBlock(
5063
- method,
5101
+ effectiveMethod,
5064
5102
  params,
5065
5103
  roles,
5066
5104
  defaultRole,
@@ -5070,7 +5108,7 @@ async function configureAuthHandler(params, cwd) {
5070
5108
  protectedRoutes,
5071
5109
  useProxy
5072
5110
  ) : generateYamlBlock(
5073
- method,
5111
+ effectiveMethod,
5074
5112
  params,
5075
5113
  roles,
5076
5114
  defaultRole,
@@ -5100,14 +5138,14 @@ async function configureAuthHandler(params, cwd) {
5100
5138
  isError: true
5101
5139
  };
5102
5140
  }
5103
- const securityWarning = method === "cac" ? "SECURITY REVIEW REQUIRED \u2014 CAC certificate chain must be verified before production deployment" : null;
5141
+ const securityWarning = effectiveMethod === "cac" ? "SECURITY REVIEW REQUIRED \u2014 CAC certificate chain must be verified before production deployment" : null;
5104
5142
  return {
5105
5143
  content: [
5106
5144
  {
5107
5145
  type: "text",
5108
5146
  text: JSON.stringify({
5109
5147
  success: true,
5110
- method,
5148
+ method: effectiveMethod,
5111
5149
  provider: provider ?? null,
5112
5150
  rbacRoles: roles,
5113
5151
  rbacDefaultRole: defaultRole,
@@ -5116,6 +5154,7 @@ async function configureAuthHandler(params, cwd) {
5116
5154
  convention: useProxy ? "proxy" : "middleware",
5117
5155
  nextMajorVersion: params.nextMajorVersion ?? null,
5118
5156
  securityWarning,
5157
+ autoUpgradeWarning,
5119
5158
  ...devOnly ? {
5120
5159
  devScripts: {
5121
5160
  written: filesWritten.includes("package.json"),
@@ -5191,7 +5230,7 @@ var _checksums = /* @__PURE__ */ new Map([
5191
5230
  ],
5192
5231
  [
5193
5232
  "stackwright-pro-auth-otter.json",
5194
- "539c7145e88dd2afa7f2417be8cfa8e0e7d82608d051271a20f9c7e4e77d98e7"
5233
+ "07134125ab4f8c82ee015f27587e4d84bdeefca5ec211d1563bcb25b8aa61eb3"
5195
5234
  ],
5196
5235
  [
5197
5236
  "stackwright-pro-dashboard-otter.json",
@@ -5199,7 +5238,7 @@ var _checksums = /* @__PURE__ */ new Map([
5199
5238
  ],
5200
5239
  [
5201
5240
  "stackwright-pro-data-otter.json",
5202
- "b135cb0013edaa40baaf8a03f1d8795920dc0ce611183f047e55104bf8cf35be"
5241
+ "709c8e49328908549fe87de181a5991e09c918ef24bbfe6948f9888f0c758c25"
5203
5242
  ],
5204
5243
  [
5205
5244
  "stackwright-pro-designer-otter.json",
@@ -5223,19 +5262,19 @@ var _checksums = /* @__PURE__ */ new Map([
5223
5262
  ],
5224
5263
  [
5225
5264
  "stackwright-pro-polish-otter.json",
5226
- "02cfa56354bfcd33af6d634ac647f38812a2353e487816b67edc2e9eb2c3e357"
5265
+ "bd87327b9a9a62fabaee8837492ce943feae8bfc15e5d43b45ba0e84619daec3"
5227
5266
  ],
5228
5267
  [
5229
5268
  "stackwright-pro-scaffold-otter.json",
5230
- "ccbc9d20a65dcf7cc2eacb5ac3060cd95a10a3ef795883170684658872299e7b"
5269
+ "91de5861f1406043d1d387388302fb1492211b81e2eea9777dec60e48f317f2a"
5231
5270
  ],
5232
5271
  [
5233
5272
  "stackwright-pro-theme-otter.json",
5234
- "a271eac375db9d014afb781536f60f2e6716a9054b12b9c35713af09a63912ff"
5273
+ "fe10108e3ba67106751ea662f512bb5f4eb58f7abda26880ef4cf6b0f9feb944"
5235
5274
  ],
5236
5275
  [
5237
5276
  "stackwright-pro-workflow-otter.json",
5238
- "6cc800374de6e723a283e4757af97f7b8337c64ee78053d7e50a79e17314a049"
5277
+ "5f6209fadc1355580e2455a16386f06bd7d5814f047b2dd5b33800abf6a48ff8"
5239
5278
  ],
5240
5279
  [
5241
5280
  "stackwright-services-otter.json",
@@ -5965,7 +6004,15 @@ var SCAFFOLD_FILES_TO_DELETE = [
5965
6004
  "content/posts/getting-started.yaml",
5966
6005
  "content/posts/hello-world.yaml"
5967
6006
  ];
6007
+ var GETTING_STARTED_SCAFFOLD_FINGERPRINTS = [
6008
+ "Welcome to your new Stackwright",
6009
+ "Petstore API",
6010
+ "Petstore"
6011
+ ];
6012
+ var POST_FILE_EXTENSIONS = [".yaml", ".yml", ".md", ".mdx"];
6013
+ var POSTS_COLLECTION_FILE = "_collection.yaml";
5968
6014
  var SCAFFOLD_DIRS_TO_PRUNE = [
6015
+ "pages/getting-started",
5969
6016
  "content/posts"
5970
6017
  // Don't prune 'content' — user may have other content directories
5971
6018
  ];
@@ -6059,7 +6106,8 @@ function handleCleanupScaffold(_cwd) {
6059
6106
  rewritten: [],
6060
6107
  skipped: [],
6061
6108
  errors: [],
6062
- prunedDirs: []
6109
+ prunedDirs: [],
6110
+ cleanupWarnings: []
6063
6111
  };
6064
6112
  for (const relPath of SCAFFOLD_FILES_TO_DELETE) {
6065
6113
  const fullPath = join9(cwd, relPath);
@@ -6078,6 +6126,60 @@ function handleCleanupScaffold(_cwd) {
6078
6126
  result.errors.push(`Failed to delete ${relPath}: ${String(err)}`);
6079
6127
  }
6080
6128
  }
6129
+ {
6130
+ const relPath = "pages/getting-started/content.yml";
6131
+ const fullPath = join9(cwd, relPath);
6132
+ if (!existsSync9(fullPath)) {
6133
+ result.skipped.push(relPath);
6134
+ } else if (!isSafePath(fullPath)) {
6135
+ result.errors.push(`Refusing to delete symlink: ${relPath}`);
6136
+ } else {
6137
+ const content = readFileSync9(fullPath, "utf-8");
6138
+ const isScaffoldDefault = GETTING_STARTED_SCAFFOLD_FINGERPRINTS.some(
6139
+ (marker) => content.includes(marker)
6140
+ );
6141
+ if (isScaffoldDefault) {
6142
+ try {
6143
+ unlinkSync2(fullPath);
6144
+ result.deleted.push(relPath);
6145
+ } catch (err) {
6146
+ result.errors.push(`Failed to delete ${relPath}: ${String(err)}`);
6147
+ }
6148
+ } else {
6149
+ result.cleanupWarnings.push(
6150
+ `pages/getting-started/content.yml preserved \u2014 no scaffold fingerprint found (user-modified content)`
6151
+ );
6152
+ }
6153
+ }
6154
+ }
6155
+ {
6156
+ const relPath = `content/posts/${POSTS_COLLECTION_FILE}`;
6157
+ const fullPath = join9(cwd, relPath);
6158
+ const postsDir = join9(cwd, "content/posts");
6159
+ if (!existsSync9(fullPath)) {
6160
+ result.skipped.push(relPath);
6161
+ } else if (!isSafePath(fullPath)) {
6162
+ result.errors.push(`Refusing to delete symlink: ${relPath}`);
6163
+ } else if (!existsSync9(postsDir)) {
6164
+ result.skipped.push(relPath);
6165
+ } else {
6166
+ const userPostFiles = readdirSync3(postsDir).filter(
6167
+ (f) => f !== POSTS_COLLECTION_FILE && POST_FILE_EXTENSIONS.some((ext) => f.endsWith(ext))
6168
+ );
6169
+ if (userPostFiles.length === 0) {
6170
+ try {
6171
+ unlinkSync2(fullPath);
6172
+ result.deleted.push(relPath);
6173
+ } catch (err) {
6174
+ result.errors.push(`Failed to delete ${relPath}: ${String(err)}`);
6175
+ }
6176
+ } else {
6177
+ result.cleanupWarnings.push(
6178
+ `content/posts/_collection.yaml preserved \u2014 ${userPostFiles.length} user post file(s) exist: ${userPostFiles.slice(0, 3).join(", ")}`
6179
+ );
6180
+ }
6181
+ }
6182
+ }
6081
6183
  for (const relDir of SCAFFOLD_DIRS_TO_PRUNE) {
6082
6184
  const fullDir = join9(cwd, relDir);
6083
6185
  if (!existsSync9(fullDir)) continue;
@@ -6398,7 +6500,7 @@ var package_default = {
6398
6500
  "test:coverage": "vitest run --coverage"
6399
6501
  },
6400
6502
  name: "@stackwright-pro/mcp",
6401
- version: "0.2.0-alpha.82",
6503
+ version: "0.2.0-alpha.90",
6402
6504
  description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
6403
6505
  license: "SEE LICENSE IN LICENSE",
6404
6506
  main: "./dist/server.js",