---
title: "Override Register"
slug: override-register
section: Rules & Compliance
status: stable
description: "The Override Register is a single read-only, permission-aware, scope-clamped view of every SEVIS readiness, compliance-rule, and legacy eligibility override in Globus."
last-updated: 2026-10-07
---

# Override Register

The Override Register is a single read-only, permission-aware, scope-clamped view of every SEVIS readiness, compliance-rule, and legacy eligibility override in Globus.

## Overview

Overrides are stored in three different tables, each with its own lifecycle. The register (`GET /api/override-register`) reads all three, normalizes each row into one shape, and classifies it with one status and urgency vocabulary so staff can see what is pending, what needs review, and what is about to lapse without walking applicants one by one.

It is an oversight queue, not an approvals or mutation surface. The endpoint is a GET, the detail drawer makes no mutation call, and each row links out to the surface that governs the override (the applicant compliance section, or the SEVIS Ready Pool for SEVIS readiness overrides). Applying, approving, revoking, and re-expiring overrides stay on those surfaces; see [Rules Engine](/docs/rules-engine) for override governance and [SEVIS Readiness Criteria](/docs/sevis-readiness) for the SEVIS readiness override.

New broad SEVIS readiness override creation is retired: every authorized create request returns `409` with `LEGACY_SEVIS_OVERRIDE_RETIRED`, and the Ready Pool no longer creates them. Existing SEVIS readiness overrides remain effective only until their recorded expiry or revocation. Their expiry may be shortened only; an extension or renewal returns `409` with `LEGACY_SEVIS_OVERRIDE_EXTENSION_RETIRED`.

> **Read-only by design**
> 
> The register never writes. A failed load is shown as an error with a retry, and the page states that an unavailable register is not confirmation that no overrides exist.

## Sources and Permissions

Each row carries a `source`. A source is included only when the caller holds at least one of that source's permissions (or is in god mode, in which case all three are included).

| Source | Stored in | Permissions that reveal it |
| --- | --- | --- |
| `sevis_readiness` (labeled "Legacy SEVIS overrides" on the staff page) | `sevis_readiness_overrides` (joined through the application) | `sevis.override.manage` |
| `compliance_rule` (labeled "Compliance" on the staff page) | `rule_overrides` (applicant-level, with rule definition and version) | `compliance.overrides.review`, `compliance.console.view`, `compliance.review.manage`, `programs.manage` |
| `legacy_eligibility` (labeled "Legacy" on the staff page) | `eligibility_overrides` | `eligibility:override:create`, `override.apply`, `compliance.view` |

The route itself requires any one of the union of those eight permissions; the sidebar entry and the page use the same list. A caller who passes the route guard but holds permissions for only one source sees only that source, and requesting a source they cannot see simply returns no rows for it. Each source is therefore fail-closed by the permission that already governs it. A fourth store, `rule_override_records` (application-level rule override records), is not a register source. It is managed through `/api/admin/rules/overrides`: `POST` (`201`) and `PATCH /:id` (`404` for an unknown record, a validation error for an empty body) require the restricted permission `compliance.gates.override` ("Override compliance gate blocks", flagged `requiresReason`), which the `compliance.read` API scope also accepts; `GET` needs `compliance.overrides.review`.

### Scope Clamping

Unless the caller is in god mode, rows are limited to applicants inside the caller's program, season (operational cycle), and brand scope. When the caller holds a valid permission but their scope reaches no programs, seasons, or brands, the response sets `scopeEmpty: true` and the page shows an alert ("Your access reaches no programs") so the empty list is not mistaken for "no overrides exist".

## Request

`GET /api/override-register` accepts these query parameters, all optional.

| Parameter | Values | Default |
| --- | --- | --- |
| `source` | `all`, `sevis_readiness`, `compliance_rule`, `legacy_eligibility` | `all` |
| `status` | `all`, `pending`, `active`, `lapsing_soon`, `review_required`, `expired`, `revoked`, `rejected` | `all` |
| `urgency` | `all`, `urgent`, `due_soon`, `normal`, `closed` | `all` |
| `search` | up to 200 characters, matched case-insensitively against applicant first name, last name, or application short code | none |
| `programId`, `seasonId` | an id, or `all` (treated as no filter) | none |
| `page` | integer, minimum 1 | 1 |
| `limit` | integer, 1 to 100 | 25 |

Program, season, and search are applied in the database query; `status` and `urgency` are applied after the rows from the permitted sources are normalized.

## Status and Urgency

Status is derived at read time from the stored status and the expiry and review dates, using one clock value for the whole response.

| Normalized status | Rule (evaluated in this order) |
| --- | --- |
| `revoked`, `rejected` | The stored status is already `revoked` or `rejected` |
| `pending` | The stored status is `pending`, `pending_primary`, or `pending_secondary` |
| `review_required` | A review date exists and has passed |
| `expired` | An expiry exists and has passed |
| `lapsing_soon` | The expiry falls within the next 8 hours |
| `active` | Everything else |

Urgency is derived from the status and the nearest deadline, where the deadline is the review date if present, otherwise the expiry.

| Urgency | Rule |
| --- | --- |
| `closed` | Status is `expired`, `revoked`, or `rejected` |
| `urgent` | Deadline within 2 hours (or already passed, for non-closed rows) |
| `due_soon` | Deadline within 24 hours |
| `normal` | Otherwise, or no deadline |

Only compliance-rule overrides carry a review date, so `review_required` applies to that source. SEVIS readiness and legacy eligibility rows are classified from their expiry alone.

## Response

The response body (inside the standard success envelope) contains:

| Field | Meaning |
| --- | --- |
| `items` | The requested page of normalized rows |
| `total` | Rows matching the `status` and `urgency` filters, across all pages |
| `page`, `limit` | Echo of the paging parameters |
| `counts` | `all`, `pending`, `active`, `lapsingSoon`, `reviewRequired`, `expired`, `revoked`, `rejected`, computed over the scoped, searched set before the `status` and `urgency` filters |
| `sourceCounts` | `sevisReadiness`, `complianceRule`, `legacyEligibility`, computed over the same set |
| `scopeEmpty` | True when the caller's scope reaches nothing |
| `generatedAt` | The clock value used for classification |

Each item includes `id`, `source`, applicant and application identity (`applicantId`, `applicationId`, `applicantName`, `applicationCode`), `programId`, `programName`, `seasonId`, `seasonName`, `title`, `context`, `status`, `storedStatus`, `urgency`, `justification`, `requirementLabels`, `riskClassification`, `policyClass`, `appliedBy` (user id, name, email, and a `deleted` flag), `requestedAt`, `appliedAt`, `expiresAt`, `reviewDueAt`, `legacyOrigin`, and `governanceUrl`. Fields a source does not have are `null` (`requirementLabels` is an empty array instead); `requirementLabels` is populated only for SEVIS readiness overrides (the waived blockers, with processing tracks shown as Application processing, Validation, Interview, and Placement), and risk and policy classification only for compliance-rule overrides.

`appliedBy` is the approving user where one exists, otherwise the requester: primary approver then requester for compliance rules, approver then requester for SEVIS readiness, and approver then creator for legacy eligibility.

### Ordering and Paging

Rows are de-duplicated on source plus id, then sorted on the server with pending, review-required, and urgent rows first, other open rows next, and closed history (expired, revoked, rejected) last; ties are broken by review date when present, otherwise expiry (earliest first; rows with neither sort last). Paging is applied to that sorted list in memory after all permitted sources have been loaded. The staff page re-sorts the page it receives with a similar priority (pending, review required, urgent, due soon or lapsing soon, other open, closed).

## Staff Page

The page is `/sevis-override-register` (sidebar label "Override Register"), titled "Override Register" with the description "Read-only operational view of SEVIS readiness, compliance rule, and legacy eligibility overrides." It provides:

- Filters for search (debounced), source, status, urgency, program, and operational cycle, with paging at 25 rows.
- A counts line (pending, active, review required, closed) and per-source badges.
- Rows showing applicant (linking to the applicant application), override title and source, status and urgency, program and cycle, and the expiry or review deadline.
- A read-only detail drawer with identity and context, requirement labels, justification, risk and policy, actors and deadlines, a legacy-record notice when `legacyOrigin` is set, and a link to the governing applicant or compliance surface. The drawer states that opening it never changes an override.

## Relationship to the SEVIS-Only Register

The earlier SEVIS-only register endpoint, `GET /api/sevis-readiness-overrides`, is still registered at HEAD. It is gated on `sevis.override.manage` alone, supports an `appliedBy` filter, an `appliers` facet and a CSV export, and is documented on [SEVIS Readiness Criteria](/docs/sevis-readiness). The unified register is a separate endpoint and does not offer those three features. The SEVIS-only search also now matches application short code in addition to applicant name.

Legacy eligibility overrides (the `legacy_eligibility` source) are read at `GET /api/admin/eligibility-overrides` (filters `applicantId`, `programId`, `seasonId`, `status`, `limit` up to 500, `offset`) and `GET /api/admin/eligibility-overrides/:id`, which returns `override` and its `auditTrail` and `404` for an unknown id. Both need `compliance.view` (API key scope `compliance.read` or `admin.read`). Writes use `eligibility:override:create` (create), `eligibility:override:approve` (approve, reject, expiry; approving an override you created is refused with `403`) and `eligibility:override:revoke`.

## Governed Override Requests

The same change set tightened how compliance-rule override requests are recorded, which is what the `pending` status and the compliance-rule source reflect.

- A pending compliance-rule override is linked to a Compliance Case. See [Rules Engine](/docs/rules-engine) for the Compliance Case model and who may request or apply overrides.
- The link is made through the `compliance_case_items` table, which models an independently governed rule request inside a Compliance Case. Each item in a case has its own status and lifecycle, and is associated with a specific rule definition. An approved item may result in a record in `rule_overrides`.
- Each compliance-rule override carries a `requires_secondary_approval` column that snapshots whether secondary approval is required; a migration added the column and backfilled existing rows.
- Approving a pending compliance-rule override re-evaluates the rule against current server-resolved evidence. If the rule now passes naturally, no override is applied: the case item is marked no longer required and the response carries `authorization: "no_longer_required"`. Otherwise it refuses with `409 RULE_OVERRIDE_VALIDITY_CONFLICT` when the request no longer matches: the evaluated rule version is no longer the published or program-applicable one, the current outcome is not an adjudicable failure (`fail` or `review_required`), the evidence or rule configuration changed since the request, the request has no request-time evidence binding, a selected supporting document changed, or the applicant has several enrollments in the program and no exact `applicationId`. Details carry `refreshRequired: true` when a reviewer must refresh the current evidence first (`POST /api/compliance-cases/:caseId/items/:itemId/refresh`, which requires `compliance.review.manage`). The check runs on the case item decision (made via `POST /api/compliance-cases/:caseId/items/:itemId/decision`, which requires `compliance.review.manage`) and on `approve-primary` and `approve-secondary` under `/api/rules-engine/overrides/:id`, each of which requires a reviewer `reason` of 8 to 2000 characters. A case item may also be resubmitted via `POST /api/compliance-cases/:caseId/items/:itemId/resubmit` (`eligibility:override:create`).
- **Batch request idempotency.** `POST /api/rules-engine/overrides/batch` (session or API key with `compliance.read` or `admin.write` scope, plus `compliance.review.manage`) files one request holding up to 30 rule items in a single Compliance Case, under a request-level `requestIdempotencyKey` and a unique per-item `idempotencyKey` (1 to 200 characters each). It accepts an optional exact `applicationId` to bind the request to one enrollment, required when the applicant has multiple enrollments in the program. Creating rows returns 201; an exact replay of the same request returns 200 with `deduplicated` true on every item and creates nothing. Any conflicting reuse returns 409 with the top-level error code `RULE_OVERRIDE_IDEMPOTENCY_CONFLICT`: the request key is already bound to a different request fingerprint, some or all item keys already belong to another request, or the replayed items do not match the request case.

## Sources

- BackOfficePrototype#2279 "Unify override governance and operational review"
- `server/routes/overrideRegister.ts`, `server/services/overrideRegister.ts`, `server/services/overrideRegister/` (`types.ts`, `normalization.ts`, `response.ts`, and the three source loaders)
- `client/src/pages/sevis-override-register.tsx`, `client/src/pages/sevis-override-register/register-row.tsx`
- `server/routes/sevisOverrideRegisterRoutes.ts`
- `migrations/20271204020000_link_override_requests_to_compliance_cases.sql`, `20271204030000_enforce_override_request_case_links.sql`, `20271204040000_fix_deferred_override_case_link_check.sql`, `20271204050000_snapshot_override_secondary_approval.sql`
