/ hermes_cli / vercel_auth.py
vercel_auth.py
 1  """Helpers for reporting Vercel Sandbox authentication state."""
 2  
 3  from __future__ import annotations
 4  
 5  import os
 6  from dataclasses import dataclass
 7  
 8  
 9  _TOKEN_TUPLE_VARS = ("VERCEL_TOKEN", "VERCEL_PROJECT_ID", "VERCEL_TEAM_ID")
10  
11  
12  @dataclass(frozen=True)
13  class VercelAuthStatus:
14      ok: bool
15      label: str
16      detail_lines: tuple[str, ...]
17  
18  
19  def _present(name: str) -> bool:
20      return bool(os.getenv(name))
21  
22  
23  def describe_vercel_auth() -> VercelAuthStatus:
24      """Return Vercel auth status without exposing secret values."""
25  
26      has_oidc = _present("VERCEL_OIDC_TOKEN")
27      token_states = {name: _present(name) for name in _TOKEN_TUPLE_VARS}
28      present_token_vars = tuple(name for name, present in token_states.items() if present)
29      missing_token_vars = tuple(name for name, present in token_states.items() if not present)
30  
31      if has_oidc:
32          details = [
33              "mode: OIDC",
34              "active env: VERCEL_OIDC_TOKEN",
35              "note: OIDC tokens are development-only; use access-token auth for deployments and long-running processes",
36          ]
37          if present_token_vars:
38              details.append(f"also present: {', '.join(present_token_vars)}")
39          return VercelAuthStatus(True, "OIDC token via VERCEL_OIDC_TOKEN", tuple(details))
40  
41      if not missing_token_vars:
42          return VercelAuthStatus(
43              True,
44              "access token + project/team via VERCEL_TOKEN, VERCEL_PROJECT_ID, VERCEL_TEAM_ID",
45              (
46                  "mode: access token",
47                  "active env: VERCEL_TOKEN, VERCEL_PROJECT_ID, VERCEL_TEAM_ID",
48              ),
49          )
50  
51      if present_token_vars:
52          return VercelAuthStatus(
53              False,
54              f"partial access-token auth (missing {', '.join(missing_token_vars)})",
55              (
56                  "mode: incomplete access token",
57                  f"present env: {', '.join(present_token_vars)}",
58                  f"missing env: {', '.join(missing_token_vars)}",
59                  "recommended: set VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID together",
60              ),
61          )
62  
63      return VercelAuthStatus(
64          False,
65          "not configured",
66          (
67              "recommended: set VERCEL_TOKEN, VERCEL_PROJECT_ID, and VERCEL_TEAM_ID",
68              "development-only alternative: set VERCEL_OIDC_TOKEN",
69          ),
70      )