* docs(specs): add custom block messages and package blocklist spec
* docs(specs): add custom block messages and package blocklist implementation plan
* feat(config): add blocked_packages list and custom block messages
* feat(audit): add package_blocklist_blocked event and blocklist model
* feat(proxy): block blocklisted packages in the policy gate before analysis
* feat(guard): block blocklisted packages before trust skip and analysis
* feat(ui): render blocklist blocks and custom messages, fix silent-mode block output
* feat(proxy): append custom messages to malware and go-cooldown block bodies
* test(proxye2e): cover blocklist enforcement and custom block messages
* docs(specs): remove spec and plan documents
* refactor: drop guard-flow blocklist enforcement and trim docs
Guard mode is being deprecated; the blocklist is enforced in proxy mode
only. Remove the trusted_packages mirroring references outside the docs.
* refactor(config): consolidate blocklist and block message under top-level block section
Replace dependency_cooldown.message, malware.message and blocked_packages
with a single block section: block.message is appended to every block
output regardless of which control blocked, and block.packages is the
package blocklist.
* fix(ui): render block.message as info note with clean spacing
* fix(ui): indent wrapped continuation lines in block reasons and messages
* update config template
* refactor(config): replace block section with top-level advisory_message
Remove the package blocklist (will be implemented as part of policies in
the future) and replace block.message with an optional top-level
advisory_message appended to every block output.
* chore(config): move advisory_message near top-level scalar configs in template
* feat(cooldown): respect trusted_packages in dependency cooldown
Trusted packages are now treated as a superset waiver that bypasses every
PMG control (malware analysis, cooldown, and any future controls). A
globally trusted package is automatically exempt from the cooldown window
and no longer needs a duplicate entry in dependency_cooldown.skip.
The skip list remains the narrower, cooldown-only waiver for packages
that must bypass the cooldown wait but still be malware-scanned.
* refactor(cooldown): tag skip reason and audit-log skipped packages
Address review feedback on #342:
- Restore cooldownSkip to a pure single-list function (SRP); the merge
into trusted_packages now happens in a separate mergeCooldownSkip step,
driven by the exported CooldownSkip wrapper.
- Extend CooldownSkipInfo with a CooldownSkipReason (TrustedPackage /
CooldownSkipList) on both SkipAll and per-version entries, so callers
can tell apart the broad waiver from the cooldown-only one. When both
lists match the same package, trusted_packages wins.
- Add audit.LogCooldownSkipped and emit it from the npm and PyPI
interceptors on the SkipAll path, alongside the existing info log,
carrying the source list as the reason.
* refactor(cooldown): inline list merge, audit per-version exemptions
Address further review feedback:
- Drop the separate mergeCooldownSkip helper; cooldownSkip now writes
into a shared *CooldownSkipInfo and is called twice from CooldownSkip
(cooldown skip list first, trusted_packages on top so trusted entries
override the reason on overlap).
- Audit log every exemption, not just SkipAll: a new auditCooldownSkip
helper in proxy/interceptors/cooldown.go emits one event per match
(package-wide or per-version), each tagged with its source list.
LogCooldownSkipped gains a version argument for the per-version case.
- Cover the trusted_packages reason path in TestCooldownSkip.
* fix(cooldown): avoid double-auditing trusted package exemptions
auditCooldownSkip now only emits EventTypeCooldownSkipped for entries
that came from dependency_cooldown.skip. Trusted-package exemptions
already get an EventTypeInstallTrustedAllowed event at tarball-download
time (proxy/interceptors/base_registry.go), so emitting a cooldown event
for them too would double-count the same waiver.
* emit trusted and cooldown skip events to cloud
* fix tests
* refactor(cooldown): return value from collectCooldownSkip, short-circuit on trusted SkipAll
Address PR review feedback:
- Rename cooldownSkip to collectCooldownSkip and return CooldownSkipInfo
instead of mutating an input pointer.
- Add mergeCooldownSkip to combine per-list results with trusted_packages
taking precedence on overlap.
- CooldownSkip now consults trusted_packages first and returns immediately
on a package-wide trusted exemption (DC skip list cannot add anything).
- Extend tests to cover disjoint pinned entries across both lists and the
case where DC version-less subsumes a trusted pinned entry.
* fix(audit): address cooldown review feedback
* fix(cooldown): audit cooldown skips at download time with concrete version
Backend rejects PackageVersion messages without a version, and audit logs
should reflect the runtime fact (a specific version was skipped) rather
than the config rule. Move the audit emission from metadata-request
handling to download-request handling, where the concrete version is
known, and require version in LogCooldownSkipped.
* chore(audit): drop dead scope assignment in LogCooldownSkipped
* refactor(cooldown): move skip-list logic into cooldown handlers
Registry interceptors no longer compute CooldownSkip or branch on SkipAll;
they just call HandleMetadataRequest. The npm and pypi cooldown handlers
own the skip lookup, the package-wide exemption short-circuit, and (for
pypi) the canonical-name denormalization. Also align LogCooldownSkipped
with other LogXxx signatures by taking *packagev1.PackageVersion.
* fix: Simplify audit logging for dependency cooldown skip
* refactor: Simplify cooldown handling and maintain separation of concepts for trusted and DC skip packages
* fix: Code review fixes
* fix: Emit cooldown skipped audit event ONLY when an in-window version is skipped
---------
Co-authored-by: Abhisek Datta <abhisek.datta@gmail.com>
Let dependency cooldown respect an explicit skip list so first-party /
internal packages that must be installed the moment they are published
(e.g. to sanity-test a freshly released version) are not held back by the
cooldown window.
Per review, this is a per-control skip list — NOT a second definition of
"trusted package". There remains a single top-level `trusted_packages`
(which waives malware analysis); `dependency_cooldown.skip` waives ONLY
the cooldown wait, so a fast-tracked package is still malware-scanned.
Matching:
- a PURL without a version skips cooldown for all versions of the package
(package-level) — the metadata passes through unmodified;
- a PURL with a version skips cooldown for that version only — that
version is preserved during stripping while other recent versions are
still held.
- config: DependencyCooldownConfig.Skip + CooldownSkip()/CooldownSkipInfo.
- npm/pypi interceptors: bypass on package-level skip; thread per-version
exemptions into the cooldown stripper so pinned versions survive.
- docs + config template; unit tests for the matcher (package/version
level, precedence, mismatches) and the skip-vs-trusted independence.
Signed-off-by: dmdhrumilmistry <56185972+dmdhrumilmistry@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>