Skip to main content

Privacy data map

Status: Built, runs on simulatorStatus: Coming soon

The backend data map separates public chain records, server-held material and material intended only for a reader’s device.

Limits of this map

Payment amounts are public onchain in this version. The report verifier sees the attested income figure and prior opening briefly in memory. Private payouts are coming soon. This inventory describes the pinned backend design and its local implementation; it does not establish a production deployment or a completed independent audit.

Tier-one exception: a series using the onchain income router exposes routed income, its threshold and rate per unit onchain. The backend rows about device-only income and encrypted terms do not hide those public router fields. See who sees what for that separate chain path.

Reading the map​

“Vault” means server-key encryption. “e2e” means client encryption for the addressed attestor; the server holds ciphertext. These are different trust boundaries. Admin access to ciphertext is not a decryption key. The upstream document’s owner, issuer, holder, backer, attestor, admin and public labels identify readers.

Retention is not implemented as a deletion promise. The source says time limits remain undecided and nothing is deleted automatically. The “Deleted when” column records intended rules. Chain records persist; requesting account deletion does not erase them.

Income and the things derived from it​

Source: stage2:PRIVACY.md#L48.

FieldWhereStorageReadersIntended deletion
Income figure (year to date, per source)the issuer's device only: its income chain keeps each reported quarter's year-to-date figure and salt (the opening the next quarter's proof chains from). The report verifier sees the figure inside the zkTLS proof, and the prior quarter's opening, in memory only; a tier-3 attestor receives the opening end-to-end encryptednone on the server—never exists at rest on the server
Income saltdevice; derived from a device secret (HMAC-SHA512 under the device secret over the series and period, reduced mod the BN254 field order; @merces/poi-device deriveIncomeSalt), so a reinstalled device rebuilds its openings from its own records and no server-side copy exists (owner question 2 open since S1, the default). Sent to the verifier in memory only (tier 2) or end-to-end encrypted to the attestor (tier 3)none——
Income commitment and the prior it chains fromreports.income_commitment, reports.prior_income_commitment, periods, series.last_income_commitment, onchain ReportAcceptedhash (Stage 1 Poseidon(2) over the year-to-date figure and the salt)issuer, holders, public (onchain)—
Payment amounts (gross, fee, net, accrual)reports, periods, money_events, fees_ledger, onchainplain (public onchain in v1)issuer, holders, admin; never in the public activity feedend of retention
Threshold θ, rate r (and the share rate it comes from; on a curve series r is per base lamport, units offered × 10^6, S3, derived in memory by the terms service and the issuer's device) and the terms saltterms_vault.ciphertext; terms_amendments.ciphertextvaultissuer, eligible backers (every read logged in terms_access_log; eligibility read live); the reviewing attestor on an amendment. No admin bypass. Never in an error message or a log: a share rate a WAD cannot hold is refused naming the rule only (A-TERMS-5), and the logger censors theta, rWad, shareRate, ratePerUnitWad and termsSaltseries end + retention
Terms commitmentseries, series_drafts, onchainhash (Stage 1 Poseidon(5) over θ, r, the currency code, the indexing rule and the terms salt)public—
zkTLS proof (contains the figure)never on the server; device → verifier in memorynone——
Report proof + public inputsreports.proof: Stage 1's Groth16 proof and its six public signals (terms commitment, units outstanding, FX rate, prior and income commitments, payment); never the witness, which stays inside the device's proverplainissuer, holders, adminend of retention
Verifier attestation (since S4 WP6 Stage 1's REPORT signature {signer, signature}: the verifier key's secp256k1 signature over the chain's signing domain, the series key, the period, prior and income commitments, tier 2 and the liquidity flag; no figure, no source)reports.attestation, onchain (an argument of submit_report)plain (public onchain)issuer, holders, admin—
Report verifier keys (20-byte addresses, registration and revocation times)verifier_keys (migration 024), onchain registryplain (public onchain)admin (GET /admin/verifier-keys); public onchain—
Tier-3 attestation (since S4 WP9 Stage 1's REPORT signature with tier 3 by the case's attestor key: {signer, signature, digest} over the chain's signing domain, the series key, the period, prior and income commitments, tier 3 and the liquidity flag; no figure, no salt, no opening) and the signing request it answers (GET /attestor/tier3/{caseId}/message: the same public fields)tier3_cases.attestation, reports.attestation ({signer, signature}), onchain (an argument of submit_report)plain (public onchain once submitted; only the series' issuer can submit a report, so an unsubmitted one is no bearer authorisation)issuer, the case's attestor, admin; holders through the report and onchainend of retention
FX fallback signatures (since S4 WP9 Stage 1's FX signature per series: the attestor key's {signer, signature, digest} over the chain's signing domain, the series key, the period and the rate; a public rate, no income)fx_fallback_signatures (migration 026), reports.fx_fallback ({signer, signature}), onchain (fx_fallback_sig, fxFallbackSignature)plain (public onchain once submitted; only the series' issuer can submit the report)attestors on the request's chain, the series' issuer (GET /series/{seriesId}/reporting/fx-fallback/{periodId}), adminend of retention
Tier-3 income opening (year-to-date figures and salts of the quarter and its prior)tier3_cases.opening_ciphertexte2e (a merces-e2e v1 envelope; anything else is refused)the chosen attestor only, to check the commitments against the documents; server: nobody. The attestor's signed case carries commitments, the proof and the attestation onlycase closed + retention
Tier-3 documents (tax returns, accounting exports)tier3_cases.documents_ciphertext, tier3_annual.documents_ciphertexte2ethe chosen attestor only (client-side decryption); server: nobodycase closed + retention
Tier-3 attested paymenttier3_cases, tier3_annual (amounts only)plainissuer, attestor, adminend of retention
Annual TRUEUP signature (S4 WP13: the attestation key's Stage 1 TRUEUP signature, the true-up nonce, the attestation time and the signed adjustment it binds, its digest; the adjustment is a payment figure Stage 1 publishes onchain with submit_trueup, never income)tier3_annual.trueup_signature, .trueup_signer, .trueup_nonce, .attestation_ts, .adjustment, .trueup_digest (migration 030), audit_log (signer, nonce, time, digest; never the signature), onchain once the issuer submits it (S5)plain (S4 amendment D2: not public until onchain; only the issuer can submit it)the signature: nobody through the API (stored for the issuer's submit_trueup, S5); its signer, nonce, time, adjustment and digest (trueUp): the attestation's key holder, the issuer and admins; never in the activity feed or a notificationend of retention
Income source kinds (stripe/deel/…)applications.income_source_kinds, income_sources.kindplainowner, adminaccount deletion
Report source kind (stripe/deel/…)reports.source (never in the verifier attestation or onchain)plainissuer, admin (holders get report rows without it)end of retention
zkTLS session source kindzktls_sessions.sourceplainnobody through the API (written at session start, never served)end of retention
Source credentials / API keysnever (zkTLS sessions run on the device with the provider)none——

Hardship and personal circumstances​

Source: stage2:PRIVACY.md#L73.

FieldWhereStorageReadersIntended deletion
Hardship reason and evidencehardship_requests.ciphertexte2ethe chosen attestor only; server: nobodydecision + retention
Hardship state and dateshardship_requests (state, until, decided_at; withdrawn since S4 WP10), onchain PauseRequested/Approved/Ended/RequestWithdrawnplainissuer, holders (status and dates only), attestor, admin—
Pause nonce and the relayed approval (S4 WP10: the pause nonce of the onchain request; the attestor key's Stage 1 PAUSE signature {signer, signature, digest, pauseNonce, pauseEnd} and the keeper's relay transaction; no reason, no figure)hardship_requests.pause_nonce, .approval, .relay_tx (migration 027), audit_log (signer, nonce, digest, relay transaction), onchain (approve_pause's arguments)plain (public onchain: stored only once the chain accepted it)the request's attestor key holder and admins (GET /attestor/hardship/{id}, the decision's response); never in the holders' status view, the activity feed or a notification—
An unrelayed PAUSE signature (a bearer authorisation until used or its nonce moves, S4 amendment D2)never stored: a refused or failed relay stores nothing; the idempotency record keeps the hash of the decision's body, and the response of a relayed one———
Decision codehardship_requests.decision_code, audit_logplain (codes only)attestor, admin—
Approval refusalAPI response only (detail.stage1: Stage 1's rule name; the message names the rule and the protocol bound, never a date); nothing stored, recorded in the audit log or notifiedplain (codes only)the deciding attestor—
Extinguishment evidenceextinguishment_requests.evidence_ciphertexte2ethe two attestors; server: nobody—
Extinguishment signatures (S4 WP12: the two named keys' Stage 1 EXTINGUISH signatures {signer, signature, digest}, the nonce they bind, the keeper's relay transaction and the Stage 1 name of a refused relay; no evidence, no figure)extinguishment_requests.signatures, .extinguish_nonce, .relay_tx, .relay_error (migration 029), audit_log (signer, nonce, digest, relay transaction), onchain once relayed (extinguish's arguments)plain; an unrelayed signature is a bearer authorisation (S4 amendment D2)before the relay: no read shows a signature (the named keys' holders and admins see which keys signed, signers); once relayed (public onchain): the named keys' holders and admins (GET /attestor/extinguish/{id}, the relay's response); never in the activity feed or a notification— (a signature over a nonce that moved, or by a key no longer active, is dropped)

Identity and accounts​

Source: stage2:PRIVACY.md#L86.

FieldWhereStorageReadersIntended deletion
Wallet addressesaccount_wallets, eligibility, allowlist (indexed), onchainplainowner; public onchainaccount deletion (chain data persists)
Email addressaccounts.emailplainowner, the email channelaccount deletion / on request
Display name, countryaccounts, applications.countryplainowner, adminaccount deletion
Identity documentsnever (the identity-check provider holds them)none—provider's policy
Identity check id and statusapplications.identity_check_id, identity_statusplainowner, adminapplication retention
Attestor identity check id and status (A-SIG-7, migration 031)attestor_identity_checks (the provider's check id, its status, when started); one row per accountplainowner (GET /me/attestor/identity-check), admin (the status only, GET /admin/attestors identityStatus); never public, never in a notification or the activity feedaccount deletion (the provider holds the documents, under its policy)
Application notesapplications.notes_encryptedvaultowner, adminapplication retention
Personaapplications.personaplainowner, admin—
Readiness reportapplications.readinessplainowner, admin—
Decision reasonapplications.decision_reason_code, audit_logcodes onlyadmin (owner sees the code)—
Attestor key links (S4 WP7)account_signer_keys (a key's 20-byte address, the account, when linked); audit_log (signer-key.link / .unlink)plainowner, admin (GET /admin/attestors); never public, never in a notification, the activity feed or another account's view. The key's address and its registration are public onchain (GET /chains/{chain}/signer-keys shows no account)unlink (409 while work addressed to the key is open) / account deletion
Attestor private key (S4 WP8)the attestor's own machine only: the Merces attestor tool's Web3 Secret Storage v3 keystore (~/.merces/attestor/keystore.json, mode 0600; scrypt n ≥ 2^18, AES-128-CTR)encrypted under the attestor's password; never sent, stored or logged by Merces (the tool posts only signatures and the link proof, and prints no key)the attestor onlythe attestor deletes the file (a lost keystore or password is a lost key: rotate it)
Sign-in nonces and key-link challengesauth_nonces (purpose sign-in or link-signer-key; a link challenge names the account and the key and no chain)plainnobody (consumed)10 minutes (expiry); purge weekly
Session tokenclient only (HMAC)none—24 h expiry

Contracts and terms​

Source: stage2:PRIVACY.md#L105.

FieldWhereStorageReadersIntended deletion
Signed HEU contract and chartercontract_sessions.signed_document_encryptedvaultthe signer, admin (every read recorded in the audit log)legal retention
Contract hashcontract_sessions.signed_hash, series.contract_hash, onchainhashpublic—
Rendered (unsigned) documentsreturned once to the signer; not storednone——
An amendment's AMEND signature (S4 WP11: the attestor key's Stage 1 signature over the series' amendment nonce, the new terms commitment and the new cap; no term in plain, no figure) with its nonce and digestterms_amendments.attestor_signature, .amendment_nonce, .digest (migration 028), audit_log (signer, nonce, digest; never the signature), onchain once it lands (amend_terms's arguments)plain (only the issuer can submit it: amend_terms is the issuer's transaction)the issuer, in its built amendTerms only, until it lands; the nonce and digest in the amendment list (issuer, the series' chain's attestors, admins); never in the activity feed or a notification (S4 amendment D2)dropped when the signature dies (the nonce moved or the key is no longer active: the amendment awaits an attestor again)

Bids and holdings​

Source: stage2:PRIVACY.md#L114.

FieldWhereStorageReadersIntended deletion
Bid price, quantity, saltclient; revealed onchain at reveal timenone until reveal (public afterwards). The commitment is Stage 1's keccak over the price, quantity, salt and wallet and binds no series or window (S4, A-SIG-8), so the client draws a fresh 32-byte salt for every bid and order: a reused salt would make equal bids in two series commit identically and link them——
Reveal backupbid_backups.ciphertext (plaintext fields rejected)client-encryptedowner; server: nobodyafter settlement + retention
Commitment, depositbids, onchainplainowner, issuer; public onchain—
Auction settlement: rounds and rejections, the clearing price, units sold, proceeds, the failure reason, the mint gateseries, settlement_rounds, onchainplainpublic (GET /series, GET /series/{id}/auction; onchain); the activity feed names rounds, reasons and unit counts only, never an amount (the indexer's summary())—
A bid's validity, processing and delivery state, and what it is owed (pending units and refund) or was deliveredbids, onchainplainowner (/me/bids); public onchain: Stage 1 keeps every bid's state in a public account, and anyone may deliver any bid (deliverBid pays the bidder only); the public preview projects each revealed bid's processing—
A bid's non-reveal charge (NRC: what an unrevealed bid paid the fee collector when its raise settled)bids.non_reveal_charge, fees_ledger (kind nonReveal), money_events, onchainplainowner (/me/bids), admin (accounting); public onchain (Stage 1's NonRevealCharged, amount-bearing); the activity feed and the bidder's notice name no amount; not income—
Positions, claims (S3: Stage 1's claim family)positions, money_events, onchainplainholder, issuer, admin; public onchain (PayoutClaimed, TailClaimed, FinalClaimed, RedemptionClaimed, UnitsBurned; none is income). A position row, and so holder access, comes only from an allocation, a window fill or, on a curve, a stake or a tender: never from a claim (a claim of nothing emits its event with zeros) or a holder registration, so neither grants holder access (A-REV-10). A claim of 0 writes no money row. The claim events are amount-bearing: the activity feed never names an amount—
Curve census, stakes, tenders and proceeds (S3: the unit mint's supply and protocol-held balances, each holder's stake, the stake and tender totals, the collected proceeds and trading fees)curve_census, positions.staked_units, series.staked_total/tendered_total, curves, money_events, fees_ledger, onchainplainpublic onchain (Stage 1's CurveUnitsSynced, UnitsStaked, UnitsUnstaked, the stake vault, a tender's RedemptionClaimed and UnitsBurned, CurveActivated, CurveProceedsCollected, TreasuryFunded, FeeTaken{curveTrading}); the amount events among them are amount-bearing; the activity feed names unit counts only, never an amount or a holder; none of it is income—
A wallet's curve position (S3 WP12: wallet and staked units, pending and claimable payout, what it can stake, the tender)read live from the chain per request (GET /series/{id}/curve/position); not storednonethe account that linked the wallet (account tier; every curve builder takes one of the caller's wallets), and admin for any wallet it names (the admin bypass of every wallet builder; the position holds no income data, only unit counts, payouts and the allowlist flag, all public onchain, and a transaction built for a wallet needs that wallet's signature; a live read of chain-public data, so not recorded in the audit log, like admin's other reads of public chain state); public onchain as balances and holder records—
The buyer's acknowledgement of the statements before a buy (S3 WP12: acknowledged, beforeYouBuyVersion)the build-swap request only; checked against the current version, not recordednone——

Operational data​

Source: stage2:PRIVACY.md#L129.

FieldWhereStorageReadersIntended deletion
Audit log (actor, action, target, codes)audit_log (append-only)plainadminnever (immutable)
Terms access logterms_access_logplainissuer, adminseries end + retention
Notifications (statuses, ids, dates)notifications, email_outbox (mock)plainowner; admin views are recorded in the audit logread + retention
Curve keeper records (S3 WP11: each lifecycle check that acted or read a change, with the pool's public reserve and the chain time; the curve reminders sent, by wallet, series, payment round and next step)curve_monitor, reminders_sentplainpublic onchain facts; a reminder goes to the account of the one linked wallet it names, never to the issuer, and names no amount, price or count (templates read the whitelisted keys only; the wallet's step is a fixed code); keeper errors carry codes only—
Outbox payloadsoutboxplain (may carry amounts owed to the issuer, and an auction event's public onchain amounts: a delivered refund, proceeds; never income)adminafter dispatch + 30 days
Logsprocess stdoutredacted (income-bearing keys censored at the sink, with Stage 1's openings and private terms: incomeSalt, priorSalt, termsSalt, priorIncomeYtd, theta, rWad, shareRate, ratePerUnitWad, opening, priorOpening, tier3Opening, deviceSecret); error messages carry no valuesoperatorslog retention
Keeper runs, reconciliation runskeeper_runs, reconciliation_runsplainadmin90 days
Delivery retries (series, bidder, attempts, next attempt, Stage 1 error name or code; never a message)auction_deliveriesplainadminwhen the bid is delivered

Signatures and keys (S4)​

Source: stage2:PRIVACY.md#L173.

FieldWhereStorageReadersIntended deletion
The attestor and verifier key registry (20-byte addresses, active, registration and revocation times)attestors, verifier_keys (indexed from the chain; migrations 023, 024), onchainplain (public onchain)public (GET /chains/{chain}/signer-keys: address, active, revokedAt, graceUntil; no account); admin (GET /admin/attestors, GET /admin/verifier-keys)—
Attestor proposals (a chain, a key, the account it was proposed for, register or revoke)attestor_proposals, admin_tx_requests, audit_logplainadmin—
A signing request (S4 WP9-WP13: kind, chain, series, series key, domain, the addressed key, the typed fields, pre-image, digest, validity)API response only; never storednonethe addressed key's account, admins (the routes' tiers)—

What can go wrong​

A private document can still reveal facts through a public payment, a disclosed wallet or a compromised device. Server-key encryption and attestor-only encryption expose data to different parties. Retention deadlines remain undecided, and the source inventory does not make an automatic deletion workflow exist.