# Orb NFT avatars

Current source behavior, October 1, 2026. This review is local, not a deployment.

Profile settings offer an ERC-721 avatar picker on Monad testnet 10143. Manual
contract and token-ID entry works without an indexer. Automatic discovery needs
the operator's Etherscan V2 key; its absence is shown as unavailable listing, not
an implementation task for the member. Supported imagery still depends on valid
metadata, reachable resources and the profile image processor.

Applying an avatar requires an Orb session and a server-verified Privy token.
The selected wallet must belong to that Privy session. The session must also match
the profile's stored Privy binding and/or linked login wallet. Profiles without
either binding must connect first. External wallets linked to the same authorized
Privy session are accepted without replacing or creating a spending-wallet link.
The backend calls ERC-721 `ownerOf` before setting the avatar.

NFT URLs accept bounded inline data or public HTTPS, including normalized IPFS
gateway paths. The server pins public DNS results, refuses private hosts and
redirects, and limits remote bodies and timeouts. Display names are bounded;
downloaded images pass through the existing profile-photo processor before storage.

The NFT reference is a snapshot at application time. Transferring the NFT later
does not automatically remove a copied profile image. An avatar badge is therefore
not a live ownership certificate or proof of a unique person. Role gates use their
own onchain checks; applying an avatar grants no community role or moderation.

`test-nft-url-policy.mjs` checks URL/resource refusal. `test-nft-profile-binding.mjs`
checks real disposable-database profile/session isolation. The production security
suite rejects anonymous and cross-origin NFT mutations and requires Privy beyond
an Orb cookie. These tests do not establish a real Privy NFT application on the
public network or an independent audit.
