scopes.py python
64 lines 2.0 KB
Raw
sha256:0e9549ec7b463911bc08b7d586dc320b1ac9b1f5c943ee7e3865dcc6cb0f6f83 chore(governance): sync handover+roadmap to 84db8c8 (drift:… Human 1 day ago
1 """Upstream credential scope refuse helpers (§HGD.6.2)."""
2
3 from __future__ import annotations
4
5 # Conceptual write-class scopes — refuse when advertised by host introspection.
6 REJECTED_SCOPE_TOKENS = frozenset(
7 {
8 "contents:write",
9 "administration",
10 "admin:org",
11 "admin:repo_hook",
12 "admin:org_hook",
13 "workflows",
14 "delete_repo",
15 "workflow",
16 "repo:status", # not write; keep focused on true write classes below
17 }
18 )
19
20 # Explicit write-class tokens used by tests and startup checks.
21 WRITE_SCOPE_TOKENS = frozenset(
22 {
23 "contents:write",
24 "administration",
25 "admin:org",
26 "admin:repo_hook",
27 "admin:org_hook",
28 "workflows",
29 "workflow",
30 "delete_repo",
31 "repo", # classic full-access PAT — refuse when introspected
32 }
33 )
34
35 # Narrow read-only conceptual scopes (informational).
36 READ_SCOPE_TOKENS = frozenset(
37 {
38 "contents:read",
39 "metadata:read",
40 "public_repo", # classic public read — handled carefully; prefer contents:read
41 }
42 )
43
44
45 def scopes_contain_write_class(scopes: frozenset[str] | set[str] | list[str] | None) -> bool:
46 """Return True when any advertised scope is a rejected write class.
47
48 When scopes cannot be introspected (``None``), returns False so the operator
49 runbook + tests must prove write HTTP verbs are unreachable.
50 """
51 if scopes is None:
52 return False
53 normalized = {s.strip().lower() for s in scopes if isinstance(s, str) and s.strip()}
54 write_normalized = {s.lower() for s in WRITE_SCOPE_TOKENS}
55 # ``repo`` is classic full access — refuse when present among introspected scopes
56 # unless the only intersection is empty.
57 return bool(normalized & write_normalized)
58
59
60 def refuse_write_scopes(scopes: frozenset[str] | set[str] | list[str] | None) -> str | None:
61 """Return error token ``write_scope_refused`` when write scopes are present."""
62 if scopes_contain_write_class(scopes):
63 return "write_scope_refused"
64 return None
File History 1 commit
sha256:6abcf1fa82a7a621ccbc945f19acdba5bc0db54569599404a1452fb4a096a199 fix(ISR): default require_independent_second_reviewer to require Human minor 1 day ago