← back to KPOP

KPOP — questions, and where it goes next

Working notes. The first half is what the app does today and why; the second half is a family of flows it does not do yet — the ones where custody itself moves — kept here so they have a home while the shape settles.

The app

What is a check?

A signature over a challenge that cannot be a transaction. Every challenge starts with the bytes KPOP1 — the first byte, read as a protobuf tag, is field 9 with a wire type no Hedera decoder accepts — followed by 16 random bytes. Signing one proves the key is available and can move nothing. KSIGN shows it as undecodable body — verify checksum out of band, which is correct.

Why four states and not three?

Current, due soon, overdue, unconfirmed. Overdue is not lost — a key that has not answered for a month still exists; there is just less evidence it is available. Unconfirmed is where consequences live: the key is treated as unavailable for planning. The app never records "lost"; it records "possession not demonstrated within policy". That wording matters once anything automatic depends on it.

What sets the policy?

The key's authority — how consequential it is where it is used. The check falls somewhere in the last part of each cycle, picked from a hash of the key and its cycle, so it is stable but not readable off a calendar. Nothing is checked more often than fortnightly: weekly was judged too intense for any key.

AuthorityCadenceWindowAnswer withinUnconfirmed afterExtra
Practicemonthlylast 7 days48 h30 days overdue—
Lowannuallast 60 days72 h60 days—
Mediumquarterlylast 21 days48 h30 days—
Highmonthlylast 7 days24 h14 daysrandom day
Criticalfortnightlylast 4 days4 h7 daysrandom day, biometric

What does the storage grade mean?

A number out of 100 and a letter, from the storage questionnaire on the key card, meant to read like a password-strength meter. It starts at 100 and loses points for each finding, in three sections each with a cap so one bad section cannot zero the whole thing:

SectionUp toWhat costs
Copies50no copy recorded at all (40); no offline copy (30); a single copy (10); each digital or fragile copy by its kind (a cloud copy 40, a photo 35, an online file 30, a password manager 15); an unencrypted digital copy (10); a copy an organisation can reach (10) or nobody is sure who can (20); a copy nobody is sure where it is (15)
History40each "yes" to the secret's past — in a cloud or a message (30), typed into an untrusted site (25), on a connected device or photographed (20), still possibly on that device (15), shown on a visible screen or printed on a shared printer (10); each question left unanswered (3)
Origin20created by someone else (20); made on a connected device (10); origin unknown (10); not sure every copy is accounted for (25, or 5 if merely unconfirmed)

Letters: A 85 and above, B 70, C 55, D 40, F below 40. Below 55, or any cloud, message or untrusted-site exposure, the card suggests rotating. The card's "Storage grade F — 10 of 100. Lost to:" block lists exactly which findings took the points, biggest first.

What are a key's "copies"?

A key is usually held as more than one copy of the same secret: a sealed envelope in a safe, the same words in a wallet on a phone, a second envelope with someone else. The card lists each copy as one line — a custodian (a person, a place, a vault reference; the same names the fragments use, offered back as a dropdown) and free-text notes on how that copy manifests: "sealed envelope", "HashPack", "paper, unsealed, in the desk", "metal plate". Sealed matters: a sealed copy can be inspected now and then and seen never to have been opened, which an unsealed one cannot claim. Add as many lines as copies were made — when minting, that is the number KGEN printed. Removing a line asks first, because a copy you cannot account for is exactly what the list is there to catch; two lines with the same custodian and notes is a mistake, say which is which. The earlier tick-boxes (every place the secret exists, what unlocks it, hardware-backed and attested) were dropped on 2026-09-16: they could say what a copy was but never where it was. The storage questionnaire still grades copies by class.

Do fragments work the same way?

Yes, since 2026-09-16 they are the same list, edited the same way: a line per copy, two fields saved when you click away, + copy to add one and ✕ to remove one after a confirm. A fragment keeps one thing a key does not — each copy is marked sealed or opened, and the chip toggles it, because a sealed copy that has never been opened is a stronger claim than a note saying so. A fragment's column is where rather than custodian, but the names come from the same pool, so a place you have already used is offered back on either.

What does "exposed" on a master key mean?

A key with salted children on the accounts list is a master, and the whole point of salting was that the master's public key never appears on chain — anyone holding it can enumerate the children by trying account numbers as salts. If the mirror node finds the master itself on an account, or it sits on a listed account as itself, that linkage has been given away. It is a privacy loss, not a key compromise, but it is the privacy the children were bought for, so the card says so and offers it as a reason to rotate.

What does KPOP hold?

Public keys, names, custody notes, receipts. No seeds, no private keys, nothing that can sign. All of it in this browser's storage; Back up hands it to you as one line. Places in the storage questionnaire are classes (home, safe, bank), never addresses.

Why did my key vanish when I switched the toggle?

Because it is declared for the other network. The toggle filters: on mainnet you see keys declared mainnet, keys the mirror node found on mainnet, and keys not declared at all. A key declared testnet only shows on testnet — unless it is in conflict, in which case it shows everywhere, loudly.

What is the network rule?

One key, one network — never both. A key declared for one network but found in use on the other, or found on both, is a broken invariant. It is flagged on every view whichever network is selected, and the fix is to rotate it out of one side.

Look up accounts asks both mirror nodes every time, precisely so a key cannot hide on the network you are not looking at. It is the one network call KPOP makes, and only when pressed.

How does KPOP know a key is a salted child of one of mine?

It cannot see it on chain — a child leaves no link to its master, which is the point. What it can do is work forwards: KSIG-SALT-v1 is additive on ed25519, so the child's public key follows from the master's public key and the salt, with no secret involved. KSUB salts each account's key with the account number, so for every ed25519 key in the ledger and every account on the Accounts tab, KPOP derives child(master, number) and compares it to the account's key leaves. A hit is shown as salted child, salt N. An account whose keys were salted with something else is pasted as 0.0.N(salt), KSUB's notation; the salt is kept on the account and tried as well as the number, so a master that arrives later is still matched. That is why the Accounts tab matters: without a candidate list of accounts there is nothing to test against, short of walking every account on the network.

And a hardened child?

Cannot be found that way, by design. A hardened derivation hashes the master's private key into each child, so the master public key says nothing about them, and a child says nothing about its siblings or the master. Two consequences worth holding onto:

Non-hardened has the opposite trade: anyone holding the master public key can link every child by enumerating salts (privacy), and a child's secret plus the master public key recovers the master (the BIP-32 leak). KSIGN treats the master public key as a secret for exactly that reason.

Why do I get an old version after a deploy?

The app keeps a copy of itself so it opens with no network. A new build is picked up on the next visit and a banner offers it; Get a fresh copy on About forces it. Neither touches your keys. An incognito window always shows the live build.

Rotation

Rotation keeps custody where it is and changes the key. That is KPOP's home ground, and the reason categories on the questionnaire are the reasons you rotate:

WhyUrgencyTypically
Leak or suspected exposureurgentanything on the storage questionnaire's history list answered "yes"
On a break-glass keyurgenta single device holds it — temporary by design, see below
On an interim 1-of-1—safe, but not the policy the asset deserves
Storage grade too low—sloppy custody: copies unaccounted for, digital copies, unknown access
Test key—printed to kick the tyres; would not survive as a mainnet key
Policy or asset value changed—the thing it protects grew; the key needs more cover than one signer
Custody moving to another party—not really a rotation — a transfer, below
Routine—hygiene
If there has actually been a leak you will not be filling in a form. Break-glass is a rehearsed process with its own tooling (KSUB raising the updates in bulk, KSIGN signing). KPOP's job in that moment is the ledger: which keys are on the temporary key now, and what still needs tidying afterwards.

Transitions — where custody moves

Rotation is one family. The other is where the arrangement changes: who holds the key, on what, under what policy. These are workflows with steps, not a flag on a card. KPOP does not run them today; this is the list, so they are not lost.

The break-glass flow

Three transitions, in order, each a real rotation:

Leak event → break-glassRapid. Every affected account rotated to a temporary key as fast as possible. The break-glass device is one place, holding everything: secure, and a single point of failure.
Break-glass → interim offline 1-of-1Once the incident is wrapped up. Takes the keys off the break-glass device so nothing depends on it. Still one signer, but offline and not the emergency kit.
Interim → policyBack to whatever the asset's proper arrangement is: the threshold, the keyholders, the cadence. The emergency is over when this lands.

A key's current stage on this path — break-glass, interim, policy — is a fact worth recording per key. Today the closest thing is the rotation reason; a first-class stage is the obvious next field.

The others

ScenarioWhat changesNotes
UpliftAsset value rose; policy tightensa single key becomes a threshold; new keyholders join; cadence shortens. Reverse it when an asset is retired.
OnboardingWallet-made key → managed policythe wallet key becomes the interim; the storage questionnaire is the entry gate
Hand-overCustody to a third partyyou rotate them in, they rotate you out. Two ledgers, one receipt trail.
SaleAssets and keys change togethera batch: swap the assets and update the keys atomically, so no moment exists where one side has both
StructuralA keyholder leaves a thresholdthe natural end of Unconfirmed: the group rotates the absent key out; the absentee sees it on their own ledger when they wake up
Network hygieneA key found on both networksrotate it out of one side — the only fix for the rule above

Does this belong in KPOP?

Partly. KPOP is the ledger and the flag: which stage each key is at, which are marked, what the receipts say. Executing a transition — raising the account updates, collecting signatures, submitting — is KSUB and KSIGN's, and should stay there. The seam is a plan: a named flow (break-glass, uplift, hand-over) with its steps, attached to a set of keys, that KPOP tracks and KSUB carries out. That is a tab's worth of work, and the right time for it is after the stage field and the reason categories have been used for real.

Growing the accounts list: crawling

The accounts you care about are connected on chain — one testnet portal account spawns the rest. So rather than pasting hundreds of ids, pick an account and a category of relation, see the candidates, and choose which to add. Each added account's note records how it got here (created by 0.0.1532, crawl) — a default you can edit, not a locked field. Categories, each one mirror-node query:

CategoryQueryGuard
Accounts it createdtransactions by this payer, type CRYPTOCREATEACCOUNT → the entity idsbounded by the payer's own history; the safest crawl
Accounts it sent toCRYPTOTRANSFER where it is a debit; the credited accountscan explode on an exchange or a faucet — cap and confirm
Accounts that sent to itthe credits into itspam airdrops make this the noisiest; never auto-add
Same operatorother accounts whose creating payer was the same accountone hop only
Token treasury / token holderstokens it is treasury of; accounts holding those tokensholders can be millions — show the count first, add only on selection
Same key/accounts?account.publickey= for each of its leavesalready what Look up accounts on a key does

Every crawl is one hop, shows its results as a list with a count before anything is added, and adds nothing without a selection. The one hop that matters most — accounts it created — is also the one that cannot run away, so it is the one to build first.

Open questions

← back to KPOP