@dnsid-ai/registry
v0.24.1
Published
DNSid registry client and TXT publishing helpers.
Downloads
1,118
Readme
@dnsid-ai/registry
Registry control-plane client and TXT publishing helpers for DNSid TypeScript packages.
This package owns the current DNSid registry API surface and registry-shaped lifecycle/status behavior. It intentionally keeps registry-specific states separate from protocol-strict @dnsid-ai/protocol agent status types.
Install
npm install @dnsid-ai/registry @dnsid-ai/protocolExample
import { RegistryClient, publishClientControlledRecord } from '@dnsid-ai/registry';
import { createRegistryClientFromEnvironment } from '@dnsid-ai/sdk/node';
// Local by default: http://127.0.0.1:7755 from `dnsid local up`, no credential.
// Hosted: set DNSID_REGISTRY_URL and DNSID_API_KEY from the console.
const registryClient = await createRegistryClientFromEnvironment();
// Or explicitly: new RegistryClient({ baseUrl, token }). HTTPS required except on loopback.
await publishClientControlledRecord({
config,
entityKeyProvider,
registryClient,
});Notes
Registry workflow status is kept separate from protocol AgentStatus. Client-controlled identities publish with publishClientControlledRecord(); registry-managed identities use awaitRegistryManagedPublication(), which requires an observed and verified DNS record before succeeding. publishToRegistry() remains as a deprecated compatibility alias.
The client supports self-managed, zone-explicit, and Live registration workflows, authenticated/custom requests, verification/challenge helpers, typed preparation of C2SP issuance and key rotation, record signing, revoke, cancel, unregister, and retire helpers. registerLiveAgent() sets tier: "live" and managed: true internally, requires a separate idempotency key, and returns a distinct proof challenge rather than a normal registration. While challenge_pending, the response includes the assigned domain and validated challenge transcript. Sign the exact bytes decoded from the latest challengeMessage; a reissued challenge supersedes every earlier challenge and message. Preparation returns untrusted exact bytes and their bound log reference; it does not submit or append them. Registry-managed lifecycle operations are single-owner workflows: callers submit through the registry and must not append a duplicate local lifecycle event.
Registration retries (breaking API change)
registerAgent(), registerSelfManagedAgent(), and registerInZone() now require input.idempotencyKey. Generate and persist the
key and registration input before the first attempt, then reuse both for
reconciliation. Do not generate a fresh key on each retry: the POST may have
created an agent even when its response or the subsequent status GET fails.
Matching ordinary registration replays still require HTTP 201.
Request/response failures throw RegistrationError with idempotencyKey, the
original cause, and domain when the creation response supplied it. If the
domain is known, call getRegistration(error.domain) to recover status without
another POST; otherwise replay the original registration with the same key and
input. An error does not prove creation succeeded or failed. No automatic
retries are performed; resolve permanent request errors rather than blindly
retrying them. Replay safety depends on the registry's idempotency retention
policy; reconcile with the registry before retrying beyond that window.
Key-rotation preparation requires owner credentials: a session cookie or organization API key. An agent bearer token is not accepted.
Registry status semantics are still expected to align with ongoing registry server status work before this API is considered stable.
registerAgent() takes either domain, for a name you control (self-managed),
or zoneId, for a registry-assigned name in a delegated zone (managed). The two
are mutually exclusive, and managed requires zoneId. environment may be
left unset. Private JWK members are rejected before any request is sent. Client-controlled
publication validates every known TXT tag against
the effective publication configuration. config.maxKeyAge controls the ka
tag; when omitted, the helper expects ka to be omitted. Legacy callers may
pass effectiveMaxKeyAge as an explicit override. Callers must configure the
effective gi, ek, ku, lr, su, fl, and cu values exactly.
submitPreparedEvent() throws PreparedEventSubmissionError for structured
product errors. Only TLOG_SUBMISSION_BUSY and
TLOG_SUBMISSION_INDETERMINATE are marked retryable; callers must retain and
retry the same idempotency key and exact entry bytes when
retryWithSameBytes is true.
