fix(secrets): admit periods in Secret names and namespace segments

LanceDB namespace names permit periods, so excluding them here put Secrets out
of reach inside any namespace a user already has one in -- unreachable to
create, alter, describe, drop or bind, with no way to recover but renaming the
namespace.

The exclusion was reasoned from delimiter ambiguity, and that argument only
covers the delimiter itself. Identifiers join on the id delimiter, and a period
separates a column from a nested field, which is a grammar this layer never
meets. Names and path segments widen together: the join has to read the same
from either side, so a rule that held for one and not the other would be worse
than either.

Also drops a `pub(crate)` that local clippy flags as redundant inside a private
module. CI does not flag it, so this is tidying rather than a fix.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UfmeJ533rQDnPBkMtjerV6
This commit is contained in:
Jonathan M Hsieh
2026-09-09 20:47:46 +00:00
co-authored by Claude Opus 5
parent e541a3be93
commit def04be12e
3 changed files with 19 additions and 2 deletions
+5 -1
View File
@@ -14,7 +14,11 @@ from __future__ import annotations
import re
_SECRET_NAME = re.compile(r"^[A-Za-z0-9_-]{1,255}$")
# Periods are legal: identifiers are joined by the id delimiter (`$`), and a
# period separates a column from a nested field, which is a different grammar
# entirely. Excluding it would put Secrets out of reach of any namespace whose
# name carries one, which LanceDB namespaces allow.
_SECRET_NAME = re.compile(r"^[A-Za-z0-9_.-]{1,255}$")
_ENV_VARIABLE = re.compile(r"^[A-Za-z_][A-Za-z0-9_]*$")
@@ -281,6 +281,7 @@ def test_a_credential_value_is_rejected_in_the_binding_position():
("openai-prod", "not-a-var", "invalid environment variable name"),
("openai-prod", "API-TOKEN", "invalid environment variable name"),
("not a name", "API_TOKEN", "invalid Secret name"),
("openai$prod", "API_TOKEN", "invalid Secret name"),
],
)
def test_a_binding_validates_both_names_locally(secret, variable, message):
@@ -288,6 +289,18 @@ def test_a_binding_validates_both_names_locally(secret, variable, message):
EnvVarSecret(secret=secret, env_variable=variable)
def test_a_secret_name_may_carry_a_period():
"""A period is not a delimiter at this layer.
Identifiers join on the id delimiter and a period separates a column from a
nested field, so nothing here can parse two ways. LanceDB namespaces already
permit one, and excluding it would put Secrets out of reach inside them.
"""
binding = EnvVarSecret(secret="openai.prod.v1", env_variable="OPENAI_API_KEY")
assert binding.secret == "openai.prod.v1"
def _main_udf_source(
*, threshold: int = 20, input_annotation: str = "int", comparison: str = ">="
) -> str:
+1 -1
View File
@@ -412,7 +412,7 @@ fn validate_dns_hostname(hostname: &str) -> Result<()> {
/// remembering to extend this. Every secrets route is denied, not only the two
/// that carry a value: their bodies hold names and page tokens, which are worth
/// nothing in a debug log next to the risk of a new verb landing here unnoticed.
pub(crate) fn route_carries_credential(path: &str) -> bool {
fn route_carries_credential(path: &str) -> bool {
path.split('/').any(|segment| segment == "secrets")
}