Initial commit of local doc search (#4624)

This commit is contained in:
Mike Cohen
2026-01-12 19:36:01 +10:00
committed by GitHub
parent aabf6f67ba
commit 2df65032cd
34 changed files with 2373 additions and 831 deletions
+26
View File
@@ -1,5 +1,12 @@
package api
import (
"context"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
"www.velocidex.com/golang/velociraptor/services"
)
/*
# How does the Velociraptor server work?
@@ -69,3 +76,22 @@ NOTE: The gateway's certificates are critical to protect - if an actor
*/
func (self *ApiServer) SearchDocs(
ctx context.Context,
in *api_proto.DocSearchRequest) (*api_proto.DocSearchResponses, error) {
users := services.GetUserManager()
_, org_config_obj, err := users.GetUserFromContext(ctx)
if err != nil {
return nil, Status(self.verbose, err)
}
// All users can search the docs with no permission required.
doc_manager, err := services.GetDocManager(org_config_obj)
if err != nil {
return nil, Status(self.verbose, err)
}
return doc_manager.Search(ctx, in.Query, int(in.Start), int(in.Length))
}
+20 -40
View File
@@ -241,26 +241,6 @@ func (mr *MockAPIClientMockRecorder) CreateUser(arg0, arg1 interface{}, arg2 ...
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateUser", reflect.TypeOf((*MockAPIClient)(nil).CreateUser), varargs...)
}
// DefineSecret mocks base method.
func (m *MockAPIClient) DefineSecret(arg0 context.Context, arg1 *proto0.SecretDefinition, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "DefineSecret", varargs...)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// DefineSecret indicates an expected call of DefineSecret.
func (mr *MockAPIClientMockRecorder) DefineSecret(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DefineSecret", reflect.TypeOf((*MockAPIClient)(nil).DefineSecret), varargs...)
}
// DeleteNotebook mocks base method.
func (m *MockAPIClient) DeleteNotebook(arg0 context.Context, arg1 *proto0.NotebookMetadata, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
@@ -281,26 +261,6 @@ func (mr *MockAPIClientMockRecorder) DeleteNotebook(arg0, arg1 interface{}, arg2
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNotebook", reflect.TypeOf((*MockAPIClient)(nil).DeleteNotebook), varargs...)
}
// DeleteSecretDefinition mocks base method.
func (m *MockAPIClient) DeleteSecretDefinition(arg0 context.Context, arg1 *proto0.SecretDefinition, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "DeleteSecretDefinition", varargs...)
ret0, _ := ret[0].(*emptypb.Empty)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// DeleteSecretDefinition indicates an expected call of DeleteSecretDefinition.
func (mr *MockAPIClientMockRecorder) DeleteSecretDefinition(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSecretDefinition", reflect.TypeOf((*MockAPIClient)(nil).DeleteSecretDefinition), varargs...)
}
// DeleteSubject mocks base method.
func (m *MockAPIClient) DeleteSubject(arg0 context.Context, arg1 *proto0.DataRequest, arg2 ...grpc.CallOption) (*emptypb.Empty, error) {
m.ctrl.T.Helper()
@@ -1281,6 +1241,26 @@ func (mr *MockAPIClientMockRecorder) Scheduler(arg0 interface{}, arg1 ...interfa
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Scheduler", reflect.TypeOf((*MockAPIClient)(nil).Scheduler), varargs...)
}
// SearchDocs mocks base method.
func (m *MockAPIClient) SearchDocs(arg0 context.Context, arg1 *proto0.DocSearchRequest, arg2 ...grpc.CallOption) (*proto0.DocSearchResponses, error) {
m.ctrl.T.Helper()
varargs := []interface{}{arg0, arg1}
for _, a := range arg2 {
varargs = append(varargs, a)
}
ret := m.ctrl.Call(m, "SearchDocs", varargs...)
ret0, _ := ret[0].(*proto0.DocSearchResponses)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// SearchDocs indicates an expected call of SearchDocs.
func (mr *MockAPIClientMockRecorder) SearchDocs(arg0, arg1 interface{}, arg2 ...interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
varargs := append([]interface{}{arg0, arg1}, arg2...)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SearchDocs", reflect.TypeOf((*MockAPIClient)(nil).SearchDocs), varargs...)
}
// SearchFile mocks base method.
func (m *MockAPIClient) SearchFile(arg0 context.Context, arg1 *proto0.SearchFileRequest, arg2 ...grpc.CallOption) (*proto0.SearchFileResponse, error) {
m.ctrl.T.Helper()
+751 -740
View File
File diff suppressed because it is too large Load Diff
+83
View File
@@ -1660,6 +1660,42 @@ func local_request_API_LoadArtifactPack_0(ctx context.Context, marshaler runtime
}
var (
filter_API_SearchDocs_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
func request_API_SearchDocs_0(ctx context.Context, marshaler runtime.Marshaler, client APIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DocSearchRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_API_SearchDocs_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.SearchDocs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_API_SearchDocs_0(ctx context.Context, marshaler runtime.Marshaler, server APIServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DocSearchRequest
var metadata runtime.ServerMetadata
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_API_SearchDocs_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.SearchDocs(ctx, &protoReq)
return msg, metadata, err
}
var (
filter_API_GetToolInfo_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
)
@@ -3563,6 +3599,29 @@ func RegisterAPIHandlerServer(ctx context.Context, mux *runtime.ServeMux, server
})
mux.Handle("GET", pattern_API_SearchDocs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/proto.API/SearchDocs", runtime.WithHTTPPathPattern("/api/v1/SearchDocs"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_API_SearchDocs_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_API_SearchDocs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_API_GetToolInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -5102,6 +5161,26 @@ func RegisterAPIHandlerClient(ctx context.Context, mux *runtime.ServeMux, client
})
mux.Handle("GET", pattern_API_SearchDocs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/proto.API/SearchDocs", runtime.WithHTTPPathPattern("/api/v1/SearchDocs"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_API_SearchDocs_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_API_SearchDocs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_API_GetToolInfo_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -5716,6 +5795,8 @@ var (
pattern_API_LoadArtifactPack_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "LoadArtifactPack"}, ""))
pattern_API_SearchDocs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "SearchDocs"}, ""))
pattern_API_GetToolInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "GetToolInfo"}, ""))
pattern_API_SetToolInfo_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "SetToolInfo"}, ""))
@@ -5860,6 +5941,8 @@ var (
forward_API_LoadArtifactPack_0 = runtime.ForwardResponseMessage
forward_API_SearchDocs_0 = runtime.ForwardResponseMessage
forward_API_GetToolInfo_0 = runtime.ForwardResponseMessage
forward_API_SetToolInfo_0 = runtime.ForwardResponseMessage
+8
View File
@@ -12,6 +12,7 @@ import "google/protobuf/empty.proto";
import "artifacts.proto";
import "clients.proto";
import "datastore.proto";
import "docs.proto";
import "health.proto";
import "hunts.proto";
import "flows.proto";
@@ -414,6 +415,13 @@ service API {
};
}
// Documentation
rpc SearchDocs(DocSearchRequest) returns (DocSearchResponses) {
option (google.api.http) = {
get: "/api/v1/SearchDocs",
};
}
// Tools
rpc GetToolInfo(Tool) returns (Tool) {
option (google.api.http) = {
+38
View File
@@ -80,6 +80,8 @@ type APIClient interface {
GetArtifactFile(ctx context.Context, in *GetArtifactRequest, opts ...grpc.CallOption) (*GetArtifactResponse, error)
SetArtifactFile(ctx context.Context, in *SetArtifactRequest, opts ...grpc.CallOption) (*SetArtifactResponse, error)
LoadArtifactPack(ctx context.Context, in *LoadArtifactPackRequest, opts ...grpc.CallOption) (*LoadArtifactPackResponse, error)
// Documentation
SearchDocs(ctx context.Context, in *DocSearchRequest, opts ...grpc.CallOption) (*DocSearchResponses, error)
// Tools
GetToolInfo(ctx context.Context, in *proto1.Tool, opts ...grpc.CallOption) (*proto1.Tool, error)
SetToolInfo(ctx context.Context, in *proto1.Tool, opts ...grpc.CallOption) (*proto1.Tool, error)
@@ -555,6 +557,15 @@ func (c *aPIClient) LoadArtifactPack(ctx context.Context, in *LoadArtifactPackRe
return out, nil
}
func (c *aPIClient) SearchDocs(ctx context.Context, in *DocSearchRequest, opts ...grpc.CallOption) (*DocSearchResponses, error) {
out := new(DocSearchResponses)
err := c.cc.Invoke(ctx, "/proto.API/SearchDocs", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *aPIClient) GetToolInfo(ctx context.Context, in *proto1.Tool, opts ...grpc.CallOption) (*proto1.Tool, error) {
out := new(proto1.Tool)
err := c.cc.Invoke(ctx, "/proto.API/GetToolInfo", in, out, opts...)
@@ -1018,6 +1029,8 @@ type APIServer interface {
GetArtifactFile(context.Context, *GetArtifactRequest) (*GetArtifactResponse, error)
SetArtifactFile(context.Context, *SetArtifactRequest) (*SetArtifactResponse, error)
LoadArtifactPack(context.Context, *LoadArtifactPackRequest) (*LoadArtifactPackResponse, error)
// Documentation
SearchDocs(context.Context, *DocSearchRequest) (*DocSearchResponses, error)
// Tools
GetToolInfo(context.Context, *proto1.Tool) (*proto1.Tool, error)
SetToolInfo(context.Context, *proto1.Tool) (*proto1.Tool, error)
@@ -1220,6 +1233,9 @@ func (UnimplementedAPIServer) SetArtifactFile(context.Context, *SetArtifactReque
func (UnimplementedAPIServer) LoadArtifactPack(context.Context, *LoadArtifactPackRequest) (*LoadArtifactPackResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method LoadArtifactPack not implemented")
}
func (UnimplementedAPIServer) SearchDocs(context.Context, *DocSearchRequest) (*DocSearchResponses, error) {
return nil, status.Errorf(codes.Unimplemented, "method SearchDocs not implemented")
}
func (UnimplementedAPIServer) GetToolInfo(context.Context, *proto1.Tool) (*proto1.Tool, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetToolInfo not implemented")
}
@@ -2154,6 +2170,24 @@ func _API_LoadArtifactPack_Handler(srv interface{}, ctx context.Context, dec fun
return interceptor(ctx, in, info, handler)
}
func _API_SearchDocs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DocSearchRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(APIServer).SearchDocs(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/proto.API/SearchDocs",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(APIServer).SearchDocs(ctx, req.(*DocSearchRequest))
}
return interceptor(ctx, in, info, handler)
}
func _API_GetToolInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(proto1.Tool)
if err := dec(in); err != nil {
@@ -3021,6 +3055,10 @@ var API_ServiceDesc = grpc.ServiceDesc{
MethodName: "LoadArtifactPack",
Handler: _API_LoadArtifactPack_Handler,
},
{
MethodName: "SearchDocs",
Handler: _API_SearchDocs_Handler,
},
{
MethodName: "GetToolInfo",
Handler: _API_GetToolInfo_Handler,
+428
View File
@@ -0,0 +1,428 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: docs.proto
package proto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type DocSearchRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"`
Start int64 `protobuf:"varint,2,opt,name=start,proto3" json:"start,omitempty"`
Length int64 `protobuf:"varint,3,opt,name=length,proto3" json:"length,omitempty"`
}
func (x *DocSearchRequest) Reset() {
*x = DocSearchRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_docs_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DocSearchRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DocSearchRequest) ProtoMessage() {}
func (x *DocSearchRequest) ProtoReflect() protoreflect.Message {
mi := &file_docs_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DocSearchRequest.ProtoReflect.Descriptor instead.
func (*DocSearchRequest) Descriptor() ([]byte, []int) {
return file_docs_proto_rawDescGZIP(), []int{0}
}
func (x *DocSearchRequest) GetQuery() string {
if x != nil {
return x.Query
}
return ""
}
func (x *DocSearchRequest) GetStart() int64 {
if x != nil {
return x.Start
}
return 0
}
func (x *DocSearchRequest) GetLength() int64 {
if x != nil {
return x.Length
}
return 0
}
type Highlight struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Start uint64 `protobuf:"varint,1,opt,name=start,proto3" json:"start,omitempty"`
End uint64 `protobuf:"varint,2,opt,name=end,proto3" json:"end,omitempty"`
}
func (x *Highlight) Reset() {
*x = Highlight{}
if protoimpl.UnsafeEnabled {
mi := &file_docs_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Highlight) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Highlight) ProtoMessage() {}
func (x *Highlight) ProtoReflect() protoreflect.Message {
mi := &file_docs_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Highlight.ProtoReflect.Descriptor instead.
func (*Highlight) Descriptor() ([]byte, []int) {
return file_docs_proto_rawDescGZIP(), []int{1}
}
func (x *Highlight) GetStart() uint64 {
if x != nil {
return x.Start
}
return 0
}
func (x *Highlight) GetEnd() uint64 {
if x != nil {
return x.End
}
return 0
}
type DocSearchResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Link string `protobuf:"bytes,1,opt,name=link,proto3" json:"link,omitempty"`
Title string `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`
Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"`
Fragment string `protobuf:"bytes,4,opt,name=fragment,proto3" json:"fragment,omitempty"`
FullText string `protobuf:"bytes,5,opt,name=full_text,json=fullText,proto3" json:"full_text,omitempty"`
Highlights []*Highlight `protobuf:"bytes,6,rep,name=highlights,proto3" json:"highlights,omitempty"`
Tags []string `protobuf:"bytes,7,rep,name=tags,proto3" json:"tags,omitempty"`
}
func (x *DocSearchResponse) Reset() {
*x = DocSearchResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_docs_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DocSearchResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DocSearchResponse) ProtoMessage() {}
func (x *DocSearchResponse) ProtoReflect() protoreflect.Message {
mi := &file_docs_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DocSearchResponse.ProtoReflect.Descriptor instead.
func (*DocSearchResponse) Descriptor() ([]byte, []int) {
return file_docs_proto_rawDescGZIP(), []int{2}
}
func (x *DocSearchResponse) GetLink() string {
if x != nil {
return x.Link
}
return ""
}
func (x *DocSearchResponse) GetTitle() string {
if x != nil {
return x.Title
}
return ""
}
func (x *DocSearchResponse) GetType() string {
if x != nil {
return x.Type
}
return ""
}
func (x *DocSearchResponse) GetFragment() string {
if x != nil {
return x.Fragment
}
return ""
}
func (x *DocSearchResponse) GetFullText() string {
if x != nil {
return x.FullText
}
return ""
}
func (x *DocSearchResponse) GetHighlights() []*Highlight {
if x != nil {
return x.Highlights
}
return nil
}
func (x *DocSearchResponse) GetTags() []string {
if x != nil {
return x.Tags
}
return nil
}
type DocSearchResponses struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Total uint64 `protobuf:"varint,1,opt,name=total,proto3" json:"total,omitempty"`
Items []*DocSearchResponse `protobuf:"bytes,2,rep,name=Items,proto3" json:"Items,omitempty"`
}
func (x *DocSearchResponses) Reset() {
*x = DocSearchResponses{}
if protoimpl.UnsafeEnabled {
mi := &file_docs_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DocSearchResponses) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DocSearchResponses) ProtoMessage() {}
func (x *DocSearchResponses) ProtoReflect() protoreflect.Message {
mi := &file_docs_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DocSearchResponses.ProtoReflect.Descriptor instead.
func (*DocSearchResponses) Descriptor() ([]byte, []int) {
return file_docs_proto_rawDescGZIP(), []int{3}
}
func (x *DocSearchResponses) GetTotal() uint64 {
if x != nil {
return x.Total
}
return 0
}
func (x *DocSearchResponses) GetItems() []*DocSearchResponse {
if x != nil {
return x.Items
}
return nil
}
var File_docs_proto protoreflect.FileDescriptor
var file_docs_proto_rawDesc = []byte{
0x0a, 0x0a, 0x64, 0x6f, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x22, 0x56, 0x0a, 0x10, 0x44, 0x6f, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a,
0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x73, 0x74,
0x61, 0x72, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x18, 0x03, 0x20,
0x01, 0x28, 0x03, 0x52, 0x06, 0x6c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x22, 0x33, 0x0a, 0x09, 0x48,
0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72,
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10,
0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x03, 0x65, 0x6e, 0x64,
0x22, 0xd0, 0x01, 0x0a, 0x11, 0x44, 0x6f, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69,
0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x74, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x72, 0x61, 0x67, 0x6d, 0x65, 0x6e, 0x74,
0x12, 0x1b, 0x0a, 0x09, 0x66, 0x75, 0x6c, 0x6c, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20,
0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x75, 0x6c, 0x6c, 0x54, 0x65, 0x78, 0x74, 0x12, 0x30, 0x0a,
0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x48, 0x69, 0x67, 0x68, 0x6c, 0x69,
0x67, 0x68, 0x74, 0x52, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12,
0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74,
0x61, 0x67, 0x73, 0x22, 0x5a, 0x0a, 0x12, 0x44, 0x6f, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74,
0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12,
0x2e, 0x0a, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x44, 0x6f, 0x63, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68,
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x05, 0x49, 0x74, 0x65, 0x6d, 0x73, 0x42,
0x31, 0x5a, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x64, 0x65, 0x78,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x76, 0x65, 0x6c, 0x6f,
0x63, 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_docs_proto_rawDescOnce sync.Once
file_docs_proto_rawDescData = file_docs_proto_rawDesc
)
func file_docs_proto_rawDescGZIP() []byte {
file_docs_proto_rawDescOnce.Do(func() {
file_docs_proto_rawDescData = protoimpl.X.CompressGZIP(file_docs_proto_rawDescData)
})
return file_docs_proto_rawDescData
}
var file_docs_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_docs_proto_goTypes = []interface{}{
(*DocSearchRequest)(nil), // 0: proto.DocSearchRequest
(*Highlight)(nil), // 1: proto.Highlight
(*DocSearchResponse)(nil), // 2: proto.DocSearchResponse
(*DocSearchResponses)(nil), // 3: proto.DocSearchResponses
}
var file_docs_proto_depIdxs = []int32{
1, // 0: proto.DocSearchResponse.highlights:type_name -> proto.Highlight
2, // 1: proto.DocSearchResponses.Items:type_name -> proto.DocSearchResponse
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_docs_proto_init() }
func file_docs_proto_init() {
if File_docs_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_docs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DocSearchRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_docs_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Highlight); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_docs_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DocSearchResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_docs_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DocSearchResponses); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_docs_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_docs_proto_goTypes,
DependencyIndexes: file_docs_proto_depIdxs,
MessageInfos: file_docs_proto_msgTypes,
}.Build()
File_docs_proto = out.File
file_docs_proto_rawDesc = nil
file_docs_proto_goTypes = nil
file_docs_proto_depIdxs = nil
}
+32
View File
@@ -0,0 +1,32 @@
syntax = "proto3";
package proto;
option go_package = "www.velocidex.com/golang/velociraptor/api/proto";
message DocSearchRequest {
string query = 1;
int64 start = 2;
int64 length = 3;
}
message Highlight {
uint64 start = 1;
uint64 end = 2;
}
message DocSearchResponse {
string link = 1;
string title = 2;
string type = 3;
string fragment = 4;
string full_text = 5;
repeated Highlight highlights = 6;
repeated string tags = 7;
}
message DocSearchResponses {
uint64 total = 1;
repeated DocSearchResponse Items = 2;
}
@@ -39,3 +39,7 @@ tools:
url: https://github.com/Velocidex/velociraptor/releases/download/v<VERSION_BARE>/velociraptor-v<VERSION>-windows-386.msi
serve_locally: true
version: <VERSION>
- name: DocsIndex
url: https://docs.velociraptor.app/docs_index/docs_index_v1.zip
serve_locally: true
@@ -39,3 +39,7 @@ tools:
url: https://github.com/Velocidex/velociraptor/releases/download/v0.75/velociraptor-v0.75.6-windows-386.msi
serve_locally: true
version: 0.75.6
- name: DocsIndex
url: https://docs.velociraptor.app/docs_index/docs_index_v1.zip
serve_locally: true
+25 -7
View File
@@ -72,7 +72,7 @@ require (
golang.org/x/crypto v0.46.0
golang.org/x/mod v0.31.0
golang.org/x/net v0.48.0
golang.org/x/sys v0.39.0
golang.org/x/sys v0.40.0
golang.org/x/text v0.32.0
golang.org/x/time v0.14.0
google.golang.org/api v0.258.0
@@ -112,6 +112,7 @@ require (
github.com/Velocidex/ordereddict v0.0.0-20250821063524-02dc06e46238
github.com/Velocidex/sigma-go v0.0.0-20241113062227-c1c5ea4b5250
github.com/Velocidex/tracee_velociraptor v0.0.0-20260102153735-470363a4efa4
github.com/Velocidex/velociraptor-site-search v0.0.0-20260112074704-546a177e6dad
github.com/Velocidex/yara-x-go v0.0.0-20251010010632-d8eaad9c539c
github.com/VirusTotal/gyp v0.9.1-0.20231202132633-bb35dbf177a6
github.com/alecthomas/kingpin/v2 v2.4.0
@@ -122,6 +123,7 @@ require (
github.com/aws/aws-sdk-go-v2/credentials v1.17.6
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.8
github.com/aws/aws-sdk-go-v2/service/s3 v1.51.3
github.com/blevesearch/bleve v1.0.14
github.com/charmbracelet/huh v0.6.0
github.com/charmbracelet/lipgloss v1.0.0
github.com/clayscode/Go-Splunk-HTTP/splunk/v2 v2.0.1-0.20221027171526-76a36be4fa02
@@ -179,6 +181,7 @@ require (
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.54.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.54.0 // indirect
github.com/PuerkitoBio/goquery v1.8.1 // indirect
github.com/RoaringBitmap/roaring v1.9.4 // indirect
github.com/alecthomas/colour v0.1.0 // indirect
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20240927000941-0f3dac36c52b // indirect
@@ -203,6 +206,16 @@ require (
github.com/aymerick/douceur v0.2.0 // indirect
github.com/beevik/etree v1.1.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.24.4 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/mmap-go v1.0.4 // indirect
github.com/blevesearch/segment v0.9.1 // indirect
github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/zap/v11 v11.0.14 // indirect
github.com/blevesearch/zap/v12 v12.0.14 // indirect
github.com/blevesearch/zap/v13 v13.0.6 // indirect
github.com/blevesearch/zap/v14 v14.0.5 // indirect
github.com/blevesearch/zap/v15 v15.0.3 // indirect
github.com/bmatcuk/doublestar v1.3.4 // indirect
github.com/catppuccin/go v0.2.0 // indirect
github.com/cavaliergopher/cpio v1.0.1 // indirect
@@ -216,6 +229,7 @@ require (
github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 // indirect
github.com/couchbase/vellum v1.0.2 // indirect
github.com/crewjam/httperr v0.2.0 // indirect
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 // indirect
github.com/dlclark/regexp2 v1.7.0 // indirect
@@ -232,11 +246,11 @@ require (
github.com/go-jose/go-jose/v4 v4.1.3 // indirect
github.com/go-logr/logr v1.4.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-yaml v1.19.1 // indirect
github.com/goccy/go-yaml v1.19.2 // indirect
github.com/godzie44/go-uring v0.0.0-20220926161041-69611e8b13d5 // indirect
github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f // indirect
github.com/golang/glog v1.2.5 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/golang/snappy v1.0.0 // indirect
github.com/google/gopacket v1.1.19 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.7 // indirect
@@ -268,12 +282,13 @@ require (
github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect
github.com/nsf/termbox-go v1.1.1 // indirect
github.com/paulmach/orb v0.10.0 // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/philhofer/fwd v1.2.0 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
@@ -285,14 +300,17 @@ require (
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.7.1 // indirect
github.com/spiffe/go-spiffe/v2 v2.6.0 // indirect
github.com/steveyen/gtreap v0.1.0 // indirect
github.com/tidwall/btree v1.6.0 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/tinylib/msgp v1.6.3 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/ulikunitz/xz v0.5.15 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/willf/bitset v1.1.11 // indirect
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/bbolt v1.4.3 // indirect
go.mongodb.org/mongo-driver v1.12.1 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
@@ -353,12 +371,12 @@ require (
// replace github.com/Velocidex/go-ext4 => ../go-ext4
// replace github.com/Velocidex/amsi => ../amsi
// replace github.com/Velocidex/go-journalctl ../go-journalctl
// replace github.com/Velocidex/velociraptor-site-search => ../velociraptor-site-search
// Remove search for html end block. This allows inserting unbalanced
// HTML tags into the markdown
replace github.com/russross/blackfriday/v2 => github.com/Velocidex/blackfriday/v2 v2.0.2-0.20200811050547-4f26a09e2b3b
go 1.25
go 1.25.3
// Needed for syntax highlighting VQL. Removes extra fat.
replace github.com/alecthomas/chroma => github.com/Velocidex/chroma v0.6.8-0.20200418131129-82edc291369c
+105 -17
View File
@@ -71,6 +71,9 @@ github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBK
github.com/PuerkitoBio/goquery v1.7.1/go.mod h1:XY0pP4kfraEmmV1O7Uf6XyjoslwsneBbgeDjLYuN8xY=
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
github.com/RoaringBitmap/roaring v1.9.4 h1:yhEIoH4YezLYT04s1nHehNO64EKFTop/wBhxv2QzDdQ=
github.com/RoaringBitmap/roaring v1.9.4/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
github.com/Showmax/go-fqdn v1.0.0 h1:0rG5IbmVliNT5O19Mfuvna9LL7zlHyRfsSvBPZmF9tM=
github.com/Showmax/go-fqdn v1.0.0/go.mod h1:SfrFBzmDCtCGrnHhoDjuvFnKsWjEQX/Q9ARZvOrJAko=
github.com/Velocidex/WinPmem/go-winpmem v0.0.0-20251014141320-f59d776a3def h1:1FiSNT+Xh7UGohKsOoeDMkuw0gVyf6SUlnxeDbqiHPw=
@@ -128,6 +131,8 @@ github.com/Velocidex/tracee_velociraptor v0.0.0-20260102153735-470363a4efa4 h1:k
github.com/Velocidex/tracee_velociraptor v0.0.0-20260102153735-470363a4efa4/go.mod h1:nOb8af1ftRw8owHabTPNZ0R2X2WnPt6BftzQDRzVlxs=
github.com/Velocidex/ttlcache/v2 v2.9.1-0.20240517145123-a3f45e86e130 h1:+QujZ0D7KSy3WJVchkOhMkvAUab6/CIisO5LCoN48q4=
github.com/Velocidex/ttlcache/v2 v2.9.1-0.20240517145123-a3f45e86e130/go.mod h1:3/pI9BBAF7gydBWvMVtV7W1qRwshEG9lBwed/d8xfFg=
github.com/Velocidex/velociraptor-site-search v0.0.0-20260112074704-546a177e6dad h1:AE7V8khX6vG/5jN0BRPQFY73eAZ1kIrFqnMatTl7oUw=
github.com/Velocidex/velociraptor-site-search v0.0.0-20260112074704-546a177e6dad/go.mod h1:Uxx/8s068gjruUaKHvhfkXllL3dDbWenSc5VNfW0I1o=
github.com/Velocidex/yaml/v2 v2.2.8 h1:GUrSy4SBJ6RjGt43k6MeBKtw2z/27gh4A3hfFmFY3No=
github.com/Velocidex/yaml/v2 v2.2.8/go.mod h1:PlXIg/Pxmoja48C1vMHo7C5pauAZvLq/UEPOQ3DsjS4=
github.com/Velocidex/yara-x-go v0.0.0-20251010010632-d8eaad9c539c h1:3X4jyfzsTuOhiGaDXPu+WOrwRxDx2gk1akUdnpb4NHE=
@@ -176,6 +181,7 @@ github.com/aquasecurity/tracee/api v0.0.0-20251229080346-032e875eaa90 h1:7c1+tK0
github.com/aquasecurity/tracee/api v0.0.0-20251229080346-032e875eaa90/go.mod h1:51UhfaqeC9MU/kMMQYHnHvz4jEu9J7E3GC0UfSO6xxw=
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aws/aws-sdk-go-v2 v1.25.2 h1:/uiG1avJRgLGiQM9X3qJM8+Qa6KRGK5rRPuXE0HUM+w=
@@ -224,6 +230,34 @@ github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs=
github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE=
github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blevesearch/bleve v1.0.14 h1:Q8r+fHTt35jtGXJUM0ULwM3Tzg+MRfyai4ZkWDy2xO4=
github.com/blevesearch/bleve v1.0.14/go.mod h1:e/LJTr+E7EaoVdkQZTfoz7dt4KoDNvDbLb8MSKuNTLQ=
github.com/blevesearch/blevex v1.0.0 h1:pnilj2Qi3YSEGdWgLj1Pn9Io7ukfXPoQcpAI1Bv8n/o=
github.com/blevesearch/blevex v1.0.0/go.mod h1:2rNVqoG2BZI8t1/P1awgTKnGlx5MP9ZbtEciQaNhswc=
github.com/blevesearch/cld2 v0.0.0-20200327141045-8b5f551d37f5/go.mod h1:PN0QNTLs9+j1bKy3d/GB/59wsNBFC4sWLWG3k69lWbc=
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
github.com/blevesearch/mmap-go v1.0.2/go.mod h1:ol2qBqYaOUsGdm7aRMRrYGgPvnwLe6Y+7LMvAB5IbSA=
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
github.com/blevesearch/segment v0.9.0/go.mod h1:9PfHYUdQCgHktBgvtUOF4x+pc4/l8rdH0u5spnW85UQ=
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
github.com/blevesearch/zap/v11 v11.0.14 h1:IrDAvtlzDylh6H2QCmS0OGcN9Hpf6mISJlfKjcwJs7k=
github.com/blevesearch/zap/v11 v11.0.14/go.mod h1:MUEZh6VHGXv1PKx3WnCbdP404LGG2IZVa/L66pyFwnY=
github.com/blevesearch/zap/v12 v12.0.14 h1:2o9iRtl1xaRjsJ1xcqTyLX414qPAwykHNV7wNVmbp3w=
github.com/blevesearch/zap/v12 v12.0.14/go.mod h1:rOnuZOiMKPQj18AEKEHJxuI14236tTQ1ZJz4PAnWlUg=
github.com/blevesearch/zap/v13 v13.0.6 h1:r+VNSVImi9cBhTNNR+Kfl5uiGy8kIbb0JMz/h8r6+O4=
github.com/blevesearch/zap/v13 v13.0.6/go.mod h1:L89gsjdRKGyGrRN6nCpIScCvvkyxvmeDCwZRcjjPCrw=
github.com/blevesearch/zap/v14 v14.0.5 h1:NdcT+81Nvmp2zL+NhwSvGSLh7xNgGL8QRVZ67njR0NU=
github.com/blevesearch/zap/v14 v14.0.5/go.mod h1:bWe8S7tRrSBTIaZ6cLRbgNH4TUDaC9LZSpRGs85AsGY=
github.com/blevesearch/zap/v15 v15.0.3 h1:Ylj8Oe+mo0P25tr9iLPp33lN6d4qcztGjaIsP51UxaY=
github.com/blevesearch/zap/v15 v15.0.3/go.mod h1:iuwQrImsh1WjWJ0Ue2kBqY83a0rFtJTqfa9fp1rbVVU=
github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
@@ -267,13 +301,25 @@ github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsV
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5 h1:6xNmx7iTtyBRev0+D/Tv1FZd4SCg8axKApyNyRsAt/w=
github.com/cncf/xds/go v0.0.0-20251210132809-ee656c7534f5/go.mod h1:KdCmV+x/BuvyMxRnYBlmVaq4OLiKW6iRQfvC62cvdkI=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
github.com/coreos/go-oidc/v3 v3.11.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k=
github.com/couchbase/moss v0.1.0/go.mod h1:9MaHIaRuy9pvLPUJxB8sh8OrLfyDczECVL37grCIubs=
github.com/couchbase/vellum v1.0.2 h1:BrbP0NKiyDdndMPec8Jjhy0U47CZ0Lgx3xUC2r9rZqw=
github.com/couchbase/vellum v1.0.2/go.mod h1:FcwrEivFpNi24R3jLOs3n+fs5RnuQnQqCLBJ1uAg1W4=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/crewjam/httperr v0.2.0 h1:b2BfXR8U3AlIHwNeFFvZ+BV1LFvKLlzMjzaTnZMybNo=
github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3pglZ5oH4=
github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0h6pVabbcbyGRK1DckRn7r/STdZEeIDzZc=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9hchkHSWYkEqJwUGisez3G1QY8Ryz0sdWrLPMGjLk=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -318,6 +364,9 @@ github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c/go.mod h1:Yg+htXGokKKdzcwhuNDwVvN+uBxDGXJ7G/VN1d8fa64=
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052/go.mod h1:UbMTZqLaRiH3MsBH8va0n7s1pQYcu3uTb8G4tygF4Zg=
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4/go.mod h1:5tD+neXqOorC30/tWg0LCSkrqj/AR6gu8yY8/fpw1q0=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
@@ -333,6 +382,8 @@ github.com/gizak/termui/v3 v3.1.0 h1:ZZmVDgwHl7gR7elfKf1xc4IudXZ5qqfDh4wExk4Iajc
github.com/gizak/termui/v3 v3.1.0/go.mod h1:bXQEBkJpzxUAKf0+xq9MSWAvWZlE7c+aidmyFlkYTrY=
github.com/glaslos/tlsh v0.2.0 h1:9zr1gNyYCAMMsirzU5FFlUEEWp5hsrFE+B4LZEg8psk=
github.com/glaslos/tlsh v0.2.0/go.mod h1:S/OBGINihiGogV6WoaLeMY2UrS5Rl1iqMnplLonIOI4=
github.com/glycerine/go-unsnap-stream v0.0.0-20181221182339-f9677308dec2/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-jose/go-jose/v4 v4.1.3 h1:CVLmWDhDVRa6Mi/IgCgaopNosCaHz7zrMeF9MlZRkrs=
github.com/go-jose/go-jose/v4 v4.1.3/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08=
github.com/go-json-experiment/json v0.0.0-20250910080747-cc2cfa0554c3 h1:02WINGfSX5w0Mn+F28UyRoSt9uvMhKguwWMlOAh6U/0=
@@ -349,8 +400,8 @@ github.com/go-quicktest/qt v1.101.1-0.20240301121107-c6c8733fa1e6/go.mod h1:p4lG
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/goccy/go-yaml v1.19.1 h1:3rG3+v8pkhRqoQ/88NYNMHYVGYztCOCIZ7UQhu7H+NE=
github.com/goccy/go-yaml v1.19.1/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM=
github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
github.com/godzie44/go-uring v0.0.0-20220926161041-69611e8b13d5 h1:5zELAgnSz0gqmr4Q5DWCoOzNHoeBAxVUXB7LS1eG+sw=
github.com/godzie44/go-uring v0.0.0-20220926161041-69611e8b13d5/go.mod h1:ermjEDUoT/fS+3Ona5Vd6t6mZkw1eHp99ILO5jGRBkM=
github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
@@ -387,8 +438,8 @@ github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU=
github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -427,6 +478,7 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.7/go.mod h1:MkHOF77EYAE7
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.16.0 h1:iHbQmKLLZrexmb0OSsNGTeSTS0HO4YvFOG8g5E4Zd0Y=
github.com/googleapis/gax-go/v2 v2.16.0/go.mod h1:o1vfQjjNZn4+dPnRdl/4ZD7S9414Y4xA+a/6Icj6l14=
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/csrf v1.7.3 h1:BHWt6FTLZAb2HtWT5KDBf6qgpZzvtbp9QWDRKZMXJC0=
github.com/gorilla/csrf v1.7.3/go.mod h1:F1Fj3KG23WYHE6gozCmBAezKookxbIvUJT+121wTuLk=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
@@ -459,6 +511,7 @@ github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hillu/go-archive-zip-crypto v0.0.0-20200712202847-bd5cf365dd44 h1:seZZ+imS3iv6i0op0cqgt9K6BETRkXwUV9e8inrF+ws=
github.com/hillu/go-archive-zip-crypto v0.0.0-20200712202847-bd5cf365dd44/go.mod h1:xUc/S/HgVuP6lhDvD0Wqtu/Npwx93VSXzbdyEDbqBb8=
github.com/hillu/go-ntdll v0.0.0-20220801201350-0d23f057ef1f h1:es0IoL1/OOoGYUuvRtSzbtG3STd7Fm5LIniUWsfzMHE=
@@ -472,10 +525,12 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
github.com/ikawaha/kagome.ipadic v1.1.2/go.mod h1:DPSBbU0czaJhAb/5uKQZHMc9MTVRpDugJfX+HddPHHg=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jackwakefield/gopac v1.0.2 h1:TdHTGtC/kMc5kyYw7PEO5kqAHxcpuU4RFY4ztfg4nAM=
@@ -485,6 +540,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
@@ -492,6 +549,7 @@ github.com/josharian/native v1.1.0 h1:uuaP0hAbW7Y4l0ZRQ6C9zfb7Mg1mbFKry/xzDAfmtL
github.com/josharian/native v1.1.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/jsimonetti/rtnetlink/v2 v2.0.1 h1:xda7qaHDSVOsADNouv7ukSuicKZO7GgVUCXxpaIEIlM=
github.com/jsimonetti/rtnetlink/v2 v2.0.1/go.mod h1:7MoNYNbb3UaDHtF8udiJo/RH6VsTKP1pqKLUTVCvToE=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/ratelimit v1.0.1 h1:+7AIFJVQ0EQgq/K9+0Krm7m530Du7tIz0METWzN0RgY=
github.com/juju/ratelimit v1.0.1/go.mod h1:qapgC/Gy+xNh9UxzV13HGGl/6UXNN+ct+vwSgWNm/qk=
github.com/kaptinlin/go-i18n v0.2.0 h1:8iwjAERQbCVF78c3HxC4MxUDxDRFvQVQlMDvlsO43hU=
@@ -512,6 +570,7 @@ github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zt
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU=
github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kljensen/snowball v0.6.0/go.mod h1:27N7E8fVU5H68RlUmnWwZCfxgt4POBJfENGMvNRhldw=
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@@ -552,6 +611,7 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattermost/xml-roundtrip-validator v0.1.0 h1:RXbVD2UAl7A7nOTR4u7E3ILa4IbtvKBHw64LDsmu9hU=
github.com/mattermost/xml-roundtrip-validator v0.1.0/go.mod h1:qccnGMcpgwcNaBnxqpJpWWUiPNr5H3O8eDgGV9gT5To=
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@@ -591,12 +651,14 @@ github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgS
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4=
github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE=
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/panicwrap v1.0.0 h1:67zIyVakCIvcs69A0FGfZjBdPleaonSgGlXRSRlb6fE=
github.com/mitchellh/panicwrap v1.0.0/go.mod h1:pKvZHwWrZowLUzftuFq7coarnxbBXU4aQh3N0BJOeeA=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@@ -609,6 +671,9 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/mooijtech/go-pst/v6 v6.0.2 h1:mXzOgcSZ30UPuCWpz4DAQCTm0ttOmiejOuF/CN32C2Q=
github.com/mooijtech/go-pst/v6 v6.0.2/go.mod h1:pF4o5rQwF33uLJQ0c+CZICeK4GwcKTpGVq6yVOHrvkY=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
@@ -632,12 +697,14 @@ github.com/paulmach/orb v0.1.5/go.mod h1:pPwxxs3zoAyosNSbNKn1jiXV2+oovRDObDKfTvR
github.com/paulmach/orb v0.10.0 h1:guVYVqzxHE/CQ1KpfGO077TR0ATHSNjp4s6XGLn3W9s=
github.com/paulmach/orb v0.10.0/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29 h1:6P7XZEBu/ZWizC/liUX4UYm4nEAACofmSkOzY39RBxM=
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@@ -664,6 +731,8 @@ github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJf
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/qri-io/starlib v0.5.0 h1:NlveoBAhO6mNgM7+JpM9QlHh3/3pOtOiH6iXaqSdVK0=
github.com/qri-io/starlib v0.5.0/go.mod h1:FpVumyB2CMrKIrjf39fAi4uydYWVvnWEvXEOwfzZRHY=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5 h1:mZHayPoR0lNmnHyvtYjDeq0zlVHn9K/ZXoy17ylucdo=
github.com/rifflock/lfshook v0.0.0-20180920164130-b9218ef580f5/go.mod h1:GEXHk5HgEKCvEIIrSpFI3ozzG5xOKA2DVlEX/gGnewM=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
@@ -681,6 +750,7 @@ github.com/rotisserie/eris v0.5.4 h1:Il6IvLdAapsMhvuOahHWiBnl1G++Q0/L5UIkI5mARSk
github.com/rotisserie/eris v0.5.4/go.mod h1:Z/kgYTJiJtocxCbFfvRmO+QejApzG6zpyky9G1A4g9s=
github.com/russellhaering/goxmldsig v1.3.0 h1:DllIWUgMy0cRUMfGiASiYEa35nsieyD3cigIwLonTPM=
github.com/russellhaering/goxmldsig v1.3.0/go.mod h1:gM4MDENBQf7M+V824SGfyIUVFWydB7n0KkEubVJl+Tw=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/sebdah/goldie v1.0.0 h1:9GNhIat69MSlz/ndaBg48vl9dF5fI+NBB6kfOxgfkMc=
github.com/sebdah/goldie v1.0.0/go.mod h1:jXP4hmWywNEwZzhMuv2ccnqTSFpuq8iyQhtQdkkZBH4=
@@ -700,15 +770,23 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spiffe/go-spiffe/v2 v2.6.0 h1:l+DolpxNWYgruGQVV0xsfeya3CsC7m8iBzDnMpsbLuo=
github.com/spiffe/go-spiffe/v2 v2.6.0/go.mod h1:gm2SeUoMZEtpnzPNs2Csc0D/gX33k1xIx7lEzqblHEs=
github.com/steveyen/gtreap v0.1.0 h1:CjhzTa274PyJLJuMZwIzCO1PfC00oRa8d1Kc78bFXJM=
github.com/steveyen/gtreap v0.1.0/go.mod h1:kl/5J7XbrOmlIbYIXdRHDDE5QxHqpk0cmkT7Z4dM9/Y=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
@@ -731,15 +809,20 @@ github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tebeka/snowball v0.4.2/go.mod h1:4IfL14h1lvwZcp1sfXuuc7/7yCsvVffTWxWxCLfFpYg=
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c h1:g+WoO5jjkqGAzHWCjJB1zZfXPIAaDpzXIEJ0eS6B5Ok=
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
github.com/tidwall/btree v1.6.0 h1:LDZfKfQIBHGHWSwckhXI0RPSXzlo+KYdjK7FWSqOzzg=
github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EUQ2cKY=
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s=
github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY=
github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
@@ -753,6 +836,9 @@ github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8A
github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U=
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459 h1:x9pIfbdIjnw+Ylb2vE27Gtqb7BDmfR+nLcJwvbJh98U=
github.com/virtuald/go-paniclog v0.0.0-20190812204905-43a7fa316459/go.mod h1:nFvuG3SWu3VWqobG3cX8nt57wXU0OOFapeCs/8axIuM=
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bitset v1.1.11 h1:N7Z7E9UvjW+sGsEl7k/SJrvY2reP1A07MrGuCjIOjRE=
github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
@@ -764,6 +850,7 @@ github.com/xor-gate/ar v0.0.0-20170530204233-5c72ae81e2b7 h1:Vo3q7h44BfmnLQh5SdF
github.com/xor-gate/ar v0.0.0-20170530204233-5c72ae81e2b7/go.mod h1:TCWCUPhQU1j7axqROa/VHnlgJGHthAOqJZahg7b/DUc=
github.com/xor-gate/debpkg v1.0.0 h1:yopCuVtQ0Xd843qItHj2MxEeekZuTCNkI646wyvE1wY=
github.com/xor-gate/debpkg v1.0.0/go.mod h1:EuBN56P7is1flqkYoKve4T7vi0hod1dHoshBctTtce4=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -774,6 +861,9 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.einride.tech/aip v0.73.0 h1:bPo4oqBo2ZQeBKo4ZzLb1kxYXTY1ysJhpvQyfuGzvps=
go.einride.tech/aip v0.73.0/go.mod h1:Mj7rFbmXEgw0dq1dqJ7JGMvYCZZVxmGOR3S4ZcV5LvQ=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
go.mongodb.org/mongo-driver v1.12.1 h1:nLkghSU8fQNaK7oUmDhQFsnrtcoNy7Z6LVFKsEecqgE=
go.mongodb.org/mongo-driver v1.12.1/go.mod h1:/rGBTebI3XYboVmgz+Wv3Bcbl3aD0QF9zl6kDDw18rQ=
@@ -814,6 +904,7 @@ go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg=
golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A=
golang.org/x/crypto v0.0.0-20170808112155-b176d7def5d7/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
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-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -842,7 +933,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
@@ -868,7 +958,6 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
@@ -893,6 +982,8 @@ golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181221143128-b4a75ba826a6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -901,6 +992,7 @@ golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191224085550-c709ea063b76/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -918,18 +1010,16 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ=
golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
@@ -941,7 +1031,6 @@ 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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
@@ -965,7 +1054,6 @@ golang.org/x/tools v0.0.0-20210112230658-8b4aab62c064/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
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=
+17 -2
View File
@@ -15,7 +15,7 @@
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "0.2.6",
"@popperjs/core": "^2.11.8",
"ace-builds": "^1.43.5",
"ace-builds": "1.43.5",
"axios": ">=1.13.2",
"axios-retry": "3.9.1",
"bootstrap": "5.3.8",
@@ -24,6 +24,7 @@
"csv-stringify": "5.6.5",
"dompurify": "3.3.0",
"env-cmd": "^10.1.0",
"highlight.js": "11.11.1",
"hosted-git-info": "^2.8.9",
"html-react-parser": "^0.14.3",
"http-proxy-middleware": "^2.0.9",
@@ -54,7 +55,7 @@
"recharts": "^2.15.4",
"sprintf-js": "1.1.3",
"url-parse": "^1.5.10",
"webpack": "^5.103.0"
"webpack": "5.103.0"
},
"devDependencies": {
"@babel/core": "^7.25.2",
@@ -8691,6 +8692,15 @@
"node": ">= 0.4"
}
},
"node_modules/highlight.js": {
"version": "11.11.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=12.0.0"
}
},
"node_modules/history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
@@ -21618,6 +21628,11 @@
"function-bind": "^1.1.2"
}
},
"highlight.js": {
"version": "11.11.1",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.11.1.tgz",
"integrity": "sha512-Xwwo44whKBVCYoliBQwaPvtd/2tYFkRQtXDWj1nackaV2JPXx3L0+Jvd8/qCJ2p+ML0/XVkJ2q+Mr+UVdpJK5w=="
},
"history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
+2 -1
View File
@@ -10,8 +10,8 @@
"@fortawesome/free-solid-svg-icons": "^6.7.2",
"@fortawesome/react-fontawesome": "0.2.6",
"@popperjs/core": "^2.11.8",
"axios": ">=1.13.2",
"ace-builds": "1.43.5",
"axios": ">=1.13.2",
"axios-retry": "3.9.1",
"bootstrap": "5.3.8",
"classnames": "^2.5.1",
@@ -19,6 +19,7 @@
"csv-stringify": "5.6.5",
"dompurify": "3.3.0",
"env-cmd": "^10.1.0",
"highlight.js": "11.11.1",
"hosted-git-info": "^2.8.9",
"html-react-parser": "^0.14.3",
"http-proxy-middleware": "^2.0.9",
+6 -1
View File
@@ -8,6 +8,7 @@ import VeloNavigator from './components/sidebar/navigator.jsx';
import GlobalMessages from './components/users/global-messages.jsx';
import VeloClientSearch from './components/clients/search.jsx';
import VeloClientList from './components/clients/clients-list.jsx';
import DocButton from './components/docs/doc-button.jsx';
import VeloHostInfo from './components/clients/host-info.jsx';
import ServerInfo from './components/server/server-info.jsx';
import ClientSetterFromRoute from './components/clients/client_info.jsx';
@@ -37,6 +38,7 @@ import { UserSettings } from './components/core/user.jsx';
import { Switch, Route, withRouter } from "react-router-dom";
import { Join } from './components/utils/paths.jsx';
import SecretManager from './components/secrets/secrets.jsx';
import ButtonGroup from 'react-bootstrap/ButtonGroup';
import Navbar from 'react-bootstrap/Navbar';
import Nav from 'react-bootstrap/Nav';
@@ -226,7 +228,10 @@ class App extends Component {
</div>
<Navbar fixed="bottom" className="app-footer justify-content-between ">
<Nav>
<GlobalMessages/>
<ButtonGroup>
<GlobalMessages/>
<DocButton />
</ButtonGroup>
</Nav>
<Nav>
<VeloLiveClock className="float-right" />
@@ -4,6 +4,7 @@ import _ from 'lodash';
import React from 'react';
import PropTypes from 'prop-types';
import {CancelToken} from 'axios';
import { cleanupHTML } from '../core/sanitize.jsx';
import parseHTML from '../core/sanitize.jsx';
import api from '../core/api-service.jsx';
@@ -131,25 +132,8 @@ export default class VeloReportViewer extends React.Component {
});
}
cleanupHTML = (html) => {
// React expect no whitespace between table elements
html = html.replace(/>\s*<thead/g, "><thead");
html = html.replace(/>\s*<tbody/g, "><tbody");
html = html.replace(/>\s*<tr/g, "><tr");
html = html.replace(/>\s*<th/g, "><th");
html = html.replace(/>\s*<td/g, "><td");
html = html.replace(/>\s*<\/thead/g, "></thead");
html = html.replace(/>\s*<\/tbody/g, "></tbody");
html = html.replace(/>\s*<\/tr/g, "></tr");
html = html.replace(/>\s*<\/th/g, "></th");
html = html.replace(/>\s*<\/td/g, "></td");
return html;
}
render() {
let template = parseHTML(this.cleanupHTML(this.state.template), {
let template = parseHTML(cleanupHTML(this.state.template), {
replace: (domNode) => {
if (domNode.name === "velo-csv-viewer") {
try {
@@ -9,6 +9,7 @@ import DOMPurify from 'dompurify';
export function sanitize(html) {
let clean = DOMPurify.sanitize(html, {
USE_PROFILES: { html: true },
// Line up with NewBlueMondayPolicy() in reporting/gui.go
CUSTOM_ELEMENT_HANDLING: {
@@ -23,6 +24,25 @@ export function sanitize(html) {
return clean;
}
export function cleanupHTML(html) {
// React expect no whitespace between table elements
html = html.replace(/>\s*<thead/g, "><thead");
html = html.replace(/>\s*<tbody/g, "><tbody");
html = html.replace(/>\s*<tr/g, "><tr");
html = html.replace(/>\s*<th/g, "><th");
html = html.replace(/>\s*<td/g, "><td");
html = html.replace(/>\s*<\/thead/g, "></thead");
html = html.replace(/>\s*<\/tbody/g, "></tbody");
html = html.replace(/>\s*<\/tr/g, "></tr");
html = html.replace(/>\s*<\/th/g, "></th");
html = html.replace(/>\s*<\/td/g, "></td");
return html;
};
export default function parseHTML(html, options) {
html = cleanupHTML(html);
return parse(sanitize(html), options);
}
@@ -0,0 +1,236 @@
import _ from 'lodash';
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import api from '../core/api-service.jsx';
import Button from 'react-bootstrap/Button';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Modal from 'react-bootstrap/Modal';
import Form from 'react-bootstrap/Form';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import T from '../i8n/i8n.jsx';
import {CancelToken} from 'axios';
import Alert from 'react-bootstrap/Alert';
import Accordion from 'react-bootstrap/Accordion';
import Badge from 'react-bootstrap/Badge';
import parseHTML from '../core/sanitize.jsx';
import { cleanupHTML } from '../core/sanitize.jsx';
import hljs from 'highlight.js';
import ToolViewer from '../tools/tool-viewer.jsx';
import markdownit from 'markdown-it';
import { TablePaginationControl } from '../core/paged-table.jsx';
import InputGroup from 'react-bootstrap/InputGroup';
import "./docs.css";
class HelpDialog extends Component {
static propTypes = {
onClose: PropTypes.func.isRequired,
}
state = {
query: "",
hits: [],
error: "",
total_size: 0,
start: 0,
page_size: 10,
}
componentDidMount = () => {
this.source = CancelToken.source();
}
componentWillUnmount = () => {
this.source.cancel();
}
componentDidUpdate = (prevProps, prevState, rootNode) => {
if(prevState.query != this.state.query ||
prevState.start != this.state.start ||
prevState.page_size != this.state.page_size) {
this.updateSearch();
}
}
updateSearch = ()=>{
api.get("v1/SearchDocs", {
query: this.state.query,
start: this.state.start,
length: this.state.page_size,
}, this.source.token).then(response=>{
if (response.cancel)
return;
let data = response && response.data;
let items = data && data.Items;
let total_size = data && data.total;
this.setState({error: "",
total_size: parseInt(total_size || 0) ,
hits: items || []});
}).catch(response=>{
let error = response && response.response &&
response.response.data && response.response.data.message;
this.setState({error: error});
return false;
});
}
highlight = (text, highlights)=>{
if(!highlights) {
return text;
}
let res = [];
let offset = 0;
let text_len = text.length;
for(let i=0;i<highlights.length;i++) {
let h = highlights[i];
let start = parseInt(h.start);
let end = parseInt(h.end);
if(start > text_len) {
break;
}
if(start > offset) {
res.push(text.slice(offset, start));
}
res.push("<span class='highlight'>" + text.slice(start, end) + "</span>");
offset = end;
}
if(offset < text_len) {
res.push(text.slice(offset, text_len));
}
return res.join("");
}
searchTag = tag=>{
this.setState({query: "tags:" + tag + " " + this.state.query});
}
renderTags = tags=>{
return _.map(tags, (x, idx)=>{
return <Badge
onClick={()=>this.searchTag(x)}
className="tag"
key={idx}>{x}</Badge>;
});
}
sanitize = text=>{
return parseHTML(text);
}
render() {
const md = markdownit({
html: true,
linkify: false,
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(str, { language: lang }).value;
} catch (__) {}
}
return ''; // use external default escaping
}
});
return (
<Modal show={true}
dialogClassName="modal-90w"
onHide={this.props.onClose}>
<Modal.Header closeButton>
<Modal.Title>{T("Search Documentation")}</Modal.Title>
</Modal.Header>
<Modal.Body className="search-hit">
<Form>
<InputGroup>
<Form.Control
spellCheck="false"
value={this.state.query}
onChange={e=>this.setState({query: e.target.value})}
as="input"
placeholder={T("Search Docs")} />
<TablePaginationControl
total_size={this.state.total_size}
start_row={this.state.start}
page_size={this.state.page_size}
current_page={this.state.start_row / this.state.page_size}
onRowChange={row_offset=>{
this.setState({start: row_offset});
}}
onPageSizeChange={size=>this.setState({page_size: size})}
/>
</InputGroup>
</Form>
<Accordion>
{_.map(this.state.hits, (v, idx)=>{
let full_text = this.highlight(v.full_text, v.highlights);
full_text = md.render(full_text || "");
return <Accordion.Item eventKey={idx} key={idx}>
<Accordion.Header>
<Row className="hit-row">
<Col sm="2">{this.renderTags(v.tags)}</Col>
<Col sm="10">
<a target="_blank" href={v.link}>
{v.title}
</a>
</Col>
</Row>
</Accordion.Header>
<Accordion.Body>
{this.sanitize(full_text)}
</Accordion.Body>
</Accordion.Item>;
})}
</Accordion>
</Modal.Body>
<Modal.Footer>
{ this.state.error &&
<Alert className="doc-error-bar"
variant="warning">{this.state.error}</Alert>
}
<ToolViewer key="3" name="DocsIndex" />
<Button variant="secondary"
onClick={()=>this.props.onClose()}>
{T("Close")}
</Button>
</Modal.Footer>
</Modal>
);
}
}
export default class DocButton extends Component {
state = {
show_dialog: false,
}
render() {
return (
<>
<Button
variant="primary"
className="help-button"
onClick={()=>this.setState({show_dialog: true})}
>
<FontAwesomeIcon icon="circle-question" />
</Button>
{ this.state.show_dialog &&
<HelpDialog
onClose={()=>this.setState({show_dialog: false})}
/> }
</>
);
}
}
@@ -0,0 +1,203 @@
.btn.help-button {
margin-top: 5px;
}
.doc-error-bar {
width: 100%;
}
.highlight {
background: var(--hex-highlight-background);
color: var(--hex-highlight-foreground);
}
.accordion-body img {
width: 100%;
}
.tag.bg-primary {
background-color: var(--accent-color) !important;
margin-left: 2px;
margin-right: 2px;
margin-top: 2px;
}
.tags-container {
width: 200px;
}
.hit-row {
width: 100%;
}
.vql_type {
background-color: var(--color-accent-50);
padding: 5px;
border-radius: 10px;
}
.search-hit pre {
border-color: var(--color-btn-default-border);
border-width: 2px;
border-style: solid;
padding: 2px;
}
.permission_list {
color: var(--color-level-error);
padding-left: 10px;
margin-top: 10px;
}
.search-hit thead {
border-bottom-style: solid;
border-bottom-width: 2px;
}
.search-hit td {
padding: 5px;
}
pre code.hljs {
display: block;
overflow-x: auto;
padding: 1em;
}
code.hljs {
padding: 3px 5px;
}
.hljs {
color: var(--hljs-color);
background: var(--hljs-background);
}
.hljs ::selection {
color: var(--hljs-color-selection);
}
/* purposely do not highlight these things */
.hljs-formula,
.hljs-params,
.hljs-property
{}
/* base03 - #808080 - Comments, Invisibles, Line Highlighting */
.hljs-comment {
color: var(--hljs-comment);
}
/* base04 - #808080 - Dark Foreground (Used for status bars) */
.hljs-tag {
color: var(--hljs-comment);
}
/* base05 - #404040 - Default Foreground, Caret, Delimiters, Operators */
.hljs-subst,
.hljs-punctuation,
.hljs-operator {
color: var(--hljs-color);
}
.hljs-operator {
opacity: 0.7;
}
/* base08 - Variables, XML Tags, Markup Link Text, Markup Lists, Diff Deleted */
.hljs-bullet,
.hljs-variable,
.hljs-template-variable,
.hljs-selector-tag,
.hljs-name,
.hljs-deletion {
color: var(--hljs-name);
}
/* base09 - Integers, Boolean, Constants, XML Attributes, Markup Link Url */
.hljs-symbol,
.hljs-number,
.hljs-link,
.hljs-attr,
.hljs-variable.constant_,
.hljs-literal {
color: var(--hljs-literal);
}
/* base0A - Classes, Markup Bold, Search Text Background */
.hljs-title,
.hljs-class .hljs-title,
.hljs-title.class_
{
color: var(--hljs-title);
}
.hljs-strong {
font-weight:bold;
color: var(--hljs-title);
}
/* base0B - Strings, Inherited Class, Markup Code, Diff Inserted */
.hljs-code,
.hljs-addition,
.hljs-title.class_.inherited__,
.hljs-string {
color: var(--hljs-code);
}
/* base0C - Support, Regular Expressions, Escape Characters, Markup Quotes */
.hljs-built_in,
.hljs-doctag, /* guessing */
.hljs-quote,
.hljs-keyword.hljs-atrule,
.hljs-regexp {
color: var(--hljs-quote);
}
/* base0D - Functions, Methods, Attribute IDs, Headings */
.hljs-function .hljs-title,
.hljs-attribute,
.ruby .hljs-property,
.hljs-title.function_,
.hljs-section {
color: var(--hljs-func);
}
/* base0E - Keywords, Storage, Selector, Markup Italic, Diff Changed */
.hljs-type,
/* .hljs-selector-id, */
/* .hljs-selector-class, */
/* .hljs-selector-attr, */
/* .hljs-selector-pseudo, */
.hljs-template-tag,
.diff .hljs-meta,
.hljs-keyword {
color: var(--hljs-keyword);
}
.hljs-emphasis {
color: var(--hljs-keyword);
font-style: italic;
}
/* base0F - Deprecated, Opening/Closing Embedded Language Tags, e.g. <?php ?> */
.hljs-meta,
/*
prevent top level .keyword and .string scopes
from leaking into meta by accident
*/
.hljs-meta .hljs-keyword,
.hljs-meta .hljs-string
{
color: var(--hljs-title);
}
.hljs-meta .hljs-keyword,
/* for v10 compatible themes */
.hljs-meta-keyword {
font-weight: bold;
}
+12
View File
@@ -92,4 +92,16 @@
--hex-highlight-foreground: var(--color-canvas-background);
--invalid-form-control-error: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
--hljs-color: #404040;
--hljs-background: #ffffff;
--hljs-color-selection: #c0c0c0;
--hljs-comment: #808080;
--hljs-name: #c41a15;
--hljs-literal: #eb8500;
--hljs-title: #826b28;
--hljs-code: #007400;
--hljs-quote: #318495;
--hljs-func: #0000ff;
--hljs-keyword: #a90d91;
}
+4 -3
View File
@@ -28,7 +28,7 @@ import { faHome, faCrosshairs, faWrench, faEye, faServer, faBook, faLaptop,
faCircleExclamation, faTable, faHouse, faRotateLeft, faRotateRight,
faChevronRight, faEllipsis, faLayerGroup, faBullseye, faPersonRunning,
faQuestion, faCalendarPlus, faForwardFast, faBackwardFast, faSliders,
faRepeat, faBorderAll, faBell,
faRepeat, faBorderAll, faBell, faCircleQuestion,
} from '@fortawesome/free-solid-svg-icons';
import { faSquare, faSquareCheck, faSquareMinus,
@@ -52,8 +52,9 @@ library.add(faHome, faCrosshairs, faWrench, faEye, faServer, faBook, faLaptop,
faArrowsUpDown, faBan, faFileExport, faCircleExclamation,
faTable, faHouse, faRotateLeft, faRotateRight, faChevronRight,
faEllipsis, faLayerGroup, faBullseye, faPersonRunning, faQuestion,
faCalendarPlus, faForwardFast, faBackwardFast, faSquareCheck, faSquare,
faSquareMinus, faSliders, faRepeat, faBorderAll, faBell,
faCalendarPlus, faForwardFast, faBackwardFast, faSquareCheck,
faSquare, faSquareMinus, faSliders, faRepeat, faBorderAll, faBell,
faCircleQuestion
);
ReactDOM.render(
@@ -115,6 +115,9 @@
--color-level-error: #ff0000;
--invalid-form-control-error: #ff0000;
--color-danger-emphasis: #dd4b3920;
--hljs-color: #FFFFFF;
--hljs-comment: #4EC9B0;
}
body.coolgray-dark {
@@ -129,6 +129,10 @@
--color-level-error: #aa0000;
--invalid-form-control-error: #aa0000;
--hljs-color: #FFFFFF;
--hljs-comment: #4EC9B0;
--hljs-keyword: #2aabd2;
}
body.github-dimmed-dark {
+3 -1
View File
@@ -36,7 +36,7 @@
--accent-color: red;
--color-accent: 135, 184, 221;
--color-accent-complement: blue;
--color-accent-100: #ff0000;
--color-accent-100: #ffffffff;
--color-accent-75: #BF0000;
--color-accent-50: #800000;
--color-accent-25: #400000;
@@ -117,6 +117,8 @@
--color-danger-emphasis: #dd4b3920;
--invalid-form-control-error: #ff7f00;
}
.midnight img.velo-logo {
@@ -102,6 +102,9 @@
--color-level-error: #ef5350;
--invalid-form-control-error: #ff6666;
--hljs-color: #FFFFFF;
--hljs-comment: #4EC9B0;
}
body.ncurses-dark {
@@ -131,6 +131,9 @@
--color-level-error: #ff0000;
--invalid-form-control-error: #3f0505;
--hljs-color: #FFFFFF;
--hljs-comment: #4EC9B0;
}
body.veloci-dark {
@@ -143,6 +143,9 @@
--hex-highlight-foreground: #FFFFFF;
--invalid-form-control-error: #5A1D1D;
--hljs-color: #FFFFFF;
--hljs-comment: #4EC9B0;
}
body.vscode-dark {
-1
View File
@@ -111,7 +111,6 @@ func InitLogging(config_obj *config_proto.Config) error {
for _, component := range components {
logger, err := new_manager.makeNewComponent(config_obj, component)
if err != nil {
mu.Unlock()
return err
}
new_manager.contexts[component] = logger
+21
View File
@@ -0,0 +1,21 @@
package paths
import "www.velocidex.com/golang/velociraptor/file_store/api"
type DocsIndexPathManager struct{}
func (self DocsIndexPathManager) Metadata() api.FSPathSpec {
return CONFIG_ROOT.AsFilestorePath().
AddChild("docs", "index_meta.json").
SetType(api.PATH_TYPE_FILESTORE_ANY)
}
func (self DocsIndexPathManager) Index() api.FSPathSpec {
return CONFIG_ROOT.AsFilestorePath().
AddChild("docs").
SetType(api.PATH_TYPE_FILESTORE_ANY)
}
func NewDocsIndexPathManager() *DocsIndexPathManager {
return &DocsIndexPathManager{}
}
+23
View File
@@ -0,0 +1,23 @@
package services
import (
"context"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
config_proto "www.velocidex.com/golang/velociraptor/config/proto"
)
func GetDocManager(config_obj *config_proto.Config) (DocManager, error) {
org_manager, err := GetOrgManager()
if err != nil {
return nil, err
}
return org_manager.Services(config_obj.OrgId).DocManager()
}
// The doc manager is responsible for searching documentation.
type DocManager interface {
Search(ctx context.Context,
query string, start, len int) (*api_proto.DocSearchResponses, error)
}
+162
View File
@@ -0,0 +1,162 @@
package docs
import (
"archive/zip"
"context"
"github.com/Velocidex/velociraptor-site-search/api"
"www.velocidex.com/golang/velociraptor/datastore"
"www.velocidex.com/golang/velociraptor/file_store"
fs_api "www.velocidex.com/golang/velociraptor/file_store/api"
"www.velocidex.com/golang/velociraptor/logging"
"www.velocidex.com/golang/velociraptor/paths"
"www.velocidex.com/golang/velociraptor/services"
"www.velocidex.com/golang/velociraptor/utils"
)
func (self *DocManager) getInventoryStat(ctx context.Context) (fs_api.FileInfo, error) {
inventory_service, err := services.GetInventory(self.config_obj)
if err != nil {
return nil, err
}
// Materialize the tool because we need to check it's timestamp
tool, err := inventory_service.GetToolInfo(ctx, self.config_obj,
"DocsIndex", "")
if err != nil {
return nil, err
}
path_manager := paths.NewInventoryPathManager(self.config_obj, tool)
path, file_store_factory, err := path_manager.Path()
if err != nil {
return nil, err
}
return file_store_factory.StatFile(path)
}
func (self *DocManager) shouldUnpackTool(ctx context.Context) (
inventory_path, index_path fs_api.FSPathSpec, unpack bool, err error) {
// Check the index on disk
path_manager := paths.NewDocsIndexPathManager()
file_store_factory := file_store.GetFileStore(self.config_obj)
existing_stat, err := file_store_factory.StatFile(
path_manager.Metadata())
if err != nil {
// Index does not exist, we need to unpack it.
inv_stat, err := self.getInventoryStat(ctx)
if err != nil {
return nil, nil, true, err
}
return inv_stat.PathSpec(), path_manager.Index(), true, nil
}
// Index exists, we need to see if it is newer than the inventory
// one.
inv_stat, err := self.getInventoryStat(ctx)
if err != nil {
// We can not access the inventory for some reason, this is an
// error.
return nil, nil, true, err
}
// The existing index is later than the inventory file, we do not
// need to refresh it.
if existing_stat.ModTime().After(inv_stat.ModTime()) {
logging.GetLogger(self.config_obj, &logging.GUIComponent).
Info("<green>Docs Manager</>: Loading existing index")
return inv_stat.PathSpec(), path_manager.Index(), false, nil
}
// We need to unpack the index.
logging.GetLogger(self.config_obj, &logging.GUIComponent).
Info("<green>Docs Manager</>: Existing index is too old, unpacking index from inventory")
return inv_stat.PathSpec(), path_manager.Index(), true, nil
}
func (self *DocManager) unpackIndex(
ctx context.Context,
inventory_path, index_path fs_api.FSPathSpec) error {
file_store_factory := file_store.GetFileStore(self.config_obj)
reader, err := file_store_factory.ReadFile(inventory_path)
if err != nil {
return err
}
defer reader.Close()
stat, err := reader.Stat()
if err != nil {
return err
}
zipfd, err := zip.NewReader(utils.MakeReaderAtter(reader), stat.Size())
if err != nil {
return err
}
for _, file := range zipfd.File {
fd, err := file.Open()
if err != nil {
return err
}
w, err := file_store_factory.WriteFile(
index_path.AddUnsafeChild(file.Name))
if err != nil {
return err
}
w.Truncate()
_, err = utils.Copy(ctx, w, fd)
if err != nil {
return err
}
w.Close()
}
return nil
}
// Gets a working index. If the index does not exist in the file
// store, we use the inventory service to fetch it.
func (self *DocManager) GetIndex(ctx context.Context) (res api.Index, err error) {
self.mu.Lock()
defer self.mu.Unlock()
if self.index != nil {
return self.index, nil
}
inventory_path, index_path, unpack, err := self.shouldUnpackTool(ctx)
if err != nil {
return nil, err
}
if unpack {
err = self.unpackIndex(ctx, inventory_path, index_path)
if err != nil {
return nil, err
}
}
db, err := datastore.GetDB(self.config_obj)
if err != nil {
return nil, err
}
// The raw underlying filename on disk.
raw_filename := datastore.AsFilestoreFilename(
db, self.config_obj, index_path)
index, err := api.OpenIndex(raw_filename)
if err != nil {
return nil, err
}
self.index = index
return index, err
}
+103
View File
@@ -0,0 +1,103 @@
package docs
import (
"context"
"sync"
"github.com/Velocidex/velociraptor-site-search/api"
"github.com/blevesearch/bleve"
api_proto "www.velocidex.com/golang/velociraptor/api/proto"
config_proto "www.velocidex.com/golang/velociraptor/config/proto"
"www.velocidex.com/golang/velociraptor/services"
"www.velocidex.com/golang/velociraptor/utils"
)
type DocManager struct {
mu sync.Mutex
config_obj *config_proto.Config
index api.Index
}
func (self *DocManager) Search(
ctx context.Context,
query_str string, start, len int) (*api_proto.DocSearchResponses, error) {
index, err := self.GetIndex(ctx)
if err != nil {
return nil, err
}
query := bleve.NewQueryStringQuery(query_str)
searchRequest := bleve.NewSearchRequest(query)
searchRequest.Fields = []string{"title", "text", "url", "tags", "rank"}
searchRequest.Highlight = bleve.NewHighlight()
searchRequest.From = start
searchRequest.Size = len
searchRequest.SortBy([]string{"-rank", "-_score"})
searchResult, err := index.Search(searchRequest)
if err != nil {
return nil, err
}
res := &api_proto.DocSearchResponses{
Total: searchResult.Total,
}
for _, i := range searchResult.Hits {
page, err := api.PageFromFields(i.Fields)
if err != nil {
continue
}
item := &api_proto.DocSearchResponse{
Title: page.Title,
FullText: page.Text,
Link: page.Url,
Tags: page.Tags,
}
// We only highlight the Text field
locations, pres := i.Locations["text"]
if pres {
for _, hit_locations := range locations {
for _, loc := range hit_locations {
item.Highlights = append(item.Highlights, &api_proto.Highlight{
Start: loc.Start,
End: loc.End,
})
}
}
}
res.Items = append(res.Items, item)
}
return res, nil
}
func NewDocManager(
ctx context.Context,
wg *sync.WaitGroup,
config_obj *config_proto.Config) (services.DocManager, error) {
if utils.IsRootOrg(config_obj.OrgId) {
return &DocManager{
config_obj: config_obj,
}, nil
}
org_manager, err := services.GetOrgManager()
if err != nil {
return nil, err
}
root_org_config, err := org_manager.GetOrgConfig(services.ROOT_ORG_ID)
if err != nil {
return nil, err
}
return services.GetDocManager(root_org_config)
}
+1
View File
@@ -67,6 +67,7 @@ type ServiceContainer interface {
SecretsService() (SecretsService, error)
BackupService() (BackupService, error)
ExportManager() (ExportManager, error)
DocManager() (DocManager, error)
}
// The org manager manages multi-tenancies.
+18
View File
@@ -18,6 +18,7 @@ import (
"www.velocidex.com/golang/velociraptor/services/client_info"
"www.velocidex.com/golang/velociraptor/services/client_monitoring"
"www.velocidex.com/golang/velociraptor/services/ddclient"
"www.velocidex.com/golang/velociraptor/services/docs"
"www.velocidex.com/golang/velociraptor/services/exports"
"www.velocidex.com/golang/velociraptor/services/frontend"
"www.velocidex.com/golang/velociraptor/services/hunt_dispatcher"
@@ -65,6 +66,7 @@ type ServiceContainer struct {
secrets services.SecretsService
backups services.BackupService
export_manager services.ExportManager
doc_manager services.DocManager
}
func (self *ServiceContainer) MockFrontendManager(svc services.FrontendManager) {
@@ -241,6 +243,16 @@ func (self *ServiceContainer) Journal() (services.JournalService, error) {
return self.journal, nil
}
func (self *ServiceContainer) DocManager() (services.DocManager, error) {
self.mu.Lock()
defer self.mu.Unlock()
if self.doc_manager == nil {
return nil, errors.New("Doc Manager service not ready")
}
return self.doc_manager, nil
}
func (self *ServiceContainer) ClientInfoManager() (services.ClientInfoManager, error) {
self.mu.Lock()
defer self.mu.Unlock()
@@ -569,8 +581,14 @@ func (self *OrgManager) startOrgFromContext(org_ctx *OrgContext) (err error) {
return err
}
dm, err := docs.NewDocManager(ctx, wg, org_config)
if err != nil {
return err
}
service_container.mu.Lock()
service_container.repository = repo_manager
service_container.doc_manager = dm
service_container.mu.Unlock()
}