# Full Access Permission Lists

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>


## Full Access Permission Lists Report

**Report ID:** `security-full-access-permlists`
**Category:** Security
**Default Parameter:** `minMenuCount = 50`

## Purpose

This report identifies PeopleSoft permission lists that have an unusually high number of menu authorizations. Permission lists with 50+ menu authorizations are usually "superuser" lists that grew organically. Find them so you can audit who has them.

## What It Detects

Permission lists where the total count of menu authorizations meets or exceeds a configurable threshold (default: 50).

Menu authorizations are entries in `PSAUTHITEM` that match real menus in `PSMENUITEM` via a parent-child join. This excludes special permissions like APPLICATION_DESIGNER, DATA_MOVER, QUERY, and WEBLIB entries.

## Tables Queried

### PSCLASSDEFN — Permission List Definitions

The primary record for PeopleSoft permission lists (also called "classes").

|     Field     |                   Description                   |
| ------------- | ----------------------------------------------- |
| CLASSID       | Permission list name (primary key)              |
| CLASSDEFNDESC | Description of the permission list              |
| LASTUPDOPRID  | Last operator who modified this permission list |
| LASTUPDDTTM   | Timestamp of last modification                  |

### PSAUTHITEM — Menu Authorization Entries

Each row represents a menu/bar/item combination that a permission list is authorized to access.

|       Field       |                 Description                  |
| ----------------- | -------------------------------------------- |
| CLASSID           | Permission list (foreign key to PSCLASSDEFN) |
| MENUNAME          | Menu name                                    |
| BARNAME           | Menu bar name                                |
| BARITEMNAME       | Menu bar item name                           |
| DISPLAYONLY       | Whether access is display-only               |
| AUTHORIZEDACTIONS | Bitmask of authorized actions                |

### PSMENUITEM — Menu Item Details

Used via a parent-child join with PSAUTHITEM to validate that authorization entries correspond to real menu items. Only PSAUTHITEM entries matching a PSMENUITEM record are counted.

|   Field    |           Description            |
| ---------- | -------------------------------- |
| MENUNAME   | Menu name (join key)             |
| BARNAME    | Menu bar name (join key)         |
| ITEMNAME   | Item name (joins to BARITEMNAME) |
| PNLGRPNAME | Component name                   |
| MARKET     | Market code                      |
| ITEMLABEL  | Display label                    |

## Data Flow

```text
1. Fetch ALL permission lists from PSCLASSDEFN
   via SearchPermissionLists (batches of 300)
        |
        v
2. For EACH permission list:
   Query PSAUTHITEM joined with PSMENUITEM
   via GetMenuAuthorizations (pages of 100)
   Count total matching entries
        |
        v
3. Filter: keep only permission lists where
   menu auth count >= minMenuCount (default 50)
        |
        v
4. Sort results by menu auth count (descending)
        |
        v
5. Generate Markdown report with summary table
```

## Report Output

The generated report contains:

- **Header** with database name, generation timestamp, and threshold value
- **Summary** showing total permission lists analyzed and count flagged
- **Flagged Permission Lists table** with columns:
  - Permission List (CLASSID)
  - Description (truncated to 50 characters)
  - Menu Auth Count
  - Last Updated By (operator ID)
  - Last Updated (timestamp)
- **Recommendations** section with remediation guidance

## Parameters

|   Parameter    | Default |                           Description                           |
| -------------- | ------- | --------------------------------------------------------------- |
| `minMenuCount` | `50`    | Minimum number of menu authorizations to flag a permission list |

## Interpreting Results

- **High counts (200+):** These permission lists likely grant access to a very large portion of the application. They are often "admin" or "superuser" lists and should be reviewed to ensure they are only assigned to appropriate roles.
- **Moderate counts (50-200):** May indicate permission lists that have grown over time. Consider whether they can be split into more focused lists.
- **Last Updated By:** If the operator is not a known security administrator, investigate whether the change was authorized.

## Recommendations

1. Review flagged permission lists for excessive access
2. Consider splitting broad permission lists into more focused, role-specific lists
3. Verify that the "Last Updated By" operator is authorized to make security changes
