@neobiotechlabs/neobiotech-dev-agent 0.1.20 → 0.1.22
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/data/cyber_sec.png +0 -0
- package/data/hazard_panel.png +0 -0
- package/data/risk_score.png +0 -0
- package/dist/index.js +354 -145
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"source": "npm",
|
|
11
11
|
"package": "@neobiotechlabs/neobiotech-dev-agent",
|
|
12
12
|
"registry": "https://registry.npmjs.org",
|
|
13
|
-
"version": "0.1.
|
|
13
|
+
"version": "0.1.22"
|
|
14
14
|
},
|
|
15
15
|
"description": "의료기기 SW 규제 개발 자동화 (Jira·Confluence·Risk·CVSS·Xray·IEC 62304/62366·MDR·문서 렌더)",
|
|
16
16
|
"category": "medical-device",
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -159642,6 +159642,7 @@ var RiskClient = class {
|
|
|
159642
159642
|
this.authHeader = `Basic ${Buffer.from(`${email2}:${token}`).toString("base64")}`;
|
|
159643
159643
|
this.riskAuthToken = riskAuthToken2;
|
|
159644
159644
|
}
|
|
159645
|
+
/** Jira issue property 활성화 (Jira 표준 REST + Basic auth) */
|
|
159645
159646
|
async activateRiskPanel(issueKey) {
|
|
159646
159647
|
const appId = "306e01a8-5530-427d-b93a-f91f4898ff16";
|
|
159647
159648
|
const configId = "2a1d023a-d4a5-42c7-91e2-51a05b9eb9be";
|
|
@@ -159660,11 +159661,23 @@ var RiskClient = class {
|
|
|
159660
159661
|
);
|
|
159661
159662
|
return resp.ok;
|
|
159662
159663
|
}
|
|
159663
|
-
|
|
159664
|
-
|
|
159665
|
-
|
|
159666
|
-
|
|
159667
|
-
|
|
159664
|
+
/**
|
|
159665
|
+
* Legacy 0.1.20 호환 — classifier/option name을 받아 lookup 후 setRawPayload 호출.
|
|
159666
|
+
* 0.1.21+ 핸들러는 planSetRisk 결과를 setRiskValueRaw로 직접 보내므로 이 메서드는
|
|
159667
|
+
* 그레이스존 유지용. 그러나 RISK_DEFAULTS 정의를 사용하지 않으므로 항상 undefined.
|
|
159668
|
+
*/
|
|
159669
|
+
async setRiskValue(_issueKey, _riskConfig, _classifierName, _optionName) {
|
|
159670
|
+
return {
|
|
159671
|
+
ok: false,
|
|
159672
|
+
status: 0,
|
|
159673
|
+
error: "risk_set_values\uC740 0.1.21\uC5D0\uC11C setRiskValueRaw\uB85C \uC774\uC804\uB418\uC5C8\uC2B5\uB2C8\uB2E4. planSetRisk() \uC0AC\uC6A9 \uAD8C\uC7A5."
|
|
159674
|
+
};
|
|
159675
|
+
}
|
|
159676
|
+
/**
|
|
159677
|
+
* 신규 0.1.21 메서드 — payload가 완전 set된 상태로 RMP webtrigger 호출.
|
|
159678
|
+
* endpoint+token은 환경변수에서 받음 (회사 사이트마다 다름).
|
|
159679
|
+
*/
|
|
159680
|
+
async setRiskValueRaw(issueKey, payload) {
|
|
159668
159681
|
if (!this.riskAuthToken) {
|
|
159669
159682
|
return {
|
|
159670
159683
|
ok: false,
|
|
@@ -159672,24 +159685,28 @@ var RiskClient = class {
|
|
|
159672
159685
|
error: "RISK_PLUGIN_AUTH_TOKEN not configured (x-trigger-authentication header would be empty)"
|
|
159673
159686
|
};
|
|
159674
159687
|
}
|
|
159675
|
-
const
|
|
159688
|
+
const DEFAULT_RMP_ENDPOINT = "https://306e01a8-5530-427d-b93a-f91f4898ff16.hello.atlassian-dev.net/x1/p3_h8rdLbpp1-9mjDOXQiqJ4jL4";
|
|
159689
|
+
const endpoint = process.env.RISK_PLUGIN_ENDPOINT || DEFAULT_RMP_ENDPOINT;
|
|
159690
|
+
if (!endpoint) {
|
|
159691
|
+
return {
|
|
159692
|
+
ok: false,
|
|
159693
|
+
status: 0,
|
|
159694
|
+
error: "RISK_PLUGIN_ENDPOINT not configured. \uD658\uACBD\uBCC0\uC218 \uB610\uB294 \uCF54\uB4DC \uC815\uC801 \uAE30\uBCF8\uAC12\uC744 \uD655\uC778\uD558\uC138\uC694."
|
|
159695
|
+
};
|
|
159696
|
+
}
|
|
159697
|
+
const fullPayload = {
|
|
159698
|
+
...payload,
|
|
159676
159699
|
issueKey,
|
|
159677
|
-
author:
|
|
159678
|
-
riskModelKey: riskConfig.riskModelKey,
|
|
159679
|
-
riskSetId: riskConfig.riskSetId,
|
|
159680
|
-
classifierValuePayload: {
|
|
159681
|
-
classifierId: classifier.id,
|
|
159682
|
-
optionId
|
|
159683
|
-
}
|
|
159700
|
+
author: payload.author ?? ""
|
|
159684
159701
|
};
|
|
159685
159702
|
try {
|
|
159686
|
-
const resp = await fetch(
|
|
159703
|
+
const resp = await fetch(endpoint, {
|
|
159687
159704
|
method: "POST",
|
|
159688
159705
|
headers: {
|
|
159689
159706
|
"x-trigger-authentication": this.riskAuthToken,
|
|
159690
159707
|
"Content-Type": "application/json"
|
|
159691
159708
|
},
|
|
159692
|
-
body: JSON.stringify(
|
|
159709
|
+
body: JSON.stringify(fullPayload)
|
|
159693
159710
|
});
|
|
159694
159711
|
const body = await resp.text();
|
|
159695
159712
|
return {
|
|
@@ -160081,57 +160098,244 @@ var registerConfluenceTools = (ctx2) => {
|
|
|
160081
160098
|
});
|
|
160082
160099
|
};
|
|
160083
160100
|
|
|
160084
|
-
// src/config/
|
|
160085
|
-
var
|
|
160086
|
-
|
|
160087
|
-
|
|
160088
|
-
|
|
160089
|
-
|
|
160090
|
-
|
|
160091
|
-
|
|
160092
|
-
|
|
160093
|
-
|
|
160094
|
-
|
|
160095
|
-
|
|
160096
|
-
|
|
160097
|
-
|
|
160098
|
-
|
|
160099
|
-
|
|
160100
|
-
|
|
160101
|
-
|
|
160101
|
+
// src/config/risk-models.ts
|
|
160102
|
+
var RISK_MODELS = {
|
|
160103
|
+
p1_p2_iso14971: {
|
|
160104
|
+
label: "P1-P2 ISO14971 Hazard analysis",
|
|
160105
|
+
modelKey: "risk-model-9dc1c741-0858-4a96-65d6-5feaf052da71",
|
|
160106
|
+
riskSets: {
|
|
160107
|
+
initial: "2f43f135-d043-84bd-4222-46ba4a309738",
|
|
160108
|
+
current: "f957cae9-a34c-30d7-557b-f7f29a414ba5"
|
|
160109
|
+
},
|
|
160110
|
+
classifiers: {
|
|
160111
|
+
severity: {
|
|
160112
|
+
id: "120dbe93-8a5c-89d9-398c-6fdefc8fa072",
|
|
160113
|
+
options: {
|
|
160114
|
+
negligible: "0750b204-3be7-14b2-34c9-5100846e99db",
|
|
160115
|
+
minor: "70ccea9f-a585-d248-dbd0-e6eefcc683e8",
|
|
160116
|
+
serious: "a8b765c0-2e55-f6c4-25ff-1a4513c1cfd7",
|
|
160117
|
+
critical: "587d166e-890a-5123-e179-15bafbd617e1",
|
|
160118
|
+
catastrophic: "981fbfd5-604d-f9b9-6765-3405a165f401"
|
|
160119
|
+
}
|
|
160120
|
+
},
|
|
160121
|
+
p1: {
|
|
160122
|
+
id: "c2c0af5d-74de-e463-ad13-ba80da1b6afd",
|
|
160123
|
+
options: {
|
|
160124
|
+
improvable: "3ac4a3b1-55ef-de93-3452-61c572a905a3",
|
|
160125
|
+
remote: "2d173a68-c28f-d589-1300-bc127f962810",
|
|
160126
|
+
occasional: "039596ac-784e-f0ac-50cf-d4d2cc96b096",
|
|
160127
|
+
probable: "702cb81f-3bc6-d150-5cc3-daa04d3f0404",
|
|
160128
|
+
frequent: "09fb301a-4448-d8aa-afd2-76d371f501f3"
|
|
160129
|
+
}
|
|
160130
|
+
},
|
|
160131
|
+
p2: {
|
|
160132
|
+
id: "cdada7bb-cb4a-3b00-260b-5e5227e85a74",
|
|
160133
|
+
options: {
|
|
160134
|
+
improvable: "7e044b34-25c4-ffae-5237-48eebb190358",
|
|
160135
|
+
remote: "58257cb8-59e2-5ec7-dd1d-9e966fb13589",
|
|
160136
|
+
occasional: "6cf5ebce-3b07-69b1-b093-9e0ef9def95c",
|
|
160137
|
+
probable: "bbcbfdd1-0c02-6105-e8e4-f60ae6cacb5c",
|
|
160138
|
+
frequent: "e35de539-93d5-f854-c6ed-50067ad8599b"
|
|
160139
|
+
}
|
|
160102
160140
|
}
|
|
160141
|
+
}
|
|
160142
|
+
},
|
|
160143
|
+
rpn: {
|
|
160144
|
+
label: "Risk Score Calculator",
|
|
160145
|
+
modelKey: "risk-model-c3edfff2-bea1-eb85-1f53-1007c429357a",
|
|
160146
|
+
riskSets: {
|
|
160147
|
+
initial: "f0f50906-1516-0826-8e82-009813ce7ff7",
|
|
160148
|
+
current: "069094fa-c4b1-28a1-d330-464f78b4ecb5",
|
|
160149
|
+
final: "d972671a-06c1-cf5d-e73b-20779079b509"
|
|
160103
160150
|
},
|
|
160104
|
-
|
|
160105
|
-
|
|
160106
|
-
|
|
160107
|
-
|
|
160108
|
-
|
|
160109
|
-
|
|
160110
|
-
|
|
160111
|
-
|
|
160151
|
+
classifiers: {
|
|
160152
|
+
severity: {
|
|
160153
|
+
id: "fec8bdcd-0c55-4ab3-87e3-cfd7176aefd5",
|
|
160154
|
+
options: {
|
|
160155
|
+
negligible: "a87a6249-03e4-5419-d50e-0818d824e8cb",
|
|
160156
|
+
minor: "f0f50906-1516-0826-8e82-009813ce7ff7",
|
|
160157
|
+
serious: "15f87aeb-28ec-98ea-7310-4ad04b294127",
|
|
160158
|
+
critical: "bf9cf219-e342-12ef-4305-2963f930138d",
|
|
160159
|
+
catastrophic: "e04cdc89-ffae-6001-4c06-d14b9fea0eee"
|
|
160160
|
+
}
|
|
160161
|
+
},
|
|
160162
|
+
occurrence: {
|
|
160163
|
+
id: "dc6e3abf-8cfa-b48f-5693-0f51a2362c8f",
|
|
160164
|
+
options: {
|
|
160165
|
+
improvable: "421dfccd-e545-2ec1-6d76-74913955cb63",
|
|
160166
|
+
remote: "8933daea-a933-3ea0-59c1-eb8b7aa0120e",
|
|
160167
|
+
occasional: "96861e6d-1b59-6616-7dda-0e6f413f4f65",
|
|
160168
|
+
probable: "40cd4688-3f91-3781-40c1-5ce65f7cb272",
|
|
160169
|
+
frequent: "7d1c1103-238d-a104-28d7-ba312dd4e394"
|
|
160170
|
+
}
|
|
160171
|
+
},
|
|
160172
|
+
detectability: {
|
|
160173
|
+
id: "2c266e79-f190-1234-95d1-201f72c98acc",
|
|
160174
|
+
options: {
|
|
160175
|
+
improvable: "f57c4581-c957-a270-65e6-1d6930b93a7f",
|
|
160176
|
+
remote: "f7fdea4b-5378-8c45-854d-bcd8ba3bee12",
|
|
160177
|
+
occasional: "45fb0720-f204-acf9-33dd-c92ba27910fa",
|
|
160178
|
+
probable: "c1a7a596-6fc4-db5d-1da3-f2b13d64da8c",
|
|
160179
|
+
frequent: "67ea818d-8ed7-a1af-57ff-6ba68a24c4b4"
|
|
160180
|
+
}
|
|
160112
160181
|
}
|
|
160182
|
+
}
|
|
160183
|
+
},
|
|
160184
|
+
cia: {
|
|
160185
|
+
label: "Cyber Sec Risk Model",
|
|
160186
|
+
modelKey: "risk-model-ciaRiskModel",
|
|
160187
|
+
riskSets: {
|
|
160188
|
+
initial: "68f0e9de-26c6-7ad8-5a72-a688ad770b24",
|
|
160189
|
+
current: "b43d25e0-0ab5-3605-cd2d-3f54f904d26c"
|
|
160190
|
+
},
|
|
160191
|
+
ciaWrapper: {
|
|
160192
|
+
id: "54d9d60c-7c53-2454-a48d-3c464bad23a9",
|
|
160193
|
+
riskModelKey: "risk-model-overallCIAImpact"
|
|
160113
160194
|
},
|
|
160114
|
-
|
|
160115
|
-
|
|
160116
|
-
|
|
160117
|
-
|
|
160118
|
-
|
|
160119
|
-
|
|
160120
|
-
|
|
160121
|
-
|
|
160195
|
+
classifiers: {
|
|
160196
|
+
confidentiality: {
|
|
160197
|
+
id: "193ceea6-d531-808b-bb83-d16eb233d73f",
|
|
160198
|
+
options: {
|
|
160199
|
+
negligible: "9dc59ace-7484-108c-77fc-383c85a54052",
|
|
160200
|
+
low: "c1802cd2-a655-3ed9-8138-376297ab39ab",
|
|
160201
|
+
moderate: "d96e2893-515d-29da-d168-c134fb055fa1",
|
|
160202
|
+
high: "dc7f3d58-a8cd-7729-5e0a-37cedfe7996f",
|
|
160203
|
+
severe: "39fe9a59-c8b9-d0b5-a273-fbfcc6efdb6c"
|
|
160204
|
+
}
|
|
160205
|
+
},
|
|
160206
|
+
availability: {
|
|
160207
|
+
id: "1121ee15-e019-dbd7-64f2-47e7af76e789",
|
|
160208
|
+
options: {
|
|
160209
|
+
negligible: "863fd4fd-d939-4e73-fdc9-b27489fcbbb4",
|
|
160210
|
+
low: "cbb40d71-238c-97d7-02cd-4b905929eedb",
|
|
160211
|
+
moderate: "4fbc0ef0-1378-3b2c-7401-75ce94d9443b",
|
|
160212
|
+
high: "33a53544-c011-c30d-dc66-d5f9e0d0bb88",
|
|
160213
|
+
severe: "d9f4a792-0822-c0b0-b463-4c2887ce4d01"
|
|
160214
|
+
}
|
|
160215
|
+
},
|
|
160216
|
+
integrity: {
|
|
160217
|
+
id: "639c61e6-9d11-9bb3-04e7-c1c3512c7e33",
|
|
160218
|
+
options: {
|
|
160219
|
+
negligible: "f35284c1-52a2-edce-e60b-69b97703b891",
|
|
160220
|
+
low: "af67cc1b-9e25-76ce-baf3-d2e8247af569",
|
|
160221
|
+
moderate: "a35a0d14-e8d4-b3c8-35fc-a1f81d2730c7",
|
|
160222
|
+
high: "e535be53-21a8-0f8d-3c78-db4c3d7ebde1",
|
|
160223
|
+
severe: "7a45c4d7-d926-5d01-0034-c9ef929117b3"
|
|
160224
|
+
}
|
|
160225
|
+
},
|
|
160226
|
+
likelihood: {
|
|
160227
|
+
id: "ff7ed5a9-53fe-7e29-f564-b8f3b96bdd5b",
|
|
160228
|
+
options: {
|
|
160229
|
+
rare: "5b3f2233-4603-f34a-9e06-1473e4e1da02",
|
|
160230
|
+
unlikely: "7af594cb-4a87-73c1-2d0a-924124c5f247",
|
|
160231
|
+
possibly: "ed8a2a21-ec63-5e9b-d1d3-60d39ad4ec91",
|
|
160232
|
+
likely: "afe83dfb-fc00-7d3c-9b65-ed0ba6607b96",
|
|
160233
|
+
almost_certain: "86def84c-70c4-15c2-7b7b-f084a9aaf19f"
|
|
160234
|
+
}
|
|
160122
160235
|
}
|
|
160123
160236
|
}
|
|
160124
160237
|
}
|
|
160125
160238
|
};
|
|
160126
|
-
|
|
160127
|
-
|
|
160239
|
+
|
|
160240
|
+
// src/config/project-config.ts
|
|
160241
|
+
function planSetRisk(model, riskSet, classifierOptions, issueKey) {
|
|
160242
|
+
const m3 = RISK_MODELS[model];
|
|
160243
|
+
if (!m3) return { items: [], skipped: [{ classifier: "*", optionName: model }] };
|
|
160244
|
+
const setId = m3.riskSets[riskSet];
|
|
160245
|
+
if (!setId) return { items: [], skipped: [{ classifier: "*", optionName: `riskSet.${riskSet}` }] };
|
|
160246
|
+
const author = process.env.JIRA_EMAIL;
|
|
160247
|
+
if (!author) return { items: [], skipped: [{ classifier: "*", optionName: "JIRA_EMAIL missing" }] };
|
|
160248
|
+
const items = [];
|
|
160249
|
+
const skipped = [];
|
|
160250
|
+
for (const [classifierName, optionName] of Object.entries(classifierOptions)) {
|
|
160251
|
+
if (!optionName) continue;
|
|
160252
|
+
const cls = m3.classifiers[classifierName];
|
|
160253
|
+
if (!cls) {
|
|
160254
|
+
skipped.push({ classifier: classifierName, optionName });
|
|
160255
|
+
continue;
|
|
160256
|
+
}
|
|
160257
|
+
const optionId = cls.options[optionName];
|
|
160258
|
+
if (!optionId) {
|
|
160259
|
+
skipped.push({ classifier: classifierName, optionName });
|
|
160260
|
+
continue;
|
|
160261
|
+
}
|
|
160262
|
+
items.push({
|
|
160263
|
+
model,
|
|
160264
|
+
riskSet,
|
|
160265
|
+
classifierName,
|
|
160266
|
+
optionName,
|
|
160267
|
+
payload: {
|
|
160268
|
+
issueKey,
|
|
160269
|
+
author,
|
|
160270
|
+
riskModelKey: m3.modelKey,
|
|
160271
|
+
riskSetId: setId,
|
|
160272
|
+
classifierValuePayload: { classifierId: cls.id, optionId }
|
|
160273
|
+
}
|
|
160274
|
+
});
|
|
160275
|
+
}
|
|
160276
|
+
return {
|
|
160277
|
+
items: items.map((i2) => ({ payload: i2.payload })),
|
|
160278
|
+
skipped
|
|
160279
|
+
};
|
|
160128
160280
|
}
|
|
160129
160281
|
|
|
160130
160282
|
// src/tools/risk.ts
|
|
160131
|
-
|
|
160283
|
+
var SEVERITY_P1P2 = external_exports.enum(["negligible", "minor", "serious", "critical", "catastrophic"]);
|
|
160284
|
+
var PROB_P1P2 = external_exports.enum(["improvable", "remote", "occasional", "probable", "frequent"]);
|
|
160285
|
+
var SEVERITY_RPN = external_exports.enum(["negligible", "minor", "serious", "critical", "catastrophic"]);
|
|
160286
|
+
var PROB_RPN = external_exports.enum(["improvable", "remote", "occasional", "probable", "frequent"]);
|
|
160287
|
+
var CIA_LEVEL = external_exports.enum(["negligible", "low", "moderate", "high", "severe"]);
|
|
160288
|
+
var LIKELIHOOD = external_exports.enum(["rare", "unlikely", "possibly", "likely", "almost_certain"]);
|
|
160289
|
+
var RISK_SET = external_exports.enum(["initial", "current", "final"]).default("current");
|
|
160290
|
+
var p1P2Payload = external_exports.object({
|
|
160291
|
+
severity: SEVERITY_P1P2.optional(),
|
|
160292
|
+
p1: PROB_P1P2.optional(),
|
|
160293
|
+
p2: PROB_P1P2.optional()
|
|
160294
|
+
}).strict();
|
|
160295
|
+
var rpnPayload = external_exports.object({
|
|
160296
|
+
severity: SEVERITY_RPN.optional(),
|
|
160297
|
+
occurrence: PROB_RPN.optional(),
|
|
160298
|
+
detectability: PROB_RPN.optional()
|
|
160299
|
+
}).strict();
|
|
160300
|
+
var ciaPayload = external_exports.object({
|
|
160301
|
+
confidentiality: CIA_LEVEL.optional(),
|
|
160302
|
+
availability: CIA_LEVEL.optional(),
|
|
160303
|
+
integrity: CIA_LEVEL.optional(),
|
|
160304
|
+
likelihood: LIKELIHOOD.optional()
|
|
160305
|
+
}).strict();
|
|
160306
|
+
function classifierFromId(model, id) {
|
|
160307
|
+
const m3 = RISK_MODELS[model];
|
|
160308
|
+
for (const [name, cls] of Object.entries(m3.classifiers)) {
|
|
160309
|
+
if (cls.id === id) return name;
|
|
160310
|
+
}
|
|
160311
|
+
return id;
|
|
160312
|
+
}
|
|
160313
|
+
function formatSetDetail(line) {
|
|
160314
|
+
const r2 = line.result;
|
|
160132
160315
|
const tag = r2.ok ? "OK" : "FAILED";
|
|
160133
160316
|
const detail = r2.error ? `status=${r2.status}, error=${r2.error}` : `status=${r2.status}${r2.body ? `, body=${r2.body}` : ""}`;
|
|
160134
|
-
return `${
|
|
160317
|
+
return `${tag} [${line.model}] ${line.classifier}=${line.optionName} (${detail})`;
|
|
160318
|
+
}
|
|
160319
|
+
async function runSetPlans(riskStub, plans) {
|
|
160320
|
+
const out = { details: [] };
|
|
160321
|
+
for (const p of plans) {
|
|
160322
|
+
if (p.res.skipped.length > 0) {
|
|
160323
|
+
for (const sk of p.res.skipped) {
|
|
160324
|
+
out.skipped = out.skipped ?? [];
|
|
160325
|
+
out.skipped.push({ classifier: `${p.name}.${sk.classifier}`, reason: "option-not-mapped" });
|
|
160326
|
+
}
|
|
160327
|
+
}
|
|
160328
|
+
for (const { payload } of p.res.items) {
|
|
160329
|
+
const r2 = await riskStub.setRiskValueRaw(p.issueKey, payload);
|
|
160330
|
+
out.details.push({
|
|
160331
|
+
model: p.name,
|
|
160332
|
+
classifier: classifierFromId(p.model, payload.classifierValuePayload.classifierId),
|
|
160333
|
+
optionName: payload.classifierValuePayload.optionId,
|
|
160334
|
+
result: r2
|
|
160335
|
+
});
|
|
160336
|
+
}
|
|
160337
|
+
}
|
|
160338
|
+
return out;
|
|
160135
160339
|
}
|
|
160136
160340
|
var registerRiskTools = (ctx2) => {
|
|
160137
160341
|
const { server: server2, risk: risk2, jira: jira2 } = ctx2;
|
|
@@ -160141,62 +160345,77 @@ var registerRiskTools = (ctx2) => {
|
|
|
160141
160345
|
const ok = await risk2.activateRiskPanel(issue_key);
|
|
160142
160346
|
return { content: [{ type: "text", text: ok ? `Risk panel activated on ${issue_key}` : `Failed to activate risk panel on ${issue_key}` }] };
|
|
160143
160347
|
});
|
|
160144
|
-
server2.tool(
|
|
160145
|
-
|
|
160146
|
-
|
|
160147
|
-
|
|
160148
|
-
|
|
160149
|
-
|
|
160150
|
-
|
|
160151
|
-
|
|
160152
|
-
|
|
160153
|
-
|
|
160154
|
-
|
|
160155
|
-
|
|
160156
|
-
|
|
160157
|
-
|
|
160158
|
-
|
|
160159
|
-
|
|
160160
|
-
|
|
160161
|
-
|
|
160162
|
-
|
|
160163
|
-
|
|
160164
|
-
|
|
160165
|
-
const r2 = await risk2.setRiskValue(issue_key, configForSet, name, value);
|
|
160166
|
-
results.push(formatRiskResult(name, value, r2));
|
|
160348
|
+
server2.tool(
|
|
160349
|
+
"risk_set_values",
|
|
160350
|
+
"Set risk values on an issue via RMP webtrigger. P1-P2 / RPN / CIA \uB3D9\uC2DC \uC785\uB825 \uAC00\uB2A5. \uC635\uC158\uC740 name \uBB38\uC790\uC5F4(UUID \uC790\uB3D9 \uB9E4\uD551). lookup \uC2E4\uD328 \uD56D\uBAA9\uC740 SKIP.",
|
|
160351
|
+
{
|
|
160352
|
+
issue_key: external_exports.string().describe("Issue key"),
|
|
160353
|
+
project_key: external_exports.string().describe("Project key (for context)"),
|
|
160354
|
+
risk_set: RISK_SET,
|
|
160355
|
+
p1_p2_iso14971: p1P2Payload.optional(),
|
|
160356
|
+
rpn: rpnPayload.optional(),
|
|
160357
|
+
cia: ciaPayload.optional()
|
|
160358
|
+
},
|
|
160359
|
+
async ({ issue_key, project_key, risk_set, p1_p2_iso14971, rpn, cia }) => {
|
|
160360
|
+
const tasks = [
|
|
160361
|
+
{ model: "p1_p2_iso14971", name: "P1-P2", res: planSetRisk("p1_p2_iso14971", risk_set, p1_p2_iso14971 ?? {}, issue_key), issueKey: issue_key },
|
|
160362
|
+
{ model: "rpn", name: "RPN", res: planSetRisk("rpn", risk_set, rpn ?? {}, issue_key), issueKey: issue_key },
|
|
160363
|
+
{ model: "cia", name: "CIA", res: planSetRisk("cia", risk_set, cia ?? {}, issue_key), issueKey: issue_key }
|
|
160364
|
+
];
|
|
160365
|
+
const out = await runSetPlans(risk2, tasks);
|
|
160366
|
+
const lines = [`Risk values for ${issue_key} (${risk_set} set):`];
|
|
160367
|
+
if (out.details.length === 0 && (out.skipped ?? []).length === 0) {
|
|
160368
|
+
lines.push(`(no risk values specified for ${project_key})`);
|
|
160167
160369
|
}
|
|
160370
|
+
for (const d2 of out.details) lines.push(formatSetDetail(d2));
|
|
160371
|
+
for (const s2 of out.skipped ?? []) lines.push(`SKIPPED ${s2.classifier} (${s2.reason})`);
|
|
160372
|
+
return { content: [{ type: "text", text: lines.join("\n") }] };
|
|
160168
160373
|
}
|
|
160169
|
-
|
|
160170
|
-
|
|
160171
|
-
|
|
160172
|
-
|
|
160173
|
-
|
|
160174
|
-
|
|
160175
|
-
|
|
160176
|
-
|
|
160177
|
-
|
|
160178
|
-
|
|
160179
|
-
|
|
160180
|
-
|
|
160181
|
-
|
|
160182
|
-
|
|
160183
|
-
|
|
160184
|
-
|
|
160185
|
-
|
|
160186
|
-
|
|
160187
|
-
|
|
160188
|
-
|
|
160374
|
+
);
|
|
160375
|
+
server2.tool(
|
|
160376
|
+
"risk_get_config",
|
|
160377
|
+
"Get RMP risk model configuration for a project. Returns 3 model identifiers, classifier/option UUID \uD480, \uD658\uACBD \uC548\uB0B4.",
|
|
160378
|
+
{
|
|
160379
|
+
project_key: external_exports.string().describe("Project key")
|
|
160380
|
+
},
|
|
160381
|
+
async ({ project_key }) => {
|
|
160382
|
+
const endpoint = process.env.RISK_PLUGIN_ENDPOINT ?? null;
|
|
160383
|
+
const tokenPresent = !!process.env.RISK_PLUGIN_AUTH_TOKEN;
|
|
160384
|
+
return { content: [{ type: "text", text: JSON.stringify({
|
|
160385
|
+
endpoint,
|
|
160386
|
+
token_present: tokenPresent,
|
|
160387
|
+
diagnostic_note: "token\uC774 \uC5C6\uAC70\uB098 endpoint\uAC00 \uC124\uC815\uB418\uC9C0 \uC54A\uC73C\uBA74 setRiskValue \uD638\uCD9C\uC774 \uC2E4\uD328\uD569\uB2C8\uB2E4. /plugin configure \uB85C RISK_PLUGIN_ENDPOINT / RISK_PLUGIN_AUTH_TOKEN \uC744 \uC785\uB825.",
|
|
160388
|
+
models: Object.fromEntries(
|
|
160389
|
+
Object.keys(RISK_MODELS).map((k) => {
|
|
160390
|
+
const m3 = RISK_MODELS[k];
|
|
160391
|
+
return [k, {
|
|
160392
|
+
label: m3.label,
|
|
160393
|
+
modelKey: m3.modelKey,
|
|
160394
|
+
riskSets: m3.riskSets,
|
|
160395
|
+
classifiers: Object.fromEntries(
|
|
160396
|
+
Object.entries(m3.classifiers).map(([cn, c]) => [cn, { id: c.id, options: Object.keys(c.options) }])
|
|
160397
|
+
),
|
|
160398
|
+
...m3.ciaWrapper ? { ciaWrapper: m3.ciaWrapper } : {}
|
|
160399
|
+
}];
|
|
160400
|
+
})
|
|
160401
|
+
),
|
|
160402
|
+
project: project_key
|
|
160403
|
+
}, null, 2) }] };
|
|
160404
|
+
}
|
|
160405
|
+
);
|
|
160406
|
+
server2.tool("risk_create_hazards", "Batch create Hazard tickets with Risk Source links and (\uC120\uD0DD\uC801) 3 \uBAA8\uB378 risk values \uC790\uB3D9 \uC14B\uD305.", {
|
|
160407
|
+
project_key: external_exports.string(),
|
|
160408
|
+
rmr_key: external_exports.string(),
|
|
160189
160409
|
hazards: external_exports.array(external_exports.object({
|
|
160190
160410
|
summary: external_exports.string(),
|
|
160191
160411
|
description: external_exports.string(),
|
|
160192
160412
|
harm: external_exports.string(),
|
|
160193
|
-
|
|
160194
|
-
|
|
160195
|
-
|
|
160196
|
-
|
|
160197
|
-
})
|
|
160413
|
+
source_keys: external_exports.array(external_exports.string()),
|
|
160414
|
+
p1_p2_iso14971: p1P2Payload.optional(),
|
|
160415
|
+
rpn: rpnPayload.optional(),
|
|
160416
|
+
cia: ciaPayload.optional()
|
|
160417
|
+
}).strict())
|
|
160198
160418
|
}, async ({ project_key, rmr_key, hazards }) => {
|
|
160199
|
-
const riskConfig = getRiskConfig(project_key);
|
|
160200
160419
|
const { textToAdf: textToAdf2 } = await Promise.resolve().then(() => (init_jira_client(), jira_client_exports));
|
|
160201
160420
|
const results = [];
|
|
160202
160421
|
const errors = [];
|
|
@@ -160215,50 +160434,45 @@ ${results.join("\n")}` }] };
|
|
|
160215
160434
|
continue;
|
|
160216
160435
|
}
|
|
160217
160436
|
await risk2.activateRiskPanel(issueKey);
|
|
160218
|
-
|
|
160219
|
-
|
|
160220
|
-
|
|
160221
|
-
|
|
160222
|
-
|
|
160223
|
-
|
|
160224
|
-
|
|
160225
|
-
|
|
160226
|
-
riskSetId: riskConfig.risk_sets[setName],
|
|
160227
|
-
classifiers: riskConfig.classifiers
|
|
160228
|
-
};
|
|
160229
|
-
for (const [name, value] of [["severity", h2.severity], ["p1", h2.p1], ["p2", h2.p2]]) {
|
|
160230
|
-
const r2 = await risk2.setRiskValue(issueKey, setConfig, name, value);
|
|
160231
|
-
if (!r2.ok) riskOk = false;
|
|
160232
|
-
riskDetails.push(`${setName}.${name}=${value}: ${r2.ok ? "OK" : "FAILED"} (${r2.error ?? `status=${r2.status}${r2.body ? `, body=${r2.body}` : ""}`})`);
|
|
160233
|
-
}
|
|
160234
|
-
}
|
|
160235
|
-
} else {
|
|
160236
|
-
riskOk = false;
|
|
160237
|
-
riskDetails.push("no risk config for project");
|
|
160238
|
-
}
|
|
160437
|
+
const tasks = [
|
|
160438
|
+
{ model: "p1_p2_iso14971", name: "P1-P2", res: planSetRisk("p1_p2_iso14971", "initial", h2.p1_p2_iso14971 ?? {}, issueKey), issueKey },
|
|
160439
|
+
{ model: "rpn", name: "RPN", res: planSetRisk("rpn", "initial", h2.rpn ?? {}, issueKey), issueKey },
|
|
160440
|
+
{ model: "cia", name: "CIA", res: planSetRisk("cia", "initial", h2.cia ?? {}, issueKey), issueKey }
|
|
160441
|
+
];
|
|
160442
|
+
const out = await runSetPlans(risk2, tasks);
|
|
160443
|
+
const riskOk = out.details.every((d2) => d2.result.ok);
|
|
160444
|
+
const riskSkipped = out.skipped ?? [];
|
|
160239
160445
|
for (const srcKey of h2.source_keys) {
|
|
160240
160446
|
await jira2.createLink("Risk Source", issueKey, srcKey);
|
|
160241
160447
|
}
|
|
160242
160448
|
await jira2.createLink("Relates", issueKey, rmr_key);
|
|
160243
|
-
results.push({
|
|
160449
|
+
results.push({
|
|
160450
|
+
key: issueKey,
|
|
160451
|
+
summary: h2.summary,
|
|
160452
|
+
status: "created",
|
|
160453
|
+
risk_values: {
|
|
160454
|
+
ok: riskOk,
|
|
160455
|
+
details: out.details.map(formatSetDetail),
|
|
160456
|
+
skipped: riskSkipped
|
|
160457
|
+
}
|
|
160458
|
+
});
|
|
160244
160459
|
} catch (e2) {
|
|
160245
160460
|
errors.push(`${h2.summary}: ${e2.message}`);
|
|
160246
160461
|
}
|
|
160247
160462
|
}
|
|
160248
160463
|
return { content: [{ type: "text", text: JSON.stringify({ created: results.length, failed: errors.length, results, errors }, null, 2) }] };
|
|
160249
160464
|
});
|
|
160250
|
-
server2.tool("risk_create_mitigation", "Create mitigation Requirements, link to Hazards, and update Hazard Current P2
|
|
160251
|
-
project_key: external_exports.string()
|
|
160252
|
-
srs_key: external_exports.string()
|
|
160465
|
+
server2.tool("risk_create_mitigation", "Create mitigation Requirements, link to Hazards, and update Hazard Current P2 (P1-P2 \uBAA8\uB378).", {
|
|
160466
|
+
project_key: external_exports.string(),
|
|
160467
|
+
srs_key: external_exports.string(),
|
|
160253
160468
|
requirements: external_exports.array(external_exports.object({
|
|
160254
160469
|
summary: external_exports.string(),
|
|
160255
160470
|
description: external_exports.string(),
|
|
160256
|
-
mitigates: external_exports.array(external_exports.string())
|
|
160257
|
-
implements: external_exports.array(external_exports.string())
|
|
160471
|
+
mitigates: external_exports.array(external_exports.string()),
|
|
160472
|
+
implements: external_exports.array(external_exports.string())
|
|
160258
160473
|
})),
|
|
160259
|
-
hazard_risk_updates: external_exports.record(external_exports.object({ p2: external_exports.string() }))
|
|
160474
|
+
hazard_risk_updates: external_exports.record(external_exports.object({ p2: external_exports.string() }))
|
|
160260
160475
|
}, async ({ project_key, srs_key, requirements, hazard_risk_updates }) => {
|
|
160261
|
-
const riskConfig = getRiskConfig(project_key);
|
|
160262
160476
|
const { textToAdf: textToAdf2 } = await Promise.resolve().then(() => (init_jira_client(), jira_client_exports));
|
|
160263
160477
|
const results = [];
|
|
160264
160478
|
const errors = [];
|
|
@@ -160288,20 +160502,15 @@ ${results.join("\n")}` }] };
|
|
|
160288
160502
|
}
|
|
160289
160503
|
}
|
|
160290
160504
|
const riskUpdates = [];
|
|
160291
|
-
|
|
160292
|
-
const
|
|
160293
|
-
|
|
160294
|
-
|
|
160295
|
-
|
|
160296
|
-
riskSetId: riskConfig.risk_sets.current,
|
|
160297
|
-
classifiers: riskConfig.classifiers
|
|
160298
|
-
};
|
|
160299
|
-
for (const [hazKey, update] of Object.entries(hazard_risk_updates)) {
|
|
160300
|
-
const r2 = await risk2.setRiskValue(hazKey, currentConfig, "p2", update.p2);
|
|
160301
|
-
riskUpdates.push(`${hazKey} P2\u2192${update.p2}: ${r2.ok ? "OK" : "FAILED"} (${r2.error ?? `status=${r2.status}${r2.body ? `, body=${r2.body}` : ""}`})`);
|
|
160505
|
+
for (const [hazKey, update] of Object.entries(hazard_risk_updates)) {
|
|
160506
|
+
const plan = planSetRisk("p1_p2_iso14971", "current", { p2: update.p2 }, hazKey);
|
|
160507
|
+
if (plan.skipped.length > 0) {
|
|
160508
|
+
riskUpdates.push(`SKIPPED ${hazKey} P2=${update.p2} (option-not-mapped)`);
|
|
160509
|
+
continue;
|
|
160302
160510
|
}
|
|
160303
|
-
|
|
160304
|
-
|
|
160511
|
+
const { payload } = plan.items[0];
|
|
160512
|
+
const r2 = await risk2.setRiskValueRaw(hazKey, payload);
|
|
160513
|
+
riskUpdates.push(formatSetDetail({ model: "P1-P2", classifier: "p2", optionName: update.p2, result: r2 }));
|
|
160305
160514
|
}
|
|
160306
160515
|
return { content: [{ type: "text", text: JSON.stringify({ requirements_created: results.length, results, risk_updates: riskUpdates, errors }, null, 2) }] };
|
|
160307
160516
|
});
|
|
@@ -184760,7 +184969,7 @@ var xrayClientSecret = process.env.XRAY_CLIENT_SECRET || "";
|
|
|
184760
184969
|
var xray = xrayClientId && xrayClientSecret ? new XrayClient(xrayClientId, xrayClientSecret, jiraUrl, jiraEmail, jiraToken) : null;
|
|
184761
184970
|
var server = new McpServer({
|
|
184762
184971
|
name: "jira-confluence",
|
|
184763
|
-
version: "0.1.
|
|
184972
|
+
version: "0.1.22"
|
|
184764
184973
|
});
|
|
184765
184974
|
var ctx = { server, jira, confluence, risk, xray };
|
|
184766
184975
|
registerJiraCrudTools(ctx);
|