feat: implement DNS namespace validation and remote URL uniqueness checks (#306)
## Summary - Add reverse-DNS namespace format validation for server names (namespace/name) - Validate remote URLs match the DNS namespace derived from hostname - Prevent duplicate remote URLs across different servers - Support localhost/development URLs without namespace restrictions - Add comprehensive test coverage for validation logic - Update database layer to support remote_url filtering Fixes #180 by ensuring proper namespace governance and preventing URL conflicts. --------- Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
parent
d663406280
commit
923b2e07b9
3 changed files with 497 additions and 29 deletions
|
|
@ -13,7 +13,7 @@ var (
|
|||
ErrAlreadyExists = errors.New("record already exists")
|
||||
ErrInvalidInput = errors.New("invalid input")
|
||||
ErrDatabase = errors.New("database error")
|
||||
ErrInvalidVersion = errors.New("invalid version: cannot publish older version after newer version")
|
||||
ErrInvalidVersion = errors.New("invalid version: cannot publish duplicate version")
|
||||
ErrMaxServersReached = errors.New("maximum number of versions for this server reached (10000): please reach out at https://github.com/modelcontextprotocol/registry to explain your use case")
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ func NewMemoryDB(e map[string]*model.ServerDetail) *MemoryDB {
|
|||
}
|
||||
|
||||
|
||||
// List retrieves ServerRecord entries with optional filtering and pagination
|
||||
//nolint:cyclop // Complexity from filtering logic is acceptable for memory implementation
|
||||
func (db *MemoryDB) List(
|
||||
ctx context.Context,
|
||||
filter map[string]any,
|
||||
|
|
@ -89,6 +89,18 @@ func (db *MemoryDB) List(
|
|||
if string(entry.ServerJSON.Status) != value.(string) {
|
||||
include = false
|
||||
}
|
||||
case "remote_url":
|
||||
found := false
|
||||
remoteURL := value.(string)
|
||||
for _, remote := range entry.ServerJSON.Remotes {
|
||||
if remote.URL == remoteURL {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
include = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -76,6 +76,10 @@ func (db *PostgreSQL) List(
|
|||
whereClause += fmt.Sprintf(" AND s.status = $%d", argIndex)
|
||||
args = append(args, v)
|
||||
argIndex++
|
||||
case "remote_url":
|
||||
whereClause += fmt.Sprintf(" AND EXISTS (SELECT 1 FROM jsonb_array_elements(CASE WHEN jsonb_typeof(s.remotes) = 'array' THEN s.remotes ELSE '[]'::jsonb END) AS remote WHERE remote->>'url' = $%d)", argIndex)
|
||||
args = append(args, v)
|
||||
argIndex++
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue