Web Console: Requests, intent preview, authorization, and workflow initiation (Phase 2) #643

Closed
opened 2026-07-10 14:40:42 -05:00 by jcwalker3 · 1 comment
Owner

Problem statement

Operators need to submit requests (start author/reviewer/merger/controller work) with intent preview, authorization checks, and safe workflow initiation without pasting prompts or bypassing allocator/leases.

User and operational impact

Manual prompt paste and unsafe self-selection of work continue; concurrent collisions remain likely.

Scope

  • Request model: desired role, issue/PR, intent summary.
  • Preview: capability check, lease availability, next-safe-action, prohibited actions.
  • Initiate only via allocator/sanctioned tools; record assignment + audit.
  • UI form + API behind RBAC (#633); dry-run default.

Explicit non-goals

  • No direct browser Gitea merge/approve.
  • No bypass of allocator exclusive ownership (#600/#613).
  • No auto-start from raw monitoring incidents.

Required implementation investigation

allocator_service.py, #600, #613, #434 gated actions, #633, #640 traffic view, #628, #631.

Proposed architecture or implementation direction

POST /api/v1/requests/preview and .../apply with confirmation; server calls allocator; returns assignment handoff reference.

Security and workflow-safety requirements

RBAC; fail closed; audit; head pinning for PR work; no silent lease steal.

Acceptance criteria

  1. Preview shows authorize/deny with reasons.
  2. Apply creates exclusive assignment or returns wait/blocked.
  3. Duplicate assign rejected.
  4. Tests for preview/apply/deny/collision.
  5. UI never shows full secrets; brief user messaging.

Required tests

Allocator integration tests with fakes; gated action tests.

Observability and audit requirements

Audit every preview apply; correlation id to assignment.

Dependencies and linkage

Canonical issue state

STATE: ready-for-author
WHO_IS_NEXT: author
NEXT_ACTION: Implement request preview/initiate after auth+traffic
NEXT_PROMPT: Author request initiation gates; PR; stop

Required final evidence

PR with APIs, UI, tests, docs.

Required final response and handoff expectations

Brief PR → reviewer.

## Problem statement Operators need to submit **requests** (start author/reviewer/merger/controller work) with **intent preview**, authorization checks, and safe **workflow initiation** without pasting prompts or bypassing allocator/leases. ## User and operational impact Manual prompt paste and unsafe self-selection of work continue; concurrent collisions remain likely. ## Scope * Request model: desired role, issue/PR, intent summary. * Preview: capability check, lease availability, next-safe-action, prohibited actions. * Initiate only via allocator/sanctioned tools; record assignment + audit. * UI form + API behind RBAC (#633); dry-run default. ## Explicit non-goals * No direct browser Gitea merge/approve. * No bypass of allocator exclusive ownership (#600/#613). * No auto-start from raw monitoring incidents. ## Required implementation investigation `allocator_service.py`, #600, #613, #434 gated actions, #633, #640 traffic view, #628, #631. ## Proposed architecture or implementation direction `POST /api/v1/requests/preview` and `.../apply` with confirmation; server calls allocator; returns assignment handoff reference. ## Security and workflow-safety requirements RBAC; fail closed; audit; head pinning for PR work; no silent lease steal. ## Acceptance criteria 1. Preview shows authorize/deny with reasons. 2. Apply creates exclusive assignment or returns wait/blocked. 3. Duplicate assign rejected. 4. Tests for preview/apply/deny/collision. 5. UI never shows full secrets; brief user messaging. ## Required tests Allocator integration tests with fakes; gated action tests. ## Observability and audit requirements Audit every preview apply; correlation id to assignment. ## Dependencies and linkage * Parent: #631 · Depends: #633, #640 · Related: #600, #613, #628, #434 ## Canonical issue state ```text STATE: ready-for-author WHO_IS_NEXT: author NEXT_ACTION: Implement request preview/initiate after auth+traffic NEXT_PROMPT: Author request initiation gates; PR; stop ``` ## Required final evidence PR with APIs, UI, tests, docs. ## Required final response and handoff expectations Brief PR → reviewer.
jcwalker3 added the type:featurestatus:readyworkflow-hardeningdashboard labels 2026-07-10 14:40:43 -05:00
jcwalker3 added status:pr-open and removed status:ready labels 2026-07-25 00:53:59 -05:00
Owner

Canonical Issue State

STATE: PR-open
WHO_IS_NEXT: author
NEXT_ACTION: Address the two code blockers on PR #902 at head 433f66ad and push fixes to feat/issue-643-request-preview-initiate, then request a fresh review.
NEXT_PROMPT:

Act as author on Scaled-Tech-Consulting/Gitea-Tools issue #643, PR #902, remote prgs. Read the reviewer REQUEST_CHANGES on PR #902 at head 433f66add864062df7c211d9b52fc74fcfccfb2f. Two code blockers must be resolved.

B1: in webui/request_service.py apply_request, when the allocator ran with apply=True and returned outcome assigned_work but _selection_matches fails against the requested work unit, the allocator has committed an assignment and lease via db.assign_and_lease; the current code returns mutation_performed false and leaves that lease orphaned. Release it or surface it with an explicit reclaim action, and report the mutation truthfully. The same state is reachable when _run_allocator's bare except Exception swallows an exception raised after the commit, since allocate_next_work only catches InvalidWorkKindError, LeaseRequiredError, and ControlPlaneError. Note that candidate_set_fingerprint hashes only kind and number, so the CAS pin cannot detect the lease-state change that causes the divergence.

B2: allocate_next_work calls db.upsert_session and db.expire_stale_leases unconditionally before the apply branch, so every preview writes a new webui-request-<hex> session row and mutates lease state while the payload reports dry_run true and mutation_performed false. Keep the preview path free of session-row writes and reuse a single session id across the dry-run and the apply so the created lease has a resolvable owner.

Tests: tests/test_webui_request_initiation.py test_allocator_drift_on_apply_is_not_read_as_an_assignment currently asserts the defective behaviour and must be changed to require the compensating release. Add coverage for default_allocator past its two fail-closed early returns and for default_claims_source, both of which have none.

Re-run WEBUI_TEST_OFFLINE=1 ../../venv/bin/python -m pytest tests/ -q from a branches/ worktree and compare against the clean-master baseline at 2f4dec83, which is 23 failed / 5190 passed / 6 skipped / 867 subtests. Then push to feat/issue-643-request-preview-initiate and request a fresh review.

WHAT_HAPPENED: Reviewer review of PR #902 at head 433f66ad completed and REQUEST_CHANGES posted to Gitea. Full suite re-run independently on both the PR head and a clean-master baseline worktree under branches/; three single-guard mutation runs performed; the authorization gate and the rendering surface were verified independently and are clean.
WHY: The apply path can leave an allocator-created assignment orphaned while reporting mutation_performed false, and the preview path writes control-plane session rows and expires leases while declaring itself read-only.
RELATED_PRS: #902 (open, head 433f66add8, base master @ 2f4dec8323, REQUEST_CHANGES posted by the reviewer)
BLOCKERS: B1 — apply can orphan an allocator-created assignment on egress mismatch or post-commit exception and reports mutation_performed false (webui/request_service.py:745-781). B2 — the preview path writes a control-plane session row per call and calls expire_stale_leases while reporting mutation_performed false (webui/request_service.py:892-934, allocator_service.py:888-912).
VALIDATION: WEBUI_TEST_OFFLINE=1 ../../venv/bin/python -m pytest tests/ -q from branches/review-902-baseline @2f4dec83 gave 23 failed / 5190 passed / 6 skipped / 867 subtests; the same command from branches/review-902-head @433f66ad gave 23 failed / 5242 passed / 6 skipped / 899 subtests; sorted FAILED lines diff empty, 23 identical signatures. Mutation runs gave 1, 1, and 30 failures respectively.
LAST_UPDATED_BY: sysadmin (prgs-reviewer)

NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP namespace gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha 433f66add8, submitted_verdict REQUEST_CHANGES, review_verdict_visible true. No offline, import, or helper path was used.

[THREAD STATE LEDGER] PR #902 — REQUEST_CHANGES posted to Gitea

What is true now:

  • PR state: open
  • Server-side decision state: REQUEST_CHANGES posted to Gitea
  • Local verdict/state: REQUEST_CHANGES prepared locally
  • Latest known validation: branch 23 failed / 5242 passed / 6 skipped / 899 subtests, clean-master baseline 23 failed / 5190 passed / 6 skipped / 867 subtests, identical 23 failure signatures

What changed:

  • REQUEST_CHANGES posted to Gitea

What is blocked:

  • Blocker classification: code blocker

Who/what acts next:

  • Next actor: author
  • Required action: address the two blockers on PR #902 and push fixes
  • Do not do: merge
  • Resume from: PR #902 review comments

Server-side mutation ledger:

  • gitea_submit_pr_review → REQUEST_CHANGES posted to Gitea
  • gitea_create_issue_comment → this canonical issue-state comment

Full findings, the concrete failure scenarios, the verified-clean items, and the
mutation-test table are in the review on PR #902.

## Canonical Issue State STATE: PR-open WHO_IS_NEXT: author NEXT_ACTION: Address the two code blockers on PR #902 at head 433f66ad and push fixes to feat/issue-643-request-preview-initiate, then request a fresh review. NEXT_PROMPT: ```text Act as author on Scaled-Tech-Consulting/Gitea-Tools issue #643, PR #902, remote prgs. Read the reviewer REQUEST_CHANGES on PR #902 at head 433f66add864062df7c211d9b52fc74fcfccfb2f. Two code blockers must be resolved. B1: in webui/request_service.py apply_request, when the allocator ran with apply=True and returned outcome assigned_work but _selection_matches fails against the requested work unit, the allocator has committed an assignment and lease via db.assign_and_lease; the current code returns mutation_performed false and leaves that lease orphaned. Release it or surface it with an explicit reclaim action, and report the mutation truthfully. The same state is reachable when _run_allocator's bare except Exception swallows an exception raised after the commit, since allocate_next_work only catches InvalidWorkKindError, LeaseRequiredError, and ControlPlaneError. Note that candidate_set_fingerprint hashes only kind and number, so the CAS pin cannot detect the lease-state change that causes the divergence. B2: allocate_next_work calls db.upsert_session and db.expire_stale_leases unconditionally before the apply branch, so every preview writes a new webui-request-<hex> session row and mutates lease state while the payload reports dry_run true and mutation_performed false. Keep the preview path free of session-row writes and reuse a single session id across the dry-run and the apply so the created lease has a resolvable owner. Tests: tests/test_webui_request_initiation.py test_allocator_drift_on_apply_is_not_read_as_an_assignment currently asserts the defective behaviour and must be changed to require the compensating release. Add coverage for default_allocator past its two fail-closed early returns and for default_claims_source, both of which have none. Re-run WEBUI_TEST_OFFLINE=1 ../../venv/bin/python -m pytest tests/ -q from a branches/ worktree and compare against the clean-master baseline at 2f4dec83, which is 23 failed / 5190 passed / 6 skipped / 867 subtests. Then push to feat/issue-643-request-preview-initiate and request a fresh review. ``` WHAT_HAPPENED: Reviewer review of PR #902 at head 433f66ad completed and REQUEST_CHANGES posted to Gitea. Full suite re-run independently on both the PR head and a clean-master baseline worktree under branches/; three single-guard mutation runs performed; the authorization gate and the rendering surface were verified independently and are clean. WHY: The apply path can leave an allocator-created assignment orphaned while reporting mutation_performed false, and the preview path writes control-plane session rows and expires leases while declaring itself read-only. RELATED_PRS: #902 (open, head 433f66add864062df7c211d9b52fc74fcfccfb2f, base master @ 2f4dec832327513118f2fe92b74da25d124a01cb, REQUEST_CHANGES posted by the reviewer) BLOCKERS: B1 — apply can orphan an allocator-created assignment on egress mismatch or post-commit exception and reports mutation_performed false (webui/request_service.py:745-781). B2 — the preview path writes a control-plane session row per call and calls expire_stale_leases while reporting mutation_performed false (webui/request_service.py:892-934, allocator_service.py:888-912). VALIDATION: WEBUI_TEST_OFFLINE=1 ../../venv/bin/python -m pytest tests/ -q from branches/review-902-baseline @2f4dec83 gave 23 failed / 5190 passed / 6 skipped / 867 subtests; the same command from branches/review-902-head @433f66ad gave 23 failed / 5242 passed / 6 skipped / 899 subtests; sorted FAILED lines diff empty, 23 identical signatures. Mutation runs gave 1, 1, and 30 failures respectively. LAST_UPDATED_BY: sysadmin (prgs-reviewer) NATIVE_REVIEW_PROOF: gitea_submit_pr_review via native MCP namespace gitea-reviewer, profile prgs-reviewer, identity sysadmin, expected_head_sha 433f66add864062df7c211d9b52fc74fcfccfb2f, submitted_verdict REQUEST_CHANGES, review_verdict_visible true. No offline, import, or helper path was used. [THREAD STATE LEDGER] PR #902 — REQUEST_CHANGES posted to Gitea What is true now: - PR state: open - Server-side decision state: REQUEST_CHANGES posted to Gitea - Local verdict/state: REQUEST_CHANGES prepared locally - Latest known validation: branch 23 failed / 5242 passed / 6 skipped / 899 subtests, clean-master baseline 23 failed / 5190 passed / 6 skipped / 867 subtests, identical 23 failure signatures What changed: - REQUEST_CHANGES posted to Gitea What is blocked: - Blocker classification: code blocker Who/what acts next: - Next actor: author - Required action: address the two blockers on PR #902 and push fixes - Do not do: merge - Resume from: PR #902 review comments Server-side mutation ledger: - gitea_submit_pr_review → REQUEST_CHANGES posted to Gitea - gitea_create_issue_comment → this canonical issue-state comment Full findings, the concrete failure scenarios, the verified-clean items, and the mutation-test table are in the review on PR #902.
sysadmin removed the status:pr-open label 2026-07-25 17:02:19 -05:00
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Scaled-Tech-Consulting/Gitea-Tools#643