Skip to content

feat: add admin review workflow for identity conflict resolution#29

Merged
Rajkoli145 merged 1 commit into
mainfrom
feature/admin-review-workflow
May 23, 2026
Merged

feat: add admin review workflow for identity conflict resolution#29
Rajkoli145 merged 1 commit into
mainfrom
feature/admin-review-workflow

Conversation

@Soldier224K

Copy link
Copy Markdown
Collaborator
  • Add reviewer_id, review_timestamp, review_reason to ConflictAlert
  • Add get_conflict_details() to inspect prior face history
  • Add admin_review_conflict() for approval/rejection actions
  • Add get_override_log() to persist manual review decisions
  • Add API endpoints: /face/conflict/{id}, /admin/review-conflict, /admin/override-log
  • Add new event types: ADMIN_REVIEW_STARTED, ADMIN_REVIEW_APPROVED, ADMIN_REVIEW_REJECTED, ADMIN_OVERRIDE_ACTION
  • Add 5 new tests for admin review functionality

- Add reviewer_id, review_timestamp, review_reason to ConflictAlert
- Add get_conflict_details() to inspect prior face history
- Add admin_review_conflict() for approval/rejection actions
- Add get_override_log() to persist manual review decisions
- Add API endpoints: /face/conflict/{id}, /admin/review-conflict, /admin/override-log
- Add new event types: ADMIN_REVIEW_STARTED, ADMIN_REVIEW_APPROVED, ADMIN_REVIEW_REJECTED, ADMIN_OVERRIDE_ACTION
- Add 5 new tests for admin review functionality
Copilot AI review requested due to automatic review settings May 23, 2026 14:17

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces an admin review workflow around face-identity conflict alerts, expanding the conflict alert model with review metadata and adding service/API capabilities to inspect conflicts and record approval/rejection decisions.

Changes:

  • Extend ConflictAlert with reviewer_id, review_timestamp, and review_reason, and surface them in serialization.
  • Add service methods for conflict inspection (get_conflict_details), admin decisions (admin_review_conflict), override log retrieval (get_override_log), and alert lookup (get_alert_by_id).
  • Add FastAPI endpoints for conflict details and admin review/override-log, plus associated unit tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 9 comments.

File Description
backend/tests/test_face_detection.py Updates/extends unit tests to cover conflict detail retrieval and admin review/override log behaviors.
backend/src/services/face_detection.py Adds review fields to conflict alerts and implements admin review + conflict detail/override log helpers.
backend/src/models/events.py Introduces new event type constants for admin review/override actions.
backend/src/main.py Adds request schemas and new REST endpoints for conflict details and admin review/override log.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/src/main.py
Comment on lines +79 to +84
@app.get("/face/conflict/{conflict_id}")
async def get_conflict_details(conflict_id: str):
details = face_service.get_conflict_details(conflict_id)
if details is None:
return {"error": "Conflict not found"}, 404
return details
Comment thread backend/src/main.py
Comment on lines +86 to +96
@app.post("/admin/review-conflict")
async def admin_review_conflict(request: AdminReviewRequest):
success = face_service.admin_review_conflict(
request.conflict_id,
request.approved,
request.reviewer_id,
request.reason
)
if not success:
return {"error": "Conflict not found"}, 404
return {"success": True, "message": "Review decision recorded"}
Comment thread backend/src/main.py
Comment on lines +86 to +100
@app.post("/admin/review-conflict")
async def admin_review_conflict(request: AdminReviewRequest):
success = face_service.admin_review_conflict(
request.conflict_id,
request.approved,
request.reviewer_id,
request.reason
)
if not success:
return {"error": "Conflict not found"}, 404
return {"success": True, "message": "Review decision recorded"}

@app.get("/admin/override-log")
async def get_override_log():
return face_service.get_override_log()
Comment thread backend/src/main.py
Comment on lines +79 to +84
@app.get("/face/conflict/{conflict_id}")
async def get_conflict_details(conflict_id: str):
details = face_service.get_conflict_details(conflict_id)
if details is None:
return {"error": "Conflict not found"}, 404
return details
Comment on lines +175 to +178
def test_get_conflict_details(self):
service = FaceDetectionService()
emb1 = generate_embedding(base=0.5)
emb2 = create_similar_embedding(emb1, 0.92)
Comment on lines +181 to +188
for alert in self.alerts:
if alert.conflict_id == conflict_id:
alert.status = "approved" if approved else "rejected"
alert.reviewer_id = reviewer_id
alert.review_timestamp = datetime.now(timezone.utc)
alert.review_reason = reason
return True
return False
Comment on lines +133 to 140
def resolve_alert(self, conflict_id: str, approved: bool, reviewer_id: Optional[str] = None, reason: Optional[str] = None) -> bool:
for alert in self.alerts:
if alert.conflict_id == conflict_id:
alert.status = "approved" if approved else "rejected"
alert.reviewer_id = reviewer_id
alert.review_timestamp = datetime.now(timezone.utc)
alert.review_reason = reason
return True
Comment on lines +190 to +192
def get_override_log(self) -> List[Dict[str, Any]]:
return [alert.to_dict() for alert in self.alerts if alert.status in ("approved", "rejected")]

@@ -147,4 +156,42 @@ def can_grant_access(self, roll_number: str) -> Tuple[bool, Optional[str]]:
for conflict in conflicts:
if conflict.status == "pending_review":
return False, f"Identity under review: conflict {conflict.conflict_id}"
@Rajkoli145 Rajkoli145 merged commit 42d122c into main May 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants