- Remove KCL ecosystem (~220 files deleted) - Migrate all infrastructure to Nickel schema system - Consolidate documentation: legacy docs → provisioning/docs/src/ - Add CI/CD workflows (.github/) and Rust build config (.cargo/) - Update core system for Nickel schema parsing - Update README.md and CHANGES.md for v5.0.0 release - Fix pre-commit hooks: end-of-file, trailing-whitespace - Breaking changes: KCL workspaces require migration - Migration bridge available in docs/src/development/
132 lines
4.6 KiB
Plaintext
132 lines
4.6 KiB
Plaintext
# String Validators
|
|
# Workspace names, identifiers, and other string validations
|
|
|
|
{
|
|
# Validate workspace name (alphanumeric, hyphen, underscore, max 64 chars)
|
|
ValidWorkspaceName = fun name =>
|
|
if name == "" then
|
|
std.contract.blame_with_message "Workspace name cannot be empty" name
|
|
else if std.string.length name > 64 then
|
|
std.contract.blame_with_message "Workspace name must be <= 64 characters" name
|
|
else if !std.string.matches "^[a-z0-9_-]+$" name then
|
|
std.contract.blame_with_message
|
|
"Workspace name must contain only lowercase alphanumeric, hyphen, or underscore"
|
|
name
|
|
else
|
|
name,
|
|
|
|
# Validate service name
|
|
ValidServiceName = fun name =>
|
|
if name == "" then
|
|
std.contract.blame_with_message "Service name cannot be empty" name
|
|
else if std.string.length name > 64 then
|
|
std.contract.blame_with_message "Service name must be <= 64 characters" name
|
|
else if !std.string.matches "^[a-z0-9_-]+$" name then
|
|
std.contract.blame_with_message
|
|
"Service name must contain only lowercase alphanumeric, hyphen, or underscore"
|
|
name
|
|
else
|
|
name,
|
|
|
|
# Validate filesystem path
|
|
ValidFilesystemPath = fun path =>
|
|
if path == "" then
|
|
std.contract.blame_with_message "Path cannot be empty" path
|
|
else if std.string.length path > 255 then
|
|
std.contract.blame_with_message "Path must be <= 255 characters" path
|
|
else if std.string.starts_with path "/" then
|
|
path
|
|
else
|
|
std.contract.blame_with_message "Path must be absolute (start with /)" path,
|
|
|
|
# Validate relative path
|
|
ValidRelativePath = fun path =>
|
|
if path == "" then
|
|
std.contract.blame_with_message "Path cannot be empty" path
|
|
else if std.string.length path > 255 then
|
|
std.contract.blame_with_message "Path must be <= 255 characters" path
|
|
else
|
|
path,
|
|
|
|
# Validate hostname/domain
|
|
ValidHostname = fun hostname =>
|
|
if hostname == "" then
|
|
std.contract.blame_with_message "Hostname cannot be empty" hostname
|
|
else if std.string.length hostname > 253 then
|
|
std.contract.blame_with_message "Hostname must be <= 253 characters" hostname
|
|
else if !std.string.matches "^[a-zA-Z0-9.-]+$" hostname then
|
|
std.contract.blame_with_message
|
|
"Hostname must contain only alphanumeric, dot, or hyphen"
|
|
hostname
|
|
else
|
|
hostname,
|
|
|
|
# Validate IP address (basic check)
|
|
ValidIpAddress = fun ip =>
|
|
if ip == "" then
|
|
std.contract.blame_with_message "IP address cannot be empty" ip
|
|
else if !std.string.matches "^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$|^[0-9a-fA-F:]+$" ip then
|
|
std.contract.blame_with_message
|
|
"IP address format invalid (IPv4 or IPv6)"
|
|
ip
|
|
else
|
|
ip,
|
|
|
|
# Validate URL
|
|
ValidUrl = fun url =>
|
|
if url == "" then
|
|
std.contract.blame_with_message "URL cannot be empty" url
|
|
else if !std.string.matches "^https?://" url then
|
|
std.contract.blame_with_message
|
|
"URL must start with http:// or https://"
|
|
url
|
|
else
|
|
url,
|
|
|
|
# Validate password minimum length
|
|
ValidPassword = fun password =>
|
|
if std.string.length password < 8 then
|
|
std.contract.blame_with_message
|
|
"Password must be >= 8 characters"
|
|
password
|
|
else if std.string.length password > 128 then
|
|
std.contract.blame_with_message
|
|
"Password must be <= 128 characters"
|
|
password
|
|
else
|
|
password,
|
|
|
|
# Validate JWT token format
|
|
ValidJwtToken = fun token =>
|
|
if token == "" then
|
|
std.contract.blame_with_message "JWT token cannot be empty" token
|
|
else if !std.string.matches "^[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+\\.[a-zA-Z0-9_-]+$" token then
|
|
std.contract.blame_with_message
|
|
"JWT token format invalid (must be three base64url parts separated by dots)"
|
|
token
|
|
else
|
|
token,
|
|
|
|
# Validate identifier (alphanumeric, underscore, hyphen)
|
|
ValidIdentifier = fun identifier =>
|
|
if identifier == "" then
|
|
std.contract.blame_with_message "Identifier cannot be empty" identifier
|
|
else if !std.string.matches "^[a-z0-9_-]+$" identifier then
|
|
std.contract.blame_with_message
|
|
"Identifier must contain only lowercase alphanumeric, underscore, or hyphen"
|
|
identifier
|
|
else
|
|
identifier,
|
|
|
|
# Validate category/tag name
|
|
ValidCategoryName = fun category =>
|
|
if category == "" then
|
|
std.contract.blame_with_message "Category cannot be empty" category
|
|
else if !std.string.matches "^[a-z0-9_]+$" category then
|
|
std.contract.blame_with_message
|
|
"Category must contain only lowercase alphanumeric or underscore"
|
|
category
|
|
else
|
|
category,
|
|
}
|