Documentation
¶
Index ¶
- Constants
- type APIError
- type APIErrorResponse
- type AgentConfig
- type AgentDebugBatch
- type AgentDebugConfig
- type AgentDebugPolicy
- type AgentLaunchConfig
- type AgentUpdatePolicy
- type Approval
- type AuditEvent
- type DDNSProfile
- type DNSDeployment
- type DNSRecord
- type DNSZone
- type GeoRouting
- type Group
- type GroupNetPolicy
- type GroupNetRule
- type GroupSelector
- type GuardInterface
- type GuardListener
- type GuardNodeReality
- type GuardPortRange
- type GuardRule
- type GuardZone
- type HostFacts
- type KVEntry
- type LogBatch
- type LogLine
- type LogSource
- type MachineProfile
- type MachineVendor
- type Metrics
- type Monitor
- type MonitorResult
- type NFTInputs
- type NetEndpoint
- type NetPolicy
- type NetRule
- type Node
- type NodeGeo
- type NodeGuardBinding
- type NodeIPConfig
- type NodeInventory
- type NotifyChannel
- type NotifyRule
- type OIDCIdentity
- type OIDCProvider
- type PluginInstallation
- type ProxyInbound
- type ProxyNodeProfile
- type ProxyUsageSnapshot
- type ProxyUser
- type SecurityGroup
- type SingBoxInventory
- type SingBoxNode
- type StaticObject
- type StorageAccessToken
- type StorageBinding
- type StorageBucket
- type Task
- type TaskLease
- type TaskResult
- type TerminalEvent
- type TerminalInput
- type TerminalSession
- type Token
- type TunnelIngress
- type TunnelProfile
- type User
- type WGExternalPeer
- type WGMembership
- type WGNetwork
- type WorkerScript
Constants ¶
const ( TaskQueued = "queued" TaskLeased = "leased" TaskFinished = "finished" TaskFailed = "failed" // TaskCancelled is an operator-cancelled task. Only a queued task can be // cancelled (a leased task is already running on the agent and cannot be // reliably stopped from the server); it is then never leased. TaskCancelled = "cancelled" TerminalPending = "pending" TerminalOpen = "open" TerminalClosed = "closed" TerminalFailed = "failed" ApprovalPending = "pending" ApprovalApproved = "approved" ApprovalRejected = "rejected" ApprovalApplied = "applied" PluginStatusVerified = "verified" PluginStatusInstalled = "installed" PluginStatusActive = "active" PluginStatusDisabled = "disabled" )
const ( NodeIPModeAuto = "auto" // static override if set, else resolver probe NodeIPModeStatic = "static" // use the operator-provided static IPs only NodeIPModeResolver = "resolver" // always probe the resolvers, ignore static NodeIPModeScript = "script" // run an operator-provided script on the agent )
const ( RenewalCycleMonthly = "monthly" RenewalCycleQuarterly = "quarterly" RenewalCycleSemiannual = "semiannual" RenewalCycleAnnual = "annual" RenewalCycleCustomDays = "custom_days" )
const ( DNSEngineCoreDNS = "coredns" DNSExposureMesh = "mesh" DNSExposurePublic = "public" DNSZoneForward = "forward" DNSZoneStatic = "static" DNSZoneBlock = "block" DNSStatusPending = "pending" DNSStatusApplying = "applying" DNSStatusRunning = "running" DNSStatusFailed = "failed" DNSStatusDisabled = "disabled" )
const ( GeoRoutingStrategyGeoIP = "geoip" GeoRoutingStrategyAllHealthy = "all-healthy" )
const ( NetRuleAllow = "allow" NetRuleDeny = "deny" NetDirEgress = "egress" NetDirIngress = "ingress" NetProtoTCP = "tcp" NetProtoUDP = "udp" NetProtoAny = "any" NetRefNode = "node" NetRefCIDR = "cidr" NetRefDomain = "domain" NetRefAny = "any" // NetRefGroup is a group-scoped remote. It is an authoring-layer kind only: // the server expands it to one concrete node ref per resolved group member // before compilation, so the per-node nft compiler never sees a group ref. NetRefGroup = "group" )
const ( // NetRefZone is a guard-zone-scoped remote (design-13). Like NetRefGroup it // is an authoring-layer kind: the server resolves the zone to concrete // interface/CIDR matches before the per-node nft compiler runs. NetRefZone = "zone" GuardProtoICMP = "icmp" GuardProtoICMPv6 = "icmpv6" // Builtin guard-zone ids. "public" resolves to the node's public-facing // interface, "loopback" is the always-accepted lo scaffold, and overlay // zones ("wireguard", "tailscale") resolve to the node's discovered or // managed overlay interfaces/CIDRs. GuardZonePublic = "public" GuardZoneLoopback = "loopback" GuardZoneWireGuard = "wireguard" GuardZoneTailscale = "tailscale" )
const ( // WireGuard topology modes (design-13 §5.3). Mesh is today's implicit // behavior; hub-and-spoke and custom are additive. WGTopologyMesh = "mesh" WGTopologyHubSpoke = "hub-and-spoke" WGTopologyCustom = "custom" WGRoleHub = "hub" WGRoleSpoke = "spoke" WGRolePeer = "peer" WGDefaultListenPort = 51820 WGDefaultKeepalive = 25 )
const ( ProxyCoreSingbox = "sing-box" ProxyCoreXray = "xray" ProxyProtocolVLESS = "vless" ProxyProtocolVMess = "vmess" ProxyProtocolTrojan = "trojan" ProxyProtocolShadowsocks = "shadowsocks" ProxyProtocolHysteria2 = "hysteria2" ProxyTransportTCP = "tcp" ProxyTransportWS = "ws" ProxyTransportGRPC = "grpc" ProxyTransportHTTP2 = "http2" ProxyTransportQUIC = "quic" ProxySecurityNone = "none" ProxySecurityTLS = "tls" ProxySecurityReality = "reality" ProxyUserStatusActive = "active" ProxyUserStatusExpired = "expired" ProxyUserStatusOverQuota = "over_quota" ProxyUserStatusDisabled = "disabled" ProxyUsageCollectorStatusOK = "ok" ProxyUsageCollectorStatusError = "error" )
const ( APIErrorBadRequest = "bad_request" APIErrorForbidden = "forbidden" APIErrorNotFound = "not_found" APIErrorMethodNotAllowed = "method_not_allowed" APIErrorRateLimited = "rate_limited" APIErrorBadGateway = "bad_gateway" APIErrorInternal = "internal_error" APIErrorRequestFailed = "request_failed" APIErrorCapabilityDenied = "capability_denied" APIErrorApprovalStale = "approval_stale" APIErrorAgentUpdateNoop = "agent_update_noop" APIErrorMFARequired = "mfa_required" APIErrorInvalidNodeToken = "invalid_node_token" APIErrorInvalidTaskLease = "invalid_task_lease" APIErrorTaskOutputLimitExceeded = "task_output_limit_exceeded" )
const ( StorageKindKV = "kv" StorageKindStatic = "static" StorageAccessAdmin = "admin" StorageAccessRead = "read" StorageAccessWrite = "write" )
const ( DDNSProviderCloudflare = "cloudflare" DDNSProviderWebhook = "webhook" )
const ( MonitorTypeTCP = "tcp" MonitorTypeHTTP = "http" MonitorTypeICMP = "icmp" )
const (
ApprovalStaleAgentUpdatePolicyChanged = "agent_update_policy_changed"
)
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type APIError ¶ added in v0.2.0
type APIError struct {
Code string `json:"code"`
Message string `json:"message"`
RequestID string `json:"request_id"`
}
APIError is the stable machine-readable error shape shared by server, dashboard, agents and plugins. Messages are user-facing; callers should make authorization and retry decisions from Code.
type APIErrorResponse ¶ added in v0.2.0
type APIErrorResponse struct {
Error APIError `json:"error"`
}
type AgentConfig ¶ added in v0.2.1
type AgentConfig struct {
Debug AgentDebugConfig `json:"debug"`
// LatticeIdentityUUID is the server-minted, stable node identity used by
// line discovery metadata and cross-node line graph resolution. Empty means
// the server has not minted one yet; old agents ignore this field.
LatticeIdentityUUID string `json:"lattice_identity_uuid,omitempty"`
// TerminalTransport is the server's per-node override for the agent terminal
// transport: "poll" or "stream". Empty means "no override" — the agent keeps
// its startup -terminal-transport / LATTICE_TERMINAL_TRANSPORT value. This is
// the rollout lever for promoting streaming per node without a redeploy; it
// affects only sessions opened after the change, never in-flight ones.
TerminalTransport string `json:"terminal_transport,omitempty"`
// IPConfig is the server's per-node override for public-IP discovery. nil
// means "no override" — the agent keeps its startup -ip-mode/-ip-resolvers
// flags. Old agents that do not know this field ignore it safely.
IPConfig *NodeIPConfig `json:"ip_config,omitempty"`
}
type AgentDebugBatch ¶ added in v0.2.1
type AgentDebugBatch struct {
NodeID string `json:"node_id"`
Lines []string `json:"lines"`
CapturedAt time.Time `json:"captured_at"`
}
AgentDebugBatch carries locally emitted agent diagnostics to the server log store when server-side collection is enabled for the node.
type AgentDebugConfig ¶ added in v0.2.1
type AgentDebugConfig struct {
Enabled bool `json:"enabled"`
Collect bool `json:"collect"`
MaxLineBytes int `json:"max_line_bytes,omitempty"`
MaxBatchLines int `json:"max_batch_lines,omitempty"`
}
AgentDebugConfig is the runtime policy an agent polls from the server. It is intentionally small and non-secret so older agents can ignore it safely.
type AgentDebugPolicy ¶ added in v0.2.1
type AgentDebugPolicy struct {
Enabled bool `json:"enabled"`
Collect bool `json:"collect"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
AgentDebugPolicy is the operator-owned diagnostic mode for a node-agent. When Enabled is true the agent emits verbose non-secret diagnostics locally on the node. Collect controls whether those diagnostics are also shipped back to the server log store. Server-managed debug collection defaults to true when enabled, but operators may keep local node debug output without central collection by setting Collect=false.
type AgentLaunchConfig ¶ added in v0.2.10
type AgentLaunchConfig struct {
AllowExec bool `json:"allow_exec"`
AllowRootExec bool `json:"allow_root_exec"`
NoExec bool `json:"no_exec"`
AllowTerminal bool `json:"allow_terminal"`
TerminalTransport string `json:"terminal_transport,omitempty"`
SSHAlerts bool `json:"ssh_alerts"`
SingBoxDiscover bool `json:"singbox_discover"`
SingBoxBin string `json:"singbox_bin,omitempty"`
ProxyUsageFile string `json:"proxy_usage_file,omitempty"`
ProxyUsageURL string `json:"proxy_usage_url,omitempty"`
ProxyUsageXrayAPI string `json:"proxy_usage_xray_api,omitempty"`
ProxyUsageXrayBin string `json:"proxy_usage_xray_bin,omitempty"`
ProxyUsageXrayPattern string `json:"proxy_usage_xray_pattern,omitempty"`
// SingBoxStatsAPI is the loopback host:port of the sing-box experimental
// stats API (ADR-004); empty disables the singbox-stats collector.
SingBoxStatsAPI string `json:"singbox_stats_api,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
AgentLaunchConfig mirrors lattice-agent startup flags/env vars used by the dashboard's enroll/reconfigure command generator. Runtime overrides that already-running agents poll remain in AgentConfig instead.
type AgentUpdatePolicy ¶ added in v0.2.0
type AgentUpdatePolicy struct {
NodeID string `json:"node_id"`
Enabled bool `json:"enabled"`
AutoPlan bool `json:"auto_plan"`
TargetVersion string `json:"target_version"`
BinaryURL string `json:"binary_url"`
SHA256 string `json:"sha256"`
InstallPath string `json:"install_path"`
ServiceName string `json:"service_name"`
LastPlannedVersion string `json:"last_planned_version,omitempty"`
LastPlannedAt time.Time `json:"last_planned_at,omitempty"`
LastAppliedVersion string `json:"last_applied_version,omitempty"`
LastAppliedAt time.Time `json:"last_applied_at,omitempty"`
LastError string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
AgentUpdatePolicy is a server-owned node-agent update intent. It carries no secrets: operators provide a public HTTPS binary URL plus the expected SHA-256 digest, and the server turns that into a reviewed, plan-hash-bound update task. AutoPlan never mutates a node directly; it only creates a pending approval when the node reports a different AgentVersion and no equivalent pending/approved update is already open.
type Approval ¶
type Approval struct {
ID string `json:"id"`
NodeID string `json:"node_id"`
Plugin string `json:"plugin"`
Action string `json:"action"`
Plan string `json:"plan"`
Status string `json:"status"`
Reason string `json:"reason,omitempty"`
Stale bool `json:"stale,omitempty"`
StaleCode string `json:"stale_code,omitempty"`
ActorID string `json:"actor_id"`
ApprovedBy string `json:"approved_by,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
// Operation binding (spec §9.3). When a plugin's plan-effect method produces a
// host-risk plan, the approval records the exact code and inputs that produced it,
// so execution can refuse to run against anything that has since changed. These are
// typed columns rather than values buried in Plan: each is compared to live state at
// execute time, and each is what the operator's review is accountable for.
//
// All omitempty, so an approval that is not a plugin operation (nft, dns, agent
// update) serializes exactly as before.
PluginVersion string `json:"plugin_version,omitempty"`
ArtifactDigest string `json:"artifact_digest,omitempty"`
Service string `json:"service,omitempty"`
Method string `json:"method,omitempty"`
// RequestSHA256 hashes the request that produced the plan. Re-planning with
// different inputs yields a different approval; an approval cannot be replayed
// against a request the operator never saw.
RequestSHA256 string `json:"request_sha256,omitempty"`
// Targets is the full node set the operation would touch. NodeID stays as the first
// target so the existing per-node approval machinery keeps working unchanged.
Targets []string `json:"targets,omitempty"`
}
type AuditEvent ¶
type AuditEvent struct {
ID string `json:"id"`
At time.Time `json:"at"`
ActorID string `json:"actor_id"`
TokenID string `json:"token_id"`
NodeID string `json:"node_id"`
Action string `json:"action"`
Scope string `json:"scope"`
Decision string `json:"decision"`
Reason string `json:"reason"`
CorrelationID string `json:"correlation_id"`
Metadata map[string]string `json:"metadata,omitempty"`
}
type DDNSProfile ¶ added in v0.2.0
type DDNSProfile struct {
ID string `json:"id"`
Name string `json:"name"`
NodeID string `json:"node_id"`
Provider string `json:"provider"`
Domains []string `json:"domains"`
EnableIPv4 bool `json:"enable_ipv4"`
EnableIPv6 bool `json:"enable_ipv6"`
MaxRetries int `json:"max_retries"`
TTL int `json:"ttl"`
// Cloudflare provider
CFAPIToken string `json:"cf_api_token,omitempty"`
// Webhook provider. Body/URL support the templates #ip#, #domain#, #type#.
WebhookURL string `json:"webhook_url,omitempty"`
WebhookMethod string `json:"webhook_method,omitempty"`
WebhookBody string `json:"webhook_body,omitempty"`
WebhookHeaders string `json:"webhook_headers,omitempty"`
// Status (updated by the server after each run).
LastIPv4 string `json:"last_ipv4,omitempty"`
LastIPv6 string `json:"last_ipv6,omitempty"`
LastRunAt time.Time `json:"last_run_at,omitempty"`
LastError string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
DDNSProfile describes how a node's public IP should be published to DNS. It is bound to a node; when that node's observed public IP changes, the bound profiles' records are updated.
type DNSDeployment ¶ added in v0.2.0
type DNSDeployment struct {
ID string `json:"id"`
Name string `json:"name"`
NodeID string `json:"node_id"`
Engine string `json:"engine"`
ListenPort int `json:"listen_port"`
EnableUDP bool `json:"enable_udp"`
EnableTCP bool `json:"enable_tcp"`
Exposure string `json:"exposure"`
Zones []DNSZone `json:"zones"`
Hostname string `json:"hostname,omitempty"`
PublishIPv4 bool `json:"publish_ipv4"`
PublishIPv6 bool `json:"publish_ipv6"`
RecordTTL int `json:"record_ttl,omitempty"`
CFAPIToken string `json:"cf_api_token,omitempty"`
DDNSProfileID string `json:"ddns_profile_id,omitempty"`
Status string `json:"status"`
EngineVersion string `json:"engine_version,omitempty"`
LastIPv4 string `json:"last_ipv4,omitempty"`
LastIPv6 string `json:"last_ipv6,omitempty"`
LastAppliedAt time.Time `json:"last_applied_at,omitempty"`
LastError string `json:"last_error,omitempty"`
LastPublishedAt time.Time `json:"last_published_at,omitempty"`
LastPublishError string `json:"last_publish_error,omitempty"`
Disabled bool `json:"disabled,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
DNSDeployment is the control-plane intent for a self-hosted DNS service on a node. CFAPIToken is a server-side secret and must never appear in read views or agent payloads.
type DNSRecord ¶ added in v0.2.0
type DNSRecord struct {
Name string `json:"name"`
Type string `json:"type"`
Value string `json:"value"`
TTL int `json:"ttl,omitempty"`
}
DNSRecord is a static authoritative record for a DNSZoneStatic zone.
type DNSZone ¶ added in v0.2.0
type DNSZone struct {
Suffix string `json:"suffix"`
Mode string `json:"mode"`
Upstreams []string `json:"upstreams,omitempty"`
Records []DNSRecord `json:"records,omitempty"`
}
DNSZone is one served block in a self-hosted resolver configuration. It is server-owned intent; the agent only receives the rendered, approved artifact.
type GeoRouting ¶ added in v0.2.0
type GeoRouting struct {
ID string `json:"id"`
Name string `json:"name"`
Hostname string `json:"hostname"` // the geo apex, e.g. dns.roobli.org
NodeIDs []string `json:"node_ids"` // participating targets (need NodeGeo + IP)
DNSNodeIDs []string `json:"dns_node_ids"` // authoritative DNS nodes (run self-host DNS)
TTL int `json:"ttl,omitempty"`
Strategy string `json:"strategy"` // "geoip" | "all-healthy"
GeoIPDBPath string `json:"geoip_db_path,omitempty"` // GeoLite2 path on the node
// Parent-zone NS delegation reuses the referenced DDNSProfile's CF token.
PublishNS bool `json:"publish_ns,omitempty"`
DDNSProfileID string `json:"ddns_profile_id,omitempty"`
LastRenderedSHA string `json:"last_rendered_sha,omitempty"`
Status string `json:"status,omitempty"`
LastAppliedAt time.Time `json:"last_applied_at,omitempty"`
LastDelegatedAt time.Time `json:"last_delegated_at,omitempty"`
LastError string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
GeoRouting answers one apex hostname (e.g. dns.roobli.org) with the nearest healthy participating node, served by Lattice's own DNS nodes (Design 06, Path B). It carries no secrets: the NS-delegation token is reused from the referenced DDNSProfile.
type Group ¶ added in v0.2.4
type Group struct {
ID string `json:"id"` // "grp_<ulid>"
Name string `json:"name"` // unique, display
Slug string `json:"slug"` // url/nft-safe, unique, immutable
Description string `json:"description,omitempty"`
Color string `json:"color"` // design-token name, never raw hex (CSP)
Icon string `json:"icon,omitempty"` // lucide icon name
ParentID string `json:"parent_id,omitempty"` // single parent; "" = root
Order int `json:"order"` // sort weight within the parent
Members []string `json:"members"` // explicit operator-pinned node IDs
Selector *GroupSelector `json:"selector,omitempty"` // dynamic smart-membership source
// LeaderID is the operator-designated group leader. It must be an explicit
// Member of the group (validated on upsert); empty means "no leader". This is
// the real, first-class field that replaces the old role-name heuristic used
// by the dashboard to mark a node as its group's leader.
LeaderID string `json:"leader_id,omitempty"`
System bool `json:"system,omitempty"` // built-in (e.g. "Ungrouped"); limited edits
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Group is a first-class fleet organization entity. Members are explicit, operator-pinned node IDs; Selector is a dynamic smart-membership source used by dashboard grouping and group policy planning. Because selector matches can change when node tags, role, or geo facts change, group-policy plans must surface selector impact and require fresh approval. Color is a design-token name (e.g. "sky", "violet"), never a raw hex value, so the dashboard stays CSP-safe. Slug is url/nft-safe, unique, and treated as immutable once assigned. ParentID gives a single-parent hierarchy ("" = root); Order is the operator-controlled sort weight within a parent.
type GroupNetPolicy ¶ added in v0.2.4
type GroupNetPolicy struct {
ID string `json:"id"` // "gnp_<ulid>"
ScopeGroupID string `json:"scope_group_id"` // applies to members of this group
Rules []GroupNetRule `json:"rules"`
Enabled bool `json:"enabled"`
Priority int `json:"priority"` // lower wins when a node is in 2+ scoped groups
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
GroupNetPolicy is a group-scoped authoring layer over the unchanged per-node NetPolicy engine. The server expands it into one NetPolicy per member of ScopeGroupID before compilation; the agent never receives it. Priority breaks ties when a node is a member of two or more scoped groups (lower wins).
type GroupNetRule ¶ added in v0.2.4
type GroupNetRule struct {
ID string `json:"id"`
Comment string `json:"comment,omitempty"`
Action string `json:"action"`
Direction string `json:"direction"`
Protocol string `json:"protocol"`
Ports []int `json:"ports,omitempty"`
Remote NetEndpoint `json:"remote"` // Kind may be NetRefGroup in addition to node|cidr|domain|any
Disabled bool `json:"disabled,omitempty"`
}
GroupNetRule mirrors NetRule but its Remote may additionally be a group ref (Remote.Kind == NetRefGroup with Remote.GroupID set). The server fans a group remote out to one node-ref rule per resolved remote member during expansion, so the compiled per-node rule set only ever contains node/cidr/domain/any remotes.
type GroupSelector ¶ added in v0.2.4
type GroupSelector struct {
MatchTagsAny []string `json:"match_tags_any,omitempty"`
MatchRoles []string `json:"match_roles,omitempty"`
MatchCountry []string `json:"match_country,omitempty"` // ISO-3166 alpha-2 codes
MatchContinent []string `json:"match_continent,omitempty"` // AS/EU/NA/SA/AF/OC/AN
}
GroupSelector is a dynamic "smart group" membership rule. Dashboard grouping uses it for previews, and group-policy planning uses the current match set when expanding policies into per-node nft plans. Each field is an OR-set; a node matches the selector when it satisfies any one of the populated criteria (tags-any / roles / country / continent).
type GuardInterface ¶ added in v0.2.17
type GuardInterface struct {
Name string `json:"name"`
Addresses []string `json:"addresses,omitempty"`
Up bool `json:"up,omitempty"`
}
GuardInterface is one network interface from a node reality report.
type GuardListener ¶ added in v0.2.17
type GuardListener struct {
Protocol string `json:"protocol"` // tcp | udp
Port int `json:"port"`
Address string `json:"address,omitempty"`
Process string `json:"process,omitempty"`
}
GuardListener is one listening socket from a node reality report.
type GuardNodeReality ¶ added in v0.2.17
type GuardNodeReality struct {
NodeID string `json:"node_id"`
Listeners []GuardListener `json:"listeners,omitempty"`
Interfaces []GuardInterface `json:"interfaces,omitempty"`
ManagedSHA string `json:"managed_sha,omitempty"`
ForeignTables []string `json:"foreign_tables,omitempty"`
NFTVersion string `json:"nft_version,omitempty"`
CollectedAt time.Time `json:"collected_at"`
}
GuardNodeReality is the agent-reported ground truth for reality-first authoring and drift detection (design-13 §4.3). It is low-trust input: it feeds suggestions, diffs, and display only — never silent policy.
type GuardPortRange ¶ added in v0.2.17
GuardPortRange is an inclusive L4 port range; From == To expresses a single port. Security-group rules use ranges instead of bare port lists so "9009-9013" stays one reviewable entry (design-13 §4.2).
type GuardRule ¶ added in v0.2.17
type GuardRule struct {
ID string `json:"id"`
Comment string `json:"comment,omitempty"`
Action string `json:"action"` // allow | deny
Direction string `json:"direction"` // ingress | egress
Protocol string `json:"protocol"` // tcp | udp | icmp | icmpv6 | any
Ports []GuardPortRange `json:"ports,omitempty"`
Remote NetEndpoint `json:"remote"` // Kind may additionally be NetRefZone
Log bool `json:"log,omitempty"`
Disabled bool `json:"disabled,omitempty"`
}
GuardRule is one ordered security-group rule. Empty Ports means all ports for the selected protocol. Log is an L2 render surface (design-13 §4.6): the field is part of the authoring contract now, but the compiler rejects it until renderer support lands.
type GuardZone ¶ added in v0.2.17
type GuardZone struct {
ID string `json:"id"`
Name string `json:"name"`
Builtin bool `json:"builtin,omitempty"`
Interfaces []string `json:"interfaces,omitempty"`
CIDRs []string `json:"cidrs,omitempty"`
Description string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
GuardZone is a named trust surface built from interface names and/or CIDRs. Builtin zones carry well-known ids (GuardZone* constants) and resolve per-node facts (public interface, overlay membership) at compile/view time; operator zones pin explicit interfaces/CIDRs. Zone references appear both as a rule remote (match scope) and as a node binding's trusted-zone list (full accept), reviewed like every other plan input. (design-13 §4.1)
type HostFacts ¶ added in v0.2.0
type HostFacts struct {
Hostname string `json:"hostname,omitempty"`
OS string `json:"os,omitempty"`
Platform string `json:"platform,omitempty"`
PlatformVersion string `json:"platform_version,omitempty"`
KernelVersion string `json:"kernel_version,omitempty"`
Arch string `json:"arch,omitempty"`
CPUCores int `json:"cpu_cores,omitempty"`
CPUModel string `json:"cpu_model,omitempty"`
MemoryTotal uint64 `json:"memory_total,omitempty"`
SwapTotal uint64 `json:"swap_total,omitempty"`
Virtualization string `json:"virtualization,omitempty"`
BootTime time.Time `json:"boot_time,omitempty"`
ReportedAt time.Time `json:"reported_at,omitempty"`
}
HostFacts are auto-detected, slow-changing machine facts reported by the node-agent. They are advisory low-trust telemetry: useful for display, inventory and map planning, but never for authorization decisions.
type LogBatch ¶ added in v0.2.0
type LogBatch struct {
SourceID string `json:"source_id"`
Path string `json:"path"` // echoed for server cross-check vs the source record
RotID string `json:"rot_id"` // opaque per-file-incarnation id (inode/ctime)
FirstOff uint64 `json:"first_off"` // offset before the first line in this batch
LastOff uint64 `json:"last_off"` // offset after the last line (== agent checkpoint)
Dropped uint64 `json:"dropped"` // lines the agent dropped (backpressure) since last batch
Lines []string `json:"lines"` // raw lines, ordered, no trailing newline
CapturedAt time.Time `json:"captured_at"`
}
LogBatch is the agent -> server ingest envelope (one source per batch).
type LogLine ¶ added in v0.2.0
type LogLine struct {
SourceID string `json:"source_id"`
NodeID string `json:"node_id"`
Path string `json:"path"`
Seq uint64 `json:"seq"`
Offset uint64 `json:"offset"`
At time.Time `json:"at"`
Line string `json:"line"`
Truncated bool `json:"truncated,omitempty"`
}
LogLine is one ingested line as persisted/queried. Seq is the server-assigned monotonic per-source ingest sequence (the query cursor); Offset is the agent's byte offset after this line in the (rotation-scoped) source file.
type LogSource ¶ added in v0.2.0
type LogSource struct {
ID string `json:"id"`
Name string `json:"name"`
NodeID string `json:"node_id"`
Path string `json:"path"`
Enabled bool `json:"enabled"`
MaxLineBytes int `json:"max_line_bytes"` // truncate longer lines (server default 16384)
MaxBatchLines int `json:"max_batch_lines"` // agent batch cap (server default 500)
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
LogSource declares a file on a node whose appended lines are tailed by the assigned agent and shipped to the server. It is assignment-driven like Monitor: exactly one node owns a source (a path is node-local), identified by NodeID. LogSource carries no secrets.
type MachineProfile ¶ added in v0.2.0
type MachineProfile struct {
ID string `json:"id"`
NodeID string `json:"node_id"`
Label string `json:"label,omitempty"`
Vendor string `json:"vendor,omitempty"`
ConsoleURL string `json:"console_url,omitempty"`
DetailURL string `json:"detail_url,omitempty"`
Region string `json:"region,omitempty"`
Notes string `json:"notes,omitempty"`
PriceCents int64 `json:"price_cents,omitempty"`
Currency string `json:"currency,omitempty"`
PurchasedAt time.Time `json:"purchased_at,omitempty"`
RenewalCycle string `json:"renewal_cycle,omitempty"`
CycleDays int `json:"cycle_days,omitempty"`
NextRenewal time.Time `json:"next_renewal,omitempty"`
AutoRoll bool `json:"auto_roll"`
RemindDaysBefore []int `json:"remind_days_before,omitempty"`
RemindersEnabled bool `json:"reminders_enabled"`
LastRemindedKey string `json:"last_reminded_key,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
MachineProfile is operator-authored inventory, cost, and renewal metadata for a node. It is server-only control-plane state: it must never be sent to an agent or used by an agent. ConsoleURL and DetailURL may carry account-specific or signed links and are encrypted at rest by lattice-server.
type MachineVendor ¶ added in v0.2.17
type MachineVendor struct {
ID string `json:"id"`
Name string `json:"name"`
URL string `json:"url,omitempty"`
LogoURL string `json:"logo_url,omitempty"`
Description string `json:"description,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
MachineVendor is operator-authored metadata for a provider/vendor referenced by machine profiles. MachineProfile.Vendor remains the compatibility key; the server matches this record by Name so old profiles do not require migration.
type Metrics ¶
type Metrics struct {
CPUPercent float64 `json:"cpu_percent"`
Load1 float64 `json:"load1"`
Load5 float64 `json:"load5"`
Load15 float64 `json:"load15"`
MemoryUsed uint64 `json:"memory_used"`
MemoryTotal uint64 `json:"memory_total"`
DiskUsed uint64 `json:"disk_used"`
DiskTotal uint64 `json:"disk_total"`
NetRxBytes uint64 `json:"net_rx_bytes"`
NetTxBytes uint64 `json:"net_tx_bytes"`
// NetRxSpeed / NetTxSpeed are bytes-per-second rates the agent derives from
// the delta of the cumulative byte counters between two metrics cycles. The
// first cycle after agent start (no prior sample) and any counter reset both
// report 0. Dashboards read these for live bandwidth; the cumulative
// NetRxBytes/NetTxBytes remain the source of truth.
NetRxSpeed float64 `json:"net_rx_speed"`
NetTxSpeed float64 `json:"net_tx_speed"`
UptimeSeconds uint64 `json:"uptime_seconds"`
CollectedAt time.Time `json:"collected_at"`
}
type Monitor ¶ added in v0.2.0
type Monitor struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Target string `json:"target"`
IntervalSec int `json:"interval_sec"`
TimeoutSec int `json:"timeout_sec"`
AssignAll bool `json:"assign_all"`
NodeIDs []string `json:"node_ids,omitempty"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Monitor is a periodic reachability/latency probe executed by assigned agents. Targets are host:port for tcp/icmp probes and a URL for http probes. A monitor runs on every node when AssignAll is set, otherwise on the nodes in NodeIDs — this is how a group's members continuously measure their group leader.
type MonitorResult ¶ added in v0.2.0
type MonitorResult struct {
MonitorID string `json:"monitor_id"`
NodeID string `json:"node_id"`
At time.Time `json:"at"`
Success bool `json:"success"`
LatencyMs float64 `json:"latency_ms"`
Error string `json:"error,omitempty"`
}
MonitorResult is a single probe outcome reported by an agent.
type NFTInputs ¶ added in v0.2.0
type NFTInputs struct {
ID string `json:"id"`
NodeID string `json:"node_id"`
InterfaceName string `json:"interface_name,omitempty"`
WireGuardCIDR string `json:"wireguard_cidr,omitempty"`
PublicTCP []int `json:"public_tcp,omitempty"`
PublicUDP []int `json:"public_udp,omitempty"`
WireGuardTCP []int `json:"wireguard_tcp,omitempty"`
WireGuardUDP []int `json:"wireguard_udp,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
NFTInputs are the authoritative, server-owned baseline nftables inputs for a single node. Other core providers (DNS, per-node ACL, proxy cores) compose their required ports/rules into this shape before rendering the one lattice_guard table; they must not create competing nft tables.
type NetEndpoint ¶ added in v0.2.0
type NetEndpoint struct {
Kind string `json:"kind"`
NodeID string `json:"node_id,omitempty"`
CIDR string `json:"cidr,omitempty"`
Domain string `json:"domain,omitempty"`
GroupID string `json:"group_id,omitempty"` // set when Kind == NetRefGroup; resolved to node refs before compile
ZoneID string `json:"zone_id,omitempty"` // set when Kind == NetRefZone; resolved to iface/CIDR matches before compile
}
NetEndpoint describes the non-target side of a policy rule. Node refs are resolved by the server at validation/graph/compile time. Domain refs are egress-only and compile to named nft sets that the node refreshes through the agent's DNS updater; they are not accepted as ingress identity.
type NetPolicy ¶ added in v0.2.0
type NetPolicy struct {
ID string `json:"id"`
TargetNodeID string `json:"target_node_id"`
Rules []NetRule `json:"rules"`
Enabled bool `json:"enabled"`
// GroupDerived marks a per-node policy materialized from one or more
// GroupNetPolicy documents (server-side expansion). Manually-authored
// per-node policies leave it false. Materialization refuses to overwrite a
// manual policy, so the two authoring lanes never silently clobber.
GroupDerived bool `json:"group_derived,omitempty"`
LastPlanSHA string `json:"last_plan_sha,omitempty"`
LastAppliedAt time.Time `json:"last_applied_at,omitempty"`
LastError string `json:"last_error,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
NetPolicy is the per-node network intent document. It is control-plane state only: the agent does not receive it directly. A later iteration compiles this policy into nft with dead-man rollback.
type NetRule ¶ added in v0.2.0
type NetRule struct {
ID string `json:"id"`
Comment string `json:"comment,omitempty"`
Action string `json:"action"`
Direction string `json:"direction"`
Protocol string `json:"protocol"`
Ports []int `json:"ports,omitempty"`
Remote NetEndpoint `json:"remote"`
Disabled bool `json:"disabled,omitempty"`
}
NetRule is an ordered operator-authored L3/L4 policy rule evaluated on the target node. Empty Ports means all ports for the selected protocol.
type Node ¶
type Node struct {
ID string `json:"id"`
LatticeIdentityUUID string `json:"lattice_identity_uuid,omitempty"`
Name string `json:"name"`
Comment string `json:"comment,omitempty"`
TokenHash string `json:"token_hash"`
Tags []string `json:"tags"`
Role string `json:"role"`
// Inventory is operator-registered provenance/quality metadata (dashboard
// fleet inventory). Operator-owned; agents never report or overwrite it.
Inventory *NodeInventory `json:"inventory,omitempty"`
WireGuardIP string `json:"wireguard_ip"`
WireGuardPublicKey string `json:"wireguard_public_key,omitempty"`
WireGuardEndpoint string `json:"wireguard_endpoint,omitempty"`
WireGuardPort int `json:"wireguard_port,omitempty"`
PublicIP string `json:"public_ip"`
PublicIPv6 string `json:"public_ipv6,omitempty"`
// InternalIP / InternalIPv6 are the node's LAN/primary-interface addresses,
// reported by the agent. Informational (not geocoded); private ranges allowed.
InternalIP string `json:"internal_ip,omitempty"`
InternalIPv6 string `json:"internal_ipv6,omitempty"`
AgentVersion string `json:"agent_version"`
Online bool `json:"online"`
Disabled bool `json:"disabled,omitempty"`
// AgentSourceAllowlist optionally restricts node-agent bearer-token use to
// exact source IPs or CIDR prefixes as resolved by the server's client-IP
// trust policy. Empty means no source-address restriction.
AgentSourceAllowlist []string `json:"agent_source_allowlist,omitempty"`
// TokenLastUsedAt is coarse lifecycle telemetry for the node credential. It
// is updated only after successful bearer-token authentication and may be
// write-throttled by the server to avoid heartbeat write amplification.
TokenLastUsedAt time.Time `json:"token_last_used_at,omitempty"`
LastSeen time.Time `json:"last_seen"`
Metrics Metrics `json:"metrics"`
HostFacts HostFacts `json:"host_facts"`
Geo *NodeGeo `json:"geo,omitempty"`
AgentDebug AgentDebugPolicy `json:"agent_debug"`
// AgentLaunch is the last operator-authored installer/startup profile used
// to generate an enrollment or reconfigure command. It is advisory desired
// state, not proof of the currently running process flags.
AgentLaunch *AgentLaunchConfig `json:"agent_launch,omitempty"`
// TerminalTransport is the operator-owned per-node terminal transport: "poll"
// (default) or "stream". Empty is treated as the deployment default. It is the
// rollout lever for promoting the streaming terminal one node at a time; the
// agent reads it from its polled AgentConfig and applies it to new sessions.
TerminalTransport string `json:"terminal_transport,omitempty"`
// IPConfig is the operator-owned, per-node override for how the agent
// discovers its public IPs (mirrors the agent's -ip-mode/-ip-resolvers
// flags). nil means "no override" — the agent keeps its startup flags. It is
// pushed down through the polled AgentConfig.
IPConfig *NodeIPConfig `json:"ip_config,omitempty"`
// GroupIDs is the node's resolved group memberships. It is a server-computed,
// read-only convenience field (the union of every group whose explicit
// Members or display Selector resolves this node); it is never authored by a
// client and is not persisted as node intent. Tags/Role remain the underlying
// facts that selectors read.
GroupIDs []string `json:"group_ids,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type NodeGeo ¶ added in v0.2.0
type NodeGeo struct {
Country string `json:"country,omitempty"`
Region string `json:"region,omitempty"`
City string `json:"city,omitempty"`
Lat float64 `json:"lat,omitempty"`
Lon float64 `json:"lon,omitempty"`
IP string `json:"ip,omitempty"`
ASN int `json:"asn,omitempty"`
ASOrg string `json:"as_org,omitempty"`
Provider string `json:"provider,omitempty"`
Source string `json:"source,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
NodeGeo is map metadata for a node. Operator-entered values are authoritative; automatic GeoIP values are advisory and should not overwrite operator values unless an operator explicitly asks for that replacement.
type NodeGuardBinding ¶ added in v0.2.17
type NodeGuardBinding struct {
NodeID string `json:"node_id"`
GroupIDs []string `json:"group_ids"`
Overrides []GuardRule `json:"overrides,omitempty"`
ZoneIDs []string `json:"zone_ids,omitempty"`
Managed bool `json:"managed"`
Version int64 `json:"version"`
LastPlanSHA string `json:"last_plan_sha,omitempty"`
LastAppliedAt time.Time `json:"last_applied_at,omitempty"`
LastError string `json:"last_error,omitempty"`
AppliedTableSHA string `json:"applied_table_sha,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
NodeGuardBinding composes a node's effective firewall: base scaffold, then trusted zones, then Overrides, then attached groups in GroupIDs order. Managed=false marks an observe-only node the compiler must refuse to plan. The Last*/AppliedTableSHA fields carry apply state and the drift anchor the legacy NFTInputs record never had (design-13 §4.2).
type NodeIPConfig ¶ added in v0.2.5
type NodeIPConfig struct {
Mode string `json:"mode,omitempty"` // "" | auto | static | resolver | script
StaticIPv4 string `json:"static_ipv4,omitempty"`
StaticIPv6 string `json:"static_ipv6,omitempty"`
Resolvers []string `json:"resolvers,omitempty"` // IP-echo URLs; empty = agent defaults
Script string `json:"script,omitempty"` // server->agent only; redact from node views
ScriptSHA256 string `json:"script_sha256,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
}
NodeIPConfig is the operator-owned, per-node override for how the agent determines its public IPs. It mirrors the agent's -ip-mode / -ip-resolvers / -public-ip startup flags so the server can push a change without a redeploy. An empty Mode means "no override". Script discovery is high-trust node-local code: the server stores Script for the agent only, and read-facing node views should redact Script while keeping ScriptSHA256 for operator confirmation.
type NodeInventory ¶ added in v0.2.15
type NodeInventory struct {
// PurityPercent is the operator-assessed IP purity score, 0-100.
PurityPercent *int `json:"purity_percent,omitempty"`
// Quality is a coarse grade such as "high", "medium", "low" (free-form, <=64 chars).
Quality string `json:"quality,omitempty"`
// Notes is free-form inventory context (<=2048 chars, matching MachineProfile.Notes).
Notes string `json:"notes,omitempty"`
}
NodeInventory carries the operator's own assessment of a node's provenance quality — e.g. "98% pure, high quality" residential/ISP purity notes kept in the fleet inventory. Purely informational; nothing in the control plane branches on it.
type NotifyChannel ¶ added in v0.2.0
type NotifyChannel struct {
ID string `json:"id"`
Name string `json:"name"`
Kind string `json:"kind"`
Config map[string]string `json:"config,omitempty"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
NotifyChannel is a persisted notification destination. Config holds provider-specific fields (e.g. token, chat_id, webhook_url); its values are secret and never serialized back to clients.
type NotifyRule ¶ added in v0.2.1
type NotifyRule struct {
ID string `json:"id"`
Name string `json:"name"`
EventTypes []string `json:"event_types,omitempty"`
ChannelIDs []string `json:"channel_ids,omitempty"`
TitleTemplate string `json:"title_template,omitempty"`
BodyTemplate string `json:"body_template,omitempty"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
NotifyRule routes notification events to one or more destinations. EventTypes uses stable server event ids such as monitor.down or ssh.login; "*" matches all notification events. Templates are intentionally small string templates expanded by the server with event_type, title, and body variables.
type OIDCIdentity ¶ added in v0.2.0
type OIDCIdentity struct {
ProviderID string `json:"provider_id"`
Issuer string `json:"issuer"`
Subject string `json:"subject"`
UserID string `json:"user_id"`
Email string `json:"email,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
OIDCIdentity is the durable link between an external subject and a local user. Keyed in the store by (ProviderID, Subject): the trust anchor is the admin-vetted provider record, not the bare issuer string, so a second provider that happens to share an issuer cannot reuse another provider's links. Subject is the stable identifier; Email/Issuer are reference only.
type OIDCProvider ¶ added in v0.2.0
type OIDCProvider struct {
ID string `json:"id"`
DisplayName string `json:"display_name"`
Issuer string `json:"issuer"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret,omitempty"`
Scopes []string `json:"scopes,omitempty"`
AllowedDomains []string `json:"allowed_domains,omitempty"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
OIDCProvider is an admin-configured external identity provider for SSO login. ClientSecret is a secret-at-rest field (encrypted by the store boundary) and is never returned by the API.
type PluginInstallation ¶ added in v0.2.0
type PluginInstallation struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Version string `json:"version,omitempty"`
Entrypoint string `json:"entrypoint,omitempty"`
Publisher string `json:"publisher,omitempty"`
Capabilities []string `json:"capabilities"`
ArtifactSHA256 string `json:"artifact_sha256,omitempty"`
BundlePath string `json:"bundle_path,omitempty"`
Status string `json:"status"`
VerifiedAt time.Time `json:"verified_at,omitempty"`
InstalledAt time.Time `json:"installed_at,omitempty"`
ActivatedAt time.Time `json:"activated_at,omitempty"`
DisabledAt time.Time `json:"disabled_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
PluginInstallation is the persisted lifecycle record for a verified plugin bundle. It is intentionally metadata-only: artifacts and runtime handles stay outside the shared API model.
type ProxyInbound ¶ added in v0.2.0
type ProxyInbound struct {
ID string `json:"id"`
Name string `json:"name"`
Core string `json:"core"`
Protocol string `json:"protocol"`
Listen string `json:"listen,omitempty"`
Port int `json:"port"`
Transport string `json:"transport,omitempty"`
Path string `json:"path,omitempty"`
Host string `json:"host,omitempty"`
Security string `json:"security,omitempty"`
SNI string `json:"sni,omitempty"`
ALPN []string `json:"alpn,omitempty"`
Fingerprint string `json:"fingerprint,omitempty"`
CertPath string `json:"cert_path,omitempty"`
KeyPath string `json:"key_path,omitempty"`
RealityPrivateKey string `json:"reality_private_key,omitempty"`
RealityPublicKey string `json:"reality_public_key,omitempty"`
RealityShortIDs []string `json:"reality_short_ids,omitempty"`
RealityDest string `json:"reality_dest,omitempty"`
SSMethod string `json:"ss_method,omitempty"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ProxyInbound is the central protocol/transport template that the server renders into node-local sing-box/xray config. RealityPrivateKey is a server-side secret and must never appear in API views or agent payloads.
type ProxyNodeProfile ¶ added in v0.2.0
type ProxyNodeProfile struct {
ID string `json:"id"`
NodeID string `json:"node_id"`
Core string `json:"core"`
InboundIDs []string `json:"inbound_ids"`
Hostname string `json:"hostname,omitempty"`
ListenIP string `json:"listen_ip,omitempty"`
ConfigPath string `json:"config_path,omitempty"`
StatsAPI string `json:"stats_api,omitempty"`
AppliedSHA256 string `json:"applied_sha256,omitempty"`
LastApplyAt time.Time `json:"last_apply_at,omitempty"`
LastError string `json:"last_error,omitempty"`
// Usage collector health is agent-reported and server persisted for
// operator visibility. It is not client-editable policy and must not affect
// the server's monotonic usage accounting.
UsageCollectorSource string `json:"usage_collector_source,omitempty"`
UsageCollectorStatus string `json:"usage_collector_status,omitempty"`
UsageCollectorCheckedAt time.Time `json:"usage_collector_checked_at,omitempty"`
UsageCollectorLastOKAt time.Time `json:"usage_collector_last_ok_at,omitempty"`
UsageCollectorLastError string `json:"usage_collector_last_error,omitempty"`
UsageCollectorLastErrorAt time.Time `json:"usage_collector_last_error_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ProxyNodeProfile binds the central proxy model to a single node. One profile exists per node; it is the unit rendered into a reviewed plan/apply task.
type ProxyUsageSnapshot ¶ added in v0.2.0
type ProxyUsageSnapshot struct {
NodeID string `json:"node_id"`
At time.Time `json:"at"`
CoreUptimeSec uint64 `json:"core_uptime_sec"`
UserBytes map[string]int64 `json:"user_bytes"`
// LineUserBytes optionally carries cumulative counters split by stable
// line_hash_id and proxy user id. It is additive to UserBytes so old
// collectors remain valid; if a collector sends only line_user_bytes, agents
// and servers may derive user_bytes by summing per-user line counters.
LineUserBytes map[string]map[string]int64 `json:"line_user_bytes,omitempty"`
// Collector fields describe this collection attempt. They let the agent
// report local collector errors without overwriting the previous accounting
// baseline on the server.
CollectorSource string `json:"collector_source,omitempty"` // file | http | future core transport
CollectorStatus string `json:"collector_status,omitempty"` // ok | error
CollectorError string `json:"collector_error,omitempty"`
CollectorCheckedAt time.Time `json:"collector_checked_at,omitempty"`
}
ProxyUsageSnapshot is the last node-reported accounting snapshot. The server later diffs successive snapshots to advance ProxyUser.UsedBytes monotonically.
type ProxyUser ¶ added in v0.2.0
type ProxyUser struct {
ID string `json:"id"`
Name string `json:"name"`
Enabled bool `json:"enabled"`
UUID string `json:"uuid,omitempty"`
Password string `json:"password,omitempty"`
SubToken string `json:"sub_token,omitempty"`
InboundIDs []string `json:"inbound_ids,omitempty"`
TrafficLimitBytes int64 `json:"traffic_limit_bytes,omitempty"`
ExpiresAt time.Time `json:"expires_at,omitempty"`
UsedBytes int64 `json:"used_bytes"`
LastSeenAt time.Time `json:"last_seen_at,omitempty"`
Status string `json:"status"`
// Server-managed notification cursors. They prevent repeated quota/expiry
// alerts after the operator has already been notified for the current limit
// or expiry date.
LastQuotaNotifiedKey string `json:"last_quota_notified_key,omitempty"`
LastExpiryNotifiedKey string `json:"last_expiry_notified_key,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
ProxyUser is a central subscriber identity. UUID, Password and SubToken are bearer credential material; they are encrypted at rest and only surfaced through one-time/admin rotation flows, never through list/read views.
type SecurityGroup ¶ added in v0.2.17
type SecurityGroup struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description,omitempty"`
Rules []GuardRule `json:"rules"`
Version int64 `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
SecurityGroup is a named, reusable, ordered rule set attachable to any number of nodes through NodeGuardBinding. Version implements optimistic concurrency on upserts so two operators cannot silently clobber each other (design-13 §4.2, closing the NFTInputs gap).
type SingBoxInventory ¶ added in v0.2.7
type SingBoxInventory struct {
NodeID string `json:"node_id"`
At time.Time `json:"at"`
CoreVersion string `json:"core_version,omitempty"`
Nodes []SingBoxNode `json:"nodes"`
Status string `json:"status,omitempty"` // ok | error
Error string `json:"error,omitempty"`
}
SingBoxInventory is the latest snapshot of the sing-box nodes discovered on one machine. It is reported by the agent (read-only `sb --json list`) and held in memory on the server as a live mirror — it is re-reported each interval and is not persisted (a restart simply waits for the next report). Status/Error let a node report a discovery failure (e.g. sb not installed) without a stale list.
type SingBoxNode ¶ added in v0.2.7
type SingBoxNode struct {
Name string `json:"name"`
LineID string `json:"line_id,omitempty"`
LineUUID string `json:"line_uuid,omitempty"` // design-15 D1: control-plane line identity from the sidecar
NodeIdentityUUID string `json:"node_identity_uuid,omitempty"`
Protocol string `json:"protocol,omitempty"`
Network string `json:"network,omitempty"`
Address string `json:"address,omitempty"`
Port string `json:"port,omitempty"`
SNI string `json:"sni,omitempty"`
Host string `json:"host,omitempty"`
ListenHost string `json:"listen_host,omitempty"`
OutboundRef string `json:"outbound_ref,omitempty"`
OutboundServer string `json:"outbound_server,omitempty"`
OutboundPort string `json:"outbound_port,omitempty"`
OutboundType string `json:"outbound_type,omitempty"`
// DownstreamLineUUID is the declared chain edge target (design-15 §6), read
// from the sidecar chain block; empty when the line is single-exit or the
// edge is only inferable from outbound host/port.
DownstreamLineUUID string `json:"downstream_line_uuid,omitempty"`
UserCount int `json:"user_count,omitempty"`
UserKnown bool `json:"user_known,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
PublicKey string `json:"public_key,omitempty"`
}
SingBoxNode is one inbound discovered on a node by reading its on-box sing-box management state (the 233boy `sb --json list` output). It is the adoption-model view of a proxy that exists on the machine but is NOT (necessarily) managed by Lattice's own proxy store — the bridge that lets the dashboard see proxies on machines provisioned out-of-band. Secret-free: share_url already encodes the connection without exposing additional server-side material.
type StaticObject ¶
type StorageAccessToken ¶ added in v0.2.1
type StorageAccessToken struct {
ID string `json:"id"`
Name string `json:"name"`
TokenHash string `json:"token_hash,omitempty"`
Kind string `json:"kind"`
Access string `json:"access"`
Buckets []string `json:"buckets,omitempty"`
RevokedAt time.Time `json:"revoked_at,omitempty"`
LastUsedAt time.Time `json:"last_used_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type StorageBinding ¶ added in v0.2.1
type StorageBinding struct {
ID string `json:"id"`
Kind string `json:"kind"`
Bucket string `json:"bucket"`
Hostname string `json:"hostname"`
PathPrefix string `json:"path_prefix,omitempty"`
Enabled bool `json:"enabled"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type StorageBucket ¶ added in v0.2.1
type StorageBucket struct {
ID string `json:"id"`
Kind string `json:"kind"`
Name string `json:"name"`
DisplayName string `json:"display_name,omitempty"`
Description string `json:"description,omitempty"`
IndexDocument string `json:"index_document,omitempty"`
NotFoundDocument string `json:"not_found_document,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type Task ¶
type Task struct {
ID string `json:"id"`
ApprovalID string `json:"approval_id,omitempty"`
ActorID string `json:"actor_id"`
TokenID string `json:"token_id"`
Targets []string `json:"targets"`
Interpreter string `json:"interpreter"`
Script string `json:"script"`
TimeoutSec int `json:"timeout_sec"`
OutputLimit int `json:"output_limit"`
Status string `json:"status"`
LeaseID string `json:"lease_id,omitempty"`
LeasedBy string `json:"leased_by,omitempty"`
TargetLeases map[string]TaskLease `json:"target_leases,omitempty"`
RerunOfTaskID string `json:"rerun_of_task_id,omitempty"`
RerunOfNodeID string `json:"rerun_of_node_id,omitempty"`
CreatedAt time.Time `json:"created_at"`
StartedAt time.Time `json:"started_at,omitempty"`
FinishedAt time.Time `json:"finished_at,omitempty"`
}
type TaskResult ¶
type TaskResult struct {
TaskID string `json:"task_id"`
LeaseID string `json:"lease_id,omitempty"`
NodeID string `json:"node_id"`
ExitCode int `json:"exit_code"`
Stdout string `json:"stdout"`
Stderr string `json:"stderr"`
Error string `json:"error"`
StartedAt time.Time `json:"started_at"`
FinishedAt time.Time `json:"finished_at"`
}
type TerminalEvent ¶ added in v0.2.3
type TerminalInput ¶ added in v0.2.3
type TerminalSession ¶ added in v0.2.3
type TerminalSession struct {
ID string `json:"id"`
NodeID string `json:"node_id"`
ActorID string `json:"actor_id,omitempty"`
TokenID string `json:"token_id,omitempty"`
Shell string `json:"shell,omitempty"`
Cols int `json:"cols,omitempty"`
Rows int `json:"rows,omitempty"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
BytesIn int64 `json:"bytes_in,omitempty"`
BytesOut int64 `json:"bytes_out,omitempty"`
CreatedAt time.Time `json:"created_at"`
OpenedAt time.Time `json:"opened_at,omitempty"`
ClosedAt time.Time `json:"closed_at,omitempty"`
LastSeen time.Time `json:"last_seen,omitempty"`
}
type Token ¶
type Token struct {
ID string `json:"id"`
Name string `json:"name"`
TokenHash string `json:"token_hash"`
ActorID string `json:"actor_id"`
Scopes []string `json:"scopes"`
ServerAllowlist []string `json:"server_allowlist"`
RevokedAt time.Time `json:"revoked_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type TunnelIngress ¶ added in v0.2.0
type TunnelIngress struct {
Hostname string `json:"hostname"`
Service string `json:"service"`
Path string `json:"path,omitempty"`
}
TunnelIngress maps a public hostname to a node-local service for a Cloudflare Tunnel. Service is a cloudflared service URL, e.g. http://localhost:8088, ssh://localhost:22, or the literal http_status:404.
type TunnelProfile ¶ added in v0.2.0
type TunnelProfile struct {
ID string `json:"id"`
Name string `json:"name"`
NodeID string `json:"node_id"`
TunnelID string `json:"tunnel_id"`
CredentialsFile string `json:"credentials_file,omitempty"`
Ingress []TunnelIngress `json:"ingress"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
TunnelProfile describes a Cloudflare Tunnel deployed on a node. Credentials are node-local (CredentialsFile path); the server only stores the topology.
type User ¶
type User struct {
ID string `json:"id"`
Username string `json:"username"`
PasswordHash string `json:"password_hash"`
Scopes []string `json:"scopes"`
TOTPEnabled bool `json:"totp_enabled"`
TOTPSecret string `json:"totp_secret,omitempty"`
RecoveryCodeHashes []string `json:"recovery_code_hashes,omitempty"`
// LastTOTPStep is the highest RFC-6238 counter accepted for this user. A
// successful verification must present a strictly greater step, which makes
// each code single-use and prevents replay within the validity window.
LastTOTPStep uint64 `json:"last_totp_step,omitempty"`
// SecurityEpoch is bumped on password change, 2FA disable, or admin revoke.
// Sessions carry the epoch at which they were minted; a session whose epoch
// is older than the user's current epoch is rejected, so privilege-reducing
// events invalidate all existing sessions.
SecurityEpoch uint64 `json:"security_epoch,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type WGExternalPeer ¶ added in v0.2.17
type WGExternalPeer struct {
ID string `json:"id"`
NetworkID string `json:"network_id"`
Name string `json:"name"`
Address string `json:"address"`
PublicKey string `json:"public_key"`
AllowedIPs []string `json:"allowed_ips,omitempty"`
LastIssuedAt time.Time `json:"last_issued_at,omitempty"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
WGExternalPeer is a non-node device (laptop, phone). Its private key is generated server-side, rendered once for the operator, and never persisted: only the public key and metadata survive. Regeneration mints a new key and invalidates the old config.
type WGMembership ¶ added in v0.2.17
type WGMembership struct {
NetworkID string `json:"network_id"`
NodeID string `json:"node_id"`
Address string `json:"address"`
Role string `json:"role"` // hub | spoke | peer
InterfaceName string `json:"interface_name,omitempty"`
ListenPort int `json:"listen_port,omitempty"`
// Endpoint is the peer dial address rendered into WireGuard configs. It must
// be host:port, with IPv6 hosts bracketed as in net.JoinHostPort.
Endpoint string `json:"endpoint,omitempty"`
Keepalive int `json:"keepalive,omitempty"`
MTU int `json:"mtu,omitempty"`
ExtraAllowedIPs []string `json:"extra_allowed_ips,omitempty"`
Version int64 `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
WGMembership binds a node into a network. Address is server-allocated from the network CIDR and always pinned to a host route when it becomes a peer's AllowedIPs, so a member can never claim another member's address. ExtraAllowedIPs are additive routes a hub advertises (a LAN CIDR, or 0.0.0.0/0 for an exit node); they are reviewed in the plan like any other mutation and may never widen another member's pinned address.
type WGNetwork ¶ added in v0.2.17
type WGNetwork struct {
ID string `json:"id"`
Name string `json:"name"`
CIDR string `json:"cidr"`
Topology string `json:"topology"` // mesh | hub-and-spoke | custom
ListenPort int `json:"listen_port,omitempty"`
Keepalive int `json:"keepalive,omitempty"`
MTU int `json:"mtu,omitempty"`
DNS []string `json:"dns,omitempty"`
Description string `json:"description,omitempty"`
Version int64 `json:"version"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
WGNetwork is a named WireGuard network. A fleet may run several; a node may belong to more than one (one interface per membership).