OC Me · Federation custody
me.ochk.io is built to be federation-custodied by default, with a self-custody
graduation flow on demand. This page is the user-facing explanation; the
protocol-level contract is at
oc-attest-protocol/FEDERATION-CUSTODY.md
(v1.2-draft-1, additive extension).
Honest current state. The non-custodial audit (
NON_CUSTODIAL_AUDIT.md) is the load-bearing reference for what is actually wired today. Read it before integrating against the federation surface — the descriptor schema below is a forward-looking contract, not a description of running guardians. The two paths that DO exist today are: BIP-322 (you sign in directly with your Bitcoin wallet, OC never holds keys) and email-OTP (a federation client scaffold is wired inoc-me-web/src/lib/fedimint, but Lightning send/receive and the graduation withdraw envelope are not yet shipped). Custodial state for email-OTP users today is NOT a running guardian set — it is a state machine that refuses to fabricate one.
What "federation-custodied" means
Your me.ochk.io identity is bound to a Bitcoin address (BIP-322 path) or a federation-issued ecash note set (email-OTP path). For the federation path, the private key that controls the underlying on-chain UTXOs is held collectively by an M-of-N guardian set — no single guardian (and not OC the company) can spend or freeze. Recovery is by re-proving your email, not by remembering twelve words.
When you sign in, the federation guardians threshold-sign on your behalf. You don't see this. You never need to.
The three options at threshold
| signing_method | how it works | live today? | |
|---|---|---|---|
| federation custody (default) | fedimint_threshold | guardians collectively hold the key. recovery by re-proving email. | client scaffold + state machine wired; production federation invite pending. |
| fedimint client | fedimint_threshold (different federation) | sweep to a fedimint federation you trust more (your community's, your country's, your own). | once (1) is live; depends on graduation envelope. |
| self-custody | bip-322 | sweep to any BIP-322-capable Bitcoin wallet (UniSat, Xverse, Leather, Alby, Sparrow, hardware wallet). only you can sign. | sign-in is live (in-place, no redirect); explicit graduation envelope is in build. |
You can return to federation custody at any point — the protocol accommodates the round-trip via attestation re-issuance under the new custody descriptor.
Graduation envelope
Per the v1.2-draft-1 oc-attest extension, graduation publishes an envelope carrying both an M-of-N guardian quorum sig (federation releases custody) and a self-key sig (you prove you hold the key now). The envelope is anchored to a bitcoin block via OpenTimestamps so any verifier can confirm graduation happened at a specific time.
{
"v": 1,
"kind": "orangecheck-graduation",
"address": "bc1q...",
"from_federation": "fed:abc123…",
"to": "single-key",
"graduated_at": "2026-04-30T20:00:00Z",
"proof": [
{ "address": "bc1qg1…", "sig": "..." },
{ "address": "bc1qg2…", "sig": "..." },
{ "address": "bc1qg3…", "sig": "..." },
{ "address": "bc1q...", "sig": "...", "kind": "self-key" }
]
}
| Field | Rule |
|---|---|
from_federation | Content hash of the federation custody descriptor releasing the address. |
to | "single-key" (graduating to BIP-322) or "federation" (re-binding to a new descriptor). |
proof | M signatures from M of N declared guardians PLUS one self-key signature. |
graduated_at | ISO-8601 timestamp; the OTS proof anchors this to a Bitcoin block. |
The envelope contract is finalized at the spec level and reflected in the
/me/graduate UI. The producing path (quorum
sig collection from a real federation) is the integration the
production-federation invite unlocks.
Guardian descriptor
A federation custody descriptor is a content-addressed canonical JSON object — same shape as oc-agent-protocol's federation principal, re-purposed for custody:
{
"v": 1,
"kind": "attest-federation-custody",
"address": "bc1q…",
"threshold": "3-of-5",
"guardians": [
{ "address": "bc1qg1…", "alg": "bip322", "name": "alice" },
{ "address": "bc1qg2…", "alg": "bip322", "name": "bob" },
{ "address": "bc1qg3…", "alg": "bip322", "name": "carol" },
{ "address": "bc1qg4…", "alg": "bip322", "name": "dave" },
{ "address": "bc1qg5…", "alg": "bip322", "name": "erin" }
],
"implementation": {
"kind": "fedimint",
"federation_id": "fed11qgqzcq…",
"version": "0.4"
}
}
The descriptor id is fed: + lowercase hex
SHA-256(canonical_descriptor_bytes).
What stays the same when you graduate
| Stays the same | Changes |
|---|---|
| Your bitcoin address (the canonical identifier) | The signing method (fedimint_threshold → bip-322) |
Your attest tier (anonymous / bonded / kyc-light / kyc-strong) | Who holds the private key (you, instead of the federation) |
| Your /me/earn history, connected sites, agent delegations | How recovery works (you own backup; lose the key, lose the funds) |
| Your sat-earning rate | The shape of signing_method in attestation envelopes |
Guardian rotation
Guardian rotation produces a new descriptor with a new id. Old attestations remain verifiable against the old descriptor; new attestations bind to the new descriptor. Rotation envelopes are authenticated by M-of-N signatures from the old descriptor and OTS-anchored so any verifier can resolve the active descriptor at any historical instant.
Reading further
oc-attest-protocol/FEDERATION-CUSTODY.md— full v1.2-draft-1 specoc-agent-protocol/FEDERATION.md— sibling federation principal extension for delegationsoc-me-web/NON_CUSTODIAL_AUDIT.md— the in-tree audit · what's actually wired today vs the contract above- me.ochk.io/custody — product expression of this contract with live status pills per state
- me.ochk.io/security — the OC_STORES table, disappearance scenarios, recovery matrix per signin path
- me.ochk.io/me/graduate — the graduation flow