upstream-radar 0.33.11 → 0.34.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/README.md +69 -1029
- package/dist/src/cli.js +365 -19
- package/dist/src/cli.js.map +1 -1
- package/dist/src/dependency-index.d.ts +76 -0
- package/dist/src/dependency-index.d.ts.map +1 -0
- package/dist/src/dependency-index.js +199 -0
- package/dist/src/dependency-index.js.map +1 -0
- package/dist/src/dsh-case.d.ts +50 -0
- package/dist/src/dsh-case.d.ts.map +1 -0
- package/dist/src/dsh-case.js +88 -0
- package/dist/src/dsh-case.js.map +1 -0
- package/dist/src/dsh-review.d.ts +46 -0
- package/dist/src/dsh-review.d.ts.map +1 -0
- package/dist/src/dsh-review.js +209 -0
- package/dist/src/dsh-review.js.map +1 -0
- package/dist/src/graph.d.ts +5 -1
- package/dist/src/graph.d.ts.map +1 -1
- package/dist/src/graph.js +56 -10
- package/dist/src/graph.js.map +1 -1
- package/dist/src/index.d.ts +4 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +3 -0
- package/dist/src/index.js.map +1 -1
- package/dist/src/npm.d.ts +11 -0
- package/dist/src/npm.d.ts.map +1 -1
- package/dist/src/npm.js +122 -12
- package/dist/src/npm.js.map +1 -1
- package/dist/src/render.d.ts.map +1 -1
- package/dist/src/render.js +19 -0
- package/dist/src/render.js.map +1 -1
- package/dist/src/scan.d.ts.map +1 -1
- package/dist/src/scan.js +41 -0
- package/dist/src/scan.js.map +1 -1
- package/dist/src/types.d.ts +10 -0
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/upstream-observer.d.ts +85 -0
- package/dist/src/upstream-observer.d.ts.map +1 -1
- package/dist/src/upstream-observer.js +374 -21
- package/dist/src/upstream-observer.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.d.ts.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/docs/README.zh-CN.md +98 -22
- package/examples/cases/dsh-web-ui-issue-71/before/cordis.patch.yml +4 -0
- package/examples/cases/dsh-web-ui-issue-71/before/node_modules/@linxin666/dsh-client-ui-skin-center/cordis.patch.yml +1 -0
- package/examples/cases/dsh-web-ui-issue-71/before/node_modules/@linxin666/dsh-client-ui-skin-center/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/before/node_modules/@linxin666/dsh-web-ui-all/cordis.patch.yml +1 -0
- package/examples/cases/dsh-web-ui-issue-71/before/node_modules/@linxin666/dsh-web-ui-all/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/before/package.json +12 -0
- package/examples/cases/dsh-web-ui-issue-71/before/pnpm-lock.yaml +21 -0
- package/examples/cases/dsh-web-ui-issue-71/before/pnpm-workspace.yaml +7 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/cordis.patch.yml +3 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/node_modules/@linxin666/dsh-client-ui-skin-center/cordis.patch.yml +1 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/node_modules/@linxin666/dsh-client-ui-skin-center/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/node_modules/@linxin666/dsh-web-ui-all/cordis.patch.yml +1 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/node_modules/@linxin666/dsh-web-ui-all/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/package.json +12 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/pnpm-lock.yaml +18 -0
- package/examples/cases/dsh-web-ui-issue-71/fixed/pnpm-workspace.yaml +8 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/cordis.patch.yml +4 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/node_modules/@linxin666/dsh-client-ui-skin-center/cordis.patch.yml +1 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/node_modules/@linxin666/dsh-client-ui-skin-center/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/node_modules/@linxin666/dsh-client-ui-skin-qq98/cordis.patch.yml +3 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/node_modules/@linxin666/dsh-client-ui-skin-qq98/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/node_modules/@linxin666/dsh-web-ui-all/cordis.patch.yml +1 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/node_modules/@linxin666/dsh-web-ui-all/package.json +5 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/package.json +13 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/pnpm-lock.yaml +21 -0
- package/examples/cases/dsh-web-ui-issue-71/manual-add/pnpm-workspace.yaml +5 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -1,1083 +1,123 @@
|
|
|
1
|
-
|
|
1
|
+
# Upstream Radar
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://github.com/MicroMilo/upstream-radar/actions)
|
|
4
|
+
[](https://www.npmjs.com/package/upstream-radar)
|
|
5
|
+
[](LICENSE)
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
English · <a href="docs/README.zh-CN.md">简体中文</a>
|
|
7
|
-
</p>
|
|
7
|
+
**Dependency evidence and upstream-change monitoring for [DeepSeek Harness (DSH)](https://github.com/deepseek-ai/deepseek-harness) plugins.**
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
<a href="https://www.npmjs.com/package/upstream-radar"><img alt="npm version" src="https://img.shields.io/npm/v/upstream-radar?style=flat-square&color=2563eb"></a>
|
|
11
|
-
<a href="https://github.com/MicroMilo/upstream-radar/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/MicroMilo/upstream-radar?style=flat-square&color=f59e0b"></a>
|
|
12
|
-
<a href="https://github.com/MicroMilo/upstream-radar/actions/workflows/ci.yml"><img alt="CI" src="https://img.shields.io/github/actions/workflow/status/MicroMilo/upstream-radar/ci.yml?branch=main&style=flat-square&label=CI"></a>
|
|
13
|
-
<a href="examples/dsh/README.md"><img alt="Tested with DSH 0.1.0-rc.6" src="https://img.shields.io/badge/tested_with_DSH-0.1.0--rc.6-5b5bd6?style=flat-square"></a>
|
|
14
|
-
<a href="https://github.com/MicroMilo/upstream-radar/releases"><img alt="GitHub release" src="https://img.shields.io/github/v/release/MicroMilo/upstream-radar?style=flat-square"></a>
|
|
15
|
-
<a href="LICENSE"><img alt="Apache-2.0 license" src="https://img.shields.io/badge/license-Apache--2.0-0f766e?style=flat-square"></a>
|
|
16
|
-
</p>
|
|
9
|
+
Upstream Radar answers a practical question before a plugin enters a DSH profile:
|
|
17
10
|
|
|
18
|
-
|
|
19
|
-
<picture>
|
|
20
|
-
<source media="(max-width: 600px)" srcset="docs/assets/upstream-radar-hero-mobile.jpg">
|
|
21
|
-
<img src="docs/assets/upstream-radar-hero.jpg" alt="Upstream Radar watches a dependency graph, highlights one affected path, and routes one signal to a DSH Agent." width="100%">
|
|
22
|
-
</picture>
|
|
23
|
-
</p>
|
|
11
|
+
> Which exact dependency versions does this plugin bring in, which vulnerability or upstream release changed them, and which other plugins will be affected?
|
|
24
12
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
<p align="center">
|
|
28
|
-
<a href="#try-it-in-60-seconds">Try it in 60 seconds</a> ·
|
|
29
|
-
<a href="#see-one-incident">See one incident</a> ·
|
|
30
|
-
<a href="#install-in-dsh">Install in DSH</a> ·
|
|
31
|
-
<a href="#notify-feishu-or-an-https-endpoint">Notify Feishu</a> ·
|
|
32
|
-
<a href="#observe-dsh-plugin-upstream-changes">Observe upstream changes</a> ·
|
|
33
|
-
<a href="#run-the-proof">Run the proof</a> ·
|
|
34
|
-
<a href="#run-it-in-github-actions">Run in GitHub Actions</a> ·
|
|
35
|
-
<a href="https://github.com/MicroMilo/upstream-radar/issues/new?template=trial.yml">Share feedback</a> ·
|
|
36
|
-
<a href="#how-the-loop-works">How it works</a> ·
|
|
37
|
-
<a href="ROADMAP.md">Roadmap</a>
|
|
38
|
-
</p>
|
|
39
|
-
|
|
40
|
-
## Start without guessing
|
|
41
|
-
|
|
42
|
-
If you are not sure whether this project should use a DSH profile, a lockfile, or the packaged demo, run the read-only guide first:
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
npx --yes upstream-radar@latest quickstart
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
It looks only at the current directory and local DSH profile metadata. It recommends one of the real paths below, labels every suggested command as read-only, local-file creation, or install/start, and refuses to choose between two lockfiles or multiple DSH profiles. The guide itself never installs packages, starts DSH, queries vulnerability sources, or executes plugin code. Use `--json` to feed the result into a setup page or internal launcher.
|
|
49
|
-
|
|
50
|
-
## Choose the smallest path
|
|
51
|
-
|
|
52
|
-
| Your goal | Start here | What you get |
|
|
53
|
-
| --- | --- | --- |
|
|
54
|
-
| Keep a live DSH Agent informed | [`setup`](#install-in-dsh) | A profile-aware monitor that refreshes the installed graph and routes only changed incidents to the matching Agent. |
|
|
55
|
-
| Observe DSH plugin upstream changes | [`observe`](#observe-dsh-plugin-upstream-changes) | A scheduled old → new comparison of GitHub commits, npm releases, manifests, and optional lockfile graphs; only meaningful changes wake an Agent. |
|
|
56
|
-
| Start monitoring one public plugin in 30 seconds | [Minimal GitHub Actions workflow](examples/github-actions/upstream-observer-minimal.yml) | Copy one file, change the repository URL, and get a daily report without installing or building Radar. |
|
|
57
|
-
| Respond to the first alert | [`radar next`](#install-in-dsh) | One read-only command selects the highest-priority incident and points to the DSH task, verified analysis, or next check. |
|
|
58
|
-
| Check a DSH profile before starting it | [`profile-check`](#check-a-dsh-profile-before-starting-it) | Reads the actual lockfile and patch rows and blocks missing loader packages, duplicate loader ids, and release-age rollback risk. |
|
|
59
|
-
| Add a scheduled CI gate | [GitHub Actions example](examples/github-actions/upstream-radar.yml) | A frozen check from a reviewed config or one lockfile, with a concise Job Summary and a machine-readable JSON report. |
|
|
60
|
-
| Check a plugin before installing it | [`graph` / `init` for npm or pnpm lockfiles](#inspect-an-npm-or-pnpm-lockfile-before-installation) | Exact dependency paths and OSV/GitHub Advisory results without running the plugin or its lifecycle scripts. |
|
|
61
|
-
| Scan a public DSH plugin repository | `scan https://github.com/owner/repository` | One command shallow-clones the public repo into a temporary directory and reports concrete problems without installing or running it. |
|
|
62
|
-
| Review one exact published artifact | `upstream-radar inspect <package>@<exact-version> --deep` | Package, dependency, vulnerability, and provenance evidence for one release. |
|
|
63
|
-
| Publish and maintain a DSH plugin | [Plugin author path](#for-dsh-plugin-authors) | Start from a real DSH scaffold, review its locked graph, and add a two-step CI gate before users install it. |
|
|
64
|
-
| Send changed events to Feishu | [Feishu or HTTPS webhook](#notify-feishu-or-an-https-endpoint) | Native Feishu V2 text, environment-only secrets, durable acknowledgement, and retry. |
|
|
65
|
-
|
|
66
|
-
If you want project-specific reasoning from DSH, use the first path. If you only need an independent admission or regression gate, use the second or third; they do not require a running DSH profile.
|
|
13
|
+
It reads source trees, lockfiles, exact npm artifacts, saved DSH reports, and public advisory feeds. It does not install a plugin or execute its business code during static review.
|
|
67
14
|
|
|
68
15
|
## Try it in 60 seconds
|
|
69
16
|
|
|
70
|
-
Want to see the core value before touching DSH? Run the packaged, network-free demo:
|
|
71
|
-
|
|
72
17
|
```bash
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
It prints one exact transitive path, independent advisory-source evidence (including an explicit source conflict), CISA KEV/EPSS prioritization evidence, the read-only DSH Agent handoff, and the next setup command. It uses a local fixture only; it does not inspect your repository, install a plugin, or claim that the demo advisory is real. Use `--json` when you want the same proof as a machine-readable artifact.
|
|
77
|
-
|
|
78
|
-
The core result looks like this (the demo uses a local fixture; fields are abbreviated):
|
|
79
|
-
|
|
80
|
-
```text
|
|
81
|
-
[HIGH][NEW] Dependency vulnerability
|
|
82
|
-
Affected: parser@2.9.0
|
|
83
|
-
Paths:
|
|
84
|
-
demo-plugin@1.0.0 -> logger@4.0.2 -> parser@2.9.0
|
|
85
|
-
Threat signal: CISA KEV lists this CVE as exploited in the wild.
|
|
86
|
-
FIRST EPSS estimated exploitation probability: 97.2% (percentile 100.0%)
|
|
87
|
-
Next: Review the fixed version with the DSH Agent in this project.
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
The useful part is the exact path and project-specific next step—not another generic list of vulnerable package names.
|
|
91
|
-
|
|
92
|
-
Want to try it on a real published DSH plugin immediately?
|
|
93
|
-
|
|
94
|
-
```bash
|
|
95
|
-
npx --yes upstream-radar@0.33.11 inspect dsh-feishu-bot@0.15.4 --deep
|
|
96
|
-
```
|
|
18
|
+
# No DSH profile, API key, or network state required
|
|
19
|
+
npx --yes upstream-radar@0.34.0 demo
|
|
97
20
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Want to see a real author-actionable result? This exact published DSH plugin
|
|
102
|
-
currently cannot produce a complete dependency graph in a clean npm resolver:
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
npx --yes upstream-radar@0.33.11 inspect \
|
|
106
|
-
@sanqi-normal/dsh-webui-market-plugin@0.5.4 \
|
|
107
|
-
--deep --fail-on never
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
The result is `review / incomplete`, with the concrete cause
|
|
111
|
-
`@deepseek-ai/dsh-compact@^0.0.1-rc.1` not published. No DSH profile, plugin
|
|
112
|
-
execution, or LLM is required. See the [reproducible author report](examples/dsh/reports/sanqi-market-plugin-dependency-resolution.md).
|
|
113
|
-
|
|
114
|
-
Want to scan a public DSH plugin repository without cloning it yourself? Give
|
|
115
|
-
`scan` the GitHub URL:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
npx --yes upstream-radar@latest scan \
|
|
119
|
-
https://github.com/13071301808/dsh-composer-expand \
|
|
21
|
+
# Scan a public DSH plugin repository without installing it
|
|
22
|
+
npx --yes upstream-radar@0.34.0 scan \
|
|
23
|
+
https://github.com/PlutoKeating/dsh-lark-bot \
|
|
120
24
|
--fail-on never
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
This shallow-clones only the current public branch into a temporary directory,
|
|
124
|
-
then reads the source files and lockfile. It does not install dependencies,
|
|
125
|
-
run lifecycle scripts, load plugin code, start DSH, or call an LLM. The public
|
|
126
|
-
case currently returns `REVIEW / ALLOW / INCOMPLETE` because
|
|
127
|
-
`package-lock.json` still says `0.1.0` while `package.json` says `0.1.2`; the
|
|
128
|
-
report prints the repair directly: regenerate the lockfile with lifecycle
|
|
129
|
-
scripts disabled and review the complete diff. A local `git` executable is the
|
|
130
|
-
only extra requirement for this URL form.
|
|
131
|
-
|
|
132
|
-
If the repository root has no `package.json`, Radar looks up to three directory
|
|
133
|
-
levels deep for one unique package declaring a DSH bundle. For example,
|
|
134
|
-
`https://github.com/2008924/dsh-progress-viz` keeps its plugin in `plugin/`; the
|
|
135
|
-
same command reports `plugin` as the selected directory and scans it without
|
|
136
|
-
installing or running anything. Multiple DSH plugin directories are reported as
|
|
137
|
-
ambiguous instead of guessed.
|
|
138
|
-
|
|
139
|
-
When the selected directory contains exactly one supported lockfile,
|
|
140
|
-
`package-lock.json` or `pnpm-lock.yaml`, the same scan also reconstructs its
|
|
141
|
-
committed dependency graph and prints the root, node/edge counts, direct edges,
|
|
142
|
-
and unresolved edges. It still does not install dependencies or query an
|
|
143
|
-
advisory service; use `inspect --deep` or a Radar check when you need upstream
|
|
144
|
-
vulnerability results. If both supported lockfiles are present, the scan stops
|
|
145
|
-
and explains the ambiguity instead of choosing one silently.
|
|
146
|
-
|
|
147
|
-
Tried the demo or a real DSH setup? [Share a short trial result](https://github.com/MicroMilo/upstream-radar/issues/new?template=trial.yml) with the versions, path, and redacted outcome. Never include source code, secrets, or private paths.
|
|
148
|
-
|
|
149
|
-
Every command has its own short guide: `npx --yes upstream-radar@latest setup --help`, `npx --yes upstream-radar@latest inspect --help`, and `npx --yes upstream-radar@latest radar status --help` are useful starting points when you are not sure which path to choose.
|
|
150
|
-
|
|
151
|
-
Use DSH with at least one third-party bundle. When it has exactly one such profile, `setup` selects it automatically; pass `--profile <name>` only when you have multiple profiles. The commands below are split between two terminals because DSH normally stays running:
|
|
152
|
-
|
|
153
|
-
Before running `setup`, confirm that DeepSeek Harness is installed and `dsh --help` works. If `setup` cannot find `dsh`, it prints this recovery step again.
|
|
154
|
-
|
|
155
|
-
If DSH has no third-party plugin profile yet, install the plugin you want to monitor first: `dsh plugin --profile <name> add <package>@<exact-version>`.
|
|
156
|
-
|
|
157
|
-
```bash
|
|
158
|
-
# Terminal 1
|
|
159
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar setup \
|
|
160
|
-
--project-name "My DSH project"
|
|
161
|
-
# Use the profile name printed by setup; `web` is only an example.
|
|
162
|
-
dsh --profile web --patch ./upstream-radar.dsh.yml
|
|
163
|
-
```
|
|
164
|
-
|
|
165
|
-
If you explicitly want setup to launch DSH in the same invocation after its local doctor check passes, add `--start`:
|
|
166
25
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
--
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
Without `--start`, setup never launches DSH and gives you a pause to review the generated files. The explicit flag is the one-command path; doctor verifies local wiring, but it is not a human review or a package-safety certificate.
|
|
173
|
-
|
|
174
|
-
The one-command path is also covered by a network-free showcase: `pnpm run showcase:setup-start`.
|
|
175
|
-
|
|
176
|
-
If you use npm rather than pnpm, the equivalent launcher is `npx --yes upstream-radar@latest setup --project-name "My DSH project"`. For a reproducible team workflow, replace `latest` with the exact release you have reviewed.
|
|
177
|
-
|
|
178
|
-
`setup` explicitly installs the exact Radar version used by the command into the selected DSH profile, discovers the installed graph, writes `./upstream-radar.config.json` and `./upstream-radar.dsh.yml` by default, and runs the network-free wiring check. By default it does not start DSH or execute plugin business actions; `--start` opts into launching DSH only after the doctor check passes. Use `--output` or `--dsh-patch` for different paths; if Radar is already installed, add `--no-install`.
|
|
179
|
-
|
|
180
|
-
The printed doctor command uses `npx --yes` with the exact same Radar version, so the handoff also works when the first command was launched with npm rather than pnpm.
|
|
181
|
-
|
|
182
|
-
After DSH is running, use a second terminal for the read-only status check:
|
|
183
|
-
|
|
184
|
-
```bash
|
|
185
|
-
# Terminal 2
|
|
186
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar status ./upstream-radar.config.json
|
|
26
|
+
# Review the exact package users would install, then check two DSH releases
|
|
27
|
+
npx --yes upstream-radar@0.34.0 review dsh-plugin dsh-feishu-bot@0.15.8 \
|
|
28
|
+
--dsh-version 0.1.0-rc.6,0.1.0-rc.7
|
|
187
29
|
```
|
|
188
30
|
|
|
189
|
-
The
|
|
31
|
+
The important output is evidence, not a green badge: exact package identity, dependency paths, unresolved edges, install-time scripts, npm integrity/signature/provenance, advisory matches, and DSH load results.
|
|
190
32
|
|
|
191
|
-
|
|
33
|
+
## What we have already found
|
|
192
34
|
|
|
193
|
-
|
|
194
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar history ./upstream-radar.config.json
|
|
195
|
-
```
|
|
196
|
-
|
|
197
|
-
It shows `new`, `updated`, `resolved`, and source-health transitions, including the exact affected path. Use `--json` for a dashboard or relay; the ledger keeps the latest 1,000 transitions and deduplicates stable event ids.
|
|
198
|
-
|
|
199
|
-
If you want to try the monitoring loop without booting a DSH profile, run one cycle from a reviewed inventory:
|
|
200
|
-
|
|
201
|
-
```bash
|
|
202
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar watch ./upstream-radar.config.json --once
|
|
203
|
-
```
|
|
204
|
-
|
|
205
|
-
Remove `--once` to keep a local monitor alive. This is a lightweight CLI surface for demos, CI, and diagnosis; the native DSH bundle remains the recommended always-on path because it can deliver the task to a live Agent.
|
|
206
|
-
|
|
207
|
-
## Check a DSH profile before starting it
|
|
208
|
-
|
|
209
|
-
When the concern is “will this profile boot with the packages and patch rows it
|
|
210
|
-
actually has?”, use the static profile check first:
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
pnpm run build
|
|
214
|
-
node dist/src/cli.js profile-check "$DSH_HOME/profiles/web" \
|
|
215
|
-
--report ./dsh-profile-check.md
|
|
216
|
-
```
|
|
35
|
+
These are real, reproducible cases in this repository—not synthetic “vulnerable package” demos.
|
|
217
36
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
When `DSH_HOME` contains exactly one profile with third-party bundles, the
|
|
226
|
-
directory can be omitted:
|
|
227
|
-
|
|
228
|
-
```bash
|
|
229
|
-
npx --yes upstream-radar@latest profile-check --summary
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
With no eligible profile, or more than one, Radar prints the names it found and
|
|
233
|
-
asks for an explicit directory; it never guesses between multiple profiles.
|
|
234
|
-
|
|
235
|
-
It prints only the status, the important evidence, the reason, and the next
|
|
236
|
-
repair. The exit code remains `2` for a blocked profile and `0` for a pass.
|
|
237
|
-
|
|
238
|
-
It reads the profile manifest, pnpm/npm lockfile, package metadata,
|
|
239
|
-
`pnpm-workspace.yaml`, and `cordis.patch.yml`. It catches the two concrete
|
|
240
|
-
failure shapes from [dsh-web-ui #71](https://github.com/zhu1090093659/dsh-web-ui/issues/71)
|
|
241
|
-
and [#35](https://github.com/zhu1090093659/dsh-web-ui/issues/35): a loader row
|
|
242
|
-
that names a package absent from the locked profile, and the same loader id
|
|
243
|
-
being inserted twice. It also points out a pnpm `minimumReleaseAge` policy that
|
|
244
|
-
does not exempt the plugin, because that can keep a newly fixed plugin on an
|
|
245
|
-
older release during its cooling window.
|
|
246
|
-
|
|
247
|
-
This is deliberately a pre-start check: no network, installation, plugin code,
|
|
248
|
-
DSH process, Agent, or LLM is involved. A blocked result exits with code `2`.
|
|
249
|
-
The complete replay is `pnpm run showcase:dsh-profile-check`; it runs the
|
|
250
|
-
public case before the fix, after the manual package workaround, and after the
|
|
251
|
-
correct bundled-carrier fix.
|
|
252
|
-
|
|
253
|
-
The short, author-facing result is `pnpm run showcase:dsh-case`. It turns the
|
|
254
|
-
same three static checks into one repair story: the old profile is blocked,
|
|
255
|
-
manually adding the missing package creates a duplicate loader, and the
|
|
256
|
-
bundled-carrier update reaches `pass`. If an OpenAI-compatible `issue-locator`
|
|
257
|
-
model is available, pass its env file with
|
|
258
|
-
`ISSUE_LOCATOR_ENV_FILE=/path/to/issue-locator/.env`; the model only explains
|
|
259
|
-
the already-checked facts. If the endpoint is unavailable, the command still
|
|
260
|
-
prints the deterministic evidence explanation and records that the fallback was
|
|
261
|
-
used. Add `:report` to write the [case analysis result](examples/dsh/reports/dsh-web-ui-issue-71-analysis.json).
|
|
262
|
-
|
|
263
|
-
We also ran the current static checks against the first 50 entries in the DSH
|
|
264
|
-
plugin registry. That batch found **0 confirmed runtime dependency
|
|
265
|
-
vulnerabilities**. It did find real monitoring-quality problems—development-only
|
|
266
|
-
dependencies mixed into source lockfiles, three plugin lockfiles whose root
|
|
267
|
-
version lagged the source manifest, and a tarball format the scanner could not
|
|
268
|
-
parse. The [batch report](examples/dsh/reports/dsh-batch-50-2026-08-17.md)
|
|
269
|
-
keeps those results honest; it is not marketed as a vulnerability hit list.
|
|
270
|
-
The three repeated lockfile-metadata cases are rechecked in the
|
|
271
|
-
[follow-up report](examples/dsh/reports/lockfile-metadata-follow-up-2026-08-18.md),
|
|
272
|
-
with an author-ready issue draft for the first maintainer.
|
|
37
|
+
| Case | Finding | Why it matters |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| [50-plugin batch](examples/dsh/reports/dsh-batch-50-2026-08-17.md) | 0 confirmed runtime dependency vulnerabilities; 3 lockfile root-version mismatches | Monitoring can be wrong even when the vulnerability count is zero. |
|
|
40
|
+
| [`dsh-feishu-bot@0.15.8`](examples/dsh/reports/dsh-feishu-bot-0.15.8-review-2026-08-18.md) | 89-package graph, 12 unresolved optional edges, reachable `protobufjs` `postinstall`, DSH rc.6/rc.7 compatible | “No known CVE” is not the same as “no installation trust boundary.” |
|
|
41
|
+
| [DSH-TUI source vs npm](examples/dsh/reports/dsh-tui-source-vs-npm-2026-08-18.md) | Source has `prepare`; published artifact does not | Source-only and artifact-only reviews answer different questions. |
|
|
42
|
+
| [dsh-composer-expand](examples/dsh/reports/dsh-composer-expand-lockfile-feedback.md) | Committed lockfile root says `0.1.0` while source says `0.1.2` | A small author-fix can restore the identity of the monitored graph. |
|
|
273
43
|
|
|
274
|
-
|
|
44
|
+
We report a confirmed vulnerability only when the affected exact version and runtime path are supported by the available evidence. Development-only hits, missing data, and advisory-source outages remain visibly different states.
|
|
275
45
|
|
|
276
|
-
|
|
277
|
-
every run, Radar remembers one observation point per plugin and asks what changed
|
|
278
|
-
since then.
|
|
46
|
+
## The core workflow
|
|
279
47
|
|
|
280
48
|
```text
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
Start from the [copyable target example](examples/upstream-observer/targets.yml):
|
|
293
|
-
|
|
294
|
-
```yaml
|
|
295
|
-
schema: upstream-radar.observer-targets/v1alpha1
|
|
296
|
-
targets:
|
|
297
|
-
- id: my-dsh-plugin
|
|
298
|
-
ecosystem: dsh
|
|
299
|
-
repository: acme/my-dsh-plugin
|
|
300
|
-
ref: main
|
|
301
|
-
package: my-dsh-plugin
|
|
302
|
-
packagePath: plugin/package.json
|
|
303
|
-
lockfile: plugin/pnpm-lock.yaml
|
|
304
|
-
lockfileType: pnpm
|
|
305
|
-
```
|
|
306
|
-
|
|
307
|
-
For one public repository, skip YAML and pass its GitHub URL directly. The
|
|
308
|
-
first run creates a baseline; later runs compare the ref you provide. The
|
|
309
|
-
observer automatically looks for `pnpm-lock.yaml` or `package-lock.json` and
|
|
310
|
-
uses the real committed graph. Add `--package-path` for a nested plugin,
|
|
311
|
-
`--package` when the npm name differs from the source manifest, or
|
|
312
|
-
`--lockfile` when you want to choose a particular lockfile:
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
npx --yes upstream-radar@0.33.11 observe \
|
|
316
|
-
https://github.com/PlutoKeating/dsh-lark-bot \
|
|
317
|
-
--state ./observations.json --report ./upstream-radar-observer.md
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
The public example below supplies `--package` because this repository's source
|
|
321
|
-
manifest is `dsh-lark-bot`, while its published npm package is
|
|
322
|
-
`dsh-feishu-bot`:
|
|
323
|
-
|
|
324
|
-
```bash
|
|
325
|
-
npx --yes upstream-radar@0.33.11 observe \
|
|
326
|
-
https://github.com/PlutoKeating/dsh-lark-bot \
|
|
327
|
-
--package dsh-feishu-bot \
|
|
328
|
-
--lockfile pnpm-lock.yaml --lockfile-type pnpm \
|
|
329
|
-
--state ./observations.json --report ./upstream-radar-observer.md
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
Then run one cycle:
|
|
333
|
-
|
|
334
|
-
```bash
|
|
335
|
-
export GITHUB_TOKEN='a read-only GitHub token'
|
|
336
|
-
npx --yes upstream-radar@0.33.11 observe \
|
|
337
|
-
./targets.yml \
|
|
338
|
-
--state ./observations.json \
|
|
339
|
-
--report ./upstream-radar-observer.md
|
|
340
|
-
```
|
|
341
|
-
|
|
342
|
-
This uses the published CLI; pin the exact version in CI rather than relying on
|
|
343
|
-
`latest`. The first cycle only creates a baseline. Later cycles compare:
|
|
344
|
-
|
|
345
|
-
- the source commit and changed files;
|
|
346
|
-
- the published npm version and integrity value;
|
|
347
|
-
- the package entrypoint, exports, Node requirement, DSH bundle metadata and dependency declarations;
|
|
348
|
-
- the real npm or pnpm lockfile graph, when a supported lockfile is committed;
|
|
349
|
-
the selected path is recorded in the observation state.
|
|
350
|
-
|
|
351
|
-
README/docs/tests-only changes advance the observation point without waking the
|
|
352
|
-
Agent. Runtime source, DSH bundle, package entry, dependency graph, npm version,
|
|
353
|
-
or npm integrity changes create an old → new task. If the Agent is not configured,
|
|
354
|
-
the task stays in `observations.json`; no plugin is installed or executed.
|
|
355
|
-
|
|
356
|
-
If you do not have a DSH wrapper configured yet, you can point the observer at
|
|
357
|
-
an existing issue-locator/OpenAI-compatible `.env` file instead:
|
|
358
|
-
|
|
359
|
-
```bash
|
|
360
|
-
upstream-radar observe ./targets.yml \
|
|
361
|
-
--state ./observations.json \
|
|
362
|
-
--llm-env-file /path/to/issue-locator/.env
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
Radar reads only the endpoint, API key, and model name for that call. It never
|
|
366
|
-
writes the key or endpoint into the observation state or report. The model is
|
|
367
|
-
called only after a meaningful upstream change; a baseline or docs-only change
|
|
368
|
-
does not call it. If the endpoint is unavailable, the deterministic change
|
|
369
|
-
record remains pending and can be retried with `--retry-pending`.
|
|
370
|
-
|
|
371
|
-
The env file may use the issue-locator names (`ISSUE_LOCATOR_LLM_*`), the common
|
|
372
|
-
OpenAI names (`OPENAI_BASE_URL`, `OPENAI_API_KEY`, `OPENAI_MODEL`), or `MODEL` /
|
|
373
|
-
`CODEX_MODEL` for the model name.
|
|
374
|
-
For ModelBest-style URLs, a 404 on `/llm/v1` also retries `/llm/openai/v1`.
|
|
375
|
-
|
|
376
|
-
The scheduled workflow is [examples/github-actions/upstream-observer.yml](examples/github-actions/upstream-observer.yml).
|
|
377
|
-
The checked-in workflow is a dogfood workflow for this repository: it checks out
|
|
378
|
-
and builds Radar before running the observer. It persists only the observation
|
|
379
|
-
point. A quiet run does not create a daily commit.
|
|
380
|
-
|
|
381
|
-
For the shortest copy-paste setup, use the [minimal one-repository workflow](examples/github-actions/upstream-observer-minimal.yml).
|
|
382
|
-
It uses the published npm CLI, needs no Radar checkout or build, and only asks
|
|
383
|
-
you to change the repository URL (or enter one through `workflow_dispatch`).
|
|
384
|
-
|
|
385
|
-
The workflow also supports three optional repository secrets—
|
|
386
|
-
`ISSUE_LOCATOR_LLM_BASE_URL`, `ISSUE_LOCATOR_LLM_API_KEY`, and
|
|
387
|
-
`ISSUE_LOCATOR_LLM_MODEL`. When all three exist, the job sends meaningful tasks
|
|
388
|
-
to the issue-locator/OpenAI-compatible model. When they do not exist, static
|
|
389
|
-
upstream observation still runs and the job does not pretend that model analysis
|
|
390
|
-
was performed.
|
|
391
|
-
|
|
392
|
-
### The DSH Agent boundary
|
|
393
|
-
|
|
394
|
-
The observer accepts an explicit executable through `--dsh-agent-command`. It
|
|
395
|
-
writes one bounded, read-only task prompt to stdin and expects one JSON conclusion
|
|
396
|
-
on stdout. The command is started without a shell, and the prompt treats every
|
|
397
|
-
remote repository string and release field as untrusted evidence.
|
|
398
|
-
|
|
399
|
-
```bash
|
|
400
|
-
upstream-radar observe ./targets.yml \
|
|
401
|
-
--state ./observations.json \
|
|
402
|
-
--dsh-agent-command /path/to/reviewed-dsh-agent-wrapper \
|
|
403
|
-
--dsh-agent-arg --json
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
Radar does not guess an undocumented `dsh` CLI subcommand. A reviewed DSH
|
|
407
|
-
headless wrapper is the integration boundary; this keeps the observer usable in
|
|
408
|
-
GitHub Actions and lets the DSH adapter evolve without changing observation or
|
|
409
|
-
diff logic. Use `--retry-pending` to deliver tasks left by a previous run.
|
|
410
|
-
|
|
411
|
-
## Notify Feishu or an HTTPS endpoint
|
|
412
|
-
|
|
413
|
-
To also notify a team-owned HTTPS endpoint when an incident changes, keep the endpoint outside the reviewed config and state:
|
|
414
|
-
|
|
415
|
-
```bash
|
|
416
|
-
export UPSTREAM_RADAR_WEBHOOK_URL='https://alerts.example.test/upstream-radar?token=replace-me'
|
|
417
|
-
|
|
418
|
-
# Native DSH path: the bundle reads the variable at runtime.
|
|
419
|
-
dsh --profile web --patch ./upstream-radar.dsh.yml
|
|
420
|
-
|
|
421
|
-
# Or use the CLI path for a persistent one-shot/continuous monitor.
|
|
422
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar watch \
|
|
423
|
-
./upstream-radar.config.json --webhook "$UPSTREAM_RADAR_WEBHOOK_URL"
|
|
424
|
-
```
|
|
425
|
-
|
|
426
|
-
The webhook receives only `new`, `updated`, and `resolved` changes (including source-health changes) in the bounded `upstream-radar.webhook/v1alpha1` JSON format described by the [schema](schemas/webhook.schema.json). A successful HTTP 2xx response records the event id; a failed request remains retryable on the next cycle. The state stores only a SHA-256 endpoint fingerprint, delivery ids, and a bounded copy of events waiting for retry or a quiet window; it never stores the URL or its token. Vulnerability summaries include the same short priority evidence as `radar status`—CISA KEV, then EPSS, then severity—so a Feishu message does not require a second interpretation. For a normal endpoint, this provider-neutral JSON can be turned into a Feishu or Slack card by a relay. For a Feishu/Lark V2 custom bot, Radar recognizes the `/open-apis/bot/v2/hook/` URL and sends the native text body directly:
|
|
427
|
-
|
|
428
|
-
```bash
|
|
429
|
-
export UPSTREAM_RADAR_WEBHOOK_URL='https://open.feishu.cn/open-apis/bot/v2/hook/replace-me'
|
|
430
|
-
# Only needed when the Feishu bot has signature validation enabled.
|
|
431
|
-
export UPSTREAM_RADAR_FEISHU_SECRET='replace-me'
|
|
432
|
-
|
|
433
|
-
dsh --profile web --patch ./upstream-radar.dsh.yml
|
|
434
|
-
```
|
|
435
|
-
|
|
436
|
-
The Feishu secret is read only from the environment and is never written to the Radar config or state. Follow the [official Feishu custom-bot guide](https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN?lang=zh-CN) when creating the V2 bot. Use the V2 URL; the older `/open-apis/bot/hook/` form is rejected with an actionable error. Run `pnpm run showcase:webhook` to see deduplication and retry behavior without contacting a real endpoint.
|
|
437
|
-
|
|
438
|
-
For more than one monitored project, give each project its own environment-variable route. The config stores only the variable names, never the webhook URL or secret:
|
|
439
|
-
|
|
440
|
-
```json
|
|
441
|
-
{
|
|
442
|
-
"project": {
|
|
443
|
-
"id": "payments-api",
|
|
444
|
-
"name": "Payments API",
|
|
445
|
-
"webhookUrlEnv": "UPSTREAM_RADAR_PAYMENTS_WEBHOOK_URL",
|
|
446
|
-
"webhookSecretEnv": "UPSTREAM_RADAR_PAYMENTS_FEISHU_SECRET"
|
|
447
|
-
}
|
|
448
|
-
}
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
```bash
|
|
452
|
-
export UPSTREAM_RADAR_PAYMENTS_WEBHOOK_URL='https://open.feishu.cn/open-apis/bot/v2/hook/replace-me'
|
|
453
|
-
export UPSTREAM_RADAR_PAYMENTS_FEISHU_SECRET='replace-me'
|
|
454
|
-
|
|
455
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar setup \
|
|
456
|
-
--webhook-url-env UPSTREAM_RADAR_PAYMENTS_WEBHOOK_URL \
|
|
457
|
-
--webhook-secret-env UPSTREAM_RADAR_PAYMENTS_FEISHU_SECRET
|
|
49
|
+
DSH plugin source / npm artifact
|
|
50
|
+
↓
|
|
51
|
+
exact dependency graph + DSH compatibility evidence
|
|
52
|
+
↓
|
|
53
|
+
saved observation point
|
|
54
|
+
↓
|
|
55
|
+
upstream commit, package, or advisory changes
|
|
56
|
+
↓
|
|
57
|
+
affected-plugin paths and author-facing next action
|
|
58
|
+
↓
|
|
59
|
+
optional DSH Agent analysis only when a meaningful change exists
|
|
458
60
|
```
|
|
459
61
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
## Control notification noise without losing evidence
|
|
463
|
-
|
|
464
|
-
The generated inventory can hold ordinary notices while keeping the full incident, dependency path, history, and DSH task intact. For a first setup, use flags so you do not need to edit JSON by hand:
|
|
62
|
+
For a collection of saved reports, build the reverse index that turns an upstream package update into affected plugins:
|
|
465
63
|
|
|
466
64
|
```bash
|
|
467
|
-
|
|
468
|
-
--
|
|
469
|
-
--quiet-hours 'Asia/Shanghai,22:00-08:00'
|
|
470
|
-
```
|
|
65
|
+
npx --yes upstream-radar@0.34.0 graph reverse ./reports \
|
|
66
|
+
--output reverse-dependency-index.json
|
|
471
67
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
{
|
|
476
|
-
"notificationPolicy": {
|
|
477
|
-
"minimumSeverity": "high",
|
|
478
|
-
"quietHours": {
|
|
479
|
-
"timezone": "Asia/Shanghai",
|
|
480
|
-
"start": "22:00",
|
|
481
|
-
"end": "08:00"
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
`minimumSeverity` applies to vulnerability notices; `critical` vulnerabilities and malicious-package alerts always pass. `quietHours` uses the configured IANA timezone and also supports a window crossing midnight. Compatibility and source-health notices follow the quiet window but are not hidden by a vulnerability severity threshold. With a policy in effect, DSH tasks stay in the durable outbox until they can be delivered, and the webhook outbox keeps pending events for retry or a later policy change. `radar status` shows how many tasks are currently held. Omitting the block keeps the current behavior and delivers every notice. Run `pnpm run showcase:notifications` for a network-free proof of the hold, later delivery, and durable webhook outbox.
|
|
488
|
-
|
|
489
|
-
If one active incident is noisy, mute only that incident for a bounded period:
|
|
490
|
-
|
|
491
|
-
```bash
|
|
492
|
-
upstream-radar radar next ./upstream-radar.config.json
|
|
493
|
-
upstream-radar mute './upstream-radar.config.json.state.json' '<incident-id>' \
|
|
494
|
-
--until '2026-08-17T12:00:00Z'
|
|
68
|
+
# Ask: which plugins currently depend on this exact package?
|
|
69
|
+
npx --yes upstream-radar@0.34.0 graph reverse ./reports \
|
|
70
|
+
--package parser@2.9.0
|
|
495
71
|
```
|
|
496
72
|
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
Record the human handoff next to the same incident:
|
|
500
|
-
|
|
501
|
-
```bash
|
|
502
|
-
upstream-radar triage './upstream-radar.config.json.state.json' '<incident-id>' \
|
|
503
|
-
--status in-progress --owner security-team \
|
|
504
|
-
--note 'Trace the parser input path' \
|
|
505
|
-
--due '2026-08-17T12:00:00Z'
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
The available states are `open`, `in-progress`, `blocked`, and `accepted-risk`. `blocked` and `accepted-risk` require a note. `--due` is an optional human deadline; `radar status` and `radar next` mark it as overdue when it passes. This is workflow context only: it never marks an active vulnerability resolved or suppresses its evidence. The record is bound to the exact event id, so an updated upstream fact requires a fresh review; `radar status` and `radar next` show the current owner, note, and deadline.
|
|
509
|
-
|
|
510
|
-
---
|
|
511
|
-
|
|
512
|
-
A vulnerability feed stops at “package X is affected.” Upstream Radar keeps going: it identifies the exact installed dependency path, maintains one durable incident, and wakes a [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) Agent with the project evidence needed for a useful investigation.
|
|
73
|
+
The generated JSON preserves exact paths such as:
|
|
513
74
|
|
|
514
75
|
```text
|
|
515
|
-
|
|
516
|
-
-> exact installed plugin path
|
|
517
|
-
-> new / updated / resolved incident
|
|
518
|
-
-> project-specific DSH Agent analysis task
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
**No matching installed path means no Agent wake-up.** Version matching and compatibility facts are calculated by code; the model handles only repository-specific judgment.
|
|
522
|
-
|
|
523
|
-
Radar checks OSV and the GitHub Advisory Database as independent vulnerability sources. If both sources describe the same issue through a GHSA or CVE alias, Radar emits one incident and keeps the source identifiers, source list, and fix versions together; human-readable output says `Sources: OSV + GitHub Advisory Database` for this cross-confirmed case. If their severity or fixed-version claims differ, the event also says `Source conflict` and shows each claim instead of silently making the operator infer why multiple fixes are listed. If one source times out, the last confirmed vulnerability evidence and incident identity are retained; the source itself becomes a visible health incident after three consecutive failures instead of being treated as clean. The CLI and DSH adapter use the GitHub source by default, accept an optional `GITHUB_TOKEN` from the environment for API rate limits, and expose `--no-github-advisories` when an operator deliberately needs an OSV-only run. See the [GitHub Advisory Database API](https://docs.github.com/en/rest/security-advisories/global-advisories?apiVersion=2026-03-10) for the upstream query contract.
|
|
524
|
-
|
|
525
|
-
## The missing middle: candidate dependency graphs
|
|
526
|
-
|
|
527
|
-
An upgrade can look clean at the top level while introducing a vulnerable transitive package. Radar therefore does not stop at `plugin@1.3.0`'s manifest:
|
|
528
|
-
|
|
529
|
-
```text
|
|
530
|
-
candidate plugin@1.1.0
|
|
531
|
-
└── logger@4.1.0
|
|
532
|
-
└── parser@2.9.0 ← OSV advisory
|
|
533
|
-
```
|
|
534
|
-
|
|
535
|
-
For the earliest bounded set of newer versions, Radar resolves npm metadata into a temporary `package-lock.json` with lifecycle scripts disabled, queries every resolved node against OSV, and keeps the exact path in the compatibility event. A missing required edge, resolver failure, or OSV failure is shown as incomplete or unavailable; it is never presented as “no vulnerability found”. Later versions are marked as unchecked when the candidate list is larger than the bounded prefix. The result is still a starting point for DSH project analysis, not an upgrade certificate.
|
|
536
|
-
|
|
537
|
-
## Inspect an npm or pnpm lockfile before installation
|
|
538
|
-
|
|
539
|
-
If a DSH plugin is managed with pnpm, inspect the exact locked tree before putting it into a DSH profile:
|
|
540
|
-
|
|
541
|
-
```bash
|
|
542
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar graph pnpm-lock \
|
|
543
|
-
./pnpm-lock.yaml \
|
|
544
|
-
--json
|
|
545
|
-
```
|
|
546
|
-
|
|
547
|
-
This reads only the lockfile. It does not run `pnpm install`, lifecycle scripts, plugin code, or network requests. It understands pnpm v6/v9 package locators, peer-context variants, duplicate versions, and a project root declared through the `importers` section. An unresolved or ambiguous dependency remains visible instead of being guessed away. The JSON is the same canonical graph shape used by Radar's OSV path matching, so a CI job can review the graph before the plugin is admitted to DSH. Run `pnpm run showcase:pnpm-lock` for a real repository example.
|
|
548
|
-
|
|
549
|
-
To turn that graph into a monitorable inventory and run the first vulnerability check:
|
|
550
|
-
|
|
551
|
-
```bash
|
|
552
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar init \
|
|
553
|
-
--pnpm-lock ./pnpm-lock.yaml \
|
|
554
|
-
--project-name "My DSH plugin"
|
|
555
|
-
|
|
556
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar check \
|
|
557
|
-
./upstream-radar.config.json --frozen --fail-on high
|
|
558
|
-
```
|
|
559
|
-
|
|
560
|
-
`init --pnpm-lock` does not need a DSH profile and writes a normal Radar config; `radar check` then queries exact locked versions and emits the same DSH-ready event shape. Use the native DSH `setup` path when the plugin is installed and should receive follow-up analysis in a live Agent. Run `pnpm run showcase:pnpm-lock:monitor` to see the complete lockfile-to-OSV event locally.
|
|
561
|
-
|
|
562
|
-
When `package.json` sits beside `pnpm-lock.yaml`, `--root` can be omitted; Radar reads the exact package name and version from that manifest. Keep `--root` when the lockfile belongs to another workspace root or when you want the admission coordinate to be explicit.
|
|
563
|
-
|
|
564
|
-
The same path works for npm projects with a committed `package-lock.json`:
|
|
565
|
-
|
|
566
|
-
```bash
|
|
567
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar graph npm-lock \
|
|
568
|
-
./package-lock.json --json
|
|
569
|
-
|
|
570
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar init \
|
|
571
|
-
--npm-lock ./package-lock.json \
|
|
572
|
-
--project-name "My DSH plugin"
|
|
76
|
+
plugin@1.0.0 → logger@4.0.2 → parser@2.9.0
|
|
573
77
|
```
|
|
574
78
|
|
|
575
|
-
|
|
79
|
+
It also preserves whether the graph is complete or has unresolved optional/peer edges. A later website can visualize this index; the index and evidence remain the product foundation.
|
|
576
80
|
|
|
577
|
-
|
|
81
|
+
## GitHub Action
|
|
578
82
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
If you start with the real [`create-dsh-plugin`](https://www.npmjs.com/package/create-dsh-plugin) scaffold, the shortest review-first path is:
|
|
582
|
-
|
|
583
|
-
```bash
|
|
584
|
-
npx create-dsh-plugin my-dsh-plugin -t tool --yes --skip-install
|
|
585
|
-
cd my-dsh-plugin
|
|
586
|
-
pnpm install --ignore-scripts
|
|
587
|
-
|
|
588
|
-
# Read the exact graph before adding the plugin to a DSH profile.
|
|
589
|
-
pnpm dlx --package=upstream-radar@0.33.11 upstream-radar graph pnpm-lock pnpm-lock.yaml --json
|
|
590
|
-
```
|
|
591
|
-
|
|
592
|
-
The graph includes the exact DSH package versions and keeps unresolved optional peers visible. It does not load the generated plugin or run lifecycle scripts. After reviewing it, copy this complete workflow into `.github/workflows/upstream-radar.yml`:
|
|
83
|
+
The repository already contains a reusable, composite Action in [`action.yml`](action.yml). It runs the same frozen Radar check in CI and writes a short Job Summary.
|
|
593
84
|
|
|
594
85
|
```yaml
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
on:
|
|
598
|
-
workflow_dispatch:
|
|
599
|
-
pull_request:
|
|
600
|
-
schedule:
|
|
601
|
-
- cron: '17 6 * * *'
|
|
602
|
-
|
|
603
|
-
permissions:
|
|
604
|
-
contents: read
|
|
605
|
-
|
|
606
|
-
jobs:
|
|
607
|
-
dependency-radar:
|
|
608
|
-
runs-on: ubuntu-latest
|
|
609
|
-
steps:
|
|
610
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
611
|
-
- uses: MicroMilo/upstream-radar@v0.33.11
|
|
612
|
-
with:
|
|
613
|
-
fail-on: high
|
|
614
|
-
fail-on-compatibility: breaking
|
|
615
|
-
```
|
|
616
|
-
|
|
617
|
-
The Action auto-detects the one `pnpm-lock.yaml`, checks the same exact graph, and writes the result to the Job Summary. This is a pre-install and CI gate; it does not install the plugin into DSH. After the graph is reviewed, use the normal `dsh plugin` flow to install it and `upstream-radar setup` to start project-aware monitoring.
|
|
618
|
-
|
|
619
|
-
To check a real published DSH artifact directly, run one command:
|
|
620
|
-
|
|
621
|
-
```bash
|
|
622
|
-
npx --yes upstream-radar@0.33.11 inspect dsh-feishu-bot@0.15.4 --deep
|
|
623
|
-
```
|
|
624
|
-
|
|
625
|
-
The checked result is `REVIEW`: registry integrity, signature, provenance, and
|
|
626
|
-
89 resolved packages are verified; known vulnerabilities are `0`, while 12
|
|
627
|
-
optional dependency edges remain unresolved. That is a useful author result:
|
|
628
|
-
the empty vulnerability list is visible, but it is not mislabeled as a full
|
|
629
|
-
`ALLOW` decision.
|
|
630
|
-
|
|
631
|
-
The same exact tarball loads in both DSH `0.1.0-rc.6` and `0.1.0-rc.7` disposable
|
|
632
|
-
profiles. See the [real compatibility probe](examples/dsh/reports/dsh-feishu-bot-0.15.4-probe.md)
|
|
633
|
-
for the command and boundary.
|
|
634
|
-
|
|
635
|
-
## See one incident
|
|
636
|
-
|
|
637
|
-
If an advisory affects only one of two installed `parser` versions, Radar reports the path that actually matched:
|
|
638
|
-
|
|
639
|
-
```text
|
|
640
|
-
[HIGH][NEW] Dependency vulnerability
|
|
641
|
-
Project: Payments API (payments-api)
|
|
642
|
-
Plugin: plugin@1.0.0
|
|
643
|
-
Affected: parser@2.9.0
|
|
644
|
-
Origin: plugin profile
|
|
645
|
-
Advisory: GHSA-demo-2026-parser / CVE-2026-1234
|
|
646
|
-
Sources: OSV + GitHub Advisory Database
|
|
647
|
-
Source conflict: fixed versions — OSV=3.0.0; GitHub Advisory Database=3.1.0
|
|
648
|
-
Paths:
|
|
649
|
-
plugin@1.0.0 -> logger@4.0.2 -> parser@2.9.0
|
|
650
|
-
Fixed versions: 3.0.0, 3.1.0
|
|
651
|
-
Route: payments-platform via feishu:payments-security
|
|
652
|
-
```
|
|
653
|
-
|
|
654
|
-
That incident becomes a plugin-originated DSH notice. Radar keeps both source claims visible instead of silently picking one fixed version; the DSH Agent then decides which fix is appropriate for the project. It is not copied into a generic chatbot prompt.
|
|
655
|
-
|
|
656
|
-
For a CVE, native DSH also adds two prioritization signals:
|
|
657
|
-
|
|
658
|
-
```text
|
|
659
|
-
Threat signal: CISA KEV lists this CVE as exploited in the wild.
|
|
660
|
-
FIRST EPSS estimated exploitation probability: 97.2% (percentile 100.0%)
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
[CISA KEV](https://www.cisa.gov/known-exploited-vulnerabilities-catalog) answers “is this CVE known to be exploited in the wild?” [FIRST EPSS](https://www.first.org/epss/) gives a daily estimate of exploitation probability and relative percentile. They help the Agent and the team decide what to inspect first; they do not change the exact dependency match, and a missing signal is not a safety certificate.
|
|
664
|
-
|
|
665
|
-
To replay the two signals and a source outage without network access:
|
|
666
|
-
|
|
667
|
-
```bash
|
|
668
|
-
pnpm run showcase:threat-intel
|
|
669
|
-
```
|
|
670
|
-
|
|
671
|
-
| Upstream signal | Radar proves deterministically | DSH Agent investigates |
|
|
672
|
-
| --- | --- | --- |
|
|
673
|
-
| Vulnerability or malicious package | affected `name@version`, every installed path, fixed versions, incident state | whether project code reaches it, attacker input can reach it, and the least disruptive fix |
|
|
674
|
-
| Candidate npm release | version boundary and Node.js, peer, export, entrypoint, bundle, and dependency changes; exact direct and transitive candidate OSV status; when possible, the first newer version without a deterministic blocker or known vulnerable path | which APIs or Cordis configuration would break and what migration is appropriate; the first candidate is never treated as a safety certificate |
|
|
675
|
-
|
|
676
|
-
## Install in DSH
|
|
677
|
-
|
|
678
|
-
Upstream Radar is an npm-published DSH bundle, so no install-time build permission is required:
|
|
679
|
-
|
|
680
|
-
```bash
|
|
681
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar setup \
|
|
682
|
-
--project-name "My DSH project"
|
|
683
|
-
```
|
|
684
|
-
|
|
685
|
-
When exactly one DSH profile contains third-party bundles, `setup` selects it automatically; pass `--profile <name>` when more than one profile is eligible. `setup` delegates the package installation to DSH using the exact Radar version currently being run. It then generates `upstream-radar.config.json` and `upstream-radar.dsh.yml` by default, and runs `doctor` locally without contacting OSV, npm, or GitHub. By default it does not start DSH. The explicit one-command path is:
|
|
686
|
-
|
|
687
|
-
```bash
|
|
688
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar setup \
|
|
689
|
-
--project-name "My DSH project" --start
|
|
690
|
-
```
|
|
691
|
-
|
|
692
|
-
For the review-first path, start the generated overlay yourself:
|
|
693
|
-
|
|
694
|
-
```bash
|
|
695
|
-
dsh --profile web --patch ./upstream-radar.dsh.yml --dump-config
|
|
696
|
-
dsh --profile web --patch ./upstream-radar.dsh.yml
|
|
697
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar status ./upstream-radar.config.json
|
|
698
|
-
```
|
|
699
|
-
|
|
700
|
-
For an already installed bundle, add `--no-install`. The lower-level manual path remains available when you want to review the DSH installation separately: run `dsh plugin --profile web add upstream-radar@<exact-version>`, then use `init --profile web --dsh-patch ...` and `doctor`.
|
|
701
|
-
|
|
702
|
-
The initializer reads the profile's actual third-party bundles and follows the installed `node_modules` tree exposed by that profile, including duplicate versions, overrides, and local package-manager choices. By default it records the workspace as `.` so the config can be committed and reused on another machine; start DSH from the project root. Pass `--workspace <absolute-path>` only when DSH is launched elsewhere. It reads manifests only: it does not import plugin code, run lifecycle scripts, start DSH, or enable polling.
|
|
703
|
-
|
|
704
|
-
If startup does not behave as expected, run the local wiring check before looking at upstream feeds:
|
|
705
|
-
|
|
706
|
-
```bash
|
|
707
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar doctor ./upstream-radar.config.json \
|
|
708
|
-
--profile web \
|
|
709
|
-
--patch ./upstream-radar.dsh.yml
|
|
710
|
-
```
|
|
711
|
-
|
|
712
|
-
`doctor` does not contact OSV, npm, GitHub, or execute plugin code. It checks that the config parses, the selected DSH profile actually registers `upstream-radar`, the overlay points to the same config and state files, the dependency coverage is complete, and the durable state can be read. When `UPSTREAM_RADAR_WEBHOOK_URL` is set, it also checks the HTTPS route locally, recognizes the native Feishu/Lark V2 path, and blocks the retired V1 path before the first poll; it never prints the URL or `UPSTREAM_RADAR_FEISHU_SECRET`. It exits non-zero only for a blocked setup; a missing first-run state is shown as a warning with the next command to run. Add `--json` when another tool needs the result.
|
|
713
|
-
|
|
714
|
-
The generated overlay points DSH at the config and state files explicitly and records the selected profile. If `--registry <url>` was used during initialization, the same registry is carried into the running DSH monitor; otherwise release and candidate checks use the public npm registry. Before each native DSH polling cycle, and before each CLI `radar check` or `radar watch` cycle, it re-reads that profile's installed graph, so later plugin installs, upgrades, removals, and host-runtime changes are not silently missed. If the refresh fails, that cycle stops without replacing the last durable state. `radar status` remains read-only and reports whether a check has completed, which source is unhealthy, whether dependency coverage is complete, the most important active incidents with their exact path or candidate, a suggested next step, pending DSH tasks, and verified model conclusions. Its Attention list is ordered by CISA KEV evidence, then EPSS score, then advisory severity; each vulnerability line shows the evidence that was actually available. Missing signals are not treated as a safety claim. `radar history` is also read-only and shows the bounded transition ledger from the same state file, including resolved incidents that no longer appear in the active summary. You can inspect a stored conclusion with `upstream-radar analysis list <state.json>` or `analysis show <state.json>`. Radar accepts a conclusion only when the response is strict JSON from the matching DSH model session; it never treats arbitrary chat as an analysis result. `radar compare` remains a manual comparison of the files you provide. If you prefer environment variables or need to override the polling interval, omit `--dsh-patch` and use `UPSTREAM_RADAR_CONFIG`, `UPSTREAM_RADAR_STATE`, `UPSTREAM_RADAR_INTERVAL_SECONDS`, `UPSTREAM_RADAR_REGISTRY`, and `UPSTREAM_RADAR_DEEP_CANDIDATES` as before.
|
|
715
|
-
|
|
716
|
-
When you only want the next action after an alert, use the shorter read-only view:
|
|
717
|
-
|
|
718
|
-
```bash
|
|
719
|
-
pnpm dlx --package=upstream-radar@latest upstream-radar radar next ./upstream-radar.config.json
|
|
720
|
-
```
|
|
721
|
-
|
|
722
|
-
It selects the same first incident as `radar status`, then points to its queued DSH task, verified analysis, or the next check command. When a DSH conclusion is already verified, the output also prints its urgency, recommendation, and bounded evidence list so the operator can act without opening a second report. If a task is queued, it also prints the explicit `task ack` command; acknowledging removes only that delivery item, not the active incident or its evidence.
|
|
723
|
-
|
|
724
|
-
The generated graph is the actual installed profile graph. During a native DSH run, Radar also reads the exact DSH CLI entrypoint (`@deepseek-ai/dsh/lib/bin.js`) and discovers the `node_modules` plane that process is using. It does this with bounded, read-only manifest checks: it does not import DSH, load a plugin, or run an install hook. Packages resolved from that plane are marked as `dsh-host`, and their exact versions are checked for advisories. Radar also records the exact `@deepseek-ai/dsh` executable package that owns the plane, so the DSH core and its reachable host dependencies get OSV and npm release checks even when they are not declared plugin dependencies. The graph uses an explicit `host-runtime` boundary edge; a host finding is never presented as an ordinary plugin dependency. `radar status` says whether the host plane came from the running DSH process or the profile fallback. If a required dependency is declared but cannot be resolved from either place, it remains visible as incomplete coverage instead of being treated as absent. Missing optional platform packages are retained as evidence but do not make coverage incomplete. Passing `--registry <url>` explicitly selects the older public npm artifact graph path, which is useful for comparing a profile against registry resolution but is not the default.
|
|
725
|
-
|
|
726
|
-
For a hand-written or CI fixture, use [the example inventory](examples/radar/config.json). If neither a generated `--patch` overlay nor `UPSTREAM_RADAR_CONFIG` is provided, the bundle stays dormant and performs no polling.
|
|
727
|
-
|
|
728
|
-
Once running, Radar polls OSV, GitHub Advisory Database, npm, and public GitHub Releases, then queries CISA KEV and FIRST EPSS for matched CVEs. Native DSH enables those two prioritization feeds by default; set `UPSTREAM_RADAR_THREAT_INTEL=false` when a lean run should omit them. The signals do not decide whether a package is vulnerable: they only explain which confirmed incidents deserve attention first. Radar persists incident state before delivery, and submits only changed incidents to the matching DSH project session. With one root Agent, delivery remains automatic; with multiple roots, Radar requires an exact match between `project.workspace` and `Agent.session.header.cwd`, and keeps the task queued when it cannot prove the route. The native adapter records the exact message id, DSH session, task id, and event id; it writes back only a matching `assistant/message` from that session whose visible text is the six-field JSON result. A new or updated upstream event invalidates the previous result, so an old model conclusion cannot survive a changed dependency fact. If a source is temporarily unavailable, Radar keeps the last confirmed state instead of claiming that the project is clean, continues delivering already queued tasks, and creates one source-health notice for that source after three consecutive failures.
|
|
729
|
-
|
|
730
|
-
Each release cycle also checks a bounded prefix of candidate dependency graphs. This is enabled by default in the DSH adapter and CLI; use `--no-deep-candidates` only when you deliberately want manifest-only compatibility checks. The graph resolver is isolated in a temporary directory and uses `package-lock-only` plus `ignore-scripts`, so candidate package code is not loaded or executed.
|
|
731
|
-
|
|
732
|
-
## Run the proof
|
|
733
|
-
|
|
734
|
-
Boot a real DSH `headless` profile with the packed Upstream Radar bundle installed:
|
|
735
|
-
|
|
736
|
-
```bash
|
|
737
|
-
git clone https://github.com/MicroMilo/upstream-radar.git
|
|
738
|
-
cd upstream-radar
|
|
739
|
-
corepack enable
|
|
740
|
-
pnpm install --frozen-lockfile
|
|
741
|
-
pnpm run try:dsh
|
|
742
|
-
```
|
|
743
|
-
|
|
744
|
-
No DeepSeek API key is required. The paid model endpoint is replaced by a deterministic local DeepSeek-compatible stub; the Cordis loader, DSH Agent, Session, persistence stack, bundle installation, and plugin delivery are real.
|
|
745
|
-
|
|
746
|
-
The command fails unless DSH proves all five facts:
|
|
747
|
-
|
|
748
|
-
```json
|
|
749
|
-
{
|
|
750
|
-
"bundleInstalled": true,
|
|
751
|
-
"radarTaskReachedModel": true,
|
|
752
|
-
"pluginSourcePreserved": true,
|
|
753
|
-
"pendingTasksAfterDelivery": 0,
|
|
754
|
-
"analysisResults": 1,
|
|
755
|
-
"dshEntrypointObserved": true,
|
|
756
|
-
"dshHostRuntimePlaneDiscovered": true
|
|
757
|
-
}
|
|
758
|
-
```
|
|
759
|
-
|
|
760
|
-
This proof runs in CI on Node.js 22. See the executable [showcase contract](examples/dsh/README.md) and its checked-in [result](examples/dsh/reports/headless-smoke.json). Run `pnpm run try:dsh:live` to include a current OSV and npm poll before the DSH handoff.
|
|
761
|
-
|
|
762
|
-
To demonstrate the host-runtime dependency path specifically, run `pnpm run showcase:dsh-runtime`. It starts a real DSH `headless` process, begins at the exact DSH executable package, walks the reachable host dependency closure behind an explicit `host-runtime` boundary, queries a local OSV-compatible feed for the real `@deepseek-ai/cordis` version, persists a `dsh-host` vulnerability path, and hands it to the DSH Agent. The model and advisory are deterministic local stubs; this proves integration and provenance, not the safety of a real advisory.
|
|
763
|
-
|
|
764
|
-
To see why one shared host bug should not page every plugin separately, run `pnpm run showcase:dsh-host-alert`. Two plugin roots share the same exact `@deepseek-ai/cordis` version; Radar emits one project event, keeps both exact paths, and creates one DSH analysis task. Add `:report` to refresh the checked-in [deduplication result](examples/dsh/reports/dsh-host-alert-dedup.json).
|
|
765
|
-
|
|
766
|
-
To validate the actual first-use path against several real published DSH plugins, run `pnpm run showcase:dsh-adoption`. It creates a disposable `DSH_HOME`, packs exact Radar and plugin tarballs with lifecycle scripts disabled, lets DSH build its own host runtime, runs `setup --no-install`, `doctor`, a frozen OSV/npm/GitHub check, and the human-readable status surface. The checked-in trial covers [`dsh-cloudflare-browser-run@0.1.1`](https://www.npmjs.com/package/dsh-cloudflare-browser-run), [`@open-agfs/dsh-agfs@0.1.9`](https://www.npmjs.com/package/@open-agfs/dsh-agfs), and [`dsh-feishu-bot@0.14.0`](https://www.npmjs.com/package/dsh-feishu-bot). The first two install and become monitorable; the Feishu bridge is intentionally recorded as blocked because a clean DSH profile stops on its transitive `protobufjs` build script until a human approves it. A blocked install is not reported as a clean security result. The showcase does not start a DSH Agent or call a model; the separate `try:dsh` proof covers that handoff. The checked-in [adoption result](examples/dsh/reports/adoption-smoke.json) records each plugin's install state, graph coverage, source health, and boundary.
|
|
767
|
-
|
|
768
|
-
The DSH Agent handoff is optional for dependency analysis. If you want to smoke-test that integration with a real published plugin, run `pnpm run try:dsh:real`. It installs the exact published `dsh-find-plugin@0.3.6` into a disposable headless profile and proves that a real DSH Agent receives, consumes, and writes back a Radar analysis task. The model is still a local deterministic stub; no plugin business action or paid endpoint is called. Set `DSH_REAL_PLUGINS` to another exact package only after checking its required profile and credentials.
|
|
769
|
-
|
|
770
|
-
For a public compatibility case, run `pnpm run try:dsh:public-case`. It replays [`dsh-web-ui #35`](https://github.com/zhu1090093659/dsh-web-ui/issues/35) and [`#71`](https://github.com/zhu1090093659/dsh-web-ui/issues/71): the old profile is blocked by a missing loader, the manual package workaround is blocked by a duplicate loader id, and the maintainer's bundled-carrier fix passes. The same compatibility event is then admitted to a real DSH `headless` session and written back as one verified `analysisResult`; see the checked-in [case result](examples/dsh/reports/dsh-web-ui-public-case.json). This is an end-to-end delivery proof with a local deterministic model stub, not a claim about online model quality. The command does not use your DSH credentials or call a paid model endpoint.
|
|
771
|
-
|
|
772
|
-
To see the two-source vulnerability contract without contacting the network, run `pnpm run showcase:github-advisories`. It feeds the same parser issue through OSV and a deterministic GitHub Advisory Database client, proves that two reports become one Radar incident with explicit source provenance and a visible fixed-version conflict, then simulates three GitHub failures and recovery. The existing vulnerability remains active throughout; only the GitHub source-health incident changes.
|
|
773
|
-
|
|
774
|
-
## Validate the compatibility rules
|
|
775
|
-
|
|
776
|
-
Before wiring a project into a compatibility gate, run the offline rule benchmark:
|
|
777
|
-
|
|
778
|
-
```bash
|
|
779
|
-
pnpm dlx --package=upstream-radar@0.33.11 upstream-radar benchmark compatibility
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
It covers six contracts: a safe patch, a change that only needs project analysis, an incompatible DSH peer, a publisher-declared breaking release, a vulnerable candidate dependency, and an incomplete candidate graph. The command does not access the network, install a package, load a plugin, or start DSH. It checks the behavior of Radar's deterministic rules and the `breaking`/`any` gates; it is not a runtime compatibility proof.
|
|
783
|
-
|
|
784
|
-
## Probe a real DSH bundle
|
|
785
|
-
|
|
786
|
-
When you have an exact plugin artifact and want to know whether one exact DSH release can load it, run the bounded probe:
|
|
787
|
-
|
|
788
|
-
```bash
|
|
789
|
-
# Pack an exact npm release without running its lifecycle scripts.
|
|
790
|
-
npm pack --ignore-scripts dsh-plugin@1.2.3
|
|
791
|
-
|
|
792
|
-
pnpm dlx --package=upstream-radar@0.33.11 upstream-radar probe dsh-load \
|
|
793
|
-
./dsh-plugin-1.2.3.tgz \
|
|
794
|
-
--dsh-version 0.1.0-rc.6
|
|
795
|
-
```
|
|
796
|
-
|
|
797
|
-
The probe reads the tarball first, requires a package-local `dsh.bundle.patch`, and refuses lifecycle scripts. It then creates a temporary DSH `headless` profile, adds the exact tarball, checks that DSH registered the bundle, and runs `--dump-config`. The profile is removed at the end unless `--keep-profile` is supplied.
|
|
798
|
-
|
|
799
|
-
There are three deliberate outcomes:
|
|
800
|
-
|
|
801
|
-
| Result | Meaning | Exit code |
|
|
802
|
-
| --- | --- | ---: |
|
|
803
|
-
| `compatible` | This DSH version registered the bundle and loaded its configuration. | `0` |
|
|
804
|
-
| `incompatible` | DSH accepted installation but rejected registration or configuration loading. | `2` |
|
|
805
|
-
| `unknown` | Preflight, DSH startup, installation, or the time limit prevented a reliable conclusion. | `1` |
|
|
806
|
-
|
|
807
|
-
This is a load-compatibility check only. It does not run plugin business actions, test model behavior, or prove that the package and its dependencies are safe. The repository's reproducible three-case demo is:
|
|
808
|
-
|
|
809
|
-
```bash
|
|
810
|
-
pnpm run showcase:dsh-probe
|
|
811
|
-
```
|
|
812
|
-
|
|
813
|
-
It exercises a loadable bundle, a bundle patch DSH rejects, and a package that remains `unknown` because it declares `postinstall`.
|
|
814
|
-
|
|
815
|
-
To compare a plugin against more than one DSH release, use the matrix form:
|
|
816
|
-
|
|
817
|
-
```bash
|
|
818
|
-
pnpm dlx --package=upstream-radar@0.33.11 upstream-radar probe dsh-matrix \
|
|
819
|
-
./dsh-plugin-1.2.3.tgz \
|
|
820
|
-
--dsh-version 0.1.0-rc.3 \
|
|
821
|
-
--dsh-version 0.1.0-rc.6 \
|
|
822
|
-
--json
|
|
823
|
-
```
|
|
824
|
-
|
|
825
|
-
The matrix runs versions one at a time in separate temporary profiles and evaluates the same artifact each time. It needs at least two distinct exact versions and accepts at most eight. The aggregate is `incompatible` if any version is incompatible, `unknown` if none is incompatible but at least one result is unknown, and `compatible` only when every tested version loads successfully. The JSON shape is documented in the [matrix result schema](schemas/dsh-load-matrix.schema.json).
|
|
826
|
-
|
|
827
|
-
## Run it in GitHub Actions
|
|
828
|
-
|
|
829
|
-
If your team wants the shortest scheduled CI gate before wiring a machine to a live DSH profile, copy [the example workflow](examples/github-actions/upstream-radar.yml). It auto-detects the only `pnpm-lock.yaml` or `package-lock.json` after checkout, so no Radar config is required for the first run. If you already maintain a reviewed `upstream-radar.config.json`, pass it explicitly instead. The reusable Action keeps the workflow to two meaningful steps, with an optional third step for DSH load compatibility:
|
|
830
|
-
|
|
831
|
-
```yaml
|
|
832
|
-
steps:
|
|
833
|
-
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
834
|
-
- uses: MicroMilo/upstream-radar@v0.33.11
|
|
835
|
-
with:
|
|
836
|
-
fail-on: high
|
|
837
|
-
# Optional: also fail on deterministic DSH/plugin compatibility breaks.
|
|
838
|
-
fail-on-compatibility: breaking
|
|
839
|
-
# Optional: add CISA KEV and FIRST EPSS signals to matched CVEs.
|
|
840
|
-
threat-intel: true
|
|
841
|
-
```
|
|
842
|
-
|
|
843
|
-
The Action is a thin wrapper around `radar check --frozen --state :memory: --fail-on high --json`; when the optional compatibility input is enabled, it also passes `--fail-on-compatibility breaking` or `any`. `--frozen` is deliberate: it uses the graph in the reviewed config and does not try to read a developer's local DSH profile. `threat-intel` is false by default so an ordinary CI gate stays lean; set it to `true` when the Job Summary and raw JSON should include CISA KEV and FIRST EPSS prioritization evidence. Each run is independent, exits `2` when an active vulnerability or opted-in compatibility change meets its threshold, and exits `1` for an operational or source error. `breaking` catches confirmed or strong incompatibility signals; `any` catches every active compatibility event. The default is `never`, so vulnerability-only behavior stays unchanged. In addition to the raw JSON log, the Action writes a short escaped summary to the GitHub Job Summary so a scheduled failure immediately shows the affected package, exact path, published fix version when available, one-line priority evidence, and a suggested next step. The Action does not deliver a DSH Agent task or modify a branch; the native DSH bundle remains the always-on analysis path. Pin the Action to a release tag such as `v0.33.11`, and pin the checkout Action in your workflow according to your repository's policy.
|
|
844
|
-
|
|
845
|
-
If the repository has no committed Radar config yet, the smallest setup is to omit `config`, `pnpm-lock`, and `npm-lock`. After checkout, the Action automatically uses the only one of `pnpm-lock.yaml` or `package-lock.json` that exists, generates a temporary reviewed config, and runs the same frozen check:
|
|
846
|
-
|
|
847
|
-
```yaml
|
|
848
|
-
- uses: MicroMilo/upstream-radar@v0.33.11
|
|
849
|
-
with:
|
|
850
|
-
fail-on: high
|
|
851
|
-
```
|
|
852
|
-
|
|
853
|
-
An existing `config` wins over auto-detection. If both lockfiles exist, or neither a config nor a supported lockfile exists, the Action stops with a direct message instead of guessing.
|
|
854
|
-
|
|
855
|
-
To review the exact plugin artifact before it enters DSH, add `inspect-package`:
|
|
856
|
-
|
|
857
|
-
```yaml
|
|
858
|
-
- uses: MicroMilo/upstream-radar@v0.33.11
|
|
859
|
-
with:
|
|
860
|
-
inspect-package: dsh-cloudflare-browser-run@0.1.1
|
|
861
|
-
# review is the safe default; use block only when incomplete coverage may pass.
|
|
862
|
-
inspect-fail-on: review
|
|
863
|
-
```
|
|
864
|
-
|
|
865
|
-
This downloads that exact npm tarball, verifies the registry integrity/signature and provenance when available, resolves dependencies with lifecycle scripts disabled, and puts the admission verdict, coverage, findings, and next step in the Job Summary. Write the input as `package@version`; the Action adds the internal `npm:` prefix. It does not install or execute the plugin. The optional `inspect-verdict` output exposes `allow`, `warn`, `review`, or `block` to later workflow steps. An empty finding list with incomplete coverage remains a review result, not a safety certificate.
|
|
866
|
-
|
|
867
|
-
If the repository has a pnpm lockfile but no committed Radar config yet, the Action can generate the config in the same job. See the [copyable pnpm workflow](examples/github-actions/upstream-radar-pnpm.yml):
|
|
868
|
-
|
|
869
|
-
```yaml
|
|
870
|
-
- uses: MicroMilo/upstream-radar@v0.33.11
|
|
871
|
-
with:
|
|
872
|
-
pnpm-lock: pnpm-lock.yaml
|
|
873
|
-
fail-on: high
|
|
874
|
-
```
|
|
875
|
-
|
|
876
|
-
This mode runs `init --pnpm-lock` first and then the same frozen check. `root` is optional when `package.json` is beside the lockfile, and can be supplied for an explicit or non-adjacent workspace root. It never installs the project or executes the plugin; `config` is the output path (default `upstream-radar.config.json`). Leave `pnpm-lock` empty to keep the reviewed-config mode above.
|
|
877
|
-
|
|
878
|
-
Set `npm-lock: package-lock.json` instead for npm projects; `pnpm-lock` and `npm-lock` are mutually exclusive. Both modes infer the root from the adjacent `package.json` unless `root` is supplied.
|
|
879
|
-
See the [copyable npm workflow](examples/github-actions/upstream-radar-npm.yml) for that form.
|
|
880
|
-
|
|
881
|
-
The Action requires the caller to check out the repository first. It does not install the project's dependencies or run their lifecycle scripts; it only reads the committed graph and queries the configured upstream sources. For a fully explicit, lower-level invocation, the equivalent command is:
|
|
882
|
-
|
|
883
|
-
```bash
|
|
884
|
-
pnpm dlx --package=upstream-radar@0.33.11 upstream-radar radar check \
|
|
885
|
-
./upstream-radar.config.json --frozen --state :memory: --fail-on high \
|
|
886
|
-
--fail-on-compatibility breaking --json
|
|
887
|
-
```
|
|
888
|
-
|
|
889
|
-
To add the optional DSH load matrix for a published plugin, provide an exact npm package and at least two exact DSH versions:
|
|
890
|
-
|
|
891
|
-
```yaml
|
|
892
|
-
- uses: MicroMilo/upstream-radar@v0.33.11
|
|
893
|
-
id: radar
|
|
86
|
+
- uses: MicroMilo/upstream-radar@v0.34.0
|
|
894
87
|
with:
|
|
895
88
|
config: upstream-radar.config.json
|
|
896
89
|
fail-on: high
|
|
897
|
-
probe-package: dsh-cloudflare-browser-run@0.1.1
|
|
898
|
-
probe-dsh-versions: 0.1.0-rc.3,0.1.0-rc.6
|
|
899
90
|
```
|
|
900
91
|
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
For a runnable consumer example using the real [`dsh-cloudflare-browser-run@0.1.1`](examples/github-actions/consumer/upstream-radar.config.json) graph, see the [consumer smoke README](examples/github-actions/consumer/README.md) and its [copyable workflow](examples/github-actions/consumer/upstream-radar.yml).
|
|
904
|
-
|
|
905
|
-
Run the consumer path locally from this repository with:
|
|
906
|
-
|
|
907
|
-
```bash
|
|
908
|
-
pnpm run try:consumer
|
|
909
|
-
```
|
|
910
|
-
|
|
911
|
-
This builds the current checkout and runs the same frozen consumer check with the local CLI, so it also works before the next npm version is published. To deliberately verify the public npm artifact instead, run `pnpm run try:consumer:published`; it resolves the package version in `package.json` from npm and should only be used after that version exists publicly.
|
|
912
|
-
|
|
913
|
-
For a local or self-hosted DSH machine, omit `--frozen` so Radar refreshes the selected profile before each cycle. Use `--fail-on` or `--fail-on-compatibility` only with `radar check`, `radar status`, or `radar watch --once`; a long-running watch should continue routing incidents instead of terminating on the first one.
|
|
92
|
+
See the [consumer workflow](examples/github-actions/consumer/README.md) for config and lockfile examples. The GitHub Marketplace prompt is a distribution opportunity, not a separate scanning engine: the Action listing should follow a reviewed stable release, while exact tags remain copyable and auditable.
|
|
914
93
|
|
|
915
|
-
##
|
|
94
|
+
## What it does—and does not do
|
|
916
95
|
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
8. Keep the task on disk when no Agent is available; cancel stale work and conclusions when the incident resolves or changes.
|
|
96
|
+
| It does | It does not claim |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| Reconstruct exact npm/pnpm dependency paths | An empty finding list is a safety certificate |
|
|
99
|
+
| Query OSV and GitHub Advisory evidence for exact versions | A missing provenance statement proves maliciousness |
|
|
100
|
+
| Compare source and published artifact evidence | Static review replaces sandboxing or runtime testing |
|
|
101
|
+
| Check DSH bundle/profile compatibility without business execution | “Compatible” means the plugin is secure |
|
|
102
|
+
| Monitor old → new upstream observations | An LLM can repair evidence that was never collected |
|
|
925
103
|
|
|
926
|
-
|
|
104
|
+
## Install and connect to DSH
|
|
927
105
|
|
|
928
106
|
```bash
|
|
929
|
-
pnpm
|
|
930
|
-
```
|
|
931
|
-
|
|
932
|
-
Use `radar check --frozen --state :memory: --fail-on high --fail-on-compatibility breaking --json` for a machine-enforced CI check against a reviewed graph. The local DSH path continues to use `radar watch`, which refreshes the selected profile before each cycle.
|
|
933
|
-
|
|
934
|
-
The handoff uses `ctx.agents.roots()[0].followup(...)` with:
|
|
935
|
-
|
|
936
|
-
```json
|
|
937
|
-
{
|
|
938
|
-
"kind": "plugin",
|
|
939
|
-
"plugin": "upstream-radar",
|
|
940
|
-
"form": "notice"
|
|
941
|
-
}
|
|
942
|
-
```
|
|
943
|
-
|
|
944
|
-
It is a native DSH lifecycle integration—not a chat bridge or a remote-control bot.
|
|
945
|
-
|
|
946
|
-
## Why package-name alerts are not enough
|
|
947
|
-
|
|
948
|
-
Given this installed graph:
|
|
949
|
-
|
|
950
|
-
```text
|
|
951
|
-
plugin@1.0.0
|
|
952
|
-
├── framework@2.4.7
|
|
953
|
-
│ ├── parser@3.2.1
|
|
954
|
-
│ └── archive@1.8.0
|
|
955
|
-
└── logger@4.0.2
|
|
956
|
-
└── parser@2.9.0
|
|
957
|
-
```
|
|
107
|
+
pnpm add upstream-radar
|
|
958
108
|
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
## Vulnerabilities are only half the upstream problem
|
|
962
|
-
|
|
963
|
-
Upstream Radar also watches candidate releases for compatibility boundaries that matter to DSH plugins:
|
|
964
|
-
|
|
965
|
-
- Node.js engine exclusions;
|
|
966
|
-
- incompatible `@deepseek-ai/dsh-*` or `@deepseek-ai/cordis` peer ranges;
|
|
967
|
-
- changed `main`, `exports`, or DSH bundle patch paths;
|
|
968
|
-
- removed dependencies;
|
|
969
|
-
- major and pre-1.0 breaking version boundaries;
|
|
970
|
-
- publisher-declared breaking changes in supplied release notes, including public GitHub Release notes attached to the candidate version when npm points to a GitHub repository.
|
|
971
|
-
|
|
972
|
-
These are signals for project analysis, not automatic claims that an upgrade is broken.
|
|
973
|
-
|
|
974
|
-
## The model gets judgment, not control of the facts
|
|
975
|
-
|
|
976
|
-
Upstream Radar determines facts that a model must not guess:
|
|
977
|
-
|
|
978
|
-
```text
|
|
979
|
-
parser@2.9.0 is reported as affected
|
|
980
|
-
plugin -> logger -> parser is the installed path
|
|
981
|
-
the project runs Node.js 22
|
|
982
|
-
the candidate requires Node.js >=24
|
|
983
|
-
the installed DSH peer is outside the candidate range
|
|
984
|
-
```
|
|
985
|
-
|
|
986
|
-
The DSH Agent answers the repository-specific questions:
|
|
987
|
-
|
|
988
|
-
```text
|
|
989
|
-
is the vulnerable feature reachable here?
|
|
990
|
-
can attacker-controlled input reach it?
|
|
991
|
-
which API or Cordis configuration would the upgrade disturb?
|
|
992
|
-
what is the least disruptive project-specific action?
|
|
109
|
+
# Generate a reviewable DSH profile inventory from the installed profile
|
|
110
|
+
npx --yes upstream-radar@0.34.0 setup
|
|
993
111
|
```
|
|
994
112
|
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
Advisories, release notes, links, package names, and repository strings remain untrusted data. The generated task requires read-only analysis, project evidence, explicit uncertainty, and a fixed [result schema](schemas/analysis-result.schema.json).
|
|
998
|
-
|
|
999
|
-
## What works today
|
|
113
|
+
For Feishu/webhook routing, DSH Agent handoff, observer state, report schemas, and troubleshooting, use the [full Chinese guide](docs/README.zh-CN.md). The [architecture notes](docs/architecture.md) explain the boundaries and evidence model.
|
|
1000
114
|
|
|
1001
|
-
|
|
1002
|
-
- DSH shared host-runtime dependency resolution discovered from the running DSH process, with profile and `dsh-host` packages kept distinct in both graphs and alerts;
|
|
1003
|
-
- exact `@deepseek-ai/dsh` executable-package evidence, including host-boundary OSV alerts and its own npm compatibility stream;
|
|
1004
|
-
- one project-level alert for a shared DSH host-runtime vulnerability, retaining every affected plugin root and exact path instead of sending duplicate per-plugin notices;
|
|
1005
|
-
- exact-version OSV vulnerability and malicious-package matching;
|
|
1006
|
-
- independent GitHub Advisory Database matching for exact npm versions, with GHSA/CVE alias deduplication, merged fix versions, and source-specific health;
|
|
1007
|
-
- npm release monitoring for plugins and DSH/Cordis packages, accepting only a candidate newer than the installed exact version (a regressed `latest` dist-tag is not a breaking update), with public GitHub Release notes attached when an exact candidate tag is available;
|
|
1008
|
-
- bounded transitive dependency graph checks for the earliest candidate versions, exact OSV matching for every resolved node, vulnerable path evidence, and explicit incomplete/unavailable coverage;
|
|
1009
|
-
- durable incident state with current-task replacement and resolution;
|
|
1010
|
-
- a bounded transition history with a local `radar history` audit command;
|
|
1011
|
-
- strict DSH result writeback bound to the exact message, session, task, and event, with stale-result rejection;
|
|
1012
|
-
- native DSH bundle installation, startup polling, `agent/created` retry, and plugin-source attribution;
|
|
1013
|
-
- optional provider-neutral HTTPS webhook delivery for changed events, with endpoint-safe deduplication and retry, project-specific environment routes with independent outboxes, plus direct Feishu/Lark V2 text delivery;
|
|
1014
|
-
- delivery-only notification controls for per-project minimum vulnerability severity and timezone-aware quiet hours; critical and malicious-package alerts bypass them, while held DSH tasks and webhook events remain durable;
|
|
1015
|
-
- read-only pnpm v6/v9 lockfile graph extraction, including project-root importers and explicit ambiguous peer references;
|
|
1016
|
-
- static Radar inventory generation from npm or pnpm lockfiles, followed by the same exact-version OSV check used by the DSH monitor;
|
|
1017
|
-
- automatic selection of the only DSH profile with third-party bundles, plus a network-free `radar status` snapshot;
|
|
1018
|
-
- commit-friendly `init` output that records the project workspace as `.` by default;
|
|
1019
|
-
- a reusable GitHub Action that turns the reviewed graph into a two-step, frozen CI gate;
|
|
1020
|
-
- a concise escaped GitHub Job Summary alongside the Action's raw JSON result;
|
|
1021
|
-
- an opt-in GitHub Action DSH load matrix for exact published plugin versions and exact DSH versions;
|
|
1022
|
-
- a real DSH plugin consumer smoke that runs the published Action against 18 exact package versions;
|
|
1023
|
-
- an actionable, network-free `radar status` summary with exact active paths, candidate signals, and next steps;
|
|
1024
|
-
- a network-free `doctor` command that checks local DSH registration, overlay/config alignment, state readability, and dependency coverage;
|
|
1025
|
-
- compatibility signals for Node.js, peers, exports, entrypoints, bundle paths, dependencies, and version boundaries;
|
|
1026
|
-
- top-level remediation evidence that compares active vulnerability ids and aliases with complete candidate graphs, identifying the first non-blocked plugin candidate that removes all checked paths without calling it safe;
|
|
1027
|
-
- an opt-in CI gate for confirmed/strong (`breaking`) or all (`any`) active compatibility changes;
|
|
1028
|
-
- an offline `benchmark compatibility` command that locks the deterministic rule and gate behavior into six reviewable contracts;
|
|
1029
|
-
- disposable `probe dsh-load` and `probe dsh-matrix` commands that check one exact DSH version or a bounded exact-version matrix against one bundle and return `compatible`, `incompatible`, or `unknown`;
|
|
1030
|
-
- network-free Radar and real DSH runtime showcases.
|
|
1031
|
-
|
|
1032
|
-
The bounded pre-install scanner remains available as a supporting collector. It
|
|
1033
|
-
accepts either a local directory or a public GitHub repository URL:
|
|
115
|
+
## Development
|
|
1034
116
|
|
|
1035
117
|
```bash
|
|
1036
|
-
pnpm
|
|
1037
|
-
pnpm
|
|
1038
|
-
pnpm
|
|
118
|
+
pnpm install
|
|
119
|
+
pnpm test
|
|
120
|
+
pnpm run release:check
|
|
1039
121
|
```
|
|
1040
122
|
|
|
1041
|
-
The
|
|
1042
|
-
|
|
1043
|
-
## Current boundaries
|
|
1044
|
-
|
|
1045
|
-
- `init` discovers the only DSH profile with third-party bundles when `--profile` is omitted; multiple candidates still require an explicit profile. By default it follows the installed DSH `node_modules` tree, so pnpm overrides and local resolution choices are included. `--dsh-patch <path>` writes an explicit DSH overlay so first startup needs no environment variables and preserves an explicitly selected registry. `graph npm-lock` and `graph pnpm-lock` are separate pre-install/CI collectors; they do not themselves query OSV or create a Radar config.
|
|
1046
|
-
- `init --pnpm-lock <path>` or `init --npm-lock <path>` creates a static config without a DSH profile; it reads `package.json` beside the lockfile unless `--root <name>@<version>` is supplied. Follow it with `radar check` or `radar watch` to query OSV. It does not itself start DSH or deliver Agent tasks.
|
|
1047
|
-
- If the plugin root is not published to the selected npm registry, a registry `404` skips only that package's release comparison; exact lockfile dependencies and published DSH host packages are still checked. Registry outages, timeouts, malformed responses, and OSV failures remain operational errors.
|
|
1048
|
-
- A graph with unresolved required dependency declarations is marked as incomplete coverage; optional packages that are not installed for the current platform remain visible but do not create a false required-dependency alert. Missing `@deepseek-ai/dsh`, `@deepseek-ai/dsh-*`, and Cordis peers are called out separately as unobserved DSH host dependencies because Radar cannot query a version it was never shown. If the DSH executable package itself cannot be read from the active host plane, the core-runtime boundary remains unknown rather than being guessed.
|
|
1049
|
-
- Candidate upgrade graphs are resolved only for a bounded earliest prefix. A candidate with an incomplete or unavailable graph is not recommended; later unqueried candidates remain visibly unchecked. Pass `--no-deep-candidates` to opt out of this extra registry work.
|
|
1050
|
-
- When an active vulnerability belongs to an installed plugin, candidate remediation is narrower than an upgrade recommendation: `removed` means the complete checked candidate graph has no matching OSV finding, `still-affected` means a matching path remains, and `unknown` means the graph/source is incomplete, truncated, unavailable, or the path comes from the shared DSH host runtime. A remediation candidate still needs DSH project analysis.
|
|
1051
|
-
- Compatibility CI gating is opt-in: `--fail-on-compatibility breaking` fails on confirmed or strong incompatibility signals, while `any` fails on every active compatibility event; neither setting claims that a candidate is safe.
|
|
1052
|
-
- `probe dsh-load` is intentionally narrower than a security scan: a successful load proves only that the selected DSH profile accepted the bundle configuration. It does not execute plugin actions, compare capabilities, or grant admission to an unreviewed package.
|
|
1053
|
-
- `probe dsh-matrix` is intentionally sequential and bounded to eight versions. An incomplete matrix is not green: `unknown` propagates to the aggregate result until every selected DSH version has a reliable load result.
|
|
1054
|
-
- `radar check/watch --frozen` intentionally uses the graph committed in the config for CI; it does not prove that the installed DSH profile has not changed. Without `--frozen`, native DSH and CLI polling refresh the selected profile first.
|
|
1055
|
-
- `radar status` is a local snapshot only: it does not refresh OSV, GitHub Advisory, npm, or GitHub Release data, and it cannot prove that a source is current until a check has completed. It does show whether a captured DSH host plane came from the running process or a profile fallback. Its next steps are guidance, not an automatic upgrade or safety decision.
|
|
1056
|
-
- `doctor` checks local wiring only; it cannot prove that a running DSH process has delivered a task to a model or that upstream feeds are current.
|
|
1057
|
-
- npm and pnpm lock graphs are supported; Yarn graph extraction is not implemented.
|
|
1058
|
-
- OSV, GitHub Advisory Database, npm `latest`, and public GitHub Release notes are live sources; changelog, comparison-diff, and migration-guide ingestion are deferred.
|
|
1059
|
-
- A failed advisory-source check preserves confirmed matches and returns a visible source warning; each source's health is durable and routed through DSH after three consecutive failures. When OSV and GitHub Advisory Database disagree about severity or fixed versions, the event keeps both source-labeled claims and makes the conflict explicit instead of silently choosing one. Changed events can be sent to a provider-neutral HTTPS endpoint or directly to a Feishu/Lark V2 bot; there is no separate hosted alerting service.
|
|
1060
|
-
- `radar watch` is a CLI monitoring fallback; it does not deliver tasks into DSH by itself.
|
|
1061
|
-
- Delivery uses one root Agent as the simple default; when several roots exist, it requires an exact project-workspace match and leaves ambiguous tasks queued instead of guessing.
|
|
1062
|
-
- DSH result writeback accepts only the exact six-field JSON contract from the matching model session; it does not infer conclusions from ordinary chat or tool output. The result is advisory and never changes deterministic incident state.
|
|
1063
|
-
- No Issue, branch, Pull Request, dependency override, or merge is created automatically.
|
|
1064
|
-
|
|
1065
|
-
Upstream Radar is alpha software built for the developer-preview DSH ecosystem. Event schemas and adapter boundaries can change.
|
|
1066
|
-
|
|
1067
|
-
## Project guide
|
|
1068
|
-
|
|
1069
|
-
- [Architecture](docs/architecture.md)
|
|
1070
|
-
- [DSH headless showcase](examples/dsh/README.md)
|
|
1071
|
-
- [Radar showcase walkthrough](docs/showcase.md)
|
|
1072
|
-
- [Product vision(中文)](docs/vision.zh-CN.md)
|
|
1073
|
-
- [Checks and evidence(中文)](docs/checks.zh-CN.md)
|
|
1074
|
-
- [Threat model](docs/threat-model.md)
|
|
1075
|
-
- [Roadmap](ROADMAP.md)
|
|
1076
|
-
- [Changelog](CHANGELOG.md)
|
|
1077
|
-
- [Release process](docs/releasing.md)
|
|
1078
|
-
- [Contributing](CONTRIBUTING.md)
|
|
1079
|
-
- [Security policy](SECURITY.md)
|
|
1080
|
-
|
|
1081
|
-
If DSH plugins are part of your stack, star the repository to follow the upstream safety loop as it grows. Start with the [reproducible DSH handoff showcase](https://github.com/MicroMilo/upstream-radar/discussions/11), then share questions and design feedback in [GitHub Discussions](https://github.com/MicroMilo/upstream-radar/discussions).
|
|
1082
|
-
|
|
1083
|
-
<sub>Community project for DeepSeek Harness. Not an official DeepSeek product. Apache-2.0 licensed.</sub>
|
|
123
|
+
The project is Apache-2.0 licensed. Contributions that improve a real DSH plugin report, dependency resolution, advisory matching, or reproducible author feedback are especially welcome.
|