Transparency log
An agent’s identity history consists of signed lifecycle events: ISSUANCE, KEY_ROTATION, REVOCATION, RETIREMENT, MIGRATION, and DELEGATION. The identity record’s lr= field identifies the log and stream that carry those events; a C2SP reference has the form c2sp-tlog:<scope>:<log-prefix>#<stream-id>. The SDKs currently ship the c2sp-tlog binding, which verifies C2SP tiled transparency logs using a trusted log policy, witnessed checkpoints, Merkle proofs, and signed lifecycle events.
How verification uses the log
Section titled “How verification uses the log”For draft-01 identities, VerifyDomain checks that the logged ISSUANCE binds the record’s entity key and operational key with both parties’ signatures. It also checks the chain of logged key rotations to the current operational key. Verification needs a trusted reader for the record’s lr= method and a fresh ACTIVE response from su=. Missing log trust or invalid evidence fails verification.
An operation-time non-revocation check additionally requires complete history through a fresh checkpoint. The fl=logchk record flag asks relying parties to perform this check for high-value or irreversible operations. Your application decides which operations need it, including any operations covered by local policy when the flag is absent. See Enforce logchk.
Wire the log reader into verification
Section titled “Wire the log reader into verification”Choose log trust
Section titled “Choose log trust”| Setting | Use it for | How to configure it |
|---|---|---|
| DNSid-managed | Identities on DNSid’s managed development and production logs | Explicitly select the SDK’s reviewed trust catalog in code or set logTrust.managed in a deployment file. |
| Trusted profile | A deployment with an independently supplied C2SP trust profile | Supply the profile in code, a deployment file, or DNSID_LOG_TRUST_PROFILE_FILE. The profile binds one exact log scope and prefix to its policy and stream-bundle signer keys. |
| Trusted policy | DNSid Local or a deployment that distributes a C2SP tlog-policy document or its HTTPS URL | Supply trusted policy bytes, DNSID_LOG_POLICY_FILE, or DNSID_LOG_POLICY_URL. The SDK uses its bounded complete-log scanner unless separately configured with trusted bundle signer keys. |
Trust is selected by your application or deployment configuration. Obtain profile and policy locations through a channel you trust; the identity record’s lr= and files advertised by a log server do not supply trust roots. Loaded logTrust accepts exactly one of managed, profile, policyDocument, or policyUrl. An explicitly injected logRegistry takes precedence over loaded trust.
DNSid-managed logs
Section titled “DNSid-managed logs”The managed factory accepts exact canonical public references to https://log.dev.dnsid.ai and https://log.dnsid.ai using trust material embedded in the SDK release. Select this trust setting explicitly; other scopes and log prefixes fail closed.
import ( dnsid "github.com/dnsid-ai/dnsid-go" "github.com/dnsid-ai/dnsid-go/log/c2sptlog")
registry, err := c2sptlog.NewDnsidManagedVerificationRegistry(ctx, c2sptlog.DnsidManagedVerificationConfig{})if err != nil { return err }verifier, err := dnsid.NewVerifier(dnsid.WithLogRegistry(registry))if err != nil { return err }vd, err := verifier.VerifyDomain(ctx, "agent.example") // use a DNSid-enabled domain on a supported logif err != nil { return err }import { createDnsidManagedVerificationRegistry } from '@dnsid-ai/log-c2sp-tlog';import { createNodeIdentityVerifier } from '@dnsid-ai/sdk/node';
const registry = await createDnsidManagedVerificationRegistry();const idm = await createNodeIdentityVerifier({}, { logRegistry: registry });const vd = await idm.verifyDomain('agent.example'); // use a DNSid-enabled domain on a supported logfrom dnsid import IdentityManager, IdentityManagerDependenciesfrom dnsid.c2sp_tlog import create_dnsid_managed_verification_registry
registry = create_dnsid_managed_verification_registry()manager = IdentityManager(deps=IdentityManagerDependencies(log_registry=registry))vd = manager.verify_domain("agent.example") # use a DNSid-enabled domain on a supported logThese are verification-only managers; they require no local identity or signing key. Replace the example domain with an identity whose signed lr= points to one of the supported logs.
DNSid Local and configured policy trust
Section titled “DNSid Local and configured policy trust”Follow the local quickstart to publish the agent’s record and issuance event. dnsid local env exports DNSID_LOG_POLICY_URL along with the local DNS server, CA bundle, and private-host settings. Run the SDK under dnsid local run or load that environment into your shell. The environment constructors then configure the log reader and verification transport together:
import ( dnsid "github.com/dnsid-ai/dnsid-go" "github.com/dnsid-ai/dnsid-go/config")
verifier, err := config.IdentityManagerFromEnvironment(ctx, nil, dnsid.Config{}, config.Dependencies{})if err != nil { return err }vd, err := verifier.VerifyDomain(ctx, "alice.test") // use the domain assigned by DNSid Localif err != nil { return err }import { createNodeIdentityManagerFromEnvironment } from '@dnsid-ai/sdk/node';
const idm = await createNodeIdentityManagerFromEnvironment();const vd = await idm.verifyDomain('alice.test'); // use the domain assigned by DNSid Localfrom dnsid import identity_manager_from_environment
manager = identity_manager_from_environment()vd = manager.verify_domain("alice.test") # use the domain assigned by DNSid LocalFor deployments distributing trust separately, the same environment constructors accept one of DNSID_LOG_TRUST_PROFILE_FILE, DNSID_LOG_POLICY_FILE, or DNSID_LOG_POLICY_URL. A deployment file can instead contain {"logTrust":{"managed":true}}, {"logTrust":{"profile":{...}}}, or {"logTrust":{"policyUrl":"https://policy.example/dnsid-policy"}}. Supply trusted profile bytes or policy bytes directly through the generic C2SP verification factories when you need code-level options. Pass the same DNS/CA/private-host transport settings to the generic factory and the identity manager for private or test environments. Managed trust has no environment-variable selector.
Freshness, completeness, and rollback protection
Section titled “Freshness, completeness, and rollback protection”The C2SP reader checks the log signature and witness quorum on a checkpoint, proves event inclusion under its Merkle root, checks append-only consistency with previously trusted checkpoints, and verifies lifecycle signatures and stream order. An individual inclusion proof establishes that an event was logged. A current non-revocation check requires a complete stream view through a fresh accepted checkpoint.
Managed trust prefers signed per-domain stream bundles. A trusted profile with bundle signer keys enables the same bundle-first path. The SDK can use a bounded full-log scan for specified bundle availability failures or missing consistency evidence. Invalid, expired, or conflicting bundle evidence fails verification. The generic factories also provide requireStreamBundle-style options when bundle availability must be enforced. Raw scans can be expensive on large logs; reuse the registry and checkpoint store, and set limits appropriate to your deployment.
The managed factory and environment/deployment-file trust constructors use a 10-minute checkpoint freshness policy for operation-time non-revocation. When constructing a generic registry directly, set its checkpoint maximum age (CheckpointMaxAge in Go, checkpointMaxAge in TypeScript, checkpoint_freshness_ms in Python). Without one, non-revocation checks fail closed. Historical binding and key-continuity checks can use older authenticated checkpoints.
Enforce logchk for high-value operations
Section titled “Enforce logchk for high-value operations”Perform this check immediately before an operation your application classifies as high value or irreversible. In the examples, highValueOperation / high_value_operation and localPolicyRequiresLogCheck / local_policy_requires_log_check are application policy decisions. Local policy can require the check even when fl=logchk is absent. The check retrieves fresh, complete log evidence and fails if the stream is incomplete, stale, or revoked. Reverify the domain when your operation also needs a fresh su= status response; log evidence does not refresh protocol status.
vd, err := verifier.VerifyDomain(ctx, domain)if err != nil { return err }if highValueOperation && (vd.RequiresLogCheck() || localPolicyRequiresLogCheck) { evidence, err := vd.VerifyLogEvidence(ctx, time.Time{}) // current time if err != nil { return err } _ = evidence // checkpoint, completeness, and freshness boundary}const vd = await idm.verifyDomain(domain);if (highValueOperation && (vd.requiresLogCheck() || localPolicyRequiresLogCheck)) { const evidence = await vd.verifyNonRevocation(); console.log(evidence.checkpoint, evidence.freshnessTime);}vd = manager.verify_domain(domain)if high_value_operation and (vd.requires_log_check() or local_policy_requires_log_check): evidence = manager.verify_log_evidence(vd) print(evidence.checkpoint, evidence.freshness_time)The returned evidence records the verified history, completeness, checkpoint, and freshness boundary. An unavailable log, untrusted policy, failed witness quorum, incomplete history, or stale checkpoint raises a verification error; see Verification results.
Read verified history
Section titled “Read verified history”To inspect an identity’s history, load its proof-checked events and compute a snapshot at a chosen time. Snapshots represent historical logged state; use a fresh su= response for current protocol status.
domainLog, err := verifier.LoadDomainLog(ctx, vd)if err != nil { return err }snapshot, err := domainLog.SnapshotAt(time.Now())if err != nil { return err }fmt.Println(snapshot.HistoricalState, snapshot.ActiveKeyThumbprint)const history = await idm.loadDomainLog(vd);console.log(history.snapshotAt(new Date()).historicalState);from datetime import datetime, timezone
domain_log = manager.load_domain_log(vd)print(domain_log.snapshot_at(datetime.now(timezone.utc)).historical_state)All three SDKs also support offline verification of signed dnsid-c2sp-stream-bundle@v1 bundles with independently supplied policy bytes and bundle verifier keys. See the language references for VerifyStreamBundle, verifyC2spStreamBundle, and verify_c2sp_stream_bundle.
API reference
Section titled “API reference”Go lifecycle log and Go C2SP tlog · TypeScript C2SP tlog · Python transparency log.