feat(naming): system-server names, validation, and service-token identifiers
SystemLoginServer/SystemLobbyServer plus ValidateSystemServerName (format rule without the reservation check) let the platform provision the reserved login/lobby names users can never claim. ServiceTokenSecretName/Key are the one source of truth for the internal-API credential Secret, shared by the platform renderer and the operator's login-pod injection.
This commit is contained in:
2 files changed
+79
No files matched your search
@@ -30,6 +30,32 @@ var reserved = map[string]struct{}{
|
|||||||
"www": {},
|
"www": {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// System server names Felis provisions itself. They deliberately live on the
|
||||||
|
// reserved list so no user can claim them, yet the platform must be able to
|
||||||
|
// create them — see ValidateSystemServerName.
|
||||||
|
const (
|
||||||
|
// SystemLoginServer is the always-on limbo auth gate (LOOHP/Limbo). It is the
|
||||||
|
// front door every fresh connection lands on and the ONLY safe fallback: a
|
||||||
|
// stopped/starting backend routes here, never onward past authentication.
|
||||||
|
SystemLoginServer = "login"
|
||||||
|
// SystemLobbyServer is the post-auth /menu hub (Paper + felis-paper). It is
|
||||||
|
// reachable only after the login gate passes a player through, so it must
|
||||||
|
// never be used as a fallback target (that would bypass the gate).
|
||||||
|
SystemLobbyServer = "lobby"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ServiceTokenSecretName / ServiceTokenSecretKey name the internal-API bearer
|
||||||
|
// credential Secret (spec §7). They are one source of truth shared across
|
||||||
|
// subsystems: the platform renderer wires this Secret into the felis-api
|
||||||
|
// Deployment, and the operator injects it into the login system server's pod as
|
||||||
|
// FELIS_SERVICE_TOKEN via a secretKeyRef (never a literal). The Secret itself is
|
||||||
|
// provisioned out-of-band (deploy/bootstrap.sh) and, for the login gate, replicated
|
||||||
|
// into the minecraft namespace by `felis setup`; these constants only name it.
|
||||||
|
const (
|
||||||
|
ServiceTokenSecretName = "felis-service-token"
|
||||||
|
ServiceTokenSecretKey = "token"
|
||||||
|
)
|
||||||
|
|
||||||
// ValidateServerName checks the §22 name rule and reservation list.
|
// ValidateServerName checks the §22 name rule and reservation list.
|
||||||
func ValidateServerName(name string) error {
|
func ValidateServerName(name string) error {
|
||||||
if !serverNameRE.MatchString(name) {
|
if !serverNameRE.MatchString(name) {
|
||||||
@@ -44,6 +70,22 @@ func ValidateServerName(name string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateSystemServerName checks the §22 format rule (^[a-z0-9-]{3,32}$, no
|
||||||
|
// leading/trailing dash) but DELIBERATELY skips the reservation check. It is the
|
||||||
|
// admission path for platform-provisioned system services (login, lobby), which
|
||||||
|
// carry reserved names on purpose: users can never claim them via
|
||||||
|
// ValidateServerName, yet setup must still be able to create them. It is not a
|
||||||
|
// public claim path — only the setup/system-service provisioner calls it.
|
||||||
|
func ValidateSystemServerName(name string) error {
|
||||||
|
if !serverNameRE.MatchString(name) {
|
||||||
|
return fmt.Errorf("naming: invalid system server name %q: must match ^[a-z0-9-]{3,32}$", name)
|
||||||
|
}
|
||||||
|
if strings.HasPrefix(name, "-") || strings.HasSuffix(name, "-") {
|
||||||
|
return fmt.Errorf("naming: system server name %q must not start or end with '-'", name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsReserved reports whether label is on the reserved list.
|
// IsReserved reports whether label is on the reserved list.
|
||||||
func IsReserved(label string) bool {
|
func IsReserved(label string) bool {
|
||||||
_, ok := reserved[label]
|
_, ok := reserved[label]
|
||||||
|
|||||||
@@ -37,6 +37,43 @@ func TestValidateServerName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ValidateSystemServerName keeps the format rule but drops the reservation
|
||||||
|
// check, so the platform can provision the reserved system names (login, lobby)
|
||||||
|
// that ValidateServerName correctly refuses to hand to users.
|
||||||
|
func TestValidateSystemServerName(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
ok bool
|
||||||
|
}{
|
||||||
|
{"login", true}, // reserved, but a legal system service
|
||||||
|
{"lobby", true}, // reserved, but a legal system service
|
||||||
|
{"admin", true}, // reserved names are allowed on this path
|
||||||
|
{"survival", true},
|
||||||
|
{"ab", false}, // still too short
|
||||||
|
{"Login", false}, // still case-sensitive
|
||||||
|
{"-leading", false}, // still no leading hyphen
|
||||||
|
{"has space", false}, // still no illegal chars
|
||||||
|
}
|
||||||
|
for _, c := range cases {
|
||||||
|
err := naming.ValidateSystemServerName(c.name)
|
||||||
|
if c.ok && err != nil {
|
||||||
|
t.Errorf("ValidateSystemServerName(%q) = %v, want ok", c.name, err)
|
||||||
|
}
|
||||||
|
if !c.ok && err == nil {
|
||||||
|
t.Errorf("ValidateSystemServerName(%q) = nil, want error", c.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The two paths must genuinely differ on reserved names: user path refuses
|
||||||
|
// "lobby", system path accepts it.
|
||||||
|
if naming.ValidateServerName("lobby") == nil {
|
||||||
|
t.Error("ValidateServerName(lobby) accepted; reserved name must be refused for users")
|
||||||
|
}
|
||||||
|
if naming.ValidateSystemServerName("lobby") != nil {
|
||||||
|
t.Error("ValidateSystemServerName(lobby) refused; system path must accept it")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestWorldPVCName(t *testing.T) {
|
func TestWorldPVCName(t *testing.T) {
|
||||||
cases := map[string]string{
|
cases := map[string]string{
|
||||||
"survival": "world-survival-0",
|
"survival": "world-survival-0",
|
||||||
|
|||||||
Reference in new issue
Block a user