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
- Variables
- func BuildSessionStartEvent(in SessionStartBuildInput) sdkauth.SessionStartEvent
- func OpaqueRefDigest(s string) string
- func SanitizeScope(s scope.PrincipalScopeView) error
- func ScopeFromLegacyPrincipal(p execview.PrincipalView) scope.PrincipalScopeView
- func ValidateLocalAPIKeyRecords(records []LocalAPIKeyRecord) error
- type Authenticator
- type EventDispatcher
- type EventFailurePolicy
- type EventSink
- type LocalAPIKeyAuthenticator
- type LocalAPIKeyRecord
- type LocalAttribution
- type LocalNoOpAuthenticator
- type OSIdentityProvider
- type OSIdentitySnapshot
- type PolicyAuthenticator
- type PrincipalSnapshot
- type RemoteDecider
- type ScopeBuildInput
- type ScopeBuildResult
- type SessionAuditPolicy
- type SessionStartBuildInput
Constants ¶
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).
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 ¶
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 ¶
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 ¶
func (a *LocalAPIKeyAuthenticator) Authenticate(ctx context.Context, req sdkauth.InboundCallMeta) (sdkauth.Decision, error)
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 ¶
func (a LocalNoOpAuthenticator) Authenticate(ctx context.Context, req sdkauth.InboundCallMeta) (sdkauth.Decision, error)
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 ¶
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 ¶
func (a PolicyAuthenticator) Authenticate(ctx context.Context, req sdkauth.InboundCallMeta) (sdkauth.Decision, error)
Authenticate implements Authenticator.
type PrincipalSnapshot ¶
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 ¶
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):
- Trusted scope on the decision (Decision.Scope) wins; the principal projection is derived from it and any legacy Decision.Principal is ignored for identity.
- 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.