This file is the top-level map for ard. The project is now a Go implementation using
Cobra, Gin, GORM, and Postgres.
- Registry server: self-hosted ARD registry exposing discovery, search, health, and
catalog endpoints through Gin, plus optional token-protected admin routes and
same-origin OpenARD Console static serving at
/console. - OpenARD Console: administrator-facing Vite/React app under
apps/consolefor discovery inspection, catalog lifecycle management, review decisions, audit verification, operations checks, and registry API/token configuration. - CLI: Cobra operational entry point for
serve,add catalog,add mcp,add a2a,add skill,add openapi,admin,browse,crawl,export catalog,health,list,metrics,remove,verify catalog,version, andsearchtoday. - Entrypoints:
cmd/ardships the combined toolkit,cmd/ardctlships client and management operations without server startup, andcmd/ard-serverships a dedicated registry server binary. - Public Go SDK:
pkg/ardexposes spec-shaped ARD model aliases and validation helpers, whilepkg/clientprovides an embeddable HTTP client for public discovery and token-protected admin registry surfaces.docs/SDK_COMPATIBILITY.mddefines the public import paths, pre-1.0 compatibility expectations, and unstable boundaries. - Container distribution: the root
Dockerfilebuilds all three binaries, builds the OpenARD Console static assets, and defaults to the dedicatedard-serverruntime entrypoint serving/console.infra/compose.yamlruns the registry with Postgres for local self-hosted trials. - Binary distribution:
make packageproduces versioned Linux/macOS amd64/arm64 archives forard,ardctl, andard-server, plus an SPDX SBOM and SHA-256 checksum manifest. Build metadata is embedded into all packaged binaries and exposed through CLI version commands, server startup logs, and/health.make release-dry-runexercises the same packaging path with pre-tag public surface, SDK, checksum, archive-content, and packaged-binary version checks. - Release publishing: the repository currently has no checked-in CI/CD or tag-triggered
publishing workflow. Maintainers build and verify
dist/artifacts locally before any manual release publication. - E2E verification:
make test-e2eruns live MCP, Skill, OpenAPI, A2A, policy, federation, and SDK checks locally when maintainers need live-artifact confidence. - Client flow:
ard searchand the public Go client send spec-shapedSearchRequestbodies to a registry. The registry rejects unknown request/query fields, missingquery.text, and unsupportedfederationvalues instead of silently normalizing invalid request modes. - Explore flow:
POST /exploreaccepts spec-shapedExploreRequestbodies for local facet aggregation. The registry rejects unknown request/query/facet fields and invalid facet requests instead of silently ignoring malformed introspection options. - Pagination:
POST /search,GET /agents, and admin list/review/audit endpoints return opaque offset page tokens when additional local results are available. - Browse flow:
GET /agentsvalidates public query parameters and supports deterministic filtering plus whitelisted ordering instead of ignoring malformed pagination or browse options.ardctl browsecalls this public endpoint without admin credentials and exposes filter, order, limit, and page-token flags for remote registry inventory. Filters supportAND/OR, parenthesized groups, equality, exclusion, substring containment, and timestamp boundary operators across common spec fields, tags, capabilities, and metadata keys. - Federation referrals:
POST /searchsupportsfederation=referralsby returning activeapplication/ai-registry+jsonentries inSearchResponse.referralsfor client-followed federation. - Federation auto merge:
POST /searchsupportsfederation=autoby querying active registry referrals, forcing upstream requests tofederation=none, and merging upstream results with local results by descending semanticscore. Auto-federated responses return an opaque compositepageTokenthat carries local cursors, upstream cursors, and already-fetched candidates that were not returned on the current page, so clients can continue cross-registry pagination without skipping lower-ranked results. Upstream requests propagateX-Request-IDfor log correlation. - Catalog ingestion:
ard add catalogloads local or remoteai-catalog.jsonfiles, validates them, and persists entries. - Catalog export:
ardctl export catalogwrites persisted registry entries as a spec-shapedai-catalog.jsonfor backup, migration, or well-known publication. - Local registry management:
ardctl listandardctl removeinspect and prune persisted catalog entries. Local list shares the public browse filter/order parser for deterministic inventory workflows. - Admin API: when
ARD_ADMIN_TOKEN,--admin-token,ARD_ADMIN_TOKENS_FILE, or--admin-tokens-fileis configured, Gin exposes protected/admin/*routes for entry listing, entry upsert, catalog upsert, catalog export, lifecycle status changes, review decisions, audit event listing, audit hash-chain verification, and deletion.ardctl adminandpkg/clientcan call those remote routes. - Admin authorization: a single legacy admin token still grants full access. Optional
role-scoped token files split admin access into
reader,publisher,reviewer,operator, andadminpermissions and are reloaded when the file changes. - Lifecycle governance: persisted entries have an implementation-owned lifecycle status
of
active,pending, ordisabled. Public discovery, search, explore, and catalog export only exposeactiveentries; admin list can include and filter all statuses. - Ingestion policy: an optional
ARD_POLICY_FILE/--policy-fileJSON policy can deny entries, require trust metadata fields before persistence, or require review by moving new or updated entries topendingbased on publisher or media type.ard verify catalogcan also evaluate the same policy without persistence for CI or preflight use. - Review workflow: pending entries can be listed through
/admin/reviewsand approved or rejected through dedicated review routes andardctl admin review. Policy can require multiple distinct reviewer approvals before a pending entry becomes active. Review decisions can carry an optional reason that is recorded on the audit event, not on the ARD catalog entry. - Audit log: admin mutations append persisted events for upsert, status changes, and
deletion with action, identifier, status, optional review reason, source, remote
address, request ID, timestamp, previous hash, and event hash.
/admin/audit/verifychecks the persisted hash chain. - Request correlation: Gin middleware preserves or generates
X-Request-ID, returns it on every HTTP response, emits JSON access logs, and attaches request IDs to admin audit events. Shared request-ID context propagation also covers outbound catalog/artifact fetches, source digest verification, attestation digest verification, and provenance digest verification. - Trace context: Gin middleware accepts or generates W3C
traceparent, returns the current service span on each HTTP response, adds trace IDs and span IDs to JSON access logs, optionally exports server spans to an OTLP/HTTP trace endpoint, and propagates trace context to outbound federation, catalog, artifact, source digest, attestation digest, provenance digest, and admin client requests. - Metrics: Gin exposes public Prometheus-style
/metricswith process uptime, in-flight requests, request totals, HTTP duration histograms by method, route, and status, plus low-cardinality Go runtime gauges for goroutines, heap, and GC state. - Artifact onboarding:
ard add mcp,ard add a2a,ard add skill, andard add openapitranslate real MCP server cards, A2A agent cards, Skill markdown files, and OpenAPI documents into ARD catalog entries. - Verification engine: schema-level checks cover
urn:air:, required fields, schema-aligned catalog root and host fields, media type syntax,url/dataexclusivity, absolute HTTP(S) URL syntax,updatedAtdate-time format, scalar metadata values, representative query count, duplicate catalog identifiers, and minimal catalog host metadata plustrustManifeststructure, includingidentityTypeenum validation, identity shape checks forhttps,spiffe, anddid, schema-aligned known-field enforcement,trustSchema/signature shape validation, attestation/provenance structure validation, and HTTP(S)/SPIFFE/did:webidentity trust-domain alignment with theurn:air:publisher. URL artifacts can be pinned and verified withtrustManifest.sourceDigest, and strict verification can require all URL-delivered entries to carry pinned source digests. Attestation documents can be fetched and verified againsttrustManifest.attestations[].digest, and strict verification can require every attestation to carry a pinned digest. HTTP(S) provenance sources can be fetched and verified againsttrustManifest.provenance[].sourceDigest, and strict verification can require every HTTP(S) provenancesourceIdto carry a pinned source digest. Detached compact JWStrustManifest.signaturevalues can be verified against explicit Ed25519 trust anchors supplied in ard's native format, local JWKS OKP/Ed25519 format, or explicit HTTPS remote JWKS URLs whose host matches the entry trust domain. Opt-indid:web, OIDC, SPIFFE bundle, and HTTPS TLS certificate discovery can also provide OKP/Ed25519 keys for the same verifier, and strict verification can require every catalog entry to carry a verifiable signature.
cmd/ard/: combined CLI and server binary entry point.cmd/ardctl/: CLI/client-only binary entry point.cmd/ard-server/: server-only binary entry point.internal/cli/: Cobra command tree.internal/httpapi/: Gin router and HTTP handlers.internal/ard/: ARD models, media type constants, filters, and validation.internal/adapters/: artifact-to-catalog-entry adapters for MCP, A2A, Skills, and OpenAPI.internal/buildinfo/: linked build version, commit, and build date metadata shared by binaries, HTTP health, and package checks.internal/catalog/: local and HTTP catalog loading.internal/store/: GORM/Postgres persistence and search.internal/config/: environment and CLI config helpers.internal/tools/sbom/: repository-native SPDX SBOM generator used by release packaging.internal/tools/publicsurface/: repository-native public API and CLI surface checker for pre-release compatibility gates.pkg/ard/: public ARD model aliases and validation helpers for Go consumers.pkg/client/: public HTTP client for unauthenticated registry discovery surfaces and token-protected admin management routes.packages/: reserved for future non-Go SDK packages or generated artifacts.apps/registry/: reserved for a separate deployable server only if the single binary becomes limiting.infra/: Docker Compose, deployment, and environment definitions.scripts/: repository automation that agents can run directly.docs/: repository knowledge base and system of record.
Keep the internal boundaries visible. Public packages under pkg/ should remain small,
spec-shaped, and stable enough for external import.
The smallest useful deployment is one registry process with embedded persistence:
catalog URLs / local artifacts
|
v
crawler + adapter layer
|
v
validation + verification
|
v
metadata store + search index
|
v
ARD /search API + CLI client
The first storage target is Postgres through GORM. Search is currently simple
case-insensitive text recall over persisted search_text, with score computed as a
deterministic semantic relevance approximation. Local results are ordered by descending
score and stable catalog fields. docs/SEARCH.md records the first-release search
contract. More advanced ranking can replace this behind the store boundary without
changing HTTP contracts.
- A user adds, lists, removes, exports, or searches catalog entries with the CLI or API.
- The crawler fetches
/.well-known/ai-catalog.jsonor a direct artifact URL. - The adapter layer normalizes supported artifacts into ARD catalog entries.
- The verification layer validates schema, catalog root/host known fields, media type
syntax,
url/dataexclusivity, domain-anchoredurn:air:identifiers, duplicate identifiers within a catalog, publisher domains, trust metadata, and optional URL source digests. - The index layer stores normalized entries and searchable fields.
POST /searchaccepts an ARDSearchRequestand returns a rankedSearchResponse.- Clients fetch the selected artifact and execute it through its native protocol.
- Keep ARD models and protocol handling independent from transport, storage, and CLI code.
- Keep verification pure and reusable; both server-side ingestion and CLI validation should call the same logic.
- Keep adapters narrow. MCP, Skills, A2A, and OpenAPI adapters should translate metadata, not execute tools.
- Search and ranking should consume normalized catalog entries, not protocol-specific objects.
- Page tokens are opaque implementation details. Do not expose raw database cursors or require clients to parse token contents.
- Federation traversal must stay bounded by depth, registry count, response size, and timeout controls. Auto federation currently queries at most three upstream registry referrals, uses non-recursive upstream search requests, limits response bodies, and returns a score-ranked merged result set with local entries winning duplicate identifiers. Auto federation page tokens are implementation-owned opaque cursors; do not parse them or forward local cursor internals to upstream registries. Request IDs are forwarded for correlation; admin tokens are not.
- Outbound catalog and artifact fetches should propagate request IDs when the initiating
context carries one.
ardctl admingenerates an operation-level request ID by default and accepts--request-id/ARD_REQUEST_IDwhen operators want to set it explicitly. - Inbound and outbound HTTP trace context uses W3C
traceparent. The registry should preserve the incoming trace ID, create a local span ID, optionally export the completed server span to OTLP/HTTP, and propagate that context downstream. - Secrets and tokens may be used during request scope only; they must not be stored or emitted in plain text.
- Admin API routes must remain disabled by default and require an authorized
Authorization: Bearertoken when enabled. - Role-scoped token file reloads must preserve the last valid token set if a changed file is invalid, so a partial write does not lock operators out.
- Audit hash chains are tamper-evident integrity metadata, not a replacement for external immutable storage, signatures, or database access control.
- Inactive lifecycle states are implementation metadata, not ARD catalog schema fields. Do not export disabled or pending entries through public catalog/search surfaces.
- Policy evaluation must happen before persistence for local add/crawl and remote admin imports. Denied entries must not be persisted.
- Policy preflight through
ard verify catalog --policy-filemust evaluate the same policy rules without opening the database or mutating registry state. - Policy trust metadata requirements are field-presence gates only. Cryptographic, digest, key, and identity proof must stay in explicit verification workflows.
- Specification behavior should be derived from
ards-project/ard-spec, especiallyspec/ard.md,spec/schemas/, ADRs, andconformance/.
GET /.well-known/ai-catalog.json: advertises this registry plus active configured catalog entries. Pending and disabled entries are not published. Implemented.POST /search: ARD search endpoint with root/query known-field validation plus root-levelpageSize,pageToken, andfederationenum validation. Implemented.POST /explore: optional; implemented for local facet aggregation with request, query, and facet known-field validation.GET /agents: optional deterministic browse endpoint with validatedpageSizeandpageToken, EBNF-likefiltersupport fordisplayName,type,publisherId,tags,capabilities,metadata.<key>,createdAfter, andupdatedAfter, plusAND,OR, parenthesized groups, and=,!=,contains,>, and>=operators where meaningful.orderByis whitelisted for display name, type, publisher, creation time, and update time.GET /health: deployment health with active entry count plus build version, commit, and build date metadata. Implemented.GET /metrics: Prometheus-style operational metrics. Implemented./admin/*: implementation-specific management routes; disabled unless an admin token is configured. Implemented, including entry lifecycle status management and paginated audit event listing plus audit hash-chain verification.- Go SDK equivalents:
pkg/clientimplements publicSearch,Browse,Explore,Catalog, andHealthmethods with typed responses frompkg/ard. It also exposes token-protected admin methods for entry list/upsert/delete, catalog import/export, review decisions, lifecycle status, audit listing, and audit hash-chain verification.make test-public-go-clientverifies these public packages from an external Go module. - CLI equivalents:
serve,add catalog,add mcp,add a2a,add skill,add openapi,crawl,admin,browse,export catalog,health,list,metrics,remove,verify catalog,version, andsearchare implemented.ardctl healthcalls public/healthwithout admin credentials, andardctl metricscalls public/metricsfor Prometheus text output.ardctl browsecalls public/agentswith filter/order/pagination options.ardctl list --filterand--order-byreuse the same deterministic browse parser as public/agents.ardctl admin statusmanages remote entry lifecycle state,ardctl admin review --reasonhandles pending review decisions with optional audit reasons, andardctl admin auditlists and verifies admin mutation events.ard-serverruns the same server without exposing management subcommands, while still exposing--versionandversionfor operational inventory.
The upstream specification source is:
- Repository:
https://github.com/ards-project/ard-spec - Rendered spec:
https://agenticresourcediscovery.org/spec/ - Current observed draft: v0.9
- Current observed local checkout commit:
f606687e93c98da5cc7be3a752361c3c762bfc4f
Implementation decisions should prefer the upstream main spec, schemas, ADRs, and conformance tool over older reference implementations. In particular:
- Use
urn:air:identifiers, not the olderurn:ai:form. - Treat
application/mcp-server-card+jsonas the MCP discovery media type. - Treat OpenAPI artifact onboarding as an implementation extension using
application/openapi+jsonuntil upstream ARD standardizes an OpenAPI discovery media type. - Validate catalog entry
typevalues as media type syntax, not as a fixed allowlist. This preserves extension media types while rejecting malformed envelope values. - Reject unknown catalog root and
hostfields according to the schema. Entry extension fields are not rejected by this closed-shape check. - Treat
trustManifest.sourceDigestas source artifact integrity metadata. It verifies bytes fetched from the entry URL; it is not a signature or identity proof. This is an implementation extension to the ARDtrustManifestschema. - Treat
trustManifest.attestations[].digestas attestation document integrity metadata. It verifies fetched attestation bytes only; it is not auditor trust, freshness, or claim truth verification. - Treat
trustManifest.provenance[].sourceDigestas HTTP(S) provenance source integrity metadata. It verifies fetched source bytes only; it is not lineage truth, publisher identity, or URN source resolution. - Treat detached compact JWS verification as explicit operator trust-anchor verification.
It proves the configured Ed25519 key signed the deterministic
trustManifestpayload generated byardwithsignatureremoved. Local files and explicitly supplied HTTPS remote JWKS URLs can provide trust anchors. Opt-indid:webdiscovery can resolve DID documents and use OKP/Ed25519verificationMethod[].publicKeyJwkkeys. Opt-in OIDC discovery can resolve HTTPS issuer metadata, validateissuer, and use OKP/Ed25519 keys fromjwks_uri. Opt-in TLS certificate discovery can use verified HTTPS leaf certificate Ed25519 keys. Opt-in SPIFFE discovery readsSPIFFE-X509attestationurivalues as host-matched HTTPS bundle JWKS endpoints. TLS certificate discovery can enforce operator-supplied SPKI SHA-256 pins. SPIFFE SVID validation, non-did:webDID discovery, certificate transparency, revocation, and non-Ed25519 certificate keys are out of scope. - Treat HTTP(S), SPIFFE, and
did:webtrustManifest.identitytrust-domain matching as catalog metadata consistency, not as proof of publisher ownership. - Keep
scorestrictly as semantic relevance, not a trust or safety signal. - Support web ingestion of
ai-catalog.jsoncatalogs as a required registry capability. - Keep
/explorelocal-only and optional; if unsupported, return501. - Keep federation controlled by root-level
SearchRequest.federation.referralsmode returns registry entries inSearchResponse.referrals;automode performs a bounded server-side upstream merge. Upstream auto requests are sent withfederation=noneto avoid recursive traversal and without the local registry's page token. They include the inboundX-Request-IDwhen one is available.
Do not vendor or fork the upstream spec content casually. If the implementation needs schemas or conformance tools in-repo, add a pinned, documented copy under a clearly named third-party or generated directory and record the source commit.
- SPIFFE SVID validation, non-
did:webDID, certificate transparency, revocation, and broader trust-anchor discovery depth for MVP. - Whether to add an embedded non-Postgres development mode.
- Whether to vendor selected upstream spec artifacts, use a git submodule, or fetch pinned artifacts during development.
- Whether to replace the MVP JSON ingestion policy with a richer policy engine.
When these decisions are made, update this file in the same task as the code.