diff --git a/broker/Dockerfile.dockerignore b/broker/Dockerfile.dockerignore index d9d90900..7b7e2711 100644 --- a/broker/Dockerfile.dockerignore +++ b/broker/Dockerfile.dockerignore @@ -17,3 +17,6 @@ broker/**/*_test.go # Include migrations !broker/migrations/** + +# Include statemodels +!broker/patron_request/service/statemodels diff --git a/broker/app/app.go b/broker/app/app.go index 43c47fe9..1c7ca8bd 100644 --- a/broker/app/app.go +++ b/broker/app/app.go @@ -166,7 +166,7 @@ func Init(ctx context.Context) (Context, error) { sseBroker := api.NewSseBroker(appCtx, common.NewTenant(TENANT_TO_SYMBOL)) - AddDefaultHandlers(eventBus, iso18626Client, supplierLocator, workflowManager, iso18626Handler, prActionService, prApiHandler, sseBroker) + AddDefaultHandlers(eventBus, iso18626Client, supplierLocator, workflowManager, iso18626Handler, *prActionService, prApiHandler, sseBroker) err = StartEventBus(ctx, eventBus) if err != nil { return Context{}, err diff --git a/broker/oapi/open-api.yaml b/broker/oapi/open-api.yaml index e1f74b88..c43d0fce 100644 --- a/broker/oapi/open-api.yaml +++ b/broker/oapi/open-api.yaml @@ -538,6 +538,106 @@ components: - event - data + StateModel: + type: object + description: ReShare state model definition + additionalProperties: false + properties: + type: + type: string + description: Self-referential type + name: + type: string + description: Name of the state model + desc: + type: string + description: Description of the state model + version: + type: string + description: Version of the state model in SemVer + states: + type: array + description: A list of all allowed states + items: + $ref: '#/components/schemas/ModelState' + + ModelState: + title: State + type: object + description: Definition of a particular state + properties: + name: + type: string + description: Name of the state, in capital letters with underscores + display: + type: string + description: Human-readable state name + desc: + type: string + description: Description of the state, e.g., what situation is modelled by the state + side: + type: string + description: Indicates which side of the request the state belongs to + enum: + - REQUESTER + - SUPPLIER + actions: + type: array + description: List of all actions that may be performed on the request when in this state + items: + $ref: '#/components/schemas/ModelAction' + events: + type: array + description: List of all events that may be triggered to the request when in this state + items: + $ref: '#/components/schemas/ModelEvent' + terminal: + type: boolean + description: Indicates if the state is terminal (meaning no actions or events are allowed in this state) + oneOf: + - anyOf: + - required: + - actions + - required: + - events + - required: + - terminal + required: + - name + - side + + ModelAction: + type: object + title: Action + additionalProperties: false + properties: + name: + type: string + description: Description of the action + transitions: + type: array + description: List of all possible state transitions after performing the action. When no transitions are defined, the action is considered to be non-state-changing + items: + type: string + required: + - name + + ModelEvent: + type: object + title: Event + additionalProperties: false + properties: + name: + type: string + description: Description of the event + transitions: + type: array + description: List of all possible state transitions after performing the event. When no transitions are defined, the event is considered to be non-state-changing + items: + type: string + required: + - name + paths: /: get: @@ -1084,3 +1184,30 @@ paths: application/json: schema: $ref: '#/components/schemas/SseResult' + + /state_model/models/{model}: + get: + summary: Retrieve a state model by name + tags: + - patron-requests-api + parameters: + - in: path + name: model + schema: + type: string + required: true + description: The name of the statemodel to retrieve + - $ref: '#/components/parameters/Tenant' + responses: + '200': + description: Successful retrieval of state model + content: + application/json: + schema: + $ref: '#/components/schemas/StateModel' + '500': + description: Internal Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/Error' diff --git a/broker/patron_request/api/api-handler.go b/broker/patron_request/api/api-handler.go index aa638b00..a4131499 100644 --- a/broker/patron_request/api/api-handler.go +++ b/broker/patron_request/api/api-handler.go @@ -43,6 +43,16 @@ func NewPrApiHandler(prRepo pr_db.PrRepo, eventBus events.EventBus, tenant commo } } +func (a *PatronRequestApiHandler) GetStateModelModelsModel(w http.ResponseWriter, r *http.Request, model string, params proapi.GetStateModelModelsModelParams) { + stateModel := a.actionMappingService.SMService.GetStateModel(model) + + if stateModel == nil { + addNotFoundError(w) + return + } + writeJsonResponse(w, *stateModel) +} + func (a *PatronRequestApiHandler) GetPatronRequests(w http.ResponseWriter, r *http.Request, params proapi.GetPatronRequestsParams) { symbol, err := api.GetSymbolForRequest(r, a.tenant, params.XOkapiTenant, params.Symbol) logParams := map[string]string{"method": "GetPatronRequests", "side": params.Side, "symbol": symbol} diff --git a/broker/patron_request/service/action.go b/broker/patron_request/service/action.go index e4c918e4..60100cfc 100644 --- a/broker/patron_request/service/action.go +++ b/broker/patron_request/service/action.go @@ -77,8 +77,8 @@ type PatronRequestActionService struct { actionMappingService ActionMappingService } -func CreatePatronRequestActionService(prRepo pr_db.PrRepo, eventBus events.EventBus, iso18626Handler handler.Iso18626HandlerInterface, lmsCreator lms.LmsCreator) PatronRequestActionService { - return PatronRequestActionService{ +func CreatePatronRequestActionService(prRepo pr_db.PrRepo, eventBus events.EventBus, iso18626Handler handler.Iso18626HandlerInterface, lmsCreator lms.LmsCreator) *PatronRequestActionService { + return &PatronRequestActionService{ prRepo: prRepo, eventBus: eventBus, iso18626Handler: iso18626Handler, diff --git a/broker/patron_request/service/action_mapping.go b/broker/patron_request/service/action_mapping.go index 548db4e5..115d7226 100644 --- a/broker/patron_request/service/action_mapping.go +++ b/broker/patron_request/service/action_mapping.go @@ -1,64 +1,87 @@ package prservice import ( - pr_db "github.com/indexdata/crosslink/broker/patron_request/db" "slices" + + pr_db "github.com/indexdata/crosslink/broker/patron_request/db" + "github.com/indexdata/crosslink/broker/patron_request/proapi" ) -type ActionMapping interface { - IsActionAvailable(pr pr_db.PatronRequest, action pr_db.PatronRequestAction) bool - GetActionsForPatronRequest(pr pr_db.PatronRequest) []pr_db.PatronRequestAction +type ActionMappingService struct { + SMService StateModelService } -var returnableBorrowerStateActionMapping = map[pr_db.PatronRequestState][]pr_db.PatronRequestAction{ - BorrowerStateNew: {BorrowerActionValidate}, - BorrowerStateValidated: {BorrowerActionSendRequest}, - BorrowerStateSupplierLocated: {BorrowerActionCancelRequest}, - BorrowerStateConditionPending: {BorrowerActionAcceptCondition, BorrowerActionRejectCondition}, - BorrowerStateWillSupply: {BorrowerActionCancelRequest}, - BorrowerStateShipped: {BorrowerActionReceive}, - BorrowerStateReceived: {BorrowerActionCheckOut}, - BorrowerStateCheckedOut: {BorrowerActionCheckIn}, - BorrowerStateCheckedIn: {BorrowerActionShipReturn}, +func (r *ActionMappingService) NewActionMappingService() *ActionMappingService { + return &ActionMappingService{ + SMService: StateModelService{}, + } } -var returnableLenderStateActionMapping = map[pr_db.PatronRequestState][]pr_db.PatronRequestAction{ - LenderStateNew: {LenderActionValidate}, - LenderStateValidated: {LenderActionWillSupply, LenderActionCannotSupply, LenderActionAddCondition}, - LenderStateWillSupply: {LenderActionAddCondition, LenderActionCannotSupply, LenderActionShip}, - LenderStateConditionPending: {LenderActionCannotSupply}, - LenderStateConditionAccepted: {LenderActionShip, LenderActionCannotSupply}, - LenderStateShippedReturn: {LenderActionMarkReceived}, - LenderStateCancelRequested: {LenderActionMarkCancelled, LenderActionWillSupply}, + +func (r *ActionMappingService) GetActionMapping(pr pr_db.PatronRequest) *ActionMapping { + //TODO: check the PatronRequest loan type to decide what kind of state model/mapping to return + return NewActionMapping(r.SMService.GetStateModel("returnables")) } -type ActionMappingService struct { +type ActionMapping struct { + borrowerStateActionMapping map[pr_db.PatronRequestState][]pr_db.PatronRequestAction + lenderStateActionMapping map[pr_db.PatronRequestState][]pr_db.PatronRequestAction +} + +// Constructor function to initialize the mappings for given StateModel +func NewActionMapping(stateModel *proapi.StateModel) *ActionMapping { + r := new(ActionMapping) + + borrowerMap := make(map[pr_db.PatronRequestState][]pr_db.PatronRequestAction) + lenderMap := make(map[pr_db.PatronRequestState][]pr_db.PatronRequestAction) + + for _, state := range *stateModel.States { + if state.Actions != nil { + nameList := make([]pr_db.PatronRequestAction, 0) + for _, action := range *state.Actions { + nameList = append(nameList, pr_db.PatronRequestAction(action.Name)) + } + if state.Side == proapi.REQUESTER { + borrowerMap[pr_db.PatronRequestState(state.Name)] = nameList + } else { + lenderMap[pr_db.PatronRequestState(state.Name)] = nameList + } + } + } + + r.borrowerStateActionMapping = borrowerMap + r.lenderStateActionMapping = lenderMap + + return r } -func (r *ActionMappingService) GetActionMapping(pr pr_db.PatronRequest) ActionMapping { - return new(ReturnableActionMapping) +func (r *ActionMapping) GetBorrowerActionsMap() map[pr_db.PatronRequestState][]pr_db.PatronRequestAction { + return r.borrowerStateActionMapping } -type ReturnableActionMapping struct { +func (r *ActionMapping) GetLenderActionsMap() map[pr_db.PatronRequestState][]pr_db.PatronRequestAction { + return r.lenderStateActionMapping } -func (r *ReturnableActionMapping) IsActionAvailable(pr pr_db.PatronRequest, action pr_db.PatronRequestAction) bool { +func (r *ActionMapping) IsActionAvailable(pr pr_db.PatronRequest, action pr_db.PatronRequestAction) bool { if pr.Side == SideBorrowing { - return isActionAvailable(pr.State, action, returnableBorrowerStateActionMapping) + return isActionAvailable(pr.State, action, r.borrowerStateActionMapping) } else { - return isActionAvailable(pr.State, action, returnableLenderStateActionMapping) + return isActionAvailable(pr.State, action, r.lenderStateActionMapping) } } -func (r *ReturnableActionMapping) GetActionsForPatronRequest(pr pr_db.PatronRequest) []pr_db.PatronRequestAction { + +func (r *ActionMapping) GetActionsForPatronRequest(pr pr_db.PatronRequest) []pr_db.PatronRequestAction { if pr.Side == SideBorrowing { - return getActionsByStateFromMapping(pr.State, returnableBorrowerStateActionMapping) + return getActionsByStateFromMapping(pr.State, r.borrowerStateActionMapping) } else { - return getActionsByStateFromMapping(pr.State, returnableLenderStateActionMapping) + return getActionsByStateFromMapping(pr.State, r.lenderStateActionMapping) } } func isActionAvailable(state pr_db.PatronRequestState, action pr_db.PatronRequestAction, actionMapping map[pr_db.PatronRequestState][]pr_db.PatronRequestAction) bool { return slices.Contains(getActionsByStateFromMapping(state, actionMapping), action) } + func getActionsByStateFromMapping(state pr_db.PatronRequestState, actionMapping map[pr_db.PatronRequestState][]pr_db.PatronRequestAction) []pr_db.PatronRequestAction { if actions, ok := actionMapping[state]; ok { return actions diff --git a/broker/patron_request/service/action_mapping_test.go b/broker/patron_request/service/action_mapping_test.go index 838bfe32..2e42dd82 100644 --- a/broker/patron_request/service/action_mapping_test.go +++ b/broker/patron_request/service/action_mapping_test.go @@ -1,11 +1,47 @@ package prservice import ( + "slices" + "testing" + pr_db "github.com/indexdata/crosslink/broker/patron_request/db" "github.com/stretchr/testify/assert" - "testing" ) +func TestNewReturnableActionMapping(t *testing.T) { + borrowerStateActionMapping := map[pr_db.PatronRequestState][]pr_db.PatronRequestAction{ + BorrowerStateNew: {BorrowerActionValidate}, + BorrowerStateValidated: {BorrowerActionSendRequest}, + BorrowerStateSupplierLocated: {BorrowerActionCancelRequest}, + BorrowerStateConditionPending: {BorrowerActionAcceptCondition, BorrowerActionRejectCondition}, + BorrowerStateWillSupply: {BorrowerActionCancelRequest}, + BorrowerStateShipped: {BorrowerActionReceive}, + BorrowerStateReceived: {BorrowerActionCheckOut}, + BorrowerStateCheckedOut: {BorrowerActionCheckIn}, + BorrowerStateCheckedIn: {BorrowerActionShipReturn}, + } + + lenderStateActionMapping := map[pr_db.PatronRequestState][]pr_db.PatronRequestAction{ + LenderStateNew: {LenderActionValidate}, + LenderStateValidated: {LenderActionWillSupply, LenderActionCannotSupply, LenderActionAddCondition}, + LenderStateWillSupply: {LenderActionAddCondition, LenderActionCannotSupply, LenderActionShip}, + LenderStateConditionPending: {LenderActionCannotSupply}, + LenderStateConditionAccepted: {LenderActionShip, LenderActionCannotSupply}, + LenderStateShippedReturn: {LenderActionMarkReceived}, + LenderStateCancelRequested: {LenderActionMarkCancelled, LenderActionWillSupply}, + } + + stateModel, err := LoadStateModelByName("returnables") + assert.Nil(t, err) + returnableActionMapping := NewActionMapping(stateModel) + + assert.NotNil(t, returnableActionMapping) + + mapCompare(t, returnableActionMapping.borrowerStateActionMapping, borrowerStateActionMapping) + + mapCompare(t, returnableActionMapping.lenderStateActionMapping, lenderStateActionMapping) +} + var actionMappingService = ActionMappingService{} func TestIsActionAvailable(t *testing.T) { @@ -20,10 +56,28 @@ func TestIsActionAvailable(t *testing.T) { func TestGetActionsForPatronRequest(t *testing.T) { // Borrower - assert.Equal(t, []pr_db.PatronRequestAction{BorrowerActionValidate}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideBorrowing, State: BorrowerStateNew})) - assert.Equal(t, []pr_db.PatronRequestAction{}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideBorrowing, State: BorrowerStateCompleted})) + listCompare(t, []pr_db.PatronRequestAction{BorrowerActionValidate}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideBorrowing, State: BorrowerStateNew})) + listCompare(t, []pr_db.PatronRequestAction{}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideBorrowing, State: BorrowerStateCompleted})) // Lender - assert.Equal(t, []pr_db.PatronRequestAction{LenderActionAddCondition, LenderActionCannotSupply, LenderActionShip}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideLending, State: LenderStateWillSupply})) - assert.Equal(t, []pr_db.PatronRequestAction{}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideLending, State: LenderStateShipped})) + listCompare(t, []pr_db.PatronRequestAction{LenderActionAddCondition, LenderActionCannotSupply, LenderActionShip}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideLending, State: LenderStateWillSupply})) + listCompare(t, []pr_db.PatronRequestAction{}, actionMappingService.GetActionMapping(pr_db.PatronRequest{}).GetActionsForPatronRequest(pr_db.PatronRequest{Side: SideLending, State: LenderStateShipped})) +} + +func listCompare(t *testing.T, list1 []pr_db.PatronRequestAction, list2 []pr_db.PatronRequestAction) { + assert.Equal(t, len(list1), len(list2)) + for i := range list1 { + assert.True(t, slices.Contains(list2, list1[i])) + } +} + +func mapCompare(t *testing.T, map1 map[pr_db.PatronRequestState][]pr_db.PatronRequestAction, map2 map[pr_db.PatronRequestState][]pr_db.PatronRequestAction) { + for stateName := range map1 { + listOne := map1[stateName] + listTwo := map2[stateName] + assert.Equal(t, len(listOne), len(listTwo)) + for i := range listOne { + assert.True(t, slices.Contains(listTwo, listOne[i])) + } + } } diff --git a/broker/patron_request/service/action_test.go b/broker/patron_request/service/action_test.go index 7b9e20c5..fb932373 100644 --- a/broker/patron_request/service/action_test.go +++ b/broker/patron_request/service/action_test.go @@ -869,3 +869,9 @@ func TestCallNumberFromIllRequest(t *testing.T) { callNumber := callNumberFromIllRequest(r) assert.Equal(t, "QA76.73.G63 D37 2020", callNumber) } + +func TestLoadReturnableStateModel(t *testing.T) { + stateModel, err := LoadStateModelByName("returnables") + assert.Nil(t, err) + assert.NotNil(t, stateModel) +} diff --git a/broker/patron_request/service/statemodel.go b/broker/patron_request/service/statemodel.go new file mode 100644 index 00000000..fdd7e7b0 --- /dev/null +++ b/broker/patron_request/service/statemodel.go @@ -0,0 +1,55 @@ +package prservice + +import ( + "embed" + "encoding/json" + + "github.com/indexdata/crosslink/broker/patron_request/proapi" +) + +type StateModelService struct { + stateMap map[string]*proapi.StateModel +} + +func (s *StateModelService) GetStateModel(modelName string) *proapi.StateModel { + if s.stateMap == nil { + s.stateMap = make(map[string]*proapi.StateModel) + } + + stateModel, ok := s.stateMap[modelName] + + if ok { + return stateModel + } + + stateModel, err := LoadStateModelByName(modelName) + if err == nil { + s.stateMap[modelName] = stateModel + return stateModel + } + return nil +} + +//go:embed statemodels +var modelFS embed.FS + +func LoadStateModelByName(modelName string) (*proapi.StateModel, error) { + path := "statemodels/" + modelName + ".json" + stateModel, err := loadStateModel(path) + if err != nil { + return nil, err + } + return stateModel, nil +} + +func loadStateModel(path string) (*proapi.StateModel, error) { + data, err := modelFS.ReadFile(path) + if err != nil { + return nil, err + } + + var stateModel proapi.StateModel + err = json.Unmarshal(data, &stateModel) + + return &stateModel, err +} diff --git a/broker/patron_request/service/statemodels/returnables.json b/broker/patron_request/service/statemodels/returnables.json new file mode 100644 index 00000000..7175f872 --- /dev/null +++ b/broker/patron_request/service/statemodels/returnables.json @@ -0,0 +1,516 @@ +{ + "type": "StateModel", + "name": "CrossLink Returnables State Model", + "desc": "Requester/Supplier workflow per ISO18626, including NCIP integration and ISO status events.", + "version": "1.0.0", + "states": [ + { + "name": "NEW", + "display": "New", + "desc": "Initial state after Patron Request is created (POST)", + "side": "REQUESTER", + "actions": [ + { + "name": "validate", + "desc": "Validate the request (e.g. check patron via NCIP LookupUser, if enabled)", + "transitions": [ + "VALIDATED" + ] + } + ] + }, + { + "name": "VALIDATED", + "display": "Validated", + "desc": "Patron Request is valid", + "side": "REQUESTER", + "actions": [ + { + "name": "send-request", + "desc": "Send ISO18626 request to the supplier or broker", + "transitions": [ + "SENT" + ] + } + ] + }, + { + "name": "SENT", + "display": "Sent", + "desc": "Request is sent", + "side": "REQUESTER", + "events": [ + { + "name": "expect-to-supply", + "desc": "Supplier indicates an intention to supply (ISO18626 ExpectToSupply)", + "transitions": [ + "SUPPLIER_LOCATED" + ] + }, + { + "name": "will-supply", + "desc": "Supplier will supply without conditions (ISO18626 WillSupply)", + "transitions": [ + "WILL_SUPPLY" + ] + }, + { + "name": "will-supply-conditional", + "desc": "Supplier will supply with conditions (ISO18626 WillSupply with conditions)", + "transitions": [ + "CONDITION_PENDING" + ] + }, + { + "name": "loaned", + "desc": "Supplier shipped the item (ISO18626 Loaned)", + "transitions": [ + "SHIPPED" + ] + }, + { + "name": "unfilled", + "desc": "Supplier cannot supply (ISO18626 Unfilled)", + "transitions": [ + "UNFILLED" + ] + } + ] + }, + { + "name": "SUPPLIER_LOCATED", + "display": "Supplier Located", + "desc": "After receiving ISO ExpectToSupply", + "side": "REQUESTER", + "actions": [ + { + "name": "cancel-request", + "desc": "Send ISO18626 Cancel request to supplier", + "transitions": [ + "CANCEL_PENDING" + ] + } + ], + "events": [ + { + "name": "will-supply", + "desc": "Supplier will supply without conditions (ISO18626 WillSupply)", + "transitions": [ + "WILL_SUPPLY" + ] + }, + { + "name": "will-supply-conditional", + "desc": "Supplier will supply with conditions (ISO18626 WillSupply with conditions)", + "transitions": [ + "CONDITION_PENDING" + ] + }, + { + "name": "unfilled", + "desc": "Supplier cannot supply (ISO18626 Unfilled)", + "transitions": [ + "UNFILLED" + ] + } + ] + }, + { + "name": "CONDITION_PENDING", + "display": "Condition Pending", + "desc": "Received supply conditions", + "side": "REQUESTER", + "actions": [ + { + "name": "accept-condition", + "desc": "Accept supplier conditions (ISO18626 Notification)", + "transitions": [ + "WILL_SUPPLY" + ] + }, + { + "name": "reject-condition", + "desc": "Reject supplier conditions (ISO18626 Cancel)", + "transitions": [ + "CANCEL_PENDING" + ] + } + ] + }, + { + "name": "WILL_SUPPLY", + "display": "Will Supply", + "desc": "Received ISO18626 WillSupply (without condition)", + "side": "REQUESTER", + "actions": [ + { + "name": "cancel-request", + "desc": "Send ISO18626 Cancel to supplier", + "transitions": [ + "CANCEL_PENDING" + ] + } + ], + "events": [ + { + "name": "loaned", + "desc": "Supplier shipped the item (ISO18626 Loaned)", + "transitions": [ + "SHIPPED" + ] + }, + { + "name": "unfilled", + "desc": "Supplier cannot supply (ISO18626 Unfilled)", + "transitions": [ + "UNFILLED" + ] + } + ] + }, + { + "name": "SHIPPED", + "display": "Shipped", + "desc": "After receiving ISO18626 Loaned", + "side": "REQUESTER", + "actions": [ + { + "name": "receive", + "desc": "Receive and accept item in local ILS (via NCIP AcceptItem if enabled); send ISO18626 Received", + "transitions": [ + "RECEIVED" + ] + } + ] + }, + { + "name": "RECEIVED", + "display": "Received", + "desc": "Item received and accepted into local ILS.", + "side": "REQUESTER", + "actions": [ + { + "name": "check-out", + "desc": "Check out item to patron (NCIP CheckOutItem)", + "transitions": [ + "CHECKED_OUT" + ] + } + ] + }, + { + "name": "CHECKED_OUT", + "display": "Checked Out", + "desc": "Item is checked out to patron", + "side": "REQUESTER", + "actions": [ + { + "name": "check-in", + "desc": "Check the item back-in (NCIP CheckInItem)", + "transitions": [ + "CHECKED_IN" + ] + } + ] + }, + { + "name": "CHECKED_IN", + "display": "Checked In", + "desc": "Item is checked back in to the local ILS", + "side": "REQUESTER", + "actions": [ + { + "name": "ship-return", + "desc": "Send ISO18626 ShippedReturn and delete the temporary item (NCIP DeleteItem)", + "transitions": [ + "SHIPPED_RETURNED" + ] + } + ] + }, + { + "name": "SHIPPED_RETURNED", + "display": "Shipped Returned", + "desc": "Item is in return shipment", + "side": "REQUESTER", + "events": [ + { + "name": "completed", + "desc": "Supplier/broker signals loan/copy completion", + "transitions": [ + "COMPLETED" + ] + } + ] + }, + { + "name": "CANCEL_PENDING", + "display": "Cancel Pending", + "desc": "ISO18626 Cancel action is sent to supplier/broker", + "side": "REQUESTER", + "events": [ + { + "name": "cancel-accepted", + "desc": "Supplier accepts cancellation", + "transitions": [ + "CANCELLED" + ] + } + ] + }, + { + "name": "COMPLETED", + "display": "Completed", + "desc": "Received LoanCompleted or CopyCompleted from the supplier/broker", + "side": "REQUESTER", + "terminal": true + }, + { + "name": "CANCELLED", + "display": "Cancelled", + "desc": "Cancel response is received", + "side": "REQUESTER", + "terminal": true + }, + { + "name": "UNFILLED", + "display": "Unfilled", + "desc": "Unfilled response is received", + "side": "REQUESTER", + "terminal": true + }, + { + "name": "NEW", + "display": "New", + "desc": "Item is created on the supplier side for local fulfillment", + "side": "SUPPLIER", + "actions": [ + { + "name": "validate", + "desc": "Validate the request, e.g institutional patron via NCIP LookupUser, if enabled", + "transitions": [ + "VALIDATED" + ] + } + ] + }, + { + "name": "VALIDATED", + "display": "Validated", + "desc": "Request is valid", + "side": "SUPPLIER", + "actions": [ + { + "name": "will-supply", + "desc": "Indicate supplier will supply and send ISO18626 WillSupply", + "transitions": [ + "WILL_SUPPLY" + ] + }, + { + "name": "cannot-supply", + "desc": "Indicate cannot supply and send ISO18626 Unfilled", + "transitions": [ + "UNFILLED" + ] + }, + { + "name": "add-condition", + "desc": "Indicate will supply with conditions and send ISO18626 WillSupply", + "transitions": [ + "CONDITION_PENDING" + ] + } + ], + "events": [ + { + "name": "cancel-request", + "desc": "Requester sent ISO18626 Cancel", + "transitions": [ + "CANCEL_REQUESTED" + ] + } + ] + }, + { + "name": "WILL_SUPPLY", + "display": "Will Supply", + "desc": "After manual will-supply or successful auto-responder", + "side": "SUPPLIER", + "actions": [ + { + "name": "add-condition", + "desc": "Add conditions and notify requester", + "transitions": [ + "CONDITION_PENDING" + ] + }, + { + "name": "ship", + "desc": "Mark shipped; send ISO Loaned; NCIP CheckOutItem", + "transitions": [ + "SHIPPED" + ] + }, + { + "name": "cannot-supply", + "desc": "Indicate cannot supply", + "transitions": [ + "UNFILLED" + ] + } + ], + "events": [ + { + "name": "cancel-request", + "desc": "Requester sends ISO Cancel", + "transitions": [ + "CANCEL_REQUESTED" + ] + } + ] + }, + { + "name": "CONDITION_PENDING", + "display": "Condition Pending", + "desc": "Conditions are sent with a special ISO WillSupply", + "side": "SUPPLIER", + "actions": [ + { + "name": "cannot-supply", + "desc": "Indicate cannot supply", + "transitions": [ + "UNFILLED" + ] + } + ], + "events": [ + { + "name": "conditions-accepted", + "desc": "Requester accepts conditions", + "transitions": [ + "CONDITION_ACCEPTED" + ] + }, + { + "name": "condition-rejected", + "desc": "Requester rejects conditions (auto-responder may mark unfilled)", + "transitions": [ + "UNFILLED" + ] + }, + { + "name": "cancel-request", + "desc": "Requester sends ISO Cancel", + "transitions": [ + "CANCEL_REQUESTED" + ] + } + ] + }, + { + "name": "CONDITION_ACCEPTED", + "display": "Condition Accepted", + "desc": "After receiving conditions accepted notification", + "side": "SUPPLIER", + "actions": [ + { + "name": "ship", + "desc": "Mark shipped; send ISO Loaned; NCIP CheckOutItem", + "transitions": [ + "SHIPPED" + ] + }, + { + "name": "cannot-supply", + "desc": "Indicate cannot supply", + "transitions": [ + "UNFILLED" + ] + } + ], + "events": [ + { + "name": "cancel-request", + "desc": "Requester sends ISO Cancel", + "transitions": [ + "CANCEL_REQUESTED" + ] + } + ] + }, + { + "name": "SHIPPED", + "display": "Shipped", + "desc": "After marking shipped and sending ISO Loaned; NCIP CheckOutItem", + "side": "SUPPLIER", + "events": [ + { + "name": "shipped-return", + "desc": "Requester sends ISO ShippedReturn", + "transitions": [ + "SHIPPED_RETURN" + ] + } + ] + }, + { + "name": "SHIPPED_RETURN", + "display": "Shipped Return", + "desc": "After receiving ISO ShippedReturn message", + "side": "SUPPLIER", + "actions": [ + { + "name": "mark-received", + "desc": "Mark returned item received and complete (CheckInItem if configured)", + "transitions": [ + "COMPLETED" + ] + } + ] + }, + { + "name": "CANCEL_REQUESTED", + "display": "Cancel Requested", + "desc": "After receiving ISO18626 Cancel from requester", + "side": "SUPPLIER", + "actions": [ + { + "name": "mark-cancelled", + "desc": "Confirm cancellation", + "transitions": [ + "CANCELLED" + ] + }, + { + "name": "will-supply", + "desc": "Resume supplying despite cancel request", + "transitions": [ + "WILL_SUPPLY" + ] + } + ] + }, + { + "name": "COMPLETED", + "display": "Completed", + "desc": "After marking received and successful NCIP CheckInItem (if configured)", + "side": "SUPPLIER", + "terminal": true + }, + { + "name": "CANCELLED", + "display": "Cancelled", + "desc": "After marking cancelled or automatically if auto-cancellation is on", + "side": "SUPPLIER", + "terminal": true + }, + { + "name": "UNFILLED", + "display": "Unfilled", + "desc": "After manual cannot-supply or automatically if auto-responder is on", + "side": "SUPPLIER", + "terminal": true + } + ] +} \ No newline at end of file diff --git a/broker/test/patron_request/api/api-handler_test.go b/broker/test/patron_request/api/api-handler_test.go index aa14d48e..c3d32230 100644 --- a/broker/test/patron_request/api/api-handler_test.go +++ b/broker/test/patron_request/api/api-handler_test.go @@ -353,6 +353,17 @@ func TestActionsToCompleteState(t *testing.T) { assert.Equal(t, string(prservice.LenderStateCompleted), foundPr.State) } +func TestGetReturnableStateModel(t *testing.T) { + respBytes := httpRequest(t, "GET", "/state_model/models/returnables", []byte{}, 200) + var retrievedStateModel proapi.StateModel + err := json.Unmarshal(respBytes, &retrievedStateModel) + assert.NoError(t, err, "failed to unmarshal state model") + returnablesStateModel, _ := prservice.LoadStateModelByName("returnables") + assert.Equal(t, returnablesStateModel.Name, retrievedStateModel.Name) + assert.Equal(t, returnablesStateModel.Desc, retrievedStateModel.Desc) + assert.Equal(t, len(*returnablesStateModel.States), len(*retrievedStateModel.States)) +} + func httpRequest(t *testing.T, method string, uriPath string, reqbytes []byte, expectStatus int) []byte { client := http.DefaultClient hreq, err := http.NewRequest(method, getLocalhostWithPort()+uriPath, bytes.NewBuffer(reqbytes)) diff --git a/go.work b/go.work index f653d161..b2834096 100644 --- a/go.work +++ b/go.work @@ -3,11 +3,11 @@ go 1.25 use ( ./broker ./common + ./directory ./httpclient ./illmock ./iso18626 ./marcxml ./ncip ./sru - ./directory ) diff --git a/go.work.sum b/go.work.sum index 91d52f5f..a20b369f 100644 --- a/go.work.sum +++ b/go.work.sum @@ -65,6 +65,7 @@ cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2Aawl cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY= cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= +cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo= cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= cloud.google.com/go/contactcenterinsights v1.13.0 h1:6Vs/YnDG5STGjlWMEjN/xtmft7MrOTOnOZYUZtGTx0w= @@ -259,6 +260,7 @@ cloud.google.com/go/websecurityscanner v1.6.5 h1:YqWZrZYabG88TZt7364XWRJGhxmxhon cloud.google.com/go/websecurityscanner v1.6.5/go.mod h1:QR+DWaxAz2pWooylsBF854/Ijvuoa3FCyS1zBa1rAVQ= cloud.google.com/go/workflows v1.12.4 h1:uHNmUiatTbPQ4H1pabwfzpfEYD4BBnqDHqMm2IesOh4= cloud.google.com/go/workflows v1.12.4/go.mod h1:yQ7HUqOkdJK4duVtMeBCAOPiN1ZF1E9pAMX51vpwB/w= +dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.1 h1:tYLp1ULvO7i3fI5vE21ReQuj99QFSs7lGm0xWyJo87o= @@ -505,7 +507,9 @@ github.com/djherbis/atime v1.1.0/go.mod h1:28OF6Y8s3NQWwacXc5eZTsEsiMzp7LF8MbXE+ github.com/docker/cli-docs-tool v0.7.0 h1:M2Da98Unz2kz3A5d4yeSGbhyOge2mfYSNjAFt01Rw0M= github.com/docker/cli-docs-tool v0.7.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= github.com/docker/docker v27.1.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v28.2.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= @@ -513,14 +517,17 @@ github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA github.com/dvsekhvalnov/jose2go v1.6.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= github.com/dvsekhvalnov/jose2go v1.7.0 h1:bnQc8+GMnidJZA8zc6lLEAb4xNrIqHwO+9TzqvtQZPo= github.com/dvsekhvalnov/jose2go v1.7.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI= github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0= github.com/envoyproxy/go-control-plane v0.13.0 h1:HzkeUz1Knt+3bK+8LG1bxOO/jzWZmdxpwC51i202les= github.com/envoyproxy/go-control-plane v0.13.0/go.mod h1:GRaKG3dwvFoTg4nj7aXdZnvMg4d7nvT/wl9WgVXn3Q8= +github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA= github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A= github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw= +github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4= github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM= @@ -565,6 +572,7 @@ github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBj github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= @@ -611,6 +619,7 @@ github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/glog v1.2.2 h1:1+mZ9upx1Dh6FmUTFR1naJ77miKiXgALjWOZ3NVFPmY= github.com/golang/glog v1.2.2/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= +github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= @@ -629,6 +638,7 @@ github.com/google/certificate-transparency-go v1.0.10-0.20180222191210-5ab67e519 github.com/google/flatbuffers v2.0.8+incompatible h1:ivUb1cGomAB101ZM1T0nOiWz9pSrTMoa9+EiY7igmkM= github.com/google/flatbuffers v2.0.8+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.14.0 h1:z58vMqHxuwvAsVwvKEkmVBz2TlgBgH5k6koEXBtlYkw= @@ -645,7 +655,6 @@ github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4= @@ -695,6 +704,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 h1:mV02weK github.com/imkira/go-interpol v1.1.0/go.mod h1:z0h2/2T3XF8kyEPpRgJ3kmNv+C43p+I/CoI+jC3w2iA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/indexdata/crosslink v0.0.0-20260121111122-3096ccb3a8ea/go.mod h1:r0ibawAkcS/t9mThAE9T2riuuU+jd9B7qUKOkBDIoGk= github.com/indexdata/go-utils v0.0.0-20240626111027-28caddc0fd2b/go.mod h1:0sW6Szxv8GNU3LBtK6mgBKDEUnlovPfghiG9xi+i0R8= github.com/intel/goresctrl v0.3.0 h1:K2D3GOzihV7xSBedGxONSlaw/un1LZgWsc9IfqipN4c= github.com/intel/goresctrl v0.3.0/go.mod h1:fdz3mD85cmP9sHD8JUlrNWAxvwM86CrbmVXltEKd7zk= @@ -718,6 +728,7 @@ github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76 github.com/jackc/pgx/v4 v4.18.2 h1:xVpYkNR5pk5bMCZGfClbO962UIqVABcAGt7ha1s/FeU= github.com/jackc/pgx/v4 v4.18.2/go.mod h1:Ey4Oru5tH5sB6tV7hDmfWFahwF15Eb7DNXlRKx2CkVw= github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A= +github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ= github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jinzhu/gorm v0.0.0-20170222002820-5409931a1bb8 h1:CZkYfurY6KGhVtlalI4QwQ6T0Cu6iuY3e0x5RLu96WE= github.com/jinzhu/inflection v0.0.0-20170102125226-1c35d901db3d h1:jRQLvyVGL+iVtDElaEIDdKwpPqUIZJfzkNLV34htpEc= @@ -755,10 +766,13 @@ github.com/kataras/tunnel v0.0.4/go.mod h1:9FkU4LaeifdMWqZu7o20ojmW4B7hdhv2CMLwf github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0 h1:e8esj/e4R+SAOwFwN+n3zr0nYeCyeweozKfO23MvHzY= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= github.com/klauspost/asmfmt v1.3.2/go.mod h1:AG8TuvYojzulgDAMCnYn50l/5QV3Bs/tp6j0HLHbNSE= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= +github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= @@ -790,8 +804,10 @@ github.com/lestrrat-go/jwx v1.2.25 h1:tAx93jN2SdPvFn08fHNAhqFJazn5mBBOB8Zli0g0ot github.com/lestrrat-go/jwx v1.2.25/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY= github.com/lestrrat-go/option v1.0.0 h1:WqAWL8kh8VcSoD6xjSH34/1m8yxluXQbDeKNfvFeEO4= github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3 h1:jUp75lepDg0phMUJBCmvaeFDldD2N3S1lBuPwUTszio= github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4 h1:sIXJOMrYnQZJu7OB7ANSF4MYri2fTEGIsRLz6LwI4xE= github.com/lyft/protoc-gen-star/v2 v2.0.4-0.20230330145011-496ad1ac90a4/go.mod h1:amey7yeodaJhXSbf/TlLvWiqQfLOSpEk//mLlc+axEk= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw= @@ -847,6 +863,9 @@ github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9Kou github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/moby/sys/reexec v0.1.0 h1:RrBi8e0EBTLEgfruBOFcxtElzRGTEUkeIFaVXgU7wok= github.com/moby/sys/reexec v0.1.0/go.mod h1:EqjBg8F3X7iZe5pU6nRZnYCMUTXoxsjiIfHup5wYIN8= +github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= +github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -904,8 +923,10 @@ github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo= github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos= github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c= @@ -927,7 +948,9 @@ github.com/santhosh-tekuri/jsonschema/v5 v5.3.1/go.mod h1:uToXkOrWAZ6/Oc07xWQrPO github.com/schollz/closestmatch v2.1.0+incompatible h1:Uel2GXEpJqOWBrlyI+oY9LTiyyjYS17cCYRqP13/SHk= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= +github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= +github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c= github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -963,6 +986,8 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 h1:kdXcSzyDtseVEc4yCz2qF8ZrQvIDBJLl4S1c3GCXmoI= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tchap/go-patricia/v2 v2.3.1 h1:6rQp39lgIYZ+MHmdEq4xzuk1t7OdC35z/xm0BGhTkes= @@ -972,6 +997,10 @@ github.com/tdewolff/minify/v2 v2.12.9/go.mod h1:qOqdlDfL+7v0/fyymB+OP497nIxJYSvX github.com/tdewolff/parse/v2 v2.6.8 h1:mhNZXYCx//xG7Yq2e/kVLNZw4YfYmeHbhx+Zc0OvFMA= github.com/tdewolff/parse/v2 v2.6.8/go.mod h1:XHDhaU6IBgsryfdnpzUXBlT6leW/l25yrFBTEb4eIyM= github.com/tdewolff/test v1.0.9/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE= +github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= +github.com/testcontainers/testcontainers-go/modules/postgres v0.37.0/go.mod h1:Qj/eGbRbO/rEYdcRLmN+bEojzatP/+NS1y8ojl2PQsc= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/tonistiigi/go-actions-cache v0.0.0-20240320205438-9794bdbb2fb4 h1:R0lM8Jo3aZL95yjQHWQti7nszllleKBxCs9uyFbykII= github.com/tonistiigi/go-actions-cache v0.0.0-20240320205438-9794bdbb2fb4/go.mod h1:anhKd3mnC1shAbQj1Q4IJ+w6xqezxnyDYlx/yKa7IXM= github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0= @@ -1025,7 +1054,9 @@ github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg= github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -1060,6 +1091,8 @@ go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIj go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg= +go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= +go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E= go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4= go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI= go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.28.0 h1:U2guen0GhqH8o/G2un8f/aG/y++OuW6MyCo6hT9prXk= @@ -1072,26 +1105,41 @@ go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUis go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8= +go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= +go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs= go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A= go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU= +go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY= go.opentelemetry.io/otel/sdk/metric v1.28.0 h1:OkuaKgKrgAbYrrY0t92c+cC+2F6hsFNnCQArXCKlg08= +go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8= +go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= +go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA= go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc= golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= +golang.org/x/crypto v0.44.0/go.mod h1:013i+Nw79BMiQiMsOPcVCB5ZIJbYkerPrGnOa00tvmc= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo= golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= @@ -1099,13 +1147,20 @@ golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/net v0.46.0/go.mod h1:Q9BGdFy1y4nkUwiLvT5qtyhAnEHgnQ/zd8PfU6nc210= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= golang.org/x/oauth2 v0.22.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= @@ -1114,12 +1169,20 @@ golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M= golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1127,7 +1190,9 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -1140,7 +1205,9 @@ golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457 h1:zf5N6UOrA487eEFacMePxjXAJctxKmyjKUsjA11Uzuk= golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b h1:DU+gwOBXU+6bO0sEyO7o/NeMlxZxCZEvI7v+J4a1zRQ= @@ -1152,6 +1219,7 @@ golang.org/x/telemetry v0.0.0-20251008203120-078029d740a8/go.mod h1:Pi4ztBfryZoJ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= @@ -1161,9 +1229,17 @@ golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= +golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU= golang.org/x/tools v0.11.0/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= @@ -1171,8 +1247,13 @@ golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxb golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/tools/godoc v0.1.0-deprecated h1:o+aZ1BOj6Hsx/GBdJO/s815sqftjSnrZZwyYTHODvtk= golang.org/x/tools/godoc v0.1.0-deprecated/go.mod h1:qM63CriJ961IHWmnWa9CjZnBndniPt4a3CK0PVB9bIg= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= @@ -1187,17 +1268,27 @@ google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7 google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo= google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38/go.mod h1:vuAjtvlwkDKF6L1GQ0SokiRLCGFfeBUXWr/aFFkHACc= +google.golang.org/genproto/googleapis/api v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:dguCy7UOdZhTvLzDyt15+rOrawrpM4q7DD9dQ1P11P4= +google.golang.org/genproto/googleapis/api v0.0.0-20250528174236-200df99c418a/go.mod h1:a77HrdMjoeKbnd2jmgcWdaS++ZLZAEq3orIOAEIKiVw= google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM= google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20241104194629-dd2ea8efbc28/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250811230008-5f3141c8851a/go.mod h1:gw1tLEfykwDz2ET4a12jcXt4couGAm7IwsVaTy0Sflo= google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= +google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA= +google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc/examples v0.0.0-20230224211313-3775f633ce20/go.mod h1:Nr5H8+MlGWr5+xX/STzdoEqJrO+YteqFbMyCsrb6mH0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= gopkg.in/airbrake/gobrake.v2 v2.0.9 h1:7z2uVWwn7oVeeugY1DtlPAy5H+KYgB1KeKTnqjNatLo= gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/cenkalti/backoff.v2 v2.2.1 h1:eJ9UAg01/HIHG987TwxvnzK2MgxXq97YY6rYDpY9aII=