asf-tooling commented on issue #326:
URL:
https://github.com/apache/tooling-trusted-releases/issues/326#issuecomment-4410381746
<!-- gofannon-issue-triage-bot v2 -->
**Automated triage** — analyzed at `main@2da7807a`
**Type:** `new_feature` • **Classification:** `no_action` •
**Confidence:** `high`
**Application domain(s):** `authentication_authorization`,
`distribution_tracking`, `admin_operations`
### Summary
Issue #326 requests a two-approval workflow for critical/irreversible
actions (project deletion/archival, release deployment, vote-period bypass).
After extensive discussion spanning 6 months, @dave2wave's most recent comment
(1 day ago) directs to #1230, indicating the implementation is being tracked
there. @dave2wave also noted (2026-04-05) that the team has been discussing a
'separate service to handle contingent approvals and other approval evidence.'
No two-approval mechanism currently exists in the codebase.
### Where this lives in the code today
#### `atr/blueprints/admin.py` — `_check_admin_access` (lines 156-163)
_extension point_
Current admin access check only verifies single-user authentication; a
two-approval gate would extend or wrap this authorization model.
```python
@_BLUEPRINT.before_request
async def _check_admin_access() -> None:
web_session = await sessions.read()
if not isinstance(web_session, sql.UserSession):
raise base.ASFQuartException("Not authenticated", errorcode=401)
if not user.is_admin(web_session.uid):
raise base.ASFQuartException("You are not authorized to access the
admin interface", errorcode=403)
```
#### `atr/admin/__init__.py` — `delete_release_post` (lines 145-156)
_extension point_
Release deletion is one of the actions @dave2wave identified as requiring a
two-approval gate.
```python
@admin.typed
async def delete_release_post(
session: web.Committer, _delete_release_get: Literal["delete-release"],
delete_form: DeleteReleaseForm
) -> str | web.WerkzeugResponse:
"""
URL: POST /delete-release
Delete selected releases and their associated data and files.
"""
await _delete_releases(session, delete_form.releases_to_delete)
return await session.redirect(delete_release_get)
```
#### `atr/storage/writers/distributions.py` — `CommitteeMember.automate`
(lines 95-108)
_extension point_
Distribution automation (pushing to Maven Central) was the original example
@killerbees cited as needing two-key approval.
```python
async def automate(
self,
release_key: models.safe.ReleaseKey,
platform: models.sql.DistributionPlatform,
committee_key: str,
owner_namespace: models.safe.Alphanumeric | None,
project_key: models.safe.ProjectKey,
version_key: models.safe.VersionKey,
phase: str,
revision_number: str | None,
package: models.safe.Alphanumeric,
version: models.safe.VersionKey,
staging: bool,
) -> models.sql.Task:
```
#### `atr/post/distribution.py` — `automate_form_process_page` (lines 41-57)
_extension point_
The POST handler for distribution automation would need to incorporate
approval gating before executing the action.
```python
async def automate_form_process_page(
session: web.Committer,
form_data: shared.distribution.DistributionAutomateForm,
project: safe.ProjectKey,
version: safe.VersionKey,
/,
staging: bool = False,
) -> web.WerkzeugResponse:
allowed_platforms = _AUTOMATED_PLATFORMS_STAGE if staging else
_AUTOMATED_PLATFORMS
if form_data.platform not in allowed_platforms:
platform_str = form_data.platform.value
return await session.redirect(
get.distribution.stage_automate if staging else
get.distribution.automate,
project_key=str(project),
version_key=str(version),
error=f"Platform {platform_str} is not supported for automated
distribution",
)
```
### Where new code would go
- `atr/models/sql.py` — new table alongside existing models
A new Approval or PendingAction table would be needed to store approval
requests, who initiated them, who approved them, and timestamps.
- `atr/tasks/approval.py` — new file
A background task to send approval emails to PMC private lists and handle
expiration would live here, per @dave2wave's 4-step workflow design.
- `atr/get/approval.py` — new file
GET route for displaying the approval confirmation page (step 4 of
@dave2wave's design) when a PMC member clicks the approval link from email.
- `atr/post/approval.py` — new file
POST handler for submitting an approval, which then triggers the guarded
action if sufficient approvals are collected.
### Proposed approach
The team has redirected this work to issue #1230 (per @dave2wave's comment
from 2026-05-07). Additionally, @dave2wave noted on 2026-04-05 that they are
discussing a 'separate service to handle contingent approvals and other
approval evidence.' Given that (a) the latest comment explicitly points to
#1230 as the locus of work, and (b) the team is considering a separate service
rather than inline implementation, no diff should be proposed here. The work
should be tracked and reviewed in #1230.
The general architectural shape, per the discussion, would involve: a new
database model for pending approvals, email integration to notify PMC private
lists, a URL-based approval mechanism with access_check_committee guards, and
guards on specific transitions (project archival/deletion, release deployment,
vote-period overrides).
### Open questions
- What is the scope and status of issue #1230 that @dave2wave referenced?
- Is the 'separate service' for approvals being developed in another
repository, or will it be integrated into ATR?
- Which specific SQL model fields/tables would the approval service need?
- Should the approval mechanism use email-based links (as @dave2wave
proposed in the 4-step flow) or an in-app approval UI, or both?
- How does this interact with the existing vote mechanism that already
requires 3 +1 PMC votes for releases?
_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/get/distribution.py`
- `atr/post/distribution.py`
- `atr/shared/distribution.py`
- `atr/storage/writers/distributions.py`
- `atr/admin/__init__.py`
- `atr/tasks/distribution.py`
- `atr/blueprints/admin.py`
- `atr/models/distribution.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]