IdentityEvidence — Mentionable v0.1
Status: Draft v0.1.
Extension URI: https://mentionable.dev/ns/identity/v0.1
Deprecated alias: https://mentionable.dev/spec/identity/v0.1 (accepted on inbound only during the transition window — see ../wiki/url-scheme.md and issue #503; outbound emit MUST use the canonical /ns/ URI).
Last updated: 2026-05-06
This document defines the transport-neutral envelope Mentionable transport modules and Connectors use to surface already-verified caller identity to agents.
IdentityEvidence is not an interactive authentication protocol. It is the
ambient identity layer: a transport module or Connector verifies native
platform/auth material (DKIM, ActivityPub signatures, Slack request signing,
OAuth, SIWE, agent signatures, etc.) and records the result in a common shape.
When that evidence is not sufficient for the requested operation, the agent emits a
PolicyPart{kind:"unauthorized"} or PolicyPart{kind:"consent_required"} to
step the user up.
1. Design split
The responsibility boundary is deliberate:
- Transport module or Connector verifies native credentials and creates evidence.
- Core defines the envelope, structural validation, metadata carriers, and AgentCard policy vocabulary.
- Agent/runtime policy decides which issuers, methods, and assurance levels are acceptable for a purpose.
Mentionable core MUST NOT keep a closed enum of identity methods. New platform Connectors and transport modules add method strings without changing core.
2. Shape
type IdentityEvidence = {
id?: string
subject: string
issuer: string
method: string
assurance: 'platform' | 'domain' | 'address' | 'agent' | 'oauth' | 'wallet' | 'delegated' | string
audience: string | string[]
issued_at: string
not_before?: string
expires_at?: string
on_behalf_of?: string[]
claims?: Record<string, unknown>
source?: {
transport?: string
transport_module?: string
connector?: string
channel?: string
[key: string]: unknown
}
proof:
| { type: 'transport'; verified_by: string; key_id?: string }
| {
type: 'signed-attestation'
alg: string
kid: string
value: string
canonicalization?: string
}
| { type: 'bearer-token'; verified_by: string; token_type?: string; key_id?: string }
| { type: 'siwe'; verified_by: string; chain_id: number; address: string }
| { type: string; [key: string]: unknown }
}
Field contracts:
subjectis the principal asserted by the evidence. Examples:mailto:alice@example.com,acct:alice@example.social,slack:T123/U456,@agent@example.com,eip155:1:0xabc....issueris who produced the evidence. Native transport-module evidence MAY use a deployment-local URN. Public Connectors SHOULD use a resolvable DID, Connector Card host, AgentCard, or OAuth issuer URL.methodis an open string. Well-known Mentionable method tokens are listed in §5, but implementations MUST preserve unknown methods.assurancenames what kind of binding the evidence claims. It is not a universal level number; policy interprets it withissuerandmethod.audienceMUST include the receiving agent address before an agent relies on the evidence.claimsMUST NOT contain secrets. Email/profile claims are correlation hints unless a policy explicitly links them.proof.type:"transport"means the receiving transport module verified native credentials inside the same trust boundary. Atransportproof MUST NOT be forwarded across a public/untrusted boundary as authenticated identity unless the enclosing request is itself authenticated to a trusted component.proof.type:"signed-attestation"is the portable cross-boundary proof. The issuer signs the canonical JSON payload with theprooffield omitted. Whencanonicalizationis present,jcsmeans RFC 8785-style JSON canonicalization. Receivers resolve the issuer’s verifying key via the issuer’s advertised mechanism (Connector Card, AgentCard, DID, JWKS, etc.), verifykid/alg/value, then apply local issuer/method policy. A valid remote signature only proves control of the advertised key; it does not mean the receiver trusts that Connector or accepts the asserted subject.audiencematching is exact. Mentionable agent recipients SHOULD be canonicalized as@<local>@<domain>before minting or checking evidence.
2.1 Profile Claims
Verified identity evidence MAY carry presentation facts under
claims.profile. The shape matches SenderProfile in
normalized-message.md:
{
"claims": {
"profile": {
"display_name": "JC",
"username": "jc",
"avatar": { "url": "https://avatars.slack-edge.com/..." },
"locale": "ko-KR",
"timezone": "Asia/Seoul",
"provider": "slack",
"provider_subject": "slack:T123/U456",
"fetched_at": "2026-05-06T00:00:00.000Z",
"extensions": {
"slack": {
"team_id": "T123",
"user_id": "U456"
}
}
}
}
}
Receivers that have verified the evidence signature, audience, freshness, and
local trust policy MAY project claims.profile into
NormalizedMessage.sender.profile. Profile claims are not principals. They are
mutable, provider-controlled facts for attribution and UI; authorization must
continue to use subject, issuer, method, assurance, and local policy.
Connectors MUST whitelist profile fields and MUST NOT forward raw provider
objects or secrets.
3. Carriers
3.1 NormalizedMessage
Transport modules and Connectors attach evidence to
NormalizedMessage.sender.identities.
sender.auth_method and sender.verified remain the compact compatibility
view. Agents that need extensible identity policy SHOULD read
sender.identities.
3.2 A2A
Mentionable callers carry evidence under:
{
"message": {
"metadata": {
"mentionable": {
"identity_evidence": []
}
}
}
}
The receiving A2A transport module treats this metadata as caller-controlled. It MUST
NOT attach entries to sender.identities merely because they are structurally
valid. It MAY attach forwarded entries only after verifying an independently
portable proof such as signed-attestation, checking the audience/freshness,
and applying its configured trust policy. If no forwarded-evidence verifier is
configured, the safe default is to drop this metadata.
Forwarded signed-attestation evidence MUST be short-lived. The reference
profile requires expires_at, rejects attestations older than 10 minutes at
receiver time, and rejects expires_at - issued_at values longer than 10
minutes, with up to 60 seconds of clock skew for issued_at / not_before.
Separately, when the A2A transport module verifies the enclosing bearer token
through an AuthVerifier, it MAY mint local bearer-token evidence for the verified
subject/method. Claims obtained by merely decoding a JWT without
cryptographic verification are diagnostic only and MUST NOT be copied into the
trusted evidence envelope.
3.3 REST
REST callers SHOULD use existing HTTP authentication channels as the primary
proof surface: Authorization for bearer/OAuth/SIWE-derived tokens,
Signature-Input / Signature for HTTP Message Signatures and agent
self-sign profiles, Cookie for same-site browser sessions, and mTLS where
the deployment already uses client certificates. After a REST transport module
verifies one of those channels, it surfaces the normalized result in
sender.identities.
When a transport module, Connector, or gateway needs to forward an already-normalized evidence array, it MAY use:
Mentionable-Identity-Evidence: <base64url(JSON array of IdentityEvidence)>
Mentionable-Identity and X-Mentionable-Identity are accepted as legacy
aliases. Malformed headers are ignored; they do not make the request malformed.
This header is not a replacement for REST authentication. Public REST
receivers MUST drop unsigned transport evidence from arbitrary callers unless
the request itself was authenticated to a trusted component. Portable
forwarded evidence SHOULD use signed-attestation and receivers MUST verify
the signature, audience, and freshness before attaching it to
sender.identities. If the verifying key is discovered through a Connector
Card host named by the evidence, the receiver MUST match that issuer against a
local Trusted Connector Issuer policy before fetching remote metadata.
3.4 ActivityPub and Email
AP and Email transport modules do not need an extra carrier for native inbound
messages. They populate sender.identities after verifying the protocol-native
proof.
4. AgentCard Policy
Agents advertise identity acceptance policy under
mentionable.identity_policy:
{
"mentionable": {
"identity_policy": {
"default": "accept-any-valid-evidence",
"accepts": [
{
"issuers": ["did:web:slack-connector.example"],
"methods": ["urn:mentionable:auth:slack-workspace-member:v0.1"],
"assurance": ["platform"],
"purposes": ["basic-use", "terms-invocation"]
}
],
"step_up_required_for": ["payment", "delegation", "destructive-action"]
}
}
}
default:"accept-any-valid-evidence" is appropriate for open agents that only
need rate-limit keys and invocation-based terms acceptance. Sensitive agents
SHOULD use deny-by-default and explicit accepts[] rules.
This advertised policy is about what the agent will accept after evidence is verified. It is not a remote-metadata fetch policy. Runtime deployments that verify Connector-issued forwarded attestations SHOULD maintain a local Trusted Connector Issuer allow-list keyed by issuer/Connector host, method, and optionally assurance and subject namespace.
5. Well-Known Methods
The reference implementation recognizes these method strings:
| Method | Subject example | Typical assurance |
|---|---|---|
email-dkim | mailto:alice@example.com | address |
email-dmarc | mailto:alice@example.com | domain |
ap-http-signature | acct:alice@example.social | agent |
ap-object-integrity-proof | acct:alice@example.social | address |
a2a-jwt | @agent@example.com | agent |
a2a-oauth | issuer-specific subject | oauth |
urn:mentionable:auth:agent-self-sign:v0.1 | @agent@example.com | agent |
urn:mentionable:auth:slack-workspace-member:v0.1 | slack:T123/U456 | platform |
x-account-author:v0.1 | x:1234567890 | platform |
urn:mentionable:auth:oauth:v0.1 | issuer-specific subject | oauth |
urn:mentionable:auth:siwe:v0.1 | eip155:1:0xabc... | wallet |
x-account-author:v0.1 is issued by the X Connector
(examples/x-connector). The X Connector polls a
connected bot account’s mention timeline via OAuth; the X API guarantees each
mention’s author_id, which is the trust anchor (the @bot text mention is
forgeable, the author_id is not). The Connector attests “this mention’s sender
is X user_id=<author_id>, @<username>” at platform assurance
(Connector-relayed, like Slack), signs it with its Connector Card Ed25519 key
(issuer mentionable-x), and carries it in sender.identities[]. Claims are
built only from X-API-provided user_id / username / name; the Connector’s
OAuth token never appears in claims or evidence.
Recommended future additions for this repository:
- GitHub App / OAuth user for the gitagent transport module, repo analyzer, and GitHub-hosted setup flows.
- Microsoft Entra ID / Teams user for a future Teams Connector; this is the natural enterprise counterpart to Slack workspace identity.
- Discord interaction signature for a Discord Connector; Discord’s Ed25519
interaction signature maps cleanly to
platformassurance.
6. Chained Agent Calls
When one agent calls another on behalf of an upstream user, the downstream agent SHOULD receive at least:
- The direct caller agent’s own evidence.
- Any upstream user/platform evidence the caller is allowed to forward.
- An
on_behalf_ofchain or signed delegation tying the two together when the downstream operation depends on the upstream user’s authority.
For low-risk composition, the direct agent evidence may be enough. For account data, payment, delegated authority, or destructive operations, downstream agents SHOULD require explicit consent/delegation and use PolicyPart for step-up.
7. Security Rules
- Evidence MUST be audience-bound before authorization decisions.
- Evidence MUST be time-bound when it crosses a process or origin boundary.
- Public receivers MUST apply local Trusted Connector Issuer policy before fetching Connector Cards or other remote metadata named by caller-provided evidence.
- Public receivers MUST NOT treat “signature verifies against a remote Connector Card” as policy acceptance. Signature verification and issuer trust are separate checks.
- Replay-sensitive evidence SHOULD carry
id/jtiand be checked once. - A profile email claim is a join hint, not a global account link. Treat
issuer + subjectas the principal key unless explicit account linking has occurred. transportproofs are not portable across untrusted boundaries. Public Connectors SHOULD issuesigned-attestationproofs using keys discoverable via DID, Connector Card, AgentCard, or JWKS.