Use foundation/validator instead (#184)

diff --git a/go.mod b/go.mod
index b10cd0d..539d13b 100644
--- a/go.mod
+++ b/go.mod
@@ -2,16 +2,13 @@
 
 require (
 	github.com/emicklei/go-restful v2.12.0+incompatible
-	github.com/go-chassis/cari v0.2.0
+	github.com/go-chassis/cari v0.4.1-0.20210528013912-6da8395f7ff9
+	github.com/go-chassis/foundation v0.3.1-0.20210602072914-a580bed505d0
 	github.com/go-chassis/go-archaius v1.5.2-0.20210301074935-e4694f6b077b
 	github.com/go-chassis/go-chassis/v2 v2.1.2-0.20210308033545-985e98e20637
 	github.com/go-chassis/openlog v1.1.2
 	github.com/go-chassis/seclog v1.3.0
-	github.com/go-playground/universal-translator v0.17.0
-	github.com/go-playground/validator v9.31.0+incompatible
 	github.com/hashicorp/serf v0.9.5
-	github.com/leodido/go-urn v1.2.1 // indirect
-	github.com/mitchellh/mapstructure v1.3.3 // indirect
 	github.com/satori/go.uuid v1.2.0
 	github.com/stretchr/testify v1.6.1
 	github.com/urfave/cli v1.22.4
diff --git a/go.sum b/go.sum
index e61b066..f0e08bd 100644
--- a/go.sum
+++ b/go.sum
@@ -120,10 +120,16 @@
 github.com/go-chassis/cari v0.0.2-0.20210208095358-3bccdf2ce456/go.mod h1:MgtsEI0AM4Ush6Lyw27z9Gk4nQ/8GWTSXrFzupawWDM=
 github.com/go-chassis/cari v0.2.0 h1:29Rsisbq/bKc79OCZdD2TU0aGr8UBH/i0fjUniMh0+Q=
 github.com/go-chassis/cari v0.2.0/go.mod h1:Ie2lW11Y5ZFClY9z7bhAwK6BoNxqGSf3fYGs4mPFs74=
+github.com/go-chassis/cari v0.4.0 h1:2rJ7pB4dfZIu5/HQwwJhmybC1n/0MXWkKieoHCu4tQc=
+github.com/go-chassis/cari v0.4.0/go.mod h1:av/19fqwEP4eOC8unL/z67AAbFDwXUCko6SKa4Avrd8=
+github.com/go-chassis/cari v0.4.1-0.20210528013912-6da8395f7ff9 h1:UxNOY1mnK7i9qRYeu0d2jsVItfoV0ga75RF6isOhn00=
+github.com/go-chassis/cari v0.4.1-0.20210528013912-6da8395f7ff9/go.mod h1:av/19fqwEP4eOC8unL/z67AAbFDwXUCko6SKa4Avrd8=
 github.com/go-chassis/foundation v0.2.2-0.20201210043510-9f6d3de40234/go.mod h1:2PjwqpVwYEVaAldl5A58a08viH8p27pNeYaiE3ZxOBA=
 github.com/go-chassis/foundation v0.2.2/go.mod h1:2PjwqpVwYEVaAldl5A58a08viH8p27pNeYaiE3ZxOBA=
 github.com/go-chassis/foundation v0.3.0 h1:jG4BIrK8fXD9jbTtJ5rOLGQZ1pQI/mLnDuVJzToCtos=
 github.com/go-chassis/foundation v0.3.0/go.mod h1:2PjwqpVwYEVaAldl5A58a08viH8p27pNeYaiE3ZxOBA=
+github.com/go-chassis/foundation v0.3.1-0.20210602072914-a580bed505d0 h1:bWvRZc0/sxPjzOBB4DTjxcFjpoy3MdSt5fbIimx2FtE=
+github.com/go-chassis/foundation v0.3.1-0.20210602072914-a580bed505d0/go.mod h1:6NsIUaHghTFRGfCBcZN011zl196F6OR5QvD9N+P4oWU=
 github.com/go-chassis/go-archaius v1.3.6-0.20201210061741-7450779aaeb8/go.mod h1:j8vJX5c455N0cN5rzeC1dm9T5kyOI8ZvIjaSJ+rZjwc=
 github.com/go-chassis/go-archaius v1.4.0/go.mod h1:j8vJX5c455N0cN5rzeC1dm9T5kyOI8ZvIjaSJ+rZjwc=
 github.com/go-chassis/go-archaius v1.5.0/go.mod h1:QPwvvtBxvwiC48rmydoAqxopqOr93RCQ6syWsIkXPXQ=
@@ -341,6 +347,9 @@
 github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
 github.com/karlseguin/ccache v2.0.3-0.20170217060820-3ba9789cfd2c+incompatible/go.mod h1:CM9tNPzT6EdRh14+jiW8mEF9mkNZuuE51qmgGYUB93w=
+github.com/karlseguin/ccache/v2 v2.0.8 h1:lT38cE//uyf6KcFok0rlgXtGFBWxkI6h/qg4tbFyDnA=
+github.com/karlseguin/ccache/v2 v2.0.8/go.mod h1:2BDThcfQMf/c0jnZowt16eW405XIqZPavt+HoYEtcxQ=
+github.com/karlseguin/expect v1.0.2-0.20190806010014-778a5f0c6003/go.mod h1:zNBxMY8P21owkeogJELCLeHIt+voOSduHYTFUbwRAV8=
 github.com/karlseguin/expect v1.0.7/go.mod h1:lXdI8iGiQhmzpnnmU/EGA60vqKs8NbRNFnhhrJGoD5g=
 github.com/karrick/godirwalk v1.8.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
 github.com/karrick/godirwalk v1.10.3 h1:lOpSw2vJP0y5eLBW906QwKsUK/fe/QDyoqM5rnnuPDY=
@@ -402,6 +411,7 @@
 github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
 github.com/mitchellh/cli v1.1.0 h1:tEElEatulEHDeedTxwckzyYMA5c86fbmNIUL1hBIiTg=
 github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee h1:kK7VuFVykgt0LfMSloWYjDOt4TnOcL0AxF0/rDq2VkM=
 github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8=
 github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
diff --git a/pkg/model/db_schema.go b/pkg/model/db_schema.go
index 8875c24..5583df7 100644
--- a/pkg/model/db_schema.go
+++ b/pkg/model/db_schema.go
@@ -33,19 +33,19 @@
 type KVDoc struct {
 	ID             string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" swag:"string"`
 	LabelFormat    string `json:"label_format,omitempty" bson:"label_format,omitempty" yaml:"label_format,omitempty"`
-	Key            string `json:"key" yaml:"key" validate:"key"`
-	Value          string `json:"value" yaml:"value" validate:"value"`
+	Key            string `json:"key" yaml:"key" validate:"min=1,max=128,key"`
+	Value          string `json:"value" yaml:"value" validate:"max=2097152,value"`
 	ValueType      string `json:"value_type,omitempty" bson:"value_type,omitempty" yaml:"value_type,omitempty" validate:"valueType"` //ini,json,text,yaml,properties
-	Checker        string `json:"check,omitempty" yaml:"check,omitempty" validate:"check"`                                           //python script
+	Checker        string `json:"check,omitempty" yaml:"check,omitempty" validate:"max=1048576,check"`                               //python script
 	CreateRevision int64  `json:"create_revision,omitempty" bson:"create_revision," yaml:"create_revision,omitempty"`
 	UpdateRevision int64  `json:"update_revision,omitempty" bson:"update_revision," yaml:"update_revision,omitempty"`
-	Project        string `json:"project,omitempty" yaml:"project,omitempty" validate:"commonName"`
+	Project        string `json:"project,omitempty" yaml:"project,omitempty" validate:"min=1,max=256,commonName"`
 	Status         string `json:"status,omitempty" yaml:"status,omitempty" validate:"kvStatus"`
 	CreateTime     int64  `json:"create_time,omitempty" bson:"create_time," yaml:"create_time,omitempty"`
 	UpdateTime     int64  `json:"update_time,omitempty" bson:"update_time," yaml:"update_time,omitempty"`
 
 	Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty" validate:"max=6,dive,keys,labelKV,endkeys,labelKV"` //redundant
-	Domain string            `json:"domain,omitempty" yaml:"domain,omitempty" validate:"commonName"`                              //redundant
+	Domain string            `json:"domain,omitempty" yaml:"domain,omitempty" validate:"min=1,max=256,commonName"`                //redundant
 }
 
 //ViewDoc is db struct, it saves user's custom view name and criteria
@@ -76,24 +76,24 @@
 // UpdateKVRequest is db struct, it contains kv update request params
 type UpdateKVRequest struct {
 	ID      string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" swag:"string" validate:"uuid"`
-	Value   string `json:"value,omitempty" yaml:"value,omitempty" validate:"value"`
-	Project string `json:"project,omitempty" yaml:"project,omitempty" validate:"commonName"`
-	Domain  string `json:"domain,omitempty" yaml:"domain,omitempty" validate:"commonName"` //redundant
+	Value   string `json:"value,omitempty" yaml:"value,omitempty" validate:"max=2097152,value"`
+	Project string `json:"project,omitempty" yaml:"project,omitempty" validate:"min=1,max=256,commonName"`
+	Domain  string `json:"domain,omitempty" yaml:"domain,omitempty" validate:"min=1,max=256,commonName"` //redundant
 	Status  string `json:"status,omitempty" yaml:"status,omitempty" validate:"kvStatus"`
 }
 
 // GetKVRequest contains kv get request params
 type GetKVRequest struct {
-	Project string `json:"project,omitempty" yaml:"project,omitempty" validate:"commonName"`
-	Domain  string `json:"domain,omitempty" yaml:"domain,omitempty" validate:"commonName"` //redundant
+	Project string `json:"project,omitempty" yaml:"project,omitempty" validate:"min=1,max=256,commonName"`
+	Domain  string `json:"domain,omitempty" yaml:"domain,omitempty" validate:"min=1,max=256,commonName"` //redundant
 	ID      string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" swag:"string" validate:"uuid"`
 }
 
 // ListKVRequest contains kv list request params
 type ListKVRequest struct {
-	Project string            `json:"project,omitempty" yaml:"project,omitempty" validate:"commonName"`
-	Domain  string            `json:"domain,omitempty" yaml:"domain,omitempty" validate:"commonName"` //redundant
-	Key     string            `json:"key" yaml:"key" validate:"getKey"`
+	Project string            `json:"project,omitempty" yaml:"project,omitempty" validate:"min=1,max=256,commonName"`
+	Domain  string            `json:"domain,omitempty" yaml:"domain,omitempty" validate:"min=1,max=256,commonName"` //redundant
+	Key     string            `json:"key" yaml:"key" validate:"max=128,getKey"`
 	Labels  map[string]string `json:"labels,omitempty" yaml:"labels,omitempty" validate:"max=8,dive,keys,labelKV,endkeys,labelKV"` //redundant
 	Offset  int64             `validate:"min=0"`
 	Limit   int64             `validate:"min=0,max=100"`
diff --git a/pkg/validate/instance.go b/pkg/validate/instance.go
deleted file mode 100644
index fe1c2ab..0000000
--- a/pkg/validate/instance.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package validate
-
-var defaultValidator = NewValidator()
-
-const (
-	key                   = "key"
-	commonNameRegexString = `^[a-zA-Z0-9]*$|^[a-zA-Z0-9][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$`
-	getKeyRegexString     = `^[a-zA-Z0-9]*$|^[a-zA-Z0-9][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$|^beginWith\([a-zA-Z0-9][a-zA-Z0-9_\-.]*\)$|^wildcard\([a-zA-Z0-9][a-zA-Z0-9_\-.*]*\)$`
-	asciiRegexString      = `^[\x00-\x7F]*$`
-	allCharString         = `.*`
-)
-
-// custom validate rules
-// please use different tag names from third party tags
-var customRules = []*RegexValidateRule{
-	NewRule(key, commonNameRegexString, &Option{Min: 1, Max: 128}),
-	NewRule("getKey", getKeyRegexString, &Option{Max: 128}),
-	NewRule("commonName", commonNameRegexString, &Option{Min: 1, Max: 256}),
-	NewRule("valueType", `^$|^(ini|json|text|yaml|properties)$`, nil),
-	NewRule("kvStatus", `^$|^(enabled|disabled)$`, nil),
-	NewRule("value", allCharString, &Option{Max: 2097152}), //ASCII, 2M
-	NewRule("labelKV", commonNameRegexString, &Option{Max: 32}),
-	NewRule("check", asciiRegexString, &Option{Max: 1048576}), //ASCII, 1M
-}
-
-// tags of third party validate rules we used, for error translation
-var thirdPartyTags = []string{
-	"min", "max", "length", "uuid",
-}
-
-// Init initializes validate
-func Init() error {
-	for _, r := range customRules {
-		if err := defaultValidator.RegisterRule(r); err != nil {
-			return err
-		}
-	}
-	for _, t := range thirdPartyTags {
-		if err := defaultValidator.AddErrorTranslation4Tag(t); err != nil {
-			return err
-		}
-	}
-	return nil
-}
-
-// Validate validates data
-func Validate(v interface{}) error {
-	return defaultValidator.Validate(v)
-}
diff --git a/pkg/validate/instance_test.go b/pkg/validate/instance_test.go
deleted file mode 100644
index 0519656..0000000
--- a/pkg/validate/instance_test.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package validate_test
-
-import (
-	"testing"
-
-	"github.com/apache/servicecomb-kie/pkg/model"
-	"github.com/apache/servicecomb-kie/pkg/validate"
-
-	"github.com/stretchr/testify/assert"
-)
-
-func TestValidate(t *testing.T) {
-	string32 := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" //32
-	string128 := string32 + string32 + string32 + string32
-	err := validate.Init()
-	assert.NoError(t, err)
-
-	kvDoc := &model.KVDoc{Project: "a", Domain: "a",
-		Key:   "a",
-		Value: "a",
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:   "",
-		Value: "a",
-	}
-	assert.Error(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:   "a#",
-		Value: "a",
-	}
-	assert.Error(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:   string128 + "a",
-		Value: "a",
-	}
-	assert.Error(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:   "a",
-		Value: "",
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:       "a",
-		Value:     "a",
-		ValueType: "",
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:       "a",
-		Value:     "a",
-		ValueType: "text",
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:       "a",
-		Value:     "a",
-		ValueType: "a",
-	}
-	assert.Error(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:    "a",
-		Value:  "a",
-		Status: "",
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:    "a",
-		Value:  "a",
-		Status: "enabled",
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:    "a",
-		Value:  "a",
-		Status: "a",
-	}
-	assert.Error(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:    "a",
-		Value:  "a",
-		Labels: nil,
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:    "a",
-		Value:  "a",
-		Labels: map[string]string{"a": "a"},
-	}
-	assert.NoError(t, validate.Validate(kvDoc))
-
-	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
-		Key:    "a",
-		Value:  "a",
-		Labels: map[string]string{string32 + "a": "a"},
-	}
-	assert.Error(t, validate.Validate(kvDoc))
-
-	ListKVRe := &model.ListKVRequest{Project: "a", Domain: "a",
-		Key: "beginWith(a)",
-	}
-	assert.NoError(t, validate.Validate(ListKVRe))
-
-	ListKVRe = &model.ListKVRequest{Project: "a", Domain: "a",
-		Key: "beginW(a)",
-	}
-	assert.Error(t, validate.Validate(ListKVRe))
-
-	ListKVRe = &model.ListKVRequest{Project: "a", Domain: "a",
-		Key: "beginW()",
-	}
-	assert.Error(t, validate.Validate(ListKVRe))
-}
diff --git a/pkg/validate/rule.go b/pkg/validate/rule.go
deleted file mode 100644
index 3fb9560..0000000
--- a/pkg/validate/rule.go
+++ /dev/null
@@ -1,90 +0,0 @@
-package validate
-
-import (
-	"fmt"
-	"regexp"
-	"unicode/utf8"
-
-	"github.com/go-playground/validator"
-)
-
-// RegexValidateRule contains an validate tag's info
-type RegexValidateRule struct {
-	tag           string
-	min           int64
-	max           int64
-	regex         *regexp.Regexp
-	validateFuncs []func(string) bool
-}
-
-// Option is RegexValidateRule option
-type Option struct {
-	Min int64
-	Max int64
-}
-
-// Validate validates string
-func (r *RegexValidateRule) Validate(s string) bool {
-	for _, f := range r.validateFuncs {
-		if ok := f(s); !ok {
-			return false
-		}
-	}
-	return true
-}
-
-func (r *RegexValidateRule) validateFL(fl validator.FieldLevel) bool {
-	return r.Validate(fl.Field().String())
-}
-
-// Tag returns the validate rule's tag
-func (r *RegexValidateRule) Tag() string {
-	return r.tag
-}
-
-// Explain explains the rule
-func (r *RegexValidateRule) Explain() string {
-	explain := r.regex.String()
-	if r.max > 0 {
-		explain = fmt.Sprintf("%s , max = %d", explain, r.max)
-	}
-	if r.min > 0 {
-		explain = fmt.Sprintf("%s , min = %d", explain, r.min)
-	}
-	return explain
-}
-
-func (r *RegexValidateRule) matchRegex(s string) bool {
-	return r.regex.MatchString(s)
-}
-func (r *RegexValidateRule) matchMin(s string) bool {
-	return int64(utf8.RuneCountInString(s)) >= r.min
-}
-func (r *RegexValidateRule) matchMax(s string) bool {
-	return int64(utf8.RuneCountInString(s)) <= r.max
-}
-
-// NewRule news a rule
-func NewRule(tag, regexStr string, opt *Option) *RegexValidateRule {
-	r := &RegexValidateRule{
-		tag:           tag,
-		regex:         regexp.MustCompile(regexStr),
-		validateFuncs: make([]func(string) bool, 0),
-	}
-
-	if opt == nil {
-		r.validateFuncs = append(r.validateFuncs, r.matchRegex)
-		return r
-	}
-
-	if opt.Max > 0 {
-		r.max = opt.Max
-		r.validateFuncs = append(r.validateFuncs, r.matchMax)
-	}
-	if opt.Min > 0 {
-		r.min = opt.Min
-		r.validateFuncs = append(r.validateFuncs, r.matchMin)
-	}
-	r.validateFuncs = append(r.validateFuncs, r.matchRegex)
-	return r
-}
diff --git a/pkg/validate/rule_test.go b/pkg/validate/rule_test.go
deleted file mode 100644
index d2336a9..0000000
--- a/pkg/validate/rule_test.go
+++ /dev/null
@@ -1,39 +0,0 @@
-package validate_test
-
-import (
-	"testing"
-
-	"github.com/apache/servicecomb-kie/pkg/validate"
-	"github.com/stretchr/testify/assert"
-)
-
-func TestNewRule(t *testing.T) {
-	rule := validate.NewRule("t", `^[a-zA-Z0-9]*$`, &validate.Option{Min: 2, Max: 4})
-	assert.Equal(t, "t", rule.Tag())
-	rule.Explain()
-	assert.True(t, rule.Validate("ab"))
-	assert.False(t, rule.Validate("a"))
-	assert.False(t, rule.Validate("abcde"))
-	assert.False(t, rule.Validate("ab-"))
-
-	rule = validate.NewRule("t", `^[a-zA-Z0-9]*$`, &validate.Option{Min: 2})
-	rule.Explain()
-	assert.True(t, rule.Validate("ab"))
-	assert.False(t, rule.Validate("a"))
-	assert.True(t, rule.Validate("abcde"))
-	assert.False(t, rule.Validate("ab-"))
-
-	rule = validate.NewRule("t", `^[a-zA-Z0-9]*$`, &validate.Option{Max: 4})
-	rule.Explain()
-	assert.True(t, rule.Validate("ab"))
-	assert.True(t, rule.Validate("a"))
-	assert.False(t, rule.Validate("abcde"))
-	assert.False(t, rule.Validate("ab-"))
-
-	rule = validate.NewRule("t", `^[a-zA-Z0-9]*$`, nil)
-	rule.Explain()
-	assert.True(t, rule.Validate("ab"))
-	assert.True(t, rule.Validate("a"))
-	assert.True(t, rule.Validate("abcdefg12345678"))
-	assert.False(t, rule.Validate("ab-"))
-}
diff --git a/pkg/validate/validator.go b/pkg/validate/validator.go
deleted file mode 100644
index 59fdf26..0000000
--- a/pkg/validate/validator.go
+++ /dev/null
@@ -1,87 +0,0 @@
-package validate
-
-import (
-	"errors"
-	"fmt"
-	"strings"
-
-	ut "github.com/go-playground/universal-translator"
-	valid "github.com/go-playground/validator"
-)
-
-var errorTranslator ut.Translator // no use but as an index
-
-func registerErrorTranslator(_ ut.Translator) error { return nil }
-
-// Validator validates data
-// not safe, use it after initialized
-type Validator struct {
-	rules map[string]*RegexValidateRule
-	valid *valid.Validate
-}
-
-// Validate validates the input data
-func (v *Validator) Validate(i interface{}) error {
-	err := v.valid.Struct(i)
-	if err != nil {
-		return v.wrapError(err)
-	}
-	return nil
-}
-
-// converts the raw error into an easy-to-understand error
-func (v *Validator) wrapError(err error) error {
-	validErr, ok := err.(valid.ValidationErrors)
-	if !ok {
-		return err
-	}
-	msgs := make([]string, len(validErr))
-	for i, ve := range validErr {
-		fe := ve.(valid.FieldError)
-		msgs[i] = fe.Translate(errorTranslator)
-	}
-	return errors.New("validate failed, " + strings.Join(msgs, " | "))
-}
-
-// RegisterRule registers a custom validate rule
-func (v *Validator) RegisterRule(r *RegexValidateRule) error {
-	if r == nil {
-		return errors.New("empty regex validate rule")
-	}
-	v.rules[r.tag] = r
-	if err := v.valid.RegisterValidation(r.tag, r.validateFL); err != nil {
-		return err
-	}
-	return v.AddErrorTranslation4Tag(r.tag)
-}
-
-// translates raw errors to easy-to-understand messages
-func (v *Validator) translateError(_ ut.Translator, fe valid.FieldError) string {
-	var rule string
-	if r, ok := v.rules[fe.Tag()]; ok {
-		rule = r.Explain()
-	} else {
-		rule = fe.Tag()
-		if len(fe.Param()) > 0 {
-			rule = rule + " = " + fe.Param()
-		}
-	}
-	return fmt.Sprintf("field: %s, rule: %s", fe.Namespace(), rule)
-}
-
-// AddErrorTranslation4Tag adds translation for the errors of some tag,
-// to make the error easier to understand
-func (v *Validator) AddErrorTranslation4Tag(tag string) error {
-	return v.valid.RegisterTranslation(tag,
-		errorTranslator,
-		registerErrorTranslator,
-		v.translateError)
-}
-
-// NewValidator news a validator
-func NewValidator() *Validator {
-	return &Validator{
-		valid: valid.New(),
-		rules: make(map[string]*RegexValidateRule),
-	}
-}
diff --git a/pkg/validate/validator_test.go b/pkg/validate/validator_test.go
deleted file mode 100644
index 3bcde81..0000000
--- a/pkg/validate/validator_test.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package validate_test
-
-import (
-	"testing"
-
-	"github.com/apache/servicecomb-kie/pkg/validate"
-	"github.com/stretchr/testify/assert"
-)
-
-type student struct {
-	Name    string `validate:"kieTest"`
-	Address string `validate:"alpha,min=2,max=4"`
-}
-
-func TestNewValidator(t *testing.T) {
-	r := validate.NewRule("kieTest", `^[a-zA-Z0-9]*$`, nil)
-	valid := validate.NewValidator()
-	err := valid.RegisterRule(r)
-	assert.Nil(t, err)
-	assert.Nil(t, valid.AddErrorTranslation4Tag("min"))
-	assert.Nil(t, valid.AddErrorTranslation4Tag("max"))
-
-	s := &student{Name: "a1", Address: "abc"}
-	err = valid.Validate(s)
-	assert.Nil(t, err)
-
-	s = &student{Name: "a1-", Address: "abc"}
-	err = valid.Validate(s)
-	assert.NotNil(t, err)
-	t.Log(err)
-
-	s = &student{Name: "a1", Address: "abcde"}
-	err = valid.Validate(s)
-	assert.NotNil(t, err)
-	t.Log(err)
-}
diff --git a/pkg/validator/rule.go b/pkg/validator/rule.go
new file mode 100644
index 0000000..b6e9e71
--- /dev/null
+++ b/pkg/validator/rule.go
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package validator
+
+import "github.com/go-chassis/foundation/validator"
+
+const (
+	key                   = "key"
+	commonNameRegexString = `^[a-zA-Z0-9]*$|^[a-zA-Z0-9][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$`
+	labelKvRegexString    = `^[a-zA-Z0-9]{0,32}$|^[a-zA-Z0-9][a-zA-Z0-9_\-.]{0,30}[a-zA-Z0-9]$`
+	getKeyRegexString     = `^[a-zA-Z0-9]*$|^[a-zA-Z0-9][a-zA-Z0-9_\-.]*[a-zA-Z0-9]$|^beginWith\([a-zA-Z0-9][a-zA-Z0-9_\-.]*\)$|^wildcard\([a-zA-Z0-9][a-zA-Z0-9_\-.*]*\)$`
+	asciiRegexString      = `^[\x00-\x7F]*$`
+	allCharString         = `.*`
+)
+
+// custom validate rules
+// please use different tag names from third party tags
+var customRules = []*validator.RegexValidateRule{
+	validator.NewRegexRule(key, commonNameRegexString),
+	validator.NewRegexRule("getKey", getKeyRegexString),
+	validator.NewRegexRule("commonName", commonNameRegexString),
+	validator.NewRegexRule("valueType", `^$|^(ini|json|text|yaml|properties)$`),
+	validator.NewRegexRule("kvStatus", `^$|^(enabled|disabled)$`),
+	validator.NewRegexRule("value", allCharString), //ASCII, 2M
+	validator.NewRegexRule("labelKV", labelKvRegexString),
+	validator.NewRegexRule("check", asciiRegexString), //ASCII, 1M
+}
+
+func Init() error {
+	return validator.RegisterRegexRules(customRules)
+}
diff --git a/pkg/validator/rule_test.go b/pkg/validator/rule_test.go
new file mode 100644
index 0000000..5cf5705
--- /dev/null
+++ b/pkg/validator/rule_test.go
@@ -0,0 +1,173 @@
+package validator_test
+
+import (
+	"github.com/go-chassis/foundation/validator"
+	"strings"
+	"testing"
+
+	"github.com/apache/servicecomb-kie/pkg/model"
+	validsvc "github.com/apache/servicecomb-kie/pkg/validator"
+	"github.com/stretchr/testify/assert"
+)
+
+func init() {
+	if err := validsvc.Init(); err != nil {
+		panic(err)
+	}
+}
+
+func TestValidate(t *testing.T) {
+	string32 := "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" //32
+	string128 := string32 + string32 + string32 + string32
+
+	kvDoc := &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "a",
+		Value: "a",
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "",
+		Value: "a",
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "a#",
+		Value: "a",
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   string128 + "a",
+		Value: "a",
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "a",
+		Value: "",
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:       "a",
+		Value:     "a",
+		ValueType: "",
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:       "a",
+		Value:     "a",
+		ValueType: "text",
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:       "a",
+		Value:     "a",
+		ValueType: "a",
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:    "a",
+		Value:  "a",
+		Status: "",
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:    "a",
+		Value:  "a",
+		Status: "enabled",
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:    "a",
+		Value:  "a",
+		Status: "a",
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:    "a",
+		Value:  "a",
+		Labels: nil,
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:    "a",
+		Value:  "a",
+		Labels: map[string]string{"a": "a"},
+	}
+	assert.NoError(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "a",
+		Value: "a",
+		Labels: map[string]string{
+			"1": "a",
+			"2": "a",
+			"3": "a",
+			"4": "a",
+			"5": "a",
+			"6": "a",
+			"7": "a", // error
+		},
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "a",
+		Value: "a",
+		Labels: map[string]string{
+			"1":                            "a",
+			"2":                            "a",
+			"3":                            "a",
+			"4":                            "a",
+			"5":                            "a",
+			"6-" + strings.Repeat("x", 31): "a", // error
+		},
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:   "a",
+		Value: "a",
+		Labels: map[string]string{
+			"1": "a",
+			"2": "a",
+			"3": "a",
+			"4": "a",
+			"5": "a",
+			"6": "a-" + strings.Repeat("x", 31), // error
+		},
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	kvDoc = &model.KVDoc{Project: "a", Domain: "a",
+		Key:    "a",
+		Value:  "a",
+		Labels: map[string]string{string32 + "a": "a"},
+	}
+	assert.Error(t, validator.Validate(kvDoc))
+
+	ListKVRe := &model.ListKVRequest{Project: "a", Domain: "a",
+		Key: "beginWith(a)",
+	}
+	assert.NoError(t, validator.Validate(ListKVRe))
+
+	ListKVRe = &model.ListKVRequest{Project: "a", Domain: "a",
+		Key: "beginW(a)",
+	}
+	assert.Error(t, validator.Validate(ListKVRe))
+
+	ListKVRe = &model.ListKVRequest{Project: "a", Domain: "a",
+		Key: "beginW()",
+	}
+	assert.Error(t, validator.Validate(ListKVRe))
+}
diff --git a/server/resource/v1/kv_resource.go b/server/resource/v1/kv_resource.go
index b228e3a..51f74be 100644
--- a/server/resource/v1/kv_resource.go
+++ b/server/resource/v1/kv_resource.go
@@ -21,11 +21,11 @@
 import (
 	"encoding/json"
 	"fmt"
+	"github.com/go-chassis/foundation/validator"
 	"net/http"
 
 	"github.com/apache/servicecomb-kie/pkg/common"
 	"github.com/apache/servicecomb-kie/pkg/model"
-	"github.com/apache/servicecomb-kie/pkg/validate"
 	"github.com/apache/servicecomb-kie/server/pubsub"
 	"github.com/apache/servicecomb-kie/server/service"
 	"github.com/apache/servicecomb-kie/server/service/mongo/session"
@@ -55,7 +55,7 @@
 	if kv.Status == "" {
 		kv.Status = common.StatusDisabled
 	}
-	err = validate.Validate(kv)
+	err = validator.Validate(kv)
 	if err != nil {
 		WriteErrResponse(rctx, http.StatusBadRequest, err.Error())
 		return
@@ -114,7 +114,7 @@
 	kvReq.ID = kvID
 	kvReq.Domain = domain
 	kvReq.Project = project
-	err = validate.Validate(kvReq)
+	err = validator.Validate(kvReq)
 	if err != nil {
 		WriteErrResponse(rctx, http.StatusBadRequest, err.Error())
 		return
@@ -151,7 +151,7 @@
 		Domain:  ReadDomain(rctx.Ctx),
 		ID:      rctx.ReadPathParameter(common.PathParamKVID),
 	}
-	err := validate.Validate(request)
+	err := validator.Validate(request)
 	if err != nil {
 		WriteErrResponse(rctx, http.StatusBadRequest, err.Error())
 		return
@@ -198,7 +198,7 @@
 	}
 	request.Offset = offset
 	request.Limit = limit
-	err = validate.Validate(request)
+	err = validator.Validate(request)
 	if err != nil {
 		WriteErrResponse(rctx, http.StatusBadRequest, err.Error())
 		return
diff --git a/server/resource/v1/kv_resource_test.go b/server/resource/v1/kv_resource_test.go
index 7402427..b7d6f5e 100644
--- a/server/resource/v1/kv_resource_test.go
+++ b/server/resource/v1/kv_resource_test.go
@@ -22,7 +22,6 @@
 	"encoding/json"
 	common2 "github.com/apache/servicecomb-kie/pkg/common"
 	"github.com/apache/servicecomb-kie/pkg/model"
-	"github.com/apache/servicecomb-kie/pkg/validate"
 	"github.com/apache/servicecomb-kie/server/config"
 	"github.com/apache/servicecomb-kie/server/plugin/qms"
 	"github.com/apache/servicecomb-kie/server/pubsub"
@@ -47,9 +46,6 @@
 )
 
 func init() {
-	if err := validate.Init(); err != nil {
-		panic(err)
-	}
 	log.Init(log.Config{
 		Writers:       []string{"stdout"},
 		LoggerLevel:   "DEBUG",
diff --git a/server/server.go b/server/server.go
index 3f57559..93215ab 100644
--- a/server/server.go
+++ b/server/server.go
@@ -18,7 +18,7 @@
 package server
 
 import (
-	"github.com/apache/servicecomb-kie/pkg/validate"
+	"github.com/apache/servicecomb-kie/pkg/validator"
 	"github.com/apache/servicecomb-kie/server/config"
 	"github.com/apache/servicecomb-kie/server/pubsub"
 	"github.com/apache/servicecomb-kie/server/rbac"
@@ -42,7 +42,7 @@
 	if err := service.DBInit(); err != nil {
 		openlog.Fatal(err.Error())
 	}
-	if err := validate.Init(); err != nil {
+	if err := validator.Init(); err != nil {
 		openlog.Fatal("validate init failed: " + err.Error())
 	}
 	rbac.Init()
diff --git a/test/init.go b/test/init.go
index 9841401..397c104 100644
--- a/test/init.go
+++ b/test/init.go
@@ -18,6 +18,7 @@
 package test
 
 import (
+	"github.com/apache/servicecomb-kie/pkg/validator"
 	"github.com/go-chassis/go-archaius"
 	"github.com/go-chassis/go-chassis/v2/security/cipher"
 	_ "github.com/go-chassis/go-chassis/v2/security/cipher/plugins/plain"
@@ -27,4 +28,5 @@
 	archaius.Init(archaius.WithMemorySource())
 	archaius.Set("servicecomb.cipher.plugin", "default")
 	cipher.Init()
+	validator.Init()
 }