14. Network Node Protocols and Interoperability
This chapter explains how inter-node protocols deliver an interaction to the correct node while preserving verifiable context; it does not extend “request delivered” into “resource published,” nor “node authenticated” into “resource control verified.”
Envelope -> node authentication -> request signing -> business validation -> status handling -> response recording
In the OpenAgenet (OAN) implementation, inter-node operations are usually provided with structured request and response types by a shared protocol crate, while the concrete node service is responsible for HTTP routing, storage, and background tasks. Therefore, when reading a request path, verify all three layers together: the HTTP method and path, the JSON envelope fields, and the node’s internal acceptance or publication state. oan-protocol-common/schemas/agent-contract/openapi.yaml is currently the contract entry point and a version placeholder, not a complete automatically generated description of every node interface; this file alone cannot establish that an interface is enabled in every deployment.
14.1 Common Protocol Envelope and Request Headers
The common envelope may use the following field semantics, while the business body remains defined by the corresponding interface:
{
"protocolVersion": "oan-resource-2026",
"requestId": "req-01",
"purpose": "cdn-publish",
"method": "POST",
"path": "/cdn/resources",
"aud": "did:oan:...",
"requestTimestamp": "2026-09-07T10:00:00Z",
"requestNonce": "random-value",
"bodyHash": "sha256:...",
"proof": {
"type": "Ed25519Signature2020",
"creator": "did:oan:...",
"created": "2026-09-07T10:00:00Z",
"proofPurpose": "assertionMethod",
"proofValue": "z...",
"cryptoSuite": "Ed25519Sha256",
"hashAlgorithm": "SHA-256",
"verificationMethod": "did:oan:...#key-1"
}
}
The example corresponds to the fields of SignedRequestEnvelope, rather than adding another set of sourceDid, targetDid, timestamp, or sequence fields. aud in the envelope denotes the target audience, and proof carries the request signature; business payloads such as a ResourcePackage, registration submission, or batch item are carried outside the envelope by the specific request structure. The sender generates requestId, requestTimestamp, requestNonce, and bodyHash; the receiver validates the audience, time, nonce, digest, signing subject, and signature coverage. Whether unknown fields are accepted is determined by the protocol version and the deserialization rules of the specific structure. Missing required fields or an inconsistent digest must be rejected.
14.2 Inter-Node Authentication
| Check | What it proves | Failure handling |
|---|---|---|
| Node DID | Who the communicating party is | Reject authentication |
| Node authorization VC/governance status | Whether it has the current communication or business qualification | Reject or degrade to read-only |
| Validity period and status | Whether the credential is still valid | Do not use an expired or revoked credential |
| Authorization domain and capabilities | Whether the requested action is within scope | Reject an unauthorized action |
| Resource control proof | Whether the resource is controlled by the submitter | Enter business-validation failure |
Authentication decisions should be completed in order: first confirm the connection target and node DID, then resolve the verification method in the node DID Document, next verify the node authorization VC or governance status, and finally check that the requested action falls within the authorization domain. Node authorization and resource control are two different paths: the former indicates that a node may communicate as a particular network role, while the latter is established by the control proof in the resource submission, showing that the submitter can control the resource DID. Even after node authentication succeeds, the receiver must still perform business validation on the ResourcePackage, DID Document, and control proof.
14.3 Signing Upstream Requests
The signature must cover at least the canonicalized method, path, target node, time, nonce, request ID, and bodyHash. The verifier should resolve the public key according to proof.verificationMethod or a compatible verification-method identifier, and confirm that proof.creator, the verification-method controller, and the trusted upstream node identity are consistent.
The current shared protocol structure uses proof, rather than defining separate kid and signature fields in SignedRequestEnvelope. proof.verificationMethod points to a verification method in the DID Document, while proof.creator identifies the signature creator; oan-crypto canonicalizes the signable value according to the cryptographic suite before signing or verifying. For Ed25519Sha256 and Sm2Sm3, the signature input is the bytes of canonicalized JSON; legacy compatibility suites may first hash the canonicalized content, so the protocol version and cryptographic suite must jointly define the signature input. The HTTP header example applies only when a specific deployment maps envelope fields to request headers; it cannot replace the JSON envelope itself.
Signature verification failure, a mismatched target aud, a mismatched bodyHash, a verification method that does not belong to the signing subject, or an expired request should all be rejected before entering the resource-write and publication queues, with the requestId and an error category useful for operations recorded.
X-Request-ID: req-01
X-Node-DID: did:oan:...
X-Timestamp: 2026-09-07T10:00:00Z
X-Nonce: random-value
X-Body-Hash: base64url(...)
X-Signature: jws-or-equivalent
14.4 Node Authorization VC Exchange
Node authorization VC exchange should follow the order “carry or reference -> resolve issuer DID -> verify signature -> query status -> check authorization domain and capabilities.” Caching may reduce repeated resolution, but it cannot bypass validity periods, revocation status, or governance-event refreshes.
The issuer of a node authorization VC is a trusted institution with governance responsibility or the Root platform. The receiver should verify the issuer DID Document and signature, and check the subject node DID, role, authorization domain, capabilities, validity period, and revocation or suspension status in the VC. The VC may be carried as a complete credential in the request or obtained through a reference agreed by both parties; in the latter case, the referenced content must be traceable and its digest verifiable, and a cache hit must not cause the status check to be skipped. A resource registration VC is the result of resource registration; it cannot in turn prove that a Registrar node is qualified for inter-node communication.
14.5 Registrar node to Root platform Protocol
A Root platform response of “accepted” only means that the request has entered the processing flow; the registration VC, Root proof, content distribution, and Discovery node index status should be expressed separately.
The business payload submitted by a Registrar node to the Root platform is represented by ResourceVerifyAndPublishRequest, which includes the Registrar node DID, the resource registration submission, and upstreamAuth. The registration submission includes the resource DID, resource type, DID Document, metadata, version, individual digests, registration credential, and subject control proof. The Root platform first verifies the upstream envelope and node qualification, then validates the binding among the resource control proof, DID Document, and digests; only after that does it enter the Root platform’s persistence and subsequent publication flow. On timeout or connection interruption, the Registrar node should query the acceptance status using the original requestId; it must not determine whether the resource has been published solely from receiving a response again or from the number of local retries.
14.6 Root platform to content distribution platform Protocol
The distribution request should be associated with the resource DID, version, ResourcePackage digest, Root proof reference, and distribution sequence. After receiving it, the content distribution platform recomputes the digest, confirms the source and version, and then returns a received, completed, or failed status; successful receipt does not mean that a Discovery node has indexed the resource.
In the shared protocol, a single content distribution request uses ResourceCdnPublishRequest, while a batch request uses ResourceCdnBatchPublishRequest; batch items are associated with the Root platform’s publication order through publicationCursor, and the common envelope proves the upstream call context through upstreamAuth. The corresponding content distribution path constants in the code are /cdn/resources and /cdn/resources/batch, but the actual accessible address still depends on the service route prefix and reverse-proxy configuration. After validation, the content distribution platform forms its own readable resource or manifest, and the Root platform’s publication-completed status and the Discovery node’s indexing-completed status should be recorded separately.
14.7 content distribution platform to Discovery node Protocol
Discovery node synchronization should use a cursor or batch sequence, and should revalidate the digest and Root proof reference for each resource version. Duplicate batches should be processed idempotently, and the cursor must advance only after the batch content has been successfully validated.
For incremental data read from the content distribution platform, the shared protocol uses ResourceCdnIndexResponse to express items, count, afterCursor, nextCursor, and hasMore; each item carries the current cursor and ResourcePackage. Notifications sent by the Root platform to a Discovery node instead use information such as the notification batch, start and end sequences, and content distribution address; the two forms must not directly mix field names. A Discovery node should write to its local index and advance the next cursor only after the ResourcePackage, DID Document, digests, and Root proof association have all passed validation; a failed batch retains the original cursor and is retried after remediation.
14.8 Discovery Response Signatures and Source Proofs
A Discovery response should be able to distinguish at least the following information:
| Information | Meaning |
|---|---|
| Query node DID | Who generated this response |
| Data source | Which distribution or index source supplied the data |
| Index version/time | Freshness of the read model used for the query |
| Match reason | Which fields or tags matched |
| Root proof reference | External evidence entry point for the publication fact |
| Response signature | Prevents the response from being replaced |
A response signature proves that the node is responsible for the response content; it does not replace the resource control proof or Root proof.
The current ResourceDiscoveryResponse structure contains discoveryDid, candidates, createdAt, and an optional proof; the Discovery node query implementation may return an empty proof, so response signatures are a reserved protocol capability or a capability of deployments after enablement and should not be described as the default behavior of all current instances. If enabled, the signature should cover the query result, creation time, query node DID, and the necessary index or source digest; the caller must still independently check the DID Document, resource control proof, and Root proof of the candidate resource. The score in a candidate only indicates matching relevance; it is not a trust level or authorization conclusion.
14.9 Sequence Numbers, Request Identifiers, and Replay Protection
| Field | Primary use | Reuse on retry |
|---|---|---|
requestId |
Associates one business request with its logs | Reuse for the same logical request |
| Idempotency key | Prevents repeated execution of submission side effects | Reuse for the same operation |
nonce |
Prevents replay of signed messages | Usually generate again |
sequence/cursor |
Ensures batch or event order | Use according to the synchronization protocol |
| Time window | Limits request freshness | Update when resigning |
requestId connects one logical operation across the Registrar node, Root platform, content distribution platform, and Discovery node; requestNonce prevents the same signed envelope from being accepted again; publicationCursor, sequenceFrom, sequenceTo, afterCursor, and nextCursor propagate order or support incremental reads. Their numeric spaces and advancement rules differ: a request ID must not be treated as an event sequence, and pagination parameters from a Discovery query must not replace a publication synchronization cursor. When retrying the same logical request, requestId may be retained, but a new signed message should normally use a new nonce, and the receiver should determine whether it has already been processed according to idempotency rules.
14.10 Pagination, Filtering, and Compatibility Rules
Client page pagination, Discovery query pagination, and node synchronization cursors must not be mixed: page pagination serves presentation, Discovery pagination serves candidate results, and synchronization cursors serve incremental propagation. When a cursor is invalid, return an identifiable error or require resynchronization; do not silently continue from an arbitrary position.
The current shared query structure has a default limit of 10. A Discovery query may also carry conditions such as resource type, capability tags, protocol, version, and version mode; this is only the default behavior of the Discovery query structure and does not represent the default page size of every management list interface. hasMore and nextCursor in a synchronization response serve incremental propagation, while score, version mode, and candidate ordering in query results serve user retrieval. During protocol evolution, new filter fields may be handled according to compatibility rules, but changes to cursor meaning, ordering stability, or version mode should be explicitly communicated to callers through version documentation.
14.11 Timeouts, Retries, and Idempotent Operations
| Operation | Default action after a network timeout | Reason |
|---|---|---|
| Read-only query | Retry after limited backoff | Usually has no business side effect |
| Status query | Use the original request ID to query for confirmation | Distinguishes incomplete from not started |
| Resource submission | Do not blindly replay; query idempotent status first | May already have caused registration or publication side effects |
| Synchronization batch | Retry with the original cursor and batch | Preserves incremental order and idempotency |
Retries must distinguish “no response received” from “explicit failure received”: a network timeout only means that the result is unknown, so resource submission, publication, and state-change operations should first query with the original request identifier; explicit parameter, authorization, or signature errors should not be retried automatically. A background publisher may resume processing at the same publication cursor, and the receiver should identify duplicate messages using the combination of resource DID, version, digest, and cursor to avoid duplicate writes or incorrect progress. Specific timeouts, backoff, and concurrency are determined by deployment configuration; this chapter does not fix the values of a particular environment as protocol constants.
14.12 Protocol Version Negotiation
Version negotiation should declare at least the protocol version, supported capabilities, and incompatible constraints. When there is no common version, fail explicitly; do not infer from fields or silently downgrade to an insecure path.
{
"protocolVersions": ["oan-resource-2026"],
"capabilities": ["signed-response", "cursor-sync"],
"required": ["request-signature"]
}
The example expresses negotiation information; it does not mean that all current nodes provide an independent capability-negotiation endpoint. The current shared protocol uses oan-resource-2026 as the resource protocol version constant and uses protocolVersion in the envelope; info.version in openapi.yaml is the contract-file version, and the two must not be treated as equivalent. The negotiation result must at least fix field interpretations, signature coverage, cryptographic suite, cursor semantics, and error handling; if the other party supports only an insecure or uninterpretable downgrade path, refuse to establish that business link.
14.13 Message Size, Compression, and Transport Limits
Limits should account for the message before compression, the compressed transfer body, and the decompressed content at the same time; the receiver should apply size and format protections before resource writing or expensive validation. Compression changes only the transport method, not the logical content covered by the signature and digest.
The current shared protocol types define ResourcePackage, batch items, and envelope fields, but the common structure file does not uniformly declare message sizes, compression algorithms, or HTTP body limits for all deployments. Therefore, these limits should be jointly determined by the concrete service configuration, reverse proxy, and runtime environment, with verifiable values disclosed in inter-node capability or deployment documentation. Batch synchronization in particular should limit item size, batch item count, and cumulative decompressed size at the same time; when a limit is exceeded, return a clear error before persistence and retain the request ID, without truncating and continuing signature verification or indexing.
14.14 Correlation, Traceability, and Audit Identifiers
A resource propagation path should retain at least the following correlation fields:
requestId -> resourceDid -> resourceVersion -> publishSequence
-> syncCursor -> discoveryIndexVersion -> errorCode
Nodes may add local trace identifiers, but must not lose the upstream requestId, resource DID, or version; logs must not record private keys or complete sensitive credentials.
For the publication path, the following searchable correlations should be retained at minimum:
| Path stage | Key correlation fields | Purpose |
|---|---|---|
| Registration acceptance | requestId, resource DID, resource version |
Locate one registration request |
| Root platform publication | ResourcePackage digest, Root proof reference, publicationCursor |
Determine the publication fact and order |
| Incremental synchronization | afterCursor, nextCursor, batch sequence number |
Determine whether synchronization was missed or duplicated |
| Discovery index | Discovery node DID, index time, error category | Explain the freshness of query results |
Audit records should retain validation results and state transitions, rather than recording only HTTP 200. For sensitive VCs, record their type, digest or reference, and verification conclusion, and avoid writing complete credential contents or any private key to ordinary business logs.
14.15 Protocol Compatibility and Deprecation Rules
Field or version deprecation should pass through the stages of “announcement -> compatibility period -> migration -> stop accepting,” while retaining the error code and request ID. Changes involving signature coverage, authentication semantics, cursor meaning, or state semantics cannot be solved merely by adding optional fields; the protocol version should be upgraded or an explicit migration rule provided.
Compatibility tests should cover at least: whether an old-version envelope can be explicitly rejected or parsed according to compatibility rules, whether unknown optional fields leave signature semantics unchanged, whether an old cursor can never be mistaken for a new cursor, and whether the signing subject and aud are still verified under the same rules. During version migration, the sender should prefer the common version confirmed by both parties, and the receiver should return an associable request ID and the reason for incompatibility in an error response; before stopping acceptance of the old version, node configuration, background publication tasks, and historical cursors should first be migrated. Protocol files, shared structures, and service implementations must be updated together; changing only the version string in the documentation is insufficient.
References
| Source | Type | Link |
|---|---|---|
oan-protocol-common |
Code repository: inter-node request, response, error, and event types | https://github.com/wolfbrother/oan-protocol-common |
oan-root-services |
Code repository: Root platform inter-node interfaces | https://github.com/OpenAgenet/oan-root-services |
oan-registrar-node |
Code repository: Registrar node interfaces and upstream calls | https://github.com/OpenAgenet/oan-registrar-node |
oan-discovery-node |
Code repository: Discovery synchronization and query interfaces | https://github.com/OpenAgenet/oan-discovery-node |
oan-trust-indexer |
Code repository: off-chain trust indexer governance-status query interfaces | https://github.com/OpenAgenet/oan-trust-indexer |
| Agentic Overlay Network Architecture | IETF draft: node interoperability architecture | https://datatracker.ietf.org/doc/draft-xu-agentic-overlay-network-architecture/ |
| OAN Resource Identity and Discovery | IETF draft: resource identity and discovery interoperability | https://datatracker.ietf.org/doc/draft-xu-oan-resource-identity-discovery/ |