dnsid

package module
v0.37.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2026 License: Apache-2.0 Imports: 43 Imported by: 1

README

dnsid-go

The Go SDK for DNSid — verify who an agent is, who governs it, and whether it's still live, straight from DNS.

DNSid binds an agent to a domain: a signed _dnsid TXT record names the agent's governing organization (gi), accountable-entity record-signing key set (ek), and agent runtime key set (ku); a status endpoint reports whether the agent is ACTIVE or REVOKED. This SDK resolves and verifies that chain, and signs on the agent's behalf — DNSid JWTs (JOSE profile), OIDC tokens, and Web Bot Auth HTTP Message Signatures (RFC 9421).

Install

go get github.com/dnsid-ai/dnsid-go

Requires Go 1.26.6 or newer (matches the go directive in go.mod). See Compatibility.

Verify a domain

package main

import (
	"context"
	"fmt"
	"time"

	dnsid "github.com/dnsid-ai/dnsid-go"
	"github.com/dnsid-ai/dnsid-go/config"
)

func main() {
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()

	// Set DNSID_LOG_TRUST_PROFILE_FILE to an independently trusted profile first.
	idm, err := config.IdentityManagerFromEnvironment(ctx, nil, dnsid.Config{}, config.Dependencies{})
	if err != nil {
		panic(err)
	}

	verified, err := idm.VerifyDomain(ctx, "your-agent.example")
	if err != nil {
		panic(err)
	}

	fmt.Println("domain:", verified.Domain())
	fmt.Println("governance:", verified.Record().GovernanceID)
	fmt.Println("status:", verified.Status().State)
}

Replace the placeholder your-agent.example with a published DNSid-enabled domain. VerifyDomain resolves its _dnsid record, verifies the record-signing and runtime JWKS selected by its profile, and queries the status endpoint—all over SSRF-safe, DNS-rebinding-resistant transport. The default auto DNSSEC policy accepts the built-in resolver's UNKNOWN validation state, while still rejecting a resolver-reported FAILED state. Applications that require a definitive validation result must inject a DNSSEC-aware resolver and select validated or required mode.

TXT record versions

The _dnsid record's v tag selects its signed behavior profile; it is not the SDK release version. This SDK:

  • publishes new records with v=dnsid-draft-01
  • verifies both v=dnsid-draft-01 and v=DNSid1
  • preserves the exact parsed v value when canonicalizing and verifying a signature
  • rejects dated draft identifiers, legacy aliases, and unknown future selectors

While DNSid version 1 remains an Internet-Draft, dnsid-draft-01 is the immutable submitted-draft selector and the only publishable profile. Pre-RFC DNSid1 is verification-only and selects the latest submitted draft fully supported by that SDK release; it must not be rewritten to the numbered selector because v is part of the signed content. When version 1 becomes an RFC, DNSid1 freezes to that RFC behavior and becomes the version 1 publish selector.

In Go, dnsid.DefaultPublishProfile reports the current publish selector. dnsid.Version reports the Go module release; the two versions are intentionally separate.

Packages

Import What it does
github.com/dnsid-ai/dnsid-go Core SDK: IdentityManager, domain verification, TXT record parse/create, JWKS/JWK, key providers, typed errors.
.../dnsid-go/jose DNSid JOSE profile — create and verify DNSid JWTs and compact JWS.
.../dnsid-go/oidc Mint and verify DNSid OIDC tokens.
.../dnsid-go/httpsig · .../webbotauth RFC 9421 HTTP Message Signatures and the Web Bot Auth profile.

Next steps

  • QUICKSTART.md — sign as an agent, mint a JWT, and sign an HTTP request.
  • examples/ — runnable programs for domain verification, key rotation, and Web Bot Auth.
  • docs.dnsid.ai — protocol docs and account setup.

Compatibility

Supported
Go 1.26.6 (minimum, per go.mod) through the latest stable release. CI tests 1.26.6 and stable.
Platforms linux/amd64 tested in CI; linux/arm64, darwin, and windows/amd64 supported (pure Go, no platform-specific code).
Crypto/cgo Pure Go, builds with CGO_ENABLED=0. Standard-library crypto; FIPS via Go's native FIPS mode.
DNSSEC auto works with the built-in resolver and rejects known validation failures. validated and required need a DNSSEC-aware resolver supplied via WithDNSResolver.

Full details, including tested dependency versions and enterprise deployment notes, are in COMPATIBILITY.md. Production runtime behavior, key rotation, revocation, transport, cache, and error guidance are in OPERATIONS.md.

Security & trust

Official sources. Source: github.com/dnsid-ai/dnsid-go. Package: github.com/dnsid-ai/dnsid-go on the Go module proxy (pkg.go.dev/github.com/dnsid-ai/dnsid-go). Releases: GitHub Releases on this repository, each with a CycloneDX SBOM attached. Forks, mirrors, and similarly named packages are not maintained by us. Report vulnerabilities per SECURITY.md; never in a public issue.

Software is not identity. This SDK ships no private keys or credentials; its optional embedded log trust profiles do not grant an identity. A DNSid identity is proven by control of a DNS zone, an agent private key, and the registry's published status. Possessing, forking, or modifying this code grants none of those: an unofficial build cannot mint or inherit anyone's identity.

What it does on the network. Only when you call it, and only to hosts you or the domain being verified chose:

  • DNS TXT lookup of _dnsid.<domain> through your system resolver (no hardcoded resolver)
  • HTTPS GET to the JWKS and status URLs published in that TXT record
  • Opt-in only, never contacted unless you configure them: https://log.dnsid.ai / log.dev.dnsid.ai (C2SP transparency log via log/c2sptlog, bundled public trust roots), cloud KMS endpoints via key/aws
  • No telemetry, usage reporting, update checks, or crash reporting

Logging. The SDK has no logger; errors are returned to the caller. It warns on stderr if a custom HTTP transport cannot be safely preserved.

Hosted endpoints. api.dnsid.ai and log.dnsid.ai are operated separately from this SDK under their own terms. Nothing in this repository is an availability, uptime, or support commitment for them.

For your privacy notice. Using this SDK causes your system to make DNS and HTTPS requests to the domains you verify and to the JWKS/status hosts they publish. It sends them nothing about your users. If you enable the registry or transparency-log clients, requests also go to DNSid-operated endpoints; disclose that where your notice requires it.

License

Licensed under the Apache License 2.0.

Documentation

Overview

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

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

  • 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

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.

Index

Examples

Constants

View Source
const (
	AgentStatePending      = dnsidlog.AgentStatePending
	AgentStateProvisioning = dnsidlog.AgentStateProvisioning
	AgentStateVerifying    = dnsidlog.AgentStateVerifying
	AgentStateActive       = dnsidlog.AgentStateActive
	AgentStateRetired      = dnsidlog.AgentStateRetired
	AgentStateRevoked      = dnsidlog.AgentStateRevoked
)

Typed lifecycle constants for callers that want the AgentState type.

View Source
const (
	RegistryStatusReady     = "READY"
	RegistryStatusCancelled = "CANCELLED"
	RegistryStatusRejected  = "REJECTED"
	RegistryStatusError     = "ERROR"
	RegistryStatusFailed    = "FAILED"
)

Registry workflow statuses reported by the registry API, alongside the AgentState* lifecycle states. READY ends a registration workflow successfully; the others are terminal failures.

View Source
const DefaultPublishProfile = identityRecordDraft01

DefaultPublishProfile is the current _dnsid TXT behavior profile emitted by this SDK. It is distinct from Version, which reports the SDK/module release.

View Source
const DefaultRegistryURL = "http://127.0.0.1:7755"

DefaultRegistryURL 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).

View Source
const DefaultVerificationTimeout = 30 * time.Second

DefaultVerificationTimeout bounds a complete verification when no caller deadline is supplied.

Variables

View Source
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 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.

View Source
var (
	ErrOwnerSignatureMalformed     = errors.New("dnsid: signature verification failed")
	ErrOwnerSignatureInvalidJWKS   = errors.New("dnsid: signature verification failed")
	ErrOwnerSignatureNoMatchingKey = errors.New("dnsid: signature verification failed")
)

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.

View Source
var ErrKeyStoreDurability = errors.New("dnsid: key store published but durability uncertain")

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.

View Source
var ValidKeyAgeValues = map[string]bool{
	"24h": true,
	"7d":  true,
	"30d": true,
	"90d": true,
}

ValidKeyAgeValues is the enumerated set of valid ka= values.

View Source
var Version = resolveVersion()

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".

Functions

func CreateDnsidHTTPClient

func CreateDnsidHTTPClient(transportConfig TransportConfig) (*http.Client, error)

CreateDnsidHTTPClient creates an SDK-managed HTTP client using DNSid transport settings.

func MissingRequiredField

func MissingRequiredField(rec *TXTRecord) string

MissingRequiredField returns the first missing required non-signature DNSid TXT tag name, or "" if the unsigned record has all required signing inputs.

func NormalizeFQDN

func NormalizeFQDN(input string) (string, error)

NormalizeFQDN returns the canonical form of the given DNS name:

  1. Map IDNA dot-equivalent runes and strip a single trailing dot.
  2. Apply IDNA A-label encoding (Unicode -> punycode where needed).
  3. Lowercase all ASCII letters.
  4. Validate label-length limits (<=63 octets per label).
  5. 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 ParseJWKSet

func ParseJWKSet(data []byte) (jwk.Set, error)

ParseJWKSet parses a JWKS JSON document and returns a validated raw JWK set.

func ParseLogRef

func ParseLogRef(lr string) (method, entryRef string, err error)

ParseLogRef splits an lr= log reference of the form "method:entryRef" into its method and entry-reference parts. It returns a *ParseError for malformed references or invalid method names.

func RegistrantDomain

func RegistrantDomain(domain string) string

RegistrantDomain 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

func SafeDialerTransport() *http.Transport

SafeDialerTransport returns an HTTP transport that resolves a hostname once, validates every returned IP address, and dials a concrete validated IP.

func SignLogEventWithKey

func SignLogEventWithKey(event dnsidlog.LogEvent, role LogSignerRole, kp KeyProvider, canonicalizer LogEventCanonicalizer) (dnsidlog.LogEvent, error)

SignLogEventWithKey adds one lifecycle signature using an explicitly supplied key provider and bound log canonicalizer. It is suitable for accountable entity services that do not possess the operational private key.

func Tags

func Tags(rec *TXTRecord) map[string]string

Tags returns the record's tag-value pairs as a map, excluding empty optional fields. It always emits the current wire tag names.

func VerificationContext

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.

Types

type AgentDetail

type AgentDetail struct {
	ID                      string            `json:"id"`
	Domain                  string            `json:"domain"`
	DomainDisplay           string            `json:"domain_display"`
	Name                    string            `json:"name,omitempty"`
	Environment             string            `json:"environment"`
	Status                  string            `json:"status"`
	StatusURL               string            `json:"status_url"`
	Managed                 string            `json:"managed"`
	ProtocolStatus          *AgentStatus      `json:"protocolStatus,omitempty"`
	ServerStatus            string            `json:"serverStatus,omitempty"`
	DNSPublished            bool              `json:"dns_published"`
	DNSPublishedAt          *time.Time        `json:"dns_published_at,omitempty"`
	Challenge               string            `json:"challenge,omitempty"`
	ChallengeExpiresAt      *time.Time        `json:"challenge_expires_at,omitempty"`
	ChainRecordStatus       string            `json:"chain_record_status,omitempty"`
	TransactionID           string            `json:"transaction_id,omitempty"`
	RevocationReason        string            `json:"revocation_reason,omitempty"`
	RevokedAt               *time.Time        `json:"revoked_at,omitempty"`
	IdentityRecordExpiresAt *time.Time        `json:"identity_record_expires_at,omitempty"`
	IdentityRecordExpiring  *bool             `json:"identity_record_expiring,omitempty"`
	Error                   *AgentError       `json:"error,omitempty"`
	PublicationConfig       PublicationConfig `json:"publication_config"`
	CreatedAt               time.Time         `json:"created_at"`
	UpdatedAt               time.Time         `json:"updated_at"`
}

AgentDetail matches the OpenAPI AgentDetail schema.

func WaitForRegistryStatus

func WaitForRegistryStatus(ctx context.Context, client RegistryStatusReader, fqdn string, targetStatuses []string, opts *WaitForStatusOptions) (*AgentDetail, error)

WaitForRegistryStatus polls client until the agent at fqdn reaches one of targetStatuses (compared case-insensitively) and returns that AgentDetail. It returns an error when a terminal registry status is reached first, when polling fails, or when ctx (bounded by opts.Timeout, if set) is done. A nil opts polls every second with no timeout beyond ctx's own.

type AgentError

type AgentError struct {
	Code        string `json:"code"`
	Title       string `json:"title"`
	Detail      string `json:"detail"`
	Remediation string `json:"remediation"`
}

AgentError matches the OpenAPI AgentError schema.

type AgentEvent

type AgentEvent struct {
	ID        string         `json:"id"`
	AgentID   string         `json:"agent_id"`
	EventType string         `json:"event_type"`
	CreatedAt time.Time      `json:"created_at"`
	ActorID   *string        `json:"actor_id,omitempty"`
	Details   map[string]any `json:"details,omitempty"`
}

AgentEvent matches the OpenAPI AgentEvent schema.

type AgentListItem

type AgentListItem struct {
	ID            string    `json:"id"`
	Domain        string    `json:"domain"`
	DomainDisplay string    `json:"domain_display"`
	Environment   string    `json:"environment"`
	Status        string    `json:"status"`
	CreatedAt     time.Time `json:"created_at"`
	UpdatedAt     time.Time `json:"updated_at"`
}

AgentListItem matches the OpenAPI Agent schema.

type AgentListResponse

type AgentListResponse struct {
	Agents     []AgentListItem `json:"agents"`
	NextCursor string          `json:"next_cursor,omitempty"`
}

AgentListResponse matches the OpenAPI AgentListResponse schema.

type AgentRegistration

type AgentRegistration struct {
	Domain               string               `json:"domain"`
	PublicationAuthority PublicationAuthority `json:"publicationAuthority"`
	RegistryStatus       string               `json:"registryStatus"`
	DNSPublished         bool                 `json:"dnsPublished,omitempty"`
	ProtocolStatus       *AgentStatus         `json:"protocolStatus,omitempty"`
	// OIDCIssuerURL is the exact issuer returned by the registry at creation.
	OIDCIssuerURL string          `json:"oidcIssuerUrl,omitempty"`
	RegistryURL   string          `json:"registryUrl"`
	Raw           json.RawMessage `json:"raw,omitempty"`
}

AgentRegistration is normalized registry workflow state for a local identity.

type AgentRegistrationInput

type AgentRegistrationInput struct {
	Domain       string         `json:"domain"`
	Metadata     map[string]any `json:"metadata,omitempty"`
	PublicKeyJWK any            `json:"publicKeyJwk,omitempty"`
	Environment  string         `json:"environment,omitempty"`
	Managed      bool           `json:"managed,omitempty"`
}

AgentRegistrationInput is input for registering a local identity with a registry.

type AgentState

type AgentState = dnsidlog.AgentState

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.

func AgentStates

func AgentStates() []AgentState

AgentStates returns a copy of the six canonical lifecycle states in order.

func ParseAgentState

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.

type AgentStatus

type AgentStatus struct {
	State            AgentState `json:"state"`
	LastTransitionAt time.Time  `json:"lastTransitionAt"`
	RevocationReason string     `json:"revocationReason,omitempty"`
}

AgentStatus is the protocol status document fetched from su=.

func (*AgentStatus) Validate

func (s *AgentStatus) Validate() error

Validate 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.

type ArgumentError

type ArgumentError = sdkerrors.ArgumentError

ArgumentError is the shared SDK ArgumentError category.

func NewArgumentError

func NewArgumentError(msg string, cause error) *ArgumentError

NewArgumentError creates an argument error with an optional underlying cause.

type CanonicalRecordContentResponse

type CanonicalRecordContentResponse struct {
	Canonical  string          `json:"canonical"`
	SigningKid string          `json:"signingKid"`
	Raw        json.RawMessage `json:"raw,omitempty"`
}

CanonicalRecordContentResponse is registry-prepared unsigned canonical TXT content.

type ChallengeRequest

type ChallengeRequest struct {
	Nonce     string `json:"nonce"`
	Signature string `json:"signature"`
}

ChallengeRequest matches the OpenAPI ChallengeRequest schema.

type Config

type Config struct {
	Identity     *IdentityConfig
	Verification VerificationConfig
	Transport    TransportConfig
}

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.

func (Config) Validate added in v0.36.0

func (c Config) Validate() error

Validate checks every section of the configuration without constructing a manager: Identity (when set), Verification, and Transport. It performs no network or file I/O.

type CreateAgentRequest

type CreateAgentRequest struct {
	Domain    string `json:"domain,omitempty"`
	Name      string `json:"name,omitempty"`
	PublicKey any    `json:"public_key"`
	// Optional fields
	Environment     string `json:"environment,omitempty"`
	Managed         bool   `json:"managed,omitempty"`
	ZoneID          string `json:"zone_id,omitempty"`
	CapabilitiesURL string `json:"capabilities_url,omitempty"`
}

CreateAgentRequest matches the OpenAPI CreateAgentRequest schema.

type CreateAgentResponse

type CreateAgentResponse struct {
	ID                string            `json:"id"`
	Domain            string            `json:"domain"`
	DomainDisplay     string            `json:"domain_display"`
	Name              string            `json:"name,omitempty"`
	Status            string            `json:"status"`
	StatusURL         string            `json:"status_url"`
	PublicationConfig PublicationConfig `json:"publication_config"`
	OIDCIssuerURL     string            `json:"oidc_issuer_url,omitempty"`
}

CreateAgentResponse matches the OpenAPI CreateAgentResponse schema.

type DNSRecord

type DNSRecord struct {
	Name  string `json:"name"`
	Type  string `json:"type"`
	Value string `json:"value"`
	TTL   int    `json:"ttl"`
}

DNSRecord matches the OpenAPI DNSRecord schema.

type DNSResolver

type DNSResolver interface {
	FetchTXT(ctx context.Context, name string) ([]TXTRecordRData, DNSSECState, error)
}

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 DNSSECMode

type DNSSECMode string

DNSSECMode describes the caller's DNSSEC verification policy.

const (
	DNSSECModeAuto      DNSSECMode = "auto"
	DNSSECModeValidated DNSSECMode = "validated"
	DNSSECModeRequired  DNSSECMode = "required"
)

DNSSECMode values. DNSSECModeAuto accepts VALID, UNSIGNED, and UNKNOWN resolver states; DNSSECModeValidated rejects UNKNOWN; DNSSECModeRequired accepts only VALID. Every mode rejects FAILED.

type DNSSECState

type DNSSECState string

DNSSECState reports the resolver's DNSSEC validation result.

const (
	DNSSECStateUnknown  DNSSECState = "UNKNOWN"
	DNSSECStateValid    DNSSECState = "VALID"
	DNSSECStateUnsigned DNSSECState = "UNSIGNED"
	DNSSECStateFailed   DNSSECState = "FAILED"
)

DNSSECState 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.

type EventListOptions

type EventListOptions struct {
	Limit  int
	Cursor string
}

EventListOptions contains optional parameters for GetAgentEvents.

type EventListResponse

type EventListResponse struct {
	Events     []AgentEvent `json:"events"`
	NextCursor *string      `json:"next_cursor,omitempty"`
}

EventListResponse matches the OpenAPI EventListResponse schema.

type FetchOptions

type FetchOptions struct {
	AllowedHost      string
	DomainBoundary   bool
	MaxResponseBytes int64
	RedirectPolicy   RedirectPolicy
}

FetchOptions constrains HTTPS JSON fetches.

type HTTPRegistryClient

type HTTPRegistryClient struct {
	// contains filtered or unexported fields
}

HTTPRegistryClient implements RegistryClient against the standard DNSid registry endpoints.

func NewRegistryClient

func NewRegistryClient(baseURL string, transportConfig ...TransportConfig) (*HTTPRegistryClient, error)

NewRegistryClient creates an HTTP registry client for baseURL. An empty baseURL means DefaultRegistryURL (the local registry). HTTPS is required except on loopback hosts.

func NewRegistryClientWithOptions

func NewRegistryClientWithOptions(baseURL string, opts ...RegistryClientOption) (*HTTPRegistryClient, error)

NewRegistryClientWithOptions creates an HTTP registry client with functional options. URL rules follow NewRegistryClient.

func (*HTTPRegistryClient) CancelAgent

func (c *HTTPRegistryClient) CancelAgent(ctx context.Context, fqdn string) (*LifecycleResponse, error)

CancelAgent cancels an in-progress registration workflow for fqdn.

func (*HTTPRegistryClient) CanonicalRecordContent

func (c *HTTPRegistryClient) CanonicalRecordContent(ctx context.Context, domain, signingKid string) (*CanonicalRecordContentResponse, error)

CanonicalRecordContent fetches the registry-prepared unsigned canonical TXT content for domain, targeted at the given record-signing kid.

func (*HTTPRegistryClient) ConfirmReady

func (c *HTTPRegistryClient) ConfirmReady(ctx context.Context, fqdn string) (*LifecycleResponse, error)

ConfirmReady confirms the agent at fqdn is ready to go live. It is an alias for VerifyAgent.

func (*HTTPRegistryClient) CreateAgent

CreateAgent registers an agent. Pass 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 defaults to "production"; "sandbox" is also accepted. Private JWK members in PublicKey are rejected before anything is sent. Use CreateLiveAgent for Live names.

func (*HTTPRegistryClient) CreateLiveAgent

func (c *HTTPRegistryClient) CreateLiveAgent(ctx context.Context, req *LiveAgentRegistrationInput, idempotencyKey string) (*LiveProvisioningResponse, error)

CreateLiveAgent starts the separate managed Live HTTP 202 flow. It sends tier="live", managed=true, and environment="production". The idempotency key is required and must be reused for retries.

func (*HTTPRegistryClient) GetAgentEvents

func (c *HTTPRegistryClient) GetAgentEvents(ctx context.Context, fqdn string, opts *EventListOptions) (*EventListResponse, error)

GetAgentEvents lists registry audit events for the agent at fqdn. A nil opts requests the first page with the server's default limit.

func (*HTTPRegistryClient) GetAgentStatus

func (c *HTTPRegistryClient) GetAgentStatus(ctx context.Context, fqdn string) (*AgentDetail, error)

GetAgentStatus returns the registry's detailed view of the agent at fqdn, including workflow status, DNS publication state, and any workflow error.

func (*HTTPRegistryClient) GetIdentityRecord

GetIdentityRecord fetches the registry-prepared canonical identity record content for fqdn, targeted at the signing kid named in req.

func (*HTTPRegistryClient) GetRegistration

func (c *HTTPRegistryClient) GetRegistration(ctx context.Context, fqdn string) (*AgentRegistration, error)

GetRegistration returns normalized registry workflow state for fqdn, mapping the registry's managed mode ("self" or "dnsid") to a PublicationAuthority. It returns a *ValidationError for unknown managed modes.

func (*HTTPRegistryClient) ListAgents

ListAgents lists the caller's agents. A nil opts requests the first page with the server's default limit; use the response's NextCursor to page.

func (*HTTPRegistryClient) ListExpiringAgents

func (c *HTTPRegistryClient) ListExpiringAgents(ctx context.Context) (*OperationsAgentListResponse, error)

ListExpiringAgents lists agents whose identity records are approaching expiry.

func (*HTTPRegistryClient) ListFlaggedAgents

func (c *HTTPRegistryClient) ListFlaggedAgents(ctx context.Context) (*OperationsAgentListResponse, error)

ListFlaggedAgents lists agents the registry has flagged for operator attention.

func (*HTTPRegistryClient) ListPendingAgents

func (c *HTTPRegistryClient) ListPendingAgents(ctx context.Context) (*OperationsAgentListResponse, error)

ListPendingAgents lists agents whose registration workflows have not yet completed.

func (*HTTPRegistryClient) PrepareIssuance

func (c *HTTPRegistryClient) PrepareIssuance(ctx context.Context, fqdn, idempotencyKey string) (*PreparedRegistryEvent, error)

PrepareIssuance asks the registry to prepare a transparency-log ISSUANCE event for fqdn. The returned entry bytes are untrusted: parse and validate them against the returned log reference before signing. The idempotency key must be 1 to 200 bytes without surrounding whitespace; reuse the same key when retrying.

func (*HTTPRegistryClient) PrepareKeyRotation

func (c *HTTPRegistryClient) PrepareKeyRotation(ctx context.Context, fqdn string, req *KeyRotationPreparationRequest, idempotencyKey string) (*PreparedRegistryEvent, error)

PrepareKeyRotation asks the registry to prepare a transparency-log KEY_ROTATION event for fqdn. Authenticate with an organization session or API key; an agent bearer token is not accepted. The request must name the previous key ID and carry the new public key, which is rejected if it contains private JWK members. As with PrepareIssuance, the returned entry bytes are untrusted and must be validated before signing.

func (*HTTPRegistryClient) PublishSignature

func (c *HTTPRegistryClient) PublishSignature(ctx context.Context, domain, sig string) (*PublishedRecord, error)

PublishSignature submits an encoded record signature for domain and returns the resulting publication state as a PublishedRecord.

func (*HTTPRegistryClient) ReissueLiveProof

ReissueLiveProof requests a replacement challenge for an expired Live proof. RequestID is also sent as the required Idempotency-Key header.

func (*HTTPRegistryClient) RejectAgent

func (c *HTTPRegistryClient) RejectAgent(ctx context.Context, fqdn string) (*LifecycleResponse, error)

RejectAgent marks the registration workflow for fqdn as rejected.

func (*HTTPRegistryClient) RetireAgent

RetireAgent retires the immutable agent identity without revoking its key.

func (*HTTPRegistryClient) RevokeAgent

RevokeAgent revokes the immutable agent identity at fqdn with the supplied reason. Revocation is a terminal lifecycle transition whose persistence and transparency-log append are owned by the registry.

func (*HTTPRegistryClient) SetAuthToken

func (c *HTTPRegistryClient) SetAuthToken(token string) error

SetAuthToken updates the Bearer token on an existing client (e.g. after refresh). It returns an error if the client is configured for plaintext HTTP on a non-loopback host without WithInsecureHTTP.

func (*HTTPRegistryClient) SubmitChallenge

func (c *HTTPRegistryClient) SubmitChallenge(ctx context.Context, fqdn string, req *ChallengeRequest) error

SubmitChallenge submits a signed domain-control challenge response for the agent at fqdn. A nil error means the registry accepted the submission.

func (*HTTPRegistryClient) SubmitLiveProof

func (c *HTTPRegistryClient) SubmitLiveProof(ctx context.Context, fqdn string, req *LiveProofRequest) (*LiveProofResponse, error)

SubmitLiveProof submits proof of possession for a managed Live registration. RequestID is also sent as the required Idempotency-Key header.

func (*HTTPRegistryClient) SubmitPreparedEvent

func (c *HTTPRegistryClient) SubmitPreparedEvent(ctx context.Context, fqdn string, entryBytes []byte, idempotencyKey string) (*SubmissionResult, error)

SubmitPreparedEvent submits the exact signed entry bytes of a prepared event (1 to 65535 bytes) for transparency-log inclusion. On an accepted result it verifies that the registry's reported entry hash matches the SHA-256 of the submitted bytes and returns a *ValidationError on mismatch. Retry with the same bytes and idempotency key when the registry reports a retryable state (see RegistryAPIError.RetrySameEntry).

func (*HTTPRegistryClient) SubmitSignature

func (c *HTTPRegistryClient) SubmitSignature(ctx context.Context, fqdn string, req *SignatureRequest) (*SignatureResponse, error)

SubmitSignature posts a signature through the legacy self-managed identity-record endpoint.

func (*HTTPRegistryClient) UnregisterAgent

func (c *HTTPRegistryClient) UnregisterAgent(ctx context.Context, fqdn string) error

UnregisterAgent removes the agent at fqdn. It is best-effort for registry compatibility: an already-absent agent or a registry without DELETE support is treated as a successful no-op.

func (*HTTPRegistryClient) VerifyAgent

func (c *HTTPRegistryClient) VerifyAgent(ctx context.Context, fqdn string) (*LifecycleResponse, error)

VerifyAgent asks the registry to run its verification step for fqdn and advance the registration workflow.

func (*HTTPRegistryClient) VerifyDomainRemote

func (c *HTTPRegistryClient) VerifyDomainRemote(ctx context.Context, req *VerifyDomainRequest) (*VerifyDomainResponse, error)

VerifyDomainRemote asks the registry to check a domain's DNSid state from its vantage point. It complements, but does not replace, local IdentityManager.VerifyDomain verification.

func (*HTTPRegistryClient) WaitForStatus

func (c *HTTPRegistryClient) WaitForStatus(ctx context.Context, fqdn string, targetStatuses []string, opts *WaitForStatusOptions) (*AgentDetail, error)

WaitForStatus polls the registry until the agent at fqdn reaches one of targetStatuses. It is shorthand for WaitForRegistryStatus with this client.

type HTTPSFetcher

type HTTPSFetcher interface {
	FetchJSON(ctx context.Context, rawURL string, opts FetchOptions) (json.RawMessage, *tls.Certificate, error)
}

HTTPSFetcher fetches JSON over safe HTTPS. Implementations must be safe for concurrent use.

type IdentityCache

type IdentityCache struct {
	// contains filtered or unexported fields
}

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.

func NewIdentityCache

func NewIdentityCache(_ time.Duration) *IdentityCache

NewIdentityCache constructs a bounded, empty cache. The legacy defaultTTL parameter is ignored: only the original absolute evidence expiry is used.

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

func (c *IdentityCache) Get(domain string) *VerifiedDomain

Get 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

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.

type IdentityConfig

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
}

IdentityConfig contains the local identity's DNSid publication settings.

func (IdentityConfig) Validate

func (c IdentityConfig) Validate() error

Validate checks required identity configuration.

type IdentityManager

type IdentityManager struct {
	// contains filtered or unexported fields
}

IdentityManager is the primary DNSid SDK facade.

func NewIdentityManager

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

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

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

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

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

func (m *IdentityManager) CreateTXTRecord() (*TXTRecord, error)

CreateTXTRecord builds and signs this identity's _dnsid TXT record with the entity key.

func (*IdentityManager) Domain

func (m *IdentityManager) Domain() string

Domain returns this manager's local DNSid identity domain, or an empty string when the manager was constructed for verify-only use.

func (*IdentityManager) EntityKeyURL

func (m *IdentityManager) EntityKeyURL() string

EntityKeyURL 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

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

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

func (m *IdentityManager) GetEntityKeySet() *JWKS

GetEntityKeySet 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

func (m *IdentityManager) GetKeySet() *JWKS

GetKeySet returns the current active operational (ku) public signing key for publication. Draft 01 live endpoints expose exactly one current key.

func (*IdentityManager) KeyProvider

func (m *IdentityManager) KeyProvider() KeyProvider

KeyProvider returns this manager's local signing key provider, or nil for verify-only managers.

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

func (m *IdentityManager) OperationalKeyURL() string

OperationalKeyURL 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

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

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

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

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

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:
domain: agent.example
governance: agent.example
status: ACTIVE

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

VerifyLogEvidence performs an operation-time complete-history and non-revocation check for vd. A zero at value uses the current time.

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.

type IdentityManagerOption

type IdentityManagerOption func(*IdentityManager)

IdentityManagerOption configures IdentityManager.

func WithDNSResolver

func WithDNSResolver(r DNSResolver) IdentityManagerOption

WithDNSResolver overrides the built-in resolver. Resolvers used with DNSSECModeValidated or DNSSECModeRequired must report definitive DNSSEC states rather than DNSSECStateUnknown.

func WithEntityKeyProvider

func WithEntityKeyProvider(kp KeyProvider) IdentityManagerOption

WithEntityKeyProvider 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

func WithHTTPClient(client *http.Client) IdentityManagerOption

WithHTTPClient 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

func WithHTTPSFetcher(f HTTPSFetcher) IdentityManagerOption

WithHTTPSFetcher 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

func WithIdentityCache(cache *IdentityCache) IdentityManagerOption

WithIdentityCache 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

func WithLogRegistry(r *dnsidlog.LogRegistry) IdentityManagerOption

WithLogRegistry 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.

type IdentityRecordRequest

type IdentityRecordRequest struct {
	SigningKid string `json:"signingKid"`
}

IdentityRecordRequest matches the OpenAPI IdentityRecordRequest schema.

type IdentityRecordResponse

type IdentityRecordResponse struct {
	FQDN             string            `json:"fqdn"`
	CanonicalContent string            `json:"canonicalContent"`
	SigningKid       string            `json:"signingKid"`
	ExpiresAt        string            `json:"expiresAt"`
	Tags             map[string]string `json:"tags"`
}

IdentityRecordResponse matches the OpenAPI IdentityRecordResponse schema.

type IdentityResolver

type IdentityResolver interface {
	VerifyDomain(ctx context.Context, domain string) (*VerifiedDomain, error)
}

IdentityResolver verifies DNSid identity for peer domains.

type JWK

type JWK struct {
	// contains filtered or unexported fields
}

JWK is a typed wrapper over a single JWK with SDK-level helpers.

func (*JWK) Alg

func (k *JWK) Alg() JoseAlg

Alg returns the key's effective signing algorithm, deriving it from kty/crv when the JWK alg member is absent.

func (*JWK) Kid

func (k *JWK) Kid() string

Kid returns the key's kid value, or empty string if unset.

func (*JWK) Raw

func (k *JWK) Raw() jwk.Key

Raw returns the underlying jwk.Key.

func (*JWK) SignatureAlg

func (k *JWK) SignatureAlg(profile string) (JoseAlg, error)

SignatureAlg returns the signing algorithm allowed by the selected identity-record profile. Unlike JWK.Alg, draft profiles require an explicit alg member that is consistent with the key type. An empty profile selects DefaultPublishProfile.

func (*JWK) Thumbprint

func (k *JWK) Thumbprint() (string, error)

Thumbprint returns the RFC 7638 SHA-256 thumbprint of this key, base64url-unpadded encoded.

func (*JWK) Use

func (k *JWK) Use() string

Use returns the key's use value, or empty string if unset.

type JWKS

type JWKS struct {
	// contains filtered or unexported fields
}

JWKS is a typed wrapper over a JWK Set with SDK-level helpers.

func NewJWKS

func NewJWKS(set jwk.Set) *JWKS

NewJWKS wraps a jwk.Set into the typed SDK form.

func ParseJWKS

func ParseJWKS(data []byte) (*JWKS, error)

ParseJWKS parses a JWKS JSON document and returns the typed wrapper.

func (*JWKS) CurrentOperationalSigningKey

func (j *JWKS) CurrentOperationalSigningKey(profile string) (*JWK, error)

CurrentOperationalSigningKey returns the sole current operational signing key allowed by the selected identity-record profile.

func (*JWKS) CurrentRecordSigningKey

func (j *JWKS) CurrentRecordSigningKey(profile string) (*JWK, error)

CurrentRecordSigningKey returns the sole current record-signing key allowed by the selected identity-record profile.

func (*JWKS) KeyByID

func (j *JWKS) KeyByID(kid string) *JWK

KeyByID returns the key with the given kid, or nil if not found. This is an unfiltered lookup; the returned key may have use=enc or any other use value. Callers that want a signing-eligible key should filter the result against SigningKeys() or check Use() themselves.

func (*JWKS) Raw

func (j *JWKS) Raw() jwk.Set

Raw returns the underlying jwk.Set.

func (*JWKS) SigningKeys

func (j *JWKS) SigningKeys() []*JWK

SigningKeys returns all keys eligible for signature verification. Keys with unset use or use=sig are eligible.

func (*JWKS) Validate

func (j *JWKS) Validate() error

Validate enforces SDK invariants for signing keys.

func (*JWKS) ValidateOperational

func (j *JWKS) ValidateOperational(profile string) error

ValidateOperational verifies that the JWKS satisfies the selected identity-record profile's operational-key constraints. An empty profile selects DefaultPublishProfile.

func (*JWKS) ValidateRecordSigning

func (j *JWKS) ValidateRecordSigning(profile string) error

ValidateRecordSigning verifies that the JWKS satisfies the selected identity-record profile's record-signing-key constraints. An empty profile selects DefaultPublishProfile.

type JoseAlg

type JoseAlg string

JoseAlg is the default-deny allowlist of JOSE algorithms DNSid accepts.

const (
	JoseAlgEdDSA JoseAlg = "EdDSA"
	JoseAlgES256 JoseAlg = "ES256"
)

The JOSE algorithms DNSid accepts: Ed25519 (EdDSA) and ECDSA over P-256 with SHA-256 (ES256). All other algorithms are rejected.

func (JoseAlg) String

func (a JoseAlg) String() string

String returns the JOSE alg identifier as a string.

func (JoseAlg) Valid

func (a JoseAlg) Valid() bool

Valid reports whether a is in the DNSid JOSE algorithm allowlist.

type KeyAge

type KeyAge string

KeyAge is a DNSid key-age policy value.

type KeyProvider

type KeyProvider interface {
	// JWK returns one public JWK. With no kid it returns the active key.
	JWK(kid ...string) jwk.Key

	// ListKeyIds returns the active kid first, followed by retained kids.
	ListKeyIds() []string

	// Sign signs payload with the active key.
	Sign(payload []byte) (*KeySignature, error)

	// SignKey signs payload with a specific active or pending key.
	SignKey(kid string, payload []byte) (*KeySignature, error)

	// GenerateKey creates a pending key for alg and returns its kid.
	GenerateKey(alg JoseAlg) (string, error)

	// Activate promotes kid to active and retains the previous active key.
	Activate(kid string) error

	// Supersede removes a retained key after a completed rotation.
	Supersede(kid string) error

	// Purge removes a pending or retained key.
	Purge(kid string) error
}

KeyProvider abstracts key storage for the SDK.

type KeyRotationPreparationRequest

type KeyRotationPreparationRequest struct {
	PreviousKeyID string `json:"previous_key_id"`
	PublicKey     any    `json:"public_key"`
}

KeyRotationPreparationRequest requests a prepared operational-key rotation.

type KeySignature

type KeySignature struct {
	Kid       string
	Alg       JoseAlg
	Signature []byte
}

KeySignature is the result of signing with a KeyProvider's active key.

type LifecycleResponse

type LifecycleResponse struct {
	ID         string `json:"id"`
	Status     string `json:"status"`
	StatusNote string `json:"status_note,omitempty"`
}

LifecycleResponse matches the OpenAPI LifecycleResponse schema.

type ListAgentsOptions

type ListAgentsOptions struct {
	Limit  int
	Cursor string
}

ListAgentsOptions contains optional parameters for ListAgents.

type LiveAgentRegistrationInput

type LiveAgentRegistrationInput struct {
	Name string `json:"name,omitempty"`
	// PublicKey must be one public OKP/Ed25519 signing JWK with alg=EdDSA.
	PublicKey       any    `json:"public_key"`
	Environment     string `json:"environment,omitempty"`
	CapabilitiesURL string `json:"capabilities_url,omitempty"`
}

LiveAgentRegistrationInput is the caller-controlled input for managed Live registration. The client supplies the fixed tier, managed, and environment fields on the wire.

type LiveChallengeTranscript

type LiveChallengeTranscript struct {
	Protocol  string    `json:"protocol"`
	OrgID     string    `json:"org_id"`
	AgentID   string    `json:"agent_id"`
	FQDN      string    `json:"fqdn"`
	KeyID     string    `json:"key_id"`
	Nonce     string    `json:"nonce"`
	ExpiresAt time.Time `json:"expires_at"`
}

LiveChallengeTranscript is the validated proof-of-possession transcript decoded from a Live challenge message.

type LiveProofReissueRequest

type LiveProofReissueRequest struct {
	RequestID string `json:"request_id"`
	// PublicKey is the original Live registration key and is not sent on the wire.
	PublicKey any `json:"-"`
}

LiveProofReissueRequest requests a fresh challenge after an expired proof.

type LiveProofReissueResponse

type LiveProofReissueResponse struct {
	RequestID           string                   `json:"request_id"`
	AgentID             string                   `json:"agent_id"`
	Status              string                   `json:"status"`
	Challenge           string                   `json:"challenge"`
	ChallengeMessage    string                   `json:"challenge_message"`
	Domain              string                   `json:"-"`
	ChallengeTranscript *LiveChallengeTranscript `json:"-"`
}

LiveProofReissueResponse contains the replacement Live proof challenge. Domain and ChallengeTranscript are derived from the validated latest message.

type LiveProofRequest

type LiveProofRequest struct {
	RequestID string `json:"request_id"`
	// Challenge must come from the latest registration or reissue response.
	Challenge string `json:"challenge"`
	PublicKey any    `json:"public_key"`
	// Signature is unpadded base64url Ed25519 over the exact bytes obtained by
	// base64url-decoding that response's ChallengeMessage. Do not reserialize
	// ChallengeTranscript before signing.
	Signature string `json:"signature"`
}

LiveProofRequest proves possession of the key supplied for Live registration.

type LiveProofResponse

type LiveProofResponse struct {
	RequestID string `json:"request_id"`
	AgentID   string `json:"agent_id"`
	Status    string `json:"status"`
}

LiveProofResponse reports the durable Live proof handoff status.

type LiveProvisioningResponse

type LiveProvisioningResponse struct {
	RequestID           string                   `json:"request_id"`
	AgentID             string                   `json:"agent_id"`
	Status              string                   `json:"status"`
	Challenge           string                   `json:"challenge"`
	ChallengeMessage    string                   `json:"challenge_message"`
	Domain              string                   `json:"-"`
	ChallengeTranscript *LiveChallengeTranscript `json:"-"`
}

LiveProvisioningResponse is the HTTP 202 response for a managed Live registration. Domain and ChallengeTranscript are derived and populated while Status is challenge_pending.

type LocalKeyProvider

type LocalKeyProvider struct {
	// contains filtered or unexported fields
}

LocalKeyProvider loads a JWK keypair from disk or holds in-memory keys. Only one provider instance may write a given file; there is no file locking.

func GenerateES256KeyProvider

func GenerateES256KeyProvider() *LocalKeyProvider

GenerateES256KeyProvider creates an ephemeral in-memory ES256 keypair.

func GenerateEd25519KeyProvider

func GenerateEd25519KeyProvider() *LocalKeyProvider

GenerateEd25519KeyProvider creates an ephemeral in-memory Ed25519 keypair.

func LoadOrCreateLocalKeyProvider

func LoadOrCreateLocalKeyProvider(path string, alg JoseAlg) (*LocalKeyProvider, error)

LoadOrCreateLocalKeyProvider loads a JWK keypair from disk, or creates one if path does not exist.

func NewLocalKeyProvider

func NewLocalKeyProvider(path string) (*LocalKeyProvider, error)

NewLocalKeyProvider loads a key store file. It accepts the current active/retained/pending store shape and the older flat private JWK shape.

func (*LocalKeyProvider) Activate

func (p *LocalKeyProvider) Activate(kid string) error

Activate promotes the named pending or retained key to active and retains the previously active key. It returns an *ArgumentError for unknown kids. Even when kid is already active, the store is persisted again so callers can retry a durability failure. On failure before publication the previous state is restored; ErrKeyStoreDurability leaves the new state in memory and on disk.

func (*LocalKeyProvider) GenerateKey

func (p *LocalKeyProvider) GenerateKey(alg JoseAlg) (string, error)

GenerateKey creates a new pending key for alg and returns its kid (the key's RFC 7638 thumbprint). The new key is persisted to the provider's key store file, when one is configured, before the kid is returned; the active key is unchanged until Activate is called. On ErrKeyStoreDurability, the pending key is retained and its kid is returned alongside the error.

func (*LocalKeyProvider) JWK

func (p *LocalKeyProvider) JWK(kidOpt ...string) jwk.Key

JWK returns the public JWK for the requested kid, or for the active key when no kid is given. The returned key carries kid, alg, and use=sig. It returns nil when the kid is unknown or no key is active.

func (*LocalKeyProvider) ListKeyIds

func (p *LocalKeyProvider) ListKeyIds() []string

ListKeyIds returns the active kid first, followed by retained kids in insertion order. Pending kids are not listed.

func (*LocalKeyProvider) Purge

func (p *LocalKeyProvider) Purge(kid string) error

Purge removes a pending or retained key and persists the change. Purging the active key or an unknown kid returns an *ArgumentError. On ErrKeyStoreDurability the removal is not rolled back.

func (*LocalKeyProvider) Sign

func (p *LocalKeyProvider) Sign(payload []byte) (*KeySignature, error)

Sign signs payload with the active key. It returns an error when no key is active. ES256 signatures are deterministic (RFC 6979) raw R||S; EdDSA signatures are standard Ed25519.

func (*LocalKeyProvider) SignKey

func (p *LocalKeyProvider) SignKey(kid string, payload []byte) (*KeySignature, error)

SignKey signs payload with the named key, which must be in the active or pending state; signing with a retained key returns an *ArgumentError.

func (*LocalKeyProvider) Supersede

func (p *LocalKeyProvider) Supersede(kid string) error

Supersede removes a retained key after a completed rotation. It returns an *ArgumentError when kid does not name a retained key.

type LogEventCanonicalizer

type LogEventCanonicalizer interface {
	Canonical(event dnsidlog.LogEvent) ([]byte, error)
}

LogEventCanonicalizer produces the exact bytes covered by lifecycle-event signatures for one bound log method and reference.

type LogSignerRole

type LogSignerRole string

LogSignerRole identifies a DNSid lifecycle-event signer. Signatures from all roles cover the same log-method canonical bytes.

const (
	LogSignerEntity                      LogSignerRole = "entity"
	LogSignerOperationalCountersignature LogSignerRole = "operational_countersignature"
	LogSignerPreviousOperational         LogSignerRole = "previous_operational"
	LogSignerNewOperational              LogSignerRole = "new_operational"
)

The lifecycle-event signer roles: the accountable entity signature, the operational countersignature on ISSUANCE, and the previous- and new-operational signatures on KEY_ROTATION.

func RequiredLogSignatures

func RequiredLogSignatures(event dnsidlog.LogEvent) ([]LogSignerRole, error)

RequiredLogSignatures returns the base draft-01 signer roles for event.

type OperationsAgent

type OperationsAgent struct {
	ID                      string      `json:"id"`
	Domain                  string      `json:"domain"`
	DomainDisplay           string      `json:"domain_display"`
	Environment             string      `json:"environment"`
	Status                  string      `json:"status"`
	DaysRemaining           *int        `json:"days_remaining,omitempty"`
	IdentityRecordExpiresAt *string     `json:"identity_record_expires_at,omitempty"`
	Error                   *AgentError `json:"error,omitempty"`
	CreatedAt               time.Time   `json:"created_at"`
	UpdatedAt               time.Time   `json:"updated_at"`
}

OperationsAgent matches the OpenAPI OperationsAgent schema.

type OperationsAgentListResponse

type OperationsAgentListResponse struct {
	Agents []OperationsAgent `json:"agents"`
}

OperationsAgentListResponse matches the OpenAPI OperationsAgentListResponse schema.

type ParseError

type ParseError = sdkerrors.ParseError

ParseError is the shared SDK ParseError category.

func NewParseError

func NewParseError(msg string, cause error) *ParseError

NewParseError creates a parse error with an optional underlying cause.

type PolicyFlag

type PolicyFlag string

PolicyFlag is a DNSid TXT-record policy flag.

const (
	PolicyFlagMTLS     PolicyFlag = "mtls"
	PolicyFlagLogCheck PolicyFlag = "logchk"
)

DNSid TXT-record policy flags understood by the verifier.

type PreparedRegistryEvent

type PreparedRegistryEvent struct {
	EntryBytes   []byte
	LogReference string
}

PreparedRegistryEvent contains the untrusted exact bytes and log reference returned by a registry preparation endpoint. Parse and validate EntryBytes against LogReference with the selected log binding before signing.

type PublicationAuthority

type PublicationAuthority string

PublicationAuthority identifies who controls the accountable-entity key and signs the DNSid record.

const (
	PublicationAuthorityClient   PublicationAuthority = "client"
	PublicationAuthorityRegistry PublicationAuthority = "registry"
)

PublicationAuthority values: the client holds the entity key and signs the record itself, or the registry does so on the client's behalf.

type PublicationConfig

type PublicationConfig struct {
	PublishProfile  string `json:"publish_profile"`
	GovernanceID    string `json:"governance_id"`
	KeyURL          string `json:"ku_url"` // Operational-key JWKS URL.
	EntityKeyURL    string `json:"ek_url"` // Accountable-entity JWKS URL.
	LogRef          string `json:"log_ref"`
	StatusURL       string `json:"status_url"`
	CapabilitiesURL string `json:"capabilities_url,omitempty"`
	MaxKeyAge       string `json:"max_key_age,omitempty"`
}

PublicationConfig is the authoritative set of profile-known values the registry uses to construct an agent's unsigned identity record.

type PublishedRecord

type PublishedRecord struct {
	Domain            string          `json:"domain"`
	OwnerName         string          `json:"ownerName"`
	TXTRecord         string          `json:"txtRecord"`
	TTL               int             `json:"ttl"`
	PublicationStatus string          `json:"publicationStatus"`
	ProtocolStatus    *AgentStatus    `json:"protocolStatus,omitempty"`
	Raw               json.RawMessage `json:"raw,omitempty"`
}

PublishedRecord is the result of a registry TXT publication workflow.

type RedirectPolicy

type RedirectPolicy string

RedirectPolicy controls HTTPS redirect handling for SDK-managed fetches.

const (
	RedirectPolicyNone     RedirectPolicy = "none"
	RedirectPolicySameHost RedirectPolicy = "sameHost"
	RedirectPolicyHTTPS    RedirectPolicy = "https"
)

RedirectPolicy 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.

type RegistryAPIError

type RegistryAPIError struct {
	StatusCode int
	Code       string `json:"error,omitempty"`
	Message    string `json:"message,omitempty"`
	Cause      error  `json:"-"`
}

RegistryAPIError represents a registry transport failure or non-2xx API response. The registry error schema uses fields "error" and "message".

func (*RegistryAPIError) Error

func (e *RegistryAPIError) Error() string

Error implements error, formatting the HTTP status with the registry's error code and message when present.

func (*RegistryAPIError) RetrySameEntry

func (e *RegistryAPIError) RetrySameEntry() bool

RetrySameEntry reports whether the registry requires retrying the exact submitted bytes with the same idempotency key. An unclassified HTTP 5xx is indeterminate and therefore also requires an exact-byte retry. Known terminal protocol errors override that transport-level fallback.

func (*RegistryAPIError) SubmissionState

func (e *RegistryAPIError) SubmissionState() SubmissionState

SubmissionState maps a prepared-event submission failure to the durable lifecycle state shared by managed coordinators.

func (*RegistryAPIError) Transient

func (e *RegistryAPIError) Transient() bool

Transient reports whether retrying the registry operation may succeed. Prepared-event callers must additionally honor RetrySameEntry so a retry never regenerates signed bytes.

func (*RegistryAPIError) Unwrap

func (e *RegistryAPIError) Unwrap() error

Unwrap returns the underlying transport failure, if any.

type RegistryClient

type RegistryClient interface {
	RegistryPublisher

	// Agent CRUD
	CreateAgent(ctx context.Context, req *CreateAgentRequest) (*CreateAgentResponse, error)
	CreateLiveAgent(ctx context.Context, req *LiveAgentRegistrationInput, idempotencyKey string) (*LiveProvisioningResponse, error)
	UnregisterAgent(ctx context.Context, fqdn string) error
	ListAgents(ctx context.Context, opts *ListAgentsOptions) (*AgentListResponse, error)
	GetAgentStatus(ctx context.Context, fqdn string) (*AgentDetail, error)
	GetAgentEvents(ctx context.Context, fqdn string, opts *EventListOptions) (*EventListResponse, error)

	// Agent lifecycle
	SubmitChallenge(ctx context.Context, fqdn string, req *ChallengeRequest) error
	SubmitLiveProof(ctx context.Context, fqdn string, req *LiveProofRequest) (*LiveProofResponse, error)
	ReissueLiveProof(ctx context.Context, fqdn string, req *LiveProofReissueRequest) (*LiveProofReissueResponse, error)
	RevokeAgent(ctx context.Context, fqdn string, req *RevokeAgentRequest) (*LifecycleResponse, error)
	RetireAgent(ctx context.Context, fqdn string, req *RetireAgentRequest) (*LifecycleResponse, error)
	CancelAgent(ctx context.Context, fqdn string) (*LifecycleResponse, error)
	RejectAgent(ctx context.Context, fqdn string) (*LifecycleResponse, error)
	VerifyAgent(ctx context.Context, fqdn string) (*LifecycleResponse, error)
	ConfirmReady(ctx context.Context, fqdn string) (*LifecycleResponse, error)

	// Identity record (new API paths)
	GetIdentityRecord(ctx context.Context, fqdn string, req *IdentityRecordRequest) (*IdentityRecordResponse, error)
	SubmitSignature(ctx context.Context, fqdn string, req *SignatureRequest) (*SignatureResponse, error)

	// Operations
	ListExpiringAgents(ctx context.Context) (*OperationsAgentListResponse, error)
	ListFlaggedAgents(ctx context.Context) (*OperationsAgentListResponse, error)
	ListPendingAgents(ctx context.Context) (*OperationsAgentListResponse, error)

	// Verification
	VerifyDomainRemote(ctx context.Context, req *VerifyDomainRequest) (*VerifyDomainResponse, error)
}

RegistryClient is the full control-plane client for the DNSid registry API.

type RegistryClientControlledPublisher

type RegistryClientControlledPublisher interface {
	RegistryPublisher
	RegistryRegistrationReader
}

RegistryClientControlledPublisher adds the registration state needed to enforce client publication authority before signing.

type RegistryClientOption

type RegistryClientOption func(*HTTPRegistryClient)

RegistryClientOption configures an HTTPRegistryClient.

func WithAuthToken

func WithAuthToken(token string) RegistryClientOption

WithAuthToken sets a Bearer token for authenticated API calls.

func WithInsecureHTTP

func WithInsecureHTTP() RegistryClientOption

WithInsecureHTTP allows the client to use plaintext HTTP transport. This is intended only for local development and testing; production callers should always use HTTPS.

func WithRegistryHTTPClient

func WithRegistryHTTPClient(client *http.Client) RegistryClientOption

WithRegistryHTTPClient sets a custom HTTP client for the registry client.

type RegistryConfig

type RegistryConfig struct {
	RegistryURL string
}

RegistryConfig contains DNSid registry control-plane settings.

type RegistryPreparedEventClient

type RegistryPreparedEventClient interface {
	PrepareIssuance(ctx context.Context, fqdn, idempotencyKey string) (*PreparedRegistryEvent, error)
	PrepareKeyRotation(ctx context.Context, fqdn string, req *KeyRotationPreparationRequest, idempotencyKey string) (*PreparedRegistryEvent, error)
	SubmitPreparedEvent(ctx context.Context, fqdn string, entryBytes []byte, idempotencyKey string) (*SubmissionResult, error)
}

RegistryPreparedEventClient is the capability required for prepared C2SP transparency-log preparation and submission transport.

type RegistryPublisher

type RegistryPublisher interface {
	CanonicalRecordContent(ctx context.Context, domain, signingKid string) (*CanonicalRecordContentResponse, error)
	PublishSignature(ctx context.Context, domain, sig string) (*PublishedRecord, error)
}

RegistryPublisher is the canonical-record and signature-publication capability shared by registry clients.

type RegistryRegistrationReader

type RegistryRegistrationReader interface {
	GetRegistration(ctx context.Context, domain string) (*AgentRegistration, error)
}

RegistryRegistrationReader reads normalized registry workflow state.

type RegistryRevocationReason

type RegistryRevocationReason string

RegistryRevocationReason is an owner-authorized registry revocation reason. It is distinct from the protocol REVOCATION reason vocabulary.

const (
	RegistryRevocationReasonOwnerRequest  RegistryRevocationReason = "owner_request"
	RegistryRevocationReasonKeyCompromise RegistryRevocationReason = "key_compromise"
)

Owner-authorized registry revocation reasons.

type RegistryRevoker

type RegistryRevoker interface {
	RevokeAgent(ctx context.Context, fqdn string, req *RevokeAgentRequest) (*LifecycleResponse, error)
}

RegistryRevoker is the registry capability required for managed revocation.

type RegistryStatusReader

type RegistryStatusReader interface {
	GetAgentStatus(ctx context.Context, fqdn string) (*AgentDetail, error)
}

RegistryStatusReader is the subset needed by WaitForRegistryStatus.

type RegistryWorkflowError

type RegistryWorkflowError struct {
	Registration *AgentRegistration
	Status       string
	Cause        error
}

RegistryWorkflowError reports a terminal or interrupted registry workflow.

func (*RegistryWorkflowError) Error

func (e *RegistryWorkflowError) Error() string

Error implements error, naming the terminal workflow status when the registration is available.

func (*RegistryWorkflowError) Unwrap

func (e *RegistryWorkflowError) Unwrap() error

Unwrap returns the cancellation or timeout that interrupted the workflow.

type RetireAgentRequest

type RetireAgentRequest struct {
	AgentID string `json:"agent_id"`
}

RetireAgentRequest matches the OpenAPI RetireRequest schema.

type RevokeAgentRequest

type RevokeAgentRequest struct {
	AgentID string                   `json:"agent_id"`
	Reason  RegistryRevocationReason `json:"reason"`
}

RevokeAgentRequest matches the OpenAPI RevokeRequest schema.

type SDKConformanceMetadata

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"`
}

SDKConformanceMetadata describes the exact protocol behavior and log-binding revisions implemented by this SDK release.

func SDKConformance

func SDKConformance() SDKConformanceMetadata

SDKConformance returns an immutable snapshot of this release's protocol conformance metadata. Callers may mutate the returned maps and slice without changing future snapshots.

type SignatureRequest

type SignatureRequest struct {
	Signature string `json:"signature"`
}

SignatureRequest matches the OpenAPI SignatureRequest schema.

type SignatureResponse

type SignatureResponse struct {
	FQDN     string      `json:"fqdn"`
	Status   string      `json:"status"`
	Message  string      `json:"message,omitempty"`
	Records  []DNSRecord `json:"records"`
	ZoneFile string      `json:"zoneFile,omitempty"`
}

SignatureResponse is the legacy response for POST /agent/{fqdn}/signature. Its Status is publication workflow state, not protocol AgentStatus.

type SubmissionResult

type SubmissionResult struct {
	State     SubmissionState `json:"state"`
	EntryHash string          `json:"entry_hash"`
	Index     *uint64         `json:"index,omitempty"`
	KeyID     string          `json:"key_id,omitempty"`
	LogRef    string          `json:"lr,omitempty"`
	ErrorCode string          `json:"error_code,omitempty"`
}

SubmissionResult reports registry transparency-log submission state.

type SubmissionState

type SubmissionState string

SubmissionState is durable registry transparency-log submission state.

const (
	SubmissionStatePending       SubmissionState = "pending"
	SubmissionStatePrepared      SubmissionState = "prepared"
	SubmissionStateSubmitting    SubmissionState = "submitting"
	SubmissionStateAccepted      SubmissionState = "accepted"
	SubmissionStateRejected      SubmissionState = "rejected"
	SubmissionStateIndeterminate SubmissionState = "indeterminate"
)

SubmissionState values. SubmissionStateAccepted and SubmissionStateRejected are terminal; SubmissionStateIndeterminate means the outcome is unknown and the same bytes should be resubmitted with the same idempotency key.

type TXTRecord

type TXTRecord struct {
	Version      string            // v= — DNSid wire profile
	GovernanceID string            // gi= — governance identifier
	EntityKeyURI string            // ek= — accountable-entity record-signing JWKS URI
	KeyURI       string            // ku= — JWKS endpoint URL
	LogRef       string            // lr= — ledger address
	StatusURI    string            // su= — status endpoint URL
	Signature    string            // sg= — base64url owner signature
	Flags        []string          // fl= — parsed flag list (nil if absent)
	KeyAge       string            // ka= — key age policy (empty if absent)
	Capabilities string            // cu= — Agent Card URL (empty if absent)
	UnknownTags  map[string]string // syntactically valid extension tags, preserved but ignored semantically
}

TXTRecord represents a parsed _dnsid TXT record.

func ParseTXTRecord

func ParseTXTRecord(txt string) (*TXTRecord, error)

ParseTXTRecord parses a concatenated TXT record string into a TXTRecord.

func ParseUnsignedCanonical

func ParseUnsignedCanonical(txt string) (*TXTRecord, error)

ParseUnsignedCanonical parses registry-supplied unsigned canonical TXT content. It accepts required non-signature inputs and extension tags, but rejects sg=.

func (*TXTRecord) Canonical

func (r *TXTRecord) Canonical() string

Canonical returns the canonical string used for TXT-record signature verification.

func (*TXTRecord) CanonicalContent

func (r *TXTRecord) CanonicalContent() []byte

CanonicalContent returns the canonical byte string for signing under the record's declared profile. Values are signed as raw ASCII TXT tag values.

func (*TXTRecord) KnownTagsCanonical

func (r *TXTRecord) KnownTagsCanonical() []byte

KnownTagsCanonical returns the canonical byte string for known TXT tags only, excluding sg=. Unknown extension tags are ignored.

func (*TXTRecord) MarshalTXT

func (r *TXTRecord) MarshalTXT() (string, error)

MarshalTXT serializes the record as one _dnsid TXT value for wire output. It emits v= first, then all other tags sorted lexically; signing order is profile-defined and may differ.

func (*TXTRecord) Serialize

func (r *TXTRecord) Serialize() string

Serialize serializes the record as one _dnsid TXT value.

func (*TXTRecord) Tags

func (r *TXTRecord) Tags() map[string]string

Tags returns the record's tag-value pairs as a map, excluding empty optional fields. It always emits the current wire tag names.

func (*TXTRecord) Validate

func (r *TXTRecord) Validate(identityFQDN string) error

Validate checks record-level semantics with identity-domain context.

func (*TXTRecord) WithSignature

func (r *TXTRecord) WithSignature(sig string) *TXTRecord

WithSignature returns a copy of the record with Signature set to sig.

type TXTRecordRData

type TXTRecordRData struct {
	Value string
	TTL   time.Duration
}

TXTRecordRData is one concatenated TXT RDATA value plus resolver metadata.

type TransportConfig

type TransportConfig struct {
	DNSServer           string
	CABundlePath        string
	PrivateAddressHosts []string
}

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.

func (TransportConfig) IsZero added in v0.35.0

func (c TransportConfig) IsZero() bool

IsZero reports whether no transport setting is configured.

type TrustedEntity

type TrustedEntity struct {
	GovernanceID         string
	EntityKeyThumbprints []string
}

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 ValidationError

type ValidationError struct {
	Message string
	Cause   error
}

ValidationError is returned when input parses successfully but fails a semantic or structural rule: required tags missing, FQDN normalization violations, policy-flag whitelist violations, host equality checks, etc. A ValidationError is always permanent.

func NewValidationError

func NewValidationError(msg string, cause error) *ValidationError

NewValidationError constructs a ValidationError wrapping cause with msg.

func (*ValidationError) Error

func (e *ValidationError) Error() string

Error implements error.

func (*ValidationError) Is

func (e *ValidationError) Is(target error) bool

Is matches any other *ValidationError. ValidationError is a category, not an identity: errors.Is(anyValidationError, anyOther) returns true. Use errors.As to read Message / Cause.

func (*ValidationError) Unwrap

func (e *ValidationError) Unwrap() error

Unwrap returns the wrapped cause, if any.

type VerificationCode

type VerificationCode string

VerificationCode is a machine-readable classifier for *VerificationError. Codes group failures by cause so callers can branch on type without pattern-matching on error strings.

const (
	VerificationCodeDNSResolution     VerificationCode = "dns_resolution"
	VerificationCodeDNSSECFailed      VerificationCode = "dnssec_failed"
	VerificationCodeRecordInvalid     VerificationCode = "record_invalid"
	VerificationCodeSignatureInvalid  VerificationCode = "signature_invalid"
	VerificationCodeTLSError          VerificationCode = "tls_error"
	VerificationCodeKeyAgeExceeded    VerificationCode = "key_age_exceeded"
	VerificationCodeStatusUnavailable VerificationCode = "status_unavailable"
	VerificationCodeStatusNotActive   VerificationCode = "status_not_active"
	VerificationCodeLogError          VerificationCode = "log_error"
	// VerificationCodeCounterpartyNotAccepted reports that configured
	// VerificationConfig.TrustedEntities policy denied a counterparty whose
	// DNSid record verified. Always permanent.
	VerificationCodeCounterpartyNotAccepted VerificationCode = "counterparty_not_accepted"
)

Core verification codes defined by the language-agnostic SDK contract.

const (
	VerificationCodeChainContinuity   VerificationCode = "CHAIN_CONTINUITY"
	VerificationCodeDuplicateIssuance VerificationCode = "DUPLICATE_ISSUANCE"
	VerificationCodeInvalidEvidence   VerificationCode = "INVALID_EVIDENCE"
	VerificationCodeIncompleteStream  VerificationCode = "INCOMPLETE_STREAM"
	VerificationCodeKeyContinuity     VerificationCode = "KEY_CONTINUITY"
	VerificationCodeInvalidMigration  VerificationCode = "INVALID_MIGRATION"
	VerificationCodeTerminalState     VerificationCode = "TERMINAL_STATE"
)

Lifecycle log verification codes emitted when strict lifecycle state-machine enforcement rejects an agent's log evidence. Values are the uppercase identifiers defined by the cross-SDK lifecycle contract.

const (
	VerificationCodeKeyNotFound        VerificationCode = "key_not_found"
	VerificationCodeAgentNotFound      VerificationCode = "agent_not_found"
	VerificationCodeTokenExpired       VerificationCode = "token_expired"
	VerificationCodeTokenNotYetValid   VerificationCode = "token_not_yet_valid"
	VerificationCodeMalformedToken     VerificationCode = "malformed_token"
	VerificationCodeInvalidClaims      VerificationCode = "invalid_claims"
	VerificationCodeAudienceMismatch   VerificationCode = "audience_mismatch"
	VerificationCodeIssuerMismatch     VerificationCode = "issuer_mismatch"
	VerificationCodeLifetimeTooLong    VerificationCode = "lifetime_too_long"
	VerificationCodePolicyNotSatisfied VerificationCode = "policy_not_satisfied"
)

Application-profile codes retained for JOSE, HTTP-signature, and OIDC callers. Core VerifyDomain does not emit these codes.

VerificationCodeAudienceMismatch, VerificationCodeIssuerMismatch, and VerificationCodeLifetimeTooLong are specific claim-validation failures. They are children of VerificationCodeInvalidClaims for errors.Is purposes: an error with one of these codes also satisfies errors.Is(err, ErrInvalidClaims). See VerificationError.Is.

const VerificationCodeJWKSUnavailable VerificationCode = "jwks_unavailable"

VerificationCodeJWKSUnavailable is a Go binding extension for JWKS fetch failures, which the core contract does not otherwise name.

type VerificationConfig

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
}

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 VerificationError

type VerificationError struct {
	// contains filtered or unexported fields
}

VerificationError is returned when runtime verification fails: signature mismatch, JWKS fetch failure, status check failure, key not found, revoked agent, expired/invalid token, etc. The Code classifies the failure; Transient indicates whether retrying might succeed.

Fields are unexported and accessed via Code(), Transient(), AgentState(), and Message(). This prevents accidental mutation of the package-level sentinel values (ErrTokenExpired, ErrTXTRecordNotFound, etc.) that callers may obtain via errors.As. The wrapped cause is exposed via Unwrap().

func NewVerificationError

func NewVerificationError(code VerificationCode, transient bool, msg string, cause error, opts ...VerificationErrorOption) *VerificationError

NewVerificationError constructs a VerificationError.

func (*VerificationError) AgentState

func (e *VerificationError) AgentState() AgentState

AgentState returns the agent state recorded with this error, if any (populated when a status check returned a specific state).

func (*VerificationError) Code

Code returns the failure classifier.

func (*VerificationError) Error

func (e *VerificationError) Error() string

Error implements error.

func (*VerificationError) Is

func (e *VerificationError) Is(target error) bool

Is matches another *VerificationError with the same Code. It also matches a sentinel exemplar whose Code is a parent category of the receiver's Code (see invalidClaimsChildren). This lets callers compare against a sentinel — e.g. errors.Is(err, ErrTXTRecordNotFound) — without holding the original pointer, and lets specific claim errors satisfy the broader errors.Is(err, ErrInvalidClaims) check.

func (*VerificationError) Message

func (e *VerificationError) Message() string

Message returns the human-readable detail string.

func (*VerificationError) Transient

func (e *VerificationError) Transient() bool

Transient reports whether retrying might succeed.

func (*VerificationError) Unwrap

func (e *VerificationError) Unwrap() error

Unwrap returns the wrapped cause, if any.

func (*VerificationError) VerifiedEntityKeyThumbprint

func (e *VerificationError) VerifiedEntityKeyThumbprint() string

VerifiedEntityKeyThumbprint returns the observed verified record-signing key's RFC 7638 SHA-256 thumbprint for a VerificationCodeCounterpartyNotAccepted error; empty for other codes.

func (*VerificationError) VerifiedGovernanceID

func (e *VerificationError) VerifiedGovernanceID() string

VerifiedGovernanceID returns the observed verified governance ID for a VerificationCodeCounterpartyNotAccepted error; empty for other codes.

type VerificationErrorOption

type VerificationErrorOption func(*VerificationError)

VerificationErrorOption configures optional fields on a VerificationError.

func WithAgentState

func WithAgentState(state AgentState) VerificationErrorOption

WithAgentState attaches an agent state to a VerificationError. Used when a status check returned a specific state (e.g. "revoked").

func WithVerifiedIdentity

func WithVerifiedIdentity(governanceID, entityKeyThumbprint string) VerificationErrorOption

WithVerifiedIdentity records the observed verified governance ID and record-signing key thumbprint on a counterparty acceptance denial. It never carries configured allowlist or pin values.

type VerifiedDomain

type VerifiedDomain struct {
	// contains filtered or unexported fields
}

VerifiedDomain is the result of successful DNSid domain verification.

func VerifyIdentity

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

func (v *VerifiedDomain) CachedState() string

CachedState 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

func (v *VerifiedDomain) DNSSECState() DNSSECState

DNSSECState returns the resolver's DNSSEC validation result for the _dnsid lookup. It returns DNSSECStateUnknown on a nil receiver.

func (*VerifiedDomain) DNSTTL

func (v *VerifiedDomain) DNSTTL() time.Duration

DNSTTL returns the TTL of the _dnsid TXT record as reported by the resolver, or 0 on a nil receiver.

func (*VerifiedDomain) Domain

func (v *VerifiedDomain) Domain() string

Domain returns the verified identity domain in normalized FQDN form. It returns an empty string on a nil receiver.

func (*VerifiedDomain) Expiry

func (v *VerifiedDomain) Expiry() time.Time

Expiry 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

func (v *VerifiedDomain) JWKSCertificate() *tls.Certificate

JWKSCertificate returns a copy of the TLS certificate presented by the runtime (ku) JWKS endpoint, or nil when unavailable.

func (*VerifiedDomain) JWKSLeafCertificate

func (v *VerifiedDomain) JWKSLeafCertificate() *x509.Certificate

JWKSLeafCertificate returns a copy of the leaf certificate presented by the runtime (ku) JWKS endpoint, or nil when unavailable.

func (*VerifiedDomain) KeyBoundAt

func (v *VerifiedDomain) KeyBoundAt() time.Time

KeyBoundAt 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

func (v *VerifiedDomain) KeySet() *JWKS

KeySet 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

func (v *VerifiedDomain) LastStatusCheckAt() time.Time

LastStatusCheckAt 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

func (v *VerifiedDomain) LogReader() dnsidlog.LogReader

LogReader returns the lifecycle log reader bound to the record's lr= reference during verification, or nil on a nil receiver.

func (*VerifiedDomain) Record

func (v *VerifiedDomain) Record() *TXTRecord

Record 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

func (v *VerifiedDomain) RecordSigningKeySet() *JWKS

RecordSigningKeySet returns a deep copy of the accountable-entity (ek) JWKS that verified the record signature, or nil on a nil receiver.

func (*VerifiedDomain) RequiresLogCheck

func (v *VerifiedDomain) RequiresLogCheck() bool

RequiresLogCheck reports whether the verified record carries the logchk policy signal. Applications decide which operations require fresh evidence.

func (*VerifiedDomain) SigningKey

func (v *VerifiedDomain) SigningKey() *JWK

SigningKey returns a deep copy of the entity key that produced the record's sg= signature, or nil on a nil receiver.

func (*VerifiedDomain) Status

func (v *VerifiedDomain) Status() *AgentStatus

Status 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

func (v *VerifiedDomain) StatusCertificate() *tls.Certificate

StatusCertificate returns a copy of the TLS certificate presented by the status (su) endpoint, or nil when unavailable.

func (*VerifiedDomain) StatusLeafCertificate

func (v *VerifiedDomain) StatusLeafCertificate() *x509.Certificate

StatusLeafCertificate returns a copy of the leaf certificate presented by the status (su) endpoint, or nil when unavailable.

func (*VerifiedDomain) VerifiedAt

func (v *VerifiedDomain) VerifiedAt() time.Time

VerifiedAt returns when full verification completed. It returns the zero time on a nil receiver.

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.

type VerifyDomainOpts

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
}

VerifyDomainOpts contains optional inputs for core domain verification.

type VerifyDomainRequest

type VerifyDomainRequest struct {
	Domain string `json:"domain"`
}

VerifyDomainRequest matches the OpenAPI VerifyDomainRequest schema.

type VerifyDomainResponse

type VerifyDomainResponse struct {
	Domain      string  `json:"domain"`
	Registered  bool    `json:"registered"`
	AgentStatus *string `json:"agent_status,omitempty"`
	Reachable   *bool   `json:"reachable,omitempty"`
	KeyMatch    *bool   `json:"key_match,omitempty"`
	VerifiedAt  *string `json:"verified_at,omitempty"`
	ErrorTitle  string  `json:"error_title,omitempty"`
	ErrorDetail string  `json:"error_detail,omitempty"`
	Remediation string  `json:"remediation,omitempty"`
}

VerifyDomainResponse matches the OpenAPI VerifyDomainResponse schema.

type WaitForStatusOptions

type WaitForStatusOptions struct {
	PollInterval time.Duration
	Timeout      time.Duration
}

WaitForStatusOptions configures registry status polling.

Directories

Path Synopsis
Package config loads DNSid SDK configuration from sources other than code (DNSID_* environment variables and a DNSid CLI identity directory), merges partial results, and constructs an IdentityManager from them.
Package config loads DNSid SDK configuration from sources other than code (DNSID_* environment variables and a DNSid CLI identity directory), merges partial results, and constructs an IdentityManager from them.
examples
a2a command
oidc command
validate-domain command
webbotauth command
Package httpsig implements RFC 9421 HTTP Message Signatures for DNSid agents: signing outbound HTTP requests with an agent's operational key and verifying inbound signatures against the signer's published DNSid identity.
Package httpsig implements RFC 9421 HTTP Message Signatures for DNSid agents: signing outbound HTTP requests with an agent's operational key and verifying inbound signatures against the signer's published DNSid identity.
internal
Package jose implements the DNSid JOSE profile: creating and verifying DNSid JWTs and compact JWS objects signed with an agent's operational key.
Package jose implements the DNSid JOSE profile: creating and verifying DNSid JWTs and compact JWS objects signed with an agent's operational key.
key
aws module
log
Package log defines the DNSid lifecycle-log abstractions: the signed events that record an agent's identity lifecycle (issuance, key rotation, revocation, retirement, migration, and delegation) and the interfaces used to write and verify that evidence.
Package log defines the DNSid lifecycle-log abstractions: the signed events that record an agent's identity lifecycle (issuance, key rotation, revocation, retirement, migration, and delegation) and the interfaces used to write and verify that evidence.
c2sptlog
Package c2sptlog binds DNSid lifecycle logs to C2SP transparency logs: it reads, verifies, and writes DNSid lifecycle events stored as entries in a tiled Merkle log that follows the C2SP tlog-tiles, tlog-checkpoint, tlog-witness, and tlog-policy specifications (see PinnedSpecificationVersions for the exact pinned versions).
Package c2sptlog binds DNSid lifecycle logs to C2SP transparency logs: it reads, verifies, and writes DNSid lifecycle events stored as entries in a tiled Merkle log that follows the C2SP tlog-tiles, tlog-checkpoint, tlog-witness, and tlog-policy specifications (see PinnedSpecificationVersions for the exact pinned versions).
Package oidc mints and verifies DNSid OIDC tokens.
Package oidc mints and verifies DNSid OIDC tokens.
Package webbotauth implements the Web Bot Auth profile (draft-meunier-webbotauth-httpsig-protocol) on top of package httpsig: it signs HTTP requests with RFC 9421 HTTP Message Signatures tagged "web-bot-auth" so an origin can verify the caller is a specific DNSid agent.
Package webbotauth implements the Web Bot Auth profile (draft-meunier-webbotauth-httpsig-protocol) on top of package httpsig: it signs HTTP requests with RFC 9421 HTTP Message Signatures tagged "web-bot-auth" so an origin can verify the caller is a specific DNSid agent.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL