v11y-check 0.19.6 → 0.19.8

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.
@@ -1,4 +1,48 @@
1
1
  [
2
+ {
3
+ "version": "0.19.8",
4
+ "date": "2026-10-28",
5
+ "sections": [
6
+ {
7
+ "title": "🧪 Tests",
8
+ "audience": "dev",
9
+ "items": [
10
+ {
11
+ "description": "Renames the values and helpers declared in v11y-check's tests and `src/test-utils` to follow the naming conventions, which require a value's name to end with its kind, a helper's name to lead with a verb, and abbreviations to be spelled out. (#1131)",
12
+ "hash": "bd0c26180b5d692ee2845eeea4a92a357027d7de",
13
+ "entry": 1
14
+ },
15
+ {
16
+ "description": "Replaces the `setupLoadConfig` and `setupTempDir` helpers, repeated in the `cli.audit`, `cli.check`, and `cli.sync` tests, with `buildLoadConfigResult` and `callWithFakeTempDir` in `src/test-utils/cli-fixtures.ts`. (#1131)",
17
+ "hash": "bd0c26180b5d692ee2845eeea4a92a357027d7de",
18
+ "entry": 2
19
+ }
20
+ ]
21
+ }
22
+ ]
23
+ },
24
+ {
25
+ "version": "0.19.7",
26
+ "date": "2026-10-27",
27
+ "sections": [
28
+ {
29
+ "title": "♻️ Refactoring",
30
+ "audience": "dev",
31
+ "items": [
32
+ {
33
+ "description": "Apply the naming conventions to nmr-core's identifiers (#1125)",
34
+ "body": "Renames the identifiers in nmr-core to follow the naming conventions, including the exported option keys of `updateManagedFile` and `writeFileWithCheck`, which change from `dryRun` and `overwrite` to `isDryRun` and `shouldOverwrite`, and the constant `GIT_OUTPUT_LIMIT`, which becomes `GIT_OUTPUT_LIMIT_BYTES`. Updates the call sites in nmr, release-kit, and v11y-check to the new names.",
35
+ "hash": "2cb60f628512ed6ec2273a219a7b6c71aa35b1bf"
36
+ },
37
+ {
38
+ "description": "Renames the identifiers in `v11y-check`'s source and its readyup kit to the naming conventions, including the exported `CommandOptions.json` (now `isJson`) and the kit check `noLegacyAuditCiDirectory` (now `hasNoLegacyAuditCiDirectory`), and leaves the CLI flags and the JSON output keys as they were. (#1127)",
39
+ "hash": "b306cefc52c6e2a4625b99aad62c71799e5e9fd5",
40
+ "entry": 1
41
+ }
42
+ ]
43
+ }
44
+ ]
45
+ },
2
46
  {
3
47
  "version": "0.19.6",
4
48
  "date": "2026-10-24",
@@ -1,6 +1,6 @@
1
1
  /** @noformat -- @generated. Do not edit. Compiled by rdy. */
2
2
  /* eslint-disable */
3
- export const __readyupVersion = "0.43.0";
3
+ export const __readyupVersion = "0.44.0";
4
4
 
5
5
 
6
6
  // .readyup/kits/default.ts
@@ -40,7 +40,7 @@ var default_default = defineRdyKit({
40
40
  name: "audit-ci configs are under .config/audit-ci/",
41
41
  severity: "warn",
42
42
  quiet: true,
43
- check: noLegacyAuditCiDirectory,
43
+ check: hasNoLegacyAuditCiDirectory,
44
44
  fix: "Move audit-ci configs from .audit-ci/ to .config/audit-ci/ and update references"
45
45
  },
46
46
  // -- Audit workflow --
@@ -63,17 +63,17 @@ var default_default = defineRdyKit({
63
63
  ]
64
64
  });
65
65
  function getMinVersion() {
66
- const picked = { "version": "0.19.6" };
67
- if (typeof picked["version"] !== "string") {
66
+ const pickedFields = { "version": "0.19.8" };
67
+ if (typeof pickedFields["version"] !== "string") {
68
68
  throw new TypeError("v11y-check/package.json: 'version' must be a string");
69
69
  }
70
- return picked["version"];
70
+ return pickedFields["version"];
71
71
  }
72
- function noLegacyAuditCiDirectory() {
72
+ function hasNoLegacyAuditCiDirectory() {
73
73
  return !existsSync(join(process.cwd(), ".audit-ci"));
74
74
  }
75
75
  export {
76
76
  AUDIT_WORKFLOW_HASH,
77
77
  default_default as default,
78
- noLegacyAuditCiDirectory
78
+ hasNoLegacyAuditCiDirectory
79
79
  };
@@ -7,7 +7,7 @@
7
7
  "checklist": "v11y-check",
8
8
  "checks": [
9
9
  "v11y-check in devDependencies",
10
- "v11y-check >= 0.19.6",
10
+ "v11y-check >= 0.19.8",
11
11
  "audit-ci configs are under .config/audit-ci/",
12
12
  "audit.yaml workflow exists",
13
13
  "audit.yaml matches template"
@@ -20,12 +20,12 @@
20
20
  "esbuildVersion": "0.28.2",
21
21
  "inputs": [
22
22
  {
23
- "hash": "3ca06efb",
23
+ "hash": "d19aa2e6",
24
24
  "kind": "module",
25
25
  "path": "kits/default.ts"
26
26
  },
27
27
  {
28
- "hash": "2c62576f",
28
+ "hash": "7f64b742",
29
29
  "kind": "inline",
30
30
  "path": "../package.json",
31
31
  "paths": [
@@ -35,10 +35,10 @@
35
35
  ],
36
36
  "name": "default",
37
37
  "path": "kits/default.js",
38
- "readyupVersion": "0.43.0",
38
+ "readyupVersion": "0.44.0",
39
39
  "source": "kits/default.ts",
40
- "sourceHash": "3ca06efb",
41
- "targetHash": "217cf274"
40
+ "sourceHash": "d19aa2e6",
41
+ "targetHash": "cdd8ef79"
42
42
  }
43
43
  ]
44
44
  }
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 0.19.8 — 2026-10-28
6
+
7
+ ### 🧪 Tests
8
+
9
+ - Renames the values and helpers declared in v11y-check's tests and `src/test-utils` to follow the naming conventions, which require a value's name to end with its kind, a helper's name to lead with a verb, and abbreviations to be spelled out. (#1131)
10
+ - Replaces the `setupLoadConfig` and `setupTempDir` helpers, repeated in the `cli.audit`, `cli.check`, and `cli.sync` tests, with `buildLoadConfigResult` and `callWithFakeTempDir` in `src/test-utils/cli-fixtures.ts`. (#1131)
11
+
12
+ ## 0.19.7 — 2026-10-27
13
+
14
+ ### ♻️ Refactoring
15
+
16
+ - Apply the naming conventions to nmr-core's identifiers (#1125)
17
+
18
+ Renames the identifiers in nmr-core to follow the naming conventions, including the exported option keys of `updateManagedFile` and `writeFileWithCheck`, which change from `dryRun` and `overwrite` to `isDryRun` and `shouldOverwrite`, and the constant `GIT_OUTPUT_LIMIT`, which becomes `GIT_OUTPUT_LIMIT_BYTES`. Updates the call sites in nmr, release-kit, and v11y-check to the new names.
19
+
20
+ - Renames the identifiers in `v11y-check`'s source and its readyup kit to the naming conventions, including the exported `CommandOptions.json` (now `isJson`) and the kit check `noLegacyAuditCiDirectory` (now `hasNoLegacyAuditCiDirectory`), and leaves the CLI flags and the JSON output keys as they were. (#1127)
21
+
5
22
  ## 0.19.6 — 2026-10-24
6
23
 
7
24
  ### 🧪 Tests
@@ -80,36 +80,36 @@ Options:
80
80
  }
81
81
  function parseSharedFlags(flags, styles) {
82
82
  const flagSchema = {
83
- config: { long: '--config', type: 'string' },
84
- dev: { long: '--dev', type: 'boolean' },
85
- json: { long: '--json', type: 'boolean', short: '-j' },
86
- prod: { long: '--prod', type: 'boolean' },
83
+ configPath: { long: '--config', type: 'string' },
84
+ isDev: { long: '--dev', type: 'boolean' },
85
+ isJson: { long: '--json', type: 'boolean', short: '-j' },
86
+ isProd: { long: '--prod', type: 'boolean' },
87
87
  verbose: { long: '--verbose', type: 'boolean', short: '-v' },
88
88
  };
89
- const { flags: parsed } = parseArgs(flags, flagSchema);
90
- if (parsed.dev && parsed.prod) {
89
+ const { flags: parsedFlags } = parseArgs(flags, flagSchema);
90
+ if (parsedFlags.isDev && parsedFlags.isProd) {
91
91
  throw new Error('Cannot specify both --dev and --prod');
92
92
  }
93
93
  const scopes = [];
94
- if (parsed.dev)
94
+ if (parsedFlags.isDev)
95
95
  scopes.push('dev');
96
- if (parsed.prod)
96
+ if (parsedFlags.isProd)
97
97
  scopes.push('prod');
98
98
  return {
99
- configPath: parsed.config,
100
- json: parsed.json,
99
+ configPath: parsedFlags.configPath,
100
+ isJson: parsedFlags.isJson,
101
101
  scopes,
102
102
  styles,
103
- verbose: parsed.verbose,
103
+ verbose: parsedFlags.verbose,
104
104
  };
105
105
  }
106
106
  function findTypoMatch(input) {
107
107
  if (input.length < MIN_PREFIX_LENGTH || input.startsWith('-')) {
108
108
  return undefined;
109
109
  }
110
- for (const cmd of SUBCOMMANDS) {
111
- if (cmd !== input && cmd.startsWith(input)) {
112
- return cmd;
110
+ for (const subcommand of SUBCOMMANDS) {
111
+ if (subcommand !== input && subcommand.startsWith(input)) {
112
+ return subcommand;
113
113
  }
114
114
  }
115
115
  return undefined;
@@ -159,9 +159,9 @@ export async function routeCommand(args) {
159
159
  }
160
160
  return handleSubcommand(args, styles, checkCommand);
161
161
  }
162
- async function handleSubcommand(flags, styles, handler, helpFn = showHelp) {
162
+ async function handleSubcommand(flags, styles, runSubcommand, showSubcommandHelp = showHelp) {
163
163
  if (flags.some((f) => f === '--help' || f === '-h')) {
164
- helpFn();
164
+ showSubcommandHelp();
165
165
  return 0;
166
166
  }
167
167
  let options;
@@ -173,7 +173,7 @@ async function handleSubcommand(flags, styles, handler, helpFn = showHelp) {
173
173
  return 1;
174
174
  }
175
175
  try {
176
- return await handler(options);
176
+ return await runSubcommand(options);
177
177
  }
178
178
  catch (error) {
179
179
  reportError(describeError(error));
@@ -186,18 +186,18 @@ function handleInit(flags, styles) {
186
186
  return 0;
187
187
  }
188
188
  const initFlagSchema = {
189
- dryRun: { long: '--dry-run', type: 'boolean', short: '-n' },
190
- force: { long: '--force', type: 'boolean', short: '-f' },
189
+ isDryRun: { long: '--dry-run', type: 'boolean', short: '-n' },
190
+ shouldForce: { long: '--force', type: 'boolean', short: '-f' },
191
191
  };
192
- let parsed;
192
+ let parsedArgs;
193
193
  try {
194
- parsed = parseArgs(flags, initFlagSchema);
194
+ parsedArgs = parseArgs(flags, initFlagSchema);
195
195
  }
196
196
  catch (error) {
197
197
  reportError(describeError(error));
198
198
  return 1;
199
199
  }
200
- return initCommand({ dryRun: parsed.flags.dryRun, force: parsed.flags.force, styles });
200
+ return initCommand({ isDryRun: parsedArgs.flags.isDryRun, shouldForce: parsedArgs.flags.shouldForce, styles });
201
201
  }
202
202
  function handleUpdateTemplates(flags, styles) {
203
203
  if (flags.some((f) => f === '--help' || f === '-h')) {
@@ -205,15 +205,15 @@ function handleUpdateTemplates(flags, styles) {
205
205
  return 0;
206
206
  }
207
207
  const updateTemplatesFlagSchema = {
208
- dryRun: { long: '--dry-run', type: 'boolean', short: '-n' },
208
+ isDryRun: { long: '--dry-run', type: 'boolean', short: '-n' },
209
209
  };
210
- let parsed;
210
+ let parsedArgs;
211
211
  try {
212
- parsed = parseArgs(flags, updateTemplatesFlagSchema);
212
+ parsedArgs = parseArgs(flags, updateTemplatesFlagSchema);
213
213
  }
214
214
  catch (error) {
215
215
  reportError(describeError(error));
216
216
  return 1;
217
217
  }
218
- return updateTemplatesCommand({ dryRun: parsed.flags.dryRun, styles });
218
+ return updateTemplatesCommand({ isDryRun: parsedArgs.flags.isDryRun, styles });
219
219
  }
package/dist/esm/cli.js CHANGED
@@ -11,15 +11,15 @@ import { syncAllowlist } from "./sync.js";
11
11
  import { withTempDir } from "./tmp.js";
12
12
  import { AUDIT_SCOPES, isSeverityAtOrAbove, } from "./types.js";
13
13
  export async function auditCommand(options) {
14
- let loaded;
14
+ let loadedConfigResult;
15
15
  try {
16
- loaded = await loadConfig(options.configPath);
16
+ loadedConfigResult = await loadConfig(options.configPath);
17
17
  }
18
18
  catch (error) {
19
19
  reportError(describeError(error));
20
20
  return 1;
21
21
  }
22
- const { config } = loaded;
22
+ const { config } = loadedConfigResult;
23
23
  const scopes = options.scopes.length > 0 ? options.scopes : [...AUDIT_SCOPES];
24
24
  try {
25
25
  return await withTempDir(async (tempDir) => {
@@ -27,21 +27,21 @@ export async function auditCommand(options) {
27
27
  const allResults = [];
28
28
  for (const scope of scopes) {
29
29
  const configPath = await generateAuditCiConfig(config[scope], scope, tempDir);
30
- const result = runAudit({ configPath, json: options.json });
30
+ const result = runAudit({ configPath, isJson: options.isJson });
31
31
  for (const warning of result.warnings) {
32
32
  process.stderr.write(`warning: ${warning}\n`);
33
33
  }
34
34
  if (result.staleEntries.length > 0) {
35
35
  process.stderr.write(`warning: stale allowlist entries in ${scope}: ${result.staleEntries.join(', ')}\n`);
36
36
  }
37
- if (options.json) {
38
- const parsed = parseAuditCiOutput(result.stdout);
39
- for (const warning of parsed.warnings) {
37
+ if (options.isJson) {
38
+ const parsedOutput = parseAuditCiOutput(result.stdout);
39
+ for (const warning of parsedOutput.warnings) {
40
40
  process.stderr.write(`warning: ${warning}\n`);
41
41
  }
42
- for (const r of parsed.results) {
43
- if (allResults.every((existing) => existing.id !== r.id)) {
44
- allResults.push(r);
42
+ for (const auditResult of parsedOutput.results) {
43
+ if (allResults.every((existingResult) => existingResult.id !== auditResult.id)) {
44
+ allResults.push(auditResult);
45
45
  }
46
46
  }
47
47
  }
@@ -57,7 +57,7 @@ export async function auditCommand(options) {
57
57
  exitCode = result.exitCode;
58
58
  }
59
59
  }
60
- if (options.json) {
60
+ if (options.isJson) {
61
61
  process.stdout.write(JSON.stringify(allResults, null, 2) + '\n');
62
62
  }
63
63
  return exitCode;
@@ -70,15 +70,15 @@ export async function auditCommand(options) {
70
70
  }
71
71
  const CHECK_SCOPE_ORDER = ['prod', 'dev'];
72
72
  export async function checkCommand(options) {
73
- let loaded;
73
+ let loadedConfigResult;
74
74
  try {
75
- loaded = await loadConfig(options.configPath);
75
+ loadedConfigResult = await loadConfig(options.configPath);
76
76
  }
77
77
  catch (error) {
78
78
  reportError(describeError(error));
79
79
  return 1;
80
80
  }
81
- const { config } = loaded;
81
+ const { config } = loadedConfigResult;
82
82
  const requestedScopes = options.scopes.length > 0 ? options.scopes : [...CHECK_SCOPE_ORDER];
83
83
  const scopes = CHECK_SCOPE_ORDER.filter((s) => requestedScopes.includes(s));
84
84
  try {
@@ -92,8 +92,8 @@ export async function checkCommand(options) {
92
92
  const scopeConfig = config[scope];
93
93
  const effectiveThreshold = scopeConfig.severityThreshold ?? 'low';
94
94
  thresholds[scope] = effectiveThreshold;
95
- const strippedScope = { ...scopeConfig, allowlist: [], severityThreshold: 'low' };
96
- const strippedConfigPath = await generateAuditCiConfig(strippedScope, scope, tempDir);
95
+ const strippedScopeConfig = { ...scopeConfig, allowlist: [], severityThreshold: 'low' };
96
+ const strippedConfigPath = await generateAuditCiConfig(strippedScopeConfig, scope, tempDir);
97
97
  const reportOptions = { configPath: strippedConfigPath };
98
98
  if (options.verbose) {
99
99
  reportOptions.reportType = 'full';
@@ -115,7 +115,7 @@ export async function checkCommand(options) {
115
115
  }
116
116
  else if (allowedIds.has(result.id)) {
117
117
  const entry = allowlistById.get(result.id);
118
- scopeResult.allowed.push(buildAllowedVuln(result, entry));
118
+ scopeResult.allowed.push(buildAllowedVulnerability(result, entry));
119
119
  }
120
120
  else {
121
121
  scopeResult.unallowed.push(result);
@@ -128,10 +128,10 @@ export async function checkCommand(options) {
128
128
  }
129
129
  checkResult[scope] = scopeResult;
130
130
  }
131
- if (options.verbose && !options.json) {
131
+ if (options.verbose && !options.isJson) {
132
132
  process.stdout.write(formatCheckVerboseText(checkResult, scopes, options.styles.stdout, undefined, thresholds));
133
133
  }
134
- else if (options.json) {
134
+ else if (options.isJson) {
135
135
  process.stdout.write(formatCheckJson(checkResult, scopes));
136
136
  }
137
137
  else {
@@ -147,38 +147,38 @@ export async function checkCommand(options) {
147
147
  }
148
148
  }
149
149
  export async function syncCommand(options) {
150
- let loaded;
150
+ let loadedConfigResult;
151
151
  try {
152
- loaded = await loadConfig(options.configPath);
152
+ loadedConfigResult = await loadConfig(options.configPath);
153
153
  }
154
154
  catch (error) {
155
155
  reportError(describeError(error));
156
156
  return 1;
157
157
  }
158
- const { configSource } = loaded;
158
+ const { configSource } = loadedConfigResult;
159
159
  if (configSource === 'defaults') {
160
- const { configResult } = scaffoldConfig({ dryRun: false });
160
+ const { configResult } = scaffoldConfig({ isDryRun: false });
161
161
  if (configResult.outcome === 'failed') {
162
162
  reportError('Failed to create config file');
163
163
  return 1;
164
164
  }
165
- loaded = await loadConfig(options.configPath);
165
+ loadedConfigResult = await loadConfig(options.configPath);
166
166
  }
167
- let { config } = loaded;
168
- const { configFilePath } = loaded;
167
+ let { config } = loadedConfigResult;
168
+ const { configFilePath } = loadedConfigResult;
169
169
  const scopes = options.scopes.length > 0 ? options.scopes : [...AUDIT_SCOPES];
170
170
  try {
171
171
  return await withTempDir(async (tempDir) => {
172
172
  for (const scope of scopes) {
173
- const strippedScope = { ...config[scope], allowlist: [] };
174
- const strippedConfigPath = await generateAuditCiConfig(strippedScope, scope, tempDir);
173
+ const strippedScopeConfig = { ...config[scope], allowlist: [] };
174
+ const strippedConfigPath = await generateAuditCiConfig(strippedScopeConfig, scope, tempDir);
175
175
  const report = runReport({ configPath: strippedConfigPath });
176
176
  for (const warning of report.warnings) {
177
177
  process.stderr.write(`warning: ${warning}\n`);
178
178
  }
179
179
  const { syncResult, updatedConfig } = await syncAllowlist(config, scope, report.results, configFilePath);
180
180
  config = updatedConfig;
181
- if (options.json) {
181
+ if (options.isJson) {
182
182
  process.stdout.write(JSON.stringify(syncResult, null, 2) + '\n');
183
183
  }
184
184
  else {
@@ -189,8 +189,8 @@ export async function syncCommand(options) {
189
189
  }
190
190
  }
191
191
  if (configSource === 'defaults') {
192
- const totalEntries = config.dev.allowlist.length + config.prod.allowlist.length;
193
- process.stdout.write(`Created config at ${configFilePath} with ${totalEntries} allowed entries.\n`);
192
+ const allowedEntryCount = config.dev.allowlist.length + config.prod.allowlist.length;
193
+ process.stdout.write(`Created config at ${configFilePath} with ${allowedEntryCount} allowed entries.\n`);
194
194
  }
195
195
  return 0;
196
196
  });
@@ -200,26 +200,26 @@ export async function syncCommand(options) {
200
200
  return 1;
201
201
  }
202
202
  }
203
- function buildAllowedVuln(result, entry) {
204
- const allowed = {
203
+ function buildAllowedVulnerability(result, entry) {
204
+ const allowedVulnerability = {
205
205
  id: result.id,
206
206
  path: result.path,
207
207
  paths: result.paths,
208
208
  url: result.url,
209
209
  };
210
210
  if (result.ghsaId !== undefined)
211
- allowed.ghsaId = result.ghsaId;
211
+ allowedVulnerability.ghsaId = result.ghsaId;
212
212
  if (result.severity !== undefined)
213
- allowed.severity = result.severity;
213
+ allowedVulnerability.severity = result.severity;
214
214
  if (result.title !== undefined)
215
- allowed.title = result.title;
215
+ allowedVulnerability.title = result.title;
216
216
  if (result.description !== undefined)
217
- allowed.description = result.description;
217
+ allowedVulnerability.description = result.description;
218
218
  if (result.cvss !== undefined)
219
- allowed.cvss = result.cvss;
219
+ allowedVulnerability.cvss = result.cvss;
220
220
  if (entry?.reason !== undefined)
221
- allowed.reason = entry.reason;
221
+ allowedVulnerability.reason = entry.reason;
222
222
  if (entry?.addedAt !== undefined)
223
- allowed.addedAt = entry.addedAt;
224
- return allowed;
223
+ allowedVulnerability.addedAt = entry.addedAt;
224
+ return allowedVulnerability;
225
225
  }
@@ -15,24 +15,24 @@ export async function loadConfig(configPath, cwd) {
15
15
  configSource: 'defaults',
16
16
  };
17
17
  }
18
- let raw;
18
+ let rawContent;
19
19
  try {
20
- raw = await readFile(filePath, 'utf8');
20
+ rawContent = await readFile(filePath, 'utf8');
21
21
  }
22
22
  catch {
23
23
  throw new Error(`Config file not found: ${filePath}`);
24
24
  }
25
- let parsed;
25
+ let parsedConfig;
26
26
  try {
27
- parsed = JSON.parse(raw);
27
+ parsedConfig = JSON.parse(rawContent);
28
28
  }
29
29
  catch {
30
30
  throw new Error(`Config file is not valid JSON: ${filePath}`);
31
31
  }
32
- const result = v11yCheckConfigSchema.safeParse(parsed);
32
+ const result = v11yCheckConfigSchema.safeParse(parsedConfig);
33
33
  if (!result.success) {
34
- const issues = result.error.issues.map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`).join('\n');
35
- throw new Error(`Invalid config in ${filePath}:\n${issues}`);
34
+ const issueText = result.error.issues.map((issue) => ` - ${issue.path.join('.')}: ${issue.message}`).join('\n');
35
+ throw new Error(`Invalid config in ${filePath}:\n${issueText}`);
36
36
  }
37
37
  return { config: result.data, configDir, configFilePath: filePath, configSource: 'file' };
38
38
  }
@@ -1,6 +1,6 @@
1
- const HINT_ADD = 'Run `v11y sync` to add the listed vulnerabilities to the allowlist.';
2
- const HINT_REMOVE = 'Run `v11y sync` to remove stale allowlist entries.';
3
- const HINT_BOTH = 'Run `v11y sync` to add the listed vulnerabilities to the allowlist and remove stale entries.';
1
+ const ADD_SYNC_HINT = 'Run `v11y sync` to add the listed vulnerabilities to the allowlist.';
2
+ const REMOVE_SYNC_HINT = 'Run `v11y sync` to remove stale allowlist entries.';
3
+ const ADD_AND_REMOVE_SYNC_HINT = 'Run `v11y sync` to add the listed vulnerabilities to the allowlist and remove stale entries.';
4
4
  function buildVerboseFlag(scopes) {
5
5
  if (scopes.length === 1) {
6
6
  return `--${scopes[0]} --verbose`;
@@ -9,24 +9,24 @@ function buildVerboseFlag(scopes) {
9
9
  }
10
10
  function selectSyncHint(hasUnallowed, hasStale) {
11
11
  if (hasUnallowed && hasStale)
12
- return HINT_BOTH;
12
+ return ADD_AND_REMOVE_SYNC_HINT;
13
13
  if (hasUnallowed)
14
- return HINT_ADD;
15
- return HINT_REMOVE;
14
+ return ADD_SYNC_HINT;
15
+ return REMOVE_SYNC_HINT;
16
16
  }
17
17
  export function formatActionHints(result, scopes) {
18
18
  const hasUnallowed = scopes.some((scope) => result[scope].unallowed.length > 0);
19
19
  const hasAllowed = scopes.some((scope) => result[scope].allowed.length > 0);
20
20
  const hasStale = scopes.some((scope) => result[scope].stale.length > 0);
21
- const hasVulns = hasUnallowed || hasAllowed;
22
- const needsSync = hasUnallowed || hasStale;
23
- if (!hasVulns && !needsSync)
21
+ const hasVulnerabilities = hasUnallowed || hasAllowed;
22
+ const isSyncNeeded = hasUnallowed || hasStale;
23
+ if (!hasVulnerabilities && !isSyncNeeded)
24
24
  return '';
25
25
  const bullets = [];
26
- if (hasVulns) {
26
+ if (hasVulnerabilities) {
27
27
  bullets.push(` \u{2022} Run \`v11y check ${buildVerboseFlag(scopes)}\` for full report`);
28
28
  }
29
- if (needsSync) {
29
+ if (isSyncNeeded) {
30
30
  bullets.push(` \u{2022} ${selectSyncHint(hasUnallowed, hasStale)}`);
31
31
  }
32
32
  return ` Actions:\n${bullets.join('\n')}`;
@@ -1,7 +1,7 @@
1
1
  import { type OutputStyle } from '@williamthorsen/nmr-core';
2
2
  import type { AuditResult, AuditScope, SeverityThreshold } from './types.js';
3
3
  /** An audit finding that the allowlist admits, with the entry's reason and date. */
4
- export interface AllowedVuln {
4
+ export interface AllowedVulnerability {
5
5
  addedAt?: string | undefined;
6
6
  cvss?: {
7
7
  score?: number;
@@ -23,7 +23,7 @@ export interface StaleEntry {
23
23
  }
24
24
  /** Check results for a single scope. */
25
25
  export interface ScopeCheckResult {
26
- allowed: AllowedVuln[];
26
+ allowed: AllowedVulnerability[];
27
27
  belowThreshold: AuditResult[];
28
28
  stale: StaleEntry[];
29
29
  unallowed: AuditResult[];
@@ -34,9 +34,9 @@ export interface CheckResult {
34
34
  prod: ScopeCheckResult;
35
35
  }
36
36
  /** Maps a severity string to its indicator in a style: a colored circle when rich, nothing when plain. */
37
- export declare function severityIndicator(severity: string | undefined, style: OutputStyle): string;
37
+ export declare function getSeverityIndicator(severity: string | undefined, style: OutputStyle): string;
38
38
  /** Resolves the best display ID for a vulnerability: GHSA ID if available, otherwise the numeric ID. */
39
- export declare function displayId(vuln: {
39
+ export declare function resolveDisplayId(vulnerability: {
40
40
  ghsaId?: string | undefined;
41
41
  id: string;
42
42
  }): string;