ohrisk 0.127.0
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 +571 -0
- package/LICENSE +21 -0
- package/README.md +416 -0
- package/dist/cli.js +21875 -0
- package/package.json +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# Ohrisk
|
|
2
|
+
|
|
3
|
+
Ohrisk catches open-source license risk before your PR ships.
|
|
4
|
+
|
|
5
|
+
It is a local CLI for developers who need a quick answer to questions like:
|
|
6
|
+
|
|
7
|
+
- Did this dependency bring in AGPL, GPL, BUSL, or unknown license evidence?
|
|
8
|
+
- Is the risky package production-relevant or dev-only?
|
|
9
|
+
- Which parent package introduced the transitive risk?
|
|
10
|
+
- Does the answer change for SaaS versus distributed app usage?
|
|
11
|
+
|
|
12
|
+
Ohrisk is a risk decision aid, not legal advice. It reports `low`, `review`,
|
|
13
|
+
`high`, and `unknown` findings for the selected usage profile.
|
|
14
|
+
|
|
15
|
+
## When to use it
|
|
16
|
+
|
|
17
|
+
Run Ohrisk when you are about to add or upgrade a dependency and want a fast,
|
|
18
|
+
local read on whether the license evidence introduces risk for your shipping
|
|
19
|
+
model. It sits between "I just installed a package" and "legal review."
|
|
20
|
+
|
|
21
|
+
- before opening a PR that adds or changes dependencies
|
|
22
|
+
- before cutting a release or tagging a build
|
|
23
|
+
- when a transitive dependency surprise appears in a lockfile diff
|
|
24
|
+
- when you need a SARIF or SBOM artifact for a compliance pipeline
|
|
25
|
+
|
|
26
|
+
Ohrisk does not approve or block packages on its own. It gives you the
|
|
27
|
+
evidence and a profile-aware severity so you can decide.
|
|
28
|
+
|
|
29
|
+
## Commands
|
|
30
|
+
|
|
31
|
+
| Command | What it answers |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| `ohrisk scan` | What does my dependency tree look like right now? Non-failing local decision aid. |
|
|
34
|
+
| `ohrisk ci` | Should this PR fail the build? Runs a scan and exits non-zero when findings meet `--fail-on`. |
|
|
35
|
+
| `ohrisk diff <ref>` | What changed since the baseline git ref? Surfaces only new or meaningfully changed findings. |
|
|
36
|
+
| `ohrisk explain <expr>` | How would Ohrisk classify this license expression for a profile, without scanning a project? |
|
|
37
|
+
|
|
38
|
+
## Usage profiles
|
|
39
|
+
|
|
40
|
+
Ohrisk evaluates the same dependency tree differently depending on how you ship
|
|
41
|
+
software, because redistribution changes license obligations.
|
|
42
|
+
|
|
43
|
+
- `saas` (default): you run the service and do not redistribute the package
|
|
44
|
+
binaries to users. GPL-only copyleft such as GPL-2.0 and GPL-3.0 is treated
|
|
45
|
+
as `review` rather than an immediate block, because SaaS usage does not
|
|
46
|
+
trigger redistribution obligations. AGPL and source-available restrictions
|
|
47
|
+
remain `high`.
|
|
48
|
+
- `distributed-app`: you ship the package to users. GPL becomes `high` because
|
|
49
|
+
redistribution obligations apply. Weak copyleft (LGPL, MPL, EPL) is flagged as
|
|
50
|
+
`review`.
|
|
51
|
+
|
|
52
|
+
Pick the profile that matches how the dependency reaches your users:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
ohrisk scan --profile saas
|
|
56
|
+
ohrisk scan --profile distributed-app
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Runtime
|
|
60
|
+
|
|
61
|
+
Ohrisk is distributed as an npm package, and the packaged CLI runs on Node.js
|
|
62
|
+
`>=20.0.0`. Bun is used for Ohrisk development, tests, and packaging, but users
|
|
63
|
+
do not need Bun installed to run the published CLI.
|
|
64
|
+
|
|
65
|
+
Ohrisk scans Bun, npm package-lock/shrinkwrap, pnpm, Deno npm, and Yarn v1
|
|
66
|
+
lockfiles regardless of which package manager you use to install the CLI.
|
|
67
|
+
|
|
68
|
+
## Current Scope
|
|
69
|
+
|
|
70
|
+
The current implementation is the first npm-style vertical slice:
|
|
71
|
+
|
|
72
|
+
- Bun `bun.lock`, npm `package-lock.json`, npm `npm-shrinkwrap.json`, pnpm `pnpm-lock.yaml`, Deno `deno.lock`, and Yarn v1 `yarn.lock` project discovery
|
|
73
|
+
- Node-compatible packaged CLI entrypoint for npm, pnpm, Yarn, npx, pnpm dlx, and yarn dlx users
|
|
74
|
+
- explicit lockfile selection with `--lockfile <path>` for projects that contain more than one supported lockfile
|
|
75
|
+
- direct and transitive dependency graph extraction
|
|
76
|
+
- Bun, npm, pnpm, and Yarn v1 workspace projects are scanned from every workspace/importer package root
|
|
77
|
+
- Deno `deno.lock` projects are scanned for npm package dependencies recorded in `npm:` specifiers; remote URL imports and JSR packages are not scanned yet
|
|
78
|
+
- npm alias dependency resolution, including pnpm alias package keys, with alias context preserved in dependency paths
|
|
79
|
+
- production, development, optional, and peer dependency classification
|
|
80
|
+
- local `file:` package artifact evidence
|
|
81
|
+
- installed `node_modules` package evidence, including npm alias install names, before network fallback
|
|
82
|
+
- remote HTTP(S) package tarball evidence when the lockfile points to a tarball, with credential-bearing URLs, obvious local, private, special-purpose, and DNS-resolved internal hosts blocked before fetch, DNS answers rechecked at the default connection boundary, and redirects followed only after each target is validated
|
|
83
|
+
- lockfile integrity verification for local and remote package tarballs
|
|
84
|
+
- npm registry metadata lookup when the lockfile does not include a direct tarball URL
|
|
85
|
+
- gzipped package tarball evidence
|
|
86
|
+
- `package.json` license fields
|
|
87
|
+
- common root-level `LICENSE`, `LICENCE`, `UNLICENSE`, `COPYING`, and `NOTICE` file variants
|
|
88
|
+
- medium-confidence standard license detection from recognizable `LICENSE` and `COPYING` file text, including SPDX identifiers, GPL-family v2/v3 text, Zlib text, public-domain-style text, and malformed metadata pointers
|
|
89
|
+
- SPDX-like license expression parsing
|
|
90
|
+
- common human-readable license metadata alias normalization, including slash and comma dual-license shorthands
|
|
91
|
+
- low-risk classification for common permissive, Zlib, and public-domain-style SPDX licenses
|
|
92
|
+
- NOTICE evidence is surfaced as attribution-preservation action text without raising severity
|
|
93
|
+
- high-risk classification for common source-available restriction licenses
|
|
94
|
+
- explicit commercial restriction text detection in license evidence and package metadata
|
|
95
|
+
- profile-aware risk evaluation for `saas` and `distributed-app`
|
|
96
|
+
- terminal and JSON reports
|
|
97
|
+
- SARIF 2.1.0 reports for code scanning upload
|
|
98
|
+
- waived findings in SARIF output as externally suppressed results
|
|
99
|
+
- Markdown reports for PR comments and release notes
|
|
100
|
+
- CycloneDX 1.5 JSON SBOM reports with dependency relationships and Ohrisk risk decision properties
|
|
101
|
+
- stable finding IDs for PR comments and local waiver workflows
|
|
102
|
+
- local `.ohrisk-waivers.json` waivers by finding ID or fingerprint
|
|
103
|
+
- stable diff matching that ignores reason and evidence prose churn while surfacing severity, recommendation, and action changes
|
|
104
|
+
- exact finding fingerprints for SARIF partial fingerprints and audit trails
|
|
105
|
+
- finding fingerprints in terminal and Markdown reports for waiver and audit workflows
|
|
106
|
+
- structured dependency type and direct/transitive scope in findings
|
|
107
|
+
- report file output with `--output <file>`
|
|
108
|
+
- command-specific help with `ohrisk help <command>` and `ohrisk <command> --help`
|
|
109
|
+
- standalone license expression explanation
|
|
110
|
+
- git ref diff reports that show only new or meaningfully changed findings
|
|
111
|
+
- JSON threshold outcomes for `ci --fail-on` and `diff --fail-on`
|
|
112
|
+
- terminal and Markdown threshold outcomes for `ci --fail-on` and `diff --fail-on`
|
|
113
|
+
- strict CI waiver drift checks for expired or unmatched local waivers
|
|
114
|
+
- raw scan and CI mode with `--no-waivers` when waiver files should be ignored
|
|
115
|
+
- explicit waiver mode in JSON, terminal, Markdown, and SARIF reports
|
|
116
|
+
- explicit waiver mode in CycloneDX SBOM metadata
|
|
117
|
+
|
|
118
|
+
Central approval workflows, GitHub App checks, and ecosystem adapters beyond
|
|
119
|
+
npm-style lockfiles are not part of this slice yet.
|
|
120
|
+
|
|
121
|
+
## Usage
|
|
122
|
+
|
|
123
|
+
Install globally after the package is published:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
npm install -g ohrisk
|
|
127
|
+
pnpm add -g ohrisk
|
|
128
|
+
yarn global add ohrisk
|
|
129
|
+
bun add -g ohrisk
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Run once without a global install:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
npx ohrisk scan
|
|
136
|
+
pnpm dlx ohrisk scan
|
|
137
|
+
yarn dlx ohrisk scan
|
|
138
|
+
bunx ohrisk scan
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Run a local scan from a supported project:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
ohrisk scan
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Print command help or the installed package version:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
ohrisk help
|
|
151
|
+
ohrisk help scan
|
|
152
|
+
ohrisk version
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Supported lockfiles:
|
|
156
|
+
|
|
157
|
+
- `bun.lock`
|
|
158
|
+
- `package-lock.json` with either a modern `packages` section or an npm v1 dependency tree
|
|
159
|
+
- `npm-shrinkwrap.json` with the same package-lock parser support
|
|
160
|
+
- `pnpm-lock.yaml` with `importers`, `packages`, and `snapshots` sections
|
|
161
|
+
- `deno.lock` npm package entries from Deno v3/v4-style lockfiles
|
|
162
|
+
- Yarn v1 `yarn.lock` with root and workspace dependency sets from `package.json` manifests
|
|
163
|
+
|
|
164
|
+
Select a specific lockfile when a project contains more than one supported lockfile:
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
ohrisk scan --lockfile package-lock.json
|
|
168
|
+
ohrisk scan --lockfile npm-shrinkwrap.json
|
|
169
|
+
ohrisk ci --lockfile pnpm-lock.yaml --fail-on high
|
|
170
|
+
ohrisk scan --lockfile deno.lock
|
|
171
|
+
ohrisk diff main --lockfile bun.lock
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Pick the usage profile:
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
ohrisk scan --profile saas
|
|
178
|
+
ohrisk scan --profile distributed-app
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
Limit the scan to production-relevant dependencies by excluding development-only packages:
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
ohrisk scan --prod
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Print machine-readable output:
|
|
188
|
+
|
|
189
|
+
```bash
|
|
190
|
+
ohrisk scan --json
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Print SARIF output for code scanning upload:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
ohrisk scan --sarif
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Print a Markdown report:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
ohrisk scan --markdown --prod
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Print a CycloneDX SBOM:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
ohrisk scan --cyclonedx --prod
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Write a report to a file:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
ohrisk scan --sarif --output reports/ohrisk.sarif
|
|
215
|
+
ohrisk scan --cyclonedx --output reports/ohrisk.cdx.json
|
|
216
|
+
ohrisk diff main --prod --markdown --output reports/ohrisk-pr.md
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Fail a local CI step when findings meet a threshold:
|
|
220
|
+
|
|
221
|
+
```bash
|
|
222
|
+
ohrisk ci --fail-on high
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Fail a local CI step when waiver files contain expired or unmatched waivers:
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
ohrisk ci --strict-waivers
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Run a raw audit scan or CI step without reading local waiver files:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
ohrisk scan --no-waivers
|
|
235
|
+
ohrisk ci --no-waivers --fail-on high
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
Waive a finding locally by ID or fingerprint in `.ohrisk-waivers.json`:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
{
|
|
242
|
+
"waivers": [
|
|
243
|
+
{
|
|
244
|
+
"id": "agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0",
|
|
245
|
+
"reason": "Accepted for this release after internal review.",
|
|
246
|
+
"expiresOn": "2026-09-30"
|
|
247
|
+
}
|
|
248
|
+
]
|
|
249
|
+
}
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Waived findings are excluded from `ci --fail-on` threshold failures, but scan
|
|
253
|
+
and CI JSON, terminal, Markdown, and SARIF reports still show them. Terminal
|
|
254
|
+
and Markdown reports include finding fingerprints so waiver files can target
|
|
255
|
+
either `id` or `fingerprint`. Expired waivers and unmatched active waivers are
|
|
256
|
+
reported separately in JSON, terminal, and Markdown reports and are not applied.
|
|
257
|
+
`ci --strict-waivers` exits non-zero when either expired or unmatched waivers
|
|
258
|
+
are present, even if active findings stay below the `--fail-on` threshold. JSON,
|
|
259
|
+
terminal, Markdown, and SARIF outputs include the strict waiver drift result
|
|
260
|
+
when that option is enabled. `scan --no-waivers` and `ci --no-waivers` do not
|
|
261
|
+
read or apply local waiver files; `ci --no-waivers` cannot be combined with
|
|
262
|
+
`--strict-waivers`. Reports include a waiver mode field or summary line so raw
|
|
263
|
+
audits can distinguish ignored waiver files from projects with no waivers.
|
|
264
|
+
|
|
265
|
+
Explain a license expression without scanning a project:
|
|
266
|
+
|
|
267
|
+
```bash
|
|
268
|
+
ohrisk explain AGPL-3.0-only --profile saas
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
Compare the current findings against a baseline git ref:
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
ohrisk diff main --prod
|
|
275
|
+
ohrisk diff main --prod --fail-on unknown
|
|
276
|
+
ohrisk diff main --prod --markdown
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
Print the package version:
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
ohrisk --version
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
Once installed as a package, the intended command shape is:
|
|
286
|
+
|
|
287
|
+
```bash
|
|
288
|
+
ohrisk scan --profile saas --prod
|
|
289
|
+
ohrisk scan --lockfile package-lock.json
|
|
290
|
+
ohrisk scan --lockfile npm-shrinkwrap.json
|
|
291
|
+
ohrisk ci --fail-on high
|
|
292
|
+
ohrisk ci --strict-waivers
|
|
293
|
+
ohrisk scan --no-waivers
|
|
294
|
+
ohrisk ci --no-waivers --fail-on high
|
|
295
|
+
ohrisk scan --sarif
|
|
296
|
+
ohrisk scan --markdown --prod
|
|
297
|
+
ohrisk scan --cyclonedx --prod
|
|
298
|
+
ohrisk scan --sarif --output reports/ohrisk.sarif
|
|
299
|
+
ohrisk explain AGPL-3.0-only --profile saas
|
|
300
|
+
ohrisk diff main --prod --fail-on unknown
|
|
301
|
+
ohrisk --version
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Report Shape
|
|
305
|
+
|
|
306
|
+
The terminal report is designed to show the highest-risk findings first:
|
|
307
|
+
|
|
308
|
+
```text
|
|
309
|
+
Ohrisk scan
|
|
310
|
+
Profile: saas
|
|
311
|
+
Production only: yes
|
|
312
|
+
Risks: 1 high, 1 review, 1 unknown, 2 low
|
|
313
|
+
Waiver mode: local (.ohrisk-waivers.json)
|
|
314
|
+
Waived: 0 applied, 0 expired, 0 unmatched
|
|
315
|
+
|
|
316
|
+
Findings:
|
|
317
|
+
- [high] agpl-child@0.1.0
|
|
318
|
+
id: agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0
|
|
319
|
+
fingerprint: agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0::high::replace::License expression is high risk for saas.::license: AGPL-3.0-only|dependency: production|transitive dependency|source: local|package.json license: AGPL-3.0-only|file: COPYING (copying)
|
|
320
|
+
License expression is high risk for saas.
|
|
321
|
+
recommendation: replace
|
|
322
|
+
action: Replace this package or escalate before shipping.
|
|
323
|
+
dependency: production transitive
|
|
324
|
+
path: fixture-bun-project -> permissive-parent@1.0.0 -> agpl-child@0.1.0
|
|
325
|
+
evidence: license: AGPL-3.0-only; dependency: production; transitive dependency; source: local; package.json license: AGPL-3.0-only; file: COPYING (copying)
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
JSON output reuses the same finding model:
|
|
329
|
+
|
|
330
|
+
```json
|
|
331
|
+
{
|
|
332
|
+
"status": "profile_risk_evaluated",
|
|
333
|
+
"profile": "saas",
|
|
334
|
+
"prodOnly": true,
|
|
335
|
+
"waiverMode": "local",
|
|
336
|
+
"nextAction": "Replace or escalate high-risk dependencies before shipping.",
|
|
337
|
+
"failOn": "high",
|
|
338
|
+
"failed": true,
|
|
339
|
+
"failingFindingCount": 1,
|
|
340
|
+
"findings": [
|
|
341
|
+
{
|
|
342
|
+
"id": "agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0",
|
|
343
|
+
"fingerprint": "agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0::high::replace::License expression is high risk for saas.::license: AGPL-3.0-only|dependency: production|transitive dependency",
|
|
344
|
+
"packageId": "agpl-child@0.1.0",
|
|
345
|
+
"severity": "high",
|
|
346
|
+
"reason": "License expression is high risk for saas.",
|
|
347
|
+
"recommendation": "replace",
|
|
348
|
+
"action": "Replace this package or escalate before shipping.",
|
|
349
|
+
"dependencyType": "production",
|
|
350
|
+
"dependencyScope": "transitive",
|
|
351
|
+
"paths": [
|
|
352
|
+
[
|
|
353
|
+
"fixture-bun-project",
|
|
354
|
+
"permissive-parent@1.0.0",
|
|
355
|
+
"agpl-child@0.1.0"
|
|
356
|
+
]
|
|
357
|
+
]
|
|
358
|
+
}
|
|
359
|
+
]
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
Markdown output keeps the scan summary and PR-facing decision fields together:
|
|
364
|
+
|
|
365
|
+
```markdown
|
|
366
|
+
- Licenses: `4 high-confidence`, `0 medium-confidence`, `1 low-confidence`
|
|
367
|
+
- License issues: `1 missing`, `0 malformed`
|
|
368
|
+
- Waiver mode: `local (.ohrisk-waivers.json)`
|
|
369
|
+
- Threshold: failed on high (1 finding at or above threshold)
|
|
370
|
+
|
|
371
|
+
| ID | Fingerprint | Severity | Package | Dependency | Reason | Recommendation | Action | Path |
|
|
372
|
+
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
|
|
373
|
+
| `agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0` | `agpl-child@0.1.0::production::transitive::fixture-bun-project>permissive-parent@1.0.0>agpl-child@0.1.0::high::replace::License expression is high risk for saas.::license: AGPL-3.0-only\|dependency: production\|transitive dependency\|source: local\|package.json license: AGPL-3.0-only\|file: COPYING (copying)` | high | `agpl-child@0.1.0` | production transitive | License expression is high risk for saas. | replace | Replace this package or escalate before shipping. | fixture-bun-project -> permissive-parent@1.0.0 -> agpl-child@0.1.0 |
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Risk Language
|
|
377
|
+
|
|
378
|
+
Ohrisk intentionally avoids legal `safe` or `unsafe` verdicts.
|
|
379
|
+
|
|
380
|
+
- `low`: known low-risk license expression for the selected profile
|
|
381
|
+
- `review`: review before shipping under the selected profile
|
|
382
|
+
- `high`: replace or escalate before shipping under the selected profile, including explicit commercial-use restrictions and packages marked `UNLICENSED`
|
|
383
|
+
- `unknown`: missing, malformed, or unrecognized license evidence
|
|
384
|
+
|
|
385
|
+
For example, GPL is treated differently for `saas` and `distributed-app`
|
|
386
|
+
because redistribution changes the risk profile.
|
|
387
|
+
|
|
388
|
+
## Development
|
|
389
|
+
|
|
390
|
+
Run the test suite:
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
bun test
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
Run the release-ready local gate:
|
|
397
|
+
|
|
398
|
+
```bash
|
|
399
|
+
bun run verify:release
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Run the fixture scan manually:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
cd test/fixtures/bun-project
|
|
406
|
+
bun run ../../../src/cli/main.ts scan --profile saas
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
## Documentation
|
|
410
|
+
|
|
411
|
+
- [Documentation Index](https://github.com/0disoft/ohrisk/blob/main/docs/README.md) — All guides in one place
|
|
412
|
+
- [CI Usage Guide](https://github.com/0disoft/ohrisk/blob/main/docs/ci.md) — GitHub Actions examples for PR gates and artifacts
|
|
413
|
+
- [Waiver Guide](https://github.com/0disoft/ohrisk/blob/main/docs/waivers.md) — Managing license risk waivers safely
|
|
414
|
+
- [Profile Guide](https://github.com/0disoft/ohrisk/blob/main/docs/profiles.md) — Choosing between saas and distributed-app
|
|
415
|
+
- [Report Formats Guide](https://github.com/0disoft/ohrisk/blob/main/docs/report-formats.md) — What each output format includes
|
|
416
|
+
- [한국어 사용 가이드](https://github.com/0disoft/ohrisk/blob/main/docs/ko/README.md) — Korean usage guide for developers
|