5.5 KiB
Task 3 Report: Safe Blocker Resolution Workflow
Status
Implemented Task 3 only. The old hidden-context blocker action was replaced by a structured, server-rendered, CSRF-protected resolution workflow. The JSON control-panel route now uses the same validated transaction service and rejects arbitrary context text.
RED
Created central/tests/test_blocker_resolution_panel.py before production implementation.
Initial focused command:
python -m pytest central/tests/test_blocker_resolution_panel.py -q
Expected RED result:
ModuleNotFoundError: No module named 'central.app.blocker_resolution'
The failure occurred during collection because the required production module did not yet exist.
Implementation
- Added
central/app/blocker_resolution.pywith structured input validation throughvalidate_entry, workflow-scope restrictions, exact PRODUCT scope-key enforcement, persisted installation/company context derivation, context upsert, boundedREPROCESS_PRODUCTSjob creation, sanitized audit recording, and one commit with rollback on failure. - Added
GET /blockers/{blocker_id}with installation-aware blocker detail and context form. - Added
POST /blockers/{blocker_id}/resolve-contextwith human authentication and CSRF enforcement. - Updated
/v1/blockers/{blocker_id}/resolve-humanand added/v1/blockers/{blocker_id}/resolve-contextto call the same service; neither accepts arbitrary context text. - Removed the blocker-list hidden fixed-context form and
data-confirmaction. - Added focused coverage for enum validation, unknown keys, unsupported NCM scope, empty reason, missing PRODUCT scope key, authentication, CSRF, context/job/audit persistence, exact product scoping, and secret redaction.
GREEN
Focused command:
python -m pytest central/tests/test_blocker_resolution_panel.py -q
Result:
5 passed, 1 warning
Central suite:
python -m pytest central/tests -q
Result:
261 passed, 1 warning
The warnings are existing third-party test-environment warnings from pytest_asyncio configuration and openpyxl print-area parsing.
Safety Review
- No Firebird, AI, SQL execution, shell, credential, or remote-write path was added.
- The workflow accepts only
scope,scope_key,key,value, andreason; context keys and enum values are validated against existing shared rules. - Company context is derived from persisted blocker/installation data, not arbitrary client
company_keyinput. - Jobs contain exactly the blocked product code.
- Audit context passes through existing redaction before persistence.
Concerns
- Live PostgreSQL and agent execution were not exercised; verification used the repository's offline SQLite test fixtures.
- The blocker remains open until the agent's normal reprocess completion path reports resolution; this prevents marking it resolved before the bounded job succeeds.
Review Fixes
RED
Added regression tests before changing production code for the four review findings:
- Legacy blockers with
installation_id=NULLmust fail closed without selecting an Agent or creating work. - Cross-tenant installation and Agent pointers must fail before context, job, or audit mutation.
- Oversized values/reasons and non-string fields must be rejected cleanly.
- Successful web resolution must redirect to the blocker detail page.
Focused command before the fixes:
python -m pytest central/tests/test_blocker_resolution_panel.py -q
RED result:
4 failed, 5 passed
The failures reproduced the legacy Agent fallback, cross-tenant acceptance, unbounded/malformed input, and /blockers redirect behavior.
GREEN
- Resolution now requires a non-null exact installation and verifies both installation and Agent tenant ownership before mutation.
valueis required to be a string of at most 512 characters;reasonis required to be a string of at most 2000 characters.- Boundary-sized audit data retains all required audit fields without whole-context truncation.
- Web success redirects to
/blockers/{blocker_id}.
Focused command:
python -m pytest central/tests/test_blocker_resolution_panel.py -q
Result:
9 passed, 1 warning
Full central command:
python -m pytest central/tests -q
Result:
265 passed, 1 warning
The existing pytest_asyncio configuration and openpyxl print-area warnings remain unchanged.
UTF-8 Byte-Length Re-Review Fix
RED
Added test_resolution_input_rejects_multibyte_utf8_at_ascii_character_limits before changing production code. It submits é repeated 512 times as value and 2000 times as reason; both are within the existing character counts but exceed the corresponding UTF-8 byte budgets.
Focused command:
python -m pytest central/tests/test_blocker_resolution_panel.py -q
RED result:
1 failed, 9 passed
The failure confirmed character-count validation accepted the multibyte inputs.
GREEN
valueandreasonlimits now uselen(value.encode("utf-8"))andlen(reason.encode("utf-8")).- Existing ASCII boundary inputs remain accepted.
- Multibyte inputs fail closed with explicit UTF-8 byte-limit validation errors, before persistence or audit sanitization.
- Redaction and remote-write boundaries were not changed.
Focused result:
10 passed, 1 warning
Full central result:
266 passed, 1 warning
The existing pytest_asyncio configuration and openpyxl print-area warnings remain unchanged.