auth

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 5, 2026 License: Apache-2.0 Imports: 16 Imported by: 0

Documentation

Overview

Package auth defines core-owned consuming ports for authentication and auth/session event delivery. Implementations of Authenticator and RemoteDecider map policy into github.com/matdev83/go-llm-interactive-proxy/pkg/lipsdk/auth types; EventSink receives non-secret event DTOs. EventDispatcher applies EventFailurePolicy when delivering those events to a sink. Transport (HTTP) and remote clients live outside this package.

Index

Constants

View Source
const LocalUnknownOSPrincipalID = "lip_local_unknown"

LocalUnknownOSPrincipalID is the stable principal id when OS identity cannot be resolved (must match infra osidentity fallback for operator-visible consistency).

View Source
const MinLocalAPIKeyRunes = 16

MinLocalAPIKeyRunes is the minimum accepted length (in Unicode code points) for LocalAPIKeyRecord.Key. Shorter keys are rejected at validation to reduce trivial online guessing when the listener is exposed.

Variables

View Source
var (
	ErrDuplicateLocalAPIKeyID       = errors.New("auth.local_api_keys: duplicate key_id")
	ErrDuplicateLocalAPIKeyMaterial = errors.New("auth.local_api_keys: duplicate key material")
	ErrLocalAPIKeyEmpty             = errors.New("auth.local_api_keys: key is required")
	ErrInvalidLocalAttribution      = errors.New("auth.local_api_keys: invalid attribution")

	// ErrDeniedNoScope is returned by [BuildScope] when the auth decision is not an allow,
	// so denied or challenged requests do not create a successful lifecycle scope.
	ErrDeniedNoScope = errors.New("auth: denied or challenged decision has no lifecycle scope")
	// ErrNoIdentity is returned by [BuildScope] when an allow decision carries no trusted
	// scope, no legacy principal, and no local fallback is permitted.
	ErrNoIdentity = errors.New("auth: no trusted identity or local fallback for scope")
	// ErrUnsafeScope is returned by [BuildScope] when a trusted scope value looks like
	// credential material and is rejected before entering request lifecycle evidence.
	ErrUnsafeScope = errors.New("auth: scope value rejected as unsafe")
)

ErrDuplicateLocalAPIKeyID is returned when two records share the same key_id.

Functions

func BuildSessionStartEvent

func BuildSessionStartEvent(in SessionStartBuildInput) sdkauth.SessionStartEvent

BuildSessionStartEvent maps resolved executor state into a non-secret sdkauth.SessionStartEvent.

func OpaqueRefDigest

func OpaqueRefDigest(s string) string

OpaqueRefDigest returns a short stable hex digest for opaque client hints (same algorithm as runtime.HashOpaqueIDForLog) so session-start events never carry raw client session material.

func SanitizeScope

func SanitizeScope(s scope.PrincipalScopeView) error

SanitizeScope rejects credential-like material in any scope string field or map value before the snapshot enters request lifecycle or audit evidence (requirements 2.6, 5.4). It is the shared safety gate called by BuildScope for accepted decisions and by the HTTP auth bridge for denied/challenged attribution evidence.

The substring heuristic is best-effort defense-in-depth and is not exhaustive; trusted callers remain responsible for never placing raw secret material in scope fields.

func ScopeFromLegacyPrincipal

func ScopeFromLegacyPrincipal(p execview.PrincipalView) scope.PrincipalScopeView

ScopeFromLegacyPrincipal derives an authoritative scope from a legacy principal view without inferring optional org/tenant fields (requirement 3.5). SubjectKind is unknown because the legacy view does not carry subject classification. AuthMethod and CredentialID remain unknown here; callers that have them (auth BuildScope) set them on the returned view. Shared by auth BuildScope and runtime request-scope resolution.

func ValidateLocalAPIKeyRecords

func ValidateLocalAPIKeyRecords(records []LocalAPIKeyRecord) error

ValidateLocalAPIKeyRecords checks records for duplicates, required fields, min key length, and safe attribution (non-empty roles/claim/label keys, no credential-like values).

Types

type Authenticator

type Authenticator interface {
	Authenticate(ctx context.Context, req sdkauth.InboundCallMeta) (sdkauth.Decision, error)
}

Authenticator performs local auth (no-op, API key) using protocol-neutral metadata.

type EventDispatcher

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

EventDispatcher delivers auth and session-start events to an EventSink and applies EventFailurePolicy when the sink returns an error.

Event DTO additions remain subject to non-secret classification; see EventSink and sdkauth.AuthDecisionEvent / sdkauth.SessionStartEvent package docs.

func NewEventDispatcher

func NewEventDispatcher(sink EventSink, policy EventFailurePolicy) *EventDispatcher

NewEventDispatcher constructs a dispatcher. sink may be nil (explicit no delivery).

func (*EventDispatcher) DispatchAuthDecision

func (d *EventDispatcher) DispatchAuthDecision(ctx context.Context, ev sdkauth.AuthDecisionEvent) error

DispatchAuthDecision invokes the sink when non-nil; applies failure policy on sink error. Challenge summary is sanitized before any sink (including custom sinks) for defense in depth.

func (*EventDispatcher) DispatchSessionStart

func (d *EventDispatcher) DispatchSessionStart(ctx context.Context, ev sdkauth.SessionStartEvent) error

DispatchSessionStart invokes the sink when non-nil; applies failure policy on sink error.

type EventFailurePolicy

type EventFailurePolicy string

EventFailurePolicy controls whether event sink errors fail the request path.

const (
	EventFailureBestEffort EventFailurePolicy = "best_effort"
	EventFailureFailClosed EventFailurePolicy = "fail_closed"
)

type EventSink

type EventSink interface {
	OnAuthDecision(ctx context.Context, ev sdkauth.AuthDecisionEvent) error
	OnSessionStart(ctx context.Context, ev sdkauth.SessionStartEvent) error
}

EventSink receives non-secret auth and session events. Implementations are wired at the composition root (e.g. structured logging). EventDispatcher serializes calls per dispatcher instance; sinks should still avoid long blocking work because delivery remains on request paths. OnAuthDecision: do not treat sdkauth.AuthDecisionEvent fields as proof of absence of secrets in upstream state; log only stable, operator-approved attributes (the default JSON sink logs sdkauth.AuthDecisionEvent.PrincipalSafeClaims keys only, not map values). New fields on event DTOs require explicit non-secret data classification before use; EventDispatcher.DispatchAuthDecision sanitizes sdkauth.AuthDecisionEvent.ChallengeSummary for every sink including custom implementations.

type LocalAPIKeyAuthenticator

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

LocalAPIKeyAuthenticator validates bearer API keys against operator-configured records. Records must pass ValidateLocalAPIKeyRecords before construction.

func NewLocalAPIKeyAuthenticator

func NewLocalAPIKeyAuthenticator(records []LocalAPIKeyRecord) (*LocalAPIKeyAuthenticator, error)

NewLocalAPIKeyAuthenticator builds an authenticator from validated key records.

func (*LocalAPIKeyAuthenticator) Authenticate

Authenticate implements Authenticator.

type LocalAPIKeyRecord

type LocalAPIKeyRecord struct {
	KeyID       string
	PrincipalID string
	Key         string
	Attribution LocalAttribution
}

LocalAPIKeyRecord is one operator-configured API key for LocalAPIKeyAuthenticator. It mirrors config-layer YAML records without importing internal/core/config.

type LocalAttribution

type LocalAttribution struct {
	DisplayName    string
	AuthMethod     string
	TenantID       string
	OrganizationID string
	WorkspaceID    string
	ProjectID      string
	DepartmentID   string
	CostCenterID   string
	Roles          []string
	SafeClaims     map[string]string
	PolicyLabels   map[string]string
}

LocalAttribution carries optional operator-controlled safe attribution for a local API key record. Zero values mean "not configured" and map to unknown scope fields (no inference). Raw key material, bearer tokens, and transport headers must never be placed here.

type LocalNoOpAuthenticator

type LocalNoOpAuthenticator struct {
	OS OSIdentityProvider
	// OnOSIdentityFallback, if set, is called when the OS provider is nil or [OSIdentityProvider.Current] fails,
	// before a fallback principal ([LocalUnknownOSPrincipalID]) is used. err is non-nil only when
	// Current was invoked; hadProvider is false when OS is nil.
	OnOSIdentityFallback func(ctx context.Context, err error, hadProvider bool)
}

LocalNoOpAuthenticator grants credential-free access with an explicit non-anonymous principal derived from OSIdentityProvider. It must only be wired when access posture validation permits local no-op.

func (LocalNoOpAuthenticator) Authenticate

Authenticate implements Authenticator.

type OSIdentityProvider

type OSIdentityProvider interface {
	Current(ctx context.Context) (OSIdentitySnapshot, error)
}

OSIdentityProvider resolves the current process identity for local no-op authentication. Implementations live in infrastructure (e.g. os/user + env); core consumes this port only.

type OSIdentitySnapshot

type OSIdentitySnapshot struct {
	PrincipalID  string
	DisplayName  string
	FallbackUsed bool
}

OSIdentitySnapshot is non-secret principal material resolved from the OS or explicit environment hints. FallbackUsed is true when neither OS account nor env hints yielded a stable identity (operator-visible).

type PolicyAuthenticator

type PolicyAuthenticator struct {
	Handler  sdkauth.HandlerKind
	Required sdkauth.RequiredLevel
	Noop     Authenticator
	APIKey   Authenticator
	Remote   RemoteDecider
	// OnRemoteDecideError, if set, is invoked when [RemoteDecider].Decide returns a non-nil error
	// before the policy maps the outcome to deny (err is not returned to the transport). Used for
	// observability at the composition root; [internal/core/auth] does not import logging.
	OnRemoteDecideError func(ctx context.Context, err error)
}

PolicyAuthenticator routes inbound metadata to the configured local handler or RemoteDecider and enforces api_key_sso sequencing (local API key then remote).

func (PolicyAuthenticator) Authenticate

Authenticate implements Authenticator.

type PrincipalSnapshot

type PrincipalSnapshot struct {
	ID          string
	DisplayName string
}

PrincipalSnapshot is a minimal non-secret identity fragment for core-local audit helpers without depending on pkg/lipsdk/execview in call signatures.

func NewPrincipalSnapshot

func NewPrincipalSnapshot(id, displayName string) PrincipalSnapshot

NewPrincipalSnapshot trims stable identity fields for session-start and related audit paths.

type RemoteDecider

type RemoteDecider interface {
	Decide(ctx context.Context, req sdkauth.InboundCallMeta) (sdkauth.Decision, error)
}

RemoteDecider is the consumer-side port for delegated (remote) auth. Implementations are wired at the composition root; this package does not include transport.

type ScopeBuildInput

type ScopeBuildInput struct {
	Decision sdkauth.Decision
}

ScopeBuildInput is the input to BuildScope: a trusted auth decision.

type ScopeBuildResult

type ScopeBuildResult struct {
	Scope     scope.PrincipalScopeView
	Principal execview.PrincipalView
}

ScopeBuildResult is the output of BuildScope: one authoritative scope snapshot and the derived legacy principal projection. The principal is always derived from the scope.

func BuildScope

func BuildScope(input ScopeBuildInput) (ScopeBuildResult, error)

BuildScope normalizes a trusted auth decision into one authoritative principal/scope snapshot plus the derived legacy principal projection.

Precedence (highest first):

  1. Trusted scope on the decision (Decision.Scope) wins; the principal projection is derived from it and any legacy Decision.Principal is ignored for identity.
  2. Legacy principal fallback: when no scope is supplied but the decision carries a non-empty principal id, a scope is derived from it. Unknown optional fields remain unknown (no inference). AuthMethod is derived from SatisfiedLevel and CredentialID from Device.KeyID.

Denied or challenged decisions never produce a successful lifecycle scope. Unsafe credential-like material in trusted scope values is rejected before lifecycle evidence.

type SessionAuditPolicy

type SessionAuditPolicy struct {
	AccessMode    sdkauth.AccessMode
	HandlerKind   sdkauth.HandlerKind
	RequiredLevel sdkauth.RequiredLevel
}

SessionAuditPolicy is a frozen access + auth handler snapshot for operator-visible audit events emitted from the executor (session-start) and should stay aligned with HTTP auth policy snapshots.

type SessionStartBuildInput

type SessionStartBuildInput struct {
	Now                  time.Time
	TraceID              string
	Policy               SessionAuditPolicy
	Frontend             string
	PrincipalID          string
	PrincipalDisplayName string

	AuthoritativeSessionID string
	ClientSessionIDRaw     string
	ALegID                 string
	IsNew                  bool
	// SyntheticLocalPrincipal is true when the composition root supplies a dev-only inferred principal.
	SyntheticLocalPrincipal bool
}

SessionStartBuildInput carries resolved, non-secret session identity inputs for BuildSessionStartEvent.

Jump to

Keyboard shortcuts

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