@stackwright-pro/mcp 0.2.0-alpha.90 → 0.2.0-alpha.92
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 +5 -5
- package/dist/integrity.js.map +1 -1
- package/dist/integrity.mjs +5 -5
- package/dist/integrity.mjs.map +1 -1
- package/dist/server.js +104 -36
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +104 -36
- package/dist/server.mjs.map +1 -1
- package/dist/tools/type-schemas.js +1 -1
- package/dist/tools/type-schemas.js.map +1 -1
- package/dist/tools/type-schemas.mjs +1 -1
- package/dist/tools/type-schemas.mjs.map +1 -1
- package/package.json +3 -3
package/dist/server.mjs
CHANGED
|
@@ -1595,6 +1595,9 @@ var OTTER_NAME_TO_PHASE = [
|
|
|
1595
1595
|
["dashboard", "dashboard"],
|
|
1596
1596
|
["data", "data"],
|
|
1597
1597
|
["page", "pages"],
|
|
1598
|
+
// swp-4071: workflow-otter renamed to form-wizard-otter; keep 'workflow' for
|
|
1599
|
+
// any in-flight session that still uses the old name (belt-and-suspenders)
|
|
1600
|
+
["form-wizard", "workflow"],
|
|
1598
1601
|
["workflow", "workflow"],
|
|
1599
1602
|
["services", "services"],
|
|
1600
1603
|
["polish", "polish"],
|
|
@@ -1609,7 +1612,7 @@ var PHASE_TO_OTTER = {
|
|
|
1609
1612
|
pages: "stackwright-pro-page-otter",
|
|
1610
1613
|
dashboard: "stackwright-pro-dashboard-otter",
|
|
1611
1614
|
data: "stackwright-pro-data-otter",
|
|
1612
|
-
workflow: "stackwright-pro-
|
|
1615
|
+
workflow: "stackwright-pro-form-wizard-otter",
|
|
1613
1616
|
services: "stackwright-services-otter",
|
|
1614
1617
|
polish: "stackwright-pro-polish-otter",
|
|
1615
1618
|
geo: "stackwright-pro-geo-otter"
|
|
@@ -2757,7 +2760,7 @@ var PHASE_TO_OTTER2 = {
|
|
|
2757
2760
|
data: "stackwright-pro-data-otter",
|
|
2758
2761
|
pages: "stackwright-pro-page-otter",
|
|
2759
2762
|
dashboard: "stackwright-pro-dashboard-otter",
|
|
2760
|
-
workflow: "stackwright-pro-
|
|
2763
|
+
workflow: "stackwright-pro-form-wizard-otter",
|
|
2761
2764
|
services: "stackwright-services-otter",
|
|
2762
2765
|
polish: "stackwright-pro-polish-otter",
|
|
2763
2766
|
geo: "stackwright-pro-geo-otter"
|
|
@@ -3470,7 +3473,7 @@ var PHASE_ARTIFACT_SCHEMA = {
|
|
|
3470
3473
|
workflow: JSON.stringify(
|
|
3471
3474
|
{
|
|
3472
3475
|
version: "1.0",
|
|
3473
|
-
generatedBy: "stackwright-pro-
|
|
3476
|
+
generatedBy: "stackwright-pro-form-wizard-otter",
|
|
3474
3477
|
// Root key is `workflow` — NOT `workflowConfig` (see swp-k7cl)
|
|
3475
3478
|
workflow: {
|
|
3476
3479
|
id: "procurement-approval",
|
|
@@ -3680,6 +3683,57 @@ function handleValidateArtifact(input) {
|
|
|
3680
3683
|
const issues = result.error.issues.slice(0, 3).map((i) => `${i.path.join(".")}: ${i.message}`).join("; ");
|
|
3681
3684
|
return { success: false, error: { message: issues } };
|
|
3682
3685
|
}
|
|
3686
|
+
const rbacRoles = authConfig["rbacRoles"];
|
|
3687
|
+
const rbacDefaultRole = authConfig["rbacDefaultRole"];
|
|
3688
|
+
const protectedRoutes = authConfig["protectedRoutes"];
|
|
3689
|
+
if (Array.isArray(rbacRoles) && rbacRoles.length > 2 && Array.isArray(protectedRoutes) && protectedRoutes.length > 0 && typeof rbacDefaultRole === "string") {
|
|
3690
|
+
const uniqueRoles = new Set(
|
|
3691
|
+
protectedRoutes.map(
|
|
3692
|
+
(r) => typeof r === "string" ? rbacDefaultRole : r.requiredRole ?? rbacDefaultRole
|
|
3693
|
+
)
|
|
3694
|
+
);
|
|
3695
|
+
if (uniqueRoles.size === 1 && uniqueRoles.has(rbacDefaultRole)) {
|
|
3696
|
+
return {
|
|
3697
|
+
success: false,
|
|
3698
|
+
error: {
|
|
3699
|
+
message: `RBAC theatre detected: all ${protectedRoutes.length} protectedRoutes require '${rbacDefaultRole}' (the defaultRole), but ${rbacRoles.length} roles are defined. This defeats the RBAC hierarchy. Each route MUST have the minimum role required for its function. See auth-otter PER-ROUTE RBAC GRANULARITY section.`
|
|
3700
|
+
}
|
|
3701
|
+
};
|
|
3702
|
+
}
|
|
3703
|
+
}
|
|
3704
|
+
return { success: true };
|
|
3705
|
+
},
|
|
3706
|
+
// swp-4071 — opt-in cross-reference validator for the services phase.
|
|
3707
|
+
// If workflow-config exists and declares serviceHooks, every hook ref must resolve
|
|
3708
|
+
// to a flow or state-machine in this services-config artifact.
|
|
3709
|
+
// Skips gracefully when wizard-otter didn't run (Pro-only install) or declared no hooks.
|
|
3710
|
+
services: (artifact2) => {
|
|
3711
|
+
const workflowArtifactPath = join4(cwd, ".stackwright", "artifacts", "workflow-config.json");
|
|
3712
|
+
if (!existsSync5(workflowArtifactPath)) {
|
|
3713
|
+
return { success: true };
|
|
3714
|
+
}
|
|
3715
|
+
let workflowArtifact;
|
|
3716
|
+
try {
|
|
3717
|
+
workflowArtifact = JSON.parse(readFileSync4(workflowArtifactPath, "utf-8"));
|
|
3718
|
+
} catch {
|
|
3719
|
+
return { success: true };
|
|
3720
|
+
}
|
|
3721
|
+
const declaredHooks = workflowArtifact.serviceHooks ?? [];
|
|
3722
|
+
if (declaredHooks.length === 0) {
|
|
3723
|
+
return { success: true };
|
|
3724
|
+
}
|
|
3725
|
+
const flows = artifact2["flows"] ?? [];
|
|
3726
|
+
const workflows = artifact2["workflows"] ?? [];
|
|
3727
|
+
const flowNames = /* @__PURE__ */ new Set([...flows.map((f) => f.name), ...workflows.map((w) => w.name)]);
|
|
3728
|
+
const unresolved = declaredHooks.filter((h) => !flowNames.has(h.ref));
|
|
3729
|
+
if (unresolved.length > 0) {
|
|
3730
|
+
return {
|
|
3731
|
+
success: false,
|
|
3732
|
+
error: {
|
|
3733
|
+
message: `Workflow declared ${declaredHooks.length} service hook(s) but ${unresolved.length} unresolved by services-config: ` + unresolved.map((h) => `${h.ref} (${h.kind ?? "unknown"}: ${h.purpose ?? "no purpose"})`).join("; ") + ". Either add matching flows to services-config OR remove the hooks from the workflow YAML."
|
|
3734
|
+
}
|
|
3735
|
+
};
|
|
3736
|
+
}
|
|
3683
3737
|
return { success: true };
|
|
3684
3738
|
}
|
|
3685
3739
|
};
|
|
@@ -3919,7 +3973,7 @@ var OTTER_WRITE_ALLOWLISTS = {
|
|
|
3919
3973
|
{ prefix: "pages/", suffix: "/content.yaml", description: "Dashboard content YAML" },
|
|
3920
3974
|
{ prefix: ".stackwright/artifacts/", suffix: ".json", description: "Dashboard manifest" }
|
|
3921
3975
|
],
|
|
3922
|
-
"stackwright-pro-
|
|
3976
|
+
"stackwright-pro-form-wizard-otter": [
|
|
3923
3977
|
{ prefix: "workflows/", suffix: ".yml", description: "Workflow definition" },
|
|
3924
3978
|
{ prefix: "workflows/", suffix: ".yaml", description: "Workflow definition" },
|
|
3925
3979
|
{ prefix: ".stackwright/artifacts/", suffix: ".json", description: "Workflow config" }
|
|
@@ -4321,9 +4375,14 @@ function hierarchyToYaml(hierarchy, indent) {
|
|
|
4321
4375
|
function rolesToYaml(roles, indent) {
|
|
4322
4376
|
return roles.map((r) => `${indent}- ${r}`).join("\n");
|
|
4323
4377
|
}
|
|
4324
|
-
function
|
|
4325
|
-
return routes.map(
|
|
4326
|
-
|
|
4378
|
+
function normalizeRoutes(routes, defaultRole) {
|
|
4379
|
+
return routes.map(
|
|
4380
|
+
(r) => typeof r === "string" ? { pattern: r, requiredRole: defaultRole } : { pattern: r.pattern, requiredRole: r.requiredRole ?? defaultRole }
|
|
4381
|
+
);
|
|
4382
|
+
}
|
|
4383
|
+
function routesToYaml(routes, indent) {
|
|
4384
|
+
return routes.map((r) => `${indent}- pattern: ${r.pattern}
|
|
4385
|
+
${indent} requiredRole: ${r.requiredRole}`).join("\n");
|
|
4327
4386
|
}
|
|
4328
4387
|
function detectNextMajorVersion(cwd) {
|
|
4329
4388
|
try {
|
|
@@ -4367,9 +4426,10 @@ function generateMiddlewareContent(method, params, roles, defaultRole, hierarchy
|
|
|
4367
4426
|
enabled: ${auditEnabled},
|
|
4368
4427
|
retentionDays: ${auditRetentionDays},
|
|
4369
4428
|
},`;
|
|
4370
|
-
const
|
|
4429
|
+
const patterns = protectedRoutes.map((r) => r.pattern);
|
|
4430
|
+
const routesBlock = ` protectedRoutes: ${JSON.stringify(patterns)},`;
|
|
4371
4431
|
const configBlock = `export const config = {
|
|
4372
|
-
matcher: ${JSON.stringify(
|
|
4432
|
+
matcher: ${JSON.stringify(patterns)},
|
|
4373
4433
|
};`;
|
|
4374
4434
|
if (method === "cac") {
|
|
4375
4435
|
const caBundle = params.cacCaBundle ?? "./certs/dod-ca-bundle.pem";
|
|
@@ -4452,9 +4512,10 @@ function generateProxyContent(method, params, roles, defaultRole, hierarchy, aud
|
|
|
4452
4512
|
enabled: ${auditEnabled},
|
|
4453
4513
|
retentionDays: ${auditRetentionDays},
|
|
4454
4514
|
},`;
|
|
4455
|
-
const
|
|
4515
|
+
const patterns = protectedRoutes.map((r) => r.pattern);
|
|
4516
|
+
const routesBlock = ` protectedRoutes: ${JSON.stringify(patterns)},`;
|
|
4456
4517
|
const configBlock = `export const config = {
|
|
4457
|
-
matcher: ${JSON.stringify(
|
|
4518
|
+
matcher: ${JSON.stringify(patterns)},
|
|
4458
4519
|
};`;
|
|
4459
4520
|
if (method === "cac") {
|
|
4460
4521
|
const caBundle = params.cacCaBundle ?? "./certs/dod-ca-bundle.pem";
|
|
@@ -4563,10 +4624,7 @@ ${hierarchyToYaml(hierarchy, " ")}`;
|
|
|
4563
4624
|
const auditSection = ` audit:
|
|
4564
4625
|
enabled: ${auditEnabled}
|
|
4565
4626
|
retentionDays: ${auditRetentionDays}`;
|
|
4566
|
-
const
|
|
4567
|
-
${routesToYaml(protectedRoutes, " ", defaultRole)}`.replace(/\n\s+,/g, "");
|
|
4568
|
-
const routeLines = protectedRoutes.map((r) => ` - pattern: ${r}
|
|
4569
|
-
requiredRole: ${defaultRole}`).join("\n");
|
|
4627
|
+
const routeLines = routesToYaml(protectedRoutes, " ");
|
|
4570
4628
|
const providerLine = params.provider ? ` provider: ${params.provider}
|
|
4571
4629
|
` : "";
|
|
4572
4630
|
if (method === "cac") {
|
|
@@ -4632,9 +4690,10 @@ function generateDevOnlyMiddlewareContent(method, params, roles, defaultRole, hi
|
|
|
4632
4690
|
enabled: ${auditEnabled},
|
|
4633
4691
|
retentionDays: ${auditRetentionDays},
|
|
4634
4692
|
},`;
|
|
4635
|
-
const
|
|
4693
|
+
const patterns = protectedRoutes.map((r) => r.pattern);
|
|
4694
|
+
const routesBlock = ` protectedRoutes: ${JSON.stringify(patterns)},`;
|
|
4636
4695
|
const configBlock = `export const config = {
|
|
4637
|
-
matcher: ${JSON.stringify(
|
|
4696
|
+
matcher: ${JSON.stringify(patterns)},
|
|
4638
4697
|
};`;
|
|
4639
4698
|
const devHeader = [
|
|
4640
4699
|
"// middleware.ts \u2014 generated by @stackwright-pro/auth-nextjs (dev-only mock)",
|
|
@@ -4721,9 +4780,10 @@ function generateDevOnlyProxyContent(method, params, roles, defaultRole, hierarc
|
|
|
4721
4780
|
enabled: ${auditEnabled},
|
|
4722
4781
|
retentionDays: ${auditRetentionDays},
|
|
4723
4782
|
},`;
|
|
4724
|
-
const
|
|
4783
|
+
const patterns = protectedRoutes.map((r) => r.pattern);
|
|
4784
|
+
const routesBlock = ` protectedRoutes: ${JSON.stringify(patterns)},`;
|
|
4725
4785
|
const configBlock = `export const config = {
|
|
4726
|
-
matcher: ${JSON.stringify(
|
|
4786
|
+
matcher: ${JSON.stringify(patterns)},
|
|
4727
4787
|
};`;
|
|
4728
4788
|
const devHeader = [
|
|
4729
4789
|
"// proxy.ts -- generated by @stackwright-pro/auth (Next.js >=16, dev-only mock)",
|
|
@@ -4810,8 +4870,8 @@ ${hierarchyToYaml(hierarchy, " ")}`;
|
|
|
4810
4870
|
const auditSection = ` audit:
|
|
4811
4871
|
enabled: ${auditEnabled}
|
|
4812
4872
|
retentionDays: ${auditRetentionDays}`;
|
|
4813
|
-
const routeLines = protectedRoutes.map((r) => ` - pattern: ${r}
|
|
4814
|
-
requiredRole: ${
|
|
4873
|
+
const routeLines = protectedRoutes.map((r) => ` - pattern: ${r.pattern}
|
|
4874
|
+
requiredRole: ${r.requiredRole}`).join("\n");
|
|
4815
4875
|
const providerLine = params.provider ? ` provider: ${params.provider}
|
|
4816
4876
|
` : "";
|
|
4817
4877
|
if (method === "cac") {
|
|
@@ -4944,6 +5004,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
4944
5004
|
} = params;
|
|
4945
5005
|
const roles = rbacRoles;
|
|
4946
5006
|
const defaultRole = params.rbacDefaultRole ?? roles[roles.length - 1];
|
|
5007
|
+
const normalizedRoutes = normalizeRoutes(protectedRoutes, defaultRole);
|
|
4947
5008
|
const hierarchy = buildHierarchy(roles);
|
|
4948
5009
|
const detectedVersion = params.nextMajorVersion ?? detectNextMajorVersion(cwd);
|
|
4949
5010
|
const useProxy = (detectedVersion ?? 0) >= 16;
|
|
@@ -4980,7 +5041,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
4980
5041
|
hierarchy,
|
|
4981
5042
|
auditEnabled,
|
|
4982
5043
|
auditRetentionDays,
|
|
4983
|
-
|
|
5044
|
+
normalizedRoutes
|
|
4984
5045
|
) : generateDevOnlyMiddlewareContent(
|
|
4985
5046
|
effectiveMethod,
|
|
4986
5047
|
params,
|
|
@@ -4989,7 +5050,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
4989
5050
|
hierarchy,
|
|
4990
5051
|
auditEnabled,
|
|
4991
5052
|
auditRetentionDays,
|
|
4992
|
-
|
|
5053
|
+
normalizedRoutes
|
|
4993
5054
|
) : useProxy ? generateProxyContent(
|
|
4994
5055
|
effectiveMethod,
|
|
4995
5056
|
params,
|
|
@@ -4998,7 +5059,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
4998
5059
|
hierarchy,
|
|
4999
5060
|
auditEnabled,
|
|
5000
5061
|
auditRetentionDays,
|
|
5001
|
-
|
|
5062
|
+
normalizedRoutes
|
|
5002
5063
|
) : generateMiddlewareContent(
|
|
5003
5064
|
effectiveMethod,
|
|
5004
5065
|
params,
|
|
@@ -5007,7 +5068,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
5007
5068
|
hierarchy,
|
|
5008
5069
|
auditEnabled,
|
|
5009
5070
|
auditRetentionDays,
|
|
5010
|
-
|
|
5071
|
+
normalizedRoutes
|
|
5011
5072
|
);
|
|
5012
5073
|
writeFileSync6(join6(cwd, conventionFile), authFileContent, "utf8");
|
|
5013
5074
|
filesWritten.push(conventionFile);
|
|
@@ -5105,7 +5166,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
5105
5166
|
hierarchy,
|
|
5106
5167
|
auditEnabled,
|
|
5107
5168
|
auditRetentionDays,
|
|
5108
|
-
|
|
5169
|
+
normalizedRoutes,
|
|
5109
5170
|
useProxy
|
|
5110
5171
|
) : generateYamlBlock(
|
|
5111
5172
|
effectiveMethod,
|
|
@@ -5115,7 +5176,7 @@ async function configureAuthHandler(params, cwd) {
|
|
|
5115
5176
|
hierarchy,
|
|
5116
5177
|
auditEnabled,
|
|
5117
5178
|
auditRetentionDays,
|
|
5118
|
-
|
|
5179
|
+
normalizedRoutes,
|
|
5119
5180
|
useProxy
|
|
5120
5181
|
);
|
|
5121
5182
|
const ymlPath = join6(cwd, "stackwright.yml");
|
|
@@ -5204,8 +5265,15 @@ function registerAuthTools(server2) {
|
|
|
5204
5265
|
// Audit
|
|
5205
5266
|
auditEnabled: boolCoerce(z15.boolean().optional()),
|
|
5206
5267
|
auditRetentionDays: numCoerce(z15.number().int().positive().optional()),
|
|
5207
|
-
// Routes
|
|
5208
|
-
protectedRoutes: jsonCoerce(
|
|
5268
|
+
// Routes — accepts bare strings (backward-compat) or per-route objects (swp-owu0)
|
|
5269
|
+
protectedRoutes: jsonCoerce(
|
|
5270
|
+
z15.array(
|
|
5271
|
+
z15.union([
|
|
5272
|
+
z15.string(),
|
|
5273
|
+
z15.object({ pattern: z15.string(), requiredRole: z15.string().optional() })
|
|
5274
|
+
])
|
|
5275
|
+
).optional()
|
|
5276
|
+
),
|
|
5209
5277
|
// Injection for tests
|
|
5210
5278
|
_cwd: z15.string().optional(),
|
|
5211
5279
|
devOnly: boolCoerce(z15.boolean().optional()),
|
|
@@ -5230,7 +5298,7 @@ var _checksums = /* @__PURE__ */ new Map([
|
|
|
5230
5298
|
],
|
|
5231
5299
|
[
|
|
5232
5300
|
"stackwright-pro-auth-otter.json",
|
|
5233
|
-
"
|
|
5301
|
+
"643344b88e42992e0467845fb0184d3932e115b85130fbc6a47a3175759678c8"
|
|
5234
5302
|
],
|
|
5235
5303
|
[
|
|
5236
5304
|
"stackwright-pro-dashboard-otter.json",
|
|
@@ -5252,6 +5320,10 @@ var _checksums = /* @__PURE__ */ new Map([
|
|
|
5252
5320
|
"stackwright-pro-foreman-otter.json",
|
|
5253
5321
|
"438b03d2c35f64536055c68b3a9044fe3b5e4f2889acde4500dd801fad724be1"
|
|
5254
5322
|
],
|
|
5323
|
+
[
|
|
5324
|
+
"stackwright-pro-form-wizard-otter.json",
|
|
5325
|
+
"3dffa3ef2d2ef057578391f784cbea779d768e87d98321894ea5bcd9e3ab7e60"
|
|
5326
|
+
],
|
|
5255
5327
|
[
|
|
5256
5328
|
"stackwright-pro-geo-otter.json",
|
|
5257
5329
|
"2ec83c26a08c413d9553ff8b8f0f0f643c1a8da043741b356e27106cad78f05f"
|
|
@@ -5272,10 +5344,6 @@ var _checksums = /* @__PURE__ */ new Map([
|
|
|
5272
5344
|
"stackwright-pro-theme-otter.json",
|
|
5273
5345
|
"fe10108e3ba67106751ea662f512bb5f4eb58f7abda26880ef4cf6b0f9feb944"
|
|
5274
5346
|
],
|
|
5275
|
-
[
|
|
5276
|
-
"stackwright-pro-workflow-otter.json",
|
|
5277
|
-
"5f6209fadc1355580e2455a16386f06bd7d5814f047b2dd5b33800abf6a48ff8"
|
|
5278
|
-
],
|
|
5279
5347
|
[
|
|
5280
5348
|
"stackwright-services-otter.json",
|
|
5281
5349
|
"c013d7fc2475e62d0af54d57bc988182feee7766bac0edf841cbfad5c73e9261"
|
|
@@ -5919,7 +5987,7 @@ function buildTypeSchemaSummary() {
|
|
|
5919
5987
|
"TransitionConditionSchema",
|
|
5920
5988
|
"PersistenceSchema"
|
|
5921
5989
|
],
|
|
5922
|
-
otter: "stackwright-pro-
|
|
5990
|
+
otter: "stackwright-pro-form-wizard-otter",
|
|
5923
5991
|
artifactKey: "workflowConfig"
|
|
5924
5992
|
},
|
|
5925
5993
|
auth: {
|
|
@@ -6500,7 +6568,7 @@ var package_default = {
|
|
|
6500
6568
|
"test:coverage": "vitest run --coverage"
|
|
6501
6569
|
},
|
|
6502
6570
|
name: "@stackwright-pro/mcp",
|
|
6503
|
-
version: "0.2.0-alpha.
|
|
6571
|
+
version: "0.2.0-alpha.92",
|
|
6504
6572
|
description: "MCP tools for Stackwright Pro - Data Explorer, Security, ISR, and Dashboard generation",
|
|
6505
6573
|
license: "SEE LICENSE IN LICENSE",
|
|
6506
6574
|
main: "./dist/server.js",
|