Appendix E - Reference Deployments and Examples

This appendix provides reference paths that can be used for development, verification, and operations handover. The specification requires attention to role boundaries, evidence binding, state propagation, and interface semantics; the reference implementation uses Rust nodes, a TypeScript SDK, community skill packages, PostgreSQL/NATS, and a website gateway; specific domain names, ports, keys, database URLs, model directories, and system service names are all environment configuration. Deployment personnel should first confirm the trust root, authorized domains, node DIDs, and protocol version of the target network before writing configuration, and should not copy private keys, tokens, or online addresses from the examples. Server-side build artifacts, logs, caches, and database data are kept separate from the source archive, and secrets are injected only through protected runtime configuration.

When synchronizing versioned source archives, the archived content should come from a confirmed commit or release version, rather than unreviewed files in the working tree. The following command represents one general method for creating a source archive:

git archive --format=tar --prefix=release/ <COMMIT_OR_TAG> | gzip -c > <RELEASE_ARCHIVE>.tar.gz

The archive represents source deliverables only; build directories, dependency caches, database files, runtime keys, and logs should not be mixed into the source package. Source code, build artifacts, configuration, runtime data, and website static files should be stored separately in controlled directories defined by the deployment environment, with their versions and digests associated through release records. Directory names, filesystem layout, and transfer methods are environment implementation details, not protocol requirements.

The recommended general startup chain is as follows:

Governance state/node authorization
        |
        v
Root platform verification and publication -----> content distribution platform -----> Discovery node -----> Caller
        ^                        ^                 |
        |                        |                 v
Registrar node -----------------+           Structured/semantic query
        ^
        |
Resource controller, SDK, or community skill package

The startup order should first satisfy dependencies such as the database, message system, and off-chain trust indexer, then start the Root platform, Registrar node, content distribution components, and Discovery node, and finally start the website backend, static frontend, and reverse proxy. During shutdown or upgrade, new writes should be stopped first, and the publication and distribution queues should be allowed to reach an acceptable state before the program is replaced, while the database, cursors, version records, and redacted logs are retained. If a dependency is temporarily unavailable, the service should perform limited retries and backoff according to its own configuration, and report unknown, unavailable, or pending synchronization externally, rather than generating false publication or authorization facts.

E.1 Official Network Deployment

The reference layering of the official network is as follows: the Registrar node handles resource onboarding, the Root platform performs network-level verification, publication, and coordination, the content distribution platform transfers Root platform-verified ResourcePackages and proofs, the Discovery node establishes structured and semantic indexes within the authorized domain, the off-chain trust indexer projects governance events into queryable state, and the website backend provides the frontend with display and user-operation entry points through a public gateway. The website is not a trust authority; a website failure should not change the protocol state of a resource or node.

Production deployment should verify at least the following chain:

  1. The database, message system, and listening addresses of all nodes are ready, and the public Internet exposes only the public HTTPS entry protected by the reverse proxy.
  2. The Root platform, Registrar node, Discovery node, content distribution platform, and off-chain trust indexer each return an interpretable status through /health or their role-status interface.
  3. The Registrar node can complete controlled registration-request validation and submission to the Root platform; registration smoke tests should use dedicated test resources or controlled failure inputs and must not pollute the production resource directory.
  4. Root platform publication results can be consumed by the content distribution platform, validated and indexed by the Discovery node, and then observed through exact and semantic queries.
  5. The website frontend’s VITE_* endpoints point to the current public gateway, and build artifacts contain no residual localhost or 127.0.0.1; after website deployment, perform smoke tests for registration, discovery, Network, routing, and the browser console.

Deployment records should retain the build version, configuration summary, service-switch time, health-check results, registration and discovery smoke-test results, index cursor, and failed-retry information. Public domains, node addresses, and certificates belong to the target environment configuration; when migrating to another environment, endpoints and certificates authorized by that environment must be used.

Each service should be released through a reversible replacement order: first verify the new binary and static artifacts, then switch the corresponding service through the target environment’s service manager, and finally check routing through the public entry point. Website static files may first be uploaded to a controlled temporary release directory; after checking the file count, entry file, and endpoint references, switch to the current version. For node services, retain the old binary, configuration, and runtime state before replacing the new version. During rollback, restore only a verified old version; do not reset the database, publication cursor, or governance state.

Layer Typical observations Handling boundary on failure
Process layer Service-manager status, listening ports, and startup logs Fix the configuration or binary and restart; process liveness is not business availability
Interface layer /health, node status, and public-route status codes Distinguish reverse-proxy, upstream-service, and request-format problems
Business layer Registration acceptance, Root platform publication, and discovery queries Use controlled test data; block publication or roll back on failure
Data layer Database connection, cursor, index statistics, and version records Retain the scene and backups first; do not directly delete or rebuild business data

E.2 Private and Alliance Network Deployment

Private or alliance networks may deploy the Root platform, Registrar node, Discovery node, and content distribution platform within an organization’s internal or isolated network, but they should retain the same protocol responsibilities: the Root platform is the hub for network-level verification, trust authorization, data distribution, and semantic governance; the Registrar node is responsible for resource onboarding; and the Discovery node establishes indexes only for published materials. Network isolation changes reachability, not the rules for judging DIDs, control proofs, Root proofs, authorized domains, or lifecycle states.

Typical configuration boundaries are as follows:

Configuration item Handling in private/alliance networks Facts that must not change
Trust root Use the root DID, root keys, and governance process agreed by the organization or alliance, and inject them through secure configuration. Node authorization must be verifiable; it cannot rely only on network segments or IP allowlists.
Resource visibility Control the visible scope through authorized domains, Discovery node partitions, and the reverse proxy. Visibility filtering must not disguise an out-of-domain resource as an in-domain resource.
Data distribution An internal CDN, object storage, or node-to-node synchronization may be used. The recipient must still verify the hash, version, and Root proof.
Operations boundary Place the database, off-chain trust indexer, and management interfaces in a controlled network. An ordinary caller must not obtain private keys or governance write access merely because the network is reachable.

When an alliance member joins, it should first submit its node identity, role, endpoint, authorized domain, and protocol-version materials, and then obtain authorization from the governance authority; revocation or suspension should be able to propagate to the Root platform and Discovery node. During integration, use an independent database and test domain to avoid accidentally synchronizing private-network test resources to the official public network.

The boundary of an alliance network should also appear in operations accounts and data backups: node operators may manage processes, configuration, and logs, but should not read the resource controller’s private key from application configuration; resource publishers submit only public DID Documents, proofs, and ResourcePackages and do not gain governance write access because the network is internal. During cross-member integration, record each member’s node DID, authorized domain, configuration version, and revocation status; after testing, clean up temporary credentials and test-resource indexes while retaining necessary audit summaries.

E.3 Minimal Registrar Node Deployment

The minimal Registrar node needs only its own DID Document and runtime key, resource-record storage, Root platform address, Root platform DID or audience, listening address, CORS/network policy, and necessary database configuration. The reference Rust implementation provides /health, /registrar/did, /resources/register, a compatible submission entry point, registration status, resource records, the capability-tag tree, tag suggestions, and authorization queries; the specific available interfaces should be determined by the source and configuration of the target version. The registration flow is: receive a ResourcePackage, check the DID and resource type, metadata, authorized domain, control proof, and hash, generate a signed request for the Root platform, wait for Root platform verification and publication, then save the registration record and return the registration credential and Root platform response.

Minimum verification should include:

curl -fsS "${REGISTRAR_BASE_URL}/health"
curl -fsS "${REGISTRAR_BASE_URL}/registrar/did"
curl -X POST "${REGISTRAR_BASE_URL}/resources/register" \
  -H 'content-type: application/json' \
  --data-binary @registration-request.json

${REGISTRAR_BASE_URL} is an example variable injected by the deployment environment, not a fixed address or port requirement. The Registrar node must not receive the resource controller’s private key; the private key is used in the resource controller’s SDK, browser, or local Skill, while the node receives only the public key, signature, and public proof. When the Root platform is unreachable, the node must return a distinguishable upstream failure and must not display local storage or acceptance as Root platform publication.

E.4 Minimal Discovery Node Deployment

The minimal Discovery node needs its own identity and authorization materials, a synchronization endpoint for the Root platform or content distribution platform, authorized domains, a database, index configuration, and a listening address. It first obtains or receives Root platform publication materials, verifies the Root proof, ResourcePackage hash, DID Document, version, and lifecycle, and then writes them into the local structured index; semantic retrieval may use the tag tree, text fields, and vector index on this basis, but must not skip publication and authorization verification. The reference implementation provides role interfaces such as /discovery/did, /discovery/resources/query, query explanations, query suggestions, the capability-tag tree, synchronization history, and index statistics.

The criterion for completed initial synchronization is not “the HTTP request succeeded,” but rather: the synchronization cursor has been recorded, the ResourcePackage’s source and hash checks have passed, resources within the authorized domain have entered the index, out-of-domain, suspended, revoked, or protocol-mismatched resources have been filtered, and index statistics are consistent with the synchronization record. It is recommended to use a fixed resource set to perform the following query:

{
  "query": "Find an MCP server for security audit",
  "resourceType": "mcp_server",
  "limit": 10
}

Returned results should distinguish matching sources such as text, tags, structured conditions, and semantic relevance, and retain the resource DID, version, status, source, and freshness fields. If the Root platform or content distribution platform is temporarily unavailable, a known old snapshot may be displayed, but it must not be used to produce a new trusted publication or authorization conclusion.

The synchronization status of the Discovery node should be distinguished according to the following table for shared use by the Network page, operations interfaces, and alerting rules:

Status Meaning Permitted action
ready The cursor is advancing, the index is queryable, and the most recent verification succeeded Allow normal queries
syncing Full or incremental synchronization is in progress Query confirmed data and mark the synchronization status
stale An old index remains, but it has exceeded the freshness boundary configured for the environment Degrade the display or block sensitive invocations
unknown The upstream, cursor, or governance status cannot be confirmed Must not be used to confirm that a resource is trusted or callable

These statuses are observations at the operations and presentation layers, not substitutes for resource lifecycle states. The specific freshness threshold should be provided by the deployment environment and operations policy; it cannot be inferred as a fixed protocol delay from one query response.

The minimal Registrar node configuration can be abstracted as the following environment-configuration example; all values are placeholders and cannot be used directly in production:

REGISTRAR_LISTEN_ADDR=<LISTEN_ADDRESS>
ROOT_ENDPOINT=<AUTHORIZED_ROOT_ENDPOINT>
DATABASE_URL=<DATABASE_CONNECTION_REFERENCE>
NODE_DID=<NODE_DID>
AUTHORIZED_DOMAINS=<AUTHORIZED_DOMAIN_SET>

After startup, at least three results should be recorded separately: “node reachable,” “request validated locally,” and “request submitted to the Root platform.” The latter two must not be ambiguously represented by the same HTTP 200 status code; if the Root platform times out or returns an unknown result, the Registrar node should retain retryable request-correlation information and mark the result as unknown or pending.

E.5 SDK Registration Example

The SDK example should show that the private key is used only locally by the caller, that the DID Document is bound to the ResourcePackage, that the registration request is accepted by the designated Registrar node, and that the registration result requires continued observation of publication and discovery status. The following code shows the interface relationship; endpoints, domain names, and resource content must be replaced according to the environment:

import { createAgentIdentity, createRegistrationSubmissionFromIdentity } from "@openagenet/oan-sdk-ts";
import { OanClient } from "@openagenet/oan-sdk-ts/client";

const identity = await createAgentIdentity(
  "Repository structure summarizer",
  "skill",
  undefined,
  {
    domainCode: "DM",
    authorizedDomains: ["technology.software_engineering"],
    manifestUrl: "https://example.invalid/skill/manifest.json",
    description: "Searches code repositories and summarizes project structure.",
    capabilityTags: ["code.repository", "analysis.summary"],
  },
);

const submission = createRegistrationSubmissionFromIdentity(identity, {
  endpoint: "https://example.invalid/skill/manifest.json",
  packageVersion: "1.0.0",
  packageHash: "sha256:replace-with-real-hash",
  metadataHash: "sha256:replace-with-real-hash",
});

const client = new OanClient({
  registrarEndpoint: process.env.OAN_REGISTRAR_ENDPOINT!,
});

const result = await client.registerResource(submission);
console.log(result.status, result.resourceDid, result.registrationCredential);

This is an SDK flow illustration. Before real publication, actual package hashes, a complete resource description, an accessible endpoint, and an authorized domain accepted by the Registrar must be used; example.invalid or placeholder hashes cannot be used as publishable materials. The VC, Root platform response, and resource DID returned by the SDK should be saved by the caller and continuously verified according to status; the SDK does not hold private keys for the caller or automatically grant business invocation permissions.

When processing registration results, network errors, Registrar rejection, Registrar acceptance with an unknown Root platform result, and Root platform publication should be recorded separately. The example code shows only result branches and does not treat a particular field of result as a fixed field present in every version:

try {
const result = await client.registerResource(submission);
console.log("registrar response received", result);
  // The caller continues to read and verify the VC, Root platform publication status, and discovery visibility.
} catch (error) {
  console.error("registration transport or client error", error);
  // Do not automatically generate a new DID or resubmit unconditionally when the result cannot be confirmed.
}

Real integration should securely retain the request-correlation identifier, resource DID, and Local Identity backup; error logs may contain only redacted summaries and must not output signing private keys, the complete Local Identity backup, or database connection strings.

E.6 DID and Semantic Discovery Examples

DID exact queries are used to confirm whether a known resource is visible in the authorized view of a specified Discovery node; semantic queries are used to find candidate resources from a task description. Both should return the candidate resource’s DID, resource type, version, status, capability tags, authorized domain, endpoint or endpoint reference, source, and verification summary. A caller must not skip DID Document, Root proof, VC, lifecycle, or endpoint verification because of a high semantic-match score, a tag hit, or a recommendation displayed by the website.

const exact = await client.discoverResources({
  resourceDid: "did:oan:SKDM:replace-with-a-real-identifier",
  limit: 1,
});

const semantic = await client.suggestDiscoveryQuery({
  query: "Find an MCP server for security audit",
});
const candidates = await client.discoverResources({
  query: "Find an MCP server for security audit",
  resourceType: "mcp_server",
  capabilityTags: semantic.capabilityTags,
  limit: 10,
});

If the implementation supports query explanations, the caller should further read the explain result to describe how the query was converted into structured conditions, tags, or semantic conditions, and why candidates were retained or filtered. When there is no match, return a stable empty result; overly short queries, out-of-domain conditions, or invalid filter conditions should return controlled errors. Pagination and deduplication should follow DID and version rules; multiple indexed copies of the same resource must not be displayed as multiple independent resources.

Exact and semantic queries may use the same discovery entry point, but their acceptance assertions differ: exact queries focus on uniqueness, complete DID matching, and version selection; semantic queries focus on candidate sources, filtering reasons, and ranking explanations. A minimal manual acceptance record may be written as follows:

queryType=semantic
query=Find an MCP server for security audit
resourceDid=did:oan:MC:example-identifier
matchedBy=capabilityTags,text
governanceState=active
source=authorized-discovery-index
verification=root-proof-and-package-hash

Here, example-identifier is only a placeholder. If the result contains only text similarity and no verifiable source, governance state, or proof summary, it should be treated as a candidate recommendation and not directly as a trusted callable object.

E.7 Resource Verification Example

After receiving a discovery result, the caller should verify it in the order of “identity, binding, source, governance, endpoint”: first parse did:oan and check the public keys, controllers, and service references in the DID Document; then check the resource DID, type, version, DID Document hash, metadata hash, and package hash in the ResourcePackage; next verify the Root proof and its lifecycle status; then check the issuer, subject, authorized domain, hash bindings, and proof of the registration VC; finally verify the endpoint, protocol, certificate, and invocation permissions according to business policy. Any failure should block high-risk invocation and retain a redacted failure reason.

import { verifyResourcePackageShape, assertUsableLifecycle } from "@openagenet/oan-sdk-ts";

verifyResourcePackageShape(resourcePackage);
assertUsableLifecycle(resourcePackage);
// Continue with the caller's own VC, node-authorization, and endpoint-verification policies.

The SDK’s structural validation functions cannot replace governance-state reads, network-freshness judgments, or business authorization. Verification results should record the version, source URL, hash, issuer, status time, and verification-component version on which they rely; private keys, tokens, and complete sensitive requests must not be recorded.

E.8 Operations Smoke-Test Example

Post-deployment smoke tests should run in dependency order and record “service reachable,” “protocol action succeeded,” and “state converged” separately. The recommended check sequence is: health interfaces and ports; database connection and migration status; Root platform status and governance/authorization reads; Registrar node health and controlled registration request; content distribution queue and publication status; Discovery node synchronization cursor, index statistics, exact query, and semantic query; latest cursor of the off-chain trust indexer; website backend health, frontend routes, registration/discovery transport, and browser console. The deployment process should be considered complete only after the public endpoint, registration transport, discovery query, Network summary, and browser-route checks pass.

A smoke-test record may use the following structure:

{
  "deploymentId": "2026-09-07T12:00:00Z-<commit>",
  "environment": "<environment>",
  "checks": [
    {"name": "root-health", "status": "pass", "observedAt": "..."},
    {"name": "registration-transport", "status": "pass", "resourceDid": "..."},
    {"name": "discovery-query", "status": "pass", "candidateCount": 1},
    {"name": "trust-indexer-freshness", "status": "unknown", "reason": "..."}
  ]
}

The DIDs, times, and statuses in the example illustrate a record format. When a smoke test fails, first determine whether the cause is network transport, build artifacts, configuration, database, governance state, synchronization delay, or a functional error, and then decide whether to retry, roll back, or block public release; do not obtain superficial success by deleting logs, resetting cursors, or skipping registration/discovery checks.

E.9 Same-DID Update Example

A same-DID update must be generated by the original resource controller or an explicitly authorized controller using a new control proof; the DID itself remains unchanged, while updated content in the ResourcePackage or DID Document forms a new version and hash. The process is: read the Local Identity and current version, modify metadata or the ResourcePackage, increment the version according to the applicable versioning scheme, recalculate the metadata and package hashes, sign the update materials, submit them to the Registrar node, have the Root platform re-verify them and form a new Root proof, and then synchronize through the content distribution platform and Discovery node. The Discovery node responds with the latest available version by default, but must retain auditable version and status information.

Update tests should cover a missing control proof, a control proof corresponding to old materials, version rollback, same-version content conflicts, hash inconsistency after an update, and republication of an old version. A failed update must not overwrite the current valid version, and a Discovery node must not treat a VC returned by the Registrar node as a new version; the registration credential, Root proof, and discovery status should be recorded separately.

The comparison record after an update is complete should contain at least the old and new resource DIDs, DID Document hashes, ResourcePackage hashes, control-proof summary, Root proof summary, discovery-index version, and query time. If the content has not changed, the client may reuse an existing preview or idempotent result; if any field affecting a binding relationship changes, the hashes must be recalculated and re-verified, and the display-only version string must not be changed by itself.

E.10 Resource Suspension and Recovery Example

Suspension, revocation, and recovery are lifecycle facts; they are not equivalent to deleting a DID or erasing history. The governance authority or resource controller generates a state change through the permitted governance process, the Root platform and off-chain trust indexer read and project the fact, the Discovery node filters unavailable resources after synchronization, and the caller rechecks the status during verification. Suspension usually means temporarily unavailable, while revocation means that the current credential or resource status is no longer available; recovery must have a clear basis and the Discovery node must not independently change the resource back to active.

State-change fact -> governance event/authorization materials -> Root platform and indexer read
                  -> Discovery node updates filtering state -> caller re-verifies before deciding whether to invoke

Audit records should include the resource DID, original status, new status, source of the fact, event or request identifier, observation time, propagation time, and execution result. When governance status has not synchronized or has exceeded the permitted freshness, sensitive invocation should fail closed; the website or an old snapshot may display “pending synchronization,” but must not display the resource as currently callable.

E.11 Cross-Protocol A2A and MCP Mapping Example

The goal of cross-protocol mapping is to reduce the cost for existing Agent platforms, MCP clients, and tool callers to integrate with OpenAgenet (OAN), not to force objects from different protocols to be treated as the same object. During mapping, the names, capability tags, use cases, inputs, outputs, service endpoints, protocol bindings, and versions in the OAN DID Document and resource description may be mapped to an A2A Agent Card, MCP service metadata, or tool API description; during reverse conversion, the original DID, original fields, version, source, and hash must be retained. An A2A Agent Card or MCP metadata describes capabilities and connection methods, but does not replace OAN control proofs, VCs, Root proofs, governance status, or authorized domains.

OAN DID Document/ResourcePackage
  - id, resourceType, capabilityTags, useCases
  - protocolBindings, service endpoint, version, hashes
        |
        +--> A2A Agent Card: identity reference, skills, interfaces
        +--> MCP metadata: server capabilities, tools, transport
        +--> Tool/API description: operation, schema, endpoint

The mapper should make the source and conversion direction of each field explicit: capability names may be used for display and retrieval, DIDs and hashes are used for identity and integrity traceability, signatures and VCs are retained as independent verification materials, and endpoint mapping represents only a connection entry point and does not automatically authorize invocation. If the target protocol has no equivalent field, use an extension field or an additional reference, and indicate lost information in the result; semantic similarity, protocol compatibility, or successful metadata conversion must not be interpreted as proof that the resource is trusted or usable for business purposes.

The mapping relationship below only describes how information may be carried; it does not require A2A Agent Cards, MCP metadata, or tool API descriptions to use OAN field names:

OAN information Possible location in the external description Retention requirement
Resource DID, DID Document source Identity reference or extension field Retain the original DID and source; do not rewrite it as an ordinary name
Capability tags, use cases, and description Agent Card skills, MCP capabilities, or tool description May be used for display and retrieval, but cannot replace proofs
Protocol bindings, endpoints, and inputs/outputs Interface, transport, and schema descriptions Retain the version and source; endpoint availability requires separate verification
VC, hashes, and Root proof Verification attachment or reference in the external object Do not delete or overwrite the original proofs because conversion succeeded

If a mapped object re-enters the OAN registration or discovery flow, DID, hash, control-proof, authorized-domain, and lifecycle checks must be performed again; an external protocol object may serve as onboarding material, but cannot independently become an OAN publication fact.

References

Source Type Link
oan-root-services Code repository: Root platform deployment and publication examples https://github.com/OpenAgenet/oan-root-services
oan-registrar-node Code repository: Registrar node deployment and registration examples https://github.com/OpenAgenet/oan-registrar-node
oan-discovery-node Code repository: Discovery node deployment, synchronization, and query examples https://github.com/OpenAgenet/oan-discovery-node
oan-trust-indexer Code repository: trust indexer deployment and governance synchronization examples https://github.com/OpenAgenet/oan-trust-indexer
oan-sdk-ts Code repository: client integration examples https://github.com/OpenAgenet/oan-sdk-ts
oan-community-skill Code repository: community registration and discovery operation examples https://github.com/OpenAgenet/oan-community-skill
OAN Yellow Paper arXiv yellow paper: reference deployment and end-to-end mechanisms https://arxiv.org/abs/2606.03163
OAN Resource Identity and Discovery IETF draft: boundaries of resource identity and discovery examples https://datatracker.ietf.org/doc/draft-xu-oan-resource-identity-discovery/
On this page