# Forgetting

Every registered forgetting instance operation, with source-derived inputs, outputs, access policy, and errors.

Source: https://docs.minds.sh/docs/api/instance/forgetting



This reference covers **7 HTTP operations** registered by the Akasha daemon. Call these paths on your instance base URL. See [authentication](/docs/api/instance/authentication), [errors](/docs/api/instance/errors), and [coverage](/docs/api/instance/coverage) before integrating.

| Method | Path                                  | Operation                                                             |
| ------ | ------------------------------------- | --------------------------------------------------------------------- |
| `GET`  | `/v1/forgetting/requests`             | [Forgetting list requests](#get-v1-forgetting-requests)               |
| `POST` | `/v1/forgetting/requests`             | [Forgetting create request](#post-v1-forgetting-requests)             |
| `POST` | `/v1/forgetting/requests/:id/approve` | [Forgetting approve request](#post-v1-forgetting-requests-id-approve) |
| `GET`  | `/v1/forgetting/proof/:id`            | [Forgetting get proof](#get-v1-forgetting-proof-id)                   |
| `GET`  | `/v1/forgetting/policies`             | [Forgetting list policies](#get-v1-forgetting-policies)               |
| `POST` | `/v1/forgetting/policies/:id/toggle`  | [Forgetting toggle policy](#post-v1-forgetting-policies-id-toggle)    |
| `GET`  | `/v1/forgetting/stats`                | [Forgetting stats](#get-v1-forgetting-stats)                          |

<a id="get-v1-forgetting-requests" />

## GET `/v1/forgetting/requests` [#get-v1forgettingrequests]

List all forgetting requests from the system keyspace. GET /v1/forgetting/requests

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request]

No typed JSON, query, or path extractor is declared in the handler signature. Headers or request objects may still be consumed; the signature below is authoritative.

### Response [#response]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
serde_json::json!({
        "requests": results,
        "count": results.len()
    })
```

### Errors and validation [#errors-and-validation]

Directly referenced error variants: `InvalidRequest`. Middleware and delegated services can return additional errors described in the shared error reference.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_list_requests(
        State(state): State<AppState>,
        Extension(db): Extension<Arc<akasha::AkashaDB>>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();
        ensure_forgetting_keyspace(&db).await?;

        let results = db
            .query(FORGETTING_KEYSPACE)
            .limit(500)
            .execute()
            .await
            .map_err(|e| DaemonError::InvalidRequest(e.to_string()))?;

        Ok(Json(serde_json::json!({
            "requests": results,
            "count": results.len()
        })))
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:210`. Registration: `akasha-daemon/src/forgetting.rs:482`.

<a id="post-v1-forgetting-requests" />

## POST `/v1/forgetting/requests` [#post-v1forgettingrequests]

Create a new forgetting request with status "pending". POST /v1/forgetting/requests

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request-1]

**Json** — `CreateForgettingRequest`

| Field             | Rust type        | Required on input         | Notes                                          |
| ----------------- | ---------------- | ------------------------- | ---------------------------------------------- |
| `reason`          | `String`         | Yes                       | Human-readable reason for the deletion request |
| `target_keyspace` | `String`         | Yes                       | The keyspace containing the target record(s)   |
| `target_ids`      | `Vec<String>`    | Yes                       | IDs of the records to be deleted               |
| `requester`       | `Option<String>` | No; optional or defaulted | Optional requester identifier                  |

```rust
struct CreateForgettingRequest {
    /// Human-readable reason for the deletion request
    reason: String,
    /// The keyspace containing the target record(s)
    target_keyspace: String,
    /// IDs of the records to be deleted
    target_ids: Vec<String>,
    /// Optional requester identifier
    requester: Option<String>,
}
```

### Response [#response-1]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
serde_json::json!({
            "id": record.id,
            "stored_key": stored_id,
            "status": "pending"
        })
```

### Errors and validation [#errors-and-validation-1]

Directly referenced error variants: `Internal`, `InvalidRequest`. Middleware and delegated services can return additional errors described in the shared error reference.

Explicit status constants: `CREATED`.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_create_request(
        State(state): State<AppState>,
        Extension(db): Extension<Arc<akasha::AkashaDB>>,
        Json(req): Json<CreateForgettingRequest>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();
        ensure_forgetting_keyspace(&db).await?;

        if req.target_ids.is_empty() {
            return Err(DaemonError::InvalidRequest(
                "target_ids must not be empty".to_string(),
            ));
        }

        let record = ForgettingRecord {
            id: Uuid::new_v4().to_string(),
            status: "pending".to_string(),
            reason: req.reason,
            target_keyspace: req.target_keyspace,
            target_ids: req.target_ids,
            requester: req.requester.unwrap_or_else(|| "anonymous".to_string()),
            created_at: Utc::now().to_rfc3339(),
            approved_at: None,
            proof_hash: None,
            merkle_leaves: Vec::new(),
        };

        let val = serde_json::to_value(&record)
            .map_err(|e| DaemonError::Internal(format!("serialization error: {}", e)))?;

        let stored_id = db
            .put(FORGETTING_KEYSPACE, &val)
            .await
            .map_err(|e| DaemonError::Internal(format!("failed to store request: {}", e)))?;

        Ok((
            axum::http::StatusCode::CREATED,
            Json(serde_json::json!({
                "id": record.id,
                "stored_key": stored_id,
                "status": "pending"
            })),
        ))
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:233`. Registration: `akasha-daemon/src/forgetting.rs:482`.

<a id="post-v1-forgetting-requests-id-approve" />

## POST `/v1/forgetting/requests/:id/approve` [#post-v1forgettingrequestsidapprove]

Approve a forgetting request: execute the deletions and generate a proof. POST /v1/forgetting/requests/:id/approve

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request-2]

**Path** — `String`

```json
{
  "type": "string"
}
```

### Response [#response-2]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
resp
```

### Errors and validation [#errors-and-validation-2]

Directly referenced error variants: `InvalidRequest`. Middleware and delegated services can return additional errors described in the shared error reference.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_approve_request(
        Path(id): Path<String>,
        State(state): State<AppState>,
        Extension(db): Extension<Arc<akasha::AkashaDB>>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();
        ensure_forgetting_keyspace(&db).await?;

        let mut record = load_record(&db, &id).await?;

        if record.status != "pending" {
            return Err(DaemonError::InvalidRequest(format!(
                "request '{}' is not in pending state (current: {})",
                id, record.status
            )));
        }

        // Execute deletions and collect leaf hashes for the Merkle proof.
        let mut leaf_hashes: Vec<String> = Vec::new();
        let mut deletion_errors: Vec<String> = Vec::new();

        for target_id in &record.target_ids {
            // Attempt to read the record before deletion to hash its content.
            match db.get(&record.target_keyspace, target_id).await {
                Ok(Some(content)) => {
                    let content_bytes = serde_json::to_vec(&content).unwrap_or_default();
                    let leaf = sha256_hex(&content_bytes);
                    leaf_hashes.push(leaf);

                    // Now delete the record
                    match db.delete(&record.target_keyspace, target_id).await {
                        Ok(_) => {}
                        Err(e) => deletion_errors.push(format!("{}: {}", target_id, e)),
                    }
                }
                Ok(None) => {
                    // Record already gone — hash a sentinel
                    leaf_hashes.push(sha256_hex(format!("not_found:{}", target_id).as_bytes()));
                }
                Err(e) => {
                    deletion_errors.push(format!("{}: {}", target_id, e));
                    leaf_hashes.push(sha256_hex(format!("error:{}", target_id).as_bytes()));
                }
            }
        }

        // Build Merkle root from the leaf hashes
        let root_hash = merkle_root(&leaf_hashes);

        record.status = "approved".to_string();
        record.approved_at = Some(Utc::now().to_rfc3339());
        record.proof_hash = Some(root_hash.clone());
        record.merkle_leaves = leaf_hashes;

        save_record(&db, &record).await?;

        let mut resp = serde_json::json!({
            "id": record.id,
            "status": "approved",
            "proof_hash": root_hash,
            "deleted_count": record.target_ids.len(),
        });

        if !deletion_errors.is_empty() {
            resp["deletion_errors"] = serde_json::json!(deletion_errors);
        }

        Ok(Json(resp))
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:281`. Registration: `akasha-daemon/src/forgetting.rs:486`.

<a id="get-v1-forgetting-proof-id" />

## GET `/v1/forgetting/proof/:id` [#get-v1forgettingproofid]

Get the deletion proof for a completed forgetting request. GET /v1/forgetting/proof/:id

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request-3]

**Path** — `String`

```json
{
  "type": "string"
}
```

### Response [#response-3]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
serde_json::json!({
        "id": record.id,
        "status": record.status,
        "proof_hash": proof_hash,
        "algorithm": "sha256-merkle",
        "merkle_leaves": record.merkle_leaves,
        "target_keyspace": record.target_keyspace,
        "target_ids": record.target_ids,
        "approved_at": record.approved_at,
    })
```

### Errors and validation [#errors-and-validation-3]

Directly referenced error variants: `InvalidRequest`. Middleware and delegated services can return additional errors described in the shared error reference.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_get_proof(
        Path(id): Path<String>,
        State(state): State<AppState>,
        Extension(db): Extension<Arc<akasha::AkashaDB>>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();
        ensure_forgetting_keyspace(&db).await?;

        let record = load_record(&db, &id).await?;

        let proof_hash = record.proof_hash.as_deref().unwrap_or("");
        if proof_hash.is_empty() {
            return Err(DaemonError::InvalidRequest(format!(
                "no proof available for request '{}' (status: {})",
                id, record.status
            )));
        }

        Ok(Json(serde_json::json!({
            "id": record.id,
            "status": record.status,
            "proof_hash": proof_hash,
            "algorithm": "sha256-merkle",
            "merkle_leaves": record.merkle_leaves,
            "target_keyspace": record.target_keyspace,
            "target_ids": record.target_ids,
            "approved_at": record.approved_at,
        })))
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:354`. Registration: `akasha-daemon/src/forgetting.rs:490`.

<a id="get-v1-forgetting-policies" />

## GET `/v1/forgetting/policies` [#get-v1forgettingpolicies]

Return default forgetting policies. GET /v1/forgetting/policies

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request-4]

No typed JSON, query, or path extractor is declared in the handler signature. Headers or request objects may still be consumed; the signature below is authoritative.

### Response [#response-4]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
serde_json::json!({
        "policies": policies,
        "count": policies.len()
    })
```

### Errors and validation [#errors-and-validation-4]

Directly referenced error variants: none in the handler body. Middleware and delegated services can return additional errors described in the shared error reference.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_list_policies(
        State(state): State<AppState>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();
        let policies = default_policies();
        Ok(Json(serde_json::json!({
            "policies": policies,
            "count": policies.len()
        })))
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:387`. Registration: `akasha-daemon/src/forgetting.rs:491`.

<a id="post-v1-forgetting-policies-id-toggle" />

## POST `/v1/forgetting/policies/:id/toggle` [#post-v1forgettingpoliciesidtoggle]

Toggle a policy's enabled status. POST /v1/forgetting/policies/:id/toggle

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request-5]

**Path** — `String`

```json
{
  "type": "string"
}
```

**Json** — `TogglePolicyReq`

| Field     | Rust type      | Required on input         | Notes |
| --------- | -------------- | ------------------------- | ----- |
| `enabled` | `Option<bool>` | No; optional or defaulted |       |

```rust
struct TogglePolicyReq {
    enabled: Option<bool>,
}
```

### Response [#response-5]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
serde_json::json!({
                "id": p.id,
                "name": p.name,
                "enabled": p.enabled,
                "message": "Policy toggled successfully. Note: policy state is ephemeral in this release."
            })
```

### Errors and validation [#errors-and-validation-5]

Directly referenced error variants: `InvalidRequest`. Middleware and delegated services can return additional errors described in the shared error reference.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_toggle_policy(
        Path(policy_id): Path<String>,
        State(state): State<AppState>,
        Json(req): Json<TogglePolicyReq>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();

        let mut policies = default_policies();
        let policy = policies.iter_mut().find(|p| p.id == policy_id);

        match policy {
            Some(p) => {
                // If caller provides an explicit value use it; otherwise toggle.
                let new_enabled = req.enabled.unwrap_or(!p.enabled);
                p.enabled = new_enabled;
                Ok(Json(serde_json::json!({
                    "id": p.id,
                    "name": p.name,
                    "enabled": p.enabled,
                    "message": "Policy toggled successfully. Note: policy state is ephemeral in this release."
                })))
            }
            None => Err(DaemonError::InvalidRequest(format!(
                "policy '{}' not found",
                policy_id
            ))),
        }
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:401`. Registration: `akasha-daemon/src/forgetting.rs:492`.

<a id="get-v1-forgetting-stats" />

## GET `/v1/forgetting/stats` [#get-v1forgettingstats]

Count forgetting requests by status. GET /v1/forgetting/stats

| Availability         | Source contract                                                  |
| -------------------- | ---------------------------------------------------------------- |
| Registration         | `always registered; requires database at runtime`                |
| Runtime service      | No prefix-level service check; handler dependencies still apply. |
| Handler dependencies | See handler source and return expressions.                       |

**Access:** Daemon authentication and capability namespace authority; memory-domain permissions apply where mapped.

### Request [#request-6]

No typed JSON, query, or path extractor is declared in the handler signature. Headers or request objects may still be consumed; the signature below is authoritative.
&#x2A;*JSON field accesses in handler:** `status`. Nested lookups are included; this list alone does not establish requiredness.

### Response [#response-6]

**Declared return:** `Result<impl IntoResponse, DaemonError>`

The following are the exact JSON construction expressions in the handler. Values such as `rows`, `result`, and delegated types are runtime values, not literal example payloads.

```rust
serde_json::json!(resp)
```

### Errors and validation [#errors-and-validation-6]

Directly referenced error variants: `InvalidRequest`. Middleware and delegated services can return additional errors described in the shared error reference.

<Accordions>
  <Accordion title="Inspect implementation">
    This exact source excerpt includes validation, defaults, delegated calls, and response assembly.

    ```rust
    async fn forgetting_stats(
        State(state): State<AppState>,
        Extension(db): Extension<Arc<akasha::AkashaDB>>,
    ) -> Result<impl IntoResponse, DaemonError> {
        state.record_http_request();
        ensure_forgetting_keyspace(&db).await?;

        let results = db
            .query(FORGETTING_KEYSPACE)
            .limit(10_000)
            .execute()
            .await
            .map_err(|e| DaemonError::InvalidRequest(e.to_string()))?;

        let mut pending: usize = 0;
        let mut approved: usize = 0;
        let mut rejected: usize = 0;
        let total = results.len();

        for row in &results {
            let status = row
                .data
                .get("status")
                .and_then(|v| v.as_str())
                .unwrap_or("unknown");
            match status {
                "pending" => pending += 1,
                "approved" => approved += 1,
                "rejected" => rejected += 1,
                _ => {}
            }
        }

        let resp = ForgettingStatsResponse {
            total,
            pending,
            approved,
            rejected,
        };

        Ok(Json(serde_json::json!(resp)))
    }
    ```
  </Accordion>
</Accordions>

Source: `akasha-daemon/src/forgetting.rs:433`. Registration: `akasha-daemon/src/forgetting.rs:496`.
