ANP Profile 1: Core Binding (Final Revision)
May 30, 2026 ยท View on GitHub
- Document ID: ANP-P1
- Title: Core Binding
- Status: Draft
- Version: 0.2.0 (Final Revision)
- Language: English
- Applicability: This profile applies to all ANP basic profiles and security overlay profiles.
1. Purpose
This Profile defines ANP's unified outer message bindings, common fields, capability negotiation, error models, and interoperability constraints.
The goals of this Profile are:
- Provide a unified message envelope for all ANP methods;
- Avoid repeatedly reinventing request, response, notification, and error formats for different application profiles;
- Provide a common foundation for Profiles such as Direct Base, Group Base, Direct E2EE, Group E2EE, Attachment, Federation, etc.;
- While retaining the basic compatibility of JSON-RPC 2.0, tighten the optional degrees of freedom and reduce cross-implementation ambiguity.
2. Terminology and Normative Conventions
2.1 Normative Keywords
In this article, MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, OPTIONAL are interpreted as normative requirements according to their capitalized form.
2.2 Terminology
- ANP Endpoint: The protocol endpoint that implements ANP, usually the entrance service of the domain where the Agent is located, the group Host service, or other declared service endpoint.
- Request: JSON-RPC call object with
id. - Notification: JSON-RPC call object without
id. - Result:
resultmember in the Successful Response object. - Error:
errormember in the failure response object. - Profile: ANP's protocol capability unit, such as
anp.direct.base.v1. - Security Profile: Security semantic unit of ANP, such as
transport-protected,direct-e2ee,group-e2ee. - Operation: A protocol action that can be recognized idempotently, such as sending a message, creating a group, adding a member, or submitting a group state change.
- Message-bearing Operation: Operation carrying application layer message payload, such as
direct.send,group.send,group.e2ee.send. - Message-bearing Notification: A notification used to carry an application-layer message payload, such as
direct.incoming,group.incoming, orgroup.e2ee.notice. - Control Operation: does not carry application layer business messages, but operations that change the protocol or business state, such as
group.create,group.add, andgroup.remove. - Origin Proof: Application layer origin proof generated by the business subject's private key and carried through
auth.origin_proof. - Object Proof: A verifiable object-level assertion made by object-embedded
proofon the "entire object withproofremoved". - Signed Request Object: A shared normalized business object composed of
method,meta, andbodyand used to calculatecontentDigest.
3. Design Principles
3.1 Layering principle
ANP uses the following layering:
- Transport layer: HTTP(S), WebSocket Secure and other secure transmission;
- Binding layer: JSON-RPC 2.0 binding defined by this Profile;
- Business layer: Business semantics such as Direct Base and Group Base;
- Security Overlay layer: Direct E2EE, Group E2EE and other security semantics;
- Media/Object layer: Large object extensions such as Attachment.
To help readers quickly build an overall mental model of ANP layering boundaries, the following diagram gives an overview from the transport layer to the media/object layer. Subsequent Profiles further constrain their own objects, flows, and requirements on top of this layering framework.
flowchart TB T[Transport Layer<br/>HTTPS / WSS / secure channel] B[Binding Layer<br/>anp.core.binding.v1<br/>JSON-RPC 2.0 / meta / auth / body] D[Business Layer<br/>Direct Base / Group Base] S[Security Overlay Layer<br/>Direct E2EE / Group E2EE] M[Media / Object Layer<br/>Attachment / object transfer] T --> B --> D --> S --> M
Figure P1-1: ANP layering overview (non-normative).
This diagram emphasizes responsibility boundaries rather than deployment topology: an implementation may merge multiple layers into the same service, but implementations should still preserve the semantic separation of these layers for cross-implementation interoperability.
3.2 Minimum interoperability principle
Different implementations can share the same as long as they meet this Profile constraint:
- Request/response format;
- Notification format;
- Common field semantics;
- Capacity negotiation methods;
- Error model;
- Idempotent processing principle.
3.3 Non-Goals
This Profile does not define the following capabilities:
- History pull;
- Read status;
- Device synchronization;
- online status;
- Internal copy consistency;
- Specific E2EE algorithm.
These capabilities must be defined by other Profiles or explicitly stated as being outside the scope of the ANP standard.
3.4 Profile identification
The standard name of this Profile is:
anp.core.binding.v1
Subsequent Profiles MUST use this name to reference this Profile when declaring dependencies.
4. Binding basics
4.1 JSON-RPC version
ANP Core Binding MUST use JSON-RPC 2.0.
The jsonrpc member MUST in every request object and response object is exactly equal to the string "2.0".
4.2 Secure transmission requirements
All ANP bindings MUST run over a certified secure transport layer, such as:
- HTTPS;
- WSS;
- Other secure channels that provide confidentiality, integrity and peer authentication.
This profile does not allow operation over unauthenticated, unencrypted raw transfers.
4.3 Transport independence
This Profile is logically transport-agnostic; HTTP(S) and WSS are the recommended bindings, but not the only allowed bindings. Any new binding that does not change the message object semantics of this Profile is defined as a supplementary binding document.
5. JSON-RPC interoperability constraints
5.1 params form
The original JSON-RPC specification allowed params to take either a per-position array or a per-name object.
In ANP, params MUST be an object; MUST NOT use array form.
If the array form params is received, the receiver MUST return an anp.invalid_params_shape error.
5.2 id type
The original JSON-RPC specification allowed id to be a string, a number, or null.
In ANP, id MUST of Request is a non-empty string.
ANP Request MUST NOT use the number id.
An ANP request MUST NOT use null as id.
If an id that does not meet the requirements is received, the receiver MUST return anp.invalid_request_id.
5.3 Notification usage scope
In ANP, Notification is only used in the following scenarios:
- Asynchronous events actively pushed by the peer;
- One-way prompts that do not require confirmation and should not return error details.
The following operations MUST NOT use Notification:
- Control operations that change persistent state;
- Sending messages that require idempotent confirmation;
- Any operation that requires the caller to perceive success or failure.
5.4 Batch prohibited
JSON-RPC batch calls MUST NOT be used in ANP.
Client MUST NOT send batches.
When the server receives the batch, it MUST reject it and returns anp.batch_not_supported.
5.5 Method name constraints
The method name MUST be a string and follows the following naming rules:
- Use logical namespace;
- Start with a lowercase letter;
- Use
.to separate sections; - The method name MUST NOT start with
rpc.; - Business method SHOULD use
<domain>.<action>style.
Recommended examples:
anp.get_capabilitiesdirect.sendgroup.creategroup.addgroup.send
5.6 Response constraints
Except for Notification, the server MUST return a Response for each Request.
Successful Response MUST contain result, and MUST NOT contain error.
The failure response MUST contain error, and MUST NOT contain result.
Response's id MUST be exactly the same as the corresponding Request's id.
6. Generic params structure
6.1 Top-level objects
With certain exceptions, ANP's params MUST have the following structure:
{
"meta": { "...": "..." },
"auth": { "...": "..." },
"body": { "...": "..." }
}
Among them:
meta: general metadata, carrying interpretation Profile, target, idempotent, security profile, etc.;auth: Optional authentication and certification object; only appears when explicitly required by the specific Profile;body: Method specific parameters.
If auth is not defined for a specific Profile, the caller MAY omit it.
If a specific Profile explicitly requires auth, the caller MUST provide it and the recipient MUST validate it.
Top-level params members other than meta, auth, and body are only allowed to appear if the corresponding Profile is explicitly defined.
The following diagram consolidates the outer envelope that appears repeatedly in this Profile into a single view. It helps readers understand which structures are shared by Request, Notification, and Response, and what responsibilities are carried by meta, auth, and body.
flowchart TB A[ANP JSON-RPC Object] A --> Req[Request<br/>with id] A --> Noti[Notification<br/>without id] A --> Resp[Response] Req --> Params[params] Noti --> Params Params --> Meta[meta<br/>profile / security_profile / sender_did / target / operation_id / message_id / content_type] Params --> Auth[auth<br/>present only as required by the specific Profile] Params --> Body[body<br/>method-specific parameters] Resp --> Ok[Successful Response<br/>result] Resp --> Err[Failure Response<br/>error]
Figure P1-2: ANP JSON-RPC envelope structure (non-normative).
Subsequent business Profiles and security overlays should extend only body and the necessary auth constraints, rather than inventing another top-level binding structure that conflicts with this diagram.
6.2 meta object
The meta object fields are defined as follows:
6.2.1 anp_version
- Type: string
- Requirements: MAY
- Semantics: ANP major version prompt
- Default: If omitted, the receiver MUST interpret it as
"1.0" - Description:
- This field is reserved for explicit debugging or cross-version gateways;
- In v1,
profileis used first to determine the interpretation rules; - New implementation of SHOULD treat this as a compatibility field rather than a primary negotiation field.
6.2.2 profile
- Type: string
- Requirements: MUST
- Semantics: the only interpretation of this request Profile
- Description:
profileis used to declare "which Profile interprets thebody,result, error constraints and method semantics of the current request";profileMUST NOT express the union semantics of multiple profiles at the same time;security_profileonly expresses security profile and does not replaceprofile.
- Example:
"anp.direct.base.v1""anp.group.base.v1""anp.direct.e2ee.v1""anp.group.e2ee.v1"
6.2.3 security_profile
- Type: string
- Requirements: MUST
- Semantics: security profile for this call
- Allowed values:
"transport-protected""direct-e2ee""group-e2ee"
- Description:
security_profileindicates the security profile currently used by Request Requirements;- It describes the security level or security semantics, not the interpretation syntax of
body; - If an
profileonly allows certainsecurity_profilecombinations, this must be explicitly specified by the corresponding Profile.
6.2.4 sender_did
- Type: String (DID)
- Requirements: In addition to anonymous public discovery capabilities, MUST
- Semantics: The sending subject DID of this request in terms of business semantics (business origin DID / logical sender DID)
- Description:
- For ordinary Request,
sender_didSHOULD indicate the current business initiator; - For Notifications generated by the server, whether
sender_didis allowed to be omitted or other fields are used to express the logical issuer is defined by the specific Profile; sender_didMUST NOT be automatically equated to the one-hop caller identity of the outer transport connection.
- For ordinary Request,
6.2.5 target
- Type: Object
- Requirement: MUST when a method has a protocol-level target
- Structure:
{
"kind": "agent | group | service",
"did": "did:example:..."
}
- Description:
kind = "agent"indicates that the target is a single Agent;kind = "group"indicates that the target is a single group;kind = "service"indicates that the target is a publicANPMessageService.serviceDid;target.didMUST NOT directly carries the transport layer URL;- Any method profile MUST explicitly declare whether it is
agent-addressed,group-addressed,service-scoped, orendpoint-local; - Whether
targetis allowed to be omitted, MUST be explicitly declared by the specific Profile, and the caller and receiver MUST NOT can guess by themselves. - If a method requires
auth.origin_proof, thenmeta.targetMUST be present andmeta.target.kindMUST be one ofagent,group, andservice.
6.2.5.1 Target modeling pattern declaration rules
In order to eliminate the bifurcation of interpretations of target by different Profiles, the specific Profile MUST explicitly declares which of the following target modeling modes its methods belong to:
-
agent-addressed
meta.target.kind = "agent"meta.target.didpoints to the target Agent DID
-
group-addressed
meta.target.kind = "group"meta.target.didpoints to the target Group DID
-
service-scoped
meta.target.kind = "service"meta.target.didpoints to target publicANPMessageService.serviceDid
-
endpoint-local
meta.targetis allowed to be omitted only if the corresponding Profile explicitly declares it
If a method is not explicitly declared endpoint-local by its profile, the receiver MUST handle it as "explicit target required".
If the meta.target.kind of a request is inconsistent with the target modeling mode declared by this method, the receiver MUST return anp.invalid_target_binding.
6.2.6 operation_id
- Type: string
- Requirement: All operations that change state MUST
- Semantics: Idempotent identifier of this operation
- Rules:
operation_idMUST remain unchanged when the same initiator retries in the same semantic context;- Idempotent scope MUST be clearly defined by a specific Profile;
- The server MUST perform idempotent hit checking first, and then performs optimistic concurrency or version precondition checking;
- For message-type operations, the sender SHOULD directly sets
operation_id = message_id, unless it really needs to distinguish between "message identification" and "operation retry identification".
6.2.7 message_id
- Type: string
- Requirement: Message-bearing Operation MUST
- Semantics: application layer message identification
- Description:
message_idis used for message-level unique identification or duplicate identification;message_idandoperation_idcan be the same or different;- If the implementation does not have an independent operation life cycle, SHOULD directly reuses
message_idasoperation_id; message_idMUST NOT implicitly replaces the general idempotent semantics ofoperation_id, unless the corresponding Profile explicitly allows the same;- This constraint also applies when the specific method is message-bearing Notification.
6.2.8 created_at
- type: string (RFC 3339 time)
- Requirements: SHOULD
- Semantics: timestamp when the initiator created the operation
- Note: Unless otherwise specified in the subsequent Profile,
created_atshall not be used as the only basis for anti-replay.
6.2.9 trace_id
- Type: string
- Requirement: No longer as a standard interoperable field
- Semantics: implement internal tracking identifiers
- Description:
- If the deployment requires cross-service tracking, SHOULD use transport layer metadata or private extension fields (such as
x_trace_id); - The recipient MUST NOT incorporate this into any security semantics, authorization judgments, or idempotence judgments.
- If the deployment requires cross-service tracking, SHOULD use transport layer metadata or private extension fields (such as
6.2.10 content_type
- Type: string
- Requirement: Message-bearing Operation MUST
- Semantics: The main business payload type of the current message operation; if the current Profile / Overlay uses an independent outer envelope, it indicates the type of the outer envelope.
The rules are as follows:
- In a base profile, if
bodyis only a structured carrier (for example, a mutually exclusivetext/payload/payload_b64ustructure),meta.content_typeMUST describe the primary business payload type carried in that structure, not the type of the JSON carrier object itself; - In the Security Overlay, if
bodycarries an independent ciphertext envelope, thenmeta.content_typeMUST represent the wire object type of the outer envelope; - If the original application content type is different from the outer envelope type, MUST be expressed by the corresponding Overlay in its internal field (such as
application_content_type); - When the specific method is message-bearing Notification, this rule also applies;
- The base interpretation of
meta.content_typeis defined exclusively by this profile; other application profiles and security overlays MUST NOT redefine its base semantics.
Example:
- Direct Base text message:
text/plain - Group Base JSON message:
application/json - Direct E2EE text message: outer
meta.content_type = "application/anp-direct-cipher+json", innerapplication_content_type = "text/plain" - Group E2EE Attachment Message: Outer
meta.content_type = "application/anp-group-cipher+json"
When the business payload is ordinary structured JSON, the content type MUST be
application/json and the JSON object MUST be carried directly in body.payload
or in the security overlay's inner payload. Profiles and applications MUST NOT
define additional content types solely to distinguish business meanings such as
commands, status updates, tasks, or results. Those meanings are application-level
semantics inside the JSON object and are outside this core binding layer.
Among them, if the inner original business type of Group E2EE is an attachment list, it should be written in the inner plain text:
{
"application_content_type": "application/anp-attachment-manifest+json"
}
And not continue writing the attachment list type in the outer meta.content_type.
6.3 body object
The body object is a method-specific parameter collection:
- Business Profile MUST define its fields;
- Security Overlay Profile MUST define its cryptography fields;
- Whether the unrecognized fields in
bodycan be ignored, MUST be clearly stated by the corresponding Profile; - The receiver MUST reject unknown fields that affect security, routing, permissions, idempotence, or state machine semantics.
7. Payload Representation Rules
7.1 JSON object first
Any business object that can be naturally expressed as a JSON object is directly represented as a JSON object. ANP MUST NOT use double serialization of "JSON within a JSON string" as the default practice.
7.2 Binary representation
When binary payload needs to be transmitted, the field MUST be represented by unpadded base64url text.
Related field names SHOULD end with _b64u, for example:
ciphertext_b64ukey_package_b64uwelcome_b64u
7.3 Numerical representation
In order to avoid differences in the representation of large integers, counters, and serial numbers in different languages, the following fields MUST be represented by decimal strings:
- Counter;
- serial number;
- logical clock;
- epoch;
- generation;
- Large integer length;
- Any value that may exceed the range of IEEE 754 double-safe integers.
If the subsequent Profile needs to perform standardized signature on JSON, the serialization rules for the signature input must be clearly defined. Once a Profile defines a Signed Payload or equivalent cryptographic binding object, the Profile MUST specify a unique normalization algorithm; different implementations MUST NOT choose different "stable serialization" strategies.
8. Capability Negotiation
8.1 General
An ANP endpoint MUST expose the capability-negotiation interface. The results of capability negotiation MUST include at least:
- List of supported ANP Profiles;
- Supported Security Profile list;
- Runtime service identity;
- Implement constraints (such as maximum payload, maximum object size, throttling policy, etc.).
The implementer MAY return more fine-grained extended fields (such as supported content types, method-level capabilities, Notification capabilities, authentication scheme capabilities), but these extended fields do not affect the minimum standard response structure defined in this section.
8.2 Standard method: anp.get_capabilities
8.2.1 Request
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "anp.get_capabilities",
"params": {
"meta": {
"profile": "anp.core.binding.v1",
"security_profile": "transport-protected",
"operation_id": "op-cap-001",
"created_at": "2026-03-29T12:00:00Z"
},
"body": {}
}
}
Notes:
anp.get_capabilitiesMAY be called as an anonymous public discovery capability;- When calling anonymously,
meta.sender_didMAY be omitted; - If the server returns different capability subsets based on identity, the caller MAY call again in the authenticated context.
8.2.2 Successful Response
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"service_did": "did:example:service",
"supported_profiles": [
"anp.core.binding.v1",
"anp.direct.base.v1",
"anp.group.base.v1",
"anp.direct.e2ee.v1"
],
"supported_security_profiles": [
"transport-protected",
"direct-e2ee"
],
"limits": {
"max_request_bytes": "1048576",
"max_message_bytes": "262144"
},
"supported_content_types": [
"text/plain",
"application/json",
"application/anp-attachment-manifest+json"
]
}
}
Notes:
result.service_didindicates the service identity DID corresponding to the current runtime capability result;- Static DID documents only provide hints, and runtime capabilities are subject to this result;
supported_content_typesis a recommended extension. Where practical, servers SHOULD return it.
8.3 Negotiation Rules
- Static extension fields in DID documents only represent cacheable static hints;
- The return result of
anp.get_capabilitiesindicates the runtime authority; - If the static hint conflicts with the runtime capability, the caller MUST take the runtime capability result as the criterion and refreshes the cache;
- The caller SHOULD obtain the target service capabilities before the first interaction or after the cache expires;
- If
profileorsecurity_profilein the request is not supported, the server MUST return an explicit error; - The caller MUST NOT assume that support for a base profile implies support for an E2EE overlay.
Static hints in DID documents and runtime capability results are easy for implementers to confuse. The following diagram fixes the recommended negotiation order and highlights the principle that static information is used for discovery, while runtime results are used for final decisions.
sequenceDiagram participant C as Caller participant D as DID Document participant S as ANPMessageService C->>D: Resolve target DID D-->>C: serviceEndpoint + static hints C->>S: anp.get_capabilities S-->>C: service_did + supported_profiles + supported_security_profiles + limits Note over C,S: Runtime results take precedence over static hints C->>C: Refresh cache and select the actual profile / security_profile
Figure P1-3: Capability negotiation and runtime authority (non-normative).
When static hints conflict with runtime capabilities, implementations should follow the runtime result shown in this diagram and treat the conflict as a signal to refresh the local cache.
9. Idempotence and retry
9.1 Idempotence principle
All state-changing operations MUST support idempotence.
Duplicate request for the same (sender_did, target_scope, method, operation_id):
- If semantically equivalent, the server MUST return the same result or an equivalent result;
- If there is a semantic conflict, the server MUST return
anp.idempotency_conflict.
Among them:
- The specific value of
target_scopeMUST be defined by the corresponding Profile; - For Direct class methods,
target_scopeis usuallytarget.did; - For Group class methods,
target_scopeis usuallygroup_did.
9.2 Message retry
For message sending operations:
message_idMUST remain unchanged when retrying;operation_idMUST remain unchanged when retrying;- If the implementation has no independent operation semantics, the sender SHOULD make the two directly the same;
- The server MUST check operation-level idempotent records first;
- The key used for message-level repeat identification (such as whether it contains
message_id) must be explicitly defined by the corresponding message Profile.
9.3 Non-idempotent operations
If an operation is inherently not idempotent, the corresponding Profile MUST be clearly marked and an alternative remediation mechanism is provided. Those not explicitly marked are always considered to be idempotent.
10. Error model
10.1 General
ANP uses JSON-RPC's error object to host errors.
ANP retains the original semantics of JSON-RPC standard error codes, while defining ANP's own application error codes.
For the following situations, the server SHOULD preferentially uses JSON-RPC standard error codes:
| Scenario | Recommended JSON-RPC error code |
|---|---|
| Unable to parse JSON | -32700 Parse error |
| Illegal JSON-RPC object | -32600 Invalid Request |
| Method does not exist | -32601 Method not found |
| Illegal parameter shape | -32602 Invalid params |
| Server internal exception | -32603 Internal error |
For ANP business layer errors, the server SHOULD use the 1000+ error codes defined in this document, and also provides machine-readable semantics in error.data.anp_code.
10.2 ANP Error Object Extension
error object suggestion structure:
{
"code": 1001,
"message": "Unsupported profile",
"data": {
"anp_code": "anp.unsupported_profile",
"retryable": false,
"details": {}
}
}
error.data.anp_code MUST exist when code belongs to the ANP custom error scope.
10.3 ANP public error code
code | anp_code | Meaning |
|---|---|---|
| 1000 | anp.invalid_request_id | id Illegal |
| 1001 | anp.unsupported_profile | The requested Profile is not supported |
| 1002 | anp.unsupported_security_profile | The requested security profile is not supported |
| 1003 | anp.invalid_params_shape | params The structure does not meet the requirements |
| 1004 | anp.batch_not_supported | Batch not supported |
| 1005 | anp.unauthorized | Failed to pass certification |
| 1006 | anp.forbidden | Authenticated but no authority |
| 1007 | anp.target_not_found | Destination DID does not exist or is unreachable |
| 1008 | anp.idempotency_conflict | Idempotent key conflict |
| 1009 | anp.unsupported_content_type | Content type not supported |
| 1010 | anp.delivery_rejected | The target service refused to receive |
| 1011 | anp.rate_limited | Trigger current limit |
| 1012 | anp.temporarily_unavailable | Service temporarily unavailable |
| 1013 | anp.invalid_security_binding | security profile and payload structures do not match |
| 1014 | anp.invalid_target_binding | The target modeling mode required by the method does not match the actual meta.target |
10.4 Error return requirements
- For ANP custom errors, the server MUST return machine-determinable
anp_code; messageSHOULD be short and readable;data.retryableSHOULD indicate whether the caller may retry;- Any errors MUST NOT leak unnecessarily sensitive internal state.
- SHOULD return
anp.invalid_target_bindingfor target binding errors, misuse of service-scoped / endpoint-local, etc.
11. Method registration and namespace
11.1 Namespace
It is recommended to use the following first-level namespace:
anp.*direct.*group.*attachment.*federation.*
11.2 Version Management
Profile name MUST be explicit with version, for example:
anp.core.binding.v1anp.identity.discovery.v1anp.direct.base.v1
11.3 Extension methods
The implementer MAY define private extension methods, but:
- MUST NOT have the same name as a standard method;
- Implementations SHOULD use a private prefix;
- Implementations MUST NOT assume that other implementations understand these methods.
12. Compatibility and version evolution
12.1 Forward Compatibility
The receiver's processing rules for unknown extended fields are as follows:
- Receiver MUST reject unknown core
metafield; - Extend the
metafield for implementations starting withx_, ignored by the receiver MAY; - For unknown
authfields, the receiver MUST reject them unless the corresponding Profile explicitly states that they can be extended; - For unknown
bodyfields, the receiver will MAY ignore them only if the corresponding Profile explicitly states that they can be ignored; - If the unknown field affects security, routing, permissions, idempotence, or state machine semantics, the receiver MUST reject.
12.2 Destructive changes
The following changes are considered breaking changes and the Profile major version must be upgraded:
- The meaning of the
metafield changes; - Changes in error code semantics;
- Semantic changes in method names;
- security profile semantic changes;
- The payload structure is no longer compatible.
13. Security Considerations
13.1 Security Profile Fixed
The caller and server MUST NOT silently downgrade from high security profile to low security profile without explicit negotiation.
If the target does not support the requested security_profile, the server MUST explicitly return anp.unsupported_security_profile.
13.2 Timestamp is not the main anti-replay mechanism
created_at MUST NOT be used as the sole anti-replay mechanism.
Anti-replay should be defined by subsequent Profiles in session state, message state or group state.
13.3 Tracking field isolation
trace_id, log label, monitoring field MUST NOT participate in any cryptographic binding or business authorization judgment.
13.4 Payload Mutual Exclusion
If a Profile defines body.payload and body.payload_b64u as mutually exclusive fields, the sender MUST NOT provide both at the same time; the receiver MUST reject when receiving conflicting input.
When meta.content_type is application/json, the corresponding payload carrier
MUST be a JSON object. The sender MUST NOT put a serialized JSON string in
body.text, and MUST NOT double-serialize the object as a JSON string inside
body.payload.
14. Privacy Considerations
14.1 Minimum Metadata Principle
The sender SHOULD place only the minimum metadata necessary for interoperability across implementations in meta.
14.2 No device semantics introduced
This Profile only identifies Agents and Groups, and does not define devices, terminals, replicas, or internal operating units. These concepts are implementation internal and must not be forced as standard fields in Core Binding.
14.3 Capability cache
The caller SHOULD cache capability-negotiation results, but MUST renegotiate upon capability changes, authentication failure, service-endpoint switching, or cache invalidation.
15. Minimum Interoperability Requirements
An ANP Core Binding compliant implementation MUST support at least:
- JSON-RPC 2.0;
- Object form
params; - String
id; anp.get_capabilities;- Public error code;
- Idempotent
operation_id; meta/bodytop-level structure;- Secure transmission;
- Processing of anonymous or authenticated
anp.get_capabilities; - Unified
content_typesemantics: the outer layer always represents the current wire object type; - Explicitly declare the target modeling mode for each method:
agent-addressed,group-addressed,service-scoped, orendpoint-local; - Force verification of
meta.target.kind = "service"andtarget.did = serviceDidfor theservice-scopedmethod; - Explicit declaration of
endpoint-localmethod allows omission oftarget, and rejects ambiguous omission when not declared.
16. Example
The following example only demonstrates the outer envelope of Core Binding; Overlay methods (such as group.e2ee.send, group.e2ee.notice) are also subject to the Request / Notification, meta, target modeling and error model of this Profile.
16.1 direct.send request example
{
"jsonrpc": "2.0",
"id": "req-10001",
"method": "direct.send",
"params": {
"meta": {
"profile": "anp.direct.base.v1",
"security_profile": "transport-protected",
"sender_did": "did:example:agent-a",
"target": {
"kind": "agent",
"did": "did:example:agent-b"
},
"operation_id": "msg-10001",
"message_id": "msg-10001",
"created_at": "2026-03-29T12:00:00Z",
"content_type": "text/plain"
},
"auth": {
"scheme": "anp-rfc9421-origin-proof-v1",
"origin_proof": {
"contentDigest": "sha-256=:BASE64_SHA256_OF_SIGNED_DIRECT_PAYLOAD:",
"signatureInput": "sig1=(\"@method\" \"@target-uri\" \"content-digest\");created=1774785600;expires=1774785660;nonce=\"n-10001\";keyid=\"did:example:agent-a#key-1\"",
"signature": "sig1=:BASE64_SIGNATURE:"
}
},
"body": {
"text": "hello"
}
}
}
16.2 Successful Response Example
{
"jsonrpc": "2.0",
"id": "req-10001",
"result": {
"accepted": true,
"message_id": "msg-10001",
"operation_id": "msg-10001",
"target_did": "did:example:agent-b",
"accepted_at": "2026-03-29T12:00:01Z"
}
}
17. IANA / Registry Placeholder
Subsequent versions of this standard SHOULD establish the following registry:
- ANP Profile name registry;
- Security Profile registry;
- Content-Type registry;
- ANP error code registry.
18. Reference Implementation Notes (Non-Normative)
Implementers should adopt the following principles when implementing this Profile:
- Core Binding only retains fields that must be consistent across implementations;
- Static hints in DID documents only perform discovery and do not perform runtime judgment;
- The business layer only cares about business semantics, and security details are placed in the Overlay;
- Tracking, routing and internal gateway fields should be placed in the private extension or transport layer as much as possible and do not enter the standard interoperability boundary.
Appendix A (Normative): Shared Origin Proof Bearing Convention
This appendix defines the application-layer origin-proof bearer convention shared by P3, P4, P6, and future application profiles.
This appendix does not repeat definitions of common signature algorithms, Structured Field serialization, or JSON normalization algorithms; these are provided directly by the following standards:
- RFC 8785: JSON Canonicalization Scheme(JCS)
- RFC 9530:
Content-Digestfield value format - RFC 9421: Construction and verification model of
Signature-Input,Signature, signature base - RFC 3986: URI percent encoding rules
- For
did:wba's DID parsing, verification method authorization relationship and path fingerprint binding verification, follow the corresponding did:wba method specification
ANP only defines the following custom parts in this appendix:
- The bearer field of
auth.origin_proof; - Unified Signed Request Object;
- Application layer
@method/@target-uri/content-digestcomponent mapping; - Responsibility boundaries with hop/service authentication and cross-domain forwarding.
A.1 Unify auth.scheme and auth.origin_proof
When an application profile uses application-layer origin proof:
auth.schemeMUST equalanp-rfc9421-origin-proof-v1auth.origin_proofMUST existauthitself MUST NOT enter the digest input
The recommended structure is as follows:
{
"auth": {
"scheme": "anp-rfc9421-origin-proof-v1",
"origin_proof": {
"contentDigest": "sha-256=:BASE64_SHA256_DIGEST:",
"signatureInput": "sig1=(\"@method\" \"@target-uri\" \"content-digest\");created=1733402096;expires=1733402156;nonce=\"abc123\";keyid=\"did:wba:example.com:user:alice:e1_<fingerprint>#key-1\"",
"signature": "sig1=:BASE64_SIGNATURE:"
}
}
}
Notes:
contentDigeststores the field value of RFC 9530Content-DigestsignatureInputstores the field value of RFC 9421Signature-Inputsignaturestores the field value of RFC 9421Signature
A.2 Shared origin_proof object structure
origin_proof MUST contain at least the following fields:
contentDigestsignatureInputsignature
Unless otherwise specified in future versions, the v1 contract is as follows:
contentDigestMUST usesha-256signatureInputMUST use tagsig1signatureMUST use tagsig1- Override component collection MUST be fixed to:
("@method" "@target-uri" "content-digest")
Regarding the specific syntax, serialization, and validation of these field values, senders and verifiers MUST directly follow RFC 9530 and RFC 9421, while MUST NOT invent alternative formats.
A.3 Sharing Signed Request Object
contentDigest MUST bind a standard business object that does not contain auth, called Signed Request Object.
The general structure is as follows:
{
"method": "<jsonrpc method>",
"meta": {
"...": "..."
},
"body": {
"...": "..."
}
}
The rules are as follows:
- The Signed Request Object MUST contain only
method,meta, andbody - It MUST NOT contain
jsonrpc,id,auth - The sender MUST use RFC 8785 JCS to normalize and serialize it before calculating
contentDigest - Default optional fields MUST be omitted
- Upstream service routing information, local cache fields, and operation and maintenance tracking fields MUST NOT be included in the Signed Request Object
Notes:
- Business Profile MAY continue to constrain the required fields in
meta/body - But as long as a method requires
auth.origin_proof, its summary object will always be the Signed Request Object defined in this appendix, instead of defining a new universal signature shell for each Profile.
A.4 Global component mapping
When the did:wba authentication information is carried in the ANP JSON-RPC request, to ensure that the signature remains stable under cross-service forwarding, the key component MUST in Signature-Input uses the following global application layer mapping:
@method: mapped toSigned Request Object.method@target-uri: mapped toanp://{meta.target.kind}/{pct-encoded meta.target.did}content-digest:contentDigestvalue mapped to Signed Request Object
Among them:
pct-encodedMUST be derived from the UTF-8 byte sequence ofmeta.target.didand then percent-encoded according to RFC 3986meta.targetMUST exist when a method requiresauth.origin_proofmeta.target.kindMUST take one ofagent,group, orservice- If an endpoint-local method introduces
auth.origin_proofin the future, the corresponding profile MUST define its target-modeling and reconstruction rules explicitly
Rationale:
meta.target.kind has entered contentDigest through the Signed Request Object; @target-uri continues to explicitly carry kind in order to allow the target category to maintain stable semantics that is readable, auditable, and independently checkable in the signature base, rather than relying on the verifier to first expand the entire summary object before knowing the target type.
Appendix A of P1 is the originator-proof foundation shared by multiple business Profiles. The following diagram compresses the relationship among the Signed Request Object, contentDigest, and the @method / @target-uri / content-digest components into one view for reuse by subsequent documents.
flowchart LR M1[method] M2[meta] M3[body] M1 --> SRO[Signed Request Object] M2 --> SRO M3 --> SRO SRO --> JCS[RFC 8785 JCS] JCS --> CD[contentDigest] M1 --> HM[@method] M2 --> TU[@target-uri<br/>anp://kind/pct-encoded-did] HM --> SB[Signature Base] TU --> SB CD --> SB SB --> SI[signatureInput] SB --> SG[signature] CD --> OP[auth.origin_proof] SI --> OP SG --> OP
Figure P1-4: Binding of the Signed Request Object and Origin Proof (non-normative).
For any subsequent business method that requires auth.origin_proof, this shared binding diagram should be used to understand the sources of digest input and signature components, instead of defining a new generic signature envelope in each document.
A.5 Relationship with the standard signature model
In addition to the application layer component mapping defined in this appendix, the sender and verifier MUST directly reuse the signature model of RFC 9421:
- Field value construction of
signatureInput - Field value construction of
signature - Generation of signature base
- Cover component order explanation
- Construction and verification of
@signature-params
Specifically:
- The sender MUST sign the signature base under RFC 9421 semantics
- The sender MUST NOT sign the raw JSON request text directly
- The sender MUST NOT sign the
signatureInputJSON string field directly
This appendix only replaces the "where the component values come from" layer: In standard HTTP Message Signatures, components typically come from HTTP messages; in ANP, they come from the application layer mapping defined in this appendix.
A.6 Minimum Authentication Requirements
The verifier MUST perform at least the following steps:
- Read
auth.origin_proof - Extract
contentDigest,signatureInput,signature - Rebuild the Signed Request Object using the
method,params.meta, andparams.bodyof the current request - Use RFC 8785 JCS to normalize and serialize it
- Recalculate
contentDigest - Rebuild
@methodfrommethod - Rebuild
@target-urifrommeta.target.kindandmeta.target.did - Rebuild and verify signature base according to RFC 9421 model
- Parse the DID document pointed to by
keyidand check that the authentication method exists and is authorized by theauthenticationrelationship - Verify signature, time window and anti-replay strategy according to corresponding DID method rules
If any step fails, the verifier MUST reject the request.
A.7 DID and verification relationship
keyidMUST point to a parsable DID URL- The verifier MUST parse the DID document to which
keyidbelongs and check whether the verification method is authorized by theauthenticationrelationship - The DID to which
keyidbelongs MUST be consistent with the business subject DID required by the applicable profile - For a did:wba path-type
e1_DID, the verifier MUST additionally perform path fingerprint binding verification
Notes:
- In the current request semantics of P3, P4, and P6, the business subject DID is usually
meta.sender_did - If a notification or declarative profile uses a different business-entity DID in the future, that DID MUST be specified explicitly by the profile
A.8 Relationship with hop authentication
anp-rfc9421-origin-proof-v1 proves the identity of the service originator, not the identity of the current network one-hop caller.
Therefore:
- Hop/service authentication for any hop MAY change
- An intermediate service MUST NOT rewrite its service-level identity into a new business Origin Proof
- The target recipient MUST independently verify the business Origin Proof, while MUST NOT presume its establishment solely based on the identity of the upstream service
A.9 Cross-Domain forwarding
If the original service request carries auth.origin_proof, the cross-domain sender:
- MUST leave it unchanged and forward it with the request
- MUST NOT create a new business Origin Proof
- MUST NOT replace
auth.origin_proofwith the outer HTTPserviceDidsignature
Notes:
- The outer cross-domain HTTP authentication is used to prove "which service is currently calling the next hop"
auth.origin_proofis used to prove "which business entity initiated this action"- The two have different responsibilities, MUST NOT replace each other
Appendix B (Normative): Shared Object Proof Profile
This appendix defines the "Object Proof" configuration shared by P4, P5, P6 and future object-based profiles. Whenever an object's chapter declares that its proof uses this appendix, that proof MUST follow this appendix.
B.0 Normative Reference and Positioning
This appendix reuses the W3C Data Integrity certification framework and its associated cipher suites, rather than not adopting the Verifiable Credentials data model as a whole.
More specifically:
DataIntegrityProof's general proof framework, following W3C Verifiable Credential Data Integrity 1.0;- The generation and verification rules of
eddsa-jcs-2022cryptosuite follow W3C Data Integrity EdDSA Cryptosuites v1.0; - JSON canonicalization algorithm, following RFC 8785: JSON Canonicalization Scheme (JCS);
- Byte sequence encoding, following RFC 3629: UTF-8, a transformation format of ISO 10646;
- DID document model, verification relationship and basic semantics of DID URL, follow W3C DID Core 1.0;
- If the deployment uses
did:wba, its method-specific parsing, path fingerprint binding and other additional verifications follow the corresponding DID method specification, such as did:wba Method Specification.
This appendix does not repeat definitions of Data Integrity, eddsa-jcs-2022, JCS, UTF-8, DID Core, or the DID method itself.
The ANP only harmonizes the following in this appendix:
- The fixed load-bearing shape of object-level
proof; - Determination rules for protected documents;
- UTF-8 + RFC 8785 JCS standardized serialization requirements;
- The default unified semantics of
proofPurpose = "assertionMethod"; - Share division of labor boundaries between verification steps and object-specific constraints.
B.1 Applicability
Currently in v1, the following objects MUST use this appendix:
group_receipt.prooffor P4prekey_bundle.prooffor P5did_wba_binding.prooffor P6
In the future, if other Profiles introduce similar object-level proof and do not explicitly define different profiles, SHOULD reuse this appendix.
B.2 Unify proof structure
Objects using this appendix must have proof MUST contain at least:
typecryptosuiteverificationMethodproofPurposecreatedproofValue
The recommended structure is as follows:
{
"proof": {
"type": "DataIntegrityProof",
"cryptosuite": "eddsa-jcs-2022",
"verificationMethod": "did:example:issuer#key-1",
"proofPurpose": "assertionMethod",
"created": "2026-03-29T12:00:00Z",
"proofValue": "z..."
}
}
The unified requirements for v1 are as follows:
proof.typeMUST equalDataIntegrityProofproof.cryptosuiteMUST equaleddsa-jcs-2022proof.proofPurposeMUST equalassertionMethodproof.verificationMethodMUST be the complete DID URLproof.createdMUST be an RFC 3339 time string *proof.proofValueMUST use base58-btc multibase (z...)
Unless explicitly allowed by the corresponding object Profile, implementations MUST NOT reinterpret the semantics of these public fields for that shared profile.
B.3 Protected documents
For any object using this appendix, the protected document MUST when generating and verifying proof is:
The entire object after removing the top-level
proofmember of the object
This means:
- The protection scope MUST NOT be reduced to several local fields
- It MUST NOT expand to the outer JSON-RPC envelope, HTTP headers, transport-layer metadata, or local cache fields
- Default optional fields MUST be omitted
- Implementations MUST NOT use
null, an empty string, an empty object placeholder, or any other dummy value to represent an omitted field
If an object requires nested proofs, separate sub-object proofs, or any other special coverage model in the future, the corresponding profile MUST define that model explicitly; otherwise, this section applies.
B.4 Normalization and Serialization
When using this appendix, the protected document MUST first:
- RFC 8785 JSON Canonicalization Scheme (JCS) standardization
- UTF-8 encoding
proof is then generated or verified as required by eddsa-jcs-2022.
Unless otherwise explicitly stated in the corresponding object Profile, validators and generators MUST NOT use other "stable serialization", "implement custom ordering", "pretty-print JSON" or local-specific encoding to replace the requirements of this section.
B.5 Issuance subject DID and verification method authorization
Each object using this appendix MUST declare its issuer DID in the corresponding object profile.
For any object proof:
- The DID to which
proof.verificationMethodbelongs MUST be equal to the issuer DID specified by the object's Profile proof.verificationMethodMUST exist in the issuer DID documentproof.verificationMethodMUST be authorized by theassertionMethodrelationship of the issuer DID documentproofPurposeis fixed toassertionMethod, whose default semantics are: issuer DID is making an assertion on the object as a whole
If the corresponding DID method requires additional verification (for example, path fingerprint binding for a did:wba path-type e1_ DID), the verifier MUST also perform the additional checks specified by that DID method.
B.6 Division of labor with object-specific business constraints
What this appendix unifies is the proof framework, not object semantics.
Therefore:
-
The shared profile defines the common syntax, protected document, normalization rules, and default authorization relationships for
proof -
Each object profile MUST specify, at minimum:
- Which DID is the issuer DID for the object
- Which minimum security-critical fields the object is required to contain
- Which business-consistency checks are required after
proofhas been verified
In other words, after proof has been verified successfully, the verifier MUST continue to validate field integrity, object semantics, and state constraints as specified by the corresponding object profile, and MUST NOT skip business-layer validation merely because proof has passed.
B.7 Minimum Authentication Requirements
Verifiers MUST perform at least the following steps for objects using this appendix:
- Read object
proof - Check whether
type,cryptosuite,verificationMethod,proofPurpose,created,proofValueexist and meet the requirements of this appendix - Determine the issuer DID according to the corresponding object Profile
- Reconstruct "the entire object after removing the top-level
proof" as a protected document - Use UTF-8 + RFC 8785 JCS to normalize and serialize protected documents
- Parse issuer DID document
- Check that
proof.verificationMethodexists and is authorized byassertionMethodof the issuer DID document - Press
DataIntegrityProof + eddsa-jcs-2022to verify the proof - Execute field integrity, time window, status reference and other business checks specified by the object Profile
If any step fails, the verifier MUST reject the object.