dsh-d365-kit 0.34.1 → 0.34.4
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/CHANGELOG.md +319 -308
- package/CHANGELOG.zh-CN.md +318 -307
- package/INSTALL.md +94 -94
- package/INSTALL.zh-CN.md +93 -93
- package/LICENSE +21 -21
- package/README.md +336 -327
- package/README.zh-CN.md +336 -327
- package/client.js +1818 -1818
- package/cordis.patch.yml +44 -44
- package/docs/en/architecture.md +172 -172
- package/docs/en/checks.md +184 -184
- package/docs/en/installation.md +151 -151
- package/docs/en/permissions.md +161 -161
- package/docs/en/scenarios.md +202 -202
- package/docs/en/tools.md +665 -665
- package/docs/en/troubleshooting.md +131 -131
- package/docs/zh/architecture.md +172 -172
- package/docs/zh/checks.md +184 -184
- package/docs/zh/installation.md +151 -151
- package/docs/zh/permissions.md +161 -161
- package/docs/zh/scenarios.md +202 -202
- package/docs/zh/tools.md +665 -665
- package/docs/zh/troubleshooting.md +131 -131
- package/examples/prompts.en.md +206 -206
- package/examples/prompts.zh-CN.md +206 -206
- package/examples/waivers.example.json +20 -20
- package/icon.svg +6 -6
- package/index.js +139 -139
- package/lib/auth.js +181 -181
- package/lib/client.js +496 -496
- package/lib/code-check.js +549 -549
- package/lib/config.js +323 -323
- package/lib/contract-history.js +49 -49
- package/lib/contract.js +583 -583
- package/lib/csharp-check.js +493 -493
- package/lib/data-migrate.js +1318 -1318
- package/lib/data-policy.js +78 -78
- package/lib/error-codes.js +80 -80
- package/lib/gitlab.js +161 -161
- package/lib/health.js +205 -205
- package/lib/migrate.js +732 -732
- package/lib/preflight.js +116 -116
- package/lib/refs.js +191 -191
- package/lib/resources.js +320 -320
- package/lib/retention-defaults.js +17 -17
- package/lib/retention.js +384 -384
- package/lib/runtime.js +232 -232
- package/lib/settings-http.js +512 -512
- package/lib/settings-store.js +371 -371
- package/lib/snapshot.js +149 -149
- package/lib/tool-code-check.js +133 -133
- package/lib/tool-configure.js +169 -169
- package/lib/tool-contract.js +376 -376
- package/lib/tool-data-sync.js +559 -559
- package/lib/tool-data-write.js +203 -203
- package/lib/tool-data.js +282 -282
- package/lib/tool-diff.js +484 -484
- package/lib/tool-environments.js +106 -106
- package/lib/tool-flows.js +540 -540
- package/lib/tool-health.js +127 -127
- package/lib/tool-layers.js +497 -497
- package/lib/tool-metadata.js +417 -417
- package/lib/tool-migrate.js +102 -102
- package/lib/tool-refs.js +206 -206
- package/lib/tool-reports.js +299 -299
- package/lib/tool-sync.js +430 -430
- package/lib/tool-write.js +563 -563
- package/lib/waivers.js +83 -83
- package/lib/write-actions.js +1374 -1374
- package/lib/write-policy.js +199 -199
- package/lib/write-store.js +167 -167
- package/locale/en.json +68 -68
- package/locale/zh.json +68 -68
- package/package.json +2 -2
- package/skills/d365-troubleshooting/SKILL.md +115 -115
package/lib/waivers.js
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Waivers: differences a team has decided to accept.
|
|
3
|
-
*
|
|
4
|
-
* A waiver is data, not code — it lives in `<data dir>/waivers.json` so it can
|
|
5
|
-
* be reviewed in a pull request. Every waiver must carry a reason and an expiry:
|
|
6
|
-
* an accepted difference that never expires is just a forgotten one.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { readFile, writeFile, mkdir } from 'node:fs/promises'
|
|
10
|
-
import { dirname, join } from 'node:path'
|
|
11
|
-
import { dataRoot } from './snapshot.js'
|
|
12
|
-
|
|
13
|
-
export function waiversPath(config) {
|
|
14
|
-
return join(dataRoot(config), 'waivers.json')
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const EMPTY = { waivers: [] }
|
|
18
|
-
|
|
19
|
-
export async function readWaivers(config) {
|
|
20
|
-
try {
|
|
21
|
-
const text = await readFile(waiversPath(config), 'utf8')
|
|
22
|
-
const parsed = JSON.parse(text.replace(/^\uFEFF/, ''))
|
|
23
|
-
return Array.isArray(parsed?.waivers) ? parsed : EMPTY
|
|
24
|
-
} catch (error) {
|
|
25
|
-
if (error?.code === 'ENOENT') return EMPTY
|
|
26
|
-
throw error
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function writeWaivers(config, document) {
|
|
31
|
-
const path = waiversPath(config)
|
|
32
|
-
await mkdir(dirname(path), { recursive: true })
|
|
33
|
-
await writeFile(path, JSON.stringify(document, null, 2), 'utf8')
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** Add or replace a waiver (same rule + env + object). */
|
|
37
|
-
export async function addWaiver(config, entry) {
|
|
38
|
-
const document = await readWaivers(config)
|
|
39
|
-
const key = `${entry.rule}|${entry.env}|${entry.object}`
|
|
40
|
-
document.waivers = document.waivers.filter(
|
|
41
|
-
(item) => `${item.rule}|${item.env}|${item.object}` !== key,
|
|
42
|
-
)
|
|
43
|
-
document.waivers.push(entry)
|
|
44
|
-
await writeWaivers(config, document)
|
|
45
|
-
return document.waivers
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export function isExpired(waiver, now = Date.now()) {
|
|
49
|
-
if (!waiver.expiresAt) return false
|
|
50
|
-
const at = Date.parse(waiver.expiresAt)
|
|
51
|
-
return Number.isFinite(at) && at < now
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** `*` matches everything, a trailing `*` matches a prefix. */
|
|
55
|
-
export function matchesWaiver(waiver, finding) {
|
|
56
|
-
if (waiver.rule !== finding.rule) return false
|
|
57
|
-
if (waiver.env !== '*' && waiver.env !== finding.env) return false
|
|
58
|
-
const object = String(waiver.object ?? '')
|
|
59
|
-
if (object === '*') return true
|
|
60
|
-
if (object.endsWith('*')) return String(finding.object).startsWith(object.slice(0, -1))
|
|
61
|
-
return object === String(finding.object)
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Split findings into kept and waived, and report expired waivers so the
|
|
66
|
-
* report can say "this waiver expired, so the finding is back".
|
|
67
|
-
*/
|
|
68
|
-
export function applyWaivers(findings, document, now = Date.now()) {
|
|
69
|
-
const active = []
|
|
70
|
-
const expired = []
|
|
71
|
-
for (const waiver of document.waivers ?? []) {
|
|
72
|
-
if (isExpired(waiver, now)) expired.push(waiver)
|
|
73
|
-
else active.push(waiver)
|
|
74
|
-
}
|
|
75
|
-
const kept = []
|
|
76
|
-
const waived = []
|
|
77
|
-
for (const finding of findings) {
|
|
78
|
-
const match = active.find((waiver) => matchesWaiver(waiver, finding))
|
|
79
|
-
if (match) waived.push({ ...finding, waiver: { reason: match.reason, expiresAt: match.expiresAt ?? null } })
|
|
80
|
-
else kept.push(finding)
|
|
81
|
-
}
|
|
82
|
-
return { kept, waived, expired }
|
|
83
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Waivers: differences a team has decided to accept.
|
|
3
|
+
*
|
|
4
|
+
* A waiver is data, not code — it lives in `<data dir>/waivers.json` so it can
|
|
5
|
+
* be reviewed in a pull request. Every waiver must carry a reason and an expiry:
|
|
6
|
+
* an accepted difference that never expires is just a forgotten one.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readFile, writeFile, mkdir } from 'node:fs/promises'
|
|
10
|
+
import { dirname, join } from 'node:path'
|
|
11
|
+
import { dataRoot } from './snapshot.js'
|
|
12
|
+
|
|
13
|
+
export function waiversPath(config) {
|
|
14
|
+
return join(dataRoot(config), 'waivers.json')
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const EMPTY = { waivers: [] }
|
|
18
|
+
|
|
19
|
+
export async function readWaivers(config) {
|
|
20
|
+
try {
|
|
21
|
+
const text = await readFile(waiversPath(config), 'utf8')
|
|
22
|
+
const parsed = JSON.parse(text.replace(/^\uFEFF/, ''))
|
|
23
|
+
return Array.isArray(parsed?.waivers) ? parsed : EMPTY
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (error?.code === 'ENOENT') return EMPTY
|
|
26
|
+
throw error
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function writeWaivers(config, document) {
|
|
31
|
+
const path = waiversPath(config)
|
|
32
|
+
await mkdir(dirname(path), { recursive: true })
|
|
33
|
+
await writeFile(path, JSON.stringify(document, null, 2), 'utf8')
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Add or replace a waiver (same rule + env + object). */
|
|
37
|
+
export async function addWaiver(config, entry) {
|
|
38
|
+
const document = await readWaivers(config)
|
|
39
|
+
const key = `${entry.rule}|${entry.env}|${entry.object}`
|
|
40
|
+
document.waivers = document.waivers.filter(
|
|
41
|
+
(item) => `${item.rule}|${item.env}|${item.object}` !== key,
|
|
42
|
+
)
|
|
43
|
+
document.waivers.push(entry)
|
|
44
|
+
await writeWaivers(config, document)
|
|
45
|
+
return document.waivers
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function isExpired(waiver, now = Date.now()) {
|
|
49
|
+
if (!waiver.expiresAt) return false
|
|
50
|
+
const at = Date.parse(waiver.expiresAt)
|
|
51
|
+
return Number.isFinite(at) && at < now
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** `*` matches everything, a trailing `*` matches a prefix. */
|
|
55
|
+
export function matchesWaiver(waiver, finding) {
|
|
56
|
+
if (waiver.rule !== finding.rule) return false
|
|
57
|
+
if (waiver.env !== '*' && waiver.env !== finding.env) return false
|
|
58
|
+
const object = String(waiver.object ?? '')
|
|
59
|
+
if (object === '*') return true
|
|
60
|
+
if (object.endsWith('*')) return String(finding.object).startsWith(object.slice(0, -1))
|
|
61
|
+
return object === String(finding.object)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Split findings into kept and waived, and report expired waivers so the
|
|
66
|
+
* report can say "this waiver expired, so the finding is back".
|
|
67
|
+
*/
|
|
68
|
+
export function applyWaivers(findings, document, now = Date.now()) {
|
|
69
|
+
const active = []
|
|
70
|
+
const expired = []
|
|
71
|
+
for (const waiver of document.waivers ?? []) {
|
|
72
|
+
if (isExpired(waiver, now)) expired.push(waiver)
|
|
73
|
+
else active.push(waiver)
|
|
74
|
+
}
|
|
75
|
+
const kept = []
|
|
76
|
+
const waived = []
|
|
77
|
+
for (const finding of findings) {
|
|
78
|
+
const match = active.find((waiver) => matchesWaiver(waiver, finding))
|
|
79
|
+
if (match) waived.push({ ...finding, waiver: { reason: match.reason, expiresAt: match.expiresAt ?? null } })
|
|
80
|
+
else kept.push(finding)
|
|
81
|
+
}
|
|
82
|
+
return { kept, waived, expired }
|
|
83
|
+
}
|