---
title: Prevent Practice Squad to Reserve Move Without Active Poaching Claim
type: task
status: completed
description: >-
  Implementation plan to add validation preventing practice squad players from being moved to
  reserve unless they have an active poaching claim
aliases:
  - ████████████████████████-████████-█████-███████-███████-█████
base_uri: user:task/league/prevent-practice-squad-reserve-without-poach.md
created_at: '2025-08-19T19:44:12.612Z'
entity_id: eda6a254-9647-4624-94e9-81b55dc9257b
owner_identity_uri: █████████████████████████
priority: Medium
public_read: true
relations:
  - created_by [[████████████████████-████-████-████-████████████]]
tags:
  - user:tag/league-xo-football.md
updated_at: '2026-10-03T04:30:45.009Z'
visibility_analyzed_at: '2026-11-05T23:49:50.143Z'
---

# Implementation Plan: Prevent Practice Squad to Reserve Move Without Active Poaching Claim

## Overview

- Add validation to ensure practice squad players can ONLY be moved to reserve if they have an active poaching claim
- Ensure both server-side API validation and client-side UI feedback are consistent
- Maintain existing reserve eligibility rules while adding this new constraint

## Background

- Practice squad players are stored with slot values `PS` (12) and `PSD` (16) in the `rosters_players` table
- Poaching claims are tracked in the `poaches` table with active claims having `processed` field as NULL
- Current reserve validation in `libs-server/submit-reserve.mjs` checks protected players but not poaching claims
- Client-side eligibility is determined in `getPlayerStatus` selector in `app/core/selectors.js`
- Poaches are loaded during `AUTH_FULFILLED` event and available via `get_poaches_for_current_league` selector

## Design

- Server-side validation will be added after the existing protected player check
- Client-side will only show reserve option for practice squad players WITH active poaches
- Error messages will follow existing patterns for consistency
- Database queries will reuse the established pattern: `db('poaches').where({ pid }).whereNull('processed')`
- No new dependencies or schema changes required

## Notes

- This rule only applies to unprotected practice squad slots (PS and PSD)
- Protected practice squad players (PSP and PSDP) are already prevented from reserve moves
- Practice squad players WITHOUT active poaching claims cannot be placed on reserve
- The validation should be clear about why the move is blocked
- Consider edge case where poach might be processed between client check and server validation

## Tasks

### Server-Side Validation

- [x] **Add poaching claim validation to submit-reserve.mjs**

  - File: `/Users/trashman/user-base/repository/active/league/libs-server/submit-reserve.mjs`
  - Purpose: Ensure practice squad players can ONLY be moved to reserve if they have active poaching claims
  - Changes:
    - After line 63 (protected player validation), add check for practice squad players
    - If player is on PS or PSD slot, query for active poaching claims
    - Query pattern: `const activePoaches = await db('poaches').where({ pid: reserve_pid }).whereNull('processed')`
    - If NO active poaches exist, throw error with message: 'practice squad players can only be placed on reserve if they have an active poaching claim'
    - Ensure the check is before the reserve eligibility checks (line 65+)

### Client-Side UI Feedback

- [x] **Update getPlayerStatus selector for reserve eligibility**

  - File: `/Users/trashman/user-base/repository/active/league/app/core/selectors.js`
  - Purpose: Only show reserve option for practice squad players WITH active poaches
  - Changes:
    - In the reserve eligibility section (lines 1337-1358), add additional condition
    - Before setting `status.reserve.ir = true` (line 1344), check if player is on practice squad
    - If `playerSlot === constants.slots.PS || playerSlot === constants.slots.PSD`, check for active poaches
    - Use existing `get_poaches_for_current_league(state)` selector to get poaches
    - Only set reserve eligibility if `leaguePoaches.has(playerId)` is true
    - Apply same logic for `status.reserve.ir_long_term` (line 1348)

### Testing and Validation

- [x] **Write test cases for the new validation**

  - File: `/Users/trashman/user-base/repository/active/league/test/teams.reserve.spec.mjs` (create if doesn't exist)
  - Purpose: Ensure the validation works correctly
  - Test scenarios:
    - Practice squad player WITH active poaching claim can be reserved (when eligible)
    - Practice squad player WITHOUT poaching claim cannot be reserved
    - Protected practice squad players still cannot be reserved
    - Regular roster players are unaffected by this change

- [x] **Update existing reserve tests if needed**

  - File: `/Users/trashman/user-base/repository/active/league/test/teams.reserve.activate.spec.mjs`
  - Purpose: Ensure existing tests still pass with new validation
  - Changes:
    - Review existing tests to ensure they don't create scenarios that would be blocked
    - Add mock data for poaches table if tests involve practice squad players

### Documentation

- [x] **Update API documentation for reserve endpoint**

  - File: `/Users/trashman/user-base/repository/active/league/api/routes/teams/reserve.mjs`
  - Purpose: Document the new validation rule in API comments
  - Changes:
    - Add comment explaining practice squad with active poach restriction
    - Update any inline documentation about reserve eligibility rules
