Ctrl K
ComunidadGuías…

core/collector.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package core

import (
	"context"
	"time"
)

// Collector is the ONLY thing a new product must implement. Everything generic
// a product needs — scheduling, concurrency, storage, dedup, diffing,
// notification, display — is provided by the core. Adding product #2 means
// writing a new Collector, not a new application.
type Collector interface {
	// Describe returns static metadata. Called once at registration.
	Describe() ModuleInfo

	// ValidateTarget parses and normalises raw user input into a canonical
	// Target, or returns a user-facing error explaining what's wrong. Called
	// when a user adds a target — never during a scan.
	ValidateTarget(raw string) (Target, error)

	// Collect performs one check of one target and returns findings. This is
	// where ALL the product's intelligence lives. It MUST:
	//   - respect ctx cancellation/timeout,
	//   - be side-effect free with respect to the target beyond reading it,
	//   - fill only collector-owned Finding fields,
	//   - return a deterministic Fingerprint per finding.
	// An empty slice with nil error means "checked, all clear". A non-nil
	// error means the scan itself failed (host unreachable, timeout) — NOT
	// that a problem was found. A problem found is a Finding.
	Collect(ctx context.Context, t Target) ([]Finding, error)

	// Diff is OPTIONAL. Return nil to defer to the core's fingerprint-based
	// diff. Implement it only when "what changed since last scan" is a
	// first-class product output (e.g. Attack Surface Monitor).
	Diff(previous, current []Finding) []Change
}

// ModuleInfo is a collector's static metadata, read once at registration.
type ModuleInfo struct {
	ID              string        // "certwatch" — becomes Finding.Module
	Name            string        // "CertLight"
	Version         string        // semver
	TargetKind      string        // human hint: "host:port", "domain", "device"
	DefaultInterval time.Duration // smart default; user may override (paid tier)
	ResolveAfter    int           // consecutive-absent scans before auto-resolve (>=1)
}

// ResolveAfterOrDefault returns the effective auto-resolve threshold, defaulting
// to 1 when a module leaves it unset. One is right for deterministic checks;
// flappy modules raise it to avoid resolve/reopen churn (decision #2).
func (m ModuleInfo) ResolveAfterOrDefault() int {
	if m.ResolveAfter < 1 {
		return 1
	}
	return m.ResolveAfter
}

// Target is a validated, canonicalised scan target.
type Target struct {
	Raw       string            // exactly what the user typed
	Canonical string            // normalised, e.g. "example.com:443"
	Meta      map[string]string // collector-specific parsed bits
}

// Change is an entry produced by an optional Collector.Diff implementation.
type Change struct {
	Kind    string // "added" | "removed" | "changed"
	Finding Finding
	Detail  string
}