Go: package dnsid
Generated from the Go source by scripts/gen-docs.sh — do not edit; run it to regenerate. Canonical deep reference: pkg.go.dev/github.com/dnsid-ai/dnsid-go. Guides and account setup: https://docs.dnsid.ai.
import "github.com/dnsid-ai/dnsid-go"Package dnsid implements DNSid, domain-anchored identity for agents: verify who an agent is, who governs it, and whether it is still live, straight from DNS.
A DNSid identity is published as a signed _dnsid TXT record on the agent’s domain. The record names the agent’s governing organization (gi), the accountable-entity record-signing key set (ek), and the agent runtime key set (ku); a status endpoint (su) reports the agent’s lifecycle state (PENDING, PROVISIONING, VERIFYING, ACTIVE, RETIRED, or REVOKED — verification requires ACTIVE). This package resolves that record, verifies the record signature against the entity JWKS, checks lifecycle evidence through the bound transparency log, enforces the status endpoint, and signs on the agent’s behalf — all over SSRF-safe, DNS-rebinding-resistant transport.
IdentityManager
Section titled “IdentityManager”IdentityManager is the facade for the SDK. A verify-only manager needs no key material, but does need independently configured log trust. Set DNSID_LOG_TRUST_PROFILE_FILE to a trusted profile before using this flow:
idm, err := config.IdentityManagerFromEnvironment(ctx, nil, dnsid.Config{}, config.Dependencies{})if err != nil { log.Fatal(err)}
verified, err := idm.VerifyDomain(ctx, "your-agent.example")if err != nil { log.Fatal(err)}fmt.Println(verified.Domain(), verified.Record().GovernanceID, verified.Status().State)A manager constructed with Config.Identity and a KeyProvider can also act as an agent: build and sign its own _dnsid record (CreateTXTRecord), publish its operational and entity JWKS documents (GetKeySet, GetEntityKeySet), write lifecycle log events, and drive registry workflows. The config package loads such a manager from DNSID_* environment variables or an identity created by the DNSid CLI.
Main entry types
Section titled “Main entry types”- IdentityManager — the facade: domain verification, record creation, and registry workflows.
- Config (IdentityConfig, VerificationConfig, TransportConfig) — local publication settings, verification policy including the optional TrustedEntities counterparty allowlist, and SDK-managed transport. IdentityManagerOption injects runtime dependencies.
- VerifiedDomain — the immutable result of successful verification: record, key sets, status, and expiry.
- TXTRecord — a parsed _dnsid identity record (ParseTXTRecord, Serialize, CanonicalContent).
- KeyProvider / LocalKeyProvider — signing-key storage, generation, and rotation.
- JWKS / JWK — typed wrappers over JWK sets and keys.
- RegistryClient / HTTPRegistryClient — the DNSid registry control-plane API.
- ParseError, ValidationError, ArgumentError, VerificationError — the typed error taxonomy; VerificationError carries a VerificationCode and a transient flag.
Subpackages
Section titled “Subpackages”The application profiles build on this core: jose creates and verifies DNSid JWTs and compact JWS, oidc mints and verifies DNSid OIDC tokens, and httpsig and webbotauth implement RFC 9421 HTTP Message Signatures and the Web Bot Auth profile. The log subpackage defines the lifecycle-event and transparency-log model that verification builds on.
Guides and account setup live at https://docs.dnsid.ai; full API reference is on pkg.go.dev.
Constants
Section titled “Constants”Typed lifecycle constants for callers that want the AgentState type.
const ( AgentStatePending = dnsidlog.AgentStatePending AgentStateProvisioning = dnsidlog.AgentStateProvisioning AgentStateVerifying = dnsidlog.AgentStateVerifying AgentStateActive = dnsidlog.AgentStateActive AgentStateRetired = dnsidlog.AgentStateRetired AgentStateRevoked = dnsidlog.AgentStateRevoked)Registry workflow statuses reported by the registry API, alongside the AgentState* lifecycle states. READY ends a registration workflow successfully; the others are terminal failures.
const ( RegistryStatusReady = "READY" RegistryStatusCancelled = "CANCELLED" RegistryStatusRejected = "REJECTED" RegistryStatusError = "ERROR" RegistryStatusFailed = "FAILED")DefaultPublishProfile is the current _dnsid TXT behavior profile emitted by this SDK. It is distinct from Version, which reports the SDK/module release.
const DefaultPublishProfile = identityRecordDraft01DefaultRegistryURL is the local registry started by `dnsid local up`. It is used when no base URL is passed; hosted use requires an explicit URL (see config.RegistryClientFromEnvironment).
const DefaultRegistryURL = "http://127.0.0.1:7755"DefaultVerificationTimeout bounds a complete verification when no caller deadline is supplied.
const DefaultVerificationTimeout = 30 * time.SecondVariables
Section titled “Variables”Sentinel verification errors. Defined as *VerificationError exemplars so callers can branch with errors.Is or errors.As. Matching is code-based: a freshly-constructed VerificationError with the same Code satisfies errors.Is against the sentinel.
var ( ErrTokenExpired = &VerificationError{ code: VerificationCodeTokenExpired, message: "dnsid: token expired", } ErrTokenNotYetValid = &VerificationError{ code: VerificationCodeTokenNotYetValid, message: "dnsid: token not yet valid", } ErrInvalidSignature = &VerificationError{ code: VerificationCodeSignatureInvalid, message: "dnsid: invalid signature", } ErrMalformedToken = &VerificationError{ code: VerificationCodeMalformedToken, message: "dnsid: malformed token", } ErrInvalidClaims = &VerificationError{ code: VerificationCodeInvalidClaims, message: "dnsid: invalid claims", } ErrLifetimeTooLong = &VerificationError{ code: VerificationCodeLifetimeTooLong, message: "dnsid: requested lifetime exceeds maximum", } ErrCounterpartyNotAccepted = &VerificationError{ code: VerificationCodeCounterpartyNotAccepted, message: "dnsid: counterparty not accepted", })Sentinel causes for _dnsid record-signature verification failures, distinguishable with errors.Is: a malformed sg= value, an unusable entity JWKS, and a signature that no served key verifies. They intentionally share the same generic message so error text does not expose a verification oracle.
var ( ErrOwnerSignatureMalformed = errors.New("dnsid: signature verification failed") ErrOwnerSignatureInvalidJWKS = errors.New("dnsid: signature verification failed") ErrOwnerSignatureNoMatchingKey = errors.New("dnsid: signature verification failed"))ErrKeyStoreDurability means the new key store is visible on disk, but syncing its directory failed. The mutation is NOT rolled back in memory. Stop the workflow and resolve the storage error before proceeding; see OPERATIONS.md.
var ErrKeyStoreDurability = errors.New("dnsid: key store published but durability uncertain")ValidKeyAgeValues is the enumerated set of valid ka= values.
var ValidKeyAgeValues = map[string]bool{ "24h": true, "7d": true, "30d": true, "90d": true,}Version is the SDK release of this module — distinct from DefaultPublishProfile, which is the exact TXT behavior-profile selector emitted by new publications.
When this module is consumed as a tagged dependency (e.g. `go get github.com/dnsid-ai/dnsid-go@v0.1.0`), Version reports the module version recorded in the importing binary’s build info. When the module IS the main module (e.g. the `dnsid` CLI built from this repo) and was built from a tagged commit, Version reports that tag. In all other cases — including `go run` from a working tree — Version reports “dev”.
var Version = resolveVersion()func CreateDnsidHTTPClient(transportConfig TransportConfig) (*http.Client, error)CreateDnsidHTTPClient creates an SDK-managed HTTP client using DNSid transport settings.
func NormalizeFQDN(input string) (string, error)NormalizeFQDN returns the canonical form of the given DNS name:
- Map IDNA dot-equivalent runes and strip a single trailing dot.
- Apply IDNA A-label encoding (Unicode -> punycode where needed).
- Lowercase all ASCII letters.
- Validate label-length limits (<=63 octets per label).
- Validate total length <=246 octets (DNSid agent-FQDN limit per spec).
Returns the normalized FQDN or a non-nil error if input is invalid.
func RegistrantDomain(domain string) stringRegistrantDomain returns the registrant domain for use as gi=.
It uses the public suffix list when possible. If the suffix lookup fails, it falls back to the final two DNS labels, or the normalized domain itself when fewer than two labels exist.
func SafeDialerTransport() *http.TransportSafeDialerTransport returns an HTTP transport that resolves a hostname once, validates every returned IP address, and dials a concrete validated IP.
func Tags(rec *TXTRecord) map[string]stringTags returns the record’s tag-value pairs as a map, excluding empty optional fields. It always emits the current wire tag names.
func VerificationContext(ctx context.Context) (context.Context, context.CancelFunc)VerificationContext preserves a caller deadline, or supplies the finite SDK default. Nested verification operations must pass the returned context to their children.
AgentState is the canonical typed lifecycle state, defined in the log package (which this package imports). Re-exported here so callers can use dnsid.AgentState without importing the log package directly.
type AgentState = dnsidlog.AgentStatefunc AgentStates() []AgentStateAgentStates returns a copy of the six canonical lifecycle states in order.
func ParseAgentState(s string) (AgentState, error)ParseAgentState converts a raw string into the typed AgentState, returning an error if the value is not one of the six canonical lifecycle states. This allows callers that hold string values (e.g. from JSON or databases) to safely convert to the typed constant.
AgentStatus is the protocol status document fetched from su=.
type AgentStatus struct { State AgentState `json:"state"` LastTransitionAt time.Time `json:"lastTransitionAt"` RevocationReason string `json:"revocationReason,omitempty"`}func (*AgentStatus) Validate
Section titled “func (*AgentStatus) Validate”func (s *AgentStatus) Validate() errorValidate checks the status document against the DNSid status profile: State must exactly match one of the six canonical lifecycle states, LastTransitionAt must be set, and a REVOKED status must carry a valid revocation reason. It returns a *ValidationError describing the first violation, or nil.
Config is the single core configuration entry point for an IdentityManager. Identity holds the local identity’s publication settings and is nil for a verification-only manager. Verification and Transport apply identically in both modes. Runtime dependencies (key providers, resolvers, fetchers, caches, log registries) are supplied through IdentityManagerOption values, not here.
type Config struct { Identity *IdentityConfig Verification VerificationConfig Transport TransportConfig}func (Config) Validate
Section titled “func (Config) Validate”func (c Config) Validate() errorValidate checks every section of the configuration without constructing a manager: Identity (when set), Verification, and Transport. It performs no network or file I/O.
DNSResolver fetches DNSid TXT records.
DNSSECModeValidated and DNSSECModeRequired require a resolver that reports a definitive DNSSEC state. The default netDNSResolver reports DNSSECStateUnknown, which DNSSECModeAuto accepts.
type DNSResolver interface { FetchTXT(ctx context.Context, name string) ([]TXTRecordRData, DNSSECState, error)}DNSSECMode describes the caller’s DNSSEC verification policy.
type DNSSECMode stringDNSSECMode values. DNSSECModeAuto accepts VALID, UNSIGNED, and UNKNOWN resolver states; DNSSECModeValidated rejects UNKNOWN; DNSSECModeRequired accepts only VALID. Every mode rejects FAILED.
const ( DNSSECModeAuto DNSSECMode = "auto" DNSSECModeValidated DNSSECMode = "validated" DNSSECModeRequired DNSSECMode = "required")DNSSECState reports the resolver’s DNSSEC validation result.
type DNSSECState stringDNSSECState values reported by a DNSResolver. VerifyDomain always rejects DNSSECStateFailed. DNSSECStateUnknown is accepted by DNSSECModeAuto and rejected by DNSSECModeValidated and DNSSECModeRequired; DNSSECStateUnsigned is accepted unless the manager’s DNSSECMode is DNSSECModeRequired.
const ( DNSSECStateUnknown DNSSECState = "UNKNOWN" DNSSECStateValid DNSSECState = "VALID" DNSSECStateUnsigned DNSSECState = "UNSIGNED" DNSSECStateFailed DNSSECState = "FAILED")FetchOptions constrains HTTPS JSON fetches.
type FetchOptions struct { AllowedHost string DomainBoundary bool MaxResponseBytes int64 RedirectPolicy RedirectPolicy}HTTPSFetcher fetches JSON over safe HTTPS. Implementations must be safe for concurrent use.
type HTTPSFetcher interface { FetchJSON(ctx context.Context, rawURL string, opts FetchOptions) (json.RawMessage, *tls.Certificate, error)}IdentityCache caches domains in manager-private verification namespaces. Direct Get/Put/Evict calls use the standalone namespace; managers sharing this backend never consume each other’s results. Capacity eviction is global.
type IdentityCache struct { // contains filtered or unexported fields}func NewIdentityCache(_ time.Duration) *IdentityCacheNewIdentityCache constructs a bounded, empty cache. The legacy defaultTTL parameter is ignored: only the original absolute evidence expiry is used.
func (*IdentityCache) Evict
Section titled “func (*IdentityCache) Evict”func (c *IdentityCache) Evict(domain string)Evict removes the entry for domain, if present. The domain must already be in normalized form (see NormalizeFQDN); IdentityManager.EvictDomain normalizes for you. Evict is safe for concurrent use and is a no-op on a nil receiver.
func (*IdentityCache) Get
Section titled “func (*IdentityCache) Get”func (c *IdentityCache) Get(domain string) *VerifiedDomainGet returns a deep copy of the cached entry for domain with CachedState “cached”, or nil when the domain is absent or the entry has expired. Expired entries are evicted on access. Get is safe for concurrent use and returns nil on a nil receiver.
func (*IdentityCache) Put
Section titled “func (*IdentityCache) Put”func (c *IdentityCache) Put(vd *VerifiedDomain)Put stores a deep copy with its original absolute expiry. Zero-TTL, unbounded, expired, and empty-domain results are not stored. At most 1024 results are retained across namespaces. Put is safe for concurrent use.
IdentityConfig contains the local identity’s DNSid publication settings.
type IdentityConfig struct { Domain string GovernanceID string LogRef string StatusURL string PolicyFlags []PolicyFlag MaxKeyAge KeyAge KeyURL string // Operational-key JWKS URL serialized as ku=. EntityKeyURL string // Accountable-entity JWKS URL serialized as ek=. CapabilitiesURL string PublishProfile string}func (IdentityConfig) Validate
Section titled “func (IdentityConfig) Validate”func (c IdentityConfig) Validate() errorValidate checks required identity configuration.
IdentityManager is the primary DNSid SDK facade.
type IdentityManager struct { // contains filtered or unexported fields}func NewIdentityManager(cfg Config, kp KeyProvider, opts ...IdentityManagerOption) (*IdentityManager, error)NewIdentityManager constructs the DNSid SDK facade. A nil cfg.Identity with a nil KeyProvider yields a verification-only manager. A non-nil cfg.Identity requires a KeyProvider and enables acting as the configured local identity (record creation, JWKS publication, lifecycle events). Configuration is validated and snapshotted before any network work; it returns an *ArgumentError for invalid configuration, a KeyProvider or entity KeyProvider without identity, identity without a KeyProvider, or Config.Transport settings whose only SDK-managed consumers were all injected.
func NewVerifier(opts ...IdentityManagerOption) (*IdentityManager, error)NewVerifier constructs an IdentityManager for verification without local identity configuration or key material. It is shorthand for NewIdentityManager with a zero Config and nil KeyProvider; pass a Config with nil Identity to NewIdentityManager to set verification or transport settings.
func (*IdentityManager) AwaitRegistryManagedPublication
Section titled “func (*IdentityManager) AwaitRegistryManagedPublication”func (m *IdentityManager) AwaitRegistryManagedPublication(ctx context.Context, client RegistryRegistrationReader, opts *WaitForStatusOptions) (*PublishedRecord, error)AwaitRegistryManagedPublication waits for registry-managed DNS publication, then verifies the record observed through DNS. Required log authorization, such as C2SP ISSUANCE consent, must be completed before or concurrently with this wait through the bound log package.
func (*IdentityManager) BuildUnsignedTXTRecord
Section titled “func (*IdentityManager) BuildUnsignedTXTRecord”func (m *IdentityManager) BuildUnsignedTXTRecord() (*TXTRecord, error)BuildUnsignedTXTRecord builds and validates this identity’s unsigned _dnsid TXT record. The returned record is ready for its entity-key signature.
func (*IdentityManager) CanonicalizeLogEvent
Section titled “func (*IdentityManager) CanonicalizeLogEvent”func (m *IdentityManager) CanonicalizeLogEvent(event dnsidlog.LogEvent) ([]byte, error)CanonicalizeLogEvent returns the log-method-specific bytes covered by every lifecycle-event signature. It requires a bound log reader, but not a write-capable log or access to any private key.
func (*IdentityManager) CreateTXTRecord
Section titled “func (*IdentityManager) CreateTXTRecord”func (m *IdentityManager) CreateTXTRecord() (*TXTRecord, error)CreateTXTRecord builds and signs this identity’s _dnsid TXT record with the entity key.
func (*IdentityManager) Domain
Section titled “func (*IdentityManager) Domain”func (m *IdentityManager) Domain() stringDomain returns this manager’s local DNSid identity domain, or an empty string when the manager was constructed for verify-only use.
func (*IdentityManager) EntityKeyURL
Section titled “func (*IdentityManager) EntityKeyURL”func (m *IdentityManager) EntityKeyURL() stringEntityKeyURL returns the HTTPS URL where the draft 01 entity (ek) JWKS should be served. It returns an empty string when no entity KeyProvider is configured. Draft 01 defines no default path, so an unset EntityKeyURL returns an empty string.
func (*IdentityManager) EvictDomain
Section titled “func (*IdentityManager) EvictDomain”func (m *IdentityManager) EvictDomain(domain string)EvictDomain removes a domain’s entry from the verified-domain cache so the next VerifyDomain call performs a full re-verification. Domains that fail normalization are ignored.
func (*IdentityManager) GenerateIssuanceEvent
Section titled “func (*IdentityManager) GenerateIssuanceEvent”func (m *IdentityManager) GenerateIssuanceEvent(ctx context.Context) (dnsidlog.LogRef, error)GenerateIssuanceEvent builds a draft 01 ISSUANCE event, signs it with the entity key, countersigns it with the operational key, and writes it locally.
func (*IdentityManager) GetEntityKeySet
Section titled “func (*IdentityManager) GetEntityKeySet”func (m *IdentityManager) GetEntityKeySet() *JWKSGetEntityKeySet returns the current active entity (ek) public signing key for publication. Draft 01 live endpoints expose exactly one current key. It returns nil when no entity KeyProvider is configured.
func (*IdentityManager) GetKeySet
Section titled “func (*IdentityManager) GetKeySet”func (m *IdentityManager) GetKeySet() *JWKSGetKeySet returns the current active operational (ku) public signing key for publication. Draft 01 live endpoints expose exactly one current key.
func (*IdentityManager) KeyProvider
Section titled “func (*IdentityManager) KeyProvider”func (m *IdentityManager) KeyProvider() KeyProviderKeyProvider returns this manager’s local signing key provider, or nil for verify-only managers.
func (*IdentityManager) LoadDomainLog
Section titled “func (*IdentityManager) LoadDomainLog”func (m *IdentityManager) LoadDomainLog(ctx context.Context, vd *VerifiedDomain) (*dnsidlog.DomainLog, error)LoadDomainLog rebuilds the verified lifecycle event history for a verified domain through the log reader bound during verification. It returns a *VerificationError with VerificationCodeLogError when vd carries no log reader or history reconstruction fails.
func (*IdentityManager) OperationalKeyURL
Section titled “func (*IdentityManager) OperationalKeyURL”func (m *IdentityManager) OperationalKeyURL() stringOperationalKeyURL returns the HTTPS URL where the operational (ku) JWKS should be served. This is the ku= value that CreateTXTRecord would produce. Draft 01 defines no default path, so an unset KeyURL returns an empty string.
func (*IdentityManager) PublishClientControlledRecord
Section titled “func (*IdentityManager) PublishClientControlledRecord”func (m *IdentityManager) PublishClientControlledRecord(ctx context.Context, client RegistryClientControlledPublisher) (*PublishedRecord, error)PublishClientControlledRecord signs registry-prepared canonical TXT content when the client controls the accountable-entity key.
func (*IdentityManager) RevokeViaRegistry
Section titled “func (*IdentityManager) RevokeViaRegistry”func (m *IdentityManager) RevokeViaRegistry(ctx context.Context, client RegistryRevoker, agentID string, reason RegistryRevocationReason) (*LifecycleResponse, error)RevokeViaRegistry asks the registry to revoke the immutable managed identity at the local domain and evicts the local verified-domain cache. The registry owns lifecycle persistence and the transparency-log append; this method never appends a second local event.
func (*IdentityManager) SignAndWriteEvent
Section titled “func (*IdentityManager) SignAndWriteEvent”func (m *IdentityManager) SignAndWriteEvent(ctx context.Context, event dnsidlog.LogEvent) (dnsidlog.LogRef, error)SignAndWriteEvent adds every signature the event’s type requires that is not already present — using the entity key for entity signatures and the operational key otherwise — and writes the event to the local log. Roles whose key provider is not configured are skipped, in which case WriteSignedEvent rejects the still-unsigned event. A zero Timestamp is set to the current time truncated to seconds.
func (*IdentityManager) SignLogEvent
Section titled “func (*IdentityManager) SignLogEvent”func (m *IdentityManager) SignLogEvent(event dnsidlog.LogEvent, role LogSignerRole) (dnsidlog.LogEvent, error)SignLogEvent adds one lifecycle signature without writing the event. This supports split signing where the accountable entity and operational key are held by different SDK instances or machines.
func (*IdentityManager) VerifyDomain
Section titled “func (*IdentityManager) VerifyDomain”func (m *IdentityManager) VerifyDomain(ctx context.Context, domain string) (*VerifiedDomain, error)VerifyDomain performs core DNSid trust establishment for a peer domain: it resolves the domain’s _dnsid TXT record, verifies the record signature against the entity (ek) JWKS, fetches the runtime (ku) JWKS, checks lifecycle evidence through the log bound by lr=, and requires the su= status endpoint to report ACTIVE. Records with fl=logchk expose that policy through VerifiedDomain.RequiresLogCheck; callers decide which operations require fresh evidence through VerifyLogEvidence. Results are served from the manager’s cache until they expire.
The default DNSSECModeAuto accepts the built-in resolver’s UNKNOWN DNSSEC state; stricter DNSSECModeValidated and DNSSECModeRequired deployments need a DNSSEC-aware resolver injected via WithDNSResolver. Failures are reported as *VerificationError; check Code and Transient to classify them. It is shorthand for VerifyDomainWithOptions with zero options.
Example
ExampleIdentityManager_VerifyDomain verifies a DNSid domain end to end against in-memory fixtures: a signed _dnsid TXT record, the entity (ek) and runtime (ku) JWKS documents, and an ACTIVE status document. Against live infrastructure only the fakes change — construct the manager with a DNSSEC-aware resolver and omit WithHTTPSFetcher.
package main
import ( "context" "crypto/tls" "encoding/json" "fmt" "log" "time"
dnsid "github.com/dnsid-ai/dnsid-go" dnsidlog "github.com/dnsid-ai/dnsid-go/log")
// exampleDNSResolver serves fixed TXT answers in place of live DNS. VerifyDomain// requires an injected resolver that reports a definitive DNSSEC state; a// production deployment supplies a DNSSEC-aware resolver via dnsid.WithDNSResolver.type exampleDNSResolver map[string][]dnsid.TXTRecordRData
func (r exampleDNSResolver) FetchTXT(_ context.Context, name string) ([]dnsid.TXTRecordRData, dnsid.DNSSECState, error) { return r[name], dnsid.DNSSECStateUnsigned, nil}
// exampleHTTPSFetcher serves fixed JSON documents in place of live HTTPS// fetches of the JWKS and status endpoints.type exampleHTTPSFetcher map[string]json.RawMessage
func (f exampleHTTPSFetcher) FetchJSON(_ context.Context, rawURL string, _ dnsid.FetchOptions) (json.RawMessage, *tls.Certificate, error) { body, ok := f[rawURL] if !ok { return nil, nil, fmt.Errorf("no fixture for %s", rawURL) } return body, nil, nil}
// exampleLogReader accepts the lifecycle evidence checks that a real// transparency-log binding would verify cryptographically.type exampleLogReader struct{ dnsidlog.NoopLogReader }
func (exampleLogReader) VerifyBilateralBinding(context.Context, dnsidlog.BilateralBindingInput) (dnsidlog.BilateralBinding, error) { return dnsidlog.BilateralBinding{InitialOperationalThumbprint: "example"}, nil}
func (exampleLogReader) VerifyOperationalContinuity(context.Context, string, string, string) error { return nil}
// ExampleIdentityManager_VerifyDomain verifies a DNSid domain end to end// against in-memory fixtures: a signed _dnsid TXT record, the entity (ek) and// runtime (ku) JWKS documents, and an ACTIVE status document. Against live// infrastructure only the fakes change — construct the manager with a// DNSSEC-aware resolver and omit WithHTTPSFetcher.func main() { // The agent being verified. Its entity key signs the _dnsid record; its // operational key is the runtime key the agent signs with. entityKey := dnsid.GenerateES256KeyProvider() operationalKey := dnsid.GenerateEd25519KeyProvider() publisher, err := dnsid.NewIdentityManager(dnsid.Config{Identity: &dnsid.IdentityConfig{ Domain: "agent.example", GovernanceID: "agent.example", LogRef: "example-log:1", StatusURL: "https://agent.example/dnsid-status.json", KeyURL: "https://agent.example/jwks.json", EntityKeyURL: "https://agent.example/entity-jwks.json", }}, operationalKey, dnsid.WithEntityKeyProvider(entityKey)) if err != nil { log.Fatal(err) } record, err := publisher.CreateTXTRecord() if err != nil { log.Fatal(err) } ekJSON, _ := json.Marshal(publisher.GetEntityKeySet().Raw()) kuJSON, _ := json.Marshal(publisher.GetKeySet().Raw()) statusJSON := `{"state":"ACTIVE","lastTransitionAt":"` + time.Now().UTC().Format(time.RFC3339) + `"}`
// The verifier resolves the record, checks the record signature against // the ek JWKS, loads the ku JWKS, consults the lifecycle log, and // requires an ACTIVE status. registry := dnsidlog.NewLogRegistry() if err := registry.Register("example-log", func(string) dnsidlog.LogReader { return exampleLogReader{} }); err != nil { log.Fatal(err) } verifier, err := dnsid.NewIdentityManager(dnsid.Config{}, nil, dnsid.WithDNSResolver(exampleDNSResolver{ "_dnsid.agent.example": {{Value: record.Serialize(), TTL: time.Minute}}, }), dnsid.WithHTTPSFetcher(exampleHTTPSFetcher{ record.EntityKeyURI: ekJSON, record.KeyURI: kuJSON, record.StatusURI: json.RawMessage(statusJSON), }), dnsid.WithLogRegistry(registry), ) if err != nil { log.Fatal(err) }
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() verified, err := verifier.VerifyDomain(ctx, "agent.example") if err != nil { log.Fatal(err) } fmt.Println("domain:", verified.Domain()) fmt.Println("governance:", verified.Record().GovernanceID) fmt.Println("status:", verified.Status().State)}Output
Section titled “Output”domain: agent.examplegovernance: agent.examplestatus: ACTIVEfunc (*IdentityManager) VerifyDomainWithOptions
Section titled “func (*IdentityManager) VerifyDomainWithOptions”func (m *IdentityManager) VerifyDomainWithOptions(ctx context.Context, domain string, opts VerifyDomainOpts) (*VerifiedDomain, error)VerifyDomainWithOptions performs core DNSid trust establishment with optional peer inputs, then enforces any configured VerificationConfig.TrustedEntities acceptance policy. Acceptance runs on every successful path, including cache hits; verified protocol evidence is cached before acceptance, and denials are never cached. A denial is reported as a permanent VerificationCodeCounterpartyNotAccepted error.
func (*IdentityManager) VerifyLogEvidence
Section titled “func (*IdentityManager) VerifyLogEvidence”func (m *IdentityManager) VerifyLogEvidence(ctx context.Context, vd *VerifiedDomain, at time.Time) (dnsidlog.LoggedStateEvidence, error)VerifyLogEvidence performs an operation-time complete-history and non-revocation check for vd. A zero at value uses the current time.
func (*IdentityManager) WriteSignedEvent
Section titled “func (*IdentityManager) WriteSignedEvent”func (m *IdentityManager) WriteSignedEvent(ctx context.Context, event dnsidlog.LogEvent) (dnsidlog.LogRef, error)WriteSignedEvent writes an event without adding or replacing signatures. It rejects events missing signatures required by the shared lifecycle role model. Log bindings perform method-specific cryptographic validation.
IdentityManagerOption configures IdentityManager.
type IdentityManagerOption func(*IdentityManager)func WithDNSResolver(r DNSResolver) IdentityManagerOptionWithDNSResolver overrides the built-in resolver. Resolvers used with DNSSECModeValidated or DNSSECModeRequired must report definitive DNSSEC states rather than DNSSECStateUnknown.
func WithEntityKeyProvider(kp KeyProvider) IdentityManagerOptionWithEntityKeyProvider configures the accountable-entity key used to sign identity records and lifecycle events. Verification-only managers do not need an entity key provider.
func WithHTTPClient(client *http.Client) IdentityManagerOptionWithHTTPClient bases SDK-managed HTTPS fetches on client, preserving its TLS and timeout configuration while wrapping its transport with the SDK’s SSRF-safe, DNS-rebinding-resistant dialer. The client is caller-owned transport: Config.Transport does not apply to it.
func WithHTTPSFetcher(f HTTPSFetcher) IdentityManagerOptionWithHTTPSFetcher replaces the SDK-managed HTTPS JSON fetcher. The supplied fetcher becomes responsible for the transport-level protections the default provides (HTTPS-only URLs, host allow-listing, SSRF-safe dialing, and response size limits) and must be safe for concurrent use. Config.Transport does not apply to an injected fetcher.
func WithIdentityCache(cache *IdentityCache) IdentityManagerOptionWithIdentityCache shares a bounded storage backend, not verification results. Each manager uses a private namespace even when the backend is injected. The supplied cache is retained by the manager and must not be nil.
func WithLogRegistry(r *dnsidlog.LogRegistry) IdentityManagerOptionWithLogRegistry supplies the registry that maps lifecycle-log methods (the scheme of a record’s lr= reference) to LogReader implementations. Without a registry, or for unregistered methods, lifecycle evidence checks fail with VerificationCodeLogError.
IdentityResolver verifies DNSid identity for peer domains.
type IdentityResolver interface { VerifyDomain(ctx context.Context, domain string) (*VerifiedDomain, error)}RedirectPolicy controls HTTPS redirect handling for SDK-managed fetches.
type RedirectPolicy stringRedirectPolicy values. RedirectPolicyNone (the zero-value default) does not follow redirects; RedirectPolicySameHost follows HTTPS redirects that stay on the allowed host; RedirectPolicyHTTPS follows any HTTPS redirect.
const ( RedirectPolicyNone RedirectPolicy = "none" RedirectPolicySameHost RedirectPolicy = "sameHost" RedirectPolicyHTTPS RedirectPolicy = "https")RegistryConfig contains DNSid registry control-plane settings.
type RegistryConfig struct { RegistryURL string}SDKConformanceMetadata describes the exact protocol behavior and log-binding revisions implemented by this SDK release.
type SDKConformanceMetadata struct { PublishProfile string `json:"publishProfile"` VerificationProfiles map[string]string `json:"verificationProfiles"` SpecificationStatus string `json:"specificationStatus"` LogBindings map[string]string `json:"logBindings"` KnownDeviations []string `json:"knownDeviations"`}func SDKConformance() SDKConformanceMetadataSDKConformance returns an immutable snapshot of this release’s protocol conformance metadata. Callers may mutate the returned maps and slice without changing future snapshots.
TransportConfig contains deployment controls for SDK-managed DNS and HTTPS: a custom DNS server for TXT lookups and HTTPS name resolution, and an additional CA bundle for HTTPS trust. Settings apply only to the default implementations; injected resolvers and fetchers are never inspected or modified. Setting a DNS server routes lookups through the stdlib resolver, which performs no DNSSEC validation.
SDK-managed HTTPS refuses to dial loopback, private, link-local, multicast, reserved, and other non-routable addresses. PrivateAddressHosts is the only exemption: entries are hostnames (“agent.test”, exact match) or leading-dot suffixes (“.test”, matching “test” and every name beneath it on a DNS-label boundary). A matching destination may resolve to loopback or private-use (RFC 1918, RFC 4193) addresses; link-local, multicast, reserved, and mixed public+private resolutions are still rejected, IP-literal URLs are never exempted, and every redirect hop is matched independently. The list is empty by default and there is no built-in exemption for .test or any other name; a local `dnsid` stack needs PrivateAddressHosts: []string{“.test”} (or DNSID_PRIVATE_HOSTS=.test via config.LoadEnvironment). Entries with an IP literal, port, scheme, path, or credentials are rejected at construction.
type TransportConfig struct { DNSServer string CABundlePath string PrivateAddressHosts []string}func (TransportConfig) IsZero
Section titled “func (TransportConfig) IsZero”func (c TransportConfig) IsZero() boolIsZero reports whether no transport setting is configured.
TrustedEntity is one counterparty allowlist entry. GovernanceID must match the verified record’s gi= exactly after FQDN normalization. When EntityKeyThumbprints is non-empty, the verified current record-signing key’s RFC 7638 SHA-256 thumbprint must also equal one of the pins.
type TrustedEntity struct { GovernanceID string EntityKeyThumbprints []string}VerificationConfig contains protocol verification policy and counterparty acceptance settings. The zero value is spec-strict: status is re-fetched on every invocation, DNSSECModeAuto applies, and no acceptance decision is made.
type VerificationConfig struct { // StatusCheckInterval is the maximum age of a cached status result before // VerifyDomain re-fetches su= on a cache hit. Zero re-fetches every time. StatusCheckInterval time.Duration DNSSECMode DNSSECMode // TrustedEntities is an optional counterparty allowlist. nil makes no // acceptance decision; an empty non-nil slice denies every counterparty. TrustedEntities []TrustedEntity}VerifiedDomain is the result of successful DNSid domain verification.
type VerifiedDomain struct { // contains filtered or unexported fields}func VerifyIdentity(ctx context.Context, resolver IdentityResolver, domain string, opts VerifyDomainOpts) (*VerifiedDomain, error)VerifyIdentity resolves an application signer with trusted current-peer evidence. Resolvers without the options API cannot authenticate an mtls identity.
func (*VerifiedDomain) CachedState
Section titled “func (*VerifiedDomain) CachedState”func (v *VerifiedDomain) CachedState() stringCachedState reports how this result was produced: “fresh” for a full verification, “cached” for a cache hit, and “refreshed” for a cache hit whose status was re-fetched. It returns an empty string on a nil receiver.
func (*VerifiedDomain) DNSSECState
Section titled “func (*VerifiedDomain) DNSSECState”func (v *VerifiedDomain) DNSSECState() DNSSECStateDNSSECState returns the resolver’s DNSSEC validation result for the _dnsid lookup. It returns DNSSECStateUnknown on a nil receiver.
func (*VerifiedDomain) DNSTTL
Section titled “func (*VerifiedDomain) DNSTTL”func (v *VerifiedDomain) DNSTTL() time.DurationDNSTTL returns the TTL of the _dnsid TXT record as reported by the resolver, or 0 on a nil receiver.
func (*VerifiedDomain) Domain
Section titled “func (*VerifiedDomain) Domain”func (v *VerifiedDomain) Domain() stringDomain returns the verified identity domain in normalized FQDN form. It returns an empty string on a nil receiver.
func (*VerifiedDomain) Expiry
Section titled “func (*VerifiedDomain) Expiry”func (v *VerifiedDomain) Expiry() time.TimeExpiry returns the earliest instant at which this verification result should no longer be trusted: the minimum of the DNS TTL, the ka= key-age deadline, and the runtime and record-signing TLS certificate expiries. It returns the zero time when no bound applies or on a nil receiver.
func (*VerifiedDomain) JWKSCertificate
Section titled “func (*VerifiedDomain) JWKSCertificate”func (v *VerifiedDomain) JWKSCertificate() *tls.CertificateJWKSCertificate returns a copy of the TLS certificate presented by the runtime (ku) JWKS endpoint, or nil when unavailable.
func (*VerifiedDomain) JWKSLeafCertificate
Section titled “func (*VerifiedDomain) JWKSLeafCertificate”func (v *VerifiedDomain) JWKSLeafCertificate() *x509.CertificateJWKSLeafCertificate returns a copy of the leaf certificate presented by the runtime (ku) JWKS endpoint, or nil when unavailable.
func (*VerifiedDomain) KeyBoundAt
Section titled “func (*VerifiedDomain) KeyBoundAt”func (v *VerifiedDomain) KeyBoundAt() time.TimeKeyBoundAt returns when the operational key was introduced according to the lifecycle log. It is set only when the record carries a ka= key-age policy; otherwise, and on a nil receiver, it returns the zero time.
func (*VerifiedDomain) KeySet
Section titled “func (*VerifiedDomain) KeySet”func (v *VerifiedDomain) KeySet() *JWKSKeySet returns a deep copy of the agent runtime (ku) JWKS — the key set the agent signs with at runtime — or nil on a nil receiver.
func (*VerifiedDomain) LastStatusCheckAt
Section titled “func (*VerifiedDomain) LastStatusCheckAt”func (v *VerifiedDomain) LastStatusCheckAt() time.TimeLastStatusCheckAt returns when the agent status was last fetched, which may be later than VerifiedAt for entries refreshed from the cache. It returns the zero time on a nil receiver.
func (*VerifiedDomain) LogReader
Section titled “func (*VerifiedDomain) LogReader”func (v *VerifiedDomain) LogReader() dnsidlog.LogReaderLogReader returns the lifecycle log reader bound to the record’s lr= reference during verification, or nil on a nil receiver.
func (*VerifiedDomain) Record
Section titled “func (*VerifiedDomain) Record”func (v *VerifiedDomain) Record() *TXTRecordRecord returns a deep copy of the verified _dnsid TXT record, or nil on a nil receiver. Mutating the returned record does not affect the cached entry.
func (*VerifiedDomain) RecordSigningKeySet
Section titled “func (*VerifiedDomain) RecordSigningKeySet”func (v *VerifiedDomain) RecordSigningKeySet() *JWKSRecordSigningKeySet returns a deep copy of the accountable-entity (ek) JWKS that verified the record signature, or nil on a nil receiver.
func (*VerifiedDomain) RequiresLogCheck
Section titled “func (*VerifiedDomain) RequiresLogCheck”func (v *VerifiedDomain) RequiresLogCheck() boolRequiresLogCheck reports whether the verified record carries the logchk policy signal. Applications decide which operations require fresh evidence.
func (*VerifiedDomain) SigningKey
Section titled “func (*VerifiedDomain) SigningKey”func (v *VerifiedDomain) SigningKey() *JWKSigningKey returns a deep copy of the entity key that produced the record’s sg= signature, or nil on a nil receiver.
func (*VerifiedDomain) Status
Section titled “func (*VerifiedDomain) Status”func (v *VerifiedDomain) Status() *AgentStatusStatus returns a copy of the agent status document fetched from the su= endpoint, or nil on a nil receiver. Verification only succeeds for ACTIVE agents, so the returned status always reports State “ACTIVE”.
func (*VerifiedDomain) StatusCertificate
Section titled “func (*VerifiedDomain) StatusCertificate”func (v *VerifiedDomain) StatusCertificate() *tls.CertificateStatusCertificate returns a copy of the TLS certificate presented by the status (su) endpoint, or nil when unavailable.
func (*VerifiedDomain) StatusLeafCertificate
Section titled “func (*VerifiedDomain) StatusLeafCertificate”func (v *VerifiedDomain) StatusLeafCertificate() *x509.CertificateStatusLeafCertificate returns a copy of the leaf certificate presented by the status (su) endpoint, or nil when unavailable.
func (*VerifiedDomain) VerifiedAt
Section titled “func (*VerifiedDomain) VerifiedAt”func (v *VerifiedDomain) VerifiedAt() time.TimeVerifiedAt returns when full verification completed. It returns the zero time on a nil receiver.
func (*VerifiedDomain) VerifyLogEvidence
Section titled “func (*VerifiedDomain) VerifyLogEvidence”func (v *VerifiedDomain) VerifyLogEvidence(ctx context.Context, at time.Time) (evidence dnsidlog.LoggedStateEvidence, err error)VerifyLogEvidence performs an operation-time complete-history and non-revocation check through the log reader bound during domain verification. A zero at value uses the current time.
VerifyDomainOpts contains optional inputs for core domain verification.
type VerifyDomainOpts struct { // PeerCertificate is the TLS client certificate leaf for records with fl=mtls. // Deprecated: set VerifiedPeerCertificateChains from an already-verified // TLS connection state instead. A leaf certificate alone is not accepted for // fl=mtls because hostname-only checks do not establish mTLS trust. PeerCertificate *x509.Certificate
// VerifiedPeerCertificateChains are the peer certificate chains that the // caller's TLS stack has already authenticated for an mTLS connection, such // as tls.ConnectionState.VerifiedChains from a request with client cert auth. // At least one verified chain with a leaf certificate valid for the DNSid // domain is required when the peer record has fl=mtls. VerifiedPeerCertificateChains [][]*x509.Certificate}