# Locked OPRID Scheduled Processes

LLMS index: [llms.txt](/llms.txt)

---

<div id="pslens-context-panel" class="card border-info mb-4 d-none">
  <div class="card-header bg-light text-info py-2 fw-bold d-flex align-items-center border-bottom border-info-subtle">
    <i class="bi bi-info-circle-fill me-2"></i>
    <span>Tailored Operational Context</span>
  </div>
  <div class="card-body p-0">
    <ul class="list-group list-group-flush">
      <li id="row-db" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Target Database:</strong>
        <span id="ctx-db" class="badge bg-secondary font-monospace">&mdash;</span>
      </li>
      <li id="row-type" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Context Type:</strong>
        <span id="ctx-type" class="badge bg-light text-dark border font-monospace text-uppercase">&mdash;</span>
      </li>
      <li id="row-severity" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Alert Severity:</strong>
        <span id="ctx-severity" class="badge">&mdash;</span>
      </li>
      <li id="row-time" class="list-group-item d-flex align-items-center justify-content-between py-2 d-none">
        <strong>Triggered Time:</strong>
        <span id="ctx-time" class="text-muted small">&mdash;</span>
      </li>
      <li id="row-details" class="list-group-item py-2 d-none">
        <strong id="label-details" class="d-block mb-1">Firing Context:</strong>
        <code id="ctx-details" class="d-block p-2 bg-light border rounded small" style="white-space: pre-wrap; word-break: break-all;">&mdash;</code>
      </li>
    </ul>
  </div>
</div>

<script>
  (function() {
    const params = new URLSearchParams(window.location.search);
    const metadata = params.get('metadata');
    if (!metadata) return;

    try {
      
      const base64 = metadata.replace(/-/g, '+').replace(/_/g, '/');
      const jsonStr = decodeURIComponent(escape(window.atob(base64)));
      const data = JSON.parse(jsonStr);

      if (data) {
        let hasData = false;

        if (data.db) {
          document.getElementById('ctx-db').textContent = data.db;
          document.getElementById('row-db').classList.remove('d-none');
          hasData = true;
        }

        if (data.type) {
          document.getElementById('ctx-type').textContent = data.type;
          document.getElementById('row-type').classList.remove('d-none');
          hasData = true;
        }

        if (data.severity) {
          const severityBadge = document.getElementById('ctx-severity');
          const severity = data.severity.toLowerCase();
          severityBadge.textContent = severity.toUpperCase();
          if (severity === 'critical') {
            severityBadge.className = 'badge bg-danger';
          } else if (severity === 'warning') {
            severityBadge.className = 'badge bg-warning text-dark';
          } else {
            severityBadge.className = 'badge bg-info';
          }
          document.getElementById('row-severity').classList.remove('d-none');
          hasData = true;
        }

        if (data.t) {
          const date = new Date(data.t * 1000);
          document.getElementById('ctx-time').textContent = date.toLocaleString();
          document.getElementById('row-time').classList.remove('d-none');
          hasData = true;
        }

        if (data.details) {
          document.getElementById('ctx-details').textContent = data.details;

          
          const labelDetails = document.getElementById('label-details');
          if (data.type === 'object') {
            labelDetails.textContent = 'Object Metadata Details:';
          } else if (data.type === 'report') {
            labelDetails.textContent = 'Report Description:';
          } else {
            labelDetails.textContent = 'Firing Context:';
          }

          document.getElementById('row-details').classList.remove('d-none');
          hasData = true;
        }

        if (hasData) {
          document.getElementById('pslens-context-panel').classList.remove('d-none');
        }
      }
    } catch (e) {
      console.error('Failed to parse operational context metadata:', e);
    }
  })();
</script>


## Locked OPRID Scheduled Processes Alert

**Alert ID:** `locked_oprid_processes`
**Category:** Process Scheduler

## What This Alert Detects

This alert finds queued or scheduled Process Scheduler requests where the submitting operator's account (OPRID) is currently locked in PSOPRDEFN (ACCTLOCK = 1).

When an operator account is locked after a process has been queued, PeopleSoft will refuse to run the process, or run it under the locked account and immediately fail. PeopleSoft does not surface this condition anywhere obvious: Process Monitor shows the job queued, the operator's user page shows them locked, but nothing connects the two. This alert does.

Common scenarios:

- A service or batch account had its password expire and was locked
- An employee left and their account was locked, but scheduled jobs were not transferred
- A security lockout from failed login attempts affected a batch account

## Severity Logic

All findings are reported at **Warning** severity. Every queued or scheduled process with a locked submitting account is flagged.

## What Gets Checked

The alert queries PSPRCSRQST joined to PSOPRDEFN for process requests in Queued or Scheduled run status where the submitting OPRID has ACCTLOCK = 1.

## Alert Details

Each alert item includes:

- Process name and instance number
- Submitting OPRID (with link to User detail page)
- Current run status (Queued, Scheduled, etc.)
- Scheduled run date/time
- Recurrence name (if applicable)

## Configuration

```yaml
alerts:
  checks:
    locked_oprid_processes:
      enabled: true
      excludeProcesses: []   # Process names to ignore
```

|      Setting       | Default |                   Description                    |
| ------------------ | ------- | ------------------------------------------------ |
| `excludeProcesses` | `[]`    | List of process names to exclude from this check |

## How to Respond

1. Click the alert link to open the Process Monitor detail page for the affected instance
2. Identify the locked OPRID shown in the alert
3. Navigate to the User detail page to review the account lock status
4. Either unlock the account (if appropriate) or re-queue the process under an active operator account
5. For recurring processes, update the recurrence definition to use a non-locked operator
6. Investigate why the account was locked. If it was a failed login lockout, check the Failed Logins alert for additional context

## Tables Queried

|   Table    |             Description              |
| ---------- | ------------------------------------ |
| PSPRCSRQST | Process Scheduler request queue      |
| PSOPRDEFN  | Operator definitions (user accounts) |
