{
  "openapi": "3.1.0",
  "info": {
    "title": "PQ Shield self-hosted reference API",
    "version": "0.1.0-reference",
    "description": "Public-input construction and verification only. This unaudited Rust reference service does not accept private keys, sign transactions, broadcast, or provide a hosted endpoint. The caller must verify all artifacts and sign locally. Bloch anchor enforcement is not consensus-wired."
  },
  "servers": [{"url": "http://127.0.0.1:8787", "description": "Default local bind; run the service yourself"}],
  "tags": [
    {"name": "Vault", "description": "Bitcoin P2WSH construction; all transactions are unsigned"},
    {"name": "Anchor", "description": "PQ commitment and verification; caller controls the trust root"},
    {"name": "Service", "description": "Local process health"}
  ],
  "paths": {
    "/health": {"get": {"tags": ["Service"], "summary": "Local service liveness", "responses": {"200": {"description": "Service is running", "content": {"application/json": {"schema": {"type": "object", "required": ["status", "service", "non_custodial", "signs", "note"], "properties": {"status": {"const": "ok"}, "service": {"const": "pq-shield-api"}, "non_custodial": {"const": true}, "signs": {"const": false}, "note": {"type": "string"}}}}}}}}},
    "/vault/address": {"post": {"tags": ["Vault"], "summary": "Build deposit and trigger P2WSH addresses from public inputs", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AddressRequest"}}}}, "responses": {"200": {"description": "Public scripts and addresses; nothing signed", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AddressResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}},
    "/vault/unvault-tx": {"post": {"tags": ["Vault"], "summary": "Build unsigned deposit-to-trigger transaction", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnvaultRequest"}}}}, "responses": {"200": {"description": "Unsigned transaction and hot-key sighash", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UnvaultResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}},
    "/vault/branch-a-tx": {"post": {"tags": ["Vault"], "summary": "Build unsigned delayed normal spend", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BranchARequest"}}}}, "responses": {"200": {"description": "Unsigned CSV-delayed spend and hot-key sighash", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BranchAResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}},
    "/vault/clawback-tx": {"post": {"tags": ["Vault"], "summary": "Build unsigned immediate recovery spend", "description": "The caller must independently compare safe_destination with its authenticated anchor's designated_safe_dest; this route does not enforce that relationship.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClawbackRequest"}}}}, "responses": {"200": {"description": "Unsigned clawback and recovery-key sighash", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClawbackResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}},
    "/anchor/commitment": {"post": {"tags": ["Anchor"], "summary": "Prepare canonical bytes for local PQ signing", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AnchorFields"}}}}, "responses": {"200": {"description": "Commitment bytes and guard hashes; signature is not produced", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/CommitmentResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}},
    "/anchor/verify": {"post": {"tags": ["Anchor"], "summary": "Verify PQ signature against caller-supplied trusted public key", "description": "trusted_pq_pubkey must come from an authenticated source independent of the supplied anchor. A valid signature under a self-declared key is not proof of ownership.", "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VerifyRequest"}}}}, "responses": {"200": {"description": "Verification result; invalid signatures return valid=false", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VerifyResponse"}}}}, "400": {"$ref": "#/components/responses/BadRequest"}}}}
  },
  "components": {
    "responses": {"BadRequest": {"description": "Invalid fields or rejected secret-shaped field name", "content": {"application/json": {"schema": {"type": "object", "required": ["error", "non_custodial"], "properties": {"error": {"type": "string"}, "non_custodial": {"type": "string"}}}}}}},
    "schemas": {
      "Hex32": {"type": "string", "pattern": "^[0-9a-fA-F]{64}$", "description": "32 public bytes encoded as hexadecimal"},
      "CompressedPubkey": {"type": "string", "pattern": "^(02|03)[0-9a-fA-F]{64}$", "description": "33-byte compressed secp256k1 public key; no secret key"},
      "HexBytes": {"type": "string", "pattern": "^([0-9a-fA-F]{2})*$", "description": "Public bytes encoded as hexadecimal"},
      "Network": {"type": "string", "enum": ["mainnet", "bitcoin", "main", "testnet", "test", "signet", "regtest"], "description": "Case-insensitive aliases accepted by the implementation"},
      "SatAmount": {"type": "integer", "minimum": 0, "maximum": 18446744073709551615, "description": "Nonnegative u64 satoshis; fee must be less than input amount"},
      "VaultParams": {"type": "object", "additionalProperties": false, "required": ["hot_pubkey", "recovery_pubkey", "recovery_hash", "csv_delay"], "properties": {"hot_pubkey": {"$ref": "#/components/schemas/CompressedPubkey"}, "recovery_pubkey": {"$ref": "#/components/schemas/CompressedPubkey"}, "recovery_hash": {"$ref": "#/components/schemas/Hex32"}, "csv_delay": {"type": "integer", "minimum": 0, "maximum": 65535, "description": "u16 CSV delay; caller must assess usable policy"}}},
      "Outpoint": {"type": "object", "additionalProperties": false, "required": ["txid", "vout"], "properties": {"txid": {"$ref": "#/components/schemas/Hex32"}, "vout": {"type": "integer", "minimum": 0, "maximum": 4294967295}}},
      "AddressRequest": {"type": "object", "additionalProperties": false, "required": ["network", "hot_pubkey", "recovery_pubkey", "recovery_hash", "csv_delay"], "properties": {"network": {"$ref": "#/components/schemas/Network"}, "hot_pubkey": {"$ref": "#/components/schemas/CompressedPubkey"}, "recovery_pubkey": {"$ref": "#/components/schemas/CompressedPubkey"}, "recovery_hash": {"$ref": "#/components/schemas/Hex32"}, "csv_delay": {"type": "integer", "minimum": 0, "maximum": 65535}}},
      "UnvaultRequest": {"type": "object", "additionalProperties": false, "required": ["network", "vault", "deposit_outpoint", "deposit_amount_sat", "fee_sat"], "properties": {"network": {"$ref": "#/components/schemas/Network"}, "vault": {"$ref": "#/components/schemas/VaultParams"}, "deposit_outpoint": {"$ref": "#/components/schemas/Outpoint"}, "deposit_amount_sat": {"$ref": "#/components/schemas/SatAmount"}, "fee_sat": {"$ref": "#/components/schemas/SatAmount"}}},
      "BranchARequest": {"type": "object", "additionalProperties": false, "required": ["network", "vault", "trigger_outpoint", "trigger_amount_sat", "destination", "fee_sat"], "properties": {"network": {"$ref": "#/components/schemas/Network"}, "vault": {"$ref": "#/components/schemas/VaultParams"}, "trigger_outpoint": {"$ref": "#/components/schemas/Outpoint"}, "trigger_amount_sat": {"$ref": "#/components/schemas/SatAmount"}, "destination": {"type": "string", "description": "Bitcoin address validated for the selected network"}, "fee_sat": {"$ref": "#/components/schemas/SatAmount"}}},
      "ClawbackRequest": {"type": "object", "additionalProperties": false, "required": ["network", "vault", "trigger_outpoint", "trigger_amount_sat", "safe_destination", "fee_sat"], "properties": {"network": {"$ref": "#/components/schemas/Network"}, "vault": {"$ref": "#/components/schemas/VaultParams"}, "trigger_outpoint": {"$ref": "#/components/schemas/Outpoint"}, "trigger_amount_sat": {"$ref": "#/components/schemas/SatAmount"}, "safe_destination": {"type": "string", "description": "Bitcoin address validated for network; caller must check against authenticated anchor"}, "fee_sat": {"$ref": "#/components/schemas/SatAmount"}}},
      "AnchorFields": {"type": "object", "required": ["btc_vault_address", "recovery_hash", "pq_recovery_pubkey", "designated_safe_dest", "csv_delay"], "properties": {"target_chain": {"type": "string", "enum": ["bitcoin", "btc", "litecoin", "ltc", "bitcoincash", "bch", "dogecoin", "doge", "ethereuml1", "eth"], "default": "bitcoin", "description": "Metadata label only; other-chain adapters are not implemented"}, "btc_vault_address": {"type": "string"}, "recovery_hash": {"$ref": "#/components/schemas/Hex32"}, "pq_recovery_pubkey": {"$ref": "#/components/schemas/HexBytes"}, "designated_safe_dest": {"type": "string"}, "csv_delay": {"type": "integer", "minimum": 0, "maximum": 65535}, "policy": {"type": "string", "default": ""}, "btc_pubkey": {"$ref": "#/components/schemas/CompressedPubkey", "description": "Optional public key; enables custody guard hash"}}},
      "VerifyRequest": {"description": "Supply either signed_anchor_hex or fields plus signature, and always an independently trusted public key. In field mode, the AnchorFields properties are at the top level.", "oneOf": [{"type": "object", "required": ["signed_anchor_hex", "trusted_pq_pubkey"], "properties": {"signed_anchor_hex": {"$ref": "#/components/schemas/HexBytes"}, "trusted_pq_pubkey": {"$ref": "#/components/schemas/HexBytes"}}}, {"allOf": [{"$ref": "#/components/schemas/AnchorFields"}, {"type": "object", "required": ["signature", "trusted_pq_pubkey"], "properties": {"signature": {"$ref": "#/components/schemas/HexBytes"}, "trusted_pq_pubkey": {"$ref": "#/components/schemas/HexBytes"}}}]}]},
      "AddressResponse": {"type": "object", "required": ["network", "csv_delay", "deposit", "trigger", "import_descriptor", "notes", "non_custodial"], "properties": {"network": {"type": "string"}, "csv_delay": {"type": "integer"}, "deposit": {"$ref": "#/components/schemas/DepositArtifact"}, "trigger": {"$ref": "#/components/schemas/TriggerArtifact"}, "import_descriptor": {"type": "string"}, "notes": {"type": "array", "items": {"type": "string"}}, "non_custodial": {"type": "string"}}},
      "DepositArtifact": {"type": "object", "required": ["address", "witness_script_hex", "script_pubkey_hex", "spend_witness"], "properties": {"address": {"type": "string"}, "witness_script_hex": {"$ref": "#/components/schemas/HexBytes"}, "script_pubkey_hex": {"$ref": "#/components/schemas/HexBytes"}, "spend_witness": {"type": "string"}}},
      "TriggerArtifact": {"type": "object", "required": ["address", "witness_script_hex", "script_pubkey_hex", "branch_a_witness", "branch_b_witness"], "properties": {"address": {"type": "string"}, "witness_script_hex": {"$ref": "#/components/schemas/HexBytes"}, "script_pubkey_hex": {"$ref": "#/components/schemas/HexBytes"}, "branch_a_witness": {"type": "string"}, "branch_b_witness": {"type": "string"}}},
      "Sighash": {"type": "object", "required": ["input_index", "sighash_hex", "sighash_type", "sign_with", "witness_script_hex", "prevout_amount_sat", "witness_stack"], "properties": {"input_index": {"type": "integer"}, "sighash_hex": {"$ref": "#/components/schemas/Hex32"}, "sighash_type": {"const": "SIGHASH_ALL"}, "sign_with": {"type": "string"}, "witness_script_hex": {"$ref": "#/components/schemas/HexBytes"}, "prevout_amount_sat": {"$ref": "#/components/schemas/SatAmount"}, "witness_stack": {"type": "string"}}},
      "TxOutput": {"type": "object", "required": ["address", "vout", "amount_sat"], "properties": {"address": {"type": "string"}, "vout": {"type": "integer"}, "amount_sat": {"$ref": "#/components/schemas/SatAmount"}}},
      "UnsignedTx": {"type": "object", "required": ["unsigned_tx_hex", "txid", "sighashes", "non_custodial"], "properties": {"unsigned_tx_hex": {"$ref": "#/components/schemas/HexBytes"}, "txid": {"$ref": "#/components/schemas/Hex32"}, "sighashes": {"type": "array", "items": {"$ref": "#/components/schemas/Sighash"}}, "non_custodial": {"type": "string"}}},
      "UnvaultResponse": {"allOf": [{"$ref": "#/components/schemas/UnsignedTx"}, {"type": "object", "required": ["trigger_output"], "properties": {"trigger_output": {"$ref": "#/components/schemas/TxOutput"}}}]},
      "BranchAResponse": {"allOf": [{"$ref": "#/components/schemas/UnsignedTx"}, {"type": "object", "required": ["matures_after_blocks", "note"], "properties": {"matures_after_blocks": {"type": "integer"}, "note": {"type": "string"}}}]},
      "ClawbackResponse": {"allOf": [{"$ref": "#/components/schemas/UnsignedTx"}, {"type": "object", "required": ["safe_output", "notes"], "properties": {"safe_output": {"$ref": "#/components/schemas/TxOutput"}, "notes": {"type": "array", "items": {"type": "string"}}}}]},
      "CommitmentResponse": {"type": "object", "required": ["commitment_bytes_hex", "commitment_len", "anchor_version", "sign_algo", "bloch_governance_guard_hash", "next_step", "non_custodial"], "properties": {"commitment_bytes_hex": {"$ref": "#/components/schemas/HexBytes"}, "commitment_len": {"type": "integer"}, "anchor_version": {"type": "integer"}, "sign_algo": {"type": "string"}, "bloch_governance_guard_hash": {"$ref": "#/components/schemas/Hex32"}, "bloch_custody_guard_hash": {"$ref": "#/components/schemas/Hex32", "description": "Present only when btc_pubkey was provided"}, "next_step": {"type": "string"}, "non_custodial": {"type": "string"}}},
      "VerifyResponse": {"type": "object", "required": ["valid", "reason", "verified_against_pq_pubkey", "commitment_bytes_hex", "non_custodial"], "properties": {"valid": {"type": "boolean"}, "reason": {"type": "string"}, "verified_against_pq_pubkey": {"$ref": "#/components/schemas/HexBytes"}, "commitment_bytes_hex": {"$ref": "#/components/schemas/HexBytes"}, "non_custodial": {"type": "string"}}}
    }
  }
}
