# **System Architecture and Degraded-Mode Operation**

This document maps the components of the not.bot™ system, the trust boundaries between them, and what each component can and cannot reach. It then states what continues to work when any one component fails. The organizing fact is a split between two kinds of dependency. Administrative operations (enrollment, recovery, alias creation, credential issuance) need Julia Social and the Recovery Server. The operations users perform most, signing and verifying content, need neither. They run against the Chia blockchain and nothing else.

This split is the resilience argument. An enterprise evaluating not.bot for production asks what breaks when the vendor's servers go down. For signing and verification, the answer is nothing. A signature created last year verifies today whether or not Julia Social is available.

For the data each party holds and cannot access, see the [Privacy Architecture](http://doc_07_privacy_architecture.md) document. For the security guarantees behind each component, see the [Security Model and Known Weaknesses](http://doc_08_security_model.md) document.

## **Components**

The system distributes work across independent parties. Each runs its own infrastructure and holds a different slice of the system's state.

**The not.bot app** runs on the user's iOS or Android device. It stores the user's cryptographic keys, aliases, credentials, and contacts in an encrypted database whose key sits in the device's secure element. The app creates signatures, scans and verifies signatures, presents credentials to sites, and reaches Julia Social for administrative operations.

**Julia Social** operates not.bot. It issues credentials and runs the credential-issuance infrastructure, hosts QR signature payloads, runs the faucet that funds users' on-chain operations, mediates the reserved-names registry (the interim service until on-chain Julia Vanity Names ship), manages subscriptions, operates the decoy-transaction service that protects on-chain privacy, and serves administrative requests from the app. Julia Social holds as little user data as possible and never receives any user-identifying data.

**The Recovery Server** stores each user's encrypted recovery bundle and authorizes recoveries. Julia Social operates the only Recovery Server today. The app contacts it for recovery support and multi-device coordination, never for signing or verification.

**The Escrow Server** is software Julia Social wrote and Praxis, the independent escrow agent, operates on Praxis infrastructure. It processes passport data into credential inputs at enrollment and participates in the multiparty computations that produce credentials. It is an enrollment-time and credential-issuance participant, not a runtime one.

**Signicat** validates passport data during enrollment and recovery. It holds passport data for seconds in normal operation and is reachable only during those two flows.

**Chia blockchain nodes** hold the canonical record of DID state, key history, and credential revocation. The app reads this record to create and verify signatures. The app reaches nodes in one of three modes (see Blockchain Access below).

**not.bot Verify** is server software a business runs inside its own infrastructure to request and verify credentials from not.bot users. A Verify deployment runs its own Chia nodes and its own key store. The user's app talks to the business's Verify servers, never to Julia Social, during a verification.

**not.bot Signer** is a web tool for signing content at volume, targeted for release at the end of June 2026 (future state). Signing through Signer still requires the not.bot app on the signer's phone to authorize each signature.

## **Trust boundaries**

Three boundaries shape what any party can observe.

The **device boundary** holds the user's keys. The signing keys never leave the app's encrypted database, and the database key never leaves the secure element. No server, including Julia Social, holds a user's signing key.

The **escrow boundary** separates the encrypted identity record from its decryption key. Praxis holds the encrypted records and cannot decrypt them. Julia Social holds the decryption key on air-gapped hardware and does not hold the records. Reading any user's identity requires crossing both sides of this boundary plus a per-record brute-force step. By contract, Praxis cannot release encrypted records to Julia Social without a valid law enforcement demand, even after the contract between them ends: at termination the records may move only to a successor escrow agent bound by the same restrictions, never back to Julia Social, and Praxis must delete them if no successor is named within 90 days. The [Privacy Architecture](http://doc_07_privacy_architecture.md) document states these contractual controls.

The **deployment boundary** isolates each not.bot Verify instance. A business's Verify servers, key store, and Chia nodes run inside the business's own infrastructure. Julia Social has no path into a running deployment and no visibility into which users a business verifies or when.

Once enrollment completes, only one component can reach decrypted user data on its own: the user's device. The app holds both the encrypted database and, in the secure element, the key that opens it. No server holds both halves. Praxis holds encrypted identity records without the decryption key, Julia Social holds that key without the records, and the Recovery Server holds an encrypted recovery bundle it cannot read. The only other party that ever sees cleartext is a verifier the user chooses to share with, and then only the specific claims the user releases.

## **Administrative-time dependencies versus runtime dependencies**

The app contacts Julia Social for administrative operations only: enrollment, rekey, recovery initiate and cancel, alias creation, reserved-name requests, Verified Signer credential requests, and QR signature payload upload and download. The app contacts the Recovery Server for multi-device coordination: contacts, alias settings, network settings, password changes, and adding or resetting devices.

Every on-chain operation also draws a faucet coin from Julia Social, since users hold no XCH and cannot pay a blockchain fee. For some operations that funding is the only thing Julia Social provides. For example, a rekey is built and signed on the user's device and executed on chain; the app reaches Julia Social only for the faucet coin, not to authorize the change.

None of these operations happen during signing or verification.

Signing and verifying content reach neither Julia Social, the Escrow Server nor the Recovery Server. The app signs with on-device keys and verifies against on-chain data from blockchain nodes. The only runtime dependency for these operations is blockchain access, and that access runs by default against a pool of public nodes with no Julia Social involvement.

A user signs and verifies content many times. A user enrolls once, and recovery is a rare event. The system places its server dependencies on the rare operations and keeps the common ones independent.

## **Blockchain access**

The app needs blockchain data to create and verify signatures: DID status, key history, and revocation state. It reaches the chain in one of three modes.

| Mode | Description | Default |
|------|-------------|---------|
| Random public nodes | The app opens connections to multiple nodes at startup, queries connected nodes when it needs chain state, and opens more connections on demand. | Yes |
| Julia Social and Galactechs public node | A specific public node Julia Social and Galactechs operate. | No |
| User-specified node | A node address the user configures, including a node the user runs. | No |

The default mode reaches no Julia Social infrastructure. The Chia network includes about 30,000 nodes, so a pool of 30 or more connections with on-demand fallback stays available under adverse conditions. A user who runs their own node removes every shared dependency from signing and verification.

A not.bot Verify deployment does not use these modes. The deployment runs its own Chia nodes, at least one with three recommended, inside the business's infrastructure.

## **QR and JAB code resilience**

Signatures come in two visual formats with different dependency profiles.

A **JAB code** embeds the complete signature data in the image. Creating and scanning a JAB code signature reaches no server. A JAB code verifies in any network condition, which is what lets it survive screenshots, forwarding, and re-encoding.

A **QR code** embeds a URL, a hash, and a decryption key. Julia Social hosts the full payload at that URL. A verifier scanning a QR code fetches the payload from Julia Social, then uses the hash and key to confirm and decrypt it. If Julia Social is unreachable, the verifier cannot retrieve the payload and QR verification fails. The tradeoff is size: QR codes take much less visual space and carry a server dependency for retrieval; JAB codes take more space and carry none.

The QR dependency does not apply to not.bot Verify. A Verify deployment serves verification data from its own infrastructure.

## **Offline and in-person verification today**

A buyer evaluating not.bot for a door, a gate, or a checkout lane asks what verifies with no network today. The answer depends on the format and on how deep the check goes.

A JAB code carries its full signature in the image, so confirming the embedded content and its signature needs no network. Confirming the signer's current key state and revocation, the full chain of trust, needs the chain or a snapshot of issuer state. A JAB scan with no signal confirms that the content matches its embedded signature; it cannot confirm that the signing key was not rotated or revoked after the signature was made.

A not.bot Verify deployment verifies against its own Chia nodes inside the business's infrastructure. It needs those nodes synced and reaches no Julia Social server, so it runs through a Julia Social outage. It is an online verifier against its own chain access, not a no-network one.

The did:julia protocol supports fully offline verification against a snapshot. A verifier holding a snapshot of the relevant issuer state, the issuer DIDs, their active signing keys, and current revocation records, can verify a credential from a holder it has never seen, with no network. The [Credentials, Presentations, and Selective Disclosure](http://doc_06B_credentials.md) document describes this mode. The app code that exposes it for in-person signing and verification has not shipped; the [Roadmap](http://doc_20_roadmap.md) tracks it, along with removing the chain check that signature creation performs today.

Today: offline JAB content verification ships, online verification against the chain through Verify or the app ships and needs no Julia Social, and the fully offline snapshot mode is a protocol capability a later app release will expose.

## **Degraded-mode behavior by component**

The following states what stops and what continues when each component is unreachable.

**Julia Social administrative services down.** Signing continues, using on-device keys and the blockchain. JAB verification continues. QR verification stops, because the payload lives at Julia Social. App-to-Verify interaction continues, because Verify runs independent of Julia Social for any outage shorter than the once-a-month billing connection it requires (see not.bot Verify resilience). Enrollment, rekey, recovery, alias creation, and credential issuance stop until service returns.

**Recovery Server down.** Signing and both forms of verification continue. App-to-Verify interaction continues. Multi-device operations stop. Recovery initiate and cancel stop, because they need both the Recovery Server and Julia Social.

**Escrow Server or Signicat down.** New enrollments and recoveries stop, since both flows process passport data. Existing identities sign and verify without interruption, because neither component sits in the signing or verification path. Age-credential refresh, a three-party computation among the not.bot app, Julia Social, and the Escrow Server, pauses until the Escrow Server returns.

**Blockchain nodes unreachable.** Signature creation stops, because the app checks the chain during signing today. Removing that check is a roadmap item. JAB verification continues, since the signature data is already embedded; full chain-of-trust verification against current key and revocation state needs the chain. The default pool of 30 or more connections makes total unreachability unlikely. Enrollment and recovery need Julia Social regardless of node state.

**A not.bot Verify deployment's Chia nodes down.** That deployment cannot process verifications, because Verify checks revocation against its own synchronized nodes and accepts no credential verified against an out-of-sync node. The business runs three nodes to keep this from happening. A failure here is contained to that one deployment and affects no other business and no app-side signing or verification.

**The user's device lost.** Signing and verifying from that device stop. The identity survives. The user recovers it on a new device with their recovery password and passport, since the DID, aliases, and key history persist on the blockchain. Recovery is an administrative operation and needs Julia Social and the Recovery Server.

The pattern across these states: every failure of a Julia Social component leaves signing and JAB verification intact. The one runtime dependency that can stop signing is the blockchain itself, and the default access mode spreads that dependency across thousands of independent nodes.

## **not.bot Verify resilience**

A not.bot Verify deployment is built for production uptime and keeps serving verifications through Julia Social outages. Julia Social sits off the verification path, and a deployment reaches it at two points, neither during a verification. A signature server acquires its honest.bot™ credential when it starts up. The deployment also attempts an hourly connection to Julia Social to report billing statistics, and a missed attempt does not interrupt verification. The one limit is billing: a deployment must reach Julia Social at least once a month to keep operating, so verification continues through any Julia Social outage shorter than a month.

A deployment runs four components inside the business's Kubernetes cluster. OpenBao holds every DID's BLS12-381 private key and signs through that store, so no key leaves the cluster. The admin service manages the signature-DID pool and operates on the business's internal network with no public path. Signature servers run behind an internal load balancer with no public path, each holding one signature DID and serving user verification requests through the business's SDK adapter. Chia nodes follow the chain for the admin service and the signature servers. The deployment relies on two services the business provides, PostgreSQL for application data and Keycloak for operator login, neither part of not.bot Verify.

During a verification, traffic flows from the user's phone to the business's SDK adapter to the business's signature servers. No packets reach Julia Social. The full exchange stays inside the business's infrastructure and the user's device.

The internal verification reference is the [not.bot Verify: Julia Web SDK Reference](http://doc_18_verify_web_sdk.md).

## **not.bot Signer (future state)**

not.bot Signer, targeted for the end of June 2026, signs content from a browser at volume for newsrooms, brands, and public figures. The signatures still originate on the signer's phone: Signer drives the workflow, and the not.bot app authorizes each signature, so a verified human stands behind every signed item regardless of volume.

Signer hosts an encrypted known-good copy of each signed item. The decryption key is embedded in the signature, and Signer does not hold it, so Signer cannot read the content it stores. A verifier who finds the content in the wild compares it against the stored original. Treatment here stays brief because Signer has not shipped; the [Roadmap](http://doc_20_roadmap.md) covers it in full.

## **Why this architecture**

A vendor that holds the keys to your continued operation is a single point of failure. not.bot removes Julia Social from the operations that matter most. A user signs and verifies content against the blockchain, with keys that never leave their device, and a business verifies humans inside its own infrastructure against its own nodes. Julia Social's servers carry enrollment, recovery, and credential issuance, the once-or-rare operations, and their outage leaves daily signing and verification untouched.

The same separation bounds the blast radius of a compromise. A Julia Social breach exposes no signing key and no decryptable identity record, and it cannot stop a JAB code from verifying. A Verify deployment failure stays inside one business. A lost device strands no identity, because the identity lives on a public chain and recovers onto new hardware. For the security properties behind these claims, see the [Security Model and Known Weaknesses](http://doc_08_security_model.md) document. For the data-access boundaries, see the [Privacy Architecture](http://doc_07_privacy_architecture.md) document.

## **Related documents**

- **[Privacy Architecture](http://doc_07_privacy_architecture.md):** the parties and what each can and cannot access.
- **[Security Model and Known Weaknesses](http://doc_08_security_model.md):** authenticity, integrity, availability, and the known gaps.
- **[The not.bot App](http://doc_05_notbot_app.md):** the app whose connections this document maps.
- **[Human Verification and not.bot Verify](http://doc_03_human_verification.md):** the Verify product and its deployment model.
- **[Why Chia?](http://doc_10_why_chia.md):** the blockchain that signing and verification depend on.
- **[did:julia Technical Specification](http://doc_15_did_julia_specification.md):** the protocol behind on-chain DID state and self-certifying verification.
- **[Roadmap](http://doc_20_roadmap.md):** not.bot Signer, offline signing, and removing the blockchain check from signature creation.
