// Package sessionlimit defines the domain decision shape used for active // device-session limit evaluation. package sessionlimit import ( "errors" "fmt" ) // Kind identifies the coarse outcome of evaluating the active-session limit. type Kind string const ( // KindDisabled reports that no configured limit is currently active. KindDisabled Kind = "disabled" // KindAllowed reports that creating the next session is allowed. KindAllowed Kind = "allowed" // KindExceeded reports that creating the next session would exceed the // configured limit. KindExceeded Kind = "exceeded" ) // IsKnown reports whether Kind is one of the session-limit outcomes supported // by the current domain model. func (k Kind) IsKnown() bool { switch k { case KindDisabled, KindAllowed, KindExceeded: return true default: return false } } // Decision stores the result of evaluating one possible next session creation. type Decision struct { // Kind reports the coarse decision outcome. Kind Kind // ConfiguredLimit stores the active configured limit when one exists. ConfiguredLimit *int // ActiveSessionCount stores the current active-session count before create. ActiveSessionCount int // NextSessionCount stores the count that would exist after creating the next // session. NextSessionCount int } // Validate reports whether Decision satisfies the Stage-2 structural // invariants. func (d Decision) Validate() error { if !d.Kind.IsKnown() { return fmt.Errorf("session-limit decision kind %q is unsupported", d.Kind) } if d.ActiveSessionCount < 0 { return errors.New("session-limit active session count must not be negative") } if d.NextSessionCount < 0 { return errors.New("session-limit next session count must not be negative") } if d.NextSessionCount != d.ActiveSessionCount+1 { return errors.New("session-limit next session count must equal active session count plus one") } switch d.Kind { case KindDisabled: if d.ConfiguredLimit != nil { return errors.New("disabled session-limit decision must not contain configured limit") } case KindAllowed, KindExceeded: if d.ConfiguredLimit == nil { return errors.New("limited session-limit decision must contain configured limit") } if *d.ConfiguredLimit <= 0 { return errors.New("session-limit configured limit must be positive") } if d.Kind == KindAllowed && d.NextSessionCount > *d.ConfiguredLimit { return errors.New("allowed session-limit decision must not exceed configured limit") } if d.Kind == KindExceeded && d.NextSessionCount <= *d.ConfiguredLimit { return errors.New("exceeded session-limit decision must be above configured limit") } } return nil }