mirror of
https://github.com/safedep/pmg.git
synced 2026-08-03 07:24:09 +02:00
feat: emit cloud events for dependency cooldown and host observations (#243)
* feat: emit cloud events for dependency cooldown and host observations (#237) Wire cooldown blocks and proxy host observations through the cloud sync pipeline so they appear as telemetry in Control Tower. - Cooldown blocks emit PACKAGE_DECISION with COOLDOWN_BLOCKED action and PmgDependencyCooldown context (publish date, cooldown days, days since publish, days remaining) - Proxy host observations emit HOST_OBSERVATION with PmgHostObservation (hostname, method) - Session summary now includes cooldown_blocked_count - Updated buf API dependency for new proto schema Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * format file * fix: add explicit eventlog mapping for EventTypeDependencyCooldown Follow the existing pattern where every audit event type has an explicit case in mapEventType and a corresponding constant in the eventlog package. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Apply suggestion from @devin-ai-integration[bot] Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> Signed-off-by: Abhisek Datta <abhisek.datta@gmail.com> --------- Signed-off-by: Abhisek Datta <abhisek.datta@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Abhisek Datta <abhisek.datta@gmail.com> Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
co-authored by
Claude Opus 4.6
devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Abhisek Datta
devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
parent
b671192598
commit
19d735cdd2
@@ -1,6 +1,11 @@
|
||||
package interceptors
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1"
|
||||
"github.com/safedep/pmg/internal/audit"
|
||||
)
|
||||
|
||||
// cooldownIsWithinWindow reports whether a version published at publishDate is still
|
||||
// within the cooldown window of cooldownDays. Returns withinCooldown, daysSincePublish,
|
||||
@@ -34,21 +39,32 @@ func cooldownOldestVersion(dates map[string]time.Time) (string, time.Time) {
|
||||
// recordCooldownStats records a cooldown block event. When all versions are blocked
|
||||
// (remaining == 0), it reports the oldest version (closest to exiting cooldown).
|
||||
// Otherwise, if a pinned version was stripped, it reports that specific version.
|
||||
func recordCooldownStats(statsCollector *AnalysisStatsCollector, packageName string, pinnedVersion string, dates map[string]time.Time, remaining int, cooldownDays int) {
|
||||
func recordCooldownStats(statsCollector *AnalysisStatsCollector, ecosystem packagev1.Ecosystem, packageName string, pinnedVersion string, dates map[string]time.Time, remaining int, cooldownDays int) {
|
||||
if statsCollector == nil {
|
||||
return
|
||||
}
|
||||
|
||||
logCooldown := func(version string, publishDate time.Time, daysAgo, daysLeft int) {
|
||||
statsCollector.RecordCooldownBlocked(packageName, version, publishDate, daysAgo, daysLeft, cooldownDays)
|
||||
|
||||
pv := &packagev1.PackageVersion{}
|
||||
pv.SetPackage(&packagev1.Package{})
|
||||
pv.GetPackage().SetName(packageName)
|
||||
pv.GetPackage().SetEcosystem(ecosystem)
|
||||
pv.SetVersion(version)
|
||||
audit.LogDependencyCooldown(pv, publishDate, cooldownDays, daysAgo, daysLeft)
|
||||
}
|
||||
|
||||
if remaining == 0 {
|
||||
oldestVer, oldestDate := cooldownOldestVersion(dates)
|
||||
if oldestVer != "" {
|
||||
_, daysAgo, daysLeft := cooldownIsWithinWindow(oldestDate, cooldownDays)
|
||||
statsCollector.RecordCooldownBlocked(packageName, oldestVer, oldestDate, daysAgo, daysLeft, cooldownDays)
|
||||
logCooldown(oldestVer, oldestDate, daysAgo, daysLeft)
|
||||
}
|
||||
} else if pinnedVersion != "" {
|
||||
if pinnedDate, ok := dates[pinnedVersion]; ok {
|
||||
if withinCooldown, daysAgo, daysLeft := cooldownIsWithinWindow(pinnedDate, cooldownDays); withinCooldown {
|
||||
statsCollector.RecordCooldownBlocked(packageName, pinnedVersion, pinnedDate, daysAgo, daysLeft, cooldownDays)
|
||||
logCooldown(pinnedVersion, pinnedDate, daysAgo, daysLeft)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1"
|
||||
"github.com/safedep/dry/log"
|
||||
"github.com/safedep/pmg/proxy"
|
||||
)
|
||||
@@ -66,7 +67,7 @@ func (h *npmCooldownHandler) HandleMetadataRequest(ctx *proxy.RequestContext, pa
|
||||
log.Infof("[%s] Cooldown: stripped %d version(s) from %s metadata (%d days, %d eligible remain)",
|
||||
ctx.RequestID, stripped, packageName, cooldownDays, remaining)
|
||||
|
||||
recordCooldownStats(h.statsCollector, packageName, pinnedVersion, dates, remaining, cooldownDays)
|
||||
recordCooldownStats(h.statsCollector, packagev1.Ecosystem_ECOSYSTEM_NPM, packageName, pinnedVersion, dates, remaining, cooldownDays)
|
||||
|
||||
// Prevent npm from caching the modified response. Without this,
|
||||
// npm would serve the stripped metadata from cache even after the
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
packagev1 "buf.build/gen/go/safedep/api/protocolbuffers/go/safedep/messages/package/v1"
|
||||
"github.com/safedep/dry/log"
|
||||
"github.com/safedep/pmg/proxy"
|
||||
)
|
||||
@@ -53,7 +54,7 @@ func (h *pypiCooldownHandler) HandleMetadataRequest(ctx *proxy.RequestContext, p
|
||||
log.Infof("[%s] Cooldown: stripped %d version(s) from %s metadata (%d days, %d eligible remain)",
|
||||
ctx.RequestID, stripped, packageName, cooldownDays, remaining)
|
||||
|
||||
recordCooldownStats(h.statsCollector, packageName, pinnedVersion, dates, remaining, cooldownDays)
|
||||
recordCooldownStats(h.statsCollector, packagev1.Ecosystem_ECOSYSTEM_PYPI, packageName, pinnedVersion, dates, remaining, cooldownDays)
|
||||
|
||||
headers.Set("Cache-Control", "no-store")
|
||||
return statusCode, headers, strippedBody, nil
|
||||
|
||||
Reference in New Issue
Block a user