A Domino Compass recipe turns deterministic physical entropy into reproducible identity and Bitcoin key hierarchies β without trusting a cloud account, custodial wallet, hosted password database, or opaque recovery service.
The recipe does not contain the secret. The physical card is the root of authority.
Domino Compass is a deterministic secret-generation and key-runtime system. It is not a seed-phrase generator, a wallet, a password manager, or a key vault β it is the thing that produces those from physical reality.
An 8Γ7 domino card β two passes of all 28 tiles β is the source. It is read, canonicalized, and hashed. Nothing else is the root.
A recipe is an explicit deterministic program: which ceremony, which ordering, which normalization, which lane. It is not the secret.
From one root, domain-separated derivation produces an identity lane and a Bitcoin lane as siblings β never one as the child of the other.
Capabilities, descriptors, and encrypted operational state can be rotated, revoked, and persisted β without ever exposing the root.
The domino set is a finite, observable physical system. Its state β the ordered arrangement and orientation of 28 tiles across two passes β is the entropy source. The physical object is not magic; the deterministic encoding rules are what make it reproducible.
The compass is the navigation metaphor: from the root, a recipe steers through a derivation space to reach specific keys. Doubles carry a compass quadrant (NE/SE/SW/NW) β 2 bits of entropy each β because the quadrant is an independent, observable post-spin state.
The physical object is not magic. The deterministic encoding rules are what allow reproducibility.
There are two distinct things, and the site keeps them separate:
| Random physical entropy | Deterministically encoded physical state | |
|---|---|---|
| What it is | The unpredictable outcome of a physical process (a shuffle, a spin, a toss). | The recorded state of that outcome, written down under fixed rules so it can be reproduced exactly. |
| Role | Supplies the uncertainty. | Makes the uncertainty reproducible β the same state always yields the same bytes. |
| Example | Shuffling 28 dominoes into a random order. | Reading that order as 56 canonical tokens, in a fixed pass structure, with doubles carrying a compass quadrant. |
For the Domino Compass ceremony specifically:
One pass of 28 tiles contributes:
Two independent passes:
265.89 > 256 β two full sortitions exceed the 256-bit target. This is why the ceremony requires exactly two passes.
56 Γ log2(70) β 343 bits. This is wrong: each pass uses every tile exactly once (a permutation, not independent draws), and the canonical byte encoding is a bijection onto the true sample space (28!Β·2Β²ΒΉΒ·4β·)Β².| Material | Status | Why |
|---|---|---|
| The 8Γ7 domino card / transcript / canonical bytes | SECRET | It is the root. Anyone with it can regenerate every key. |
| The recipe | GRADED | Not root-equivalent, but reveals purpose, scope, lane context, and the commitment. Protect it. |
| Public fingerprints | PUBLIC | Verification handles. They prove regeneration without revealing the secret. |
| Capability records | PUBLIC | Delegation statements. They can be shared with service peers. |
| Watch-only descriptors / xpub | PUBLIC | Track funds without signing authority. |
A recipe is an explicit deterministic program β a transformation description β not vague "instructions." It describes how physical material becomes deterministic entropy and which lanes to derive.
The recipe is a versioned structured object. Its canonical serialization hashes to its identifier:
The recipe must not contain S_root, the canonical transcript bytes, or any value from which S_root is recoverable. It may be backed up or stored without necessarily revealing the root secret.
| Field | Meaning |
|---|---|
recipe_version | e.g. dc-recipe-v1 |
ceremony_profile | which physical ceremony, e.g. dc-v1-8x7 |
domain_tag | high-level namespace, e.g. pluronymous |
entropy_card_commitment | non-revealing commitment to the physical card |
purpose | Nostr identity, Kapnet actor, service-peer access, trustee recovery, decoy⦠|
scope | read-only, sign events, publish to channel, spend up to limit⦠|
service_namespace | which service the key is for |
actor_namespace | which actor / identity |
identity_lane | Nostr, Kapnet, KNU, Pluronymous, delegation, recovery, revocation |
bitcoin_lane | key paths, descriptors, watch-only, payment, claim, recovery, decoy |
time_authorization | wall-clock and/or Bitcoin-native |
revocation_lane | which revocation path applies |
child_index | per-recipe child index |
network | mainnet / testnet / regtest / KNU |
output_type | nsec, private key, BIP-39, BIP-85 child, descriptor⦠|
checksum | integrity of the recipe itself |
signature | recipe signature by an authority |
The commitment is a one-way hash that is not equal to S_root and does not reveal it:
The domain tag "dc-commit-v1" makes the commitment input different from the KDF input (canonical_transcript_bytes alone), so the commitment is a distinct hash. An attacker who obtains the recipe gets a one-way hash of the transcript, not the root secret. The commitment is used for verification and binding, never as a derivation input.
The recipe must be signed by an authority, and the signature must be over the canonical recipe bytes. A recipe without a valid signature from a trusted authority must be rejected β otherwise an attacker could substitute a malicious recipe with bitcoin_lane: spend-capable for a watch-only recipe, and the user would derive spend keys they never intended.
Build a recipe and inspect its exact serialized form. The builder shows the canonical JSON and the resulting recipe_id.
entropy_card_commitment is filled from the current transcript in the simulator. Changing any field changes recipe_id β and therefore every derived key.From the root secret, a domain-separated runtime derives parallel, independent key lanes. The Bitcoin tree is a sibling of the identity key β never a child.
S_root = SHA-256(canonical_transcript_bytes) is the ceremony root and is unchanged. HKDF is a post-root lane expander, not the root derivation. It never replaces S_root; it domain-separates it into per-lane seeds. Because the derivation transcript binds lane_tag, each lane produces a distinct lane seed and therefore a distinct BIP32 master. Identity and Bitcoin are sibling domains under S_root β not sibling children of a single master.Two derivations are distinct if any bound field differs:
identity vs bitcoin lanes use different lane_tag values, so the same recipe yields distinct keys per lane.recipe_id salt) yield distinct keys even for the same lane.child_index values yield distinct keys.scope) changes the transcript bytes and therefore the derived secret.The info input to HKDF is a length-delimited binary transcript. Each field is serialized as 1-byte tag || 2-byte big-endian length || field bytes, in a fixed order. No field may be omitted, reordered, or padded.
Root Secret branches into sibling runtime lanes β parallel domain-separated derivations, not one lane as the child of the other.
Each lane has its own BIP32 master from its own lane seed. Changing the derivation profile (e.g. BIP-86 vs BIP-84) visibly produces a different subtree.
Identity and Bitcoin keys originate from the same deterministic root while remaining cryptographically domain separated.
Explicitly:
This is a core Domino Compass property. The two lanes are derived from the same root secret via domain-separated HKDF, each producing its own lane seed and its own BIP32 master β sibling domains under S_root, never one as the child of the other.
If the Bitcoin tree were a child of the identity key, then identity compromise would equal funds compromise. Because each lane derives its own BIP32 master from its own lane seed (both under S_root), a leaked identity key does not reveal the Bitcoin lane β and a leaked identity master does not reveal the Bitcoin master either. The separation is stronger than sibling children of a single master: the two lanes share only S_root and the recipe, never a master or a chain code.
The Bitcoin lane is not a single spend capability; it is a namespace whose spend posture is set by the profile:
| Posture | Meaning |
|---|---|
spend-capable | the lane derives spend keys |
watch-only | the lane derives descriptors / xpub only, no private spend keys |
claim-only | the lane derives claim keys for a specific claim |
service-payment-only | the lane derives payment keys for a specific service |
recovery-only | the lane derives recovery-branch keys |
decoy | the lane derives decoy keys |
A spend-capable lane is an explicit, deliberate choice, never the default.
You should not need to expose or repeatedly use your root key. Capabilities express operational access as scoped, time-bounded, revocable delegation statements.
| Field | Meaning |
|---|---|
capability_id | content hash of the record |
issuer_public_key | who issued (the authority) |
derived_public_key | the key being delegated |
purpose | what it is for |
scope | what it may do |
valid_from / valid_until | time bounds |
block_context_limits | Bitcoin-native bounds |
service_namespace | which service honors it |
revocation_lane | which revocation path applies |
recipe_id | which recipe produced it |
entropy_card_fingerprint | the commitment |
signature | bare secp256k1 by the issuer |
A signed capability is a claim, not a grant. Access is granted by the service's admission decision (its accepted-key set). The lifecycle:
A capability that is signed but never admitted is not valid.
Cryptographic authorization without forcing the user to manually administer raw cryptographic keys.
Time-scoped authorization, with a clear distinction between secret derivation and authorization policy.
valid_for_single_session
valid_until_timestamp
valid_until_block_height
valid_until_next_knot
valid_for_pwbt_window
valid_until_parent_rotation
The root secret does not change merely because a capability expires. Expiration is a property of the capability record (an authorization policy), not of the derived key or the root. When a capability expires, the same root can issue a new capability β the underlying key material is unchanged.
Revocation is not deletion of a copied secret. Revocation is refusal to honor the secret after a revocation condition.
When Capability B is compromised, you revoke B β without requiring Root compromise. You preserve the root and all unrelated derivations.
Capability D and Application E are unaffected. The root is untouched.
Revocation is honored only at acceptance boundaries that check revocation state. It is not honored by:
revocation_lane must be bound to a distinct revocation authority at issuance β a key that is not the capability issuer and that the issuer does not control. A capability whose revocation lane is self-declared must be rejected.You lose the laptop, phone, application database, and operational keys β but you retain the physical entropy material and the recipe. Recovery reconstructs authority.
Recovery reconstructs the root and the runtimes β the authority. It does not necessarily recover every historical operational key. Where appropriate, operational state may instead be restored from encrypted backup material (e.g. the dStor keychain).
S_root, both lane masters, and every downstream key. Holding only a BIP85 child seed reveals nothing about the Domino Compass root or the lane masters β that is a deliberate separation property.Generate a printable recovery checklist describing what physical material must be retained, which recipe identifier applies, which derivation profile/version applies, and what public fingerprints should be expected. It does not include secrets.
The optional Domino Compass + dStor architecture. dStor stores encrypted operational material β never root custody.
dStor stores encrypted operational material. The user retains root authority.
The cloud keychain must not be portrayed as holding custody of the root secret.
nsec in dStor.The keychain snapshot is content-addressed, manifest-backed, encrypted, and independently verifiable:
The manifest root is signed by the air-gapped authority (authenticity, not just integrity). Encryption is a deterministic AEAD (SIV-style, scheme dc-keychain-aead-v1): the IV is derived from the plaintext (iv = SHA-256(plaintext)[:16]), the keystream is HMAC-SHA256 counter blocks, and an HMAC-SHA256 tag authenticates iv || ciphertext. Because the IV is a function of the plaintext, re-encrypting the same plaintext yields the same ciphertext β so the content address is stable without ordinary nonce reuse. This is a misuse-resistant construction: the IV cannot be reused across different plaintexts, which is what breaks naive CTR. The exact scheme and version are bound in the manifest.
The online machine asks. The air-gapped signer authorizes. The cloud keychain obeys only signed instructions.
The secure dStor keychain workflow is the sealed round trip β both the outgoing encrypted TXXM and the incoming dStor response are sealed inside the same Tails amnesiac environment.
In strong mode, the Tails sealed round trip is the only acceptable way to operate the dStor keychain. The full sequence:
Allowed exports: encrypted TXXM blob, encrypted dStor response packet, content-addressed dStor manifest, signed receipt, public fingerprint, capability public record, revocation public record, watch-only descriptor, verification checksum, audit hash.
Disallowed unless explicitly intended: plaintext TXXM, plaintext nsec, plaintext recipe transcript, plaintext recovery packet, plaintext delegated secret, plaintext dStor response, unencrypted keychain snapshot.
The sealed round-trip derives the root inside Tails and connects to dStor from that same environment β the root is handled in a networked environment during the round-trip. For the highest-sensitivity operations, the air-gapped signer signs the request offline; the Tails session only handles the encrypted artifacts and the network round-trip, never the root in a form that can be exfiltrated.
No "military-grade security," no "unhackable." Here are the assumptions and failure modes, honestly stated.
S_root = SHA-256(canonical_transcript_bytes) is the root of all derivationFor each threat: what is exposed, what remains safe, what must be rotated, what must be reconstructed.
| Threat | What is exposed | What remains safe | What you must rotate / reconstruct |
|---|---|---|---|
| Compromised browser | Anything rendered in it | Root (if never entered online) | Rotate operational keys; reconstruct from card offline |
| Compromised OS | Local plaintext state | Root (if air-gapped) | Rotate operational keys; rebuild environment |
| Compromised cloud storage | Encrypted operational material | Root (never stored there); decryption key (user-only) | Nothing if encryption holds; rotate if decryption key leaked |
| Leaked recipe | Purpose, scope, lane context, commitment | Root secret (commitment is computationally hiding, not absolute) | Reconstruct a new recipe; re-derive lanes |
| Leaked capability | That capability's scope | Root, other capabilities | Revoke the capability; issue a replacement |
| Stolen entropy cards | The root | Nothing β this is the root | Reconstruct a new physical card; migrate everything |
| Partial physical entropy disclosure | Some of the transcript | Remaining entropy (search space shrinks) | Reconstruct a new card if disclosure is material |
| Poor entropy construction | Reduced search space | β | Reconstruct with a proper ceremony |
| Compromised operational key | That key's scope | Root, other lanes | Revoke; rotate the operational key |
| Compromised root key | Everything | Nothing | Reconstruct a new physical card; migrate everything |
| Metadata leakage | Who/what/when of operations | Key material | Reduce metadata; rotate affected capabilities |
| Deterministic encoding ambiguity | Potential wrong-key derivation | β | Verify fingerprints; use canonical encoding |
| Implementation bugs | Depends on the bug | β | Use the audited reference; verify against test vectors |
In the current DKR model, the secret is the root: S_root = SHA-256(canonical_transcript_bytes). It is the physical entropy commitment and the root of all derivation. The recipe and the derivation transcript are context for domain-separated HKDF β they do not carry the secret.
S_root or anything from which it is recoverable.An educational browser-based simulator. It runs the real Domino Compass math in your browser β nothing is sent anywhere.
Paste an 8Γ7 Domino Compass transcript (two passes of 28 tiles), or load the sample. Rows 1β4 = pass 1, rows 5β8 = pass 2. Each pass uses all 28 tiles exactly once. Doubles carry a compass quadrant (NE/SE/SW/NW).
A dedicated reproducibility tool. Enter an example recipe and entropy, and the page outputs the root commitment, transcript hash, identity fingerprint, Bitcoin fingerprint, and capability fingerprint. Reload the page and reproduce the same outputs.
Official Domino Compass test vectors β valid, invalid, boundary, versioning, and domain-separation cases. Downloadable as JSON.
This is the older ceremony/export mechanism: the physical transcript is hashed to a secret S, split into a nine-level hardened BIP32 path, and exported via BIP85 (BIP39 / WIF / xprv). It is not the current DKR derivation model β it is retained here only as the historical ceremony/export profile. The current DKR model (below) derives lane masters via domain-separated HKDF instead.
The coherent modern DKR vector: recipe ID, card commitment, separate identity/Bitcoin lane seeds, pubkeys, and fingerprints. This is the model the rest of the site teaches.
| Category | What it covers |
|---|---|
| Valid cases | Correct transcripts and recipes producing expected outputs |
| Invalid cases | Malformed tokens, wrong token counts, bare doubles without a quadrant |
| Boundary cases | Edge token values, minimum/maximum indices |
| Versioning cases | Different recipe/derivation/encoding versions producing different results |
| Domain-separation cases | Identity vs Bitcoin lanes, different child indices, different scopes |
The derivation transcript at the byte level β protocol documentation, not ordinary web copy. Expand and collapse every derivation stage.
Each field is serialized as 1-byte tag || 2-byte big-endian length || field bytes, in fixed order.
Fingerprints are verification handles. They prove regeneration succeeded without exposing the secret.
| Fingerprint | Formula | Proves | Does not reveal |
|---|---|---|---|
| Root commitment | SHA-256(transcript || "dc-commit-v1") | You hold the same physical card | The root secret |
| Identity fingerprint | SHA-256(id_pubkey || recipe_id || "identity") | Regeneration of the identity key | The identity private key |
| Bitcoin fingerprint | SHA-256(btc_pubkey || recipe_id || "bitcoin") | Regeneration of the Bitcoin key | The Bitcoin private key |
| Capability fingerprint | content hash of the capability record | The capability is intact and signed | Any private material |
| Descriptor fingerprint | hash of the descriptor | The descriptor is intact | Signing authority |
nsec itself never needs to be printed, cloud-stored, screenshotted, or placed in a persistent password manager.Paste a public fingerprint or capability record and verify format validity, version, checksum, public identity, scope, expiration, and derivation profile identifier. The verifier requires no private material.
Bitcoin public material can be separated from signing material. Watch-only systems track funds without possessing signing authority.
Watch-only wallets can track funds without possessing signing authority. The signing keys stay under the user's physical control; only public material (xpub, descriptors) is shared with the watch-only surface.
A Nostr-oriented example: the nsec can be regenerated from the deterministic root rather than permanently stored online.
The nsec is a downstream artifact of the identity lane. It can be regenerated from the deterministic root whenever needed β it does not need to be permanently stored online.
m/220'/0'/0', unregistered private placeholder). It is not a standard BIP path β it is Domino-Compass-native.The system as independent layers β never melded.
Domino Compass is an authority and key-generation substrate that can interact with Kapnet applications. It does not depend on Kapnet β it remains usable independently.
Kapnet actors can have deterministic Nostr identity, Kapnet actor key, service-peer key, recovery key, decoy identity, Bitcoin path namespace, and KSP payment lane β without storing root secret material digitally.
Deterministic cryptographic systems require strict versioning. Changing any versioned component may deliberately produce a different derivation result.
Changing any versioned component may deliberately produce a different derivation result. The system must not silently reinterpret older recipes.
Strict vocabulary. The distinctions below are load-bearing.
| Term | Definition |
|---|---|
| Recipe | Deterministic derivation grammar + identifier. β secret. |
| Root secret (S_root) | SHA-256(canonical_transcript_bytes). The root of all derivation. |
| Root commitment | SHA-256(transcript || "dc-commit-v1"). β root secret. Non-revealing. |
| Fingerprint | Post-derivation verification handle. β key. |
| Identity key | Nostr / Kapnet / service key. β Bitcoin key. |
| Bitcoin key | BIP-86/84 derived key. β identity key. |
| Capability | Scoped, time-bounded, revocable delegation statement. β root authority. |
| Encrypted cloud keychain | Encrypted operational material in dStor. β custody. |
| Physical entropy | The unpredictable physical outcome. β recipe. |
| Recovery | Reconstructing authority from physical material + recipe. β backup file restoration. |
The normative specification, reference implementation, and developer resources.
| Artifact | Path |
|---|---|
| BIP draft (normative spec) | BIP-draft.md |
| Canonical transcript encoding spec | docs/transcript-encoding.md |
| Runtime spec (DC-RUNTIME v0.2) | runtime-spec.md |
| Derivation encoding spec | docs/derivation-encoding.md |
| Entropy & security analysis | docs/security-analysis.md |
| Reference implementation (pure stdlib) | ref/domino_compass.py |
| Runtime reference implementation | ref/dc_runtime.py |
| Capability + revocation schema | ref/dc_capability.py |
| dStor keychain manifest schema | ref/dc_keychain.py |
| Tails sealed round-trip | ref/tails_round_trip.py |
| Test vectors | ref/vectors.json, ref/runtime-vectors.json |
| Decision | Default used |
|---|---|
| KDF profile | HKDF-SHA256 (RFC 5869), post-root lane expander |
| Derivation codec | length-delimited binary |
| Commitment | SHA-256(transcript || "dc-commit-v1") |
| Identity lane | m/220'/0'/0' (DC purpose 220, unregistered private placeholder) |
| Bitcoin lane | BIP-86 m/86'/0'/0'/0/0 (P2TR) default; BIP-84 m/84'/0'/0'/0/0 (P2WPKH) interop profile |
The long-term runtime is installable or downloadable for offline use.
The public website explains this separation: documentation and simulation are distinct from a hardened production runtime. If production secret generation is eventually supported in-browser, it is a separate hardened application surface with explicit security assumptions. The marketing site must not silently become a wallet.
What the initial website does not do.
Privacy-preserving analytics or none. Never log secrets.
This site defaults toward privacy-preserving analytics or no analytics. It never logs:
Telemetry boundaries are documented. All cryptography runs locally in your browser β nothing is sent anywhere.
All derivation diagrams have textual equivalents.
Cryptographic information never depends exclusively on color. Every diagram has a text equivalent.
Mobile supports understanding and verification. Complex derivation editing progressively moves to desktop.
Public and encrypted artifacts can be encoded as QR where appropriate.
Site search indexes protocol terms and immediately resolves concepts.