Features

Protection plans

Time-bounded admission policies, scoped to discovered applications, with cluster-truth health and a violations feed.

Protection plans are the flagship feature of telark. A plan binds one or more policy templates to a scope (applications, namespaces, or both), a mode (audit or enforce), and an optional time range. When the plan is active, an in-cluster controller has deployed the corresponding admission policies to the cluster; when the plan ends, those policies are cleaned up.

This page covers the full surface as the UI uses it.

The plan resource

A ProtectionPlan is persisted as a custom resource owned by the exporter service. The UI form maps directly onto the same shape.

FieldTypeNotes
idstringGenerated server-side.
namestringHuman label.
descriptionstring?Optional.
severitystring?UI-only annotation.
priorityint?Sorting hint; the UI submits it as an int.
scope.typeapplications | namespacesPicked in the Scope section.
scope.applicationIdsstring[]Used when type=applications.
scope.namespacesstring[]Used when type=namespaces.
policies[].templateIDstringA template ID from the catalog.
policies[].paramsRecord<string, string[]>Required when the template declares them.
modeaudit | enforcePer-plan. Drives Kyverno validationFailureAction.
timeModepermanent | time_rangePermanent plans run until cancelled.
timeRange.startAtRFC3339Required when timeMode=time_range.
timeRange.endAtRFC3339Required when timeMode=time_range.
phasedraft | scheduled | active | terminated | canceled | failedController-owned.
reasonstring?Populated on failure or manual cancel.
renderedPoliciesstring[]?Names of admission policies the applier deployed.
participantsIDsstring[]?User / group IDs responsible for the plan.
healthunknown | healthy | drifted | degradedSet by the health check; only meaningful when phase=active.
healthCheckedAtstring?ISO timestamp of the last health probe.
healthDetail[]PlanHealthDetailPer-policy presence / readiness / failure action.
createdAt / createdByauditSet on prepare.
lastUpdatedAt / lastUpdatedByauditSet on every patch.
startedAt / startedByauditSet on activate.
terminatedAt / terminatedByauditSet on terminate.

Lifecycle endpoints

Discovery owns the plan logic; the API surface looks like:

MethodPathPurpose
POST/protection-plans/prepareCreate a plan, validate, persist.
PATCH/protection-plans/{id}Update scope / templates / schedule.
POST/protection-plans/{id}/cancelCancel a running or scheduled plan.
POST/protection-plans/{id}/reactivateBring a cancelled plan back into the schedule.
POST/protection-plans/{id}/duplicateClone into a new draft with regenerated IDs.
GET/protection-plans/{id}/statusLatest phase + health.
GET/protection-plans/{id}/violationsSorted, paginated cluster-side violations.
GET/protection-plans/templatesThe template catalog.
DELETE/protection-plans/{id}Remove (controller cleans up cluster-side policies first).

Every write endpoint requires the user header — the audit fields are populated from it.

Phases

PhaseSet byCluster effect
draftprepare for permanent plans you haven't started, or for new schedules ahead of time.None.
scheduledprepare when timeMode=time_range and startAt is in the future.None until startAt.
activeController when startAt ≤ now.Applier deploys policies; health and violations begin.
terminatedController when endAt ≤ now for time_range plans.Applier cleans up policies; phase is terminal.
canceledManual cancel.Applier cleans up policies; phase is terminal.
failedController on activation failure.Partial cluster state may be left; manual reactivate to retry.

Controller tick interval defaults to 31 seconds and is overridable via the PROTECTION_PLAN_TICK_INTERVAL_SEC environment variable on the discovery deployment.

Mode: audit vs enforce

The per-plan mode field drives the validationFailureAction on every deployed Kyverno policy:

  • audit — admission is not blocked. Violations are recorded against the Kyverno PolicyReport and surfaced in the telark violations feed. Good for staging a rule before turning it on.
  • enforce — admission is rejected when a policy fails. Operators see a Kubernetes API error at the source of the change.

Health flags the plan as drifted if the deployed validationFailureAction no longer matches the plan's mode.

Templates

Nine templates ship today, each declaring its id, code, the scopes it supports, and the parameters it needs:

CodeIDScopeParams
bcblock-createapps + namespaces
bublock-updateapps + namespaces
bdblock-deleteapps + namespaces
bitblock-image-typesapps + namespacesimagePatterns (glob)
bitgblock-image-tagsapps + namespacestags
brsblock-replica-scalingapps only
bscblock-storage-changesapps + namespaces
bcsrblock-config-secret-resource-changesapps + namespaces
bwcmblock-workload-config-mount-changesapps + namespaces

Templates are static today (built into the discovery service's template registry). A customer-authored template CRD is in the ideas list — not shipped.

Plan health

Health is computed by reading the cluster, not by trusting the API write. The discovery service lists every Kyverno kyverno.io/v1/Policy labelled with the plan ID, walks each renderedPolicies entry the plan declared, and decides:

  • healthy — every declared policy present, ready, and using the failure action the plan demands.
  • drifted — a declared policy missing, an unexpected policy wearing the plan label, or validationFailureAction no longer matches mode.
  • degraded — declared policy present but not ready (the policy engine has not reconciled it yet).
  • unknown — plan is not yet active.

The health result is persisted back to the ProtectionPlan CRD via a PATCH so the dashboard has a single source of truth. Reconciliation runs in parallel for active plans on every controller tick.

Violations

The violations endpoint walks Kyverno PolicyReport (wgpolicyk8s.io/v1alpha2/policyreports) across every namespace that the plan's scope resolves to, filters to the policy names the plan deployed, and returns:

FieldNotes
policyThe Kyverno policy that fired.
ruleThe rule within the policy.
namespaceThe namespace of the violating resource.
resource.kind / name / namespaceThe resource that triggered the rule.
resultpass | fail | warn | error | skip.
messageThe engine's message.
timestampThe PolicyReport timestamp.

Query params:

  • limit — default 50, max 200, sorted newest first.
  • result — optional filter on one of the result enum values.

Where it lives in the UI

The protection-plan feature in the dashboard (features/plans/protection) renders:

  • A list page with phase quick filters and applied search.
  • A detail page with overview / scope / policies / participants / health / violations sections.
  • A create panel built from five SectionCard blocks: Basic info, Scope, Policies, Schedule, Participants.
  • A small set of per-row actions: edit, duplicate, cancel, reactivate, delete.