{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/atlasyield-club/json-schema/atlasyield-club-score-schema.json",
  "title": "Score",
  "x-generated": "2026-11-02",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/atlasyield-club-openapi.json#/components/schemas/Score",
  "type": "object",
  "properties": {
    "vaultId": {
      "type": "string",
      "description": "Stable identifier: protocol:chainId:address."
    },
    "chainId": {
      "type": "integer",
      "description": "Chain id. EVM chains use their EIP-155 id (1 Ethereum, 8453 Base, 42161 Arbitrum); Solana is 792703809 (Relay's id)."
    },
    "protocolId": {
      "type": "string",
      "description": "Adapter/protocol slug. Currently one of beefy, yearn-v3, morpho, pendle, aave-v3, euler, etherfi, ethena, kamino. New adapters are added over time — treat this as an open set rather than a fixed enum."
    },
    "name": {
      "type": [
        "string",
        "null"
      ],
      "description": "Human-readable vault name, the same string /catalog reports, so no join is needed. Null only when the vault is absent from the live catalog cache."
    },
    "onchainId": {
      "type": [
        "string",
        "null"
      ],
      "description": "The vault address with its original case. vaultId is lowercased, which is lossless for 0x addresses but not for Solana base58, so use this field to look a vault up on-chain. Null only when the vault is absent from the live cache."
    },
    "adminTopology": {
      "type": [
        "object",
        "null"
      ],
      "description": "AY-269: per-vault admin setup, read daily. Null when the vault is not screened (Aave, Pendle, EtherFi, Ethena, and BNB vaults) and scores on protocol metadata instead. `class` is one of immutable, timelock_long_multisig_strong (7+ day delay, a 3+ threshold multisig that is also a majority of signers), timelock_short_multisig_weak, multisig_only, eoa (a single admin key), or unknown. For an `eoa` vault, `curatorRating` decides the score directly: 40 when the curator is rated established, 10 when unknown or new; every class floors at 10. `roles` never carries an address, only kind (none, eoa, safe, dao, unrecognised) plus threshold/owners for a safe. `dao` is on-chain governance (a token-vote governor or Sky), scored like a strong multisig; a dao with `unverifiedGovernance` (Aragon, plugin not inspected) is scored like a weak one. `delaySeconds` is the delay a timelock or supervisor adds in front of that role, on top of the vault's own `timelockSeconds`.",
      "properties": {
        "class": {
          "type": "string",
          "enum": [
            "immutable",
            "timelock_long_multisig_strong",
            "timelock_short_multisig_weak",
            "multisig_only",
            "eoa",
            "unknown"
          ]
        },
        "curatorId": {
          "type": [
            "string",
            "null"
          ]
        },
        "curatorRating": {
          "type": [
            "string",
            "null"
          ],
          "enum": [
            "established",
            "unknown_new"
          ]
        },
        "timelockSeconds": {
          "type": [
            "number",
            "null"
          ]
        },
        "roles": {
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "role": {
                "type": "string"
              },
              "kind": {
                "type": "string",
                "enum": [
                  "none",
                  "eoa",
                  "safe",
                  "dao",
                  "unrecognised"
                ]
              },
              "threshold": {
                "type": "number"
              },
              "owners": {
                "type": "number"
              },
              "delaySeconds": {
                "type": "number"
              },
              "unverifiedGovernance": {
                "type": "boolean"
              }
            }
          }
        },
        "checkedAt": {
          "type": "string",
          "format": "date-time"
        }
      }
    },
    "asset": {
      "type": "string",
      "description": "Underlying asset symbol."
    },
    "assetClass": {
      "type": [
        "string",
        "null"
      ],
      "enum": [
        "stablecoin",
        "stablecoin-yield",
        "eth",
        "btc",
        "top50",
        "usd-exotic",
        "other"
      ],
      "description": "Asset class bucket used to contextualise the yield factors. May be null."
    },
    "composite": {
      "type": "number",
      "description": "0–100 composite Atlas Score."
    },
    "label": {
      "type": "string",
      "enum": [
        "Conservative",
        "Balanced",
        "Aggressive"
      ],
      "description": "Risk-posture band for the composite."
    },
    "pillarScores": {
      "type": "object",
      "description": "The four pillar scores, 0–100 each.",
      "properties": {
        "yield": {
          "type": "number"
        },
        "safety": {
          "type": "number"
        },
        "liquidity": {
          "type": "number"
        },
        "sustainability": {
          "type": "number"
        }
      }
    },
    "apy": {
      "type": [
        "number",
        "null"
      ],
      "description": "Current APY in percentage points (5.21 = 5.21%). May be null."
    },
    "tvl": {
      "type": [
        "number",
        "null"
      ],
      "description": "Total value locked, USD. May be null."
    },
    "dataQuality": {
      "type": "string",
      "enum": [
        "sufficient",
        "partial",
        "fallback"
      ],
      "description": "How complete the inputs were."
    },
    "scoredAt": {
      "type": "string",
      "format": "date-time",
      "description": "ISO-8601 UTC timestamp the score was computed (ex-ante, immutable)."
    },
    "scorerVersion": {
      "type": "string",
      "description": "Scoring engine version that produced the row."
    }
  }
}