Groundskeeper

Detector and plugin contract

Semantic boundary

A detector analyses canonical content and returns observations. It cannot select policy, authorize traffic, mutate provider payloads, or return the final decision. The same versioned semantics apply to compile-time built-ins and future execution adapters.

Conceptual operations are:

Describe()                 capabilities, schemas, limits, health metadata
Detect(request)            one bounded event
DetectBatch(requests)      optional, explicitly declared batching

The initial transport-neutral model appears in the OpenAPI schemas. A proposed future protobuf is in api/proto/groundskeeper/detector/v1. It is a design artefact, not a frozen generated-code API.

Required behavior

  • Honor caller deadlines and cancellation.
  • Enforce declared payload and batch limits.
  • Treat request IDs as opaque correlation values.
  • Return deterministic output when the manifest claims determinism.
  • Return code-point spans into the exact supplied segment text.
  • Distinguish complete, partial, unsupported, timed-out, failed, and skipped coverage; never represent an execution failure as zero findings.
  • Return findings/evidence, not allow/block actions.
  • Avoid matched sensitive values in errors, health output, logs, and evidence.
  • Declare idempotency before the host may retry.

Manifest

The manifest schema records detector ID and SemVer, artefact digest, host protocol range, kinds/categories/modalities, configuration schema reference, permissions, resource bounds, determinism, idempotency, batching, and streaming support. The host validates configuration at activation and intersects requested permissions with operator policy.

Execution tiers

Built-in Go

Phase 1 detectors are trusted, compile-time implementations. They provide the lowest latency and simplest deployment but ship on the host release cadence.

Supervised local gRPC

The first external mode is a warm protobuf/gRPC subprocess. Process separation is crash and language isolation, not a security sandbox. Run under a dedicated identity with read-only filesystem, bounded CPU/memory/processes, seccomp and namespaces or a container, and network denied by default. The host owns startup, readiness, deadlines, draining, restart budgets, and circuit breaking.

Remote gRPC

Remote execution is for GPU or operationally independent services. Require mTLS and workload identity, explicit tenant/data-destination approval, payload limits, deadlines, circuit breakers, and bounded retries only when idempotency is declared. External processing and cross-border privacy decisions remain unresolved.

WASM/wazero

WASM is the intended portable untrusted-detector path after the ABI and Component Model maturity are validated. The ABI is small and capability-denied: no network, filesystem, clock, randomness, or environment access unless separately specified and approved. Bound memory, fuel/time, output size, and cancellation.

Not selected

Go native .so plugins are not supported: they share host privileges, cannot be reliably unloaded, and couple operating system, Go version, dependencies, and build flags. HTTP/JSON may exist as an interoperability adapter but is not the canonical plugin protocol.

Distribution and lifecycle

Future plugin artefacts are digest-pinned and signed in OCI with SBOM, provenance, compatibility range, and trust tier (built-in, trusted-process, untrusted-wasm, or remote). Activation follows verify → conformance → shadow → canary → atomic promotion. The platform supports drain, rollback, revocation, and last-known-good.

Conformance

Every adapter runs the same cases for discovery, malformed input, Unicode spans, coverage states, cancellation, deadline, oversized payload, output bounds, configuration rejection, determinism claims, and sensitive error redaction.

On this page