@stackwright-pro/mcp 0.2.0-alpha.109 → 0.2.0-alpha.111

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.js CHANGED
@@ -873,6 +873,9 @@ var BASELINE_DEPS = {
873
873
  "@stackwright-pro/openapi": "latest",
874
874
  "@stackwright-pro/auth": "latest",
875
875
  "@stackwright-pro/auth-nextjs": "latest",
876
+ // SBOM compliance — every Pro raft is a compliance product (swp-ryqz)
877
+ "@stackwright-pro/sbom-enterprise": "latest",
878
+ "@stackwright/sbom-generator": "^0.2.2",
876
879
  zod: "^3.23.0"
877
880
  };
878
881
  var BASELINE_DEV_DEPS = {
@@ -2026,7 +2029,7 @@ function registerOrchestrationTools(server2) {
2026
2029
  }
2027
2030
 
2028
2031
  // src/tools/pipeline.ts
2029
- var import_zod13 = require("zod");
2032
+ var import_zod14 = require("zod");
2030
2033
  var import_fs8 = require("fs");
2031
2034
  var import_proper_lockfile = require("proper-lockfile");
2032
2035
  var import_path8 = require("path");
@@ -2750,6 +2753,19 @@ function validateAuthConfig(artifact, artifactPath) {
2750
2753
  // src/tools/auth-manifest-aggregator.ts
2751
2754
  var import_fs6 = require("fs");
2752
2755
  var import_path6 = require("path");
2756
+ var import_zod11 = require("zod");
2757
+ function computeLowestRole(requiredRoles, rbacRoles) {
2758
+ let lowestIndex = -1;
2759
+ let lowestRole = requiredRoles[0];
2760
+ for (const role of requiredRoles) {
2761
+ const idx = rbacRoles.indexOf(role);
2762
+ if (idx > lowestIndex) {
2763
+ lowestIndex = idx;
2764
+ lowestRole = role;
2765
+ }
2766
+ }
2767
+ return lowestRole;
2768
+ }
2753
2769
  function extractPatternBaseSlug(pattern) {
2754
2770
  const stripped = pattern.replace(/^\//, "");
2755
2771
  if (!stripped) return null;
@@ -2783,16 +2799,105 @@ function extractManifestSlugs(artifactsDir) {
2783
2799
  }
2784
2800
  return slugs;
2785
2801
  }
2802
+ function normalizeNextJsSlug(slug) {
2803
+ return slug.replace(/\[\[\.\.\.([\w]+)\]\]/g, ":$1*").replace(/\[\.\.\.([\w]+)\]/g, ":$1*").replace(/\[([\w]+)\]/g, ":$1");
2804
+ }
2805
+ function deriveProtectedRoutes(pages, rbacRoles) {
2806
+ const protectedRoutes = [];
2807
+ const uncoveredSlugs = [];
2808
+ const seen = /* @__PURE__ */ new Set();
2809
+ for (const page of pages) {
2810
+ if (seen.has(page.slug)) continue;
2811
+ seen.add(page.slug);
2812
+ if (page.authRequired === false) continue;
2813
+ if (page.authRequired === true && Array.isArray(page.requiredRoles) && page.requiredRoles.length > 0) {
2814
+ const normalizedSlug = normalizeNextJsSlug(page.slug);
2815
+ const lowestRole = computeLowestRole(page.requiredRoles, rbacRoles);
2816
+ protectedRoutes.push({ pattern: `/${normalizedSlug}`, requiredRole: lowestRole });
2817
+ if (!normalizedSlug.endsWith("*")) {
2818
+ protectedRoutes.push({ pattern: `/${normalizedSlug}/:path*`, requiredRole: lowestRole });
2819
+ }
2820
+ continue;
2821
+ }
2822
+ const reason = page.authRequired === true ? "authRequired: true but requiredRoles is missing or empty" : "page emitter did not declare authRequired + requiredRoles";
2823
+ uncoveredSlugs.push({ source: page.source, slug: page.slug, reason });
2824
+ }
2825
+ return { protectedRoutes, uncoveredSlugs };
2826
+ }
2827
+ function readAllManifestPages(artifactsDir) {
2828
+ const allPages = [];
2829
+ if (!(0, import_fs6.existsSync)(artifactsDir)) return allPages;
2830
+ let entries;
2831
+ try {
2832
+ entries = (0, import_fs6.readdirSync)(artifactsDir);
2833
+ } catch {
2834
+ return allPages;
2835
+ }
2836
+ for (const entry of entries) {
2837
+ if (!entry.endsWith("-manifest.json")) continue;
2838
+ const filePath = (0, import_path6.join)(artifactsDir, entry);
2839
+ try {
2840
+ const raw = JSON.parse((0, import_fs6.readFileSync)(filePath, "utf-8"));
2841
+ if (!Array.isArray(raw.pages)) continue;
2842
+ for (const page of raw.pages) {
2843
+ if (typeof page.slug !== "string" || !page.slug) continue;
2844
+ allPages.push({
2845
+ slug: page.slug,
2846
+ authRequired: page.authRequired,
2847
+ requiredRoles: page.requiredRoles,
2848
+ source: entry
2849
+ });
2850
+ }
2851
+ } catch {
2852
+ }
2853
+ }
2854
+ return allPages;
2855
+ }
2856
+ function registerReadAuthManifestsTool(server2) {
2857
+ server2.tool(
2858
+ "stackwright_pro_read_auth_manifests",
2859
+ "Read ALL *-manifest.json files from the pipeline artifacts directory (pages-manifest.json, dashboard-manifest.json, geo-manifest.json, etc.) and deterministically derive protectedRoutes and uncoveredSlugs. Uses the both-forms invariant (swp-n7kk): every authRequired route registers BOTH /{slug} (exact) AND /{slug}/:path* (sub-path). Call this in Step 1 of auth configuration instead of manually reading each manifest file. Fixes the Bead C issue where dashboard-manifest.json and geo-manifest.json were silently missed.",
2860
+ {
2861
+ rbacRoles: import_zod11.z.array(import_zod11.z.string()).describe(
2862
+ 'RBAC role hierarchy in descending privilege order, e.g. ["ESF8_COORDINATOR", "HOSPITAL_EM", "OBSERVER"]. Used to compute the lowestRole for each authRequired page.'
2863
+ ),
2864
+ artifactsDir: import_zod11.z.string().optional().describe(
2865
+ "Absolute or relative path to the pipeline artifacts directory. Defaults to .stackwright/artifacts relative to cwd."
2866
+ )
2867
+ },
2868
+ (params) => {
2869
+ const cwd = process.cwd();
2870
+ const artifactsDir = params.artifactsDir ? params.artifactsDir : (0, import_path6.join)(cwd, ".stackwright", "artifacts");
2871
+ const allPages = readAllManifestPages(artifactsDir);
2872
+ const { protectedRoutes, uncoveredSlugs } = deriveProtectedRoutes(allPages, params.rbacRoles);
2873
+ const manifestsRead = [...new Set(allPages.map((p) => p.source))].sort();
2874
+ const result = {
2875
+ protectedRoutes,
2876
+ uncoveredSlugs,
2877
+ manifestsRead,
2878
+ summary: {
2879
+ totalPages: allPages.length,
2880
+ protectedCount: protectedRoutes.length,
2881
+ uncoveredCount: uncoveredSlugs.length,
2882
+ artifactsDir
2883
+ }
2884
+ };
2885
+ return {
2886
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
2887
+ };
2888
+ }
2889
+ );
2890
+ }
2786
2891
 
2787
2892
  // src/tools/pipeline.ts
2788
2893
  var import_types3 = require("@stackwright-pro/types");
2789
2894
 
2790
2895
  // src/tools/get-schema.ts
2791
- var import_zod12 = require("zod");
2896
+ var import_zod13 = require("zod");
2792
2897
  var import_types2 = require("@stackwright-pro/types");
2793
2898
 
2794
2899
  // src/tools/validate-yaml-fragment.ts
2795
- var import_zod11 = require("zod");
2900
+ var import_zod12 = require("zod");
2796
2901
  var import_js_yaml2 = require("js-yaml");
2797
2902
  var import_types = require("@stackwright-pro/types");
2798
2903
  var SUPPORTED_SCHEMA_NAMES = [
@@ -2803,18 +2908,18 @@ var SUPPORTED_SCHEMA_NAMES = [
2803
2908
  "navigation_item",
2804
2909
  "auth_config"
2805
2910
  ];
2806
- var NavigationLinkSchema = import_zod11.z.lazy(
2807
- () => import_zod11.z.object({
2808
- label: import_zod11.z.string().min(1),
2809
- href: import_zod11.z.string().min(1),
2810
- children: import_zod11.z.array(NavigationLinkSchema).optional()
2911
+ var NavigationLinkSchema = import_zod12.z.lazy(
2912
+ () => import_zod12.z.object({
2913
+ label: import_zod12.z.string().min(1),
2914
+ href: import_zod12.z.string().min(1),
2915
+ children: import_zod12.z.array(NavigationLinkSchema).optional()
2811
2916
  })
2812
2917
  );
2813
- var NavigationSectionSchema = import_zod11.z.object({
2814
- section: import_zod11.z.string().min(1),
2815
- items: import_zod11.z.array(NavigationLinkSchema)
2918
+ var NavigationSectionSchema = import_zod12.z.object({
2919
+ section: import_zod12.z.string().min(1),
2920
+ items: import_zod12.z.array(NavigationLinkSchema)
2816
2921
  });
2817
- var NavigationItemSchema = import_zod11.z.union([
2922
+ var NavigationItemSchema = import_zod12.z.union([
2818
2923
  NavigationLinkSchema,
2819
2924
  NavigationSectionSchema
2820
2925
  ]);
@@ -2916,10 +3021,10 @@ function registerValidateYamlFragmentTool(server2) {
2916
3021
  "stackwright_pro_validate_yaml_fragment",
2917
3022
  'Validates a YAML snippet against a canonical Zod schema before writing to disk. Returns actionable errors with "did you mean?" suggestions for common field-name drift (title vs label, id vs name, style vs theme.variant, etc.). Call this before stackwright_pro_safe_write to catch schema violations in-session.',
2918
3023
  {
2919
- schemaName: import_zod11.z.enum(SUPPORTED_SCHEMA_NAMES).describe(
3024
+ schemaName: import_zod12.z.enum(SUPPORTED_SCHEMA_NAMES).describe(
2920
3025
  "Schema to validate against. One of: workflow_step, workflow_definition, workflow_field, workflow_action, navigation_item, auth_config"
2921
3026
  ),
2922
- yaml: import_zod11.z.string().describe("YAML string to validate (can also be JSON \u2014 js-yaml parses both)")
3027
+ yaml: import_zod12.z.string().describe("YAML string to validate (can also be JSON \u2014 js-yaml parses both)")
2923
3028
  },
2924
3029
  async ({ schemaName, yaml: yaml3 }) => {
2925
3030
  const result = handleValidateYamlFragment({ schemaName, yaml: yaml3 });
@@ -2931,18 +3036,18 @@ function registerValidateYamlFragmentTool(server2) {
2931
3036
  }
2932
3037
 
2933
3038
  // src/tools/get-schema.ts
2934
- var NavigationLinkSchema2 = import_zod12.z.lazy(
2935
- () => import_zod12.z.object({
2936
- label: import_zod12.z.string().min(1),
2937
- href: import_zod12.z.string().min(1),
2938
- children: import_zod12.z.array(NavigationLinkSchema2).optional()
3039
+ var NavigationLinkSchema2 = import_zod13.z.lazy(
3040
+ () => import_zod13.z.object({
3041
+ label: import_zod13.z.string().min(1),
3042
+ href: import_zod13.z.string().min(1),
3043
+ children: import_zod13.z.array(NavigationLinkSchema2).optional()
2939
3044
  })
2940
3045
  );
2941
- var NavigationSectionSchema2 = import_zod12.z.object({
2942
- section: import_zod12.z.string().min(1),
2943
- items: import_zod12.z.array(NavigationLinkSchema2)
3046
+ var NavigationSectionSchema2 = import_zod13.z.object({
3047
+ section: import_zod13.z.string().min(1),
3048
+ items: import_zod13.z.array(NavigationLinkSchema2)
2944
3049
  });
2945
- var NavigationItemSchema2 = import_zod12.z.union([
3050
+ var NavigationItemSchema2 = import_zod13.z.union([
2946
3051
  NavigationLinkSchema2,
2947
3052
  NavigationSectionSchema2
2948
3053
  ]);
@@ -3043,7 +3148,7 @@ function handleGetSchema(input) {
3043
3148
  const synonyms = FIELD_SYNONYMS[name];
3044
3149
  let jsonSchema;
3045
3150
  try {
3046
- const raw = import_zod12.z.toJSONSchema(schema, { unrepresentable: "any" });
3151
+ const raw = import_zod13.z.toJSONSchema(schema, { unrepresentable: "any" });
3047
3152
  jsonSchema = raw;
3048
3153
  } catch {
3049
3154
  jsonSchema = { type: "object", description: "Schema introspection unavailable for this type" };
@@ -3097,7 +3202,7 @@ function registerGetSchemaTool(server2) {
3097
3202
  "stackwright_pro_get_schema",
3098
3203
  'Returns a compact, LLM-friendly summary of a canonical schema derived programmatically from Zod. Includes required/optional fields, types, constraints, and "did you mean?" warnings for common field-name drift. Use before authoring YAML to confirm exact field names.',
3099
3204
  {
3100
- schemaName: import_zod12.z.enum(SUPPORTED_SCHEMA_NAMES).describe(
3205
+ schemaName: import_zod13.z.enum(SUPPORTED_SCHEMA_NAMES).describe(
3101
3206
  "Schema to summarize. One of: workflow_step, workflow_definition, workflow_field, workflow_action, navigation_item, auth_config"
3102
3207
  )
3103
3208
  },
@@ -4808,28 +4913,28 @@ function registerPipelineTools(server2) {
4808
4913
  "stackwright_pro_set_pipeline_state",
4809
4914
  `Atomic read\u2192modify\u2192write pipeline state. ${DESC}`,
4810
4915
  {
4811
- phase: import_zod13.z.string().optional().describe('Phase to update, e.g. "designer"'),
4812
- field: import_zod13.z.enum(["questionsCollected", "answered", "executed", "artifactWritten", "inFlight"]).optional().describe("Boolean field to set"),
4916
+ phase: import_zod14.z.string().optional().describe('Phase to update, e.g. "designer"'),
4917
+ field: import_zod14.z.enum(["questionsCollected", "answered", "executed", "artifactWritten", "inFlight"]).optional().describe("Boolean field to set"),
4813
4918
  // inFlight: set true BEFORE specialist invoke (dataflow mode, swp-ioc7); false after.
4814
- value: boolCoerce(import_zod13.z.boolean().optional()).describe(
4919
+ value: boolCoerce(import_zod14.z.boolean().optional()).describe(
4815
4920
  'Value for the field \u2014 must be a JSON boolean (true/false), NOT the string "true"/"false"'
4816
4921
  ),
4817
- status: import_zod13.z.enum(["setup", "questions", "execution", "done"]).optional().describe("Top-level status override"),
4818
- incrementRetry: boolCoerce(import_zod13.z.boolean().optional()).describe(
4922
+ status: import_zod14.z.enum(["setup", "questions", "execution", "done"]).optional().describe("Top-level status override"),
4923
+ incrementRetry: boolCoerce(import_zod14.z.boolean().optional()).describe(
4819
4924
  "Bump retryCount by 1 \u2014 must be a JSON boolean"
4820
4925
  ),
4821
4926
  updates: jsonCoerce(
4822
- import_zod13.z.array(
4823
- import_zod13.z.object({
4824
- phase: import_zod13.z.string(),
4825
- field: import_zod13.z.enum([
4927
+ import_zod14.z.array(
4928
+ import_zod14.z.object({
4929
+ phase: import_zod14.z.string(),
4930
+ field: import_zod14.z.enum([
4826
4931
  "questionsCollected",
4827
4932
  "answered",
4828
4933
  "executed",
4829
4934
  "artifactWritten",
4830
4935
  "inFlight"
4831
4936
  ]),
4832
- value: import_zod13.z.boolean()
4937
+ value: import_zod14.z.boolean()
4833
4938
  })
4834
4939
  ).optional()
4835
4940
  ).describe("Batch updates \u2014 apply multiple field changes in one atomic read\u2192modify\u2192write")
@@ -4849,7 +4954,7 @@ function registerPipelineTools(server2) {
4849
4954
  "stackwright_pro_check_execution_ready",
4850
4955
  `Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,
4851
4956
  {
4852
- phase: import_zod13.z.string().optional().describe("If provided, check only this phase's readiness. Omit to check all phases.")
4957
+ phase: import_zod14.z.string().optional().describe("If provided, check only this phase's readiness. Omit to check all phases.")
4853
4958
  },
4854
4959
  async ({ phase }) => res(handleCheckExecutionReady(void 0, phase))
4855
4960
  );
@@ -4869,9 +4974,9 @@ function registerPipelineTools(server2) {
4869
4974
  "stackwright_pro_write_phase_questions",
4870
4975
  `Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC}`,
4871
4976
  {
4872
- phase: import_zod13.z.string().optional().describe('Phase name, e.g. "designer" (required for direct write)'),
4873
- responseText: import_zod13.z.string().optional().describe("Raw LLM response from QUESTION_COLLECTION_MODE"),
4874
- questions: jsonCoerce(import_zod13.z.array(import_zod13.z.any()).optional()).describe(
4977
+ phase: import_zod14.z.string().optional().describe('Phase name, e.g. "designer" (required for direct write)'),
4978
+ responseText: import_zod14.z.string().optional().describe("Raw LLM response from QUESTION_COLLECTION_MODE"),
4979
+ questions: jsonCoerce(import_zod14.z.array(import_zod14.z.any()).optional()).describe(
4875
4980
  "Questions array for direct specialist write"
4876
4981
  )
4877
4982
  },
@@ -4913,22 +5018,22 @@ function registerPipelineTools(server2) {
4913
5018
  server2.tool(
4914
5019
  "stackwright_pro_build_specialist_prompt",
4915
5020
  `Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC}`,
4916
- { phase: import_zod13.z.string().describe('Phase to build prompt for, e.g. "pages"') },
5021
+ { phase: import_zod14.z.string().describe('Phase to build prompt for, e.g. "pages"') },
4917
5022
  async ({ phase }) => res(handleBuildSpecialistPrompt({ phase }))
4918
5023
  );
4919
5024
  server2.tool(
4920
5025
  "stackwright_pro_validate_artifact",
4921
5026
  `Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC}`,
4922
5027
  {
4923
- phase: import_zod13.z.string().describe('Phase that produced this artifact, e.g. "designer"'),
4924
- responseText: import_zod13.z.string().optional().describe("Raw response text from the specialist otter (Foreman-mediated path, legacy)"),
4925
- artifact: jsonCoerce(import_zod13.z.record(import_zod13.z.string(), import_zod13.z.unknown()).optional()).describe(
5028
+ phase: import_zod14.z.string().describe('Phase that produced this artifact, e.g. "designer"'),
5029
+ responseText: import_zod14.z.string().optional().describe("Raw response text from the specialist otter (Foreman-mediated path, legacy)"),
5030
+ artifact: jsonCoerce(import_zod14.z.record(import_zod14.z.string(), import_zod14.z.unknown()).optional()).describe(
4926
5031
  "Artifact object to validate and write directly (specialist direct path \u2014 skips off-script detection and JSON parsing)"
4927
5032
  ),
4928
- integrationName: import_zod13.z.string().optional().describe(
5033
+ integrationName: import_zod14.z.string().optional().describe(
4929
5034
  'When phase="api": write to api-config-<integrationName>.json instead of api-config.json. Enables concurrent per-spec fan-out without collision (swp-530y).'
4930
5035
  ),
4931
- workflowName: import_zod13.z.string().optional().describe(
5036
+ workflowName: import_zod14.z.string().optional().describe(
4932
5037
  `When phase="workflow": write to workflow-config-<workflowName>.json instead of workflow-config.json. Enables concurrent per-workflow fan-out without collision (swp-x8sm). Must be a kebab-case slug matching the workflow's id field.`
4933
5038
  )
4934
5039
  },
@@ -4957,7 +5062,7 @@ function registerPipelineTools(server2) {
4957
5062
  "stackwright_pro_emit_event",
4958
5063
  `FOREMAN ONLY \u2014 specialist otters that call this will receive an authorization rejection (no-op, not an error). Emit a telemetry event to .stackwright/pipeline-events.ndjson. Foreman calls this at phase boundaries and agent-invoke boundaries. Best-effort: failures are silent and never block. ${DESC}`,
4959
5064
  {
4960
- type: import_zod13.z.enum([
5065
+ type: import_zod14.z.enum([
4961
5066
  "phase_start",
4962
5067
  "phase_complete",
4963
5068
  "phase_ready",
@@ -4966,20 +5071,20 @@ function registerPipelineTools(server2) {
4966
5071
  ]).describe("Event type to emit"),
4967
5072
  // phase_ready: emitted in dataflow mode (swp-ioc7) when a phase enters the ready set
4968
5073
  // (deps satisfied, not inFlight, not yet complete) — BEFORE invoking the specialist.
4969
- phase: import_zod13.z.string().optional().describe("Current phase name"),
4970
- targetOtter: import_zod13.z.string().optional().describe("For agent_invoke_* events: which otter is being invoked"),
4971
- success: boolCoerce(import_zod13.z.boolean().optional()).describe(
5074
+ phase: import_zod14.z.string().optional().describe("Current phase name"),
5075
+ targetOtter: import_zod14.z.string().optional().describe("For agent_invoke_* events: which otter is being invoked"),
5076
+ success: boolCoerce(import_zod14.z.boolean().optional()).describe(
4972
5077
  'For agent_invoke_complete: did the invocation succeed? (boolean; string "true"/"false" also accepted for caller tolerance)'
4973
5078
  ),
4974
- otter: import_zod13.z.string().optional().describe('Which otter is emitting (defaults to "foreman")'),
4975
- durationSec: import_zod13.z.number().optional().describe("Duration in seconds (for *_complete events)")
5079
+ otter: import_zod14.z.string().optional().describe('Which otter is emitting (defaults to "foreman")'),
5080
+ durationSec: import_zod14.z.number().optional().describe("Duration in seconds (for *_complete events)")
4976
5081
  },
4977
5082
  async ({ type, phase, targetOtter, success, otter, durationSec }) => res(handleEmitEvent({ type, phase, targetOtter, success, otter, durationSec }))
4978
5083
  );
4979
5084
  }
4980
5085
 
4981
5086
  // src/tools/safe-write.ts
4982
- var import_zod14 = require("zod");
5087
+ var import_zod15 = require("zod");
4983
5088
  var import_fs9 = require("fs");
4984
5089
  var import_path9 = require("path");
4985
5090
  var import_telemetry2 = require("@stackwright-pro/telemetry");
@@ -5475,10 +5580,10 @@ function registerSafeWriteTools(server2) {
5475
5580
  "stackwright_pro_safe_write",
5476
5581
  DESC,
5477
5582
  {
5478
- callerOtter: import_zod14.z.string().describe('The otter agent name requesting the write, e.g. "stackwright-pro-page-otter"'),
5479
- filePath: import_zod14.z.string().describe('Relative path from project root, e.g. "pages/dashboard/content.yml"'),
5480
- content: import_zod14.z.string().describe("File content to write"),
5481
- createDirectories: boolCoerce(import_zod14.z.boolean().optional().default(true)).describe(
5583
+ callerOtter: import_zod15.z.string().describe('The otter agent name requesting the write, e.g. "stackwright-pro-page-otter"'),
5584
+ filePath: import_zod15.z.string().describe('Relative path from project root, e.g. "pages/dashboard/content.yml"'),
5585
+ content: import_zod15.z.string().describe("File content to write"),
5586
+ createDirectories: boolCoerce(import_zod15.z.boolean().optional().default(true)).describe(
5482
5587
  "Create parent directories if they don't exist. Default: true"
5483
5588
  )
5484
5589
  },
@@ -5495,9 +5600,12 @@ function registerSafeWriteTools(server2) {
5495
5600
  }
5496
5601
 
5497
5602
  // src/tools/auth.ts
5498
- var import_zod15 = require("zod");
5603
+ var import_zod16 = require("zod");
5499
5604
  var import_fs10 = require("fs");
5500
5605
  var import_path10 = require("path");
5606
+ function normalizeProviderSlug(slug) {
5607
+ return slug.replace(/-/g, "_");
5608
+ }
5501
5609
  function buildHierarchy(roles) {
5502
5610
  const h = {};
5503
5611
  for (let i = 0; i < roles.length - 1; i++) {
@@ -5752,13 +5860,12 @@ ${hierarchyToYaml(hierarchy, " ")}`;
5752
5860
  const ocspEndpoint = params.cacOcspEndpoint ?? "https://ocsp.disa.mil";
5753
5861
  const certHeader = params.cacCertHeader ?? "X-SSL-Client-Cert";
5754
5862
  return `# stackwright.auth.yml \u2014 generated by Auth Otter
5755
- method: cac
5756
- ${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
5757
- cac:
5758
- caBundle: \${CAC_CA_BUNDLE}
5759
- edipiLookup: ${edipiLookup}
5760
- ocspEndpoint: \${CAC_OCSP_ENDPOINT}
5761
- certHeader: ${certHeader}
5863
+ type: pki
5864
+ ${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
5865
+ caBundle: \${CAC_CA_BUNDLE}
5866
+ edipiLookup: ${edipiLookup}
5867
+ ocspEndpoint: \${CAC_OCSP_ENDPOINT}
5868
+ certHeader: ${certHeader}
5762
5869
  ${rbacSection}
5763
5870
  protectedRoutes:
5764
5871
  ${routeLines}
@@ -5769,14 +5876,13 @@ ${auditSection}
5769
5876
  const scopes2 = params.oidcScopes ?? "openid profile email";
5770
5877
  const roleClaim = params.oidcRoleClaim ?? "roles";
5771
5878
  return `# stackwright.auth.yml \u2014 generated by Auth Otter
5772
- method: oidc
5879
+ type: oidc
5773
5880
  ${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
5774
- oidc:
5775
- discoveryUrl: \${OIDC_DISCOVERY_URL}
5776
- clientId: \${OIDC_CLIENT_ID}
5777
- clientSecret: \${OIDC_CLIENT_SECRET}
5778
- scopes: ${scopes2}
5779
- roleClaim: ${roleClaim}
5881
+ discoveryUrl: \${OIDC_DISCOVERY_URL}
5882
+ clientId: \${OIDC_CLIENT_ID}
5883
+ clientSecret: \${OIDC_CLIENT_SECRET}
5884
+ scopes: ${scopes2}
5885
+ roleClaim: ${roleClaim}
5780
5886
  ${rbacSection}
5781
5887
  protectedRoutes:
5782
5888
  ${routeLines}
@@ -5785,14 +5891,13 @@ ${auditSection}
5785
5891
  }
5786
5892
  const scopes = params.oauth2Scopes ?? "read write";
5787
5893
  return `# stackwright.auth.yml \u2014 generated by Auth Otter
5788
- method: oauth2
5894
+ type: oauth2
5789
5895
  ${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
5790
- oauth2:
5791
- authorizationUrl: \${OAUTH2_AUTH_URL}
5792
- tokenUrl: \${OAUTH2_TOKEN_URL}
5793
- clientId: \${OAUTH2_CLIENT_ID}
5794
- clientSecret: \${OAUTH2_CLIENT_SECRET}
5795
- scopes: ${scopes}
5896
+ authorizationUrl: \${OAUTH2_AUTH_URL}
5897
+ tokenUrl: \${OAUTH2_TOKEN_URL}
5898
+ clientId: \${OAUTH2_CLIENT_ID}
5899
+ clientSecret: \${OAUTH2_CLIENT_SECRET}
5900
+ scopes: ${scopes}
5796
5901
  ${rbacSection}
5797
5902
  protectedRoutes:
5798
5903
  ${routeLines}
@@ -5999,14 +6104,13 @@ ${hierarchyToYaml(hierarchy, " ")}`;
5999
6104
  const ocspEndpoint = params.cacOcspEndpoint ?? "https://ocsp.disa.mil";
6000
6105
  const certHeader = params.cacCertHeader ?? "X-SSL-Client-Cert";
6001
6106
  return `# stackwright.auth.yml \u2014 generated by Auth Otter
6002
- method: cac
6107
+ type: pki
6003
6108
  devOnly: true
6004
- ${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
6005
- cac:
6006
- caBundle: ${caBundle}
6007
- edipiLookup: ${edipiLookup}
6008
- ocspEndpoint: ${ocspEndpoint}
6009
- certHeader: ${certHeader}
6109
+ ${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
6110
+ caBundle: ${caBundle}
6111
+ edipiLookup: ${edipiLookup}
6112
+ ocspEndpoint: ${ocspEndpoint}
6113
+ certHeader: ${certHeader}
6010
6114
  ${rbacSection}
6011
6115
  protectedRoutes:
6012
6116
  ${routeLines}
@@ -6017,15 +6121,14 @@ ${auditSection}
6017
6121
  const scopes2 = params.oidcScopes ?? "openid profile email";
6018
6122
  const roleClaim = params.oidcRoleClaim ?? "roles";
6019
6123
  return `# stackwright.auth.yml \u2014 generated by Auth Otter
6020
- method: oidc
6124
+ type: oidc
6021
6125
  devOnly: true
6022
6126
  ${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
6023
- oidc:
6024
- discoveryUrl: https://dev-mock-oidc/.well-known/openid-configuration
6025
- clientId: dev-mock-client
6026
- clientSecret: dev-mock-secret
6027
- scopes: ${scopes2}
6028
- roleClaim: ${roleClaim}
6127
+ discoveryUrl: https://dev-mock-oidc/.well-known/openid-configuration
6128
+ clientId: dev-mock-client
6129
+ clientSecret: dev-mock-secret
6130
+ scopes: ${scopes2}
6131
+ roleClaim: ${roleClaim}
6029
6132
  ${rbacSection}
6030
6133
  protectedRoutes:
6031
6134
  ${routeLines}
@@ -6034,15 +6137,14 @@ ${auditSection}
6034
6137
  }
6035
6138
  const scopes = params.oauth2Scopes ?? "read write";
6036
6139
  return `# stackwright.auth.yml \u2014 generated by Auth Otter
6037
- method: oauth2
6140
+ type: oauth2
6038
6141
  devOnly: true
6039
6142
  ${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
6040
- oauth2:
6041
- authorizationUrl: https://dev-mock-oauth2/authorize
6042
- tokenUrl: https://dev-mock-oauth2/token
6043
- clientId: dev-mock-client
6044
- clientSecret: dev-mock-secret
6045
- scopes: ${scopes}
6143
+ authorizationUrl: https://dev-mock-oauth2/authorize
6144
+ tokenUrl: https://dev-mock-oauth2/token
6145
+ clientId: dev-mock-client
6146
+ clientSecret: dev-mock-secret
6147
+ scopes: ${scopes}
6046
6148
  ${rbacSection}
6047
6149
  protectedRoutes:
6048
6150
  ${routeLines}
@@ -6112,6 +6214,10 @@ function updatePackageJsonScripts(existingJson, roles, mockUsers) {
6112
6214
  return JSON.stringify(pkg, null, 2) + "\n";
6113
6215
  }
6114
6216
  async function configureAuthHandler(params, cwd) {
6217
+ params = {
6218
+ ...params,
6219
+ provider: params.provider != null ? normalizeProviderSlug(params.provider) : void 0
6220
+ };
6115
6221
  const {
6116
6222
  method,
6117
6223
  provider,
@@ -6363,45 +6469,46 @@ function registerAuthTools(server2) {
6363
6469
  "stackwright_pro_configure_auth",
6364
6470
  "Generate authentication middleware and configuration for a Next.js Stackwright application. Writes `middleware.ts` (or `proxy.ts` for Next.js >=16) from a secure template, writes a standalone `stackwright.auth.yml` sibling file, and generates `.env.example` with required environment variables. \u26A0\uFE0F For CAC/PKI: generated `middleware.ts` carries a SECURITY REVIEW REQUIRED comment \u2014 certificate chain validation must be verified by a DoD security officer before production deployment. This is the ONLY approved path to generating `middleware.ts`. Never write TypeScript auth files directly.",
6365
6471
  {
6366
- method: import_zod15.z.enum(["cac", "oidc", "oauth2", "none"]),
6367
- provider: import_zod15.z.enum(["azure-ad", "okta", "ping", "cognito", "custom"]).optional(),
6472
+ method: import_zod16.z.enum(["cac", "oidc", "oauth2", "none"]),
6473
+ // Both hyphen and underscore accepted at the tool surface; normalized to underscore downstream.
6474
+ provider: import_zod16.z.enum(["azure-ad", "azure_ad", "okta", "ping", "cognito", "custom"]).optional(),
6368
6475
  // CAC
6369
- cacCaBundle: import_zod15.z.string().optional(),
6370
- cacEdipiLookup: import_zod15.z.string().optional(),
6371
- cacOcspEndpoint: import_zod15.z.string().optional(),
6372
- cacCertHeader: import_zod15.z.string().optional(),
6476
+ cacCaBundle: import_zod16.z.string().optional(),
6477
+ cacEdipiLookup: import_zod16.z.string().optional(),
6478
+ cacOcspEndpoint: import_zod16.z.string().optional(),
6479
+ cacCertHeader: import_zod16.z.string().optional(),
6373
6480
  // OIDC
6374
- oidcDiscoveryUrl: import_zod15.z.string().optional(),
6375
- oidcClientId: import_zod15.z.string().optional(),
6376
- oidcClientSecret: import_zod15.z.string().optional(),
6377
- oidcScopes: import_zod15.z.string().optional(),
6378
- oidcRoleClaim: import_zod15.z.string().optional(),
6481
+ oidcDiscoveryUrl: import_zod16.z.string().optional(),
6482
+ oidcClientId: import_zod16.z.string().optional(),
6483
+ oidcClientSecret: import_zod16.z.string().optional(),
6484
+ oidcScopes: import_zod16.z.string().optional(),
6485
+ oidcRoleClaim: import_zod16.z.string().optional(),
6379
6486
  // OAuth2
6380
- oauth2AuthUrl: import_zod15.z.string().optional(),
6381
- oauth2TokenUrl: import_zod15.z.string().optional(),
6382
- oauth2ClientId: import_zod15.z.string().optional(),
6383
- oauth2ClientSecret: import_zod15.z.string().optional(),
6384
- oauth2Scopes: import_zod15.z.string().optional(),
6487
+ oauth2AuthUrl: import_zod16.z.string().optional(),
6488
+ oauth2TokenUrl: import_zod16.z.string().optional(),
6489
+ oauth2ClientId: import_zod16.z.string().optional(),
6490
+ oauth2ClientSecret: import_zod16.z.string().optional(),
6491
+ oauth2Scopes: import_zod16.z.string().optional(),
6385
6492
  // RBAC
6386
- rbacRoles: jsonCoerce(import_zod15.z.array(import_zod15.z.string()).optional()),
6387
- rbacDefaultRole: import_zod15.z.string().optional(),
6493
+ rbacRoles: jsonCoerce(import_zod16.z.array(import_zod16.z.string()).optional()),
6494
+ rbacDefaultRole: import_zod16.z.string().optional(),
6388
6495
  // Audit
6389
- auditEnabled: boolCoerce(import_zod15.z.boolean().optional()),
6390
- auditRetentionDays: numCoerce(import_zod15.z.number().int().positive().optional()),
6496
+ auditEnabled: boolCoerce(import_zod16.z.boolean().optional()),
6497
+ auditRetentionDays: numCoerce(import_zod16.z.number().int().positive().optional()),
6391
6498
  // Routes — accepts bare strings (backward-compat) or per-route objects (swp-owu0)
6392
6499
  protectedRoutes: jsonCoerce(
6393
- import_zod15.z.array(
6394
- import_zod15.z.union([
6395
- import_zod15.z.string(),
6396
- import_zod15.z.object({ pattern: import_zod15.z.string(), requiredRole: import_zod15.z.string().optional() })
6500
+ import_zod16.z.array(
6501
+ import_zod16.z.union([
6502
+ import_zod16.z.string(),
6503
+ import_zod16.z.object({ pattern: import_zod16.z.string(), requiredRole: import_zod16.z.string().optional() })
6397
6504
  ])
6398
6505
  ).optional()
6399
6506
  ),
6400
6507
  // Injection for tests
6401
- _cwd: import_zod15.z.string().optional(),
6402
- devOnly: boolCoerce(import_zod15.z.boolean().optional()),
6403
- mockUsers: jsonCoerce(import_zod15.z.array(import_zod15.z.object({ name: import_zod15.z.string(), email: import_zod15.z.string() })).optional()),
6404
- nextMajorVersion: numCoerce(import_zod15.z.number().int().positive().optional())
6508
+ _cwd: import_zod16.z.string().optional(),
6509
+ devOnly: boolCoerce(import_zod16.z.boolean().optional()),
6510
+ mockUsers: jsonCoerce(import_zod16.z.array(import_zod16.z.object({ name: import_zod16.z.string(), email: import_zod16.z.string() })).optional()),
6511
+ nextMajorVersion: numCoerce(import_zod16.z.number().int().positive().optional())
6405
6512
  },
6406
6513
  async (params) => {
6407
6514
  const cwd = params._cwd ?? process.cwd();
@@ -6421,7 +6528,7 @@ var _checksums = /* @__PURE__ */ new Map([
6421
6528
  ],
6422
6529
  [
6423
6530
  "stackwright-pro-auth-otter.json",
6424
- "69fa03c5532ef617c86fe7af41e8174c168d282baf602b1b269a7e933ea86b7c"
6531
+ "eee511fa214203ce88d51996c6b1b483b6ad3a0ae474cc7be5d380fdbbc43bb1"
6425
6532
  ],
6426
6533
  [
6427
6534
  "stackwright-pro-dashboard-otter.json",
@@ -6457,7 +6564,7 @@ var _checksums = /* @__PURE__ */ new Map([
6457
6564
  ],
6458
6565
  [
6459
6566
  "stackwright-pro-polish-otter.json",
6460
- "fd8f8963266c6179eebf8eac4f656e8274aa3a721e5296abdbde5b00ad8a2297"
6567
+ "4b8223d89af7f92b9051fee7bb29fc4b1ee2a5a9ab87e8e67a6d8be6122fa029"
6461
6568
  ],
6462
6569
  [
6463
6570
  "stackwright-pro-qa-otter.json",
@@ -6690,7 +6797,7 @@ function registerIntegrityTools(server2) {
6690
6797
  }
6691
6798
 
6692
6799
  // src/tools/domain.ts
6693
- var import_zod16 = require("zod");
6800
+ var import_zod17 = require("zod");
6694
6801
  var import_fs12 = require("fs");
6695
6802
  var import_path12 = require("path");
6696
6803
  function handleListCollections(input) {
@@ -7076,7 +7183,7 @@ function registerDomainTools(server2) {
7076
7183
  "stackwright_pro_resolve_data_strategy",
7077
7184
  "Look up the data freshness strategy configuration from the user's answer. Returns mechanism, revalidation seconds, required packages, and the exact MCP tool call to make. Replaces the strategy table in the data-otter prompt.",
7078
7185
  {
7079
- strategy: import_zod16.z.string().describe(
7186
+ strategy: import_zod17.z.string().describe(
7080
7187
  'The data-1 answer value: "pulse-fast", "isr-fast", "isr-standard", or "isr-slow"'
7081
7188
  )
7082
7189
  },
@@ -7086,7 +7193,7 @@ function registerDomainTools(server2) {
7086
7193
  "stackwright_pro_validate_workflow",
7087
7194
  "Validate a workflow definition against the Stackwright workflow schema. Checks step ID uniqueness, transition targets, terminal state existence, and service references. Call this after the workflow otter produces output.",
7088
7195
  {
7089
- workflow: jsonCoerce(import_zod16.z.record(import_zod16.z.string(), import_zod16.z.unknown()).optional()).describe(
7196
+ workflow: jsonCoerce(import_zod17.z.record(import_zod17.z.string(), import_zod17.z.unknown()).optional()).describe(
7090
7197
  "Parsed workflow object. If omitted, reads from .stackwright/artifacts/workflow-config.json"
7091
7198
  )
7092
7199
  },
@@ -7095,7 +7202,7 @@ function registerDomainTools(server2) {
7095
7202
  }
7096
7203
 
7097
7204
  // src/tools/type-schemas.ts
7098
- var import_zod17 = require("zod");
7205
+ var import_zod18 = require("zod");
7099
7206
  function buildTypeSchemaSummary() {
7100
7207
  return {
7101
7208
  version: "1.0",
@@ -7172,7 +7279,7 @@ function registerTypeSchemasTool(server2) {
7172
7279
  "stackwright_pro_get_type_schemas",
7173
7280
  "Returns a structured summary of all canonical @stackwright-pro/types schemas, organized by domain. Use this to determine which otter owns a given schema and what artifact key to expect.",
7174
7281
  {
7175
- format: import_zod17.z.enum(["full", "domains-only"]).optional().default("full").describe("full = complete summary with all fields; domains-only = just domain names")
7282
+ format: import_zod18.z.enum(["full", "domains-only"]).optional().default("full").describe("full = complete summary with all fields; domains-only = just domain names")
7176
7283
  },
7177
7284
  async ({ format }) => {
7178
7285
  const summary = buildTypeSchemaSummary();
@@ -7188,7 +7295,7 @@ function registerTypeSchemasTool(server2) {
7188
7295
  var fs2 = __toESM(require("fs"));
7189
7296
  var os = __toESM(require("os"));
7190
7297
  var path3 = __toESM(require("path"));
7191
- var import_zod18 = require("zod");
7298
+ var import_zod19 = require("zod");
7192
7299
  var import_js_yaml3 = require("js-yaml");
7193
7300
  var import_cli = require("@stackwright/cli");
7194
7301
  var import_types4 = require("@stackwright-pro/types");
@@ -7300,10 +7407,10 @@ function registerProPageTools(server2) {
7300
7407
  "stackwright_pro_write_page",
7301
7408
  "Write or update a page's YAML content with Pro content-type awareness. Validates against the Stackwright schema (including Pro types like stats_grid, data_table_pulse, map_pulse, alert_banner). Invalid YAML or schema violations on OSS-type fields are rejected with field-level errors. Use this instead of stackwright_write_page for any page containing Pro content types.",
7302
7409
  {
7303
- projectRoot: import_zod18.z.string().describe("Absolute path to the Stackwright project root"),
7304
- slug: import_zod18.z.string().describe('Page slug (e.g. "dashboard/main" or "/dashboard/main")'),
7305
- content: import_zod18.z.string().describe("Full YAML content for the page (content.yml contents)"),
7306
- locale: import_zod18.z.string().optional().describe(
7410
+ projectRoot: import_zod19.z.string().describe("Absolute path to the Stackwright project root"),
7411
+ slug: import_zod19.z.string().describe('Page slug (e.g. "dashboard/main" or "/dashboard/main")'),
7412
+ content: import_zod19.z.string().describe("Full YAML content for the page (content.yml contents)"),
7413
+ locale: import_zod19.z.string().optional().describe(
7307
7414
  'BCP 47 locale tag (e.g. "fr", "de"). If provided, writes content.<locale>.yml instead of content.yml.'
7308
7415
  )
7309
7416
  },
@@ -7553,7 +7660,7 @@ function registerScaffoldCleanupTools(server2) {
7553
7660
  }
7554
7661
 
7555
7662
  // src/tools/contrast.ts
7556
- var import_zod19 = require("zod");
7663
+ var import_zod20 = require("zod");
7557
7664
  function linearizeChannel(c255) {
7558
7665
  const c = c255 / 255;
7559
7666
  return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
@@ -7725,8 +7832,8 @@ function registerContrastTools(server2) {
7725
7832
  "stackwright_pro_check_contrast",
7726
7833
  'Compute the exact WCAG 2.1 contrast ratio between a foreground and background color. Returns the ratio and AA/AAA pass/fail flags. Use this to verify any foreground/background color pair before writing it to the token set. Accepts #RGB, #RRGGBB, hsl(...), or shadcn HSL format ("H S% L%").',
7727
7834
  {
7728
- fg: import_zod19.z.string().describe("Foreground (text) color \u2014 hex or HSL"),
7729
- bg: import_zod19.z.string().describe("Background color \u2014 hex or HSL")
7835
+ fg: import_zod20.z.string().describe("Foreground (text) color \u2014 hex or HSL"),
7836
+ bg: import_zod20.z.string().describe("Background color \u2014 hex or HSL")
7730
7837
  },
7731
7838
  async ({ fg, bg }) => {
7732
7839
  let result;
@@ -7756,8 +7863,8 @@ function registerContrastTools(server2) {
7756
7863
  "stackwright_pro_derive_accessible_palette",
7757
7864
  'Given a seed color (treated as a background), derive the best accessible foreground (text) color that meets the target contrast ratio. Evaluates #ffffff and #000000 against the seed and picks whichever satisfies the target ratio with the highest contrast. Use this for every {name}-foreground token derivation instead of guessing white vs black. Accepts #RGB, #RRGGBB, hsl(...), or shadcn HSL format ("H S% L%").',
7758
7865
  {
7759
- seed: import_zod19.z.string().describe("Background (seed) color \u2014 hex or HSL"),
7760
- targetRatio: numCoerce(import_zod19.z.number().default(4.5)).describe(
7866
+ seed: import_zod20.z.string().describe("Background (seed) color \u2014 hex or HSL"),
7867
+ targetRatio: numCoerce(import_zod20.z.number().default(4.5)).describe(
7761
7868
  "Minimum required contrast ratio (default 4.5 for WCAG AA)"
7762
7869
  )
7763
7870
  },
@@ -7792,7 +7899,7 @@ function registerContrastTools(server2) {
7792
7899
  }
7793
7900
 
7794
7901
  // src/tools/compile.ts
7795
- var import_zod20 = require("zod");
7902
+ var import_zod21 = require("zod");
7796
7903
  var import_fs14 = __toESM(require("fs"));
7797
7904
  var import_path14 = __toESM(require("path"));
7798
7905
  var import_server = require("@stackwright-pro/pulse/server");
@@ -7838,7 +7945,7 @@ async function tryOssCompile(fn, ctx, extra) {
7838
7945
  }
7839
7946
  }
7840
7947
  function registerCompileTools(server2) {
7841
- const projectRootArg = import_zod20.z.string().optional().describe("Absolute path to project root (defaults to cwd)");
7948
+ const projectRootArg = import_zod21.z.string().optional().describe("Absolute path to project root (defaults to cwd)");
7842
7949
  server2.tool(
7843
7950
  "stackwright_pro_compile_collections",
7844
7951
  "Compile stackwright.collections.yml \u2192 public/stackwright-content/_collections.json. Reads and validates the live-collections sidecar config file and emits the JSON sink consumed at runtime by PulseCollectionProvider.",
@@ -8014,7 +8121,7 @@ ${results.join("\n")}`;
8014
8121
  "stackwright_pro_compile_page",
8015
8122
  "Compile a single page by slug. Delegates to compilePage from @stackwright/build-scripts installed in the project.",
8016
8123
  {
8017
- slug: import_zod20.z.string().describe('Page slug (relative path under pages/, e.g. "dashboard")'),
8124
+ slug: import_zod21.z.string().describe('Page slug (relative path under pages/, e.g. "dashboard")'),
8018
8125
  projectRoot: projectRootArg
8019
8126
  },
8020
8127
  async ({ slug, projectRoot }) => {
@@ -8034,7 +8141,7 @@ ${results.join("\n")}`;
8034
8141
  }
8035
8142
 
8036
8143
  // src/tools/strip-legacy-integrations.ts
8037
- var import_zod21 = require("zod");
8144
+ var import_zod22 = require("zod");
8038
8145
  var import_fs15 = require("fs");
8039
8146
  var import_path15 = require("path");
8040
8147
  function handleStripLegacyIntegrations(input) {
@@ -8097,7 +8204,7 @@ function registerStripLegacyIntegrationsTool(server2) {
8097
8204
  "stackwright_pro_strip_legacy_integrations",
8098
8205
  "Removes the deprecated top-level integrations[] block from stackwright.yml. The authoritative source for integration config is stackwright.integrations.yml \u2014 this tool cleans up legacy entries from older raft runs. Idempotent: no-op if no legacy block present. Preserves all other top-level keys, comments, and formatting.",
8099
8206
  {
8100
- projectRoot: import_zod21.z.string().describe("Absolute path to the project root directory")
8207
+ projectRoot: import_zod22.z.string().describe("Absolute path to the project root directory")
8101
8208
  },
8102
8209
  async ({ projectRoot }) => {
8103
8210
  const result = handleStripLegacyIntegrations({ projectRoot });
@@ -8109,7 +8216,7 @@ function registerStripLegacyIntegrationsTool(server2) {
8109
8216
  }
8110
8217
 
8111
8218
  // src/tools/emitters.ts
8112
- var import_zod22 = require("zod");
8219
+ var import_zod23 = require("zod");
8113
8220
  var import_fs16 = require("fs");
8114
8221
  var import_path16 = require("path");
8115
8222
  var import_js_yaml4 = __toESM(require("js-yaml"));
@@ -8168,7 +8275,7 @@ Call this tool, then write both files with stackwright_pro_safe_write:
8168
8275
 
8169
8276
  Do NOT compose the contents by hand. This emitter is the source of truth. If an env var is missing, update integrations.yml or the emitter \u2014 not the file. This is the first concrete instance of the swp-zf9y deterministic emitter pattern. ${ENV_LOCAL_DESC}`,
8170
8277
  {
8171
- cwd: import_zod22.z.string().describe(
8278
+ cwd: import_zod23.z.string().describe(
8172
8279
  "Absolute path to the project root containing stackwright.integrations.yml and optionally services/*.yml"
8173
8280
  )
8174
8281
  },
@@ -8215,8 +8322,8 @@ mapProvider options:
8215
8322
 
8216
8323
  This is the second concrete instance of the swp-zf9y deterministic emitter pattern. Refs: swp-57ku, swp-2m89, swp-zf9y, drawer 957. ${PROVIDERS_DESC}`,
8217
8324
  {
8218
- cwd: import_zod22.z.string().describe("Absolute path to the project root containing stackwright.integrations.yml"),
8219
- mapProvider: import_zod22.z.enum(["maplibre", "cesium", "none"]).optional().describe(
8325
+ cwd: import_zod23.z.string().describe("Absolute path to the project root containing stackwright.integrations.yml"),
8326
+ mapProvider: import_zod23.z.enum(["maplibre", "cesium", "none"]).optional().describe(
8220
8327
  "Map provider to register (default: cesium for Pro \u2014 3D globe + terrain). Use maplibre for OSS-style 2D dashboards (explicit opt-out). Use none if pages have no map content_items."
8221
8328
  )
8222
8329
  },
@@ -8257,7 +8364,7 @@ Workflow:
8257
8364
 
8258
8365
  This is the third concrete instance of the swp-zf9y deterministic emitter pattern. Refs: swp-phkh, swp-zf9y. ${PORTS_DESC}`,
8259
8366
  {
8260
- cwd: import_zod22.z.string().describe("Absolute path to the project root containing stackwright.integrations.yml")
8367
+ cwd: import_zod23.z.string().describe("Absolute path to the project root containing stackwright.integrations.yml")
8261
8368
  },
8262
8369
  async ({ cwd }) => {
8263
8370
  const integrations = readIntegrations(cwd);
@@ -8286,7 +8393,7 @@ This is the third concrete instance of the swp-zf9y deterministic emitter patter
8286
8393
  }
8287
8394
 
8288
8395
  // src/tools/list-specs.ts
8289
- var import_zod23 = require("zod");
8396
+ var import_zod24 = require("zod");
8290
8397
  var import_fs17 = require("fs");
8291
8398
  var import_path17 = require("path");
8292
8399
  var STRIP_SUFFIXES = ["-openapi", "-asyncapi", "-api", "-spec"];
@@ -8351,7 +8458,7 @@ function registerListSpecsTool(server2) {
8351
8458
  "stackwright_pro_list_specs",
8352
8459
  "Enumerate OpenAPI/AsyncAPI specs in the project's specs/ directory. Returns one entry per spec with integration name (derived from filename), detected format, and size. Used by the foreman to fan out the api phase with one api-otter invocation per spec.",
8353
8460
  {
8354
- projectRoot: import_zod23.z.string().describe("Absolute path to the project root directory")
8461
+ projectRoot: import_zod24.z.string().describe("Absolute path to the project root directory")
8355
8462
  },
8356
8463
  async ({ projectRoot }) => {
8357
8464
  const result = handleListSpecs({ projectRoot });
@@ -8363,7 +8470,7 @@ function registerListSpecsTool(server2) {
8363
8470
  }
8364
8471
 
8365
8472
  // src/tools/consolidate-integrations.ts
8366
- var import_zod24 = require("zod");
8473
+ var import_zod25 = require("zod");
8367
8474
  var import_fs18 = require("fs");
8368
8475
  var import_proper_lockfile2 = require("proper-lockfile");
8369
8476
  var import_path18 = require("path");
@@ -8484,7 +8591,7 @@ function registerConsolidateIntegrationsTool(server2) {
8484
8591
  "no per-spec artifacts are found."
8485
8592
  ].join(" "),
8486
8593
  {
8487
- projectRoot: import_zod24.z.string().describe("Absolute path to the project root directory")
8594
+ projectRoot: import_zod25.z.string().describe("Absolute path to the project root directory")
8488
8595
  },
8489
8596
  async ({ projectRoot }) => {
8490
8597
  try {
@@ -8542,7 +8649,7 @@ var package_default = {
8542
8649
  "test:coverage": "vitest run --coverage"
8543
8650
  },
8544
8651
  name: "@stackwright-pro/mcp",
8545
- version: "0.2.0-alpha.109",
8652
+ version: "0.2.0-alpha.111",
8546
8653
  description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
8547
8654
  license: "SEE LICENSE IN LICENSE",
8548
8655
  main: "./dist/server.js",
@@ -8598,6 +8705,7 @@ registerOrchestrationTools(server);
8598
8705
  registerPipelineTools(server);
8599
8706
  registerSafeWriteTools(server);
8600
8707
  registerAuthTools(server);
8708
+ registerReadAuthManifestsTool(server);
8601
8709
  registerIntegrityTools(server);
8602
8710
  registerArtifactSigningTools(server);
8603
8711
  registerDomainTools(server);