package openai import ( "errors" "fmt" "reflect" "iop/apps/edge/internal/authprojection" edgeservice "iop/apps/edge/internal/service" "iop/packages/go/config" "iop/packages/go/singlerequesttemplate" ) var ( errSingleRequestBindingMissingStage = errors.New("single-request binding: missing stage") errSingleRequestBindingDuplicate = errors.New("single-request binding: duplicate stage role") errSingleRequestBindingUnauthorized = errors.New("single-request binding: stage model not authorized for principal") errSingleRequestBindingDynamic = errors.New("single-request binding: stage model dynamically selected") errSingleRequestBindingInconsistent = errors.New("single-request binding: option-inconsistent stage") ) // compileSingleRequestBinding builds the surface-neutral immutable admission // value from an authorized execution preset and its resolved canonical // bindings. It is called only after the preset's selector and every referenced // stage model have been verified through their canonical catalog bindings for // the authenticated principal. // // The function rejects missing, duplicate, unauthorized, dynamically selected, // or option-inconsistent inputs without generic fallback. It keeps the // external model echo equal to the requested public model. func compileSingleRequestBinding( publicModel string, preset config.ExecutionPreset, bindings map[string]routeDispatch, view authprojection.AuthenticatedView, ) (*edgeservice.SingleRequestBinding, error) { if preset.SingleRequest == nil { return nil, nil } sr := preset.SingleRequest // Defense-in-depth: independently re-verify the approved fixed shape at the // admission boundary instead of trusting only the load-time config // validation. A refreshed or crafted preset that no longer matches the frozen // plan→work→review light shape must not compile an immutable admission. if err := validateFixedSingleRequestShape(preset, sr); err != nil { return nil, err } // Build the stage bindings from the preset's approved plan/work/review stage // map, resolved through the canonical bindings authorized for the principal. // Each stage's approved options come from the frozen policy config, never // from dynamic provider dispatch metadata. planBinding, err := resolveStageBinding("plan", sr.Stages.Plan, bindings, view) if err != nil { return nil, fmt.Errorf("single-request plan stage: %w", err) } workBinding, err := resolveStageBinding("work", sr.Stages.Work, bindings, view) if err != nil { return nil, fmt.Errorf("single-request work stage: %w", err) } reviewBinding, err := resolveStageBinding("review", sr.Stages.Review, bindings, view) if err != nil { return nil, fmt.Errorf("single-request review stage: %w", err) } srLimits := sr.Limits limits := edgeservice.SingleRequestLimits{ WallClockMS: srLimits.WallClockMS, StageTimeoutMS: srLimits.StageTimeoutMS, MaxToolIterations: srLimits.MaxToolIterations, MaxOutputBytes: srLimits.MaxOutputBytes, } effectivePlan := sr.Templates.EffectivePlan if effectivePlan == "" { effectivePlan = singlerequesttemplate.DefaultPlanTemplate } effectiveReview := sr.Templates.EffectiveReview if effectiveReview == "" { effectiveReview = singlerequesttemplate.DefaultReviewTemplate } return edgeservice.NewSingleRequestBindingWithTemplates( publicModel, sr.WorkspaceRef, *planBinding, *workBinding, *reviewBinding, limits, edgeservice.SingleRequestTemplateBinding{ Plan: effectivePlan, Review: effectiveReview, }, ) } // validateFixedSingleRequestShape re-verifies the approved immutable // single-request shape at admission time. It independently confirms the // selector, allowed modes, and the single light route match the frozen // plan→work→review policy stages, including high reasoning on plan/review and // no reasoning option on work. Every violation maps to a typed single-request // binding error without generic fallback. func validateFixedSingleRequestShape(preset config.ExecutionPreset, sr *config.ExecutionSingleRequestPolicy) error { // Allowed modes must be exactly ["light"]. if len(preset.AllowedModes) != 1 || preset.AllowedModes[0] != config.ModeLight { return errSingleRequestBindingInconsistent } // The fused selector must exactly match the fixed plan stage (model and // options); the selector cannot diverge from the frozen plan binding. if preset.Selector.Model != sr.Stages.Plan.Model || !singleRequestOptionsEqual(preset.Selector.Options, sr.Stages.Plan.Options) { return errSingleRequestBindingInconsistent } // Plan and review must declare high reasoning; work must not declare it. if singleRequestReasoningEffort(sr.Stages.Plan.Options) != config.SingleRequestReasoningEffortHigh { return errSingleRequestBindingInconsistent } if singleRequestReasoningEffort(sr.Stages.Review.Options) != config.SingleRequestReasoningEffortHigh { return errSingleRequestBindingInconsistent } if _, present := sr.Stages.Work.Options["reasoning_effort"]; present { return errSingleRequestBindingInconsistent } // Exactly one light route with ordered, unique plan→work→review roles whose // model and options exactly match the frozen policy stages. if len(preset.Routes) != 1 { return errSingleRequestBindingInconsistent } route, ok := preset.Routes[config.ModeLight] if !ok { return errSingleRequestBindingMissingStage } expected := []struct { role string stage config.ExecutionSingleRequestStageConfig }{ {"plan", sr.Stages.Plan}, {"work", sr.Stages.Work}, {"review", sr.Stages.Review}, } if len(route.Stages) != len(expected) { return errSingleRequestBindingMissingStage } seenRoles := make(map[string]struct{}, len(route.Stages)) for _, stage := range route.Stages { if _, dup := seenRoles[stage.Role]; dup { return errSingleRequestBindingDuplicate } seenRoles[stage.Role] = struct{}{} } for i, want := range expected { st := route.Stages[i] if st.Role != want.role { return errSingleRequestBindingInconsistent } if st.Model != want.stage.Model { // The route would dynamically select a downstream model other than // the frozen policy stage model. return errSingleRequestBindingDynamic } if !singleRequestOptionsEqual(st.Options, want.stage.Options) { return errSingleRequestBindingInconsistent } } return nil } // resolveStageBinding maps a frozen stage config to its authorized routeDispatch // binding and copies the approved stage options and managed route facts into a // service DTO. It verifies that the binding is present, managed, // principal-consistent, and names exactly the canonical model the frozen stage // declares. The returned dispatch binding carries only secret-free managed // route facts for provider-pool dispatch. func resolveStageBinding(role string, stage config.ExecutionSingleRequestStageConfig, bindings map[string]routeDispatch, view authprojection.AuthenticatedView) (*edgeservice.SingleRequestStageBinding, error) { canonicalModel := stage.Model dispatch, ok := bindings[canonicalModel] if !ok { return nil, errSingleRequestBindingMissingStage } // The binding must come from a managed principal resolution. Unmanaged // legacy routes cannot back a single-request admission. if !dispatch.Managed { return nil, errSingleRequestBindingUnauthorized } // Verify the binding's model group matches the canonical reference. if dispatch.ModelGroupKey != canonicalModel { return nil, errSingleRequestBindingInconsistent } // Verify the binding's principal matches the authenticated view. if dispatch.PrincipalRef != view.Principal.PrincipalRef { return nil, errSingleRequestBindingUnauthorized } // Copy the approved stage-level options from the frozen policy stage config, // not from dynamic provider dispatch metadata. NewSingleRequestBinding takes // a defensive deep copy, so a later config refresh cannot mutate an admitted // binding through this reference. return &edgeservice.SingleRequestStageBinding{ Model: canonicalModel, Options: stage.Options, Dispatch: managedRouteDispatchSnapshot(&dispatch), }, nil } // managedRouteDispatchSnapshot extracts the secret-free managed route facts from // a resolved routeDispatch into a SingleRequestStageDispatchBinding. The // returned value is a fresh allocation independent of the source; the caller // may mutate the original without affecting the snapshot. func managedRouteDispatchSnapshot(d *routeDispatch) *edgeservice.SingleRequestStageDispatchBinding { if d == nil || !d.Managed { return nil } return &edgeservice.SingleRequestStageDispatchBinding{ Managed: d.Managed, ModelGroupKey: d.ModelGroupKey, RouteID: d.RouteID, ProfileID: d.ProfileID, CredentialSlotRef: d.CredentialSlotRef, CredentialRevision: d.CredentialRevision, RouteRevision: d.RouteRevision, PrincipalRef: d.PrincipalRef, ProjectionGeneration: d.ProjectionGeneration, ProviderID: d.ProviderID, UpstreamModel: d.UpstreamModel, TimeoutSec: d.TimeoutSec, MaxQueue: d.MaxQueue, QueueTimeoutMS: d.QueueTimeoutMS, CandidatePredicate: d.ManagedPredicate, } } // compileSingleRequestBindingForUnmanaged builds the service binding from an // unmanaged (legacy) preset resolution. It rejects the compilation because // single-request admission requires managed principal authorization. func compileSingleRequestBindingForUnmanaged(publicModel string, preset config.ExecutionPreset) (*edgeservice.SingleRequestBinding, error) { if preset.SingleRequest == nil { return nil, nil } // Unmanaged presets cannot back a single-request admission because there // is no authenticated principal to verify stage authorization against. return nil, errSingleRequestBindingUnauthorized } // singleRequestOptionsEqual reports whether two option maps are equal, treating // nil and empty maps as equal. func singleRequestOptionsEqual(a, b map[string]any) bool { if len(a) == 0 && len(b) == 0 { return true } return reflect.DeepEqual(a, b) } // singleRequestReasoningEffort extracts the reasoning_effort option value from a // stage's options map, returning "" when absent or non-string. func singleRequestReasoningEffort(opts map[string]any) string { if opts == nil { return "" } v, ok := opts["reasoning_effort"] if !ok { return "" } s, ok := v.(string) if !ok { return "" } return s }