Skip to content

Commit 433d7e1

Browse files
committed
feat(sigstore): scaffold opt-in signing surface (Round 2 #16)
Phase F (signed releases via sigstore) needs a key-management ADR before it can ship in full. The scaffold + opt-in extras land today so the surface is stable: - pyproject.toml: new [sigstore] extras pulls sigstore>=3.0 - verify.sign_bundle_with_sigstore(bundle_path, dry_run=True): - Raises SecurityError if sigstore isn't installed (clear path: `pip install 'get-installer[sigstore]'`) - dry_run=True returns the planned .sigstore path; no signing - dry_run=False raises NotImplementedError with a pointer to SPEC Phase F. We prefer fail-loud to silent no-op. When the ADR lands, the implementation slots in behind this same signature and existing callers don't change.
1 parent 054a35b commit 433d7e1

2 files changed

Lines changed: 42 additions & 0 deletions

File tree

pyproject.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ dev = [
4747
"ruff>=0.9",
4848
"mypy>=1.13",
4949
]
50+
# `pip install 'get-installer[sigstore]'` enables future signed-bundle
51+
# attestations (SPEC Phase F). Skeleton wired; full signing flow is
52+
# pending the key-management ADR (which signing identity, key
53+
# rotation, where the public verification key ships).
54+
sigstore = ["sigstore>=3.0"]
5055

5156
[project.scripts]
5257
get-installer = "get_installer.__main__:main"

src/get_installer/verify.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,43 @@ def _hardened_ssl_context() -> ssl.SSLContext:
3939
return ctx
4040

4141

42+
def sign_bundle_with_sigstore(
43+
bundle_path: Path,
44+
*,
45+
dry_run: bool = True,
46+
) -> Path:
47+
"""Sign ``bundle_path`` with sigstore (SCAFFOLD — Phase F).
48+
49+
Wired today as a clean opt-in surface; full signing is pending
50+
the key-management ADR. Install with::
51+
52+
pip install 'get-installer[sigstore]'
53+
54+
@param bundle_path the installer.py to sign.
55+
@param dry_run no actual signing yet.
56+
@return the .sig path that would be written.
57+
@raises SecurityError when sigstore is not installed.
58+
@raises NotImplementedError when called with dry_run=False —
59+
we'd rather fail loudly than silently produce a no-op.
60+
"""
61+
try:
62+
import sigstore # type: ignore[import-not-found] # noqa: F401 # optional [sigstore] extra
63+
except ImportError as e:
64+
raise SecurityError(
65+
"Sigstore signing requires the sigstore package. "
66+
"Install via: pip install 'get-installer[sigstore]'"
67+
) from e
68+
sig_path = bundle_path.with_suffix(bundle_path.suffix + ".sigstore")
69+
if dry_run:
70+
return sig_path
71+
raise NotImplementedError(
72+
"Sigstore signing is pending the key-management ADR. The "
73+
"scaffold + extras install are ready; the actual sign() call + "
74+
"verification command land in a follow-up release. See "
75+
"SPEC §4 Phase F for the design questions still open."
76+
)
77+
78+
4279
def sha256_of(path: Path) -> str:
4380
h = hashlib.sha256()
4481
with open(path, "rb") as f:

0 commit comments

Comments
 (0)