Personhood Assertion (v1)

Status: Draft v1 — 2026-05-19 Extension URI: https://projectmaya.deoscomputing.io/identity/personhood/v1 Maintainer: DEOS Computing (did:web:deos.computing) Depends on: did:deos v1, W3C Verifiable Credentials v2.0 Companions: Receipt-Rooted Reputation white paper


1. Motivation

A receipt-rooted reputation system that admits sybils has no floor: 10,000 mutually-attesting did:deos agents game any centrality measure. The receipt-reputation white paper (§4.1) defers this to a separate personhood primitive — "the receipt layer carries the personhood proof but does not generate it" — and lists candidates (Worldcoin Orb, government digital ID, social-graph attestation, deposit bonds) without picking one.

Which scheme to require is a deployment policy, not a protocol decision. A consumer agent and a regulated financial substrate cannot ship the same personhood floor. This spec defines where personhood evidence lives in the identity layer and how relying parties consume it, without pre-committing to any one mechanism.

This document specifies:

  1. A personhoodAssertion extension on did:deos DID documents, carrying one or more W3C-style Verifiable Credentials.
  2. A tier vocabulary relying parties use to write policy without knowing every scheme's internals.
  3. Verifier obligations and the privacy-preserving disclosure path.
  4. One reference scheme (did-web/social-graph-v1) that ships without depending on an external provider.

2. DID document extension

A DID document MAY carry a personhoodAssertion array. Each entry is a Verifiable Credential attesting that the document's subject DID is operated by a real, distinct human (or, where relevant, a real distinct organization).

{
  "@context": [
    "https://www.w3.org/ns/did/v1",
    "https://projectmaya.deoscomputing.io/identity/personhood/v1"
  ],
  "id": "did:deos:alice",
  "verificationMethod": [ { "id": "did:deos:alice#sig-1", "type": "Ed25519VerificationKey2020", "controller": "did:deos:alice", "publicKeyBase64Url": "..." } ],
  "personhoodAssertion": [
    {
      "@context": ["https://www.w3.org/ns/credentials/v2"],
      "type": ["VerifiableCredential", "PersonhoodAssertion"],
      "issuer": "did:web:deos.computing",
      "validFrom": "2026-05-19T00:00:00Z",
      "validUntil": "2027-05-19T00:00:00Z",
      "credentialSubject": {
        "id": "did:deos:alice",
        "scheme": "did-web/social-graph-v1",
        "tier": "moderate",
        "evidence_ref": "ipfs://Qm...",
        "anonymity_set": 184
      },
      "proof": {
        "type": "Ed25519Signature2020",
        "verificationMethod": "did:web:deos.computing#sig-1",
        "proofValue": "z..."
      }
    }
  ]
}

2.1 credentialSubject fields

Field Required Meaning
id DID this assertion is about (MUST match the enclosing DID document's id)
scheme Personhood scheme identifier — see §3
tier weak | moderate | strong — see §4
evidence_ref optional URI to scheme-specific evidence (CID, audit log entry, etc.). MUST NOT contain biometrics or PII directly
anonymity_set optional Cardinality of the set this DID is indistinguishable within for this scheme (helps relying parties reason about ZK-friendliness)
expires_at optional If absent, use the VC's validUntil

Additional scheme-specific fields are permitted but MUST be namespaced (<scheme>:<field>) to avoid collision.

2.2 Multiple assertions

A DID MAY carry assertions from multiple schemes simultaneously. Relying parties evaluate the disjunction ("any one passes my floor") unless their policy explicitly requires conjunction.

A DID MAY carry assertions of the same scheme issued by multiple issuers. This supports trust-graph redundancy (e.g. Alice has social-graph attestations from three different attesting communities); duplicates of the same (scheme, issuer) pair are treated as a single assertion with the most-recent validFrom.


3. Schemes

A scheme is a named personhood-attestation mechanism. Schemes are not centrally registered; the scheme identifier is a URI-shaped string that points to its definition. Production schemes SHOULD publish their definition under a stable URI.

This spec normatively defines one scheme and lists three external schemes the verifier MUST recognize.

3.1 Normative: did-web/social-graph-v1

The minimum-viable scheme. Personhood is asserted by a set of attesting DIDs that the relying party trusts — typically a community of identified individuals who have met in person or otherwise have first-party knowledge of each other.

Issuer: a did:web (an organization or community).

Evidence: an evidence_ref pointing to a signed manifest listing the attesting DIDs (≥ N for tier moderate, ≥ M for tier strong, where N and M are scheme-policy constants).

"credentialSubject": {
  "id": "did:deos:alice",
  "scheme": "did-web/social-graph-v1",
  "tier": "moderate",
  "evidence_ref": "ipfs://Qm...",
  "anonymity_set": 1,
  "did-web/social-graph-v1:attestors_required": 5,
  "did-web/social-graph-v1:attestors_observed": 7
}

This scheme generates identified, not anonymous personhood — anonymity_set is typically 1 because the attesting DIDs are public. Relying parties that need privacy-preserving personhood MUST use a scheme with anonymity_set > 1.

Tier mapping for did-web/social-graph-v1 is scheme-policy:

3.2 Recognized: worldcoin/orb/v1

External scheme. Personhood proven via Worldcoin Orb biometric iris scan. Issuer is Worldcoin (a did:web-style root). Tier is strong; anonymity_set is the Orb-verified-human population at issuance time. Relying parties that include this scheme inherit Worldcoin's threat model — see Worldcoin's protocol for the full surface.

This spec does not bundle Worldcoin verifier code. Verifiers that wish to accept Worldcoin assertions MUST implement Worldcoin's verification path independently.

3.3 Recognized: government-vc/v1

External scheme. Personhood proven via a government-issued Verifiable Credential (mDL / eID / national ID). Issuer is a government's DID. Tier is typically strong; anonymity_set is typically 1 (identified) but MAY be larger via selective disclosure constructions.

3.4 Recognized: deposit-bond/v1

External scheme. Personhood proven by an on-chain or substrate-locked economic bond, slashable upon detected sybil-correlated behavior. Issuer is the bonding venue. Tier is operator-policy (weakstrong) per bond size. Useful for substrate operators who can't depend on biometric / government schemes but want a cost-of-sybil-creation floor.

3.5 Custom schemes

A substrate operator MAY define custom schemes. Custom scheme identifiers MUST be URIs (not bare names) so verifiers can disambiguate. Operators publishing custom schemes SHOULD document the tier semantics and the anonymity model.


4. Tier semantics

The tier field is a coarse portability hint for policy authors. It lets a relying party write required_tier: moderate without enumerating every scheme.

Tier Meaning Example schemes
weak A nonzero floor; better than nothing. Easy to acquire; easy to lose. Mostly useful for first-touch / try-it interactions. did-web/social-graph-v1 (1 attestor), small deposit bonds
moderate A meaningful floor for low-stakes commerce, social, and informational actions. Costs an attacker real effort or money to forge at scale. social-graph (5+ attestors), moderate deposit bonds
strong Suitable as a floor for high-stakes actions (large transactions, claims against the user, regulated workflows). Costs an attacker biometric resources or government collusion. worldcoin/orb/v1, government-vc/v1, large deposit bonds

The tier reflects attack cost, not anonymity guarantees. A weak worldcoin/orb/v1 is a contradiction (Orb scans are not weak); a strong did-web/social-graph-v1 is achievable but specific.

Relying parties MUST verify the underlying VC signature; they MUST NOT trust the tier field on its own. Scheme-specific fields MAY be inspected independently.


5. Verifier obligations

Given a DID document containing a personhoodAssertion array and a relying-party policy of the form:

policy:
  required_tier: moderate            # one of weak | moderate | strong
  required_schemes_any:              # optional whitelist
    - did-web/social-graph-v1
    - government-vc/v1
  required_schemes_all: []           # optional conjunction
  trusted_issuers:
    - did:web:deos.computing
    - did:web:state.example.gov
  reject_after_expiry: true
  reject_if_revoked: true

A conforming verifier MUST:

  1. Parse personhoodAssertion. If absent, reject with personhood:missing.
  2. For each VC in the array:
    • Verify the proof signature against the issuer's DID document.
    • Check validFrom <= now < validUntil (or expires_at).
    • Confirm credentialSubject.id matches the enclosing DID's id.
    • Confirm credentialSubject.scheme is recognized OR explicitly allow-listed by the policy.
    • If reject_if_revoked is set, check the scheme's revocation list (if defined).
  3. Apply policy:
    • required_schemes_any non-empty → at least one matching scheme must produce a passing VC.
    • required_schemes_all non-empty → every listed scheme must produce a passing VC.
    • required_tier → at least one passing VC must meet or exceed the tier.
    • All VCs from issuers not in trusted_issuers are filtered out before applying the rules above.
  4. Return one of pass | fail(reason).

A verifier MUST NOT silently accept an assertion from an unknown issuer or unrecognized scheme. Policy authors who wish to accept any trusted issuer must explicitly set trusted_issuers: ["*"] and document the implication.


6. Privacy-preserving disclosure

A personhoodAssertion in a DID document is public. Anyone who resolves the DID sees the array, including any evidence_ref. This is appropriate for did-web/social-graph-v1 (where the attesting DIDs are themselves public) but not for worldcoin/orb/v1 or government-vc/v1, where the user-visible privacy guarantee is meaningful.

For high-anonymity schemes, the recommended pattern is:

  1. The issuer signs a VC whose credentialSubject carries the assertion without an evidence_ref (or with one that resolves to a ZK commitment, not raw evidence).
  2. The DID document carries this VC publicly. Anyone resolving the DID sees tier=strong, scheme=worldcoin/orb/v1, anonymity_set=12.4M, and the issuer's signature.
  3. To prove a stronger fact ("I have a Worldcoin orb assertion and I am NOT the same person as DID X"), the DID controller generates a ZK proof and presents it out-of-band.

The DID document publishes the existence of an assertion; richer disclosure happens per-conversation, the same as with capability chains.

This spec does not standardize the ZK suite — that's per-scheme. v1.1 adds a personhoodProof artifact for inline ZK-proof attachment if demand materializes.


7. Composition with A2A and capability

An A2A agent card MAY require a personhood floor on inbound requests by extending its UCAN-extension SecurityScheme:

{
  "type": "https://projectmaya.deoscomputing.io/a2a/ext/ucan/v1#UcanSecurityScheme",
  "scheme_id": "maya-ucan-with-personhood",
  "audience_did": "did:web:amazon.com",
  "accepted_capabilities": [{ "with": "commerce.purchase", "max_amount_usd": 200 }],
  "chain_max_depth": 4,
  "personhood_policy": {
    "required_tier": "moderate",
    "trusted_issuers": ["*"]
  }
}

The server, when validating the UCAN chain (per a2a-ext/ucan/v1 §2.3), additionally resolves the chain's root issuer DID and applies the personhood policy. Failure returns UNAUTHENTICATED (401) with an opaque message; the detailed reason stays in the server log.

Personhood binds to the chain root, not every link. Intermediate agents are software, not humans; requiring personhood on them would either ban delegation or force agents to carry fake attestations. Personhood applies to the human at the root, and the chain binds intermediates back to that human.


8. Threat model

8.1 Sybil at issuance

An attacker tries to acquire many personhood assertions for fake identities. Defended by the scheme's own anti-sybil property — biometric (Worldcoin), government ID (state monopoly on identity issuance), social graph (real humans must vouch), deposit bond (cost-per-identity). This spec inherits each scheme's strength; an operator who picks a weak scheme inherits its sybil susceptibility.

8.2 Issuer collusion

A corrupted or coerced issuer issues VCs for non-existent humans. Defended by:

8.3 Key compromise

The DID's keys are stolen and the attacker masquerades. Defended by the underlying did:deos key-rotation and deactivation mechanism (did:deos v1 §7). A deactivated DID's personhood assertions become invalid as of the deactivation timestamp.

8.4 Coercion / hostage personhood

The DID controller is coerced into transferring or using their personhood-attested DID. This spec does not solve coercion; no signature-based system can. Two mitigations carry forward from the white paper:

8.5 Re-issuance after revocation

An attacker who got a personhood VC revoked tries to acquire a fresh one for the same human under a new DID. Defended at the scheme level, not the assertion level. Biometric schemes deduplicate at issuance (Worldcoin checks the iris hash); social-graph schemes deduplicate by the human (the attesting community recognizes the person regardless of DID). Deposit-bond schemes do not deduplicate — that is a known property of cost-based personhood.


9. Reference implementations

9.1 Substrate-side: DID document emitter

The substrate's POST /attestation/v1/did/register handler accepts an optional personhood_assertions: [VerifiableCredential, ...] parameter and includes it verbatim in the published DID document. The substrate does not verify the VCs at registration — that is the relying party's job. The substrate's role is custody of the DID document; the assertions are user-controlled content.

A Rust client helper (personhood::build_social_graph_assertion) and a TypeScript verifier (@deos/receipt/identity) ship in DEOS Computing's working repo. Public packages will follow once v1 stabilizes; §3.1 is self-contained for early implementers.

9.2 Relying party: verifier

The TS SDK ships verifyPersonhoodPolicy(didDocument, policy) returning a PersonhoodResult { pass, matchingSchemes, reason? }. A2A servers that wish to apply a personhood floor call this after the UCAN chain walk and before invoking the action handler.


10. Versioning

v1.0. The URI https://projectmaya.deoscomputing.io/identity/personhood/v1 is immutable; breaking changes go to /v2.

Likely v1.1 additions:


11. Maintainer

DEOS Computing — pull requests, scheme proposals, and policy critiques to github.com/DEOS-Computing.

License: CC BY 4.0 (text), Apache-2.0 (reference code).