protocol

package
v1.12.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

Documentation

Overview

Package protocol implements the admin-scoped `governance.*` tenant-default override Protocol methods the Console control plane consumes:

  • governance.set_tenant_overrides — set (or clear) a tenant's default LLM parameters (model / additive extra-instructions / temperature / max-tokens / reasoning-effort) live, with no redeploy.
  • governance.get_tenant_overrides — read the current tenant default.

Both methods are admin-scoped (the `auth.ScopeAdmin` claim, enforced at the wire handler) and identity-mandatory. The override is a tenant-wide desired-state record applied to every session in the tenant on its NEXT run — never mid-flight (the run loop snapshots it at run start).

The seam (CLAUDE.md §4.4)

The Service depends on a narrow `TenantOverrideStore` interface — the `*governance.TenantOverridePolicy` concrete satisfies it, and tests inject a fake. The Service owns wire validation + the wire↔policy spec mapping; the policy owns persistence + audit.

Identity is mandatory (CLAUDE.md §6 rule 9)

Every method takes the wire request's `IdentityScope`. An incomplete triple fails closed with `ErrIdentityRequired`. The tenant whose defaults are set/read is the caller's verified tenant — the handler overlays the verified identity, so a caller cannot target another tenant's defaults through this surface (single-tenant V1; a cross-tenant admin path is a future extension, mirroring the posture surface).

Concurrent reuse

A constructed *Service is immutable after NewService and safe to share across N goroutines: it holds only the store reference + a clock + logger. Per-call state lives in arguments and locals.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrIdentityRequired — the request carried an incomplete identity
	// triple. RFC §5.5 / CLAUDE.md §6 rule 9 — fails closed.
	ErrIdentityRequired = errors.New("governance/protocol: identity scope incomplete")
	// ErrMisconfigured — NewService was called with a nil store.
	ErrMisconfigured = errors.New("governance/protocol: NewService missing a mandatory dependency")
)

Sentinel errors the Service returns. The wire handler maps each onto a canonical Protocol Code + HTTP status; in-process callers compare with errors.Is.

View Source
var ErrKeyRotateMisconfigured = errors.New("governance/protocol: NewKeyRotateService missing a mandatory dependency")

ErrKeyRotateMisconfigured — NewKeyRotateService was called with a nil rotator.

Functions

This section is empty.

Types

type Clock

type Clock func() time.Time

Clock is the time source the Service stamps AppliedAt from.

type KeyRotateOption

type KeyRotateOption func(*KeyRotateService)

KeyRotateOption configures NewKeyRotateService.

func WithKeyRotateBus

func WithKeyRotateBus(b events.EventBus) KeyRotateOption

WithKeyRotateBus wires the events.EventBus the `governance.key_rotated` audit event publishes onto. A nil bus logs the rotation at Info instead (never fully silent — CLAUDE.md §13).

func WithKeyRotateClock

func WithKeyRotateClock(c Clock) KeyRotateOption

WithKeyRotateClock injects the time source. Defaults to time.Now.

func WithKeyRotateLogger

func WithKeyRotateLogger(l *slog.Logger) KeyRotateOption

WithKeyRotateLogger sets the slog.Logger. A nil logger routes to slog.Default().

func WithKeyRotateRedactor

func WithKeyRotateRedactor(r audit.Redactor) KeyRotateOption

WithKeyRotateRedactor wires the audit.Redactor the secret-free payload runs through before the emit (defence-in-depth — the payload carries no secret by construction, but the redactor pass is mandatory per §7 rule 6).

type KeyRotateService

type KeyRotateService struct {
	// contains filtered or unexported fields
}

KeyRotateService implements the admin-scoped `governance.rotate_key` method. It validates identity, drives the rotator, and emits the secret-free `governance.key_rotated` audit event. The KEY VALUE is handled only on the request leg + inside the rotator's holder — it never touches a log, the audit payload, or the response (CLAUDE.md §7).

Concurrent reuse: immutable after construction; per-call state lives in arguments + locals. The rotator's holder is internally synchronised.

func NewKeyRotateService

func NewKeyRotateService(rotator KeyRotator, opts ...KeyRotateOption) (*KeyRotateService, error)

NewKeyRotateService builds the rotate-key service over a KeyRotator. rotator is mandatory — a nil fails loud with ErrKeyRotateMisconfigured.

The returned *KeyRotateService is immutable after construction and safe for concurrent use by N goroutines.

func (*KeyRotateService) RotateKey

RotateKey validates identity, rotates the provider key via the rotator, emits the secret-free audit event, and returns the provider + fingerprint + rotation timestamp. The new key never appears in the response, the audit event, or any log line.

type KeyRotator

type KeyRotator interface {
	RotateKey(provider, newKey string) (resolvedProvider, fingerprint string, err error)
}

KeyRotator is the narrow seam the KeyRotateService drives — the `*llm.ProviderKeyRotator` concrete satisfies it. The implementation validates the provider + key and swaps the atomic key holder; it returns the resolved provider + a NON-REVERSIBLE fingerprint of the new key, never the key itself.

type Option

type Option func(*Service)

Option configures NewService.

func WithClock

func WithClock(c Clock) Option

WithClock injects the time source. Defaults to time.Now.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the slog.Logger. A nil logger routes to slog.Default().

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service implements the admin-scoped governance tenant-override methods.

func NewService

func NewService(store TenantOverrideStore, opts ...Option) (*Service, error)

NewService builds the governance tenant-override Service over a TenantOverrideStore. store is mandatory — a nil fails loud with ErrMisconfigured rather than building a Service that would nil-panic on the first request (CLAUDE.md §5).

The returned *Service is immutable after construction and safe for concurrent use by N goroutines.

func (*Service) GetTenantOverrides

GetTenantOverrides validates identity and returns the caller tenant's current default-override record.

func (*Service) SetTenantOverrides

SetTenantOverrides validates identity, maps the wire override into the governance spec, persists it via the store, and returns the apply instant. The tenant whose defaults are set is the caller's verified tenant. Validation failures (unknown model, out-of-range value) surface from the policy and map onto CodeInvalidRequest at the wire edge.

type TenantOverrideStore

type TenantOverrideStore interface {
	// Set replaces tenant's default-override record with spec (desired-
	// state replace). actor is the admin caller (the audit anchor).
	Set(ctx context.Context, actor identity.Quadruple, tenant string, spec governance.TenantOverrideSpec) error
	// Get returns the tenant's current default-override spec and whether
	// a record exists.
	Get(ctx context.Context, tenant string) (governance.TenantOverrideSpec, bool, error)
}

TenantOverrideStore is the narrow seam the Service drives. The `*governance.TenantOverridePolicy` concrete satisfies it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL