> ## Documentation Index
> Fetch the complete documentation index at: https://docs.korve.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# projectMaintenance

> Durable project maintenance policies, evidence-backed findings, and audited remediation with bounded automation and human approval.

Durable project maintenance policies, evidence-backed findings, and audited remediation with bounded automation and human approval.

## projectMaintenance.getPolicy

Get the versioned maintenance policy for this project.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/policy
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/policy" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description              |
| ------ | ------------------------ |
| `200`  | Maintenance policy.      |
| `404`  | No policy is configured. |

### Response body (200)

| Field                                 | Type      | Description                                                                                                                      |
| ------------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                             | boolean   | —                                                                                                                                |
| `schedule`                            | string    | One of: `hourly`, `daily`, `weekly`.                                                                                             |
| `categories`                          | string\[] | —                                                                                                                                |
| `environments`                        | string\[] | —                                                                                                                                |
| `autoRemediation`                     | object    | —                                                                                                                                |
| `autoRemediation.enabled`             | boolean   | —                                                                                                                                |
| `autoRemediation.maximumRisk`         | string    | Hard ceiling for unattended actions. Dangerous and destructive actions always require a human decision. One of: `read`, `write`. |
| `autoRemediation.allowedOperationIds` | string\[] | —                                                                                                                                |
| `autoRemediation.maxActionsPerRun`    | integer   | —                                                                                                                                |
| `version`                             | integer   | —                                                                                                                                |
| `updatedBy`                           | string    | —                                                                                                                                |
| `createdAt`                           | string    | Format: `date-time`.                                                                                                             |
| `updatedAt`                           | string    | Format: `date-time`.                                                                                                             |

## projectMaintenance.updatePolicy

Create or replace the maintenance policy. Automatic execution is restricted to an exact operation allowlist and read or write risk; elevated-risk actions still require approval.

```text theme={null}
PUT /v1/orgs/{orgId}/projects/{projectId}/maintenance/policy
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `admin`
* **Risk:** `dangerous` · sensitive (elevated blast radius)

### Request body

| Field                                 | Type            | Required | Description                                                                                                                      |
| ------------------------------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                             | boolean         | Yes      | —                                                                                                                                |
| `schedule`                            | string          | Yes      | One of: `hourly`, `daily`, `weekly`.                                                                                             |
| `categories`                          | string\[]       | Yes      | —                                                                                                                                |
| `environments`                        | string\[]       | Yes      | —                                                                                                                                |
| `autoRemediation`                     | object          | Yes      | —                                                                                                                                |
| `autoRemediation.enabled`             | boolean         | Yes      | —                                                                                                                                |
| `autoRemediation.maximumRisk`         | string          | Yes      | Hard ceiling for unattended actions. Dangerous and destructive actions always require a human decision. One of: `read`, `write`. |
| `autoRemediation.allowedOperationIds` | string\[]       | Yes      | —                                                                                                                                |
| `autoRemediation.maxActionsPerRun`    | integer         | Yes      | —                                                                                                                                |
| `expectedVersion`                     | integer or null | Yes      | —                                                                                                                                |

### Example

```bash theme={null}
curl -X PUT "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/policy" \
  -H "Authorization: Bearer korve_..." \
  -H "Content-Type: application/json" \
  -d '{
  "enabled": true,
  "schedule": "hourly",
  "categories": [
    "reliability"
  ],
  "environments": [
    "example"
  ],
  "autoRemediation": {
    "enabled": true,
    "maximumRisk": "read",
    "allowedOperationIds": [
      "example"
    ],
    "maxActionsPerRun": 1
  },
  "expectedVersion": 1
}'
```

### Responses

| Status | Description                            |
| ------ | -------------------------------------- |
| `200`  | Updated maintenance policy.            |
| `409`  | The submitted policy version is stale. |

### Response body (200)

| Field                                 | Type      | Description                                                                                                                      |
| ------------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`                             | boolean   | —                                                                                                                                |
| `schedule`                            | string    | One of: `hourly`, `daily`, `weekly`.                                                                                             |
| `categories`                          | string\[] | —                                                                                                                                |
| `environments`                        | string\[] | —                                                                                                                                |
| `autoRemediation`                     | object    | —                                                                                                                                |
| `autoRemediation.enabled`             | boolean   | —                                                                                                                                |
| `autoRemediation.maximumRisk`         | string    | Hard ceiling for unattended actions. Dangerous and destructive actions always require a human decision. One of: `read`, `write`. |
| `autoRemediation.allowedOperationIds` | string\[] | —                                                                                                                                |
| `autoRemediation.maxActionsPerRun`    | integer   | —                                                                                                                                |
| `version`                             | integer   | —                                                                                                                                |
| `updatedBy`                           | string    | —                                                                                                                                |
| `createdAt`                           | string    | Format: `date-time`.                                                                                                             |
| `updatedAt`                           | string    | Format: `date-time`.                                                                                                             |

## projectMaintenance.listRuns

Page durable maintenance runs, newest first.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/runs
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Query parameters

| Name     | Type    | Required | Description                                                                              |
| -------- | ------- | -------- | ---------------------------------------------------------------------------------------- |
| `cursor` | string  | No       | —                                                                                        |
| `limit`  | integer | No       | —                                                                                        |
| `status` | string  | No       | One of: `queued`, `running`, `waiting_for_approval`, `succeeded`, `failed`, `cancelled`. |

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/runs?cursor=example" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description       |
| ------ | ----------------- |
| `200`  | Maintenance runs. |

### Response body (200)

| Field                        | Type           | Description                                                                              |
| ---------------------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `items`                      | object\[]      | —                                                                                        |
| `items[].id`                 | string         | Format: `uuid`.                                                                          |
| `items[].trigger`            | string         | One of: `scheduled`, `manual`, `deployment`.                                             |
| `items[].status`             | string         | One of: `queued`, `running`, `waiting_for_approval`, `succeeded`, `failed`, `cancelled`. |
| `items[].categories`         | string\[]      | —                                                                                        |
| `items[].environments`       | string\[]      | —                                                                                        |
| `items[].policyVersion`      | integer        | —                                                                                        |
| `items[].findingCount`       | integer        | —                                                                                        |
| `items[].pendingActionCount` | integer        | —                                                                                        |
| `items[].error`              | string or null | —                                                                                        |
| `items[].startedAt`          | string or null | Format: `date-time`.                                                                     |
| `items[].finishedAt`         | string or null | Format: `date-time`.                                                                     |
| `items[].createdAt`          | string         | Format: `date-time`.                                                                     |
| `nextCursor`                 | string or null | —                                                                                        |

## projectMaintenance.createRun

Start an evidence-backed maintenance run using the current saved policy or a bounded subset of its scope.

```text theme={null}
POST /v1/orgs/{orgId}/projects/{projectId}/maintenance/runs
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `admin`
* **Billing:** requires active organization billing — returns `402` otherwise.
* **Risk:** `write`

### Request body

| Field          | Type      | Required | Description |
| -------------- | --------- | -------- | ----------- |
| `categories`   | string\[] | No       | —           |
| `environments` | string\[] | No       | —           |

### Example

```bash theme={null}
curl -X POST "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/runs" \
  -H "Authorization: Bearer korve_..." \
  -H "Content-Type: application/json" \
  -d '{}'
```

### Responses

| Status | Description                          |
| ------ | ------------------------------------ |
| `202`  | Queued maintenance run.              |
| `409`  | An equivalent run is already active. |

### Response body (202)

| Field                | Type           | Description                                                                              |
| -------------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `id`                 | string         | Format: `uuid`.                                                                          |
| `trigger`            | string         | One of: `scheduled`, `manual`, `deployment`.                                             |
| `status`             | string         | One of: `queued`, `running`, `waiting_for_approval`, `succeeded`, `failed`, `cancelled`. |
| `categories`         | string\[]      | —                                                                                        |
| `environments`       | string\[]      | —                                                                                        |
| `policyVersion`      | integer        | —                                                                                        |
| `findingCount`       | integer        | —                                                                                        |
| `pendingActionCount` | integer        | —                                                                                        |
| `error`              | string or null | —                                                                                        |
| `startedAt`          | string or null | Format: `date-time`.                                                                     |
| `finishedAt`         | string or null | Format: `date-time`.                                                                     |
| `createdAt`          | string         | Format: `date-time`.                                                                     |

## projectMaintenance.getRun

Get one durable maintenance run and its aggregate result counts.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/runs/{runId}
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/runs/$RUN_ID" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description                  |
| ------ | ---------------------------- |
| `200`  | Maintenance run.             |
| `404`  | No such run in this project. |

### Response body (200)

| Field                | Type           | Description                                                                              |
| -------------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `id`                 | string         | Format: `uuid`.                                                                          |
| `trigger`            | string         | One of: `scheduled`, `manual`, `deployment`.                                             |
| `status`             | string         | One of: `queued`, `running`, `waiting_for_approval`, `succeeded`, `failed`, `cancelled`. |
| `categories`         | string\[]      | —                                                                                        |
| `environments`       | string\[]      | —                                                                                        |
| `policyVersion`      | integer        | —                                                                                        |
| `findingCount`       | integer        | —                                                                                        |
| `pendingActionCount` | integer        | —                                                                                        |
| `error`              | string or null | —                                                                                        |
| `startedAt`          | string or null | Format: `date-time`.                                                                     |
| `finishedAt`         | string or null | Format: `date-time`.                                                                     |
| `createdAt`          | string         | Format: `date-time`.                                                                     |

## projectMaintenance.cancelRun

Cancel an active run without executing any remaining proposed actions.

```text theme={null}
POST /v1/orgs/{orgId}/projects/{projectId}/maintenance/runs/{runId}/cancel
```

* **Auth:** Dashboard session only — organization API keys are rejected.
* **Minimum role:** `admin`
* **Risk:** `dangerous` · sensitive (elevated blast radius)

### Request body

| Field    | Type   | Required | Description |
| -------- | ------ | -------- | ----------- |
| `reason` | string | Yes      | —           |

### Example

```bash theme={null}
curl -X POST "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/runs/$RUN_ID/cancel" \
  -b "$SESSION" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "example"
}'
```

### Responses

| Status | Description                  |
| ------ | ---------------------------- |
| `200`  | Cancelled maintenance run.   |
| `404`  | No such run in this project. |
| `409`  | The run is already terminal. |

### Response body (200)

| Field                | Type           | Description                                                                              |
| -------------------- | -------------- | ---------------------------------------------------------------------------------------- |
| `id`                 | string         | Format: `uuid`.                                                                          |
| `trigger`            | string         | One of: `scheduled`, `manual`, `deployment`.                                             |
| `status`             | string         | One of: `queued`, `running`, `waiting_for_approval`, `succeeded`, `failed`, `cancelled`. |
| `categories`         | string\[]      | —                                                                                        |
| `environments`       | string\[]      | —                                                                                        |
| `policyVersion`      | integer        | —                                                                                        |
| `findingCount`       | integer        | —                                                                                        |
| `pendingActionCount` | integer        | —                                                                                        |
| `error`              | string or null | —                                                                                        |
| `startedAt`          | string or null | Format: `date-time`.                                                                     |
| `finishedAt`         | string or null | Format: `date-time`.                                                                     |
| `createdAt`          | string         | Format: `date-time`.                                                                     |

## projectMaintenance.listFindings

Page retained project findings with filters for run, status, severity, and category.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/findings
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Query parameters

| Name       | Type    | Required | Description                              |
| ---------- | ------- | -------- | ---------------------------------------- |
| `cursor`   | string  | No       | —                                        |
| `limit`    | integer | No       | —                                        |
| `runId`    | string  | No       | Format: `uuid`.                          |
| `status`   | string  | No       | One of: `open`, `dismissed`, `resolved`. |
| `severity` | string  | No       | One of: `info`, `warning`, `critical`.   |
| `category` | string  | No       | One of: `reliability`.                   |

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/findings?cursor=example" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description           |
| ------ | --------------------- |
| `200`  | Maintenance findings. |

### Response body (200)

| Field                     | Type           | Description                              |
| ------------------------- | -------------- | ---------------------------------------- |
| `items`                   | object\[]      | —                                        |
| `items[].id`              | string         | Format: `uuid`.                          |
| `items[].runId`           | string         | Format: `uuid`.                          |
| `items[].category`        | string         | One of: `reliability`.                   |
| `items[].severity`        | string         | One of: `info`, `warning`, `critical`.   |
| `items[].status`          | string         | One of: `open`, `dismissed`, `resolved`. |
| `items[].title`           | string         | —                                        |
| `items[].summary`         | string         | —                                        |
| `items[].recommendation`  | string         | —                                        |
| `items[].resourceType`    | string         | —                                        |
| `items[].resourceId`      | string or null | —                                        |
| `items[].firstObservedAt` | string         | Format: `date-time`.                     |
| `items[].lastObservedAt`  | string         | Format: `date-time`.                     |
| `items[].resolvedAt`      | string or null | Format: `date-time`.                     |
| `nextCursor`              | string or null | —                                        |

## projectMaintenance.getFinding

Get one finding with stable resource identity and retained history timestamps.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/findings/{findingId}
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/findings/$FINDING_ID" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description                      |
| ------ | -------------------------------- |
| `200`  | Maintenance finding.             |
| `404`  | No such finding in this project. |

### Response body (200)

| Field             | Type           | Description                              |
| ----------------- | -------------- | ---------------------------------------- |
| `id`              | string         | Format: `uuid`.                          |
| `runId`           | string         | Format: `uuid`.                          |
| `category`        | string         | One of: `reliability`.                   |
| `severity`        | string         | One of: `info`, `warning`, `critical`.   |
| `status`          | string         | One of: `open`, `dismissed`, `resolved`. |
| `title`           | string         | —                                        |
| `summary`         | string         | —                                        |
| `recommendation`  | string         | —                                        |
| `resourceType`    | string         | —                                        |
| `resourceId`      | string or null | —                                        |
| `firstObservedAt` | string         | Format: `date-time`.                     |
| `lastObservedAt`  | string         | Format: `date-time`.                     |
| `resolvedAt`      | string or null | Format: `date-time`.                     |

## projectMaintenance.updateFinding

Dismiss, resolve, or reopen a finding with an audited operator reason.

```text theme={null}
PATCH /v1/orgs/{orgId}/projects/{projectId}/maintenance/findings/{findingId}
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `admin`
* **Risk:** `write`

### Request body

| Field    | Type   | Required | Description                              |
| -------- | ------ | -------- | ---------------------------------------- |
| `status` | string | Yes      | One of: `open`, `dismissed`, `resolved`. |
| `reason` | string | Yes      | —                                        |

### Example

```bash theme={null}
curl -X PATCH "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/findings/$FINDING_ID" \
  -H "Authorization: Bearer korve_..." \
  -H "Content-Type: application/json" \
  -d '{
  "status": "open",
  "reason": "example"
}'
```

### Responses

| Status | Description                      |
| ------ | -------------------------------- |
| `200`  | Updated maintenance finding.     |
| `404`  | No such finding in this project. |

### Response body (200)

| Field             | Type           | Description                              |
| ----------------- | -------------- | ---------------------------------------- |
| `id`              | string         | Format: `uuid`.                          |
| `runId`           | string         | Format: `uuid`.                          |
| `category`        | string         | One of: `reliability`.                   |
| `severity`        | string         | One of: `info`, `warning`, `critical`.   |
| `status`          | string         | One of: `open`, `dismissed`, `resolved`. |
| `title`           | string         | —                                        |
| `summary`         | string         | —                                        |
| `recommendation`  | string         | —                                        |
| `resourceType`    | string         | —                                        |
| `resourceId`      | string or null | —                                        |
| `firstObservedAt` | string         | Format: `date-time`.                     |
| `lastObservedAt`  | string         | Format: `date-time`.                     |
| `resolvedAt`      | string or null | Format: `date-time`.                     |

## projectMaintenance.listEvidence

Page the immutable, redacted evidence retained for one finding.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/findings/{findingId}/evidence
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Query parameters

| Name     | Type    | Required | Description |
| -------- | ------- | -------- | ----------- |
| `cursor` | string  | No       | —           |
| `limit`  | integer | No       | —           |

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/findings/$FINDING_ID/evidence?cursor=example" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description                      |
| ------ | -------------------------------- |
| `200`  | Finding evidence.                |
| `404`  | No such finding in this project. |

### Response body (200)

| Field                       | Type           | Description                                                        |
| --------------------------- | -------------- | ------------------------------------------------------------------ |
| `items`                     | object\[]      | —                                                                  |
| `items[].id`                | string         | Format: `uuid`.                                                    |
| `items[].runId`             | string         | Format: `uuid`.                                                    |
| `items[].findingId`         | string or null | Format: `uuid`.                                                    |
| `items[].kind`              | string         | One of: `metric`, `log`, `configuration`, `query`, `verification`. |
| `items[].sourceOperationId` | string or null | —                                                                  |
| `items[].summary`           | string         | —                                                                  |
| `items[].data`              | object         | —                                                                  |
| `items[].capturedAt`        | string         | Format: `date-time`.                                               |
| `nextCursor`                | string or null | —                                                                  |

## projectMaintenance.listActions

Page proposed and completed remediation actions with their immutable previews and outcomes.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/actions
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Query parameters

| Name     | Type    | Required | Description                                                                                                       |
| -------- | ------- | -------- | ----------------------------------------------------------------------------------------------------------------- |
| `cursor` | string  | No       | —                                                                                                                 |
| `limit`  | integer | No       | —                                                                                                                 |
| `runId`  | string  | No       | Format: `uuid`.                                                                                                   |
| `status` | string  | No       | One of: `proposed`, `approval_required`, `approved`, `rejected`, `running`, `succeeded`, `failed`, `rolled_back`. |

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/actions?cursor=example" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description          |
| ------ | -------------------- |
| `200`  | Maintenance actions. |

### Response body (200)

| Field                    | Type           | Description                                                                                                       |
| ------------------------ | -------------- | ----------------------------------------------------------------------------------------------------------------- |
| `items`                  | object\[]      | —                                                                                                                 |
| `items[].id`             | string         | Format: `uuid`.                                                                                                   |
| `items[].runId`          | string         | Format: `uuid`.                                                                                                   |
| `items[].findingId`      | string or null | Format: `uuid`.                                                                                                   |
| `items[].operationId`    | string         | —                                                                                                                 |
| `items[].risk`           | string         | One of: `read`, `write`, `dangerous`, `destructive`.                                                              |
| `items[].status`         | string         | One of: `proposed`, `approval_required`, `approved`, `rejected`, `running`, `succeeded`, `failed`, `rolled_back`. |
| `items[].version`        | integer        | —                                                                                                                 |
| `items[].input`          | object         | —                                                                                                                 |
| `items[].preview`        | object         | —                                                                                                                 |
| `items[].result`         | object         | —                                                                                                                 |
| `items[].error`          | string or null | —                                                                                                                 |
| `items[].decidedBy`      | string or null | —                                                                                                                 |
| `items[].decisionReason` | string or null | —                                                                                                                 |
| `items[].decidedAt`      | string or null | Format: `date-time`.                                                                                              |
| `items[].executedAt`     | string or null | Format: `date-time`.                                                                                              |
| `items[].createdAt`      | string         | Format: `date-time`.                                                                                              |
| `nextCursor`             | string or null | —                                                                                                                 |

## projectMaintenance.listAudit

Page the append-only project maintenance audit trail for policies, runs, findings, approvals, execution, verification, and rollback.

```text theme={null}
GET /v1/orgs/{orgId}/projects/{projectId}/maintenance/audit
```

* **Auth:** Organization API key (`Authorization: Bearer korve_...`) or dashboard session.
* **Minimum role:** `member`
* **Risk:** `read`

### Query parameters

| Name     | Type    | Required | Description |
| -------- | ------- | -------- | ----------- |
| `cursor` | string  | No       | —           |
| `limit`  | integer | No       | —           |

### Example

```bash theme={null}
curl "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/audit?cursor=example" \
  -H "Authorization: Bearer korve_..."
```

### Responses

| Status | Description               |
| ------ | ------------------------- |
| `200`  | Maintenance audit events. |

### Response body (200)

| Field               | Type           | Description          |
| ------------------- | -------------- | -------------------- |
| `items`             | object\[]      | —                    |
| `items[].id`        | string         | Format: `uuid`.      |
| `items[].projectId` | string         | Format: `uuid`.      |
| `items[].runId`     | string or null | Format: `uuid`.      |
| `items[].actionId`  | string or null | Format: `uuid`.      |
| `items[].actorId`   | string or null | —                    |
| `items[].event`     | string         | —                    |
| `items[].metadata`  | object         | —                    |
| `items[].createdAt` | string         | Format: `date-time`. |
| `nextCursor`        | string or null | —                    |

## projectMaintenance.decideAction

Approve or reject one version-bound, one-use action. Approval rechecks current RBAC, tenant scope, billing, target state, and request schema before executing and recording verification evidence.

```text theme={null}
POST /v1/orgs/{orgId}/projects/{projectId}/maintenance/actions/{actionId}/decision
```

* **Auth:** Dashboard session only — organization API keys are rejected.
* **Minimum role:** `member`
* **Billing:** requires active organization billing — returns `402` otherwise.
* **Risk:** `dangerous` · sensitive (elevated blast radius)

### Request body

| Field           | Type    | Required | Description                  |
| --------------- | ------- | -------- | ---------------------------- |
| `decision`      | string  | Yes      | One of: `approve`, `reject`. |
| `actionVersion` | integer | Yes      | —                            |
| `reason`        | string  | Yes      | —                            |

### Example

```bash theme={null}
curl -X POST "https://api.korve.dev/v1/orgs/$ORG_ID/projects/$PROJECT_ID/maintenance/actions/$ACTION_ID/decision" \
  -b "$SESSION" \
  -H "Content-Type: application/json" \
  -d '{
  "decision": "approve",
  "actionVersion": 1,
  "reason": "example"
}'
```

### Responses

| Status | Description                                                  |
| ------ | ------------------------------------------------------------ |
| `200`  | Decided maintenance action.                                  |
| `403`  | Current actor cannot execute the target operation.           |
| `404`  | No such action in this project.                              |
| `409`  | The action was already decided, expired, or changed version. |

### Response body (200)

| Field            | Type           | Description                                                                                                       |
| ---------------- | -------------- | ----------------------------------------------------------------------------------------------------------------- |
| `id`             | string         | Format: `uuid`.                                                                                                   |
| `runId`          | string         | Format: `uuid`.                                                                                                   |
| `findingId`      | string or null | Format: `uuid`.                                                                                                   |
| `operationId`    | string         | —                                                                                                                 |
| `risk`           | string         | One of: `read`, `write`, `dangerous`, `destructive`.                                                              |
| `status`         | string         | One of: `proposed`, `approval_required`, `approved`, `rejected`, `running`, `succeeded`, `failed`, `rolled_back`. |
| `version`        | integer        | —                                                                                                                 |
| `input`          | object         | —                                                                                                                 |
| `preview`        | object         | —                                                                                                                 |
| `result`         | object         | —                                                                                                                 |
| `error`          | string or null | —                                                                                                                 |
| `decidedBy`      | string or null | —                                                                                                                 |
| `decisionReason` | string or null | —                                                                                                                 |
| `decidedAt`      | string or null | Format: `date-time`.                                                                                              |
| `executedAt`     | string or null | Format: `date-time`.                                                                                              |
| `createdAt`      | string         | Format: `date-time`.                                                                                              |
