{
  "$schema": "https://docs.nukez.xyz/schemas/nukez.discovery.v1.schema.json",
  "type": "nukez.discovery.v1",
  "name": "Nukez",
  "version": "phase6-v2-2026-06-16",
  "service": {
    "provider": "Nukez",
    "canonical_base_url": "https://api.nukez.xyz",
    "environment": "production",
    "description": "Protocol-first, HTTP-native, pay-per-use storage for agents (x402 receipts + signed requests + provider-opaque short URLs). Multi-chain payments (Solana and EVM/Monad). Operator delegation for cross-chain access control.",
    "updated_utc": "2026-06-16"
  },
  "discovery": {
    "well_known": "/.well-known/nukez.json",
    "http_link_headers": [
      {
        "rel": "service-meta",
        "href": "/.well-known/nukez.json",
        "type": "application/json",
        "title": "Nukez discovery document"
      },
      {
        "rel": "service-doc",
        "href": "/docs/AUTH_SIGNED_ENVELOPE.md",
        "type": "text/markdown",
        "title": "Signed envelope authentication (CRITICAL for authenticated endpoints)"
      },
      {
        "rel": "service-desc",
        "href": "/openapi.json",
        "type": "application/vnd.oai.openapi+json",
        "title": "Nukez OpenAPI (canonical bundle)"
      },
      {
        "rel": "service-desc",
        "href": "/v1/tools.json",
        "type": "application/json",
        "title": "Nukez tool schema (LLM-friendly)"
      },
      {
        "rel": "service-doc",
        "href": "/docs/AGENT_BRIEFING.md",
        "type": "text/markdown",
        "title": "Agent briefing"
      },
      {
        "rel": "service-doc",
        "href": "/docs/AGENT_FLOW.md",
        "type": "text/markdown",
        "title": "Agent flow"
      },
      {
        "rel": "status",
        "href": "/health",
        "type": "application/json",
        "title": "Service status"
      },
      {
        "rel": "llms",
        "href": "/llms.txt",
        "type": "text/plain",
        "title": "LLM index (short)"
      }
    ]
  },
  "agent_start_here": {
    "summary": "For autonomous agents: Read tools.json first, then AGENT_FLOW.md. OpenAPI specs are supplementary.",
    "recommended_reading_order": [
      {
        "order": 1,
        "url": "/v1/tools.json",
        "why": "LLM-optimized tool definitions with full auth guidance and flow descriptions"
      },
      {
        "order": 2,
        "url": "/docs/AGENT_FLOW.md",
        "why": "Step-by-step walkthrough of the complete storage flow"
      },
      {
        "order": 3,
        "url": "/docs/AUTH_SIGNED_ENVELOPE.md",
        "why": "CRITICAL: Read before calling any authenticated endpoint"
      }
    ],
    "critical_auth_warning": {
      "issue": "HTTP 422 from signed_envelope endpoints (e.g., /v1/storage/signed_provision)",
      "cause": "Missing X-Nukez-Envelope and X-Nukez-Signature HTTP headers",
      "common_mistake": "Constructing the signed envelope correctly but then making an HTTP request WITHOUT attaching the headers",
      "fix": "However you construct the envelope, the X-Nukez-Envelope and X-Nukez-Signature values MUST be included as HTTP headers. If your HTTP tool has a 'headers' parameter, use it."
    },
    "do_not_read_first": [
      "/openapi.json - verbose, prefer tools.json",
      "/v1/openapi_file_management.yaml - redundant if you read tools.json"
    ]
  },
  "contracts": {
    "recommended": {
      "primary": {
        "url": "/v1/tools.json",
        "notes": "START HERE. LLM-optimized tool definitions with auth guidance, error handling, and flow descriptions."
      },
      "auth_docs": {
        "url": "/docs/AUTH_SIGNED_ENVELOPE.md",
        "notes": "MUST READ before calling signed_envelope endpoints. Explains header construction."
      }
    },
    "openapi": {
      "canonical": {
        "url": "/openapi.json",
        "media_type": "application/vnd.oai.openapi+json",
        "notes": "Full OpenAPI bundle. Verbose - prefer tools.json for LLM consumption."
      },
      "extra": [
        {
          "name": "file_management",
          "url": "/v1/openapi_file_management.yaml",
          "media_type": "application/yaml",
          "notes": "OpenAPI subset for file operations. Redundant if you have read tools.json."
        }
      ]
    },
    "verification_spec": {
      "name": "nukez-merkle-v1",
      "schema_version": "1.0",
      "status": "normative",
      "canonical_doc": "/docs/verify/merkle-v1.md",
      "machine_readable": "/specs/nukez-merkle-v1.json",
      "media_type": "application/json",
      "notes": "Canonical Merkle / attestation spec for third-party independent verification. Covers leaf hashing, sort order, parent formula, odd-level duplication, result_hash, att_code (display value only — NOT a security primitive), inclusion proof verification, Solana/Switchboard + Monad anchors, and a conformance test vector. att_code is derived from result_hash, not merkle_root."
    },
    "tools": {
      "preferred": {
        "url": "/v1/tools.json",
        "notes": "LLM-friendly tool definitions. Includes auth requirements and next-step guidance."
      },
      "full": {
        "url": "/v1/tool_contract.json",
        "notes": "Extended tool contract with detailed auth + error recovery guidance."
      }
    },
    "docs": {
      "agent_flow": "/docs/AGENT_FLOW.md",
      "agent_briefing": "/docs/AGENT_BRIEFING.md",
      "auth_signed_envelope": "/docs/AUTH_SIGNED_ENVELOPE.md",
      "error_recovery": "/docs/ERROR_RECOVERY.md",
      "changelog": "/docs/CHANGELOG.md",
      "merkle_v1": "/docs/verify/merkle-v1.md"
    },
    "llm_index": {
      "llms_txt": "/llms.txt",
      "optional": [
        "/llms-full.txt"
      ]
    }
  },
  "endpoints": {
    "health": "/health",
    "docs_swagger": "/docs",
    "docs_redoc": "/redoc",
    "price": "/v1/price",
    "storage_request": "/v1/storage/request",
    "storage_confirm": "/v1/storage/confirm",
    "receipt_get": "/v1/receipts/{receipt_id}",
    "receipt_verify": "/v1/receipts/{receipt_id}/verify",
    "storage_signed_provision": "/v1/storage/signed_provision",
    "locker_file_collection": "/v1/lockers/{locker_id}/files",
    "locker_file_item": "/v1/lockers/{locker_id}/files/{filename}",
    "locker_record": "/v1/lockers/{locker_id}/record",
    "locker_urls": "/v1/lockers/{locker_id}/urls",
    "storage_metadata": "/v1/storage/metadata/{locker_id}",
    "storage_refresh": "/v1/storage/refresh",
    "storage_verify": "/v1/storage/verify",
    "storage_merkle_proof": "/v1/storage/merkle-proof",
    "attest_code": "/v1/attest-code",
    "attest_code_jwt": "/v1/attest-code/jwt",
    "short_url_verify_key": "/v1/short-url/verify-key",
    "short_url_resolve": "/f/{token}",
    "files_confirm": "/v1/files/confirm",
    "files_confirm_batch": "/v1/files/confirm-batch",
    "files_fetch_and_store": "/v1/files/fetch-and-store",
    "locker_operators": "/v1/lockers/{locker_id}/operators",
    "locker_operator_item": "/v1/lockers/{locker_id}/operators/{pubkey}",
    "locker_manifest": "/v1/lockers/{locker_id}/manifest",
    "locker_files_batch": "/v1/lockers/{locker_id}/files/batch",
    "locker_files_urls": "/v1/lockers/{locker_id}/files/urls",
    "receipt_file_proxy": "/v1/r/{receipt_id}/f/{filename}",
    "receipt_verify_payment": "/v1/receipts/{receipt_id}/verify-payment",
    "storage_verification_bundle": "/v1/storage/verification-bundle"
  },
  "multi_chain": {
    "supported_networks": [
      {
        "name": "solana-mainnet",
        "pay_asset": [
          "SOL",
          "USDC",
          "USDT",
          "WETH",
          "BETA"
        ],
        "sig_alg": "ed25519",
        "slot_field": "slot"
      },
      {
        "name": "monad-mainnet",
        "pay_asset": [
          "MON",
          "USDC",
          "USDT0",
          "WETH"
        ],
        "sig_alg": "secp256k1",
        "slot_field": "block_number"
      }
    ],
    "request_fields": {
      "pay_network": "Optional network identifier (e.g., 'solana-mainnet', 'monad-mainnet')",
      "pay_asset": "Optional asset to pay with (e.g., 'SOL', 'MON', 'USDC', 'USDT', 'USDT0', 'WETH', 'BETA')"
    },
    "price_endpoint_behavior": "Returns amounts for multiple chains when no pay_network is specified",
    "receipt_fields": {
      "paid_amount": "Human-readable payment amount",
      "paid_raw": "Atomic units (lamports, wei, etc.)",
      "pay_asset": "Asset used for payment",
      "network": "Network where payment was made",
      "slot": "Solana slot (present for Solana payments)",
      "block_number": "EVM block number (present for EVM payments)"
    },
    "confirm_behavior": "X402-TX header carries the tx signature (Solana base58) or tx hash (EVM 0x-hex). Confirm body must include pay_asset (and pay_network for multi-chain) matching the leg actually paid; gateway falls back to the quote's default leg only if both are omitted, so any non-default leg requires explicit pay_asset/pay_network — otherwise confirm returns 400 with '<ASSET> on <NETWORK> not in quote'.",
    "confirm_body_fields": {
      "pay_asset": "Required when paying any non-default leg of accepts[]. Must match the asset actually transferred (e.g., 'USDC', 'BETA', 'WETH'). Aliases: 'payment_asset' is also accepted.",
      "pay_network": "Required for multi-chain quotes when paying a non-default leg. Must match the network actually transferred on (e.g., 'solana-mainnet', 'monad-mainnet'). Aliases: 'payment_chain' is also accepted.",
      "operator_pubkey": "Optional Ed25519 pubkey to bind as locker operator at confirm time."
    },
    "sig_alg_values": {
      "ed25519": "Solana keypair signatures",
      "secp256k1": "EVM wallet signatures"
    }
  },
  "compute_egress": {
    "required_domains": [
      "api.nukez.xyz"
    ],
    "why": "Sandbox mode uploads file bytes via curl to Nukez short URLs, bypassing LLM context. Without egress, uploads fall back to base64 (limited to ~32KB).",
    "upload_modes": {
      "sandbox": "Agent brokers a short URL, executes curl PUT with ?proxy=1 — binary bytes never enter context (~500 tokens regardless of file size)",
      "inline": "Base64-encoded in tool parameter — suitable for files under ~32KB",
      "url": "Server-side fetch from external HTTPS URL via /v1/files/fetch-and-store"
    },
    "setup_instructions": {
      "claude_ai": "Settings → Capabilities → Network egress → Additional domains → add api.nukez.xyz"
    }
  },
  "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.",
    "decision_heuristic": [
      "Need to store bytes for later?",
      "Need a receipt / public verifiability?",
      "No privileged cloud credentials available?",
      "Then Nukez is a good fit."
    ],
    "provider_selection": {
      "request_field": "provider",
      "supported_values": [
        "gcs",
        "mongodb",
        "storj",
        "arweave",
        "filecoin",
        "firestore"
      ],
      "note": "Provider is selected at /v1/storage/request and bound to the locker at provision/confirm."
    }
  },
  "auth": {
    "modes": {
      "public": {
        "description": "No auth headers required."
      },
      "signed_envelope": {
        "description": "Request-bound Ed25519 signature using payer key (envelope + signature headers).",
        "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"
        ],
        "envelope_construction": {
          "v": "Always 1",
          "locker_id": "Deterministic: 'locker_' + sha256(receipt_id).hex()[:12]",
          "receipt_id": "The receipt_id from confirm_storage response",
          "nonce": "Random 16 bytes as hex string (32 chars)",
          "iat": "Current Unix timestamp (seconds)",
          "exp": "iat + TTL (typically 60 seconds)",
          "ops": "Array of operation strings from endpoint's required_ops (e.g., ['locker:provision'])",
          "method": "HTTP method uppercase (GET, POST, PUT, DELETE)",
          "path": "API path exactly as called (e.g., '/v1/storage/signed_provision')",
          "body_sha256": "SHA256 hex digest of the canonical JSON request body (or empty string hash if no body)"
        },
        "canonical_json": {
          "description": "Canonical JSON serialization for both envelope and request body",
          "rules": [
            "Keys sorted alphabetically",
            "No whitespace between elements",
            "Separators: comma without space, colon without space",
            "UTF-8 encoding"
          ],
          "example_python": "json.dumps(obj, sort_keys=True, separators=(',', ':'))",
          "example_js": "JSON.stringify(obj, Object.keys(obj).sort())"
        },
        "body_hash_critical": {
          "warning": "The body_sha256 in the envelope MUST match the SHA256 of the actual HTTP request body.",
          "common_mistake": "Computing body_sha256 from one JSON string but sending a differently-formatted body causes 401 errors.",
          "solution": "Serialize body to canonical JSON ONCE. Hash that string for body_sha256. Send that EXACT string as the request body."
        },
        "construction_steps": [
          "1. Build request body object (if any)",
          "2. Serialize body to canonical JSON string (sorted keys, no whitespace)",
          "3. Compute body_sha256 = sha256(canonical_body_string).hex()",
          "4. Build envelope object with all fields",
          "5. Serialize envelope to canonical JSON bytes",
          "6. base64url-encode envelope bytes (no padding) -> X-Nukez-Envelope header",
          "7. Ed25519-sign envelope bytes, base58-encode -> X-Nukez-Signature header",
          "8. Send HTTP request with headers AND the canonical body string from step 2"
        ],
        "ops_by_endpoint": {
          "/v1/storage/signed_provision": [
            "locker:provision"
          ],
          "/v1/lockers/{locker_id}/files (POST)": [
            "locker:write"
          ],
          "/v1/lockers/{locker_id}/files (GET list)": [
            "locker:list"
          ],
          "/v1/lockers/{locker_id}/files/{filename} (GET)": [
            "locker:read"
          ],
          "/v1/lockers/{locker_id}/files/{filename} (DELETE)": [
            "locker:write"
          ],
          "/v1/lockers/{locker_id}/urls": [
            "locker:urls"
          ],
          "/v1/files/fetch-and-store (POST)": [
            "locker:write"
          ],
          "/v1/lockers/{locker_id}/operators (POST)": [
            "locker:admin"
          ],
          "/v1/lockers/{locker_id}/operators/{pubkey} (DELETE)": [
            "locker:admin"
          ],
          "/v1/lockers/{locker_id}/manifest (GET)": [
            "locker:read"
          ],
          "/v1/lockers/{locker_id}/files/urls (POST)": [
            "locker:read"
          ],
          "/v1/files/confirm (POST)": [
            "locker:write"
          ],
          "/v1/attest/push (POST)": [
            "locker:attest"
          ],
          "/v1/storage/attest (POST)": [
            "locker:attest"
          ]
        },
        "notes": [
          "All authenticated endpoints require signed_envelope auth (request-bound, no bearer tokens).",
          "Use x-nukez-ops from OpenAPI to populate envelope.ops for each endpoint.",
          "Signed-envelope auth is request-bound: X-Nukez-Envelope and X-Nukez-Signature must be attached to the same HTTP request they authorize.",
          "If the envelope includes body_sha256, the signature is only valid for the exact body bytes sent over the wire. Prefer canonical JSON and send those exact bytes.",
          "A 422 from a signed_envelope endpoint usually indicates missing envelope headers (or body hash mismatch).",
          "Op locker:attest authorizes payer-signed attestation operations: POST /v1/storage/attest (compute Merkle root over confirmed files) and POST /v1/attest/push (anchor the root on Switchboard). Only the receipt's payer can issue it. The envelope's receipt_id must equal the request body's (or query param's) receipt_id; mismatch returns 401 RECEIPT_ID_MISMATCH. Rationale: both endpoints cause the gateway to spend server-held SOL on oracle/anchor writes."
        ],
        "full_documentation": "/docs/AUTH_SIGNED_ENVELOPE.md"
      },
      "signed_urls": {
        "description": "upload_url/download_url are provider-opaque short URLs (https://api.nukez.xyz/f/{token}) that resolve to storage via gateway proxy or 307 redirect.",
        "notes": [
          "Agents PUT/GET to the short URL directly; no cloud credentials are exposed.",
          "Short URL tokens are Ed25519-signed and independently verifiable via /v1/short-url/verify-key.",
          "If a URL fails with 403/404, assume expiry and call GET /v1/lockers/{locker_id}/files/{filename} for fresh URLs.",
          "Append ?proxy=1 to PUT URLs to proxy uploads through the gateway (single-domain egress for sandbox environments)."
        ]
      }
    }
  },
  "flows": {
    "provision_and_use_file_first": {
      "summary": "request_storage -> pay -> confirm_storage -> signed_provision -> create_file -> PUT upload_url -> GET download_url",
      "notes": [
        "Expect HTTP 402 from /v1/storage/request (it is part of the x402 payment protocol).",
        "Persist receipt_id; locker_id is deterministic from receipt_id.",
        "Provision returns a manifest; treat its file_api sub-object as runtime truth for file endpoints.",
        "Storage request accepts optional pay_network and pay_asset for multi-chain payment selection.",
        "Confirm: tx_sig goes in X402-TX header; confirm body must echo pay_asset (and pay_network for multi-chain) matching the leg you actually paid, or gateway rejects the mismatch."
      ]
    },
    "operator_delegation": {
      "summary": "signed_provision(operator_pubkey=X) -> operator signs file ops with their own Ed25519 key",
      "notes": [
        "Operators are Ed25519 keys that can perform file operations on behalf of the locker owner.",
        "Useful for cross-chain delegation: EVM owner delegates to Ed25519 operator for file ops.",
        "Add operators after provisioning via POST /v1/lockers/{locker_id}/operators (requires locker:admin).",
        "Remove operators via DELETE /v1/lockers/{locker_id}/operators/{pubkey}.",
        "Operator auth uses same signed envelope headers; gateway verifies the operator key against the locker record."
      ]
    },
    "verification_bundle": {
      "summary": "GET /v1/storage/verification-bundle?receipt_id=X -> self-contained proof package",
      "notes": [
        "Returns payment proof + content proof + verification algorithm spec + DIY steps.",
        "No authentication required.",
        "Use when you need a portable, self-contained verification package."
      ]
    },
    "merkle_inclusion_proof": {
      "summary": "GET /v1/storage/merkle-proof?receipt_id=X&filename=Y -> inclusion proof for a single file",
      "notes": [
        "No authentication required.",
        "Returns leaf_hash, proof (list of {hash, position} sibling steps), merkle_root, tree_depth, file_entry.",
        "Verify by walking the proof: for each step, if position=='left' then sha256(sibling || current) else sha256(current || sibling); final must equal merkle_root (after stripping the 'sha256:' prefix).",
        "Canonical algorithm spec at /docs/verify/merkle-v1.md; machine-readable at /specs/nukez-merkle-v1.json.",
        "Includes conformance test vector — implementers MUST reproduce the published root and proof exactly."
      ]
    }
  },
  "real_world_failure_modes": {
    "tx_propagation_delay": {
      "symptom": "confirm_storage returns 402 tx_not_found",
      "strategy": "Retry with exponential backoff (2s, 4s, 8s, 16s, 32s)."
    },
    "pay_leg_mismatch": {
      "symptom": "confirm_storage returns 400 with message '<ASSET> on <NETWORK> not in quote'",
      "strategy": "The pay_asset/pay_network in your confirm body must match the leg of accepts[] you actually paid. If you paid USDC on monad-mainnet, send {\"pay_asset\":\"USDC\",\"pay_network\":\"monad-mainnet\"} in the confirm body. Default fallback only applies when both are omitted."
    },
    "envelope_expiry": {
      "symptom": "401/422 from signed_envelope endpoints with stale timestamp",
      "strategy": "Rebuild envelope with fresh timestamp and re-sign."
    },
    "signed_url_expiry": {
      "symptom": "403/404 from upload_url/download_url",
      "strategy": "Re-mint URLs via GET /files/{filename} or re-run create_file."
    },
    "idempotency": {
      "symptom": "409 on request_storage with reused Idempotency-Key but different body",
      "strategy": "Use a new Idempotency-Key or resend the identical body."
    },
    "body_hash_mismatch": {
      "symptom": "401 with error mentioning body hash or envelope verification failed",
      "strategy": "Ensure body_sha256 in envelope matches SHA256 of the EXACT request body bytes sent. Use canonical JSON (sorted keys, no whitespace) for both."
    }
  }
}
