# UpdateAuditPolicy

## Overview

UpdateAuditPolicy modifies the configuration of an existing audit policy that is in DRAFT status. The command allows updating the operation type, field-level rules, and sensitivity modes. Only DRAFT policies can be updated — ACTIVE and INACTIVE policies are immutable.

This command requires the `manageAuditPolicies` permission at the appropriate scope.

## Business Rules

- Only policies in DRAFT status can be updated
- entityName and companyId are fixed by the existing record and are not part of the update input
- Operation type can be updated; must be one of CREATE, UPDATE, or DELETE
- Field names in field-level rules must be non-empty strings
- Field-level rules can be added, modified, or removed
- When adding or modifying field-level rules, sensitivityMode defaults to CAPTURE if not specified
- Field names in field-level rules must be a subset of the entity's registered auditableFields
- Duplicate field names within the same policy are rejected
- Caller must hold `manageAuditPolicies` permission at the appropriate scope
- A caller with company-scoped `manageAuditPolicies` can only update policies for their assigned companies
- A caller with global-scoped `manageAuditPolicies` can only update global policies

## Process Flow

```mermaid
flowchart TD
    A[Receive update request] --> B{Caller has manageAuditPolicies?}
    B -->|No| C[Return error: INSUFFICIENT_PERMISSION]
    B -->|Yes| D{Policy exists?}
    D -->|No| E[Return error: POLICY_NOT_FOUND]
    D -->|Yes| D2{Caller scope covers this policy?}
    D2 -->|No| D3[Return error: UNAUTHORIZED]
    D2 -->|Yes| F{Policy in DRAFT status?}
    F -->|No| G[Return error: INVALID_STATE]
    F -->|Yes| G2{operationType valid?}
    G2 -->|No| G3[Return error: INVALID_OPERATION_TYPE]
    G2 -->|Yes| H{Validate field rules}
    H -->|Invalid| I[Return validation error]
    H -->|Valid| J[Update AuditPolicy fields]
    J --> K[Update PolicyFieldRule records]
    K --> L[Return updated policy]
```

## External Dependencies

- None

## Error Scenarios

- **INSUFFICIENT_PERMISSION**: Caller lacks the required command permission (shared error from defineCommand)
- **UNAUTHORIZED**: Caller's permission scope does not cover this policy (e.g., company-scoped caller managing a different company's policy, or global-scoped caller managing a company-scoped policy)
- **POLICY_NOT_FOUND**: Specified policy ID does not exist
- **INVALID_STATE**: Policy is not in DRAFT status
- **INVALID_OPERATION_TYPE**: operationType is not one of CREATE, UPDATE, DELETE
- **INVALID_FIELD_NAME**: A field name in field-level rules is empty or not in the entity's auditableFields
- **DUPLICATE_FIELD_NAME**: The same field name appears more than once in field-level rules
- **INVALID_SENSITIVITY_MODE**: sensitivityMode is not one of CAPTURE, MASK, HASH, EXCLUDE

## Test Cases

- updates operation type on DRAFT policy
- updates field-level rules on DRAFT policy
- updates sensitivity modes on field-level rules
- adds new field-level rules to DRAFT policy
- removes field-level rules from DRAFT policy
- defaults sensitivityMode to CAPTURE when adding a field-level rule without explicit sensitivityMode
- defaults sensitivityMode to CAPTURE when modifying a field-level rule and sensitivityMode is omitted
- rejects update on ACTIVE policy
- rejects update on INACTIVE policy
- rejects when policy does not exist
- rejects duplicate field names
- rejects field names not in entity's auditableFields
- rejects invalid operation type
- rejects invalid sensitivity mode
- rejects when caller lacks manageAuditPolicies permission
- rejects when company-scoped caller updates policy for a different company
- rejects when global-scoped caller updates company-scoped policy
