G

Privacy-modes

Privacy-modes

Version: GD/1.2 — Module: Core Capabilities


Overview

Every .gao domain has a privacy mode that controls what information is visible to which parties during resolution. Privacy is on by default — a newly registered domain starts in Private mode, and the owner explicitly chooses to make information more visible.

This is the opposite of most Web3 naming systems, where wallet addresses are public by default and privacy requires additional configuration or abstraction layers.


Three Privacy Modes

Mode

Who sees the real wallet

Payment routing

Default?

Private

No one

Via proxy

✅ Yes

Contacts

Only contacts in Identity Graph

Direct to contacts, proxy to others

No

Public

Everyone

Direct

No


Private (Default)

In Private mode, the real wallet address is encrypted in the resolver and never returned to any query. Payments still work — they route through the domain’s privacy proxy, which forwards funds to the real wallet without revealing it.

Sender queries merchant.gao 

Resolver returns:
  trust_level:     2
  display_name:    "Merchant Shop"
  wallet:          "hidden"
  payment_proxy:   "0xPROXY_MERCHANT_BASE"
  content:         { website: "https://merchantshop.com" }

Merchant's real wallet: never returned, never on-chain in linkable form

What is always visible in Private mode:

  • Domain name

  • Trust level and badge

  • Display name and avatar (if configured)

  • Payment proxy address (public — needed to receive payments)

  • Web content endpoint (if configured)

  • Agent records (scope and expiry — not private keys)

What is hidden in Private mode:

  • Real wallet address

  • Contact list

  • Any information the owner has not explicitly opted in to sharing


Contacts Mode

In Contacts mode, the domain owner’s real wallet address is visible to their Identity Graph contacts — other .gao domains they have established a mutual trust relationship with. All other queries receive proxy-based resolution, same as Private mode.

Alice queries merchant.gao:

Resolver checks: is alice.gao in merchant.gao's contacts?

Yes → Returns real wallet address directly
No  → Returns proxy address (same as Private mode)

The merchant never knows whether a given query received the real address or the proxy. Both paths result in correct payment delivery — the difference is privacy level for the sender.

Use cases for Contacts mode:

  • Suppliers seeing direct wallet addresses for invoice settlement

  • Trusted business partners with direct wallet visibility

  • Team members within the same organization


Public Mode

In Public mode, the real wallet address is returned to any resolution query. There are no privacy protections on the wallet.

Resolver returns:
  wallet: {
    eth:              "0x9a2f...c3d4",
    base:             "0x9a2f...c3d4",
    preferred_chain:  "base",
    preferred_token:  "USDC"
  }

Public mode is appropriate for:

  • Individuals who want to be fully discoverable

  • Donation addresses or public fundraising

  • DAOs with intentionally transparent treasury addresses

Note: Public mode means anyone who knows your domain name can see your wallet address and look up your complete transaction history on that address. Consider this carefully before enabling.


Privacy Proxy Architecture

The privacy proxy is what makes Private and Contacts modes work — payments reach the recipient without exposing their real wallet.

Each domain in Private/Contacts mode has:
├── proxy_merchant_base    (0xPROXY_BASE...)   Base chain
├── proxy_merchant_eth     (0xPROXY_ETH...)    Ethereum
├── proxy_merchant_sol     (PROXY_SOL...)      Solana
└── proxy_merchant_polygon (0xPROXY_POLY...)   Polygon

Properties:
├── Proxy address is STABLE — never changes, even when real wallet rotates
├── Real wallet address is PRIVATE storage in proxy contract
├── Only the Registry contract can update realWallet (after owner sig verified)
└── No external call can read realWallet

When a merchant changes their real wallet (key rotation, security upgrade):

  • The proxy address stays the same

  • Customers who saved merchant.gao do not need to update anything

  • No on-chain link between old and new wallet is created


Identity Graph and Contacts Mode

The Identity Graph is the private network of verified relationships between .gao domains. It is what powers the selective disclosure in Contacts mode.

How contacts are established:

  1. Domain A sends a contact request to Domain B

  2. Domain B accepts — both are now in each other’s contact list

  3. Both see the mutual connection; neither can see the other’s full contact list

Graph privacy properties:

  • Contact lists are encrypted in the resolver — even Gao cannot read them

  • Connections are stored as domain hashes, not plaintext domain names

  • Mutual discovery is opt-in: both parties must consent to be discoverable via shared contacts

  • No global graph is visible to anyone

One-hop trust propagation:

alice.gao ←──▶️ bob.gao ←──▶️ carol.gao

Alice queries carol.gao:
  Not a direct contact
  Shared contact: bob.gao
  Response includes: "1 mutual contact"

Alice can:
   Add carol.gao as a contact
   Or proceed with proxy payment (no action required)

---

### Switching Privacy Modes

Privacy mode can be changed at any time by the domain owner with a signed update. Changes take effect immediately.

// Switch to Public mode

await resolver.updateRecord('merchant.gao', {
  action: 'set_privacy_mode',
  payload: { mode: 'public' },
  timestamp: Date.now(),
  nonce: currentNonce + 1,
}, ownerSignature);

**Switching from Public to Private:**

-   Resolver immediately stops returning real wallet address
    
-   Proxy contracts are already deployed (they are created at registration)
    
-   No on-chain transaction required to activate proxy — it is always available
    

**Switching from Private to Public:**

-   Real wallet becomes visible to all queries immediately
    
-   Proxy continues to work — payments via proxy still forward correctly
    
-   Domain owner should be aware that the wallet address is now discoverable
    

---

### How Privacy Mode Affects Resolution

The full resolution decision tree based on privacy mode:

Incoming query: GET /resolve/merchant.gao Optional header: X-Requestor: alice.gao

Privacy mode = PRIVATE: └── Return proxy address only (no real wallet, regardless of requestor)

Privacy mode = CONTACTS: ├── Is X-Requestor in contacts? AND requestor provided valid proof? │ Yes → Return real wallet address └── No → Return proxy address (same as PRIVATE)

Privacy mode = PUBLIC: └── Return real wallet address to all queries


Resolver Response by Mode

Private response:

{
  "domain": "merchant.gao",
  "trust_level": 2,
  "wallet": { "visible": false, "proxy": { "base": "0xPROXY..." } },
  "payment_available": true
}

Contacts response (requestor is a contact):

{
  "domain": "merchant.gao",
  "trust_level": 2,
  "wallet": {
    "visible": true,
    "addresses": { "base": "0xREAL...", "eth": "0xREAL..." },
    "preferred_chain": "base"
  }
}

Public response:

{
  "domain": "merchant.gao",
  "trust_level": 2,
  "wallet": {
    "visible": true,
    "addresses": { "base": "0xREAL...", "eth": "0xREAL...", "sol": "SoL..." },
    "preferred_chain": "base",
    "preferred_token": "USDC"
  }
}

---

### Developer Notes

Applications integrating Gao Domain resolution **must not** bypass privacy settings. If `wallet.visible` is false, use `wallet.proxy` for payment construction. The proxy works identically to a direct address — it simply preserves the recipient’s privacy.

const result = await resolver.resolve('merchant.gao');

const paymentAddress = result.wallet.visible
  ? result.wallet.addresses['base']   // Public or Contacts (authorized)
  : result.wallet.proxy['base'];       // Private — use proxy

// Both work correctly for payment. Privacy is preserved automatically.


Privacy modes govern what each resolution query returns. See Payment Resolution for how the payment proxy works in practice and Architecture & Resolver for the technical resolution decision tree.