@stackwright-pro/mcp 0.2.0-alpha.108 → 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/integrity.js +3 -3
- package/dist/integrity.js.map +1 -1
- package/dist/integrity.mjs +3 -3
- package/dist/integrity.mjs.map +1 -1
- package/dist/pipeline-constants.js +24 -21
- package/dist/pipeline-constants.js.map +1 -1
- package/dist/pipeline-constants.mjs +24 -21
- package/dist/pipeline-constants.mjs.map +1 -1
- package/dist/server.js +293 -160
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +293 -160
- package/dist/server.mjs.map +1 -1
- package/package.json +6 -6
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
|
|
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
|
|
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
|
|
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 =
|
|
2807
|
-
() =>
|
|
2808
|
-
label:
|
|
2809
|
-
href:
|
|
2810
|
-
children:
|
|
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 =
|
|
2814
|
-
section:
|
|
2815
|
-
items:
|
|
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 =
|
|
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:
|
|
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:
|
|
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 =
|
|
2935
|
-
() =>
|
|
2936
|
-
label:
|
|
2937
|
-
href:
|
|
2938
|
-
children:
|
|
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 =
|
|
2942
|
-
section:
|
|
2943
|
-
items:
|
|
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 =
|
|
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 =
|
|
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:
|
|
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
|
},
|
|
@@ -4424,6 +4529,31 @@ function _validateArtifactInner(input) {
|
|
|
4424
4529
|
}
|
|
4425
4530
|
}
|
|
4426
4531
|
const PHASE_ZOD_VALIDATORS = {
|
|
4532
|
+
// 5.0 Theme defaultColorMode hygiene (swp-0ryn / swp-mw97)
|
|
4533
|
+
//
|
|
4534
|
+
// DHL raft runs produced `defaultColorMode: "auto"` (not a valid value) and
|
|
4535
|
+
// `defaultColorMode: "dark"` when the designer said "respect OS preference".
|
|
4536
|
+
// This validator catches the `auto` literal at write-time so the otter
|
|
4537
|
+
// self-corrects before the artifact lands on disk.
|
|
4538
|
+
//
|
|
4539
|
+
// Valid values: 'light' | 'dark' | 'system'
|
|
4540
|
+
// Omitting the key entirely is also valid (app shell honors prefers-color-scheme).
|
|
4541
|
+
theme: (artifact2) => {
|
|
4542
|
+
const dcm = artifact2["defaultColorMode"];
|
|
4543
|
+
if (dcm === void 0 || dcm === null) {
|
|
4544
|
+
return { success: true };
|
|
4545
|
+
}
|
|
4546
|
+
const VALID_COLOR_MODES = ["light", "dark", "system"];
|
|
4547
|
+
if (!VALID_COLOR_MODES.includes(dcm)) {
|
|
4548
|
+
return {
|
|
4549
|
+
success: false,
|
|
4550
|
+
error: {
|
|
4551
|
+
message: `theme-tokens.json: \`defaultColorMode: "${String(dcm)}"\` is not a valid value. Valid values are \`light\`, \`dark\`, or \`system\`. Use \`system\` for OS-following behavior (respects \`prefers-color-scheme\`). Alternatively, OMIT the \`defaultColorMode\` key entirely when the designer has specified in design-language.json operationalNotes that OS preference should be respected (trigger phrases: "respect OS preference", "no forced default").`
|
|
4552
|
+
}
|
|
4553
|
+
};
|
|
4554
|
+
}
|
|
4555
|
+
return { success: true };
|
|
4556
|
+
},
|
|
4427
4557
|
workflow: (artifact2) => {
|
|
4428
4558
|
const workflowData = artifact2["workflow"];
|
|
4429
4559
|
if (!workflowData) {
|
|
@@ -4783,28 +4913,28 @@ function registerPipelineTools(server2) {
|
|
|
4783
4913
|
"stackwright_pro_set_pipeline_state",
|
|
4784
4914
|
`Atomic read\u2192modify\u2192write pipeline state. ${DESC}`,
|
|
4785
4915
|
{
|
|
4786
|
-
phase:
|
|
4787
|
-
field:
|
|
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"),
|
|
4788
4918
|
// inFlight: set true BEFORE specialist invoke (dataflow mode, swp-ioc7); false after.
|
|
4789
|
-
value: boolCoerce(
|
|
4919
|
+
value: boolCoerce(import_zod14.z.boolean().optional()).describe(
|
|
4790
4920
|
'Value for the field \u2014 must be a JSON boolean (true/false), NOT the string "true"/"false"'
|
|
4791
4921
|
),
|
|
4792
|
-
status:
|
|
4793
|
-
incrementRetry: boolCoerce(
|
|
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(
|
|
4794
4924
|
"Bump retryCount by 1 \u2014 must be a JSON boolean"
|
|
4795
4925
|
),
|
|
4796
4926
|
updates: jsonCoerce(
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
phase:
|
|
4800
|
-
field:
|
|
4927
|
+
import_zod14.z.array(
|
|
4928
|
+
import_zod14.z.object({
|
|
4929
|
+
phase: import_zod14.z.string(),
|
|
4930
|
+
field: import_zod14.z.enum([
|
|
4801
4931
|
"questionsCollected",
|
|
4802
4932
|
"answered",
|
|
4803
4933
|
"executed",
|
|
4804
4934
|
"artifactWritten",
|
|
4805
4935
|
"inFlight"
|
|
4806
4936
|
]),
|
|
4807
|
-
value:
|
|
4937
|
+
value: import_zod14.z.boolean()
|
|
4808
4938
|
})
|
|
4809
4939
|
).optional()
|
|
4810
4940
|
).describe("Batch updates \u2014 apply multiple field changes in one atomic read\u2192modify\u2192write")
|
|
@@ -4824,7 +4954,7 @@ function registerPipelineTools(server2) {
|
|
|
4824
4954
|
"stackwright_pro_check_execution_ready",
|
|
4825
4955
|
`Check all phases have answer files in .stackwright/answers/. If phase is provided, check only that phase. ${DESC}`,
|
|
4826
4956
|
{
|
|
4827
|
-
phase:
|
|
4957
|
+
phase: import_zod14.z.string().optional().describe("If provided, check only this phase's readiness. Omit to check all phases.")
|
|
4828
4958
|
},
|
|
4829
4959
|
async ({ phase }) => res(handleCheckExecutionReady(void 0, phase))
|
|
4830
4960
|
);
|
|
@@ -4844,9 +4974,9 @@ function registerPipelineTools(server2) {
|
|
|
4844
4974
|
"stackwright_pro_write_phase_questions",
|
|
4845
4975
|
`Parse otter question-collection response \u2192 .stackwright/questions/{phase}.json. Specialists may also call this directly with a parsed questions array. ${DESC}`,
|
|
4846
4976
|
{
|
|
4847
|
-
phase:
|
|
4848
|
-
responseText:
|
|
4849
|
-
questions: jsonCoerce(
|
|
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(
|
|
4850
4980
|
"Questions array for direct specialist write"
|
|
4851
4981
|
)
|
|
4852
4982
|
},
|
|
@@ -4888,22 +5018,22 @@ function registerPipelineTools(server2) {
|
|
|
4888
5018
|
server2.tool(
|
|
4889
5019
|
"stackwright_pro_build_specialist_prompt",
|
|
4890
5020
|
`Assemble execution prompt from answers + upstream artifacts. Foreman passes verbatim. ${DESC}`,
|
|
4891
|
-
{ phase:
|
|
5021
|
+
{ phase: import_zod14.z.string().describe('Phase to build prompt for, e.g. "pages"') },
|
|
4892
5022
|
async ({ phase }) => res(handleBuildSpecialistPrompt({ phase }))
|
|
4893
5023
|
);
|
|
4894
5024
|
server2.tool(
|
|
4895
5025
|
"stackwright_pro_validate_artifact",
|
|
4896
5026
|
`Validate and write artifact to .stackwright/artifacts/. Returns retryPrompt on failure. ${DESC}`,
|
|
4897
5027
|
{
|
|
4898
|
-
phase:
|
|
4899
|
-
responseText:
|
|
4900
|
-
artifact: jsonCoerce(
|
|
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(
|
|
4901
5031
|
"Artifact object to validate and write directly (specialist direct path \u2014 skips off-script detection and JSON parsing)"
|
|
4902
5032
|
),
|
|
4903
|
-
integrationName:
|
|
5033
|
+
integrationName: import_zod14.z.string().optional().describe(
|
|
4904
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).'
|
|
4905
5035
|
),
|
|
4906
|
-
workflowName:
|
|
5036
|
+
workflowName: import_zod14.z.string().optional().describe(
|
|
4907
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.`
|
|
4908
5038
|
)
|
|
4909
5039
|
},
|
|
@@ -4932,7 +5062,7 @@ function registerPipelineTools(server2) {
|
|
|
4932
5062
|
"stackwright_pro_emit_event",
|
|
4933
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}`,
|
|
4934
5064
|
{
|
|
4935
|
-
type:
|
|
5065
|
+
type: import_zod14.z.enum([
|
|
4936
5066
|
"phase_start",
|
|
4937
5067
|
"phase_complete",
|
|
4938
5068
|
"phase_ready",
|
|
@@ -4941,20 +5071,20 @@ function registerPipelineTools(server2) {
|
|
|
4941
5071
|
]).describe("Event type to emit"),
|
|
4942
5072
|
// phase_ready: emitted in dataflow mode (swp-ioc7) when a phase enters the ready set
|
|
4943
5073
|
// (deps satisfied, not inFlight, not yet complete) — BEFORE invoking the specialist.
|
|
4944
|
-
phase:
|
|
4945
|
-
targetOtter:
|
|
4946
|
-
success: boolCoerce(
|
|
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(
|
|
4947
5077
|
'For agent_invoke_complete: did the invocation succeed? (boolean; string "true"/"false" also accepted for caller tolerance)'
|
|
4948
5078
|
),
|
|
4949
|
-
otter:
|
|
4950
|
-
durationSec:
|
|
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)")
|
|
4951
5081
|
},
|
|
4952
5082
|
async ({ type, phase, targetOtter, success, otter, durationSec }) => res(handleEmitEvent({ type, phase, targetOtter, success, otter, durationSec }))
|
|
4953
5083
|
);
|
|
4954
5084
|
}
|
|
4955
5085
|
|
|
4956
5086
|
// src/tools/safe-write.ts
|
|
4957
|
-
var
|
|
5087
|
+
var import_zod15 = require("zod");
|
|
4958
5088
|
var import_fs9 = require("fs");
|
|
4959
5089
|
var import_path9 = require("path");
|
|
4960
5090
|
var import_telemetry2 = require("@stackwright-pro/telemetry");
|
|
@@ -5450,10 +5580,10 @@ function registerSafeWriteTools(server2) {
|
|
|
5450
5580
|
"stackwright_pro_safe_write",
|
|
5451
5581
|
DESC,
|
|
5452
5582
|
{
|
|
5453
|
-
callerOtter:
|
|
5454
|
-
filePath:
|
|
5455
|
-
content:
|
|
5456
|
-
createDirectories: boolCoerce(
|
|
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(
|
|
5457
5587
|
"Create parent directories if they don't exist. Default: true"
|
|
5458
5588
|
)
|
|
5459
5589
|
},
|
|
@@ -5470,9 +5600,12 @@ function registerSafeWriteTools(server2) {
|
|
|
5470
5600
|
}
|
|
5471
5601
|
|
|
5472
5602
|
// src/tools/auth.ts
|
|
5473
|
-
var
|
|
5603
|
+
var import_zod16 = require("zod");
|
|
5474
5604
|
var import_fs10 = require("fs");
|
|
5475
5605
|
var import_path10 = require("path");
|
|
5606
|
+
function normalizeProviderSlug(slug) {
|
|
5607
|
+
return slug.replace(/-/g, "_");
|
|
5608
|
+
}
|
|
5476
5609
|
function buildHierarchy(roles) {
|
|
5477
5610
|
const h = {};
|
|
5478
5611
|
for (let i = 0; i < roles.length - 1; i++) {
|
|
@@ -5727,13 +5860,12 @@ ${hierarchyToYaml(hierarchy, " ")}`;
|
|
|
5727
5860
|
const ocspEndpoint = params.cacOcspEndpoint ?? "https://ocsp.disa.mil";
|
|
5728
5861
|
const certHeader = params.cacCertHeader ?? "X-SSL-Client-Cert";
|
|
5729
5862
|
return `# stackwright.auth.yml \u2014 generated by Auth Otter
|
|
5730
|
-
|
|
5731
|
-
${
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
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}
|
|
5737
5869
|
${rbacSection}
|
|
5738
5870
|
protectedRoutes:
|
|
5739
5871
|
${routeLines}
|
|
@@ -5744,14 +5876,13 @@ ${auditSection}
|
|
|
5744
5876
|
const scopes2 = params.oidcScopes ?? "openid profile email";
|
|
5745
5877
|
const roleClaim = params.oidcRoleClaim ?? "roles";
|
|
5746
5878
|
return `# stackwright.auth.yml \u2014 generated by Auth Otter
|
|
5747
|
-
|
|
5879
|
+
type: oidc
|
|
5748
5880
|
${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
roleClaim: ${roleClaim}
|
|
5881
|
+
discoveryUrl: \${OIDC_DISCOVERY_URL}
|
|
5882
|
+
clientId: \${OIDC_CLIENT_ID}
|
|
5883
|
+
clientSecret: \${OIDC_CLIENT_SECRET}
|
|
5884
|
+
scopes: ${scopes2}
|
|
5885
|
+
roleClaim: ${roleClaim}
|
|
5755
5886
|
${rbacSection}
|
|
5756
5887
|
protectedRoutes:
|
|
5757
5888
|
${routeLines}
|
|
@@ -5760,14 +5891,13 @@ ${auditSection}
|
|
|
5760
5891
|
}
|
|
5761
5892
|
const scopes = params.oauth2Scopes ?? "read write";
|
|
5762
5893
|
return `# stackwright.auth.yml \u2014 generated by Auth Otter
|
|
5763
|
-
|
|
5894
|
+
type: oauth2
|
|
5764
5895
|
${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
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}
|
|
5771
5901
|
${rbacSection}
|
|
5772
5902
|
protectedRoutes:
|
|
5773
5903
|
${routeLines}
|
|
@@ -5974,14 +6104,13 @@ ${hierarchyToYaml(hierarchy, " ")}`;
|
|
|
5974
6104
|
const ocspEndpoint = params.cacOcspEndpoint ?? "https://ocsp.disa.mil";
|
|
5975
6105
|
const certHeader = params.cacCertHeader ?? "X-SSL-Client-Cert";
|
|
5976
6106
|
return `# stackwright.auth.yml \u2014 generated by Auth Otter
|
|
5977
|
-
|
|
6107
|
+
type: pki
|
|
5978
6108
|
devOnly: true
|
|
5979
|
-
${
|
|
5980
|
-
|
|
5981
|
-
|
|
5982
|
-
|
|
5983
|
-
|
|
5984
|
-
certHeader: ${certHeader}
|
|
6109
|
+
${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
|
|
6110
|
+
caBundle: ${caBundle}
|
|
6111
|
+
edipiLookup: ${edipiLookup}
|
|
6112
|
+
ocspEndpoint: ${ocspEndpoint}
|
|
6113
|
+
certHeader: ${certHeader}
|
|
5985
6114
|
${rbacSection}
|
|
5986
6115
|
protectedRoutes:
|
|
5987
6116
|
${routeLines}
|
|
@@ -5992,15 +6121,14 @@ ${auditSection}
|
|
|
5992
6121
|
const scopes2 = params.oidcScopes ?? "openid profile email";
|
|
5993
6122
|
const roleClaim = params.oidcRoleClaim ?? "roles";
|
|
5994
6123
|
return `# stackwright.auth.yml \u2014 generated by Auth Otter
|
|
5995
|
-
|
|
6124
|
+
type: oidc
|
|
5996
6125
|
devOnly: true
|
|
5997
6126
|
${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
|
|
5998
|
-
oidc
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
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}
|
|
6004
6132
|
${rbacSection}
|
|
6005
6133
|
protectedRoutes:
|
|
6006
6134
|
${routeLines}
|
|
@@ -6009,15 +6137,14 @@ ${auditSection}
|
|
|
6009
6137
|
}
|
|
6010
6138
|
const scopes = params.oauth2Scopes ?? "read write";
|
|
6011
6139
|
return `# stackwright.auth.yml \u2014 generated by Auth Otter
|
|
6012
|
-
|
|
6140
|
+
type: oauth2
|
|
6013
6141
|
devOnly: true
|
|
6014
6142
|
${providerLine}${useProxy ? "proxy" : "middleware"}: ./${useProxy ? "proxy" : "middleware"}.ts
|
|
6015
|
-
oauth2
|
|
6016
|
-
|
|
6017
|
-
|
|
6018
|
-
|
|
6019
|
-
|
|
6020
|
-
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}
|
|
6021
6148
|
${rbacSection}
|
|
6022
6149
|
protectedRoutes:
|
|
6023
6150
|
${routeLines}
|
|
@@ -6087,6 +6214,10 @@ function updatePackageJsonScripts(existingJson, roles, mockUsers) {
|
|
|
6087
6214
|
return JSON.stringify(pkg, null, 2) + "\n";
|
|
6088
6215
|
}
|
|
6089
6216
|
async function configureAuthHandler(params, cwd) {
|
|
6217
|
+
params = {
|
|
6218
|
+
...params,
|
|
6219
|
+
provider: params.provider != null ? normalizeProviderSlug(params.provider) : void 0
|
|
6220
|
+
};
|
|
6090
6221
|
const {
|
|
6091
6222
|
method,
|
|
6092
6223
|
provider,
|
|
@@ -6338,45 +6469,46 @@ function registerAuthTools(server2) {
|
|
|
6338
6469
|
"stackwright_pro_configure_auth",
|
|
6339
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.",
|
|
6340
6471
|
{
|
|
6341
|
-
method:
|
|
6342
|
-
|
|
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(),
|
|
6343
6475
|
// CAC
|
|
6344
|
-
cacCaBundle:
|
|
6345
|
-
cacEdipiLookup:
|
|
6346
|
-
cacOcspEndpoint:
|
|
6347
|
-
cacCertHeader:
|
|
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(),
|
|
6348
6480
|
// OIDC
|
|
6349
|
-
oidcDiscoveryUrl:
|
|
6350
|
-
oidcClientId:
|
|
6351
|
-
oidcClientSecret:
|
|
6352
|
-
oidcScopes:
|
|
6353
|
-
oidcRoleClaim:
|
|
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(),
|
|
6354
6486
|
// OAuth2
|
|
6355
|
-
oauth2AuthUrl:
|
|
6356
|
-
oauth2TokenUrl:
|
|
6357
|
-
oauth2ClientId:
|
|
6358
|
-
oauth2ClientSecret:
|
|
6359
|
-
oauth2Scopes:
|
|
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(),
|
|
6360
6492
|
// RBAC
|
|
6361
|
-
rbacRoles: jsonCoerce(
|
|
6362
|
-
rbacDefaultRole:
|
|
6493
|
+
rbacRoles: jsonCoerce(import_zod16.z.array(import_zod16.z.string()).optional()),
|
|
6494
|
+
rbacDefaultRole: import_zod16.z.string().optional(),
|
|
6363
6495
|
// Audit
|
|
6364
|
-
auditEnabled: boolCoerce(
|
|
6365
|
-
auditRetentionDays: numCoerce(
|
|
6496
|
+
auditEnabled: boolCoerce(import_zod16.z.boolean().optional()),
|
|
6497
|
+
auditRetentionDays: numCoerce(import_zod16.z.number().int().positive().optional()),
|
|
6366
6498
|
// Routes — accepts bare strings (backward-compat) or per-route objects (swp-owu0)
|
|
6367
6499
|
protectedRoutes: jsonCoerce(
|
|
6368
|
-
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
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() })
|
|
6372
6504
|
])
|
|
6373
6505
|
).optional()
|
|
6374
6506
|
),
|
|
6375
6507
|
// Injection for tests
|
|
6376
|
-
_cwd:
|
|
6377
|
-
devOnly: boolCoerce(
|
|
6378
|
-
mockUsers: jsonCoerce(
|
|
6379
|
-
nextMajorVersion: numCoerce(
|
|
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())
|
|
6380
6512
|
},
|
|
6381
6513
|
async (params) => {
|
|
6382
6514
|
const cwd = params._cwd ?? process.cwd();
|
|
@@ -6396,7 +6528,7 @@ var _checksums = /* @__PURE__ */ new Map([
|
|
|
6396
6528
|
],
|
|
6397
6529
|
[
|
|
6398
6530
|
"stackwright-pro-auth-otter.json",
|
|
6399
|
-
"
|
|
6531
|
+
"eee511fa214203ce88d51996c6b1b483b6ad3a0ae474cc7be5d380fdbbc43bb1"
|
|
6400
6532
|
],
|
|
6401
6533
|
[
|
|
6402
6534
|
"stackwright-pro-dashboard-otter.json",
|
|
@@ -6432,7 +6564,7 @@ var _checksums = /* @__PURE__ */ new Map([
|
|
|
6432
6564
|
],
|
|
6433
6565
|
[
|
|
6434
6566
|
"stackwright-pro-polish-otter.json",
|
|
6435
|
-
"
|
|
6567
|
+
"4b8223d89af7f92b9051fee7bb29fc4b1ee2a5a9ab87e8e67a6d8be6122fa029"
|
|
6436
6568
|
],
|
|
6437
6569
|
[
|
|
6438
6570
|
"stackwright-pro-qa-otter.json",
|
|
@@ -6444,7 +6576,7 @@ var _checksums = /* @__PURE__ */ new Map([
|
|
|
6444
6576
|
],
|
|
6445
6577
|
[
|
|
6446
6578
|
"stackwright-pro-theme-otter.json",
|
|
6447
|
-
"
|
|
6579
|
+
"afb47f8381907145c0e098bdcaae4dd9f5c4ff825a8e88d00a218d2f6858820b"
|
|
6448
6580
|
],
|
|
6449
6581
|
[
|
|
6450
6582
|
"stackwright-services-otter.json",
|
|
@@ -6665,7 +6797,7 @@ function registerIntegrityTools(server2) {
|
|
|
6665
6797
|
}
|
|
6666
6798
|
|
|
6667
6799
|
// src/tools/domain.ts
|
|
6668
|
-
var
|
|
6800
|
+
var import_zod17 = require("zod");
|
|
6669
6801
|
var import_fs12 = require("fs");
|
|
6670
6802
|
var import_path12 = require("path");
|
|
6671
6803
|
function handleListCollections(input) {
|
|
@@ -7051,7 +7183,7 @@ function registerDomainTools(server2) {
|
|
|
7051
7183
|
"stackwright_pro_resolve_data_strategy",
|
|
7052
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.",
|
|
7053
7185
|
{
|
|
7054
|
-
strategy:
|
|
7186
|
+
strategy: import_zod17.z.string().describe(
|
|
7055
7187
|
'The data-1 answer value: "pulse-fast", "isr-fast", "isr-standard", or "isr-slow"'
|
|
7056
7188
|
)
|
|
7057
7189
|
},
|
|
@@ -7061,7 +7193,7 @@ function registerDomainTools(server2) {
|
|
|
7061
7193
|
"stackwright_pro_validate_workflow",
|
|
7062
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.",
|
|
7063
7195
|
{
|
|
7064
|
-
workflow: jsonCoerce(
|
|
7196
|
+
workflow: jsonCoerce(import_zod17.z.record(import_zod17.z.string(), import_zod17.z.unknown()).optional()).describe(
|
|
7065
7197
|
"Parsed workflow object. If omitted, reads from .stackwright/artifacts/workflow-config.json"
|
|
7066
7198
|
)
|
|
7067
7199
|
},
|
|
@@ -7070,7 +7202,7 @@ function registerDomainTools(server2) {
|
|
|
7070
7202
|
}
|
|
7071
7203
|
|
|
7072
7204
|
// src/tools/type-schemas.ts
|
|
7073
|
-
var
|
|
7205
|
+
var import_zod18 = require("zod");
|
|
7074
7206
|
function buildTypeSchemaSummary() {
|
|
7075
7207
|
return {
|
|
7076
7208
|
version: "1.0",
|
|
@@ -7147,7 +7279,7 @@ function registerTypeSchemasTool(server2) {
|
|
|
7147
7279
|
"stackwright_pro_get_type_schemas",
|
|
7148
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.",
|
|
7149
7281
|
{
|
|
7150
|
-
format:
|
|
7282
|
+
format: import_zod18.z.enum(["full", "domains-only"]).optional().default("full").describe("full = complete summary with all fields; domains-only = just domain names")
|
|
7151
7283
|
},
|
|
7152
7284
|
async ({ format }) => {
|
|
7153
7285
|
const summary = buildTypeSchemaSummary();
|
|
@@ -7163,7 +7295,7 @@ function registerTypeSchemasTool(server2) {
|
|
|
7163
7295
|
var fs2 = __toESM(require("fs"));
|
|
7164
7296
|
var os = __toESM(require("os"));
|
|
7165
7297
|
var path3 = __toESM(require("path"));
|
|
7166
|
-
var
|
|
7298
|
+
var import_zod19 = require("zod");
|
|
7167
7299
|
var import_js_yaml3 = require("js-yaml");
|
|
7168
7300
|
var import_cli = require("@stackwright/cli");
|
|
7169
7301
|
var import_types4 = require("@stackwright-pro/types");
|
|
@@ -7275,10 +7407,10 @@ function registerProPageTools(server2) {
|
|
|
7275
7407
|
"stackwright_pro_write_page",
|
|
7276
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.",
|
|
7277
7409
|
{
|
|
7278
|
-
projectRoot:
|
|
7279
|
-
slug:
|
|
7280
|
-
content:
|
|
7281
|
-
locale:
|
|
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(
|
|
7282
7414
|
'BCP 47 locale tag (e.g. "fr", "de"). If provided, writes content.<locale>.yml instead of content.yml.'
|
|
7283
7415
|
)
|
|
7284
7416
|
},
|
|
@@ -7528,7 +7660,7 @@ function registerScaffoldCleanupTools(server2) {
|
|
|
7528
7660
|
}
|
|
7529
7661
|
|
|
7530
7662
|
// src/tools/contrast.ts
|
|
7531
|
-
var
|
|
7663
|
+
var import_zod20 = require("zod");
|
|
7532
7664
|
function linearizeChannel(c255) {
|
|
7533
7665
|
const c = c255 / 255;
|
|
7534
7666
|
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
@@ -7700,8 +7832,8 @@ function registerContrastTools(server2) {
|
|
|
7700
7832
|
"stackwright_pro_check_contrast",
|
|
7701
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%").',
|
|
7702
7834
|
{
|
|
7703
|
-
fg:
|
|
7704
|
-
bg:
|
|
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")
|
|
7705
7837
|
},
|
|
7706
7838
|
async ({ fg, bg }) => {
|
|
7707
7839
|
let result;
|
|
@@ -7731,8 +7863,8 @@ function registerContrastTools(server2) {
|
|
|
7731
7863
|
"stackwright_pro_derive_accessible_palette",
|
|
7732
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%").',
|
|
7733
7865
|
{
|
|
7734
|
-
seed:
|
|
7735
|
-
targetRatio: numCoerce(
|
|
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(
|
|
7736
7868
|
"Minimum required contrast ratio (default 4.5 for WCAG AA)"
|
|
7737
7869
|
)
|
|
7738
7870
|
},
|
|
@@ -7767,7 +7899,7 @@ function registerContrastTools(server2) {
|
|
|
7767
7899
|
}
|
|
7768
7900
|
|
|
7769
7901
|
// src/tools/compile.ts
|
|
7770
|
-
var
|
|
7902
|
+
var import_zod21 = require("zod");
|
|
7771
7903
|
var import_fs14 = __toESM(require("fs"));
|
|
7772
7904
|
var import_path14 = __toESM(require("path"));
|
|
7773
7905
|
var import_server = require("@stackwright-pro/pulse/server");
|
|
@@ -7813,7 +7945,7 @@ async function tryOssCompile(fn, ctx, extra) {
|
|
|
7813
7945
|
}
|
|
7814
7946
|
}
|
|
7815
7947
|
function registerCompileTools(server2) {
|
|
7816
|
-
const projectRootArg =
|
|
7948
|
+
const projectRootArg = import_zod21.z.string().optional().describe("Absolute path to project root (defaults to cwd)");
|
|
7817
7949
|
server2.tool(
|
|
7818
7950
|
"stackwright_pro_compile_collections",
|
|
7819
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.",
|
|
@@ -7989,7 +8121,7 @@ ${results.join("\n")}`;
|
|
|
7989
8121
|
"stackwright_pro_compile_page",
|
|
7990
8122
|
"Compile a single page by slug. Delegates to compilePage from @stackwright/build-scripts installed in the project.",
|
|
7991
8123
|
{
|
|
7992
|
-
slug:
|
|
8124
|
+
slug: import_zod21.z.string().describe('Page slug (relative path under pages/, e.g. "dashboard")'),
|
|
7993
8125
|
projectRoot: projectRootArg
|
|
7994
8126
|
},
|
|
7995
8127
|
async ({ slug, projectRoot }) => {
|
|
@@ -8009,7 +8141,7 @@ ${results.join("\n")}`;
|
|
|
8009
8141
|
}
|
|
8010
8142
|
|
|
8011
8143
|
// src/tools/strip-legacy-integrations.ts
|
|
8012
|
-
var
|
|
8144
|
+
var import_zod22 = require("zod");
|
|
8013
8145
|
var import_fs15 = require("fs");
|
|
8014
8146
|
var import_path15 = require("path");
|
|
8015
8147
|
function handleStripLegacyIntegrations(input) {
|
|
@@ -8072,7 +8204,7 @@ function registerStripLegacyIntegrationsTool(server2) {
|
|
|
8072
8204
|
"stackwright_pro_strip_legacy_integrations",
|
|
8073
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.",
|
|
8074
8206
|
{
|
|
8075
|
-
projectRoot:
|
|
8207
|
+
projectRoot: import_zod22.z.string().describe("Absolute path to the project root directory")
|
|
8076
8208
|
},
|
|
8077
8209
|
async ({ projectRoot }) => {
|
|
8078
8210
|
const result = handleStripLegacyIntegrations({ projectRoot });
|
|
@@ -8084,7 +8216,7 @@ function registerStripLegacyIntegrationsTool(server2) {
|
|
|
8084
8216
|
}
|
|
8085
8217
|
|
|
8086
8218
|
// src/tools/emitters.ts
|
|
8087
|
-
var
|
|
8219
|
+
var import_zod23 = require("zod");
|
|
8088
8220
|
var import_fs16 = require("fs");
|
|
8089
8221
|
var import_path16 = require("path");
|
|
8090
8222
|
var import_js_yaml4 = __toESM(require("js-yaml"));
|
|
@@ -8143,7 +8275,7 @@ Call this tool, then write both files with stackwright_pro_safe_write:
|
|
|
8143
8275
|
|
|
8144
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}`,
|
|
8145
8277
|
{
|
|
8146
|
-
cwd:
|
|
8278
|
+
cwd: import_zod23.z.string().describe(
|
|
8147
8279
|
"Absolute path to the project root containing stackwright.integrations.yml and optionally services/*.yml"
|
|
8148
8280
|
)
|
|
8149
8281
|
},
|
|
@@ -8190,8 +8322,8 @@ mapProvider options:
|
|
|
8190
8322
|
|
|
8191
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}`,
|
|
8192
8324
|
{
|
|
8193
|
-
cwd:
|
|
8194
|
-
mapProvider:
|
|
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(
|
|
8195
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."
|
|
8196
8328
|
)
|
|
8197
8329
|
},
|
|
@@ -8232,7 +8364,7 @@ Workflow:
|
|
|
8232
8364
|
|
|
8233
8365
|
This is the third concrete instance of the swp-zf9y deterministic emitter pattern. Refs: swp-phkh, swp-zf9y. ${PORTS_DESC}`,
|
|
8234
8366
|
{
|
|
8235
|
-
cwd:
|
|
8367
|
+
cwd: import_zod23.z.string().describe("Absolute path to the project root containing stackwright.integrations.yml")
|
|
8236
8368
|
},
|
|
8237
8369
|
async ({ cwd }) => {
|
|
8238
8370
|
const integrations = readIntegrations(cwd);
|
|
@@ -8261,7 +8393,7 @@ This is the third concrete instance of the swp-zf9y deterministic emitter patter
|
|
|
8261
8393
|
}
|
|
8262
8394
|
|
|
8263
8395
|
// src/tools/list-specs.ts
|
|
8264
|
-
var
|
|
8396
|
+
var import_zod24 = require("zod");
|
|
8265
8397
|
var import_fs17 = require("fs");
|
|
8266
8398
|
var import_path17 = require("path");
|
|
8267
8399
|
var STRIP_SUFFIXES = ["-openapi", "-asyncapi", "-api", "-spec"];
|
|
@@ -8326,7 +8458,7 @@ function registerListSpecsTool(server2) {
|
|
|
8326
8458
|
"stackwright_pro_list_specs",
|
|
8327
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.",
|
|
8328
8460
|
{
|
|
8329
|
-
projectRoot:
|
|
8461
|
+
projectRoot: import_zod24.z.string().describe("Absolute path to the project root directory")
|
|
8330
8462
|
},
|
|
8331
8463
|
async ({ projectRoot }) => {
|
|
8332
8464
|
const result = handleListSpecs({ projectRoot });
|
|
@@ -8338,7 +8470,7 @@ function registerListSpecsTool(server2) {
|
|
|
8338
8470
|
}
|
|
8339
8471
|
|
|
8340
8472
|
// src/tools/consolidate-integrations.ts
|
|
8341
|
-
var
|
|
8473
|
+
var import_zod25 = require("zod");
|
|
8342
8474
|
var import_fs18 = require("fs");
|
|
8343
8475
|
var import_proper_lockfile2 = require("proper-lockfile");
|
|
8344
8476
|
var import_path18 = require("path");
|
|
@@ -8459,7 +8591,7 @@ function registerConsolidateIntegrationsTool(server2) {
|
|
|
8459
8591
|
"no per-spec artifacts are found."
|
|
8460
8592
|
].join(" "),
|
|
8461
8593
|
{
|
|
8462
|
-
projectRoot:
|
|
8594
|
+
projectRoot: import_zod25.z.string().describe("Absolute path to the project root directory")
|
|
8463
8595
|
},
|
|
8464
8596
|
async ({ projectRoot }) => {
|
|
8465
8597
|
try {
|
|
@@ -8517,7 +8649,7 @@ var package_default = {
|
|
|
8517
8649
|
"test:coverage": "vitest run --coverage"
|
|
8518
8650
|
},
|
|
8519
8651
|
name: "@stackwright-pro/mcp",
|
|
8520
|
-
version: "0.2.0-alpha.
|
|
8652
|
+
version: "0.2.0-alpha.111",
|
|
8521
8653
|
description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
|
|
8522
8654
|
license: "SEE LICENSE IN LICENSE",
|
|
8523
8655
|
main: "./dist/server.js",
|
|
@@ -8573,6 +8705,7 @@ registerOrchestrationTools(server);
|
|
|
8573
8705
|
registerPipelineTools(server);
|
|
8574
8706
|
registerSafeWriteTools(server);
|
|
8575
8707
|
registerAuthTools(server);
|
|
8708
|
+
registerReadAuthManifestsTool(server);
|
|
8576
8709
|
registerIntegrityTools(server);
|
|
8577
8710
|
registerArtifactSigningTools(server);
|
|
8578
8711
|
registerDomainTools(server);
|