Skip to content
23 changes: 12 additions & 11 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,18 @@ Godocs on exported library package code (such as `resource`, `operator`, `plugin

### Table of Contents

| Document | Description |
|-------------------------------------------------------|-------------|
| [Application Design](./application-design/README.md) | The typical design patterns of an app built with the SDK |
| [Custom Kinds](./custom-kinds/README.md) | What are kinds, how to write them, and how to use them |
| [Resource Objects](./resource-objects.md) | Describes the function and usage of the `resource.Object` interface |
| [Resource Stores](./resource-stores.md) | Describes the various "Store" types in the `resource` package, and why you may want to use one or another |
| [Operators & Event-Based Design](./operators.md) | A brief primer on what operators/controllers are and working with event-based code |
| [Code Generation](./code-generation.md) | How to use CUE and the CLI for code generation. |
| [Local Dev Environment Setup](./local-development.md) | How to use the CLI to set up a local development & testing environment |
| [Kubernetes Concepts](./kubernetes.md) | A primer on some kubernetes concepts which are relevant to using the SDK backed by a kubernetes API server |
| [Admission Control](./admission-control.md) | How to set up admission control on your kinds for an API server |
| Document | Description |
| ------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------- |
| [Application Design](./application-design/README.md) | The typical design patterns of an app built with the SDK |
| [Custom Kinds](./custom-kinds/README.md) | What are kinds, how to write them, and how to use them |
| [Resource Objects](./resource-objects.md) | Describes the function and usage of the `resource.Object` interface |
| [Resource Stores](./resource-stores.md) | Describes the various "Store" types in the `resource` package, and why you may want to use one or another |
| [Operators & Event-Based Design](./operators.md) | A brief primer on what operators/controllers are and working with event-based code |
| [Code Generation](./code-generation.md) | How to use CUE and the CLI for code generation. |
| [Local Dev Environment Setup](./local-development.md) | How to use the CLI to set up a local development & testing environment |
| [Kubernetes Concepts](./kubernetes.md) | A primer on some kubernetes concepts which are relevant to using the SDK backed by a kubernetes API server |
| [Admission Control](./admission-control.md) | How to set up admission control on your kinds for an API server |
| [Validation Patterns](./architecture/validation-patterns.md) | Convention for reporting actionable runtime validation errors in resource status |

## Base Concepts of the SDK

Expand Down
20 changes: 19 additions & 1 deletion docs/admission-control.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ While an app can do some level of admission control by restricting access to the
the best practice is to implement admission control at the API server level itself. This is done by exposing webhooks from the
multi-tenant operator to validate and/or mutate requests to the API server.

> **Note**: Admission control is used for **static validation** (format, structure, type checks, static business rules). For **runtime validation**
> that depends on external systems or dynamic state, use [`fieldErrors` in status](./architecture/validation-patterns.md) instead.
> See [Validation Patterns](./architecture/validation-patterns.md) for details on when to use each approach.

The `resource` package contains two interfaces used for admission control:
* [ValidatingAdmissionController](https://pkg.go.dev/github.com/grafana/grafana-app-sdk/resource#ValidatingAdmissionController), which is used to _validate_ incoming requests, returning a yes/no on whether the request should be allowed to proceed, and
* [MutatingAdmissionController](https://pkg.go.dev/github.com/grafana/grafana-app-sdk/resource#MutatingAdmissionController), which is used to _alter_ an incoming request, returning am altered object which is translated into series of patch operations which will be made by the API server before proceeding
Expand Down Expand Up @@ -102,4 +106,18 @@ mounted in `/run/secrets/tls`.

For production use, you can either re-use the configs and secrets created by the local environment (they are self-signed, but do not need a real CA as
they are only used for communication between the API server and the webhook server), or generate new ones. Keep in mind that every time you generate
the local environment, the cert bundle is generated (and is unique each time), so don't rely on it being consistent.
the local environment, the cert bundle is generated (and is unique each time), so don't rely on it being consistent.

## Admission Control vs Runtime Validation

Admission control handles **static validation** that can be checked synchronously before a resource is persisted:
- Format validation (URL format, type checks, required fields)
- Structure validation (enum values, data types, JSON structure)
- Static business rules (naming conventions, reserved names)

For **runtime validation** that depends on external systems, internal state, or dynamic conditions, use [`fieldErrors` in status](./architecture/validation-patterns.md):
- External system checks (repository exists, branch exists, installation ID valid)
- Internal runtime state (resource conflicts, service availability)
- Dynamic state that can change over time (credentials expired, external resource deleted)

See [Validation Patterns](./architecture/validation-patterns.md) for the complete convention and implementation guide.
3 changes: 3 additions & 0 deletions docs/architecture/reconciliation.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

This document provides detailed visual representations of the reconciliation code paths in the grafana-app-sdk, tracing the complete flow from application startup through event processing.

> **Related**: When implementing reconciliation logic that performs runtime validation (e.g., checking external systems, validating dynamic state),
> populate `fieldErrors` in the resource status. See [Validation Patterns](./validation-patterns.md) for the recommended convention.

## Overview

The reconciliation system in grafana-app-sdk follows a Kubernetes-inspired operator pattern with two primary flows:
Expand Down
Loading
Loading