probe

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 14 Imported by: 0

Documentation

Overview

Package probe holds the endpoint-soundness and reachability primitives the cli's onboarding and diagnostic commands share (ip, doctor, setup, key set-base-url, mcp): base-URL validation, the public-IP probe and its allowlist report, the REST/WebSocket reachability smoke test, and the IP-allowlist error classifier. It carries no command logic — each command composes these — so a command subpackage can reach them without importing cli.

Index

Constants

View Source
const (
	// ProdBaseURL is the production REST host — the single source for the
	// production endpoint (the base-URL fallback and the always-production IP
	// probe both resolve to it).
	ProdBaseURL = "https://api.korbit.co.kr"

	// PortalURL is the developers portal — the single source for the URL where
	// users register a public key and manage a key's IP allowlist. The key-setup
	// link, the `ip` guidance, and doctor's allowlist fixes all point at it.
	PortalURL = "https://developers.korbit.co.kr"

	// DefaultTimeoutMs is the default per-probe timeout. It is shorter than the
	// regular request timeout: an unreachable target must fail fast (an
	// IPv6-less host during `setup`, a wrong WebSocket host in `doctor`) instead
	// of stalling the command. Overridable with --timeout.
	DefaultTimeoutMs = 5000
)

Variables

This section is empty.

Functions

func DeriveWSBaseURL

func DeriveWSBaseURL(raw string) string

DeriveWSBaseURL maps a REST base URL to the matching WebSocket base URL using the convention that the WebSocket endpoint lives on a sibling `ws-api` host of the REST host. The transform:

  • scheme: http → ws, https → wss.
  • first DNS label: when it begins with "api" (matched case-insensitively), everything from "api" up to the first "-" is replaced by "ws-api" and any "-suffix" is kept — so a node/cluster discriminator after "api" (a digit, letter, or word) is dropped. A label that does not begin with "api" (an IP, "localhost", or any other host) is left unchanged, so a same-host deployment (the local sandbox) keeps its host.
  • the rest of the host (remaining labels and any :port) is preserved; an IPv6 literal host is left intact and re-bracketed.

Examples (illustrative hosts):

https://api.korbit.co.kr      → wss://ws-api.korbit.co.kr
https://api-test.korbit.co.kr → wss://ws-api-test.korbit.co.kr
https://apiz.korbit.com       → wss://ws-api.korbit.com
https://api7-test.korbit.com  → wss://ws-api-test.korbit.com
http://127.0.0.1:9999         → ws://127.0.0.1:9999

The result is a base URL with no path; callers append /v2/public and /v2/private. It returns "" only when raw cannot be parsed into a host — the caller then falls back to its own default. The heuristic is best-effort: a deployment whose WebSocket host does not follow this convention can pin an exact endpoint with the explicit WS base URL override.

func FamiliesLabel

func FamiliesLabel(networks []string) string

FamiliesLabel is a human label for a set of probe networks ("IPv4", "IPv6", or "IPv4 or IPv6"), for the "could not determine" diagnostics.

func IsIPAllowlistCode

func IsIPAllowlistCode(code string) bool

IsIPAllowlistCode reports whether a symbolic API error code denotes an IP-allowlist rejection. It matches on word-ish boundaries (`IP_`, `_IP`, WHITELIST/ALLOWLIST) rather than a bare "IP" substring, so unrelated codes that merely contain the letters "ip" don't get the allowlist fix hint. The public spec doesn't pin the exact symbol, so this stays a heuristic — it only selects the *fix text*, never the exit code.

func IsLoopbackHost

func IsLoopbackHost(host string) bool

IsLoopbackHost reports whether host is localhost or a loopback IP.

func ValidateBaseURL

func ValidateBaseURL(raw string, signed bool) error

ValidateBaseURL rejects a malformed base URL, and — when the request will be signed — refuses to send credentials over plaintext http to a non-loopback host (which would expose a replayable signed request). http to localhost is allowed for the sandbox.

func ValidateWSBaseURL

func ValidateWSBaseURL(raw, label string, signed bool) error

ValidateWSBaseURL rejects a malformed WebSocket base URL, and — when the connection will be signed (a private channel upgrade) — refuses to sign over a plaintext ws:// to a non-loopback host, which would expose a replayable signed upgrade. ws:// to localhost is allowed for the sandbox. label names the source of the value for the error message (e.g. "--ws-base-url").

func WSURLsFor

func WSURLsFor(wsBase string) (publicURL, privateURL string)

WSURLsFor turns a WebSocket base URL into the public and private channel URLs the stream layer dials.

Types

type EndpointCheck

type EndpointCheck struct {
	URL       string `json:"url"`
	Reachable bool   `json:"reachable"`
	Detail    string `json:"detail"`
	// Err is the underlying transport error when the host could not be reached
	// (Reachable false), nil otherwise. Not serialized — Detail carries the
	// human-readable form; Err lets a caller classify or re-render the failure
	// without parsing Detail.
	Err error `json:"-"`
}

EndpointCheck is one endpoint's smoke-test result.

func REST

func REST(ctx context.Context, doer korbit.Doer, baseURL string) EndpointCheck

REST probes one REST base URL with an unauthenticated GET /v2/time.

func WS

func WS(ctx context.Context, dial stream.Dialer, wsBaseURL string) EndpointCheck

WS probes one WebSocket base URL with a public-channel dial.

type EndpointVerification

type EndpointVerification struct {
	REST EndpointCheck `json:"rest"`
	WS   EndpointCheck `json:"ws"`
}

EndpointVerification is the smoke test `key set-base-url` runs after storing a key's endpoints: a best-effort reachability probe of the REST and WebSocket base URLs, so the user learns immediately if the (possibly derived) WebSocket host is wrong instead of only when a `monitor` later fails to connect.

func Endpoints

func Endpoints(doer korbit.Doer, dial stream.Dialer, baseURL, wsBaseURL string, timeoutMs int) EndpointVerification

Endpoints smoke-tests the REST base URL (an unauthenticated GET /v2/time) and the WebSocket base URL (a public-channel dial). It is best-effort: every outcome is reported in the result, never returned as an error, and a nil doer or dialer marks that half "not checked". Each probe gets its OWN timeout budget so a slow REST host can't starve the WS probe into a false failure.

type Report

type Report struct {
	IPv4         *string  `json:"ipv4"`
	IPv6         *string  `json:"ipv6"`
	IPv6Prefix64 *string  `json:"ipv6Prefix64"`
	Allowlist    []string `json:"allowlistEntries"`
}

Report is the result of probing Korbit over both families. Each address is null when that family is unavailable. Allowlist is the ready-to-paste set for the portal's API-key IP allowlist: the full IPv4 address (a /32) and the IPv6 /64 prefix.

func IPs

func IPs(prober korbit.IPProber, baseURL string, timeoutMs int, networks []string) Report

IPs queries baseURL over the given TCP families ("tcp4"/"tcp6") concurrently (each best-effort) and assembles the allowlist suggestions. networks caps the probe to what --family permits — a family not listed is never contacted, so an --family ipv6 run makes no IPv4 request and suggests no IPv4 allowlist entry. A listed family that fails to connect is simply absent from the report.

func (Report) Any

func (r Report) Any() bool

Any reports whether either family's address was determined.

func (Report) EntryFor

func (r Report) EntryFor(label string) string

EntryFor returns the ready-to-paste allowlist entry for a family label ("IPv4"/"IPv6"): the full IPv4 address (a /32), or the IPv6 /64 prefix (the full address when the prefix couldn't be derived). It returns "" when that family's address wasn't determined.

Jump to

Keyboard shortcuts

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