# ListApprovalPolicies

## Overview

ListApprovalPolicies returns approval policies filtered by `purpose` and / or `status`. It is the canonical lookup that wrapper modules call from TypeScript code at request creation time to pick the right policy for a given business intent — for example `listApprovalPolicies({ purpose: "PRODUCT_ACTIVATION", status: "ACTIVE" })` returns every active product-activation policy, and the wrapper command then chooses by name based on the target's attributes. The query exposes a parametric status filter (rather than baking status into the name) because both single-status and multi-status callers exist: wrapper selection wants only ACTIVE rows, while admin reporting wants the full DRAFT / ACTIVE / INACTIVE universe.

## Business Rules

- Accepts an optional `purpose` filter; when omitted, all purposes are included
- Accepts an optional `status` filter (`DRAFT` | `ACTIVE` | `INACTIVE`); when omitted, all statuses are included
- Accepts standard pagination inputs (`limit`, `offset`, `orderBy`, `orderDirection`); `limit` defaults to the framework `DEFAULT_PAGE_SIZE`
- Default ordering when no `orderBy` is supplied is `(purpose ASC, name ASC, activatedAt DESC)` so callers see the latest activated revision of each `(purpose, name)` first within the group
- Callers may override ordering by supplying `orderBy` (`purpose | name | activatedAt | createdAt | id`) and `orderDirection`
- Returns a paginated result `{ items, hasNextPage }`; an empty `items` array is not an error

## Process Flow

```mermaid
flowchart TD
    A[Receive optional purpose and status filters,<br/>plus optional pagination inputs] --> B[SELECT ApprovalPolicy<br/>where purpose matches if supplied<br/>and status matches if supplied]
    B --> C{orderBy supplied?}
    C -->|No| C1[ORDER BY purpose ASC, name ASC, activatedAt DESC]
    C -->|Yes| C2[ORDER BY orderBy orderDirection]
    C1 --> D[LIMIT limit + 1 OFFSET offset]
    C2 --> D
    D --> E[Return paginated result &lcub; items, hasNextPage &rcub;]
```

## External Dependencies

- None

## Error Scenarios

- None — invalid status values are caught at the schema layer; an empty result is not an error

## Test Cases

- returns all ACTIVE policies when status = ACTIVE filter is supplied
- returns only policies matching the supplied purpose
- returns combinations of purpose and status filters
- returns all statuses when status filter is omitted
- returns all purposes when purpose filter is omitted
- returns an empty array when no policies match
- includes both DRAFT and INACTIVE rows when no implicit hide is applied
- orders by (purpose ASC, name ASC, activatedAt DESC) when no orderBy is supplied
