Skip to content

Auto link opt in - #69

Merged
xzyaoi merged 6 commits into
mainfrom
auto-link-opt-in
Nov 2, 2026
Merged

xzyaoi merged 6 commits into
mainfrom
auto-link-opt-in

Conversation

@xzyaoi

@xzyaoi xzyaoi commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

xzyaoi and others added 3 commits October 13, 2026 12:14
Wallet-less nodes linked to OpenTela Cloud via a deploy key previously
published no identity attestation, so the cloud's ownership checks and
peers' trust computation saw an inconsistent record. Derive a stable
Ed25519 key from the deploy key (domain-separated SHA-256 -> seed) and
sign the identity attestation with it, so Owner == attested pubkey and
the signature verifies without a Solana wallet.

- wallet.DeriveIdentityKeyFromDeployKey: deterministic, path-independent.
- wallet.SignIdentityWithKey: sign with a raw Ed25519 key.
- protocol.deployKeyIdentity + InitializeMyself fallback.
- tests for derivation stability and consistent record.

Entire-Checkpoint: 01M4TC34XQTYJ5E62907C3BWWD
'otela init' pre-generates the libp2p identity key used by --config-dir
and the mesh-bench runner, but had no way to control it: the key was
always random, so a later 'start --seed N' just loaded that random key
and the seed had no effect.

Add --seed to 'otela init' and generate a reproducible, distinct PeerID
from a non-zero seed. To make the seed actually reproducible, the seeded
path now uses Ed25519: Go's RSA generation is deliberately non-
deterministic from a seeded reader, so the old RSA-based --seed never
produced a stable PeerID. RSA is retained for the seed=0 random path,
and existing persisted keys are always loaded unchanged.

- protocol.GenerateKeyFromSeed (Ed25519) and GenerateAndWriteKey(seed).
- newHost reuses the shared keygen instead of duplicating it.
- init_test: same seed => same key, different seed => different key.
- docs: correct the false '--seed 0 is deterministic' claim.

Entire-Checkpoint: 01M4TC3GYSW0FQSHZM0RJJE6S4
'otela start' used to re-link the node with any stored deploy key on
every boot. Same-peer re-links are free, but each new peer ID spends a
key use, so nodes that mint fresh identities (e.g. --ephemeral-identity
on Slurm) drained the key on every restart and left phantom instances.

Linking at boot now requires instance.auto_link (--auto-link /
OF_INSTANCE_AUTO_LINK=true). An explicit 'otela start --deploy-key'
still links that run. Without either, a stored key only logs a hint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVobFYfzE6YvveLwKteU
Entire-Checkpoint: 01M6E8V0Q98CKK4XRXFRJYYWCE
Copilot AI balanced review requested due to automatic review settings November 2, 2026 14:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

robmsmt and others added 2 commits November 2, 2026 15:10
… reservation (#67)

* fix(protocol): worker connectivity watchdog retries bootstrap + relay reservation

A worker is only routable from the head if it holds a bootstrap connection
and a live relay reservation. Both were attempted once at startup (the
reservation 10 s after the CRDT store starts); if that raced the network,
the node stayed locally healthy but unreachable. Recovery relied on
Reconnect() firing with 50% probability per minute, and the auto-reconnect
loop only acts when there are zero connections. All failures logged at Debug,
so nothing was visible.

Add a watchdog (workers only) that, until both conditions hold, retries the
bootstrap dial and relay reservation with 5s..60s jittered backoff, and logs
state transitions at Info/Warn. Track reservation expiry so a lapsed
reservation is re-made. Export IsBootstrapConnected/HasRelayReservation.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XjjN5e5xxxaFYKQcW51ytb

* fix(protocol): make connectivity watchdog checks cheap and tie reservations to the advertised relay

Review follow-ups for the worker connectivity watchdog:

- Cache resolved bootstrap peers. Health checks are now in-memory reads;
  discovery (HTTP/DNS) runs only on refresh, reconnect, or when the cache
  is older than 10 minutes. An empty or failed resolution keeps the last
  known set, so a discovery outage no longer marks a connected node as
  disconnected.
- Parse bootstrap multiaddrs one by one, skipping entries without a
  /p2p/<id> component instead of failing the whole batch.
- Track reservations per relay peer and drop them when the last
  connection to that relay closes. "Relay reserved" now means the
  RelayPeer advertised in the CRDT is connected and holds an unexpired
  reservation, or AutoRelay advertises a circuit address through it.
- Keep the advertised relay stable while it is still valid; otherwise
  prefer a freshly reserved bootstrap peer.
- Guard MakeRelayReservations against overlapping runs from startup,
  Reconnect() and the watchdog.
- Start the watchdog under the same condition as AutoRelay, and not in
  standalone mode. With no bootstrap peers resolved, log once and back
  off without making reservations.
- Tests restore the package-global state they touch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVoeKQvu4rZ1PqgzEWKv
Entire-Checkpoint: 01M6E5X1BDH1J2XKKHPEPX3D1G

* fix(protocol): reserve on relay-capable peers in parallel; add docker NAT mesh test

MakeRelayReservations tried every connected peer serially with a 10 s
timeout each, so one watchdog step could block for minutes. Every node
runs a relay service, so it also reserved on other NATed workers, which
heads cannot route through (AutoRelay already covers worker-to-worker
circuits).

- Reserve only on bootstrap peers and peers the node table marks as
  relay/head or with a public address; fall back to all connected peers
  when none qualifies.
- Run reservations in parallel (at most 8 in flight, 10 s timeout each).
  Successes are returned in candidate order, so pickAdvertisedRelay's
  preference is unchanged.

Add TestRelayWatchdogMesh (integration tag): two isolated docker bridge
networks simulate a public network and an HPC private network, so the
head can reach workers only through the relay. It covers a baseline
worker, a worker started while the relay is unreachable, and a relay
restart while the workers stay connected to each other.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVoeKQvu4rZ1PqgzEWKv
Entire-Checkpoint: 01M6E6QF8VP2TPTQ0EE3FE7J09

* test(integration): check the response body in the relay mesh routability probe

The p2p forward error handler writes "ERROR: ..." with status 200, so a
status check alone treated failed forwards as success. Require the
worker's {"status":"ok"} health body.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVoeKQvu4rZ1PqgzEWKv
Entire-Checkpoint: 01M6E7G9T32HJGVCJNDW5DEJPM

* fix(server): report failed p2p forwards as 502/504 instead of 200

ErrorHandler wrote "ERROR: <reason>" without setting a status, so the
response went out as 200. Clients and health checks took failed
forwards for success. A relay that could not reach a worker also
answered the head with 200, and the head passed that body to the
client as a successful response.

- ErrorHandler now responds 504 on deadline errors and 502 otherwise.
  The body keeps the "ERROR: <reason>" text. Responses carry
  X-Otela-Proxy-Error: 1 to mark them as generated by the proxy.
- The service-forward retry path reuses ErrorHandler.
- On a relay hop, the head treats a marked response from the relay as
  a transport failure and retries another worker. An unmarked 5xx from
  the worker's own service is still passed through.
- The docker NAT mesh test asserts that a forward to an unreachable
  peer returns a marked 5xx.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVoeKQvu4rZ1PqgzEWKv
Entire-Checkpoint: 01M6E7XGGN2KSSE0GY9YX8RBD7

* test(integration): exercise the relay v2 circuit path in the NAT mesh test

The pub network used an RFC 1918 subnet. AutoRelay drops a relay's
private addresses when building circuit addresses, so workers
advertised no /p2p-circuit address. The head could never dial them
directly, and the test only covered the HTTP relay hop, which does not
depend on reservations. Code from before this PR passed the test.

- Use 11.213.10.0/24, which libp2p treats as public, for the pub
  network.
- Require both the relay hop and a direct circuit dial from the head
  in every scenario.

With this change, code from before the PR fails the relay-restart
scenario in 2 of 2 runs: the relay hop recovers, but the circuit dial
fails for 90 s. This PR passes all scenarios in 3 of 3 runs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVoeKQvu4rZ1PqgzEWKv
Entire-Checkpoint: 01M6E99Z6NMQVKN8SQNBJWWMXN

---------

Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com>
Co-authored-by: Xiaozhe Yao <askxzyao@gmail.com>
)

* start: --ephemeral-identity and --datadir for nodes sharing a $HOME

Nodes that share one home directory (e.g. the nodes of a multi-node Slurm
job on a shared filesystem) all load the same ~/.config/opentela/keys/id and
announce the same peer ID; --seed does not help, since a seed is only used
when no key file exists yet. They also all write their peer databases to
~/.ocfcore, which fills the home quota when nodes are killed before they can
clean up.

- --ephemeral-identity: the node uses an in-memory identity generated once
  per process; no key file is read or written. Overrides --seed. The
  instance link (deploy key) signs with the same in-memory key, so the linked
  peer is the one that serves. Warns when used without --datadir.
- --datadir (or OF_DATADIR): the existing datadir setting (usage store) now
  also moves the peer database to <datadir>/ocfcore. Unset keeps ~/.ocfcore.

Neither flag is bound with viper.BindPFlag: bound keys are written into the
cfg.yaml seeded on first run, so a one-off --ephemeral-identity or temporary
--datadir would stick to every later start. initConfig applies them per run,
like --seed.

Identity selection moves out of newHost into loadOrCreateIdentity so it can
be unit-tested without starting a libp2p host.

* start: skip bootAccount for --component ingress

An ingress-only process never brings up a libp2p host, so linking its
identity (especially an ephemeral one) only spends deploy-key uses and
leaves phantom instances in the console.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVobFYfzE6YvveLwKteU
Entire-Checkpoint: 01M6E8BSW3HH9JZF5S51EM9B6V

* ephemeral-identity: one identity resolver, env form, temp datadir

Review follow-ups for --ephemeral-identity / --datadir:

- protocol.NodeIdentity(seed) is now the single resolver for both the
  libp2p host and nodeLinkSigner, so linking and serving cannot drift
  (nodeLinkSigner previously re-implemented the selection and ignored
  the seed). ConfiguredSeed() shares the seed parsing.
- One newKey helper for persisted, seeded and ephemeral keys.
- OF_EPHEMERAL_IDENTITY enables the flag; the hyphenated viper key was
  unreachable via AutomaticEnv. Bound after the first-run cfg.yaml seed,
  so it never persists.
- With --ephemeral-identity and no --datadir, node data goes to a
  per-process temp dir instead of piling up in the shared ~/.ocfcore.
- datadir expands a leading ~ (common.DataDir), for both the peer
  database and the usage store.
- `otela peer-id` warns on stderr when ephemeral identity is enabled.
- Drop the dead connection-manager error branch in newHost.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVobFYfzE6YvveLwKteU
Entire-Checkpoint: 01M6E8Q1ECER7DRR2Q2HTF3CZD

* instance link: refuse seeded and ephemeral identities

- nodeLinkSigner refuses a seeded identity: its key is derivable from a
  small integer, so linking it would let anyone who guesses the seed
  sign as an account-linked peer. Seeds stay for tests and benchmarks.
- 'otela instance link' refuses when OF_EPHEMERAL_IDENTITY is set: the
  identity dies with the command, so the link would spend a deploy-key
  use on a peer that never comes online. Boot-time links by the serving
  node are unaffected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVobFYfzE6YvveLwKteU
Entire-Checkpoint: 01M6E8Z0MWVH1H60DHPYH383PN

---------

Co-authored-by: Xiaozhe Yao <askxzyao@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Test Coverage Report 📊

Click to view detailed coverage
opentela/entry/cmd/boot.go:43:					bootInstanceLink			80.0%
opentela/entry/cmd/boot.go:75:					bootAccount				72.1%
opentela/entry/cmd/init.go:22:					ensureLibp2pKey				85.7%
opentela/entry/cmd/init.go:147:					writeDefaultConfig			0.0%
opentela/entry/cmd/instance_link.go:65:				nodeLinkSigner				81.0%
opentela/entry/cmd/instance_link.go:105:			resolveAPIBaseURL			66.7%
opentela/entry/cmd/instance_link.go:117:			resolveDeployKey			100.0%
opentela/entry/cmd/instance_link.go:124:			runInstanceLink				82.8%
opentela/entry/cmd/instance_link.go:182:			peerIDFromPriv				75.0%
opentela/entry/cmd/instance_link.go:192:			explainInstanceLinkError		44.4%
opentela/entry/cmd/instance_link.go:215:			init					100.0%
opentela/entry/cmd/probe.go:77:					init					100.0%
opentela/entry/cmd/root.go:38:					init					98.0%
opentela/entry/cmd/root.go:105:					configFilePath				85.7%
opentela/entry/cmd/root.go:120:					initConfig				88.7%
opentela/entry/cmd/root.go:332:					Execute					0.0%
opentela/entry/cmd/start.go:68:					useEphemeralDatadir			75.0%
opentela/entry/cmd/start.go:81:					init					100.0%
opentela/entry/cmd/update.go:13:				doUpdate				0.0%
opentela/entry/cmd/wallet.go:234:				runWalletBalance			0.0%
opentela/entry/cmd/wallet.go:289:				addWalletBalanceFlags			100.0%
opentela/entry/cmd/wallet.go:412:				init					100.0%
opentela/entry/cmd/wallet_link.go:57:				runWalletLink				0.0%
opentela/entry/cmd/wallet_link.go:109:				obtainJWT				0.0%
opentela/entry/cmd/wallet_link.go:141:				promptPassword				0.0%
opentela/entry/cmd/wallet_link.go:159:				explainLinkError			0.0%
opentela/entry/cmd/wallet_link.go:183:				explainSignInError			0.0%
opentela/entry/cmd/wallet_link.go:197:				init					100.0%
opentela/entry/main.go:18:					main					0.0%
opentela/internal/account/link.go:59:				Error					0.0%
opentela/internal/account/link.go:81:				httpClient				100.0%
opentela/internal/account/link.go:90:				doJSON					82.8%
opentela/internal/account/link.go:143:				LinkWallet				90.0%
opentela/internal/account/link.go:209:				LinkInstance				82.4%
opentela/internal/account/link.go:249:				SignInEmail				74.5%
opentela/internal/account/resolve.go:27:			UnmarshalJSON				93.3%
opentela/internal/account/resolve.go:71:			GetAccount				100.0%
opentela/internal/account/resolve.go:88:			HasWallet				100.0%
opentela/internal/account/resolve.go:120:			GetBilling				85.7%
opentela/internal/analytics/aggregator.go:89:			newAggregator				100.0%
opentela/internal/analytics/aggregator.go:98:			add					94.7%
opentela/internal/analytics/aggregator.go:134:			flush					100.0%
opentela/internal/analytics/config.go:19:			Normalize				100.0%
opentela/internal/analytics/recorder.go:26:			New					100.0%
opentela/internal/analytics/recorder.go:41:			run					87.5%
opentela/internal/analytics/recorder.go:58:			Begin					100.0%
opentela/internal/analytics/recorder.go:71:			End					100.0%
opentela/internal/analytics/recorder.go:84:			Observe					100.0%
opentela/internal/analytics/recorder.go:96:			FlushNow				0.0%
opentela/internal/analytics/recorder.go:104:			flushNow				85.7%
opentela/internal/analytics/recorder.go:118:			Stop					100.0%
opentela/internal/analytics/reservoir.go:18:			newReservoir				66.7%
opentela/internal/analytics/reservoir.go:25:			add					100.0%
opentela/internal/analytics/reservoir.go:37:			len					100.0%
opentela/internal/analytics/reservoir.go:39:			mean					100.0%
opentela/internal/analytics/reservoir.go:52:			percentile				83.3%
opentela/internal/analytics/rollup.go:6:			ratio					100.0%
opentela/internal/analytics/rollup.go:13:			perSecond				66.7%
opentela/internal/analytics/rollup.go:22:			buildEvent				100.0%
opentela/internal/analytics/sink.go:32:				Enqueue					100.0%
opentela/internal/analytics/sink.go:38:				Close					0.0%
opentela/internal/analytics/sink.go:40:				Snapshot				100.0%
opentela/internal/analytics/sink.go:51:				Enqueue					0.0%
opentela/internal/analytics/sink.go:52:				Close					0.0%
opentela/internal/analytics/sink.go:59:				NewPostHogSink				33.3%
opentela/internal/analytics/sink.go:75:				Enqueue					0.0%
opentela/internal/analytics/sink.go:93:				Close					0.0%
opentela/internal/analytics/usage_parse.go:16:			ParseUsage				100.0%
opentela/internal/attestation/attestation.go:66:		configuredPubKeyHexes			100.0%
opentela/internal/attestation/attestation.go:87:		trustedPubKeys				85.0%
opentela/internal/attestation/attestation.go:123:		attestationMessage			100.0%
opentela/internal/attestation/attestation.go:130:		Verify					92.3%
opentela/internal/attestation/attestation.go:156:		Sign					100.0%
opentela/internal/attestation/cmd/buildsign/main.go:22:		main					0.0%
opentela/internal/attestation/cmd/buildsign/main.go:39:		keygen					0.0%
opentela/internal/attestation/cmd/buildsign/main.go:51:		sign					0.0%
opentela/internal/common/constants.go:13:			DataDir					66.7%
opentela/internal/common/constants.go:25:			GetHomePath				71.4%
opentela/internal/common/constants.go:47:			GetDBPath				100.0%
opentela/internal/common/filesystem.go:7:			RemoveDir				100.0%
opentela/internal/common/logger.go:11:				init					100.0%
opentela/internal/common/logger.go:15:				InitLogger				48.0%
opentela/internal/common/logger.go:61:				ReportError				50.0%
opentela/internal/common/process/manager.go:13:			NewProcessManager			100.0%
opentela/internal/common/process/manager.go:20:			StartProcess				0.0%
opentela/internal/common/process/manager.go:27:			StopAllProcesses			0.0%
opentela/internal/common/process/manager.go:33:			StartCriticalProcess			57.1%
opentela/internal/common/process/manager.go:44:			HealthCheck				50.0%
opentela/internal/common/process/process.go:36:			NewProcess				100.0%
opentela/internal/common/process/process.go:63:			Start					94.4%
opentela/internal/common/process/process.go:93:			SetTimeout				66.7%
opentela/internal/common/process/process.go:101:		Wait					100.0%
opentela/internal/common/process/process.go:105:		awaitOutput				100.0%
opentela/internal/common/process/process.go:111:		Kill					100.0%
opentela/internal/common/process/process.go:120:		OpenInputStream				71.4%
opentela/internal/common/process/process.go:133:		StreamOutput				77.8%
opentela/internal/common/process/process.go:151:		finishTimeOutOrDie			87.5%
opentela/internal/common/process/process.go:169:		cleanup					100.0%
opentela/internal/common/process/process.go:181:		isRunning				0.0%
opentela/internal/common/requests.go:12:			RemoteGET				52.6%
opentela/internal/common/serialization.go:5:			DictionaryToBytes			100.0%
opentela/internal/common/utils.go:3:				DeduplicateStrings			100.0%
opentela/internal/ingest/server.go:40:				Run					0.0%
opentela/internal/ingest/server.go:70:				collectStats				0.0%
opentela/internal/metrics/collector.go:20:			NewAggregatedCollector			100.0%
opentela/internal/metrics/collector.go:38:			Describe				0.0%
opentela/internal/metrics/collector.go:42:			Collect					88.9%
opentela/internal/metrics/collector.go:58:			SetNetworkStats				100.0%
opentela/internal/metrics/collector.go:63:			SetScraperTargets			100.0%
opentela/internal/metrics/collector.go:67:			metricFromDTO				91.7%
opentela/internal/metrics/peer_provider.go:15:			GetScrapablePeers			0.0%
opentela/internal/metrics/peer_provider.go:42:			extractServices				100.0%
opentela/internal/metrics/peer_provider.go:57:			buildPeerLabels				100.0%
opentela/internal/metrics/relabeler.go:12:			Relabel					100.0%
opentela/internal/metrics/relabeler.go:53:			sanitizeMetricName			75.0%
opentela/internal/metrics/scraper.go:54:			NewMetricsScraper			100.0%
opentela/internal/metrics/scraper.go:83:			Start					0.0%
opentela/internal/metrics/scraper.go:99:			Stop					0.0%
opentela/internal/metrics/scraper.go:103:			GetCachedMetrics			100.0%
opentela/internal/metrics/scraper.go:114:			GetSelfMetrics				0.0%
opentela/internal/metrics/scraper.go:118:			scrapeAll				100.0%
opentela/internal/metrics/scraper.go:145:			scrapePeer				72.7%
opentela/internal/metrics/scraper.go:166:			scrapeTarget				84.6%
opentela/internal/metrics/scraper.go:189:			parseMetrics				84.6%
opentela/internal/metrics/scraper.go:210:			evictStale				85.7%
opentela/internal/platform/gpu.go:10:				GetGPUInfo				75.0%
opentela/internal/platform/gpu.go:18:				getNvidiaGPUs				26.3%
opentela/internal/platform/gpu.go:48:				getAMDGPUs				12.5%
opentela/internal/platform/gpu.go:117:				csvField				100.0%
opentela/internal/platform/slurm/env.go:10:			IsSlurm					100.0%
opentela/internal/platform/slurm/env.go:14:			getJobId				100.0%
opentela/internal/platform/slurm/env.go:18:			getNodeId				100.0%
opentela/internal/platform/slurm/env.go:22:			getRemainingTimeInSeconds		44.4%
opentela/internal/platform/slurm/env.go:43:			GetJobInfo				100.0%
opentela/internal/protocol/bootstrap.go:17:			getDefaultBootstrapPeers		77.8%
opentela/internal/protocol/bootstrap.go:49:			collectBootstrapSources			100.0%
opentela/internal/protocol/bootstrap.go:89:			resolveBootstrapSources			90.0%
opentela/internal/protocol/bootstrap.go:106:			resolveBootstrapSource			85.7%
opentela/internal/protocol/bootstrap.go:122:			fetchHTTPBootstraps			80.0%
opentela/internal/protocol/bootstrap.go:138:			fetchDNSAddrBootstraps			77.8%
opentela/internal/protocol/bootstrap.go:165:			expandBootstrapValue			54.5%
opentela/internal/protocol/bootstrap.go:185:			splitBootstrapValue			100.0%
opentela/internal/protocol/bootstrap.go:192:			parseBootstrapMultiaddrs		75.0%
opentela/internal/protocol/clock.go:21:				StartTicker				0.0%
opentela/internal/protocol/connectivity.go:54:			parseBootstrapAddrInfos			100.0%
opentela/internal/protocol/connectivity.go:75:			refresh					87.5%
opentela/internal/protocol/connectivity.go:90:			refreshIfStale				0.0%
opentela/internal/protocol/connectivity.go:99:			list					0.0%
opentela/internal/protocol/connectivity.go:109:			contains				100.0%
opentela/internal/protocol/connectivity.go:116:			empty					100.0%
opentela/internal/protocol/connectivity.go:124:			connected				100.0%
opentela/internal/protocol/connectivity.go:137:			IsBootstrapConnected			0.0%
opentela/internal/protocol/connectivity.go:159:			recordRelayReservation			100.0%
opentela/internal/protocol/connectivity.go:170:			forgetRelayReservation			100.0%
opentela/internal/protocol/connectivity.go:178:			setAutoRelayAddrs			100.0%
opentela/internal/protocol/connectivity.go:192:			circuitRelayPeer			80.0%
opentela/internal/protocol/connectivity.go:211:			relayValid				100.0%
opentela/internal/protocol/connectivity.go:225:			advertisedRelayValid			100.0%
opentela/internal/protocol/connectivity.go:235:			HasRelayReservation			0.0%
opentela/internal/protocol/connectivity.go:245:			watchAutoRelayAddrs			0.0%
opentela/internal/protocol/connectivity.go:278:			connectivityWatchdogEnabled		100.0%
opentela/internal/protocol/connectivity.go:302:			step					100.0%
opentela/internal/protocol/connectivity.go:341:			startConnectivityWatchdog		0.0%
opentela/internal/protocol/crdt.go:35:				GetCRDTStore				0.0%
opentela/internal/protocol/crdt.go:215:				Reconnect				0.0%
opentela/internal/protocol/crdt.go:233:				TriggerResync				0.0%
opentela/internal/protocol/crdt.go:240:				ClearCRDTStore				0.0%
opentela/internal/protocol/deploykey.go:15:			DeployKeyPath				33.3%
opentela/internal/protocol/deploykey.go:29:			StoreDeployKey				66.7%
opentela/internal/protocol/deploykey.go:43:			LoadDeployKey				85.7%
opentela/internal/protocol/go-ds-crdt/autoban.go:52:		newAutoBan				100.0%
opentela/internal/protocol/go-ds-crdt/autoban.go:65:		bannedKey				100.0%
opentela/internal/protocol/go-ds-crdt/autoban.go:70:		loadFromStore				60.0%
opentela/internal/protocol/go-ds-crdt/autoban.go:94:		isBanned				100.0%
opentela/internal/protocol/go-ds-crdt/autoban.go:107:		recordFailure				84.6%
opentela/internal/protocol/go-ds-crdt/autoban.go:148:		clearFailure				100.0%
opentela/internal/protocol/go-ds-crdt/compaction.go:16:		decodeTombstoneTimestamp		0.0%
opentela/internal/protocol/go-ds-crdt/compaction.go:32:		CompactTombstones			0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:123:		verify					52.6%
opentela/internal/protocol/go-ds-crdt/crdt.go:164:		DefaultOptions				100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:257:		New					69.3%
opentela/internal/protocol/go-ds-crdt/crdt.go:403:		handleNext				79.2%
opentela/internal/protocol/go-ds-crdt/crdt.go:518:		decodeBroadcast				61.1%
opentela/internal/protocol/go-ds-crdt/crdt.go:549:		encodeBroadcast				100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:558:		randomizeInterval			100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:567:		rebroadcast				87.5%
opentela/internal/protocol/go-ds-crdt/crdt.go:584:		repair					60.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:613:		RebroadcastHeads			0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:629:		rebroadcastHeads			80.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:666:		logStats				55.6%
opentela/internal/protocol/go-ds-crdt/crdt.go:692:		handleBlock				90.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:715:		handleBranch				88.9%
opentela/internal/protocol/go-ds-crdt/crdt.go:733:		dagWorker				52.9%
opentela/internal/protocol/go-ds-crdt/crdt.go:773:		sendNewJobs				76.3%
opentela/internal/protocol/go-ds-crdt/crdt.go:858:		sendJobWorker				85.7%
opentela/internal/protocol/go-ds-crdt/crdt.go:874:		processedBlockKey			100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:878:		isProcessed				100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:882:		markProcessed				100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:886:		dirtyKey				100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:891:		MarkDirty				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:900:		IsDirty					75.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:909:		MarkClean				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:919:		processNode				64.6%
opentela/internal/protocol/go-ds-crdt/crdt.go:1042:		repairDAG				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1163:		Repair					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1169:		Get					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1177:		Has					100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1184:		GetSize					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1199:		Query					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1208:		Put					100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1214:		Delete					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1228:		Sync					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1272:		Context					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1277:		Close					80.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1289:		Batch					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1293:		deltaMerge				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1306:		addToDelta				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1312:		rmvToDelta				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1323:		updateDeltaWithRemove			0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1345:		updateDelta				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1356:		publishDelta				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1367:		putBlock				81.8%
opentela/internal/protocol/go-ds-crdt/crdt.go:1386:		publish					66.7%
opentela/internal/protocol/go-ds-crdt/crdt.go:1398:		addDAGNode				68.8%
opentela/internal/protocol/go-ds-crdt/crdt.go:1440:		broadcast				71.4%
opentela/internal/protocol/go-ds-crdt/crdt.go:1474:		Put					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1486:		Delete					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1500:		Commit					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1506:		PrintDAG				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1525:		printDAGRec				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1586:		DotDAG					0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1614:		dotDAGRec				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1667:		InternalStats				0.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1682:		newCidSafeSet				100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1688:		Visit					100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1701:		Remove					100.0%
opentela/internal/protocol/go-ds-crdt/crdt.go:1709:		Has					0.0%
opentela/internal/protocol/go-ds-crdt/heads.go:29:		newHeads				75.0%
opentela/internal/protocol/go-ds-crdt/heads.go:42:		key					100.0%
opentela/internal/protocol/go-ds-crdt/heads.go:47:		write					80.0%
opentela/internal/protocol/go-ds-crdt/heads.go:56:		delete					75.0%
opentela/internal/protocol/go-ds-crdt/heads.go:68:		IsHead					100.0%
opentela/internal/protocol/go-ds-crdt/heads.go:79:		Len					100.0%
opentela/internal/protocol/go-ds-crdt/heads.go:90:		Replace					77.8%
opentela/internal/protocol/go-ds-crdt/heads.go:134:		Add					87.5%
opentela/internal/protocol/go-ds-crdt/heads.go:149:		List					80.0%
opentela/internal/protocol/go-ds-crdt/heads.go:176:		primeCache				35.3%
opentela/internal/protocol/go-ds-crdt/ipld.go:23:		GetDelta				100.0%
opentela/internal/protocol/go-ds-crdt/ipld.go:33:		GetPriority				100.0%
opentela/internal/protocol/go-ds-crdt/ipld.go:48:		GetDeltas				71.4%
opentela/internal/protocol/go-ds-crdt/ipld.go:72:		extractDelta				83.3%
opentela/internal/protocol/go-ds-crdt/ipld.go:82:		makeNode				78.6%
opentela/internal/protocol/go-ds-crdt/migrations.go:18:		versionKey				100.0%
opentela/internal/protocol/go-ds-crdt/migrations.go:22:		getVersion				50.0%
opentela/internal/protocol/go-ds-crdt/migrations.go:39:		setVersion				83.3%
opentela/internal/protocol/go-ds-crdt/migrations.go:50:		applyMigrations				71.4%
opentela/internal/protocol/go-ds-crdt/migrations.go:81:		migrate0to1				46.7%
opentela/internal/protocol/go-ds-crdt/pubsub_broadcaster.go:28:	NewPubSubBroadcaster			0.0%
opentela/internal/protocol/go-ds-crdt/pubsub_broadcaster.go:60:	Broadcast				0.0%
opentela/internal/protocol/go-ds-crdt/pubsub_broadcaster.go:65:	Next					0.0%
opentela/internal/protocol/go-ds-crdt/set.go:50:		newCRDTSet				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:73:		Add					100.0%
opentela/internal/protocol/go-ds-crdt/set.go:86:		Rmv					0.0%
opentela/internal/protocol/go-ds-crdt/set.go:133:		Element					0.0%
opentela/internal/protocol/go-ds-crdt/set.go:150:		Elements				0.0%
opentela/internal/protocol/go-ds-crdt/set.go:251:		InSet					100.0%
opentela/internal/protocol/go-ds-crdt/set.go:259:		keyPrefix				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:264:		elemsPrefix				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:269:		tombsPrefix				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:274:		valueKey				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:279:		priorityKey				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:283:		getPriority				80.0%
opentela/internal/protocol/go-ds-crdt/set.go:300:		setPriority				83.3%
opentela/internal/protocol/go-ds-crdt/set.go:313:		setValue				76.2%
opentela/internal/protocol/go-ds-crdt/set.go:359:		findBestValue				0.0%
opentela/internal/protocol/go-ds-crdt/set.go:464:		putElems				80.8%
opentela/internal/protocol/go-ds-crdt/set.go:510:		putTombs				5.0%
opentela/internal/protocol/go-ds-crdt/set.go:584:		Merge					75.0%
opentela/internal/protocol/go-ds-crdt/set.go:599:		inTombsKeyID				100.0%
opentela/internal/protocol/go-ds-crdt/set.go:620:		datastoreSync				0.0%
opentela/internal/protocol/host.go:65:				GetP2PNode				0.0%
opentela/internal/protocol/host.go:88:				registerPingProtocol			100.0%
opentela/internal/protocol/host.go:94:				ConfiguredSeed				0.0%
opentela/internal/protocol/host.go:111:				NodeIdentity				60.9%
opentela/internal/protocol/host.go:152:				newHost					0.0%
opentela/internal/protocol/host.go:394:				StartAutoReconnect			0.0%
opentela/internal/protocol/host.go:405:				startAutoReconnect			0.0%
opentela/internal/protocol/host.go:458:				tryReconnectToBootstraps		0.0%
opentela/internal/protocol/host.go:506:				waitFor					100.0%
opentela/internal/protocol/host.go:522:				backoffDelay				77.8%
opentela/internal/protocol/host.go:538:				backoffBaseDelay			90.0%
opentela/internal/protocol/host.go:558:				isTransientNetworkError			87.5%
opentela/internal/protocol/host.go:575:				bigWindowYamuxMuxer			0.0%
opentela/internal/protocol/host.go:585:				relayServiceResources			0.0%
opentela/internal/protocol/host.go:594:				newResourceManager			0.0%
opentela/internal/protocol/host.go:608:				newDHT					0.0%
opentela/internal/protocol/host.go:622:				ConnectedPeers				0.0%
opentela/internal/protocol/host.go:637:				AllPeers				0.0%
opentela/internal/protocol/host.go:651:				BuildBootstrapAddr			85.7%
opentela/internal/protocol/host.go:663:				buildPublicTCPMultiaddr			66.7%
opentela/internal/protocol/host.go:676:				publicAddrHostAndProtocol		78.6%
opentela/internal/protocol/host.go:702:				appendUniqueMultiaddrs			88.2%
opentela/internal/protocol/host.go:734:				isRecentRelayPeer			100.0%
opentela/internal/protocol/host.go:743:				ConnectedBootstraps			0.0%
opentela/internal/protocol/host.go:788:				MakeRelayReservations			0.0%
opentela/internal/protocol/host.go:831:				isRelayCapablePeer			0.0%
opentela/internal/protocol/host.go:853:				relayCandidates				90.0%
opentela/internal/protocol/host.go:872:				reserveOnRelays				100.0%
opentela/internal/protocol/host.go:909:				pickAdvertisedRelay			100.0%
opentela/internal/protocol/host.go:927:				TryHolePunch				0.0%
opentela/internal/protocol/host.go:941:				ConnectednessOf				0.0%
opentela/internal/protocol/host.go:955:				IsDirectlyConnected			0.0%
opentela/internal/protocol/host.go:967:				IsTrustedDirectConn			100.0%
opentela/internal/protocol/host.go:979:				HasTrustedDirectConnection		0.0%
opentela/internal/protocol/host.go:1000:			FindRelayFor				0.0%
opentela/internal/protocol/host.go:1037:			GetResourceManagerStats			0.0%
opentela/internal/protocol/key.go:19:				ResolveKeyPath				83.3%
opentela/internal/protocol/key.go:33:				WriteKeyToFile				50.0%
opentela/internal/protocol/key.go:62:				LoadKeyFromFile				76.9%
opentela/internal/protocol/key.go:92:				GenerateKeyFromSeed			0.0%
opentela/internal/protocol/key.go:107:				GenerateAndWriteKey			77.8%
opentela/internal/protocol/key.go:125:				newKey					100.0%
opentela/internal/protocol/key.go:150:				EphemeralKey				87.5%
opentela/internal/protocol/liveness.go:48:			String					0.0%
opentela/internal/protocol/liveness.go:73:			classifyProbeError			100.0%
opentela/internal/protocol/liveness.go:99:			ProbePeerLiveness			0.0%
opentela/internal/protocol/liveness.go:193:			selfRelayVerdict			100.0%
opentela/internal/protocol/liveness.go:203:			relayDialAddr				0.0%
opentela/internal/protocol/liveness.go:237:			probeUnreachableServicePeers		0.0%
opentela/internal/protocol/liveness.go:317:			publishEviction				0.0%
opentela/internal/protocol/liveness.go:353:			mayPublishEviction			100.0%
opentela/internal/protocol/liveness.go:367:			livenessEnforced			0.0%
opentela/internal/protocol/node_table.go:36:			InitScalableNodeTable			0.0%
opentela/internal/protocol/node_table.go:44:			GetScalableSnapshot			0.0%
opentela/internal/protocol/node_table.go:51:			GetNodeTableWriter			0.0%
opentela/internal/protocol/node_table.go:57:			StartSWIM				0.0%
opentela/internal/protocol/node_table.go:231:			deployKeyIdentity			66.7%
opentela/internal/protocol/node_table.go:251:			parseLabels				0.0%
opentela/internal/protocol/node_table.go:283:			getNodeTable				100.0%
opentela/internal/protocol/node_table.go:290:			UpdateNodeTable				0.0%
opentela/internal/protocol/node_table.go:326:			MarkSelfAsBootstrap			0.0%
opentela/internal/protocol/node_table.go:353:			AnnounceLeave				0.0%
opentela/internal/protocol/node_table.go:381:			UpdateNodeTableHook			71.4%
opentela/internal/protocol/node_table.go:497:			DeleteNodeTableHook			100.0%
opentela/internal/protocol/node_table.go:515:			DeletePeerRow				75.0%
opentela/internal/protocol/node_table.go:542:			GetPeerFromTable			100.0%
opentela/internal/protocol/node_table.go:553:			GetConnectedPeers			0.0%
opentela/internal/protocol/node_table.go:565:			GetAllPeers				100.0%
opentela/internal/protocol/node_table.go:575:			GetService				0.0%
opentela/internal/protocol/node_table.go:596:			LocalServiceNameCounts			0.0%
opentela/internal/protocol/node_table.go:600:			LocalServicesByName			0.0%
opentela/internal/protocol/node_table.go:611:			GetAllProviders				0.0%
opentela/internal/protocol/node_table.go:639:			InitializeMyself			0.0%
opentela/internal/protocol/node_table.go:752:			GetSelf					100.0%
opentela/internal/protocol/node_table.go:759:			SetMyselfRelayPeer			0.0%
opentela/internal/protocol/node_table.go:767:			SetMyselfForTest			100.0%
opentela/internal/protocol/node_table.go:775:			RegisterRemotePeer			0.0%
opentela/internal/protocol/node_table.go:789:			runtimeCapabilities			0.0%
opentela/internal/protocol/node_table.go:793:			serviceNameCounts			0.0%
opentela/internal/protocol/node_table.go:804:			applyLocalRuntimeMetadata		0.0%
opentela/internal/protocol/node_table.go:815:			isKnownHeadPeer				100.0%
opentela/internal/protocol/nodetable/snapshot.go:55:		NewNodeTable				100.0%
opentela/internal/protocol/nodetable/snapshot.go:62:		Snapshot				100.0%
opentela/internal/protocol/nodetable/snapshot.go:67:		Store					100.0%
opentela/internal/protocol/nodetable/snapshot.go:72:		NewSnapshot				100.0%
opentela/internal/protocol/nodetable/snapshot.go:84:		Clone					100.0%
opentela/internal/protocol/nodetable/snapshot.go:100:		ApplyEvent				71.7%
opentela/internal/protocol/nodetable/snapshot.go:187:		RebuildIndexes				91.7%
opentela/internal/protocol/nodetable/writer.go:33:		init					100.0%
opentela/internal/protocol/nodetable/writer.go:52:		NewWriter				100.0%
opentela/internal/protocol/nodetable/writer.go:60:		Start					100.0%
opentela/internal/protocol/nodetable/writer.go:65:		Stop					100.0%
opentela/internal/protocol/nodetable/writer.go:71:		Send					100.0%
opentela/internal/protocol/nodetable/writer.go:79:		run					100.0%
opentela/internal/protocol/nodetable/writer.go:109:		drainAndApply				66.7%
opentela/internal/protocol/nodetable/writer.go:123:		applyBatch				100.0%
opentela/internal/protocol/registrar.go:26:			addLocalService				100.0%
opentela/internal/protocol/registrar.go:55:			snapshotLocalServices			100.0%
opentela/internal/protocol/registrar.go:65:			hasLocalServices			0.0%
opentela/internal/protocol/registrar.go:71:			RegisterLocalServices			0.0%
opentela/internal/protocol/registrar.go:113:			RegisterAdHocService			0.0%
opentela/internal/protocol/registrar.go:124:			normalizeHealthPath			100.0%
opentela/internal/protocol/registrar.go:135:			healthCheckRemote			62.5%
opentela/internal/protocol/registrar.go:160:			registerLLMService			0.0%
opentela/internal/protocol/registrar.go:205:			provideService				0.0%
opentela/internal/protocol/registrar.go:231:			ResetLocalServicesForTest		0.0%
opentela/internal/protocol/registrar.go:238:			SetLocalServicesForTest			0.0%
opentela/internal/protocol/registrar.go:247:			ReannounceLocalServices			0.0%
opentela/internal/protocol/service_health.go:29:		String					0.0%
opentela/internal/protocol/service_health.go:50:		observe					100.0%
opentela/internal/protocol/service_health.go:70:		serviceKey				100.0%
opentela/internal/protocol/service_health.go:81:		mergeAdvertisedServices			94.1%
opentela/internal/protocol/service_health.go:114:		snapshotWithdrawnServices		0.0%
opentela/internal/protocol/service_health.go:124:		setServiceWithdrawn			0.0%
opentela/internal/protocol/service_health.go:134:		serviceHealthInterval			0.0%
opentela/internal/protocol/service_health.go:141:		serviceHealthFailureThreshold		0.0%
opentela/internal/protocol/service_health.go:156:		StartServiceHealthRevalidation		0.0%
opentela/internal/protocol/service_health.go:203:		removeLocalService			0.0%
opentela/internal/protocol/sweep.go:32:				String					0.0%
opentela/internal/protocol/sweep.go:55:				decideSweepAction			94.4%
opentela/internal/protocol/swim/dissemination.go:23:		NewDisseminator				66.7%
opentela/internal/protocol/swim/dissemination.go:35:		UpdateN					100.0%
opentela/internal/protocol/swim/dissemination.go:44:		retransmitLimit				100.0%
opentela/internal/protocol/swim/dissemination.go:50:		Enqueue					88.9%
opentela/internal/protocol/swim/dissemination.go:73:		GetPiggyback				93.3%
opentela/internal/protocol/swim/dissemination.go:100:		statusPriority				50.0%
opentela/internal/protocol/swim/messages.go:58:			MarshalJSON				100.0%
opentela/internal/protocol/swim/messages.go:67:			UnmarshalJSON				87.5%
opentela/internal/protocol/swim/messages.go:87:			Marshal					28.6%
opentela/internal/protocol/swim/messages.go:109:		Unmarshal				100.0%
opentela/internal/protocol/swim/messages.go:129:		Marshal					80.0%
opentela/internal/protocol/swim/messages.go:149:		Unmarshal				76.9%
opentela/internal/protocol/swim/metrics.go:30:			init					100.0%
opentela/internal/protocol/swim/swim.go:72:			NewSWIM					100.0%
opentela/internal/protocol/swim/swim.go:86:			AddMember				100.0%
opentela/internal/protocol/swim/swim.go:97:			RemoveMember				100.0%
opentela/internal/protocol/swim/swim.go:107:			GetStatus				100.0%
opentela/internal/protocol/swim/swim.go:117:			GetIncarnation				100.0%
opentela/internal/protocol/swim/swim.go:124:			Members					100.0%
opentela/internal/protocol/swim/swim.go:136:			probeOnce				86.7%
opentela/internal/protocol/swim/swim.go:168:			processPendingProbes			94.2%
opentela/internal/protocol/swim/swim.go:273:			processSuspects				100.0%
opentela/internal/protocol/swim/swim.go:314:			HandleMessage				100.0%
opentela/internal/protocol/swim/swim.go:366:			processEvents				27.8%
opentela/internal/protocol/swim/swim.go:437:			Run					100.0%
opentela/internal/protocol/swim/swim.go:460:			updateMemberGauge			100.0%
opentela/internal/protocol/swim/swim.go:475:			Close					75.0%
opentela/internal/protocol/swim/transport.go:27:		NewLibP2PTransport			0.0%
opentela/internal/protocol/swim/transport.go:31:		send					0.0%
opentela/internal/protocol/swim/transport.go:49:		SendPing				0.0%
opentela/internal/protocol/swim/transport.go:53:		SendAck					0.0%
opentela/internal/protocol/swim/transport.go:57:		SendPingReq				0.0%
opentela/internal/protocol/swim/transport.go:62:		RegisterHandler				0.0%
opentela/internal/protocol/tombstone_compactor.go:21:		startTombstoneCompactor			0.0%
opentela/internal/protocol/tombstone_compactor.go:91:		readDurationSetting			100.0%
opentela/internal/protocol/tombstone_manager.go:24:		GetTombstoneManager			0.0%
opentela/internal/protocol/tombstone_manager.go:37:		CleanupLeftNodes			87.5%
opentela/internal/protocol/tombstone_manager.go:58:		collectCandidates			100.0%
opentela/internal/server/access_control.go:27:			resolveCallerWallet			46.2%
opentela/internal/server/access_control.go:51:			accessControlMiddleware			81.1%
opentela/internal/server/access_control.go:193:			maybeWorkerScopeFromContext		90.9%
opentela/internal/server/access_control.go:210:			statusForScopeDenial			50.0%
opentela/internal/server/access_control.go:228:			messageForScopeDenial			27.3%
opentela/internal/server/access_control.go:258:			isLibp2pRemoteAddr			100.0%
opentela/internal/server/access_control.go:264:			containsWallet				100.0%
opentela/internal/server/admin.go:30:				validateAdminRegisterReq		100.0%
opentela/internal/server/admin.go:40:				adminRegisterHandler			77.8%
opentela/internal/server/admin.go:56:				adminResyncHandler			0.0%
opentela/internal/server/admin.go:68:				StartAdminServer			0.0%
opentela/internal/server/affinity.go:50:			NewAffinityStore			100.0%
opentela/internal/server/affinity.go:60:			Get					100.0%
opentela/internal/server/affinity.go:85:			Put					100.0%
opentela/internal/server/affinity.go:96:			Size					85.7%
opentela/internal/server/affinity.go:113:			sanitizeAffinityKey			92.9%
opentela/internal/server/affinity.go:139:			selectAffinityPeer			100.0%
opentela/internal/server/analytics_hook.go:22:			getAnalytics				100.0%
opentela/internal/server/analytics_hook.go:26:			initAnalytics				0.0%
opentela/internal/server/analytics_hook.go:56:			stopAnalytics				0.0%
opentela/internal/server/analytics_hook.go:61:			buildProxySample			73.7%
opentela/internal/server/analytics_hook.go:100:			stageDuration				50.0%
opentela/internal/server/auth_client.go:118:			allows					100.0%
opentela/internal/server/auth_client.go:122:			allows					75.0%
opentela/internal/server/auth_client.go:130:			reason					83.3%
opentela/internal/server/auth_client.go:146:			Error					0.0%
opentela/internal/server/auth_client.go:153:			clientMessage				57.1%
opentela/internal/server/auth_client.go:208:			get					100.0%
opentela/internal/server/auth_client.go:218:			set					100.0%
opentela/internal/server/auth_client.go:227:			getFresh				100.0%
opentela/internal/server/auth_client.go:238:			getStale				100.0%
opentela/internal/server/auth_client.go:249:			set					100.0%
opentela/internal/server/auth_client.go:264:			getFresh				100.0%
opentela/internal/server/auth_client.go:275:			getStale				0.0%
opentela/internal/server/auth_client.go:286:			set					100.0%
opentela/internal/server/auth_client.go:301:			isControlPlaneEnabled			100.0%
opentela/internal/server/auth_client.go:305:			controlPlaneTimeout			66.7%
opentela/internal/server/auth_client.go:312:			controlPlaneCacheTTL			100.0%
opentela/internal/server/auth_client.go:319:			controlPlaneStaleIfError		100.0%
opentela/internal/server/auth_client.go:326:			parseBearerToken			77.8%
opentela/internal/server/auth_client.go:341:			uniquePeerIDs				90.9%
opentela/internal/server/auth_client.go:358:			cacheKeyForDecision			100.0%
opentela/internal/server/auth_client.go:364:			cacheKeyForDecisionV2			100.0%
opentela/internal/server/auth_client.go:378:			sha256Hex				100.0%
opentela/internal/server/auth_client.go:383:			controlPlaneFreshTTL			85.7%
opentela/internal/server/auth_client.go:395:			decodeStrictJSON			60.0%
opentela/internal/server/auth_client.go:411:			allowedPeerSet				100.0%
opentela/internal/server/auth_client.go:419:			validateACLResponse			76.0%
opentela/internal/server/auth_client.go:465:			isKnownACLReason			100.0%
opentela/internal/server/auth_client.go:475:			isKnownACLReasonV2			100.0%
opentela/internal/server/auth_client.go:496:			validateACLResponseV2			61.9%
opentela/internal/server/auth_client.go:541:			shouldCacheDecisionV2			100.0%
opentela/internal/server/auth_client.go:545:			evaluateBearerForPeers			82.7%
opentela/internal/server/auth_client.go:654:			evaluateBearerForScope			100.0%
opentela/internal/server/auth_client.go:661:			evaluateKeyHashForScope			57.1%
opentela/internal/server/auth_client.go:773:			authorizeRequestForPeers		66.7%
opentela/internal/server/auth_client.go:784:			authorizeRequestForScope		66.7%
opentela/internal/server/auth_client.go:801:			authorizeKeyHashForScope		66.7%
opentela/internal/server/auth_client.go:815:			verifyBearerToken			84.6%
opentela/internal/server/auth_client.go:861:			resolveClientWallet			75.0%
opentela/internal/server/cors.go:10:				corsHeader				100.0%
opentela/internal/server/cors.go:26:				rewriteHeader				100.0%
opentela/internal/server/crdt_handler.go:13:			listPeers				100.0%
opentela/internal/server/crdt_handler.go:18:			listPeersWithStatus			100.0%
opentela/internal/server/crdt_handler.go:24:			listBootstraps				0.0%
opentela/internal/server/crdt_handler.go:29:			getResourceStats			100.0%
opentela/internal/server/crdt_handler.go:46:			updateLocal				0.0%
opentela/internal/server/crdt_handler.go:64:			deleteLocal				80.0%
opentela/internal/server/crdt_handler.go:96:			getDNT					0.0%
opentela/internal/server/health.go:9:				healthStatusCheck			100.0%
opentela/internal/server/ingest.go:38:				getIngestStats				88.9%
opentela/internal/server/libp2p_http_transport.go:42:		newLibp2pHTTPRoundTripper		100.0%
opentela/internal/server/libp2p_http_transport.go:46:		newTrustedLibp2pHTTPRoundTripper	0.0%
opentela/internal/server/libp2p_http_transport.go:53:		newLibp2pHTTPRoundTripperWithMode	15.0%
opentela/internal/server/libp2p_http_transport.go:100:		RoundTrip				0.0%
opentela/internal/server/libp2p_http_transport.go:117:		CloseIdleConnections			0.0%
opentela/internal/server/loadbalancer.go:33:			Pick					100.0%
opentela/internal/server/loadbalancer.go:34:			OnRequestStart				0.0%
opentela/internal/server/loadbalancer.go:35:			OnRequestEnd				0.0%
opentela/internal/server/loadbalancer.go:43:			Pick					100.0%
opentela/internal/server/loadbalancer.go:47:			OnRequestStart				0.0%
opentela/internal/server/loadbalancer.go:48:			OnRequestEnd				0.0%
opentela/internal/server/loadbalancer.go:62:			newShortestQueueLB			100.0%
opentela/internal/server/loadbalancer.go:72:			resetLoop				55.6%
opentela/internal/server/loadbalancer.go:89:			Pick					100.0%
opentela/internal/server/loadbalancer.go:105:			OnRequestStart				100.0%
opentela/internal/server/loadbalancer.go:111:			OnRequestEnd				100.0%
opentela/internal/server/loadbalancer.go:126:			SetLoadBalancerPolicy			100.0%
opentela/internal/server/loadbalancer.go:138:			GetLoadBalancer				100.0%
opentela/internal/server/node_credentials.go:63:		resetNodeCredentialManagerForTest	100.0%
opentela/internal/server/node_credentials.go:69:		getTrustedNodeCredential		100.0%
opentela/internal/server/node_credentials.go:73:		get					80.0%
opentela/internal/server/node_credentials.go:93:		issueTrustedNodeCredential		71.4%
opentela/internal/server/node_credentials.go:142:		requestAndSignNodeCredentialChallenge	70.6%
opentela/internal/server/node_credentials.go:196:		ioLimit					100.0%
opentela/internal/server/node_credentials.go:200:		nodeCredentialResponseOK		100.0%
opentela/internal/server/p2p_listener.go:11:			P2PListener				0.0%
opentela/internal/server/probe_handler.go:24:			echoHandler				91.7%
opentela/internal/server/probe_handler.go:59:			Read					100.0%
opentela/internal/server/probe_handler.go:101:			holepunchHandler			0.0%
opentela/internal/server/probe_handler.go:149:			runHandler				75.0%
opentela/internal/server/probe_handler.go:195:			runLatency				0.0%
opentela/internal/server/probe_handler.go:229:			summariseDurations			92.3%
opentela/internal/server/probe_handler.go:260:			runThroughput				0.0%
opentela/internal/server/probe_handler.go:326:			runLibp2pPing				0.0%
opentela/internal/server/probe_handler.go:347:			processPingResults			100.0%
opentela/internal/server/proxy_handler.go:69:			init					100.0%
opentela/internal/server/proxy_handler.go:73:			getGlobalTransport			100.0%
opentela/internal/server/proxy_handler.go:90:			getTrustedTransport			0.0%
opentela/internal/server/proxy_handler.go:114:			proxyErrorStatus			100.0%
opentela/internal/server/proxy_handler.go:125:			ErrorHandler				85.7%
opentela/internal/server/proxy_handler.go:140:			relayHopError				100.0%
opentela/internal/server/proxy_handler.go:153:			WriteHeader				0.0%
opentela/internal/server/proxy_handler.go:163:			Flush					0.0%
opentela/internal/server/proxy_handler.go:170:			P2PForwardHandler			35.3%
opentela/internal/server/proxy_handler.go:230:			P2PServiceForwardHandler		0.0%
opentela/internal/server/proxy_handler.go:239:			TrustedRegionP2PServiceForwardHandler	60.0%
opentela/internal/server/proxy_handler.go:248:			p2pServiceForwardWithScope		47.8%
opentela/internal/server/proxy_handler.go:325:			ServiceForwardHandler			0.0%
opentela/internal/server/proxy_handler.go:388:			parseFallbackLevel			100.0%
opentela/internal/server/proxy_handler.go:407:			selectCandidates			100.0%
opentela/internal/server/proxy_handler.go:482:			weightedRandomSelect			81.2%
opentela/internal/server/proxy_handler.go:512:			scoreCandidates				0.0%
opentela/internal/server/proxy_handler.go:524:			excludePeers				100.0%
opentela/internal/server/proxy_handler.go:538:			shouldShedLoad				100.0%
opentela/internal/server/proxy_handler.go:548:			filterByTrust				0.0%
opentela/internal/server/proxy_handler.go:568:			intersectAllowedPeers			100.0%
opentela/internal/server/proxy_handler.go:595:			priceAwareScores			100.0%
opentela/internal/server/proxy_handler.go:619:			parseAllowedPeerOrder			100.0%
opentela/internal/server/proxy_handler.go:639:			orderCandidatesByPrice			100.0%
opentela/internal/server/proxy_handler.go:659:			filterAllowedCandidatesV2		71.4%
opentela/internal/server/proxy_handler.go:672:			buildInternalServicePath		66.7%
opentela/internal/server/proxy_handler.go:680:			GlobalServiceForwardHandler		60.0%
opentela/internal/server/proxy_handler.go:689:			TrustedRegionServiceForwardHandler	0.0%
opentela/internal/server/proxy_handler.go:698:			globalServiceForwardWithScope		14.6%
opentela/internal/server/ratelimit.go:27:			newRateLimiterStore			100.0%
opentela/internal/server/ratelimit.go:37:			getLimiter				100.0%
opentela/internal/server/ratelimit.go:51:			cleanup					57.1%
opentela/internal/server/ratelimit.go:66:			rateLimitMiddleware			88.9%
opentela/internal/server/registration.go:52:			challengePeer				81.8%
opentela/internal/server/registration.go:77:			registerPeer				37.9%
opentela/internal/server/registration.go:227:			StartChallengeCleanup			0.0%
opentela/internal/server/registration.go:236:			cleanExpiredChallenges			0.0%
opentela/internal/server/retry_writer.go:38:			newRetryableResponseWriter		100.0%
opentela/internal/server/retry_writer.go:54:			Header					100.0%
opentela/internal/server/retry_writer.go:59:			markFailed				100.0%
opentela/internal/server/retry_writer.go:65:			isRetryable				100.0%
opentela/internal/server/retry_writer.go:71:			commitHeaders				87.5%
opentela/internal/server/retry_writer.go:87:			isStreamingResponse			100.0%
opentela/internal/server/retry_writer.go:99:			WriteHeader				87.5%
opentela/internal/server/retry_writer.go:123:			Write					91.7%
opentela/internal/server/retry_writer.go:154:			Flush					100.0%
opentela/internal/server/retry_writer.go:163:			flushToClient				100.0%
opentela/internal/server/retry_writer.go:187:			newFirstByteMarker			0.0%
opentela/internal/server/retry_writer.go:195:			Write					0.0%
opentela/internal/server/retry_writer.go:206:			Flush					0.0%
opentela/internal/server/retry_writer.go:215:			Duration				0.0%
opentela/internal/server/routing_scope.go:36:			trusted					100.0%
opentela/internal/server/routing_scope.go:40:			validate				66.7%
opentela/internal/server/routing_scope.go:56:			newRoutingScope				75.0%
opentela/internal/server/self_handler.go:14:			isLoopback				80.0%
opentela/internal/server/self_handler.go:24:			getSelf					100.0%
opentela/internal/server/self_handler.go:34:			signData				10.7%
opentela/internal/server/server.go:24:				StartServer				0.0%
opentela/internal/server/service_resolution.go:15:		resolveUniqueLocalService		71.4%
opentela/internal/server/service_resolution.go:30:		writeServiceResolutionError		50.0%
opentela/internal/server/timing.go:18:				InitTiming				0.0%
opentela/internal/server/timing.go:36:				newStageTimer				100.0%
opentela/internal/server/timing.go:44:				Mark					100.0%
opentela/internal/server/timing.go:56:				AddRaw					100.0%
opentela/internal/server/timing.go:64:				Header					100.0%
opentela/internal/server/timing.go:78:				mergeWorkerTiming			100.0%
opentela/internal/server/timing.go:95:				parseServerTiming			94.4%
opentela/internal/server/timing.go:125:				setWorkerTimingHeader			100.0%
opentela/internal/server/tracer.go:20:				initTracer				0.0%
opentela/internal/server/tracer.go:44:				IngestEvents				0.0%
opentela/internal/solana/client.go:27:				NewClient				100.0%
opentela/internal/solana/client.go:55:				call					88.2%
opentela/internal/solana/client.go:93:				HasSPLToken				100.0%
opentela/internal/solana/client.go:141:				GetBalance				88.9%
opentela/internal/solana/client.go:159:				GetBalanceSOL				75.0%
opentela/internal/solana/client.go:180:				GetTokenBalance				75.0%
opentela/internal/solana/client.go:191:				GetTokenBalanceDetails			73.3%
opentela/internal/solana/client.go:238:				RequestAirdrop				77.8%
opentela/internal/solana/client.go:276:				SendSOL					0.0%
opentela/internal/solana/client.go:332:				getRecentBlockhash			0.0%
opentela/internal/solana/client.go:359:				buildTransferMessage			100.0%
opentela/internal/solana/client.go:410:				serializeTransaction			100.0%
opentela/internal/usage/extractor.go:15:			ExtractUsageMetrics			93.8%
opentela/internal/usage/store.go:16:				NewUsageStore				83.3%
opentela/internal/usage/store.go:29:				Close					100.0%
opentela/internal/usage/store.go:34:				SaveRecord				83.3%
opentela/internal/usage/store.go:48:				GetRecord				100.0%
opentela/internal/usage/tracker.go:27:				InitTracker				0.0%
opentela/internal/usage/tracker.go:53:				CloseTracker				0.0%
opentela/internal/usage/tracker.go:61:				Track					0.0%
opentela/internal/usage/tracker.go:88:				GenerateRequestID			100.0%
opentela/internal/wallet/derive.go:26:				DeriveIdentityKeyFromDeployKey		87.5%
opentela/internal/wallet/identity.go:35:			SignIdentity				71.4%
opentela/internal/wallet/identity.go:51:			SignIdentityWithKey			70.0%
opentela/internal/wallet/identity.go:81:			VerifyIdentity				77.8%
opentela/internal/wallet/wallet.go:70:				NewWalletManager			66.7%
opentela/internal/wallet/wallet.go:101:				NewWalletManagerWithDir			66.7%
opentela/internal/wallet/wallet.go:119:				loadAccounts				96.2%
opentela/internal/wallet/wallet.go:169:				upgradeLegacyOCFAccount			87.5%
opentela/internal/wallet/wallet.go:205:				normalizeSolanaAccount			87.0%
opentela/internal/wallet/wallet.go:241:				validSolanaPublicKey			100.0%
opentela/internal/wallet/wallet.go:246:				solanaPrivateKeyFromAccount		54.5%
opentela/internal/wallet/wallet.go:281:				ensureManagedSolanaKeypair		58.3%
opentela/internal/wallet/wallet.go:320:				decodePrivateKey			83.3%
opentela/internal/wallet/wallet.go:331:				migrateLegacyWallet			81.8%
opentela/internal/wallet/wallet.go:375:				migrateLegacyDir			82.9%
opentela/internal/wallet/wallet.go:443:				saveAccounts				71.4%
opentela/internal/wallet/wallet.go:464:				Accounts				100.0%
opentela/internal/wallet/wallet.go:472:				DefaultAccount				100.0%
opentela/internal/wallet/wallet.go:486:				SelectAccount				100.0%
opentela/internal/wallet/wallet.go:509:				AddSolanaAccount			73.3%
opentela/internal/wallet/wallet.go:543:				ImportSolanaKeypair			81.8%
opentela/internal/wallet/wallet.go:593:				ExportKeypair				77.8%
opentela/internal/wallet/wallet.go:612:				ExportBase58PrivateKey			85.7%
opentela/internal/wallet/wallet.go:631:				FindByFile				100.0%
opentela/internal/wallet/wallet.go:641:				FindByPublicKey				100.0%
opentela/internal/wallet/wallet.go:651:				FindByProviderID			100.0%
opentela/internal/wallet/wallet.go:661:				WalletExists				100.0%
opentela/internal/wallet/wallet.go:669:				GetPublicKey				100.0%
opentela/internal/wallet/wallet.go:676:				GetPrivateKey				100.0%
opentela/internal/wallet/wallet.go:683:				GetWalletPath				100.0%
opentela/internal/wallet/wallet.go:690:				GetWalletType				100.0%
opentela/internal/wallet/wallet.go:699:				GetProviderID				100.0%
opentela/internal/wallet/wallet.go:708:				GetPrivateKeyBytes			77.8%
opentela/internal/wallet/wallet.go:728:				InitializeWallet			83.3%
opentela/internal/wallet/wallet.go:745:				writeSolanaKeypair			77.8%
opentela/internal/wallet/wallet.go:762:				parseSolanaKeypairJSON			100.0%
opentela/internal/wallet/wallet.go:783:				deriveProviderID			100.0%
opentela/internal/wallet/wallet.go:792:				copyDirRecursive			76.9%
opentela/plugins/webui/embed.go:12:				Static					0.0%
total:								(statements)				52.1%

Summary:

Resolve conflicts with #68 (ephemeral identity): nodeLinkSigner goes through
protocol.NodeIdentity; seeded keys keep this branch's Ed25519
GenerateKeyFromSeed; GenerateAndWriteKey keeps its seed parameter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RijVoa4Sf4BDt1BrxB1v4c
Entire-Checkpoint: 01M6E9QKR0DMNQJH5VD77CQ6KR
@xzyaoi
xzyaoi merged commit f0eca38 into main Nov 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants