"""netkingdom publication-scope policy: bind npm publication scope to maturity. Resolves, for a publish lane, the *effective* publication scope and the token env-var name to inject. The graduated maturity->scope table only activates once netkingdom is production grade; until then every lane clamps to repo-scope (fail-safe). This is the policy-binding the catalog data feeds into. """ from __future__ import annotations import re from dataclasses import dataclass from pathlib import Path from typing import Any import yaml from secrets_engine.errors import PolicyGuardError VALID_MATURITY = ("maturity-build", "maturity-test", "maturity-prod") VALID_SCOPES = ("gitea", "org", "scope", "repo") # Narrow (small index) to broad (large index) — repo is narrowest, gitea broadest. SCOPE_BREADTH = {"repo": 0, "scope": 1, "org": 2, "gitea": 3} @dataclass(frozen=True) class PublicationPolicy: domain: str netkingdom_maturity: str maturity_scope: dict[str, str] dormant_scope: str token_env: dict[str, str] raw: dict[str, Any] @property def production_grade(self) -> bool: return self.netkingdom_maturity == "maturity-prod" @classmethod def load(cls, policy_dir: Path) -> "PublicationPolicy": path = Path(policy_dir) / "netkingdom-publication-scope.yaml" if not path.exists(): raise PolicyGuardError(f"publication-scope policy not found: {path}") data = yaml.safe_load(path.read_text(encoding="utf-8")) or {} maturity = data.get("netkingdom_maturity") if maturity not in VALID_MATURITY: raise PolicyGuardError( f"{path}: netkingdom_maturity '{maturity}' invalid; {VALID_MATURITY}" ) return cls( domain=data.get("domain", "netkingdom"), netkingdom_maturity=maturity, maturity_scope=data.get("maturity_scope", {}), dormant_scope=data.get("dormant_scope", "repo"), token_env=data.get("token_env", {}), raw=data, ) @dataclass(frozen=True) class Resolution: package_maturity: str effective_scope: str token_env: str active: bool # is the graduated table in effect? clamped: bool # was a broader maturity scope clamped to dormant_scope? rationale: str def render(self) -> str: return ( f" netkingdom production-grade: {self.active}\n" f" package maturity: {self.package_maturity}\n" f" effective publication scope: {self.effective_scope}" f"{' (clamped from graduated table — fail-safe)' if self.clamped else ''}\n" f" inject token as env var: {self.token_env}\n" f" rationale: {self.rationale}" ) def _slug(value: str) -> str: """COULOMB / WHYNOT / WHYNOTDESIGN — upper, strip @ and non-alphanumerics.""" return re.sub(r"[^A-Za-z0-9]", "", value).upper() def _render_env(template: str, *, org: str, npm_scope: str, repo: str) -> str: return ( template.replace("{ORG}", _slug(org)) .replace("{SCOPE}", _slug(npm_scope)) .replace("{REPO}", _slug(repo)) ) def resolve( policy: PublicationPolicy, *, org: str, repo: str, npm_scope: str, package_maturity: str, token_env_override: str = "", ) -> Resolution: """Resolve effective scope + token env for a lane under the policy.""" if package_maturity not in VALID_MATURITY: raise PolicyGuardError( f"package maturity '{package_maturity}' invalid; {VALID_MATURITY}" ) if not policy.production_grade: effective = policy.dormant_scope graduated = policy.maturity_scope.get(package_maturity, effective) clamped = SCOPE_BREADTH[graduated] > SCOPE_BREADTH[effective] rationale = ( f"netkingdom is '{policy.netkingdom_maturity}', not production grade — " f"graduated scoping is dormant; clamped to '{effective}'" if clamped else f"netkingdom dormant; lane already at safe scope '{effective}'" ) active = False else: effective = policy.maturity_scope.get(package_maturity) if effective not in VALID_SCOPES: raise PolicyGuardError( f"no scope mapped for maturity '{package_maturity}'" ) clamped = False active = True rationale = ( f"netkingdom production grade — {package_maturity} maps to " f"'{effective}' publication scope" ) if token_env_override: token_env = token_env_override else: template = policy.token_env.get(effective, "NPM_AUTH_TOKEN") token_env = _render_env(template, org=org, npm_scope=npm_scope, repo=repo) return Resolution( package_maturity=package_maturity, effective_scope=effective, token_env=token_env, active=active, clamped=clamped, rationale=rationale, )