routing

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

PolicyAllows answers "is this Model reachable through this Policy?" without picking a binding or a key — the question /v1/models needs to answer. Mirrors the allowed-paths logic in Resolve so the two stay in sync. Resolve is binding-aware (legacy + DSL + wildcard match against specific (provider, model, host) triples); PolicyAllows reduces to "is there *any* binding under this policy that would be allowed?"

Package routing resolves an inbound inference request to a fully-typed RequestPlan that the pipeline can consume. All catalog lookups happen here, against the in-memory snapshot. The pipeline itself is ignorant of the snapshot.

Resolution flow:

  1. Model: caller supplies a snapshot name (from the request body's `model` field); look it up via snapshot.SnapshotByName. The owning Model + the picked Snapshot are carried into the Plan.
  2. Policy: comes from the authenticated RelayKey's PolicyID. (No "default route" indirection in the new arch — RelayKey → Policy is direct. Anonymous traffic is served by a separate package.)
  3. Authorization: model must be allowed by the Policy. Allowed if its id is in Spec.ModelIDs, OR Spec.Models (modelref DSL) matches, OR — when both grant fields are empty — the policy is an implicit wildcard: any model reachable via its hostkeys is allowed. The hostkey-coverage check below is the real gate in that case.
  4. HostBinding: pick one of the model's HostBindings (snapshot. BindingsForModel) the operator has configured. v1 picks the first enabled binding; multi-host failover is a future feature.
  5. Host: lookup by binding.Spec.HostID for BaseURL.
  6. Keys: Policy.Spec.HostKeyIDs filtered to those whose Owner.ID is the chosen Host (a key authenticates against one host).
  7. RateLimit: Policy.Spec.RateLimitID, resolved to []pkgratelimit.Rule.

Each lookup is a snapshot.Get — no PG, no I/O. Resolve() is allocation- conscious where it matters but not micro-optimised; the hot-path budget dominates this.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrModelNotFound    = errors.New("routing: model not found")
	ErrModelDisabled    = errors.New("routing: model disabled")
	ErrPolicyNotFound   = errors.New("routing: policy not found")
	ErrPolicyDisabled   = errors.New("routing: policy disabled")
	ErrModelNotInPolicy = errors.New("routing: model not allowed by policy")
	ErrNoHostBinding    = errors.New("routing: no enabled host binding for model")
	ErrHostNotFound     = errors.New("routing: host not found")
	ErrNoKeys           = errors.New("routing: no host keys available for this host")

	// ErrPolicyless is returned when a RelayKey has no PolicyID and the
	// inference settings forbid policy-less traffic.
	ErrPolicyless = errors.New("routing: relay key has no policy and policy-less traffic is disabled")
)

Errors returned by Resolve. Each maps to a distinct HTTP status in the handler; routing keeps them as typed sentinels so handlers can errors.Is() rather than parse strings.

Functions

func PolicyAllows

func PolicyAllows(snap *appcatalog.Snapshot, pol *policy.Policy, m *model.Model) bool

PolicyAllows reports whether m is reachable through pol given snap's hostkey coverage. Used to enumerate accessible models for inventory endpoints. Single-shot; not optimised for tight loops.

Types

type Plan

type Plan struct {
	Model       *model.Model
	Snapshot    *model.Snapshot
	Policy      *policy.Policy
	HostBinding *binding.Binding
	Host        *host.Host
	Provider    string
	Keys        []*hostkey.HostKey

	// PayloadLoggingEnabled is the resolved opt-in for full request/response
	// body capture: true when the matched Policy or the inbound RelayKey
	// sets PayloadLoggingEnabled. Read by the inference entry to flag the
	// lifecycle Context so the payloadlog observer captures bodies.
	PayloadLoggingEnabled bool
}

Plan is the fully-resolved input the pipeline consumes. The handler converts this to pipeline.Request, dropping fields the pipeline doesn't need.

Snapshot is the resolved checkpoint. The handler rewrites the request body's `model` field to Snapshot.Upstream() before invoking the adapter.

type Request

type Request struct {
	// ModelName is the slug or upstream-name reference the caller asked
	// for (typically from the body's "model" field).
	ModelName string

	// RelayKey is the authenticated key (already validated for auth).
	// Its Spec.PolicyID drives policy selection.
	RelayKey *relaykey.RelayKey

	// SkipKeyCheck, when true, suppresses the Policy.HostKeyIDs → host
	// coverage gate. Used by proxy mode: the caller brings their own
	// upstream credentials, so the relay's keypool is irrelevant — only
	// the (model, binding, host) tuple matters. Plan.Keys is nil in
	// this mode.
	SkipKeyCheck bool
}

Request carries the inbound resolution inputs.

type Resolver

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

Resolver wraps a Catalog snapshot accessor and answers Resolve calls.

func New

func New(cat *appcatalog.Catalog) *Resolver

New constructs a Resolver against the live catalog. The Resolver reads cat.Current() on every Resolve — picking up the latest snapshot after any NOTIFY-driven reload.

func (*Resolver) Resolve

func (r *Resolver) Resolve(req Request) (*Plan, error)

Resolve maps the inbound request to a Plan. Errors are typed; handlers pick the appropriate HTTP status.

Jump to

Keyboard shortcuts

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