Registry

Publisher Verification

Aroha has three publisher verification tiers. Each tier is a cryptographic statement about who registered an agent — not just whether it has good reputation.

TierWhat it provesHowHub badge
communityValid API keyDefault — no extra stepscommunity
domainControls the claimed domainHost DID in /.well-known/aroha-did.json🛡 domain
org-signedOrg key authorised this registrationEd25519 signature over registration payload🔑 publisher

Community tier

The default. Any valid API key can register agents — no additional steps required. Community agents are hidden from the public discovery list for 48 hours after registration (the discovery cooldown) to prevent spam and impersonation attacks that rely on immediately appearing in search results.

Reputation signals still apply: once an agent accumulates a score ≥ 7 000 and is at least 7 days old, it is additionally flagged as verified: true in API responses — a quality signal, independent of the publisher tier.

Domain tier

Domain verification proves that the agent owner also controls a specific domain. It closes the most common impersonation attack: registering an agent with org_name = "Anthropic" when you have no connection to Anthropic. Getting domain tier requires you to own a real domain.

Step 1 — host the well-known file

Serve the following JSON at https://<your-domain>/.well-known/aroha-did.json:

{
  "did": "did:aroha:your-agent-did-here"
}

Step 2 — call the verification endpoint

curl -X POST https://registry.aroha-labs.com/v1/agents/<didHash>/verify-domain \
  -H "Authorization: Bearer $AROHA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "domain": "yourdomain.com" }'

# → { "ok": true, "verificationTier": "domain", "domain": "yourdomain.com" }

The registry fetches the well-known file and checks the DID matches. On success the agent's tier is upgraded to domain and the domain is stored. The blue 🛡 domain badge appears in the Hub.

What domain tier doesn't prove: domain control is not identity. An attacker can register anthropic-agents.com and pass domain verification. A human reading the badge tooltip will see the full domain name — but automated callers trusting only the tier label should use org-signed for strong publisher guarantees.

Org-signed tier

The highest tier. The org generates an Ed25519 keypair and signs every agent registration with their private key. A valid signature proves the agent was explicitly authorised by whoever controls that private key — even if an attacker steals the org's API key, they cannot register org-signed agents without also stealing the private signing key (a separate, never-transmitted credential).

Step 1 — generate an Ed25519 keypair

The private key never leaves your infrastructure. Generate it with any standard Ed25519 library:

import * as ed from "@noble/ed25519";
import { sha512 } from "@noble/hashes/sha512";

// Required for sync signing on Node.js
ed.etc.sha512Sync = (...m) => sha512(...m);

const privateKey = ed.utils.randomPrivateKey();           // 32 bytes
const publicKey  = ed.getPublicKeySync(privateKey);       // 32 bytes

const orgPublicKeyB64 = btoa(String.fromCharCode(...publicKey));
console.log("Store privately:", btoa(String.fromCharCode(...privateKey)));
console.log("Publish this:  ", orgPublicKeyB64);

Step 2 — publish your public key at your domain

Host the public key at https://<your-domain>/.well-known/aroha-org.json:

{
  "orgPublicKeyB64": "base64-encoded-32-byte-ed25519-public-key"
}

Step 3 — register your org key with Aroha

Submit your public key once. The registry fetches the well-known file to confirm you control the domain and that the submitted key matches what's published.

curl -X PUT https://registry.aroha-labs.com/v1/auth/org-key \
  -H "Authorization: Bearer $AROHA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "orgPublicKeyB64": "your-base64-public-key",
    "domain": "yourdomain.com"
  }'

# → { "ok": true, "domain": "yourdomain.com" }

This is a one-time step per API key. To rotate your org key, call this endpoint again with the new public key (remember to update .well-known/aroha-org.json first).

Step 4 — sign every agent registration

For each agent registration, produce an Ed25519 signature over the canonical payload, then include it in the POST /v1/agents request body.

Canonical signing payload — UTF-8 bytes of JSON with keys sorted alphabetically:
{
  "action":       "register-agent",
  "did":          "did:aroha:your-agent-did",
  "manifestCID":  "QmYourManifestCID",
  "publicKeyB64": "base64-agent-ed25519-public-key",
  "registeredAt": 1720400000000
}

registeredAt must be within ±5 minutes of the server's clock (replay protection).

import * as ed from "@noble/ed25519";

const registeredAt = Date.now();

// Canonical JSON — keys must be alphabetically sorted
const sigPayload = JSON.stringify({
  action:       "register-agent",
  did:          "did:aroha:acme-summarizer",
  manifestCID:  "QmYourManifestCID",
  publicKeyB64: agentPublicKeyB64,   // the agent's Ed25519 key (not the org key)
  registeredAt,
});

const sigBytes = ed.sign(
  new TextEncoder().encode(sigPayload),
  orgPrivateKey,   // 32-byte org private key — never transmitted
);
const orgSignature = btoa(String.fromCharCode(...sigBytes));

// Registration request
const res = await fetch("https://registry.aroha-labs.com/v1/agents", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: `Bearer ${AROHA_API_KEY}`,
  },
  body: JSON.stringify({
    did:          "did:aroha:acme-summarizer",
    manifestCID:  "QmYourManifestCID",
    publicKeyB64: agentPublicKeyB64,
    registeredAt,
    orgSignature,            // ← the org signature
  }),
});

const { didHash } = await res.json();
// Agent is immediately verificationTier: 'org-signed'

The amber 🔑 publisher badge appears in the Hub. The full signature is stored in the registry as an audit record so it can be verified offline independent of Aroha.

Security model

What org-signed closes

AttackWithout org-signingWith org-signing
Register agent as org_name="Anthropic"Free text, trivially doneRequires Anthropic's private org key
Stolen API key → rogue agent registrationAPI key is sufficientAlso requires org private key
Impersonate another org's agentsTrivialCryptographically impossible
Replay a signed registrationN/ABlocked by ±5 min registeredAt window

What it doesn't solve

Org-signing proves key ownership, not legal identity. Aroha does not yet run a certificate authority that binds keys to legal entities. For the current release, enterprise customers should contact Aroha to have their org key manually marked as enterprise-verified — a human confirmation step that legal entity X controls domain Y.

Future planned integrations: Sigstore (OIDC-based attestation linking registrations to GitHub Actions / GCP / AWS identities) and enterprise CA bridging for orgs with internal PKI. See the roadmap.

Key rotation

If your org private key is compromised, call PUT /v1/auth/org-key with a new keypair immediately (after updating your .well-known/aroha-org.json). Existing org-signed agents retain their tier — the signature stored at registration time was valid when produced. New registrations will use the rotated key.

Next steps