{
  "schema": "kerne-por-schema-changelog/v1",
  "current_schema_version": 9,
  "changelog_digest": "0x0fc2f7a6752f085436d84f7bb1e9611d98ce31fcd79e3f2c24c3bbc223342412",
  "historical_digest": "0x6e66ac3d8a188fdb9c81ab7e4c87032473c7e3d7acf222bf4398cea8053f69a0",
  "entries": [
    {
      "schema_version": 1,
      "date": "2026-01-21",
      "identifier": null,
      "summary": "Original signed attestation shape.",
      "changes_measurement": false,
      "comparability": "baseline",
      "fields_added": [
        "total_assets_eth",
        "total_liabilities_eth",
        "solvency_ratio",
        "chains",
        "offchain"
      ],
      "fields_changed": [],
      "rationale": "First publication."
    },
    {
      "schema_version": 2,
      "date": "2026-05-17",
      "identifier": null,
      "summary": "PSM and USD-aggregate fields added.",
      "changes_measurement": false,
      "comparability": "comparable",
      "fields_added": [
        "aggregate_collateral_usd",
        "aggregate_liabilities_usd",
        "aggregate_solvency_usd_ratio"
      ],
      "fields_changed": [],
      "rationale": "The USD view was previously derivable but not published, so two readers computed it two ways."
    },
    {
      "schema_version": 3,
      "date": "2026-05-23",
      "identifier": "POR_SIGNED_SOLVENCY_UNDERSTATEMENT",
      "summary": "The aggregate liability became OUTSTANDING kUSD, that is total supply minus the kUSD the PSM contracts hold as inventory.",
      "changes_measurement": true,
      "comparability": "break",
      "measured_before": "Liability was kUSD.totalSupply(), which counted the protocol's own unissued PSM inventory as if it were a claim by a user.",
      "measured_after": "Liability is totalSupply() minus PSM-held kUSD, which is the amount users can actually present for redemption.",
      "fields_added": [
        "psm_kusd_held",
        "outstanding_kusd",
        "psm_usdc_reserve"
      ],
      "fields_changed": [
        "aggregate_liabilities_usd",
        "aggregate_solvency_usd_ratio"
      ],
      "rationale": "The old basis UNDERSTATED solvency. Correcting it in our own favour is exactly the direction of change that deserves the loudest disclosure, which is why the write-up docs/security/POR_SIGNED_SOLVENCY_UNDERSTATEMENT_2026-05-23.md was published with it."
    },
    {
      "schema_version": 4,
      "date": "2026-06-12",
      "identifier": null,
      "summary": "Headline restructure. aggregate_solvency_ratio now carries the PSM stablecoin backing ratio; the old vault-share basis moved to legacy_vault_share_solvency_ratio under its own name.",
      "changes_measurement": true,
      "comparability": "break",
      "measured_before": "aggregate_solvency_ratio was a vault-share ratio, which is not a statement about whether kUSD is backed.",
      "measured_after": "aggregate_solvency_ratio is psm_usdc_reserve / outstanding_kusd: every input an on-chain quantity a reader can recompute without us, in seven read calls on Base.",
      "fields_added": [
        "aggregate_solvency_ratio_basis",
        "legacy_vault_share_solvency_ratio",
        "known_issue_vault_v1"
      ],
      "fields_changed": [
        "aggregate_solvency_ratio"
      ],
      "rationale": "The headline should be the number a lender underwrites against. The pre-v4 legacy key `solvency_ratio` deliberately kept the old share-basis value so pre-v4 verifiers parse unchanged rather than silently reading a different quantity under a familiar name."
    },
    {
      "schema_version": 5,
      "date": "2026-07-14",
      "identifier": "KRN-26-POR-DELTA-NEUTRAL-VACUOUS",
      "summary": "delta_neutral became tri-state and was bound into the signature alongside a delta_neutral_state qualifier.",
      "changes_measurement": false,
      "comparability": "comparable",
      "fields_added": [
        "delta_neutral_state"
      ],
      "fields_changed": [
        "delta_neutral"
      ],
      "rationale": "delta_neutral was advertised as client-verifiable but was not in the signed preimage, so a tamperer on the plaintext publisher-to-relay hop could flip it without breaking the hash. Binding it closed that. The tri-state exists so 'we did not measure a book this cycle' stops rendering as a confident false."
    },
    {
      "schema_version": 6,
      "date": "2026-07-23",
      "identifier": "KRN-26-POR-HEDGE-BASE-DECLARED",
      "summary": "The net_delta DENOMINATOR changed from the attested vault's ETH-exposed leg alone to the declared hedge base, which is that leg plus the disclosed founder-custodied watch-only float. The published status went from WARNING_DELTA to SOLVENT.",
      "changes_measurement": true,
      "comparability": "break",
      "measured_before": "net_delta = abs(1 - short / vault_exposed_eth). The attested vault v2 holds no user deposits, so that denominator was 0.0, and the code's divide-by-zero branch hardcoded net_delta = 1.0. A correctly sized hedge therefore scored as fully directional.",
      "measured_after": "net_delta = abs(1 - short / (vault_exposed_eth + watch_only_eth)), the base the hedge engine actually sizes against and the same base /api/por and the daily report already used. At the live book that is 0.28 percent, inside the untouched 5 percent tolerance.",
      "fields_added": [
        "hedge_base_eth",
        "hedge_base_vault_exposed_eth",
        "hedge_base_watch_only_eth",
        "hedge_base_watch_only_addresses",
        "hedge_base_watch_only_included",
        "hedge_base_verified",
        "hedge_base_basis",
        "status_explanation",
        "retired_vault_v1",
        "vault_v1_degraded_known_basis"
      ],
      "fields_changed": [
        "offchain_net_delta",
        "delta_neutral",
        "status"
      ],
      "rationale": "Three Kerne surfaces were dividing the same short by three different denominators and only one of them was declared. /api/por published totalEth 0.00792 as 'the hedge base the engine sizes its short against' at the same instant the signed PoR divided by zero. The fix made the signed surface use the declared base and published that base in its parts, signed.",
      "self_criticism": "This is the change that broke a public commitment, and it is the reason this changelog exists. At 22:48:42 UTC on 2026-07-23, in Euler governance thread 1849 post 6, Kerne wrote: 'We could clear that flag tomorrow by widening the hedge base to include that wallet. We are not going to.' Commit 4b8c9e28 landed at 23:46:12 UTC the same evening and did exactly that; the bot carrying it restarted at 00:16:36 UTC on 2026-07-24. The interval between the promise and the commit was 57 minutes 30 seconds. Two concurrent workstreams, one writing the sentence and one shipping the change, and no mechanism that would have made either notice the other. The commitment that should have been made, and that Kerne did keep, was the narrower one: the founder float never enters the canonical solvency ratio. The sentence as written promised the warning would stay, and the warning did not stay.",
      "what_did_not_change": "psm_solvency_ratio and aggregate_solvency_ratio, the canonical solvency read, on the pure PSM basis with the founder float excluded from every ratio. Verifiable in seven read calls on Base at any block either side of this change."
    },
    {
      "schema_version": 7,
      "date": "2026-07-25",
      "identifier": "KRN-26-POR-ACCOUNT-ENUMERATION",
      "summary": "The signed account enumeration is bound into the hourly attestation, and this changelog's digest is signed alongside it.",
      "changes_measurement": false,
      "comparability": "comparable",
      "fields_added": [
        "account_registry_state",
        "account_registry_version",
        "account_registry_digest",
        "account_set_digest",
        "account_registry_url",
        "schema_changelog_digest",
        "schema_changelog_url"
      ],
      "fields_changed": [],
      "rationale": "Built to the specification Oleg_Aleksandrov published in thread 1849 post 7: every account signs 'I belong to Kerne as of [date].', hedging is restricted to venues with public per-address balances, no paid attestor, and every check runnable by anyone. account_set_digest is what makes 'these are all of them' a signed claim rather than an assurance. schema_changelog_digest binds the protocol to a specific published history of its own field semantics, so a future silent redefinition has to contradict something it already signed."
    },
    {
      "schema_version": 8,
      "date": "2026-07-28",
      "identifier": "KRN-26-POR-HEDGE-BASE-NON-BACKING",
      "summary": "The net_delta DENOMINATOR is reverted to the attested vault's ETH-exposed leg alone. The founder-custodied float that schema 6 added is removed from it and demoted to its own disclosed_float_* fields with its own state. The published status returns to WARNING_DELTA and stays there until the hedge runs against collateral that actually backs kUSD.",
      "changes_measurement": true,
      "comparability": "break",
      "measured_before": "net_delta = abs(1 - short / (vault_exposed_eth + watch_only_eth)), where watch_only_eth is the native ETH plus WETH balance of a founder-custodied EOA that backs no kUSD. In force from 2026-07-24 00:16:36 UTC to 2026-07-28, schemas 6 and 7.",
      "measured_after": "net_delta = abs(1 - short / vault_exposed_eth). Protocol collateral only. This is the schema 5 denominator, so schema 8 readings are comparable with schema 5 and earlier on this field and are NOT comparable with schema 6 or 7. The float is still read and still published as disclosed_float_eth with its own delta and state, and it drives no status, no ratio and no solvency verdict.",
      "fields_added": [
        "hedge_base_watch_only_in_canonical_base",
        "disclosed_float_eth",
        "disclosed_float_native_eth",
        "disclosed_float_weth_eth",
        "disclosed_float_delta",
        "disclosed_float_delta_state"
      ],
      "fields_changed": [
        "hedge_base_eth",
        "hedge_base_verified",
        "offchain_net_delta",
        "delta_neutral",
        "status"
      ],
      "rationale": "Two defects, found together. The first is that the denominator FLAPPED: roughly 86 percent of the float was native ETH in a spendable EOA, which is a gas balance, so ordinary transactions moved the denominator while the short stayed where the engine had put it. Observed live, the float fell 0.00792155 to 0.00562139 ETH against an unchanged 0.0079 short and the signed status moved from SOLVENT to WARNING_DELTA on that alone. A solvency-adjacent flag that toggles when one person buys gas is noise, and it teaches readers to ignore the alarm that matters. The second defect is that schema 6 should never have been shipped at all: it put a non-backing wallet into the denominator of a solvency-adjacent measurement, which is the same category error the protocol already refuses to make in the solvency ratio itself. hedge_base_watch_only_in_canonical_base is hardcoded False and signed every cycle, so the commitment is now a cryptographic claim rather than a sentence on a forum, which is what it was when it was broken.",
      "self_criticism": "This entry exists because a reviewer caught it and Kerne did not. Oleg_Aleksandrov, Euler governance thread 1849 post 7, 2026-07-25 10:32:10 UTC: 'schema v6 now counts the founder wallet in the hedge base, which still backs no kUSD. That looks like exactly the change you said you wouldn't make.' He was right, and the reply took three days. The schema 6 entry above was written on 2026-07-25 and correctly recorded the broken commitment, but recording a defect is not the same as fixing it: the code went on publishing the wrong denominator for three more days while an accurate confession about it sat in the changelog. A protocol that documents a fault faster than it repairs one has only improved its paperwork. The flapping was also visible in Kerne's own published history for four days before an outsider had to point at it.",
      "what_did_not_change": "psm_solvency_ratio and aggregate_solvency_ratio, the canonical solvency read, on the pure PSM basis. The founder float has been excluded from every solvency ratio throughout, including during schemas 6 and 7: that narrower commitment was kept. The 5 percent delta tolerance is also untouched, and was untouched in schema 6. Neither the defect nor the fix moved a threshold; both moved the denominator, which is why the changelog records denominators."
    },
    {
      "schema_version": 9,
      "date": "2026-08-07",
      "identifier": "KRN-26-POR-SIGNER-VENUE-KEY",
      "summary": "The attestation signer becomes SEPARABLE from the live Hyperliquid venue key. A binding statement, signed by the venue key and countersigned by the attestation key, now travels inside the signed preimage, and the append-only registry of every binding ever issued is published at kerne.fi/api/por/signer-registry. Separability is the mechanism, not by itself the state: read signer_binding_state and compare attestation_signer against venue_account on any given payload to see whether the two keys are actually distinct yet.",
      "changes_measurement": false,
      "comparability": "comparable",
      "fields_added": [
        "attestation_signer",
        "venue_account",
        "signer_binding_state",
        "signer_binding",
        "signer_registry_version",
        "signer_registry_digest",
        "signer_registry_url"
      ],
      "fields_changed": [],
      "rationale": "Until this version the key that signed every hourly attestation was the same key that holds live trading margin on Hyperliquid and signs the protocol's on-chain transactions. A compromise of the trading key was therefore simultaneously a compromise of the attestation authority: whoever held it could publish signed, fully verifiable, entirely false solvency attestations. Kerne disclosed the narrow version of this itself, in Euler governance thread 1849 post 6: 'the attestation signing key is a live venue key.' Rotating the signer on its own would have removed the risk and destroyed the property that made the arrangement defensible, because attribution worked ONLY through signer address equalling venue account address, which any reader could confirm against the public clearinghouseState read without trusting Kerne at all. So the signed link is published first and the separation happens against it. The venue key signs a statement naming the attestation signer, the named signer countersigns to prove it holds the key, and the registry is signed as a WHOLE so that an attacker on the plaintext publisher-to-relay hop cannot serve a truthful subset with a revocation dropped.",
      "self_criticism": "This was committed as feat/por-signer-registry on 2026-07-25 and did not reach main until 2026-08-07, thirteen days later. For those thirteen days kerne.fi went on selling a synthetic dollar you can check yourself while the flagship check was signed by the account it was checking, and signer_registry_url, which this payload names as the place to see every binding, returned 404 in production. The limitation was disclosed on /legible and written up in docs/security/POR_SIGNER_SPLIT_STATUS_2026-07-30.md rather than hidden, and that is still not the same as repairing it: the criticism the schema 8 entry makes of schema 6 applies here to Kerne's own delivery. The version number is 9 and not the 7 the original design document names, because schemas 7 and 8 both landed while finished work sat unmerged.",
      "what_did_not_change": "Nothing about what is measured. No solvency basis, no denominator, no threshold and no status ladder was touched, so schema 8 and schema 9 readings are comparable on every field. psm_solvency_ratio and aggregate_solvency_ratio are computed exactly as they were at schema 8. This is pinned rather than promised: bot/tests/test_por_signer_binding.py holds thirteen canonical fields byte-identical across every binding state, so a future change in this area that moves a solvency number fails a test instead of shipping."
    }
  ],
  "measurement_breaks": [
    {
      "schema_version": 3,
      "date": "2026-05-23",
      "summary": "The aggregate liability became OUTSTANDING kUSD, that is total supply minus the kUSD the PSM contracts hold as inventory.",
      "measured_before": "Liability was kUSD.totalSupply(), which counted the protocol's own unissued PSM inventory as if it were a claim by a user.",
      "measured_after": "Liability is totalSupply() minus PSM-held kUSD, which is the amount users can actually present for redemption."
    },
    {
      "schema_version": 4,
      "date": "2026-06-12",
      "summary": "Headline restructure. aggregate_solvency_ratio now carries the PSM stablecoin backing ratio; the old vault-share basis moved to legacy_vault_share_solvency_ratio under its own name.",
      "measured_before": "aggregate_solvency_ratio was a vault-share ratio, which is not a statement about whether kUSD is backed.",
      "measured_after": "aggregate_solvency_ratio is psm_usdc_reserve / outstanding_kusd: every input an on-chain quantity a reader can recompute without us, in seven read calls on Base."
    },
    {
      "schema_version": 6,
      "date": "2026-07-23",
      "summary": "The net_delta DENOMINATOR changed from the attested vault's ETH-exposed leg alone to the declared hedge base, which is that leg plus the disclosed founder-custodied watch-only float. The published status went from WARNING_DELTA to SOLVENT.",
      "measured_before": "net_delta = abs(1 - short / vault_exposed_eth). The attested vault v2 holds no user deposits, so that denominator was 0.0, and the code's divide-by-zero branch hardcoded net_delta = 1.0. A correctly sized hedge therefore scored as fully directional.",
      "measured_after": "net_delta = abs(1 - short / (vault_exposed_eth + watch_only_eth)), the base the hedge engine actually sizes against and the same base /api/por and the daily report already used. At the live book that is 0.28 percent, inside the untouched 5 percent tolerance."
    },
    {
      "schema_version": 8,
      "date": "2026-07-28",
      "summary": "The net_delta DENOMINATOR is reverted to the attested vault's ETH-exposed leg alone. The founder-custodied float that schema 6 added is removed from it and demoted to its own disclosed_float_* fields with its own state. The published status returns to WARNING_DELTA and stays there until the hedge runs against collateral that actually backs kUSD.",
      "measured_before": "net_delta = abs(1 - short / (vault_exposed_eth + watch_only_eth)), where watch_only_eth is the native ETH plus WETH balance of a founder-custodied EOA that backs no kUSD. In force from 2026-07-24 00:16:36 UTC to 2026-07-28, schemas 6 and 7.",
      "measured_after": "net_delta = abs(1 - short / vault_exposed_eth). Protocol collateral only. This is the schema 5 denominator, so schema 8 readings are comparable with schema 5 and earlier on this field and are NOT comparable with schema 6 or 7. The float is still read and still published as disclosed_float_eth with its own delta and state, and it drives no status, no ratio and no solvency verdict."
    }
  ],
  "policy": {
    "rule": "Every change to what a published proof-of-reserves field measures gets an entry here, with the semantics before and after, on the same commit that ships the change. Adding a field is not a measurement change. Redefining a denominator is.",
    "append_only": "Historical entries are frozen and pinned by historical_digest. Editing one fails a test in both runtimes rather than passing silently.",
    "binding": "changelog_digest is inside the signed preimage of every hourly attestation from schema v7 onward, so this record cannot be revised without contradicting signatures already published.",
    "origin": "Created 2026-07-25 in response to Euler governance thread 1849 post 7, after a published metric changed 57 minutes after a public commitment not to change it. The entry for schema v6 records that incident rather than omitting it."
  },
  "verify": {
    "digest": "Canonicalize entries[] as JSON with sorted keys, no whitespace and ascii escaping, then sha256 it. That is changelog_digest.",
    "cli_cast": "curl -s https://kerne.fi/api/por/schema-changelog > cl.json\njq -cS .entries cl.json | tr -d \"\\n\" | sha256sum   # equals changelog_digest\ncurl -s https://kerne.fi/api/por/signed | jq -r .schema_changelog_digest",
    "note": "jq -cS sorts keys and compacts, which reproduces the canonical form for this document because every value in it is ascii."
  },
  "cross_links": {
    "signed_por": "https://kerne.fi/api/por/signed",
    "unsigned_live_por": "https://kerne.fi/api/por",
    "account_enumeration": "https://kerne.fi/api/por/accounts"
  }
}