{
  "$schema": "https://docs.nukez.xyz/schemas/tools.json",
  "schema_version": "1.1",
  "service": {
    "name": "Nukez",
    "base_url": "https://api.nukez.xyz",
    "discovery": "/.well-known/nukez.json",
    "openapi": "/openapi.json",
    "description": "Pay-once persistent storage with verifiable receipts + provider-opaque short URL byte transfer."
  },
  "usage_guidance": {
    "when_to_use": "Use Nukez for persistent storage over HTTP with cryptographic receipts. No cloud credentials needed — just pay with Solana or EVM (x402) and start storing.",
    "best_for": "Agent-driven file storage, cross-session persistence, verifiable data provenance, multi-chain payment workflows, and any scenario where you want receipts without managing infrastructure.",
    "agent_note": "This is HTTP-first: no SDK required. You can operate entirely via HTTP requests + Solana or EVM signing.",
    "critical_guardrails": [
      "If a valid receipt_id already exists in context, reuse it. Do not repurchase storage unless user explicitly requests a new purchase.",
      "In sandbox/proxied runtimes, prefer upload sessions and upload token flow instead of direct local-path uploads.",
      "When upload errors include details.recovery_hint and details.next_best_method, follow those fields directly."
    ]
  },
  "auth_reference": {
    "public": {
      "description": "No auth headers required.",
      "note": "Public endpoints require no auth headers.",
      "tools": [
        "nukez_request_storage",
        "nukez_confirm_storage",
        "nukez_get_receipt",
        "nukez_verify_receipt",
        "nukez_verify_storage",
        "nukez_get_merkle_proof",
        "nukez_get_attest_code",
        "nukez_get_verification_bundle"
      ]
    },
    "signed_envelope": {
      "description": "Request-bound Ed25519 signature. Use build_signed_envelope tool, then include returned headers.",
      "do_not_mix_with": "No other auth methods needed.",
      "when_to_use": [
        "nukez_signed_provision",
        "nukez_create_file",
        "nukez_create_files_batch",
        "nukez_list_files",
        "nukez_get_file",
        "nukez_delete_file",
        "nukez_add_operator",
        "nukez_remove_operator",
        "nukez_get_manifest",
        "nukez_fetch_and_store",
        "nukez_confirm_upload"
      ],
      "how_to_use": {
        "if_your_runtime_provides_a_signing_helper": [
          "1. Call your signing helper with (receipt_id, method, path, ops, body)",
          "2. It returns headers (containing X-Nukez-Envelope and X-Nukez-Signature) and a canonical body string",
          "3. Your next HTTP request MUST include those headers - pass them to your HTTP tool's 'headers' parameter",
          "4. Use the canonical body string as the raw request body (do not re-serialize)"
        ],
        "if_constructing_manually": [
          "1. Compute locker_id = 'locker_' + sha256(receipt_id)[:12]",
          "2. Serialize body to canonical JSON (sorted keys, no whitespace)",
          "3. Compute body_sha256 = sha256(canonical_body).hex()",
          "4. Build envelope object with v, locker_id, receipt_id, nonce, iat, exp, ops, method, path, body_sha256",
          "5. Serialize envelope to canonical JSON bytes",
          "6. X-Nukez-Envelope = base64url_encode(envelope_bytes).rstrip('=')",
          "7. X-Nukez-Signature = base58_encode(ed25519_sign(envelope_bytes))",
          "8. Send HTTP request with X-Nukez-Envelope and X-Nukez-Signature as headers, AND the canonical body string from step 2 as the body"
        ]
      },
      "critical_header_requirement": {
        "warning": "HTTP 422 means the server did not receive X-Nukez-Envelope and X-Nukez-Signature headers.",
        "common_mistake": "Constructing the envelope correctly but then making an HTTP request WITHOUT attaching the headers.",
        "fix": "However you construct the signed envelope (helper tool or manually), the resulting X-Nukez-Envelope and X-Nukez-Signature values MUST be included as HTTP headers in the actual request. If your HTTP tool has a 'headers' parameter, use it."
      },
      "headers": {
        "X-Nukez-Envelope": "base64url(canonical_json(envelope))",
        "X-Nukez-Signature": "base58(ed25519_sign(envelope_bytes))"
      },
      "envelope_fields": [
        "v",
        "locker_id",
        "receipt_id",
        "nonce",
        "iat",
        "exp",
        "ops",
        "method",
        "path",
        "body_sha256"
      ],
      "critical_note": "The body_sha256 in the envelope MUST match the SHA256 of the EXACT bytes sent. Serialize once, hash that, send that.",
      "see": "/docs/AUTH_SIGNED_ENVELOPE.md"
    },
    "signed_urls": {
      "description": "upload_url/download_url are provider-opaque short URLs (https://api.nukez.xyz/f/{token}) used for PUT/GET bytes.",
      "note": "If a short URL fails with 403/404, call GET /v1/lockers/{locker_id}/files/{filename} to refresh URLs. Verify token signatures with GET /v1/short-url/verify-key.",
      "verify_key": "/v1/short-url/verify-key",
      "format": "https://api.nukez.xyz/f/{ed25519_signed_token}"
    },
    "verification_spec": {
      "name": "nukez-merkle-v1",
      "schema_version": "1.0",
      "status": "normative",
      "canonical_doc": "https://docs.nukez.xyz/docs/verify/merkle-v1.md",
      "machine_readable": "https://docs.nukez.xyz/specs/nukez-merkle-v1.json",
      "summary": "Canonical Merkle / attestation spec for third-party verification. Covers leaf hashing, sort order, parent formula, odd-level duplication, result_hash, att_code, inclusion proof verification, Solana/Switchboard + Monad anchors, and a conformance test vector.",
      "important": "att_code is derived from result_hash, not merkle_root, and is NOT a security primitive. The authoritative values are result_hash, merkle_root, file entries, and on-chain anchors."
    }
  },
  "tools": [
    {
      "name": "nukez_request_storage",
      "description": "Start the x402 payment flow. IMPORTANT: this endpoint may return HTTP 402 with a JSON body that contains payment instructions. Treat HTTP 402 here as an expected 'payment challenge', not a failure. Provider can be selected via body.provider when enabled.",
      "when_to_call": "When you need to purchase/provision new storage units.",
      "input_schema": {
        "type": "object",
        "properties": {
          "units": {
            "type": "integer",
            "minimum": 1,
            "default": 1,
            "description": "Number of storage units to purchase."
          },
          "idempotency_key": {
            "type": "string",
            "description": "Optional idempotency key for safe retries (Idempotency-Key header)."
          },
          "existing_receipt_id": {
            "type": "string",
            "description": "Sandbox guardrail input. If provided with execution_mode='sandbox', the API blocks repurchase unless explicit_purchase=true."
          },
          "execution_mode": {
            "type": "string",
            "description": "Optional runtime hint. Use 'sandbox' for constrained app runtimes."
          },
          "explicit_purchase": {
            "type": "boolean",
            "description": "Set true only when the user explicitly requests buying new storage."
          },
          "provider": {
            "type": "string",
            "enum": [
              "gcs",
              "mongodb",
              "storj",
              "arweave",
              "filecoin",
              "firestore"
            ],
            "description": "Optional storage provider selection. If omitted, server default is used."
          },
          "pay_network": {
            "type": "string",
            "enum": [
              "solana-mainnet",
              "monad-mainnet"
            ],
            "description": "Optional. Network to pay on. If omitted, server default is used. solana-mainnet (CAIP-2 solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp) and monad-mainnet (CAIP-2 eip155:143) are the production networks."
          },
          "pay_asset": {
            "type": "string",
            "enum": [
              "SOL",
              "USDC",
              "USDT",
              "USDT0",
              "WETH",
              "BETA",
              "MON"
            ],
            "default": "SOL",
            "description": "Optional. Payment asset. Default: SOL. Solana-mainnet accepts SOL, USDC, USDT, WETH, BETA. Monad-mainnet accepts MON, USDC, USDT0, WETH. BETA is a flat 1-token-per-unit Nukez asset (decimals 0), not USD-priced. The accepts[] entries in the 402 response enumerate exactly what each network offers."
          }
        },
        "required": [
          "units"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "pay_req_id": {
            "type": "string"
          },
          "pay_to_address": {
            "type": "string"
          },
          "amount_sol": {
            "type": "number",
            "description": "Deprecated alias for amount when pay_asset=SOL. Prefer paid_amount."
          },
          "paid_amount": {
            "type": "string",
            "description": "Chain-agnostic human-readable payment amount."
          },
          "paid_raw": {
            "type": "string",
            "description": "Atomic units (lamports, wei, etc.)."
          },
          "pay_asset": {
            "type": "string",
            "description": "Payment asset used (SOL, USDC, USDT, USDT0, WETH, BETA, MON)."
          },
          "network": {
            "type": "string",
            "description": "Payment network (solana-mainnet, monad-mainnet)."
          },
          "amount_lamports": {
            "type": "integer"
          },
          "unit_price_usd": {
            "type": "number"
          },
          "total_usd": {
            "type": "number"
          },
          "sol_usd": {
            "type": "number"
          },
          "value": {}
        },
        "required": [
          "paid_amount",
          "network",
          "pay_req_id",
          "pay_to_address",
          "pay_asset",
          "value"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/storage/request",
        "content_type": "application/json",
        "headers": {
          "Idempotency-Key": "{idempotency_key} (optional)"
        },
        "query_parameters": {
          "pay_network": "Optional. Filter pricing by network.",
          "pay_asset": "Optional. Filter pricing by asset."
        },
        "expected_status": [
          402,
          200
        ]
      },
      "auth": "public",
      "next_step": "Pay to pay_to_address for paid_amount using the specified pay_asset on the specified network, then call nukez_confirm_storage."
    },
    {
      "name": "nukez_confirm_storage",
      "description": "Confirm payment and receive a permanent receipt_id. Preferred proof: send transaction signature/hash in the X402-TX header. X402-TX accepts both Solana signatures (base58, ~88 chars) and EVM transaction hashes (0x + 64 hex chars). Fallback for constrained clients: include tx_sig in the JSON body along with pay_req_id.",
      "when_to_call": "After sending payment to pay_to_address returned by nukez_request_storage.",
      "input_schema": {
        "type": "object",
        "properties": {
          "pay_req_id": {
            "type": "string"
          },
          "tx_sig": {
            "type": "string",
            "description": "Transaction signature (Solana base58, ~88 chars) or EVM transaction hash (0x + 64 hex chars)."
          }
        },
        "required": [
          "pay_req_id",
          "tx_sig"
        ],
        "additionalProperties": true
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "receipt_id": {
            "type": "string"
          },
          "receipt": {
            "type": "object",
            "properties": {
              "paid_amount": {
                "type": "string",
                "description": "Chain-agnostic human-readable amount paid."
              },
              "paid_raw": {
                "type": "string",
                "description": "Atomic units (lamports, wei, etc.)."
              },
              "pay_asset": {
                "type": "string",
                "description": "Payment asset (SOL, USDC, USDT, USDT0, WETH, BETA, MON)."
              },
              "network": {
                "type": "string",
                "description": "Payment network."
              },
              "slot": {
                "type": "integer",
                "description": "Solana only, null for EVM."
              },
              "block_number": {
                "type": "integer",
                "description": "EVM only, null for Solana."
              }
            }
          },
          "idempotent": {
            "type": "boolean"
          },
          "value": {}
        },
        "required": [
          "ok",
          "receipt_id",
          "value"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/storage/confirm",
        "content_type": "application/json",
        "headers": {
          "X402-TX": "{tx_sig} (preferred; Solana base58 signature or EVM 0x-prefixed tx hash; optional if tx_sig is provided in JSON body)"
        },
        "expected_status": [
          200,
          402
        ]
      },
      "auth": "public",
      "error_handling": {
        "tx_not_found": "Transaction not yet propagated; retry with exponential backoff.",
        "payment_verification_failed": "Confirm tx paid enough; retry only if you suspect RPC lag."
      },
      "next_step": "Call nukez_signed_provision with receipt_id to create a locker."
    },
    {
      "name": "nukez_signed_provision",
      "description": "Provision a locker from a confirmed receipt. Returns locker_id and a manifest describing the file API surface. Requires signed envelope with ops ['locker:provision']. Optional operator_pubkey registers an Ed25519 delegate key at provision time.",
      "when_to_call": "Once per receipt_id (safe to retry).",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string"
          },
          "tags": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Optional tags"
          },
          "operator_pubkey": {
            "type": "string",
            "description": "Optional Ed25519 public key (base58) to register as an operator at provision time. The operator can then sign file operations on behalf of the locker owner."
          },
          "value": {
            "$ref": "#/components/schemas/ProvisionRequest"
          },
          "signed_envelope": {
            "type": "string",
            "description": "Input used to populate an HTTP header."
          },
          "signed_envelope_signature": {
            "type": "string",
            "description": "Input used to populate an HTTP header."
          }
        },
        "required": [
          "receipt_id",
          "value"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "space": {
            "type": "object",
            "description": "Locker manifest (runtime affordances)",
            "additionalProperties": true
          },
          "value": {}
        },
        "required": [
          "ok",
          "space",
          "value"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/storage/signed_provision",
        "content_type": "application/json",
        "headers": {
          "X-Nukez-Envelope": "{signed_envelope}",
          "X-Nukez-Signature": "{signed_envelope_signature}"
        },
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:provision"
      ],
      "next_step": "Use space.file_api paths (or the standard /v1/lockers/{locker_id}/files endpoints) to create/list/get/delete files."
    },
    {
      "name": "nukez_create_file",
      "description": "Create (or update) a file entry and mint time-limited short URLs for upload/download. AUTH: signed_envelope with ops=['locker:write']. Upload bytes via HTTP PUT to upload_url.",
      "when_to_call": "When you need to upload new bytes or update an existing file.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "filename": {
            "type": "string",
            "description": "Optional. If omitted, server generates a filename."
          },
          "content_type": {
            "type": "string",
            "description": "Optional MIME type. If provided, you MUST use the same Content-Type in the PUT to upload_url."
          },
          "ttl_min": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "default": 30,
            "description": "Signed URL TTL in minutes."
          },
          "value": {
            "$ref": "#/components/schemas/CreateFileRequest"
          }
        },
        "required": [
          "locker_id",
          "value"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "upload_url": {
            "type": "string"
          },
          "download_url": {
            "type": "string"
          },
          "upload_headers": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "urls_expire_in_sec": {
            "type": "integer"
          },
          "value": {}
        },
        "required": [
          "download_url",
          "filename",
          "locker_id",
          "upload_url",
          "value"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/lockers/{locker_id}/files",
        "content_type": "application/json",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:write"
      ],
      "next_step": "PUT raw bytes to upload_url, including any upload_headers, and matching Content-Type if content_type was locked."
    },
    {
      "name": "nukez_create_files_batch",
      "description": "Create multiple file entries and mint short upload/download URLs in one call. AUTH: signed_envelope with ops=['locker:write'].",
      "when_to_call": "When uploading multiple files (mixed MIME types) and you want one signed request to return all URLs.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "ttl_min": {
            "type": "integer",
            "minimum": 1,
            "maximum": 1440,
            "default": 30
          },
          "files": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "properties": {
                "filename": {
                  "type": "string",
                  "description": "Optional; server can auto-generate if omitted"
                },
                "content_type": {
                  "type": "string"
                },
                "expected_hash": {
                  "type": "string",
                  "description": "Optional sha256 precommit hash"
                }
              }
            }
          },
          "value": {
            "$ref": "#/components/schemas/BatchCreateFileRequest"
          }
        },
        "required": [
          "files",
          "locker_id",
          "value"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "file_count": {
            "type": "integer"
          },
          "urls_expire_in_sec": {
            "type": "integer"
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "filename": {
                  "type": "string"
                },
                "upload_url": {
                  "type": "string"
                },
                "download_url": {
                  "type": "string"
                },
                "content_type": {
                  "type": "string"
                }
              },
              "required": [
                "filename",
                "upload_url",
                "download_url"
              ]
            }
          },
          "value": {}
        },
        "required": [
          "files",
          "locker_id",
          "value"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/lockers/{locker_id}/files/batch",
        "content_type": "application/json",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:write"
      ],
      "next_step": "Upload bytes to each returned upload_url (in parallel if desired), then confirm hashes via /v1/files/confirm-batch."
    },
    {
      "name": "nukez_get_file_urls",
      "description": "Mint fresh short URLs for an existing file (download and optionally upload).",
      "when_to_call": "When a previously minted short URL expired, or before downloading/updating an existing file.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "ttl_min": {
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "default": 30
          }
        },
        "required": [
          "filename",
          "locker_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "upload_url": {
            "type": "string"
          },
          "download_url": {
            "type": "string"
          },
          "urls_expire_in_sec": {
            "type": "integer"
          },
          "value": {}
        },
        "required": [
          "download_url",
          "filename",
          "locker_id",
          "value"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/lockers/{locker_id}/files/{filename}?ttl_min={ttl_min}",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:read"
      ]
    },
    {
      "name": "nukez_list_files",
      "description": "List file metadata in a locker (filenames, content_type, timestamps).",
      "when_to_call": "When you need to discover what files exist in a locker.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          }
        },
        "required": [
          "locker_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "file_count": {
            "type": "integer"
          },
          "files": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "value": {}
        },
        "required": [
          "files",
          "locker_id",
          "value"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/lockers/{locker_id}/files",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:list"
      ]
    },
    {
      "name": "nukez_delete_file",
      "description": "Delete a file from a locker.",
      "when_to_call": "When you need to remove a stored object.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          }
        },
        "required": [
          "filename",
          "locker_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": {
            "type": "boolean"
          },
          "locker_id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          },
          "value": {}
        },
        "required": [
          "value"
        ]
      },
      "http": {
        "method": "DELETE",
        "path": "/v1/lockers/{locker_id}/files/{filename}",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:write"
      ]
    },
    {
      "name": "nukez_get_receipt",
      "description": "Fetch a receipt by receipt_id.",
      "when_to_call": "When you need to audit or prove payment.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string"
          }
        },
        "required": [
          "receipt_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "paid_amount": {
            "type": "string",
            "description": "Chain-agnostic human-readable amount paid."
          },
          "paid_raw": {
            "type": "string",
            "description": "Atomic units (lamports, wei, etc.)."
          },
          "pay_asset": {
            "type": "string",
            "description": "Payment asset (SOL, USDC, USDT, USDT0, WETH, BETA, MON)."
          },
          "network": {
            "type": "string",
            "description": "Payment network."
          },
          "slot": {
            "type": "integer",
            "description": "Solana only, null for EVM."
          },
          "block_number": {
            "type": "integer",
            "description": "EVM only, null for Solana."
          },
          "value": {}
        },
        "required": [
          "value"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/receipts/{receipt_id}",
        "expected_status": [
          200
        ]
      },
      "auth": "public"
    },
    {
      "name": "nukez_verify_receipt",
      "description": "Verify a receipt signature / integrity.",
      "when_to_call": "When you need strong confidence the receipt is authentic.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string"
          }
        },
        "required": [
          "receipt_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "value": {}
        },
        "required": [
          "value"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/receipts/{receipt_id}/verify",
        "expected_status": [
          200
        ]
      },
      "auth": "public"
    },
    {
      "name": "nukez_verify_storage",
      "description": "Recompute stored object's sha256 and return a signed integrity certificate for the default payload.bin (legacy storage object).",
      "when_to_call": "When you need verifiable integrity for legacy payload.bin workflows.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string"
          },
          "value": {
            "title": "Payload"
          }
        },
        "required": [
          "receipt_id",
          "value"
        ]
      },
      "output_schema": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "received_amount": {
            "type": "string",
            "description": "Chain-agnostic human-readable amount received."
          },
          "received_raw": {
            "type": "string",
            "description": "Atomic units received (lamports, wei, etc.)."
          },
          "pay_asset": {
            "type": "string",
            "description": "Payment asset verified (SOL, USDC, USDT, USDT0, WETH, BETA, MON)."
          },
          "value": {}
        },
        "required": [
          "value"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/storage/verify",
        "content_type": "application/json",
        "expected_status": [
          200
        ]
      },
      "auth": "public"
    },
    {
      "name": "nukez_get_merkle_proof",
      "description": "Get a merkle inclusion proof for a specific file. Proves the file is part of the attested merkle tree without needing all other files. Walk the proof to independently verify: start with leaf_hash, for each step if position=='right' hash=SHA256(current+step.hash) else hash=SHA256(step.hash+current). Final hash must equal merkle_root.",
      "when_to_call": "When you need to verify a single file's membership in the attested merkle tree.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string",
            "description": "Receipt ID for the locker"
          },
          "filename": {
            "type": "string",
            "description": "Name of the file to prove inclusion for"
          }
        },
        "required": ["receipt_id", "filename"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "receipt_id": { "type": "string" },
          "filename": { "type": "string" },
          "leaf_hash": { "type": "string", "description": "SHA256 hash of the leaf node" },
          "leaf_index": { "type": "integer", "description": "Position in sorted file list" },
          "merkle_root": { "type": "string", "description": "Attested merkle root (sha256:...)" },
          "proof": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "hash": { "type": "string" },
                "position": { "type": "string", "enum": ["left", "right"] }
              }
            },
            "description": "Sibling hash steps from leaf to root"
          },
          "tree_depth": { "type": "integer" },
          "file_count": { "type": "integer" },
          "file_entry": {
            "type": "object",
            "properties": {
              "filename": { "type": "string" },
              "size_bytes": { "type": "integer" },
              "content_hash": { "type": "string" }
            }
          },
          "schema_version": { "type": "string" },
          "switchboard": {
            "type": "object",
            "properties": {
              "slot": { "type": "integer" },
              "tx": { "type": "string" }
            }
          }
        },
        "required": ["receipt_id", "filename", "leaf_hash", "merkle_root", "proof"]
      },
      "http": {
        "method": "GET",
        "path": "/v1/storage/merkle-proof?receipt_id={receipt_id}&filename={filename}",
        "expected_status": [200]
      },
      "auth": "public",
      "next_step": "Walk the proof path to verify: start with leaf_hash, apply each sibling step, confirm final hash equals merkle_root."
    },
    {
      "name": "nukez_get_attest_code",
      "description": "Get an attestation code derived from the stored result_hash. If missing, run nukez_verify_storage first.",
      "when_to_call": "After verify_storage, or if the receipt already has a result_hash.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string"
          }
        },
        "required": [
          "receipt_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string"
          },
          "result_hash": {
            "type": "string"
          },
          "att_code": {
            "type": "string"
          },
          "value": {}
        },
        "required": [
          "value"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/attest-code?receipt_id={receipt_id}",
        "expected_status": [
          200,
          400
        ]
      },
      "auth": "public"
    },
    {
      "name": "nukez_start_upload_session",
      "description": "Start a sandbox upload session and mint a session-scoped upload token. Use this for app-sandbox uploads where direct file paths are restricted.",
      "when_to_call": "When uploading attachments from sandboxed runtimes and you already have locker_id + receipt_id.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "receipt_id": {
            "type": "string"
          },
          "files": {
            "type": "array",
            "minItems": 1,
            "maxItems": 100,
            "items": {
              "type": "object",
              "properties": {
                "filename": {
                  "type": "string"
                },
                "content_type": {
                  "type": "string"
                },
                "expected_size_bytes": {
                  "type": "integer"
                },
                "expected_sha256": {
                  "type": "string"
                }
              },
              "required": [
                "filename"
              ]
            }
          },
          "upload_token_ttl_sec": {
            "type": "integer",
            "minimum": 60,
            "maximum": 86400
          }
        },
        "required": [
          "locker_id",
          "receipt_id",
          "files"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "upload_token": {
            "type": "string"
          },
          "endpoints": {
            "type": "object"
          },
          "viewer_url": {
            "type": "string"
          },
          "ui": {
            "type": "object"
          },
          "contract": {
            "type": "object"
          }
        },
        "required": [
          "session_id",
          "upload_token",
          "viewer_url",
          "ui",
          "contract"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/lockers/{locker_id}/upload-sessions",
        "content_type": "application/json",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:write"
      ],
      "next_step": "Upload bytes using nukez_append_upload_session_part, then call nukez_finalize_upload_session."
    },
    {
      "name": "nukez_append_upload_session_part",
      "description": "Append one base64 chunk to a file inside an upload session.",
      "when_to_call": "After nukez_start_upload_session for each file chunk.",
      "input_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "file_id": {
            "type": "string"
          },
          "part_no": {
            "type": "integer",
            "minimum": 0
          },
          "payload_b64": {
            "type": "string"
          },
          "is_last": {
            "type": "boolean",
            "default": false
          }
        },
        "required": [
          "session_id",
          "file_id",
          "part_no",
          "payload_b64"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "file_id": {
            "type": "string"
          },
          "bytes_received": {
            "type": "integer"
          },
          "part_count": {
            "type": "integer"
          }
        },
        "required": [
          "session_id",
          "file_id"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/upload-sessions/{session_id}/files/{file_id}/parts",
        "content_type": "application/json",
        "expected_status": [
          200
        ]
      },
      "auth": "upload_session_token_or_signed_envelope"
    },
    {
      "name": "nukez_get_upload_session",
      "description": "Get upload session status and per-file state. Returns viewer_url + UI contract.",
      "when_to_call": "To poll upload progress until terminal status.",
      "input_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "terminal": {
            "type": "boolean"
          },
          "viewer_url": {
            "type": "string"
          },
          "ui": {
            "type": "object"
          },
          "contract": {
            "type": "object"
          }
        },
        "required": [
          "session_id",
          "status",
          "terminal",
          "viewer_url",
          "ui",
          "contract"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/upload-sessions/{session_id}",
        "expected_status": [
          200
        ]
      },
      "auth": "upload_session_token_or_signed_envelope"
    },
    {
      "name": "nukez_finalize_upload_session",
      "description": "Finalize an upload session (assemble parts, verify upload integrity, and emit viewer contract).",
      "when_to_call": "After all chunks have been appended for all files.",
      "input_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "file_ids": {
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "session_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "session_id": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "terminal": {
            "type": "boolean"
          },
          "result": {
            "type": "object"
          },
          "viewer_url": {
            "type": "string"
          },
          "ui": {
            "type": "object"
          },
          "contract": {
            "type": "object"
          }
        },
        "required": [
          "session_id",
          "status",
          "terminal",
          "viewer_url",
          "ui",
          "contract"
        ]
      },
      "http": {
        "method": "POST",
        "path": "/v1/upload-sessions/{session_id}/finalize",
        "content_type": "application/json",
        "expected_status": [
          200
        ]
      },
      "auth": "upload_session_token_or_signed_envelope"
    },
    {
      "name": "nukez_get_viewer",
      "description": "Return a viewer-first payload for locker or file display. Always returns viewer_url + button contract.",
      "when_to_call": "When the user asks to view locker contents or a specific file.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "receipt_id": {
            "type": "string"
          },
          "filename": {
            "type": "string"
          }
        },
        "required": [
          "locker_id"
        ]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "viewer_url": {
            "type": "string"
          },
          "ui": {
            "type": "object"
          },
          "contract": {
            "type": "object"
          }
        },
        "required": [
          "viewer_url",
          "ui",
          "contract"
        ]
      },
      "http": {
        "method": "GET",
        "path": "/v1/lockers/{locker_id}/viewer",
        "expected_status": [
          200
        ]
      },
      "auth": "signed_envelope",
      "required_ops": [
        "locker:read"
      ]
    },
    {
      "name": "nukez_get_short_url_verify_key",
      "description": "Get the Ed25519 public key used to verify short URL tokens.",
      "when_to_call": "When independently validating that a short URL token was issued by Nukez.",
      "input_schema": {
        "type": "object",
        "properties": {}
      },
      "http": {
        "method": "GET",
        "path": "/v1/short-url/verify-key",
        "expected_status": [
          200
        ]
      },
      "auth": "public",
      "output_hints": [
        "verify_key_hex",
        "algorithm"
      ]
    },
    {
      "name": "nukez_confirm_upload",
      "description": "Confirm a file upload (compute SHA-256 and update manifest). Call after uploading bytes to upload_url. Some providers auto-confirm on upload; this is needed when uploading via sandbox/chunked paths or when you want explicit hash confirmation.",
      "when_to_call": "After uploading bytes to upload_url, especially for sandbox uploads or when explicit hash verification is needed.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string",
            "description": "Receipt ID for the locker"
          },
          "filename": {
            "type": "string",
            "description": "Filename to confirm (as used in create_file)"
          }
        },
        "required": ["receipt_id", "filename"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "filename": { "type": "string" },
          "size_bytes": { "type": "integer" },
          "content_hash": { "type": "string", "description": "SHA-256 hash of the uploaded content (sha256:... prefixed)" }
        },
        "required": ["ok", "filename"]
      },
      "http": {
        "method": "POST",
        "path": "/v1/files/confirm",
        "content_type": "application/json",
        "expected_status": [200]
      },
      "auth": "signed_envelope",
      "required_ops": ["locker:write"]
    },
    {
      "name": "nukez_add_operator",
      "description": "Add an Ed25519 operator key to a locker. Operators can perform file operations (read, write, list) on behalf of the locker owner. Only the locker owner can add operators. Useful for cross-chain delegation (e.g., EVM owner delegates to an Ed25519 operator for file operations).",
      "when_to_call": "When you need to delegate file access to another Ed25519 key.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "pubkey": {
            "type": "string",
            "description": "Ed25519 public key (base58) to add as an operator"
          }
        },
        "required": ["locker_id", "pubkey"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "locker_id": { "type": "string" },
          "operator_ids": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Updated list of all operator public keys"
          }
        },
        "required": ["ok", "operator_ids"]
      },
      "http": {
        "method": "POST",
        "path": "/v1/lockers/{locker_id}/operators",
        "content_type": "application/json",
        "expected_status": [200]
      },
      "auth": "signed_envelope",
      "required_ops": ["locker:admin"],
      "note": "Only the locker owner (payer key) can add operators. Operators themselves cannot add other operators."
    },
    {
      "name": "nukez_remove_operator",
      "description": "Remove an operator key from a locker. Only the locker owner can remove operators.",
      "when_to_call": "When you need to revoke an operator's access to a locker.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "pubkey": {
            "type": "string",
            "description": "Ed25519 public key (base58) of the operator to remove"
          }
        },
        "required": ["locker_id", "pubkey"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "locker_id": { "type": "string" },
          "operator_ids": {
            "type": "array",
            "items": { "type": "string" },
            "description": "Updated list of remaining operator public keys"
          }
        },
        "required": ["ok"]
      },
      "http": {
        "method": "DELETE",
        "path": "/v1/lockers/{locker_id}/operators/{pubkey}",
        "expected_status": [200]
      },
      "auth": "signed_envelope",
      "required_ops": ["locker:admin"]
    },
    {
      "name": "nukez_get_verification_bundle",
      "description": "Get a self-contained verification bundle with payment proof, content proof, verification algorithm spec, and DIY verification steps. No authentication required.",
      "when_to_call": "When you need a portable, self-contained proof package for auditing or sharing.",
      "input_schema": {
        "type": "object",
        "properties": {
          "receipt_id": {
            "type": "string",
            "description": "Receipt ID to generate verification bundle for"
          }
        },
        "required": ["receipt_id"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "receipt_id": { "type": "string" },
          "payment_proof": { "type": "object", "description": "On-chain payment evidence" },
          "content_proof": { "type": "object", "description": "Merkle root + file hashes" },
          "verification_algorithm": { "type": "object", "description": "Algorithm spec for independent verification" },
          "diy_steps": { "type": "array", "items": { "type": "string" }, "description": "Human-readable verification steps" }
        },
        "required": ["receipt_id"]
      },
      "http": {
        "method": "GET",
        "path": "/v1/storage/verification-bundle?receipt_id={receipt_id}",
        "expected_status": [200]
      },
      "auth": "public"
    },
    {
      "name": "nukez_get_manifest",
      "description": "Get the full locker manifest including all file metadata (filenames, sizes, content hashes, timestamps).",
      "when_to_call": "When you need a complete snapshot of all files and their metadata in a locker.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          }
        },
        "required": ["locker_id"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "locker_id": { "type": "string" },
          "files": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "filename": { "type": "string" },
                "content_type": { "type": "string" },
                "size_bytes": { "type": "integer" },
                "content_hash": { "type": "string" }
              }
            }
          }
        },
        "required": ["locker_id"]
      },
      "http": {
        "method": "GET",
        "path": "/v1/lockers/{locker_id}/manifest",
        "expected_status": [200]
      },
      "auth": "signed_envelope",
      "required_ops": ["locker:read"]
    },
    {
      "name": "nukez_fetch_and_store",
      "description": "Fetch a file from an external HTTPS URL and store it directly in the locker. The server downloads the content server-side, avoiding the need to transfer bytes through the agent. SSRF-protected: only HTTPS URLs to public hosts are allowed.",
      "when_to_call": "When you have a public HTTPS URL and want to store its contents without downloading first.",
      "input_schema": {
        "type": "object",
        "properties": {
          "locker_id": {
            "type": "string"
          },
          "receipt_id": {
            "type": "string"
          },
          "source_url": {
            "type": "string",
            "description": "HTTPS URL to fetch content from"
          },
          "filename": {
            "type": "string",
            "description": "Optional filename for the stored file"
          },
          "content_type": {
            "type": "string",
            "description": "Optional MIME type override"
          }
        },
        "required": ["locker_id", "receipt_id", "source_url"]
      },
      "output_schema": {
        "type": "object",
        "properties": {
          "ok": { "type": "boolean" },
          "filename": { "type": "string" },
          "size_bytes": { "type": "integer" },
          "content_hash": { "type": "string" },
          "download_url": { "type": "string" }
        },
        "required": ["ok", "filename"]
      },
      "http": {
        "method": "POST",
        "path": "/v1/files/fetch-and-store",
        "content_type": "application/json",
        "expected_status": [200]
      },
      "auth": "signed_envelope",
      "required_ops": ["locker:write"]
    }
  ],
  "flows": {
    "store_and_retrieve": {
      "name": "Store Data Flow",
      "description": "Complete flow to store data and retrieve it",
      "steps": [
        {
          "step": 1,
          "action": "nukez_request_storage",
          "input": {
            "units": 1
          },
          "expect": "HTTP 402 with pay_req_id, pay_to_address, paid_amount, pay_asset, network",
          "note": "402 is expected - it contains payment instructions"
        },
        {
          "step": 2,
          "action": "transfer_payment",
          "input": {
            "to_address": "{pay_to_address}",
            "amount": "{paid_amount}",
            "asset": "{pay_asset}",
            "network": "{network}"
          },
          "expect": "Transaction signature or hash (tx_sig)",
          "note": "Use your wallet (Solana or EVM) to send the exact amount in the specified asset on the specified network"
        },
        {
          "step": 3,
          "action": "nukez_confirm_storage",
          "input": {
            "pay_req_id": "{pay_req_id}",
            "tx_sig": "{tx_sig}"
          },
          "expect": "receipt_id",
          "note": "If tx_not_found, retry with backoff - transaction may still be propagating"
        },
        {
          "step": 4,
          "action": "nukez_signed_provision",
          "input": {
            "receipt_id": "{receipt_id}"
          },
          "auth": "REQUIRES signed_envelope with ops=['locker:provision']",
          "expect": "locker_id, space manifest",
          "note": "Use build_signed_envelope tool if available, or construct headers manually per AUTH_SIGNED_ENVELOPE.md"
        },
        {
          "step": 5,
          "action": "nukez_create_file",
          "input": {
            "locker_id": "{locker_id}",
            "filename": "mydata.txt"
          },
          "auth": "REQUIRES signed_envelope with ops=['locker:write']",
          "expect": "upload_url, download_url",
          "note": "URLs are time-limited short URLs"
        },
        {
          "step": 6,
          "action": "HTTP PUT to upload_url",
          "input": "Your data bytes",
          "expect": "HTTP 200",
          "note": "PUT directly to the short URL - no auth headers needed"
        },
        {
          "step": 7,
          "action": "HTTP GET from download_url",
          "expect": "Your data bytes back",
          "note": "GET directly from the short URL - no auth headers needed"
        }
      ]
    }
  }
}