# **Privacy Architecture**

Proving you are human should not require sacrificing your privacy. not.bot™ enforces a design principle across every component of the system: no party has access to user identity data under normal circumstances. The architecture prevents data collection at the source. Data that was never collected cannot be breached, subpoenaed, or sold.

not.bot distinguishes three categories of privacy protection, and this document labels each assertion accordingly.

**Architectural impossibilities** are protections enforced by system design. The architecture prevents certain data from reaching certain parties. No policy change, employee action, or security breach can expose data that was never collected.

**Policy choices** are protections enforced by Julia Social's operational decisions. Data passes through Julia Social's systems but is discarded without logging. These protections depend on Julia Social honoring its commitments. Code audits and operational transparency make them verifiable.

**Contractual controls** are protections enforced by legal agreements with third parties. A contract prohibits certain behavior. These protections introduce counterparty risk but provide accountability and legal recourse.

## **The parties**

not.bot distributes trust across several independent parties. Each holds a different slice of data, and the architecture prevents any single party from assembling a complete picture.

**The user** holds a verified identity through the not.bot app on their device. The app stores cryptographic keys, aliases, credentials, and contacts in an encrypted database. The database encryption key sits in the device's secure element (iOS Secure Enclave or equivalent Android TEE hardware).

**Julia Social** operates not.bot. It issues credentials, runs supporting infrastructure, and serves as the system's credential issuer. Julia Social never receives passport data and holds as little user data as possible.

**The escrow agent** ([Praxis Escrow](https://praxisescrow.com/)) is an independent US escrow company that has completed a SOC 2 Type 1 examination. Praxis operates the Escrow Server on its own infrastructure and stores the encrypted identity records the Escrow Server produces. Praxis does not hold the decryption key for those records; Julia Social does. A custom escrow contract binds Praxis to release any record only on a specific law enforcement demand for the user identified by that record, and forbids bulk release.

**The Escrow Server** is software Julia Social wrote and Praxis operates. During enrollment, it fetches passport data from Signicat, processes it into multiparty computation inputs, hashes it for duplicate detection, encrypts it to a key only Julia Social can use to decrypt, and discards the cleartext. The Escrow Server also participates in the multiparty computations that produce credentials without learning the underlying personal information.

**Signicat** validates passport data during enrollment and recovery. Signicat holds ISO/IEC 27001:2022 certification (DNV certificate C849517, with ISO/IEC 27018:2019 cloud-privacy controls in scope) and is a Qualified Trust Service Provider under eIDAS, listed on the EU Trusted List. Under a custom agreement, Julia Social (the customer) is excluded from downloading decoded passport data; Praxis, operating the Escrow Server, is the only entity with download rights. In normal operation, Signicat deletes passport data within seconds of the Escrow Server downloading it. Retention is capped at five minutes. 

**not.bot Verify** is server software operated by businesses inside their own infrastructure. Each instance runs its own private blockchain nodes. Julia Social has no visibility into which users a business verifies, when those verifications occur, or what credentials are checked.

**Galactechs** provides blockchain node services. Julia Social and Galactechs share a common founder. Users who select the default configuration (random public nodes) never interact with Galactechs.

**AWS** provides Julia Social's cloud infrastructure. Data stored on AWS is encrypted at rest. AWS does not possess the decryption keys.

## **Identity without identification**

A user's identity in not.bot consists of a **root DID** (the foundational anchor, never shared externally) and one or more **alias DIDs** (the identifiers used for interactions). Each alias has its own cryptographic keys, credentials, and signature history. Aliases are cryptographically unlinkable: examining two aliases, their credentials, and their signatures reveals nothing about whether they belong to the same person.  Even Julia Social cannot correlate two alias DIDs, nor identify which alias DIDs are associated with a root DID.

**Credentials** are signed statements by an issuer about an alias. Julia Social issues credentials based on information verified during enrollment. They include personal information (name, birthdate, gender, nationality), age thresholds and brackets, and the baseline not.bot credential proving the alias belongs to a verified human. For all aliases except the first one created at enrollment, personal information credentials are disabled by default. The user enables each credential type per alias.

**Site passes** are pairwise identifiers unique to a specific human-site combination. They provide sybil resistance: the same human interacting with the same site produces the same site pass, regardless of which alias they use. Site passes for different sites are cryptographically unlinkable, even if those sites collude and share data. Users must consent to allow a site pass to be created for a particular site.

**Signatures** are cryptographic structures that prove a human reviewed and approved something. They come in two visual formats. QR code signatures store encrypted data on Julia Social's servers, with the QR image containing a randomized URL, a decryption key, and a hash. JAB code signatures embed all data directly in the image. Both formats carry the signer's alias DID, message, credentials, timestamp, and a nonce.

## **Enrollment data flow**

During enrollment, passport data follows a controlled path. The app reads only DG1 from the passport NFC chip (name, birthdate, gender, nationality). No facial image is read. No biometric data leaves the passport chip.

The data goes from the app to Signicat for validation. Signicat checks the chip's digital signatures and passport expiry, then holds the validated data by session ID. The Escrow Server downloads the data using that session ID, tells Signicat to delete it, and Signicat complies within seconds. The Escrow Server then hashes the personal data with a pepper for duplicate detection, preprocesses and anonymizes it for multiparty computations, encrypts the cleartext to a key Julia Social holds on air-gapped hardware, stores the encrypted record, and discards the cleartext. The Escrow Server never writes cleartext identity data to persistent storage.

Julia Social never sees the passport data at any point in this flow.

## **What Julia Social cannot access**

Julia Social's infrastructure never has access to the following. These are architectural impossibilities.

**P1.1** Passport data, including name, birthdate, gender, nationality, passport number, or photograph.

**P1.2** Email addresses, phone numbers, or any other contact information.

**P1.3** Payment card numbers, bank account information, or financial account details.

**P1.4** Apple ID or Google Play account identifiers.

**P1.5** Device contacts, location data, or any data that could fingerprint the device.

**P1.6** The cleartext contents of any signature (message, alias, or credentials), in either QR or JAB format.

**P1.7** Biometric data.

**P1.8** Which sites a user interacts with.

**P1.9** Which users a site interacts with.

**P1.10** When a user creates or scans a JAB code signature.

## **What Julia Social receives but discards**

Julia Social's infrastructure receives certain data during normal operation but discards it without persistent storage or logging. These are policy choices.

**P2.1** Server logs contain timestamps for operational monitoring but no IP addresses, alias identifiers, credentials, or other information that could correlate a log entry to a user.

**P2.2** Julia Social does not store the credentials it issues, other than Verified Signer credentials.

**P2.3** Recovery endorsement requests are not stored.

**P2.4** Age credential requests are not stored.

**P2.5** The association between a reserved name and the root DID that registered it is not stored.

**P2.6** The association between a user's root DID and their alias DIDs is not stored. Given an alias DID, Julia Social cannot determine which other aliases belong to the same person.

*Exception:* For aliases holding Verified Signer badges, Julia Social retains the root-to-alias mapping to enable subscription-lapse revocation.

*Exception:* Julia Social operates the only Recovery Server and observes the complete set of aliases belonging to an identity for the duration of the recovery and rekey operations.

**P2.7** The unhashed original transaction ID for subscribers is not stored.

**P2.8** IP addresses from faucet coin requests are held in memory for rate limiting and are never written to persistent storage.

**P2.9** The coin IDs provided with faucet coin requests are not stored.

## **What Julia Social cannot derive**

Even from data Julia Social does process or store, the following cannot be derived or inferred.

**P3.1** Julia Social cannot determine which root DID an alias belongs to without possessing a signature created by that alias.

**P3.2** Julia Social cannot determine which sites a user creates site passes with.

**P3.3** Julia Social cannot correlate QR code signature fetches to users.

**P3.4** Julia Social cannot derive passport data or credential values from the data it processes or stores.

**P3.5** Julia Social cannot access the contents of QR code signatures. Julia Social hosts the encrypted signature data but does not have access to the decryption key.

**P3.6** Julia Social cannot alter the contents of a QR code signature without detection. Any modification to the stored data would be detected when the scanning app verifies the decrypted result against the hash embedded in the QR code.

**P3.7** Julia Social cannot access the cleartext contents of the encrypted recovery bundle.

**P3.8** Julia Social cannot determine how often a user presents age credentials, nor when within a month a user crosses an age threshold. The app requests fresh age credentials only when it lacks valid ones for the current month, so the refresh rate does not track how often the user presents them. Each request returns the full set of thresholds and brackets with a new encoding, so two requests in the same month reveal no threshold crossing between them.

## **What the escrow agent cannot access**

**P4.1** Praxis cannot access cleartext passport data after enrollment completes. The Escrow Server discards the cleartext before any persistent storage.

**P4.2** Praxis cannot decrypt the encrypted identity records it stores. Julia Social holds the decryption key on air-gapped hardware.

**P4.3** Praxis cannot determine a user's age or birthdate from the stored MPC input values.

**P4.4** Praxis cannot determine how often a user presents age credentials, nor when a user crosses an age threshold, for the reasons in P3.8: the app caches credentials for the month, and every refresh re-encodes the full threshold and bracket set.

## **What sites cannot learn**

Sites operating not.bot Verify receive only the information users consent to share.

**P5.1** A site cannot learn a user's root DID.

**P5.2** A site cannot learn which other aliases a user controls.

**P5.3** A site cannot learn a user's interactions with other sites.

**P5.4** A site cannot learn credential values the user did not consent to share.

**P5.5** A site cannot determine whether two aliases belong to the same human unless both aliases have presented a site pass to that site. Matching site passes reveals that both aliases belong to the same person. This is the intended behavior: site passes are a consent-based mechanism. A user who declines to provide a site pass accepts that the site cannot offer sybil-resistant services.

**P5.6** A site cannot forge or modify credentials.

**P5.7** Colluding sites cannot determine whether credentials from different aliases originate from the same human. Credentials issued to different aliases are cryptographically independent: even when the underlying values are identical (same name, nationality, or age), the signed credentials contain no common artifact that enables correlation.

## **Contractual privacy controls**

**P6.1** Praxis will not release encrypted identity data to Julia Social without Julia Social presenting a valid law enforcement demand for that specific user's data, identified by root DID.

**P6.2** If Julia Social's contract with Praxis terminates, Praxis may transfer data only to a successor escrow agent bound by equivalent restrictions. If no successor is established within 90 days, Praxis must delete all data.

**P6.3** Praxis will not release encrypted identity data to any party unless compelled by legal due process.

## **What external observers cannot learn**

**P7.1** Blockchain observers cannot correlate alias DIDs to root DIDs.

**P7.2** Blockchain observers cannot determine which credentials an alias holds. (*Exception:* Credentials presented on-chain become visible to observers.)

**P7.3** Blockchain observers cannot correlate two aliases as belonging to the same person.

**P7.4** Blockchain observers cannot detect when a user interacts with a site.

**P7.5** Blockchain observers cannot detect when a user creates or scans a signature.

**P7.6** Blockchain observers cannot determine when a new user joins. 

**P7.7** Blockchain observers cannot distinguish real DID operations from decoy operations. Julia Social generates continuous decoy DID operations (creates, recoveries, and rekeys for nonexistent users) using the same faucet coin mechanism as real operations, making them indistinguishable on the blockchain.

**P7.8** Blockchain observers cannot detect when a credential is issued.

**P7.9** Blockchain observers who detect a credential revocation event cannot determine which credential was revoked or which alias holds it.

**P7.10** Network observers cannot determine a user's identity, credential values, or alias associations from network traffic. Network observers can determine that a user communicates with not.bot infrastructure and may infer operation types from timing and destination patterns. A VPN mitigates most network-level observation; encrypted DNS mitigates DNS-level observation.

## **What Signicat cannot learn**

**P8.1** Signicat deletes passport data within seconds in normal operation, within five minutes by configuration, and within 50 days by contract.

**P8.2** Signicat cannot determine whether a passport scan is for initial enrollment or recovery.

**P8.3** Signicat cannot determine which not.bot identity is associated with a passport.

**P8.4** Signicat cannot correlate multiple verification sessions for the same passport over time.

**P8.5** Julia Social cannot access passport data through Signicat.

## **What infrastructure providers cannot learn**

**P9.1** AWS cannot access cleartext user data. Data stored on AWS is encrypted at rest.

**P9.2** Galactechs cannot access user identity or credential data. Blockchain queries contain only public DID identifiers and credential revocation indices.

**P9.3** Galactechs cannot correlate blockchain queries to users. Galactechs retains only aggregate request timestamps for capacity planning.

**P9.4** Apple and Google know a user installed the app and pays for a subscription (including tier). Julia Social stores only a hash of the original transaction ID and cannot reverse it to an Apple ID or Google Play account. Apple and Google cannot determine what a user does within the app.

**P9.5** Apple and Google cannot correlate subscription verification requests from Julia Social with user actions. Julia Social queries only the original transaction ID, which contains no information about operations, aliases, or credentials.

## **What the Recovery Server can access**

**D9.1** The Recovery Server operator stores the encrypted recovery bundle for each user. The operator cannot decrypt it. The bundle is encrypted with a key derived from the user's password, which the Recovery Server does not possess.

**D9.2** The Recovery Server operator stores the user-assigned device names for all devices registered to an identity. These names are chosen by the user and do not correspond to OS-level device identifiers. Device names may contain personal information if the user chooses identifying names.

## **Compromise scenarios**

**P10.1** Compromise of Julia Social's production infrastructure exposes no stored user identity data. A persistent attacker who controls Julia Social's infrastructure could begin logging data that Julia Social discards by policy, voiding all P2 protections going forward. Data discarded before the compromise cannot be recovered.

**P10.2** Compromise of Praxis alone does not enable decryption of stored identity data.

**P10.3** Compromise of both Julia Social's production infrastructure and Praxis does not provide access to user identities. The RSA decryption key required to begin recovering any user's identity data is held on air-gapped devices separate from production infrastructure.

**P10.4** Decrypting user identity records requires compromise of Julia Social's production infrastructure (to access the alias-to-root-DID lookup), Praxis (to obtain the encrypted data), and Julia Social's air-gapped decryption infrastructure (to obtain the RSA key). Even with all three, each user's record requires a separate multi-day brute-force computation to reconstruct deliberately erased bits of that user's unique AES encryption key.

**P10.5** Compromise of a user's device does not expose aliases, credentials, contacts, or signature history, provided the attacker cannot authenticate to the device. If the attacker can authenticate (known passcode, biometric spoof, or already-unlocked device), the encrypted database is decrypted in memory, from which a sophisticated attacker could potentially extract the data and the user’s cryptographic keys. The user can perform a rekey to invalidate compromised keys, but rekey does not protect data already taken.

**P10.6** Compromise of a site's not.bot Verify exposes site passes and aliases that users shared with that site, but does not enable correlation with other sites or access to any user credentials.  If the site stores the signatures or credential information it receives from users, that data is subject to the site’s data protection policies. Not.bot Verify does not store that information.

**P10.7** Signatures captured by a site using not.bot Verify carry dual attribution. Each signature embeds a complete copy of the request that prompted it: the requesting server's DID, its domain-name credential, the nonce, and the claims that server asked for. A captured signature identifies both the human who produced it and the server that requested it. If a site leaks a trove of collected signatures, the trove names its own source. The same embedded request supports audit: a reviewer can ask, for any signature, which server requested it and what claims that server demanded. No tooling extracts the embedded request today; it is a latent property of every Verify signature.

**P10.8** Compromise of Signicat exposes only verification sessions in progress at the time, not historical enrollment data.

**P10.9** Compromise of Galactechs infrastructure does not expose user identity data. Blockchain queries contain no personal information.

## **Affirmative data disclosures**

The preceding sections describe what parties cannot access. This section enumerates, for transparency, the data each party can access in cleartext. Encrypted data the party cannot decrypt, and hashed data with sufficient entropy to prevent reversal, are not listed.

**Julia Social** holds: root DIDs (D1.1); alias DIDs (D1.2); a mapping from SHA2-256(alias DID, not.bot credential ID) to root DID, queryable only with both values together (D1.3); a hash of the original transaction ID for each subscriber, associated with their root DID (D1.4); reserved names and their associated alias DIDs (D1.5, public by design); Verified Signer credentials including the alias DID, root DID, and proof URL for each (D1.6); domain name credentials binding server DIDs to domain names (D1.7); the count of reserved names per root DID (D1.8); the count of aliases per root DID (D1.9).

**Praxis** holds: root DIDs (D2.1); a peppered hash of passport data used for duplicate detection, further processed and not stored in its original form (D2.2); pre-computed MPC input values for non-age credentials, hashed with Argon2id using a user-specific salt and system-wide pepper (D2.3); pre-computed MPC input values for age credentials with sufficient entropy to prevent age derivation (D2.4); the total count of enrolled identities and the rate of new enrollments over time (D2.5).

**Sites** hold: site passes for users who created them with that site (D3.1); credentials users chose to share (D3.2); alias DIDs users presented (D3.3); the site's own domain name credential (D3.4); optionally the complete history of all signatures presented to the site (D3.5).

**Signicat** holds: passport data during active verification sessions, deleted within seconds under normal operation, within five minutes by configuration, and within 50 days by contract (D4.1).

**AWS** holds: encrypted data at rest without decryption capability (D5.1).

**Galactechs** holds (for users selecting Julia Social blockchain access): transient blockchain query content containing public DID identifiers and revocation indices, not stored (D6.1); aggregate request timestamps for capacity planning (D6.2).

**Public blockchain nodes** hold: blockchain query content equivalent to D6.1, distributed across randomly-selected nodes so that no single node observes a user's complete query pattern (D7.1).

**Blockchain observers** can see: when a DID was created, recovered, or rekeyed (D8.1); which public key is associated with a DID at any point (D8.2); a DID's current state (D8.3); credential revocation events (D8.4); delegation events for credential issuance (D8.5). Network observers can determine that a user communicates with not.bot infrastructure and may infer operation types from traffic patterns, but cannot determine the contents of any operation (D8.6).

## **Known privacy weakness**

**PW1** The Recovery Server receives all alias spend bundles at once during recovery and rekey operations, exposing the complete set of aliases belonging to an identity in a single moment. Julia Social operates the only Recovery Server today.

*Planned mitigation:* Julia Social plans to open-source the Recovery Server software and enable third-party and self-hosted operation, allowing users to remove Julia Social from this role.

## **What users control**

**P12.1** Users choose which alias to use for any interaction.

**P12.2** Users choose which credentials to share in any interaction.

**P12.3** Users choose whether to create a site pass for any site.

**P12.4** Users control telemetry. Telemetry is disabled by default. When enabled, it includes only screen timing data and aggregate usage metrics (screen access counts, signature and scan counts, QR versus JAB usage). Telemetry contains no identifying information, no alias or credential data, no signature contents, and no information about sites or users the person interacts with.

**P12.5** Users control their recovery configuration, including password selection.

**P12.6** Users control device authorization.

**P12.7** Users can hide aliases from casual inspection of their device.

**P12.8** Support logs are stored on-device only and are never transmitted automatically. Logs contain no identifying information, no alias or credential data, and no signature contents. Sharing logs with Julia Social support requires the user to download the log manually from the app and send it through a support channel.

## **Why this architecture**

No single point of compromise can expose user identities. Revealing a user's identity requires cooperation between Julia Social and Praxis, plus access to air-gapped decryption infrastructure. Compromising any one party is insufficient. Even compromising all three provides only the ability to decrypt records one at a time, each requiring a separate multi-day brute-force key derivation.

Signature creation and signature verification, the two operations users perform most often, do not require Julia Social or the Recovery Server. The app signs content using keys stored on-device. The app verifies signatures using on-chain data from blockchain nodes. Julia Social is contacted only for administrative operations: enrollment, rekey, recovery, alias creation, reserved name requests, Verified Signer credential requests, and QR signature data upload and download. This separation between administrative and runtime operations means a compromise of Julia Social does not affect ongoing signing and verification.

For the full treatment of security properties and known weaknesses, see the [Security Model & Known Weaknesses](http://doc_08_security_model.md) document. For the law enforcement access workflow and accountability model, see the [Law Enforcement & Accountability](http://doc_09_law_enforcement.md) document.
