asf-tooling commented on issue #250:
URL:
https://github.com/apache/tooling-trusted-releases/issues/250#issuecomment-4410407217
<!-- gofannon-issue-triage-bot v2 -->
**Automated triage** — analyzed at `main@2da7807a`
**Type:** `discussion` • **Classification:** `no_action` •
**Confidence:** `medium`
**Application domain(s):** `automated_checks`, `announcement_publishing`
### Summary
Issue #250 requests implementing basic attestations (proof of concept) for
ATR releases in a standardized format. The discussion converged on SLSA v1.2 as
the target framework (@dave2wave noted SLSA v1.2 'has enough defined that we
can design more than a proof'), with GitHub's attestation tooling as a
practical reference. While ATR already has internal 'attestable' metadata
tracking (file hashes, provenance, check results in atr/attestable.py and
atr/models/attestable.py), it does NOT yet produce standardized SLSA/in-toto
format attestations consumable by external tools. No concrete implementation
spec has been agreed upon beyond the general direction.
### Where this lives in the code today
#### `atr/models/attestable.py` — `AttestableV2` (lines 70-74)
_extension point_
Current internal attestable metadata model - tracks file hashes, paths with
classifications, and provenance. This data would serve as input to produce
SLSA-format attestations.
```python
class AttestableV2(schema.Strict):
version: Literal[2] = 2
hashes: dict[str, HashEntryV2] = schema.factory(dict)
paths: dict[str, PathEntryV2] = schema.factory(dict)
policy: dict[str, Any] = schema.factory(dict)
```
#### `atr/models/attestable.py` — `ProvenanceV2` (lines 59-61)
_extension point_
Internal provenance tracking with a generator enum. This would need to be
mapped to SLSA provenance predicates in a standardized attestation format.
```python
class ProvenanceV2(schema.Strict):
generator: GeneratorV2
metadata: dict[str, Any] = schema.factory(dict)
```
#### `atr/attestable.py` — `github_tp_payload_read` (lines 206-227)
_extension point_
GitHub Trusted Publisher OIDC payload reading - this already captures
provenance from GitHub Actions which would feed into SLSA provenance
attestations.
```python
async def github_tp_payload_read(
project_key: safe.ProjectKey, version_key: safe.VersionKey,
revision_number: safe.RevisionNumber
) -> github.TrustedPublisherPayload | None:
payload_path = github_tp_payload_path(project_key, version_key,
revision_number)
if not await aiofiles.os.path.isfile(payload_path):
return None
try:
async with aiofiles.open(payload_path, encoding="utf-8") as f:
data = json.loads(await f.read())
if not isinstance(data, dict):
log.warning(f"TP payload was not a JSON object in
{payload_path}")
return None
# Remove exp and nbf if they're stored - as of 2026-03-18 they're
validated and then removed before storage
# but we might have older data
if "exp" in data:
del data["exp"]
if "nbf" in data:
del data["nbf"]
return github.TrustedPublisherPayload.model_validate(data)
except (OSError, json.JSONDecodeError) as e:
log.warning(f"Failed to read TP payload from {payload_path}: {e}")
return None
```
#### `atr/models/attestable.py` — `AttestableChecksV2` (lines 94-96)
_extension point_
Records check results per file - these check outcomes would be attestable
claims in a standardized format.
```python
class AttestableChecksV2(schema.Strict):
version: Literal[2] = 2
checks: dict[str, dict[str, str]] = schema.factory(dict)
```
#### `atr/storage/writers/announce.py` — `CommitteeMember.release` (lines
103-115)
_extension point_
The release publication workflow - a natural point where finalized
attestations could be generated and published alongside the release artifacts.
```python
async def release( # noqa: C901
self,
project_key: safe.ProjectKey,
version_key: safe.VersionKey,
preview_revision_number: safe.RevisionNumber,
email_to: str,
body: str,
download_path_suffix: safe.RelPath | None,
fullname: str,
subject_template_hash: str | None = None,
email_cc: list[str] | None = None,
email_bcc: list[str] | None = None,
) -> None:
```
#### `atr/tasks/checks/signature.py` — `check` (lines 38-50)
_currently does this_
Existing signature verification check - its results (valid signature, signer
identity) would be claims in a SLSA attestation.
```python
async def check(args: checks.FunctionArguments) -> results.Results | None:
"""Check a signature file."""
recorder = await args.recorder(CHECK_VERSION)
if not (primary_abs_path := await recorder.abs_path()):
return None
if not (primary_rel_path := args.primary_rel_path):
await recorder.exception("Primary relative path is required",
{"primary_rel_path": primary_rel_path})
return None
artifact_rel_path = str(primary_rel_path).removesuffix(".asc")
if not (artifact_abs_path := await recorder.abs_path(artifact_rel_path)):
return None
```
### Where new code would go
- `atr/slsa.py` — new file
New module to generate SLSA v1.2 attestations (in-toto format statements)
from ATR's internal attestable data, check results, and provenance information.
- `atr/models/slsa.py` — new file
Pydantic models for SLSA v1.2 attestation predicates (provenance,
verification summary) following the in-toto statement specification.
- `atr/tasks/attestation.py` — new file
Task to generate attestations at appropriate lifecycle points (post-vote,
pre-release) using the internal metadata and check results.
### Proposed approach
The implementation would involve: (1) Creating Pydantic models for SLSA v1.2
in-toto attestation statements (subjects with digests, predicates for
provenance), following the spec at slsa.dev/spec/v1.2/attestation-model. (2)
Building a module that transforms ATR's internal attestable data (AttestableV2
paths/hashes, check results, GitHub TP payloads) into SLSA-format attestations.
(3) Integrating attestation generation into the release lifecycle — likely at
the point where a release transitions to preview or is published. (4) Exposing
generated attestations in the UI so users can review them, and making them
downloadable alongside release artifacts.
However, since the discussion is still collecting references and no concrete
implementation decisions have been documented (e.g., which specific SLSA
predicate types to emit first, whether to use Sigstore bundles or standalone
statements, how to sign the attestations), this issue remains in the design
phase. The team should decide: what predicates to emit (provenance?
verification summary?), what signing mechanism (ASF project keys? Sigstore?),
and what the minimal viable attestation looks like before coding begins.
### Open questions
- Which SLSA predicate types should be implemented first - provenance (build
origin), verification summary (checks passed), or both?
- Should attestations be signed with ASF project OpenPGP keys,
Sigstore/Fulcio certificates, or both?
- Should attestations follow the in-toto bundle format (as used by
GitHub/PyPI) or be standalone JSON statements?
- At what lifecycle point should attestations be generated - at each
revision commit, at vote start, at release publication, or all of the above?
- How should the OIDC issuer policy enforcement (Piotr's request documented
by @sbp) interact with the basic attestation PoC?
- Is there an existing Python library for producing SLSA/in-toto
attestations that should be used (e.g., in-toto-python, sigstore-python)?
_The agent reviewed this issue and is not proposing patches in this run.
Review the existing-code citations and open questions above before deciding
next steps._
### Files examined
- `atr/models/attestable.py`
- `atr/attestable.py`
- `atr/tasks/checks/__init__.py`
- `atr/hashes.py`
- `atr/tasks/checks/signature.py`
- `atr/storage/writers/announce.py`
- `atr/tasks/checks/hashing.py`
- `atr/detection.py`
---
*Draft from a triage agent. A human reviewer should validate before merging
any change. The agent did not run tests or verify diffs apply.*
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]