queries

package
v0.5.2 Latest Latest
Warning

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

Go to latest
Published: May 18, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Index

Constants

View Source
const (
	// QueryTargetPlatform defines platform as target
	QueryTargetPlatform string = "platform"
	// QueryTargetLocalname defines localname as target
	QueryTargetLocalname string = "localname"
	// QueryTargetEnvironment defines environment as target
	QueryTargetEnvironment string = "environment"
	// QueryTargetUUID defines uuid as target
	QueryTargetUUID string = "uuid"
	// StandardQueryType defines a regular query
	StandardQueryType string = "query"
	// CarveQueryType defines a regular query
	CarveQueryType string = "carve"
	// MetadataQueryType defines a regular query
	MetadataQueryType string = "metadata"
)
View Source
const (
	// StatusActive defines active status constant
	StatusActive string = "ACTIVE"
	// StatusComplete defines complete status constant
	StatusComplete string = "COMPLETE"
	// StatusExpired defines expired status constant
	StatusExpired string = "EXPIRED"
)
View Source
const (
	// TargetAll for all queries but hidden
	TargetAll string = "all"
	// TargetAllFull for all queries including hidden ones
	TargetAllFull string = "all-full"
	// TargetActive for active queries
	TargetActive string = "active"
	// TargetHiddenActive for hidden active queries
	TargetHiddenActive string = "hidden-active"
	// TargetCompleted for completed queries
	TargetCompleted string = "completed"
	// TargetExpired for expired queries
	TargetExpired string = "expired"
	// TargetSaved for saved queries
	TargetSaved string = "saved"
	// TargetHiddenCompleted for hidden completed queries
	TargetHiddenCompleted string = "hidden-completed"
	// TargetDeleted for deleted queries
	TargetDeleted string = "deleted"
	// TargetHidden for hidden queries
	TargetHidden string = "hidden"
)
View Source
const (
	DistributedQueryStatusPending   string = "pending"
	DistributedQueryStatusCompleted string = "completed"
	DistributedQueryStatusError     string = "error"
	DistributedQueryStatusExpired   string = "expired"
)

Variables

View Source
var ErrSavedQueryExists = errors.New("saved query already exists")

ErrSavedQueryExists is returned by CreateSaved when the underlying unique index on (name, environment_id) rejects the insert because a row with the same key already exists. Callers should map this to a 409 Conflict response.

View Source
var QuerySamples = []QuerySample{

	{
		Name:        "host_overview",
		Description: "Hostname, platform, OS version, kernel — basic host identity.",
		SQL:         "SELECT hostname, computer_name, cpu_brand, physical_memory FROM system_info",
		Category:    CategoryRecon,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "os_version",
		Description: "Operating system name, version, codename, and build identifiers.",
		SQL:         "SELECT name, version, codename, major, minor, patch, platform, platform_like FROM os_version",
		Category:    CategoryRecon,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "kernel_info",
		Description: "Running kernel name and version.",
		SQL:         "SELECT name, version FROM kernel_info",
		Category:    CategoryRecon,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin},
	},
	{
		Name:        "uptime",
		Description: "How long the host has been up — in days, hours, minutes.",
		SQL:         "SELECT days, hours, minutes, seconds FROM uptime",
		Category:    CategoryRecon,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},

	{
		Name:        "running_processes",
		Description: "All running processes — pid, name, full path, parent pid.",
		SQL:         "SELECT pid, name, path, parent FROM processes",
		Category:    CategoryProcesses,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "processes_root",
		Description: "Processes running as root / SYSTEM. Quick way to spot abnormal privileged execution.",
		SQL:         "SELECT pid, name, path, uid, cmdline FROM processes WHERE uid = 0",
		Category:    CategoryProcesses,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin},
	},
	{
		Name:        "processes_no_disk",
		Description: "Running processes whose executable on disk is missing — classic injected/memory-only indicator.",
		SQL:         "SELECT pid, name, path FROM processes WHERE on_disk = 0",
		Category:    CategoryProcesses,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},

	{
		Name:        "local_users",
		Description: "All local user accounts — username, uid, gid, home directory, shell.",
		SQL:         "SELECT username, uid, gid, directory, shell FROM users",
		Category:    CategoryUsers,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "logged_in_users",
		Description: "Currently logged-in users with login time and remote host.",
		SQL:         "SELECT user, host, time, tty, type FROM logged_in_users",
		Category:    CategoryUsers,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "sudoers_groups",
		Description: "Group memberships — useful for spotting unexpected sudo / wheel / admin members.",
		SQL:         "SELECT username, groupname FROM users JOIN user_groups USING(uid) JOIN groups USING(gid)",
		Category:    CategoryUsers,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin},
	},

	{
		Name:        "listening_ports",
		Description: "TCP/UDP listeners with the binding process and PID.",
		SQL:         "SELECT pid, port, protocol, address, p.name AS process FROM listening_ports l JOIN processes p USING(pid)",
		Category:    CategoryNetwork,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "active_connections",
		Description: "Established outbound TCP connections — remote IP and port.",
		SQL:         "SELECT pid, local_address, local_port, remote_address, remote_port FROM process_open_sockets WHERE state = 'ESTABLISHED'",
		Category:    CategoryNetwork,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "arp_cache",
		Description: "ARP cache entries — recently-seen MAC↔IP pairs on the LAN.",
		SQL:         "SELECT address, mac, interface FROM arp_cache",
		Category:    CategoryNetwork,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "interface_addresses",
		Description: "All network-interface addresses with subnet masks and broadcast addresses.",
		SQL:         "SELECT interface, address, mask, broadcast FROM interface_addresses",
		Category:    CategoryNetwork,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},

	{
		Name:        "crontab_all",
		Description: "Every cron job on the host across system and per-user crontabs.",
		SQL:         "SELECT command, path, minute, hour, day_of_month, month, day_of_week FROM crontab",
		Category:    CategoryPersistence,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin},
	},
	{
		Name:        "systemd_units",
		Description: "Loaded systemd units — name, state, file path. Look for unfamiliar service files.",
		SQL:         "SELECT id, fragment_path, active_state, sub_state, unit_file_state FROM systemd_units",
		Category:    CategoryPersistence,
		Platforms:   []QuerySamplePlatform{PlatformLinux},
	},
	{
		Name:        "launchd_overview",
		Description: "macOS launchd jobs — daemons and agents loaded at boot/login.",
		SQL:         "SELECT name, path, program, run_at_load, keep_alive, disabled FROM launchd",
		Category:    CategoryPersistence,
		Platforms:   []QuerySamplePlatform{PlatformDarwin},
	},
	{
		Name:        "startup_items",
		Description: "Windows autostart entries — Run/RunOnce registry keys and Startup folders.",
		SQL:         "SELECT name, path, source, status, type FROM startup_items",
		Category:    CategoryPersistence,
		Platforms:   []QuerySamplePlatform{PlatformWindows},
	},
	{
		Name:        "scheduled_tasks_windows",
		Description: "Windows Task Scheduler jobs — name, action, last_run_time, enabled state.",
		SQL:         "SELECT name, action, path, enabled, last_run_time, next_run_time FROM scheduled_tasks",
		Category:    CategoryPersistence,
		Platforms:   []QuerySamplePlatform{PlatformWindows},
	},
	{
		Name:        "services_windows",
		Description: "Windows services — name, display_name, start_type, status, path on disk.",
		SQL:         "SELECT name, display_name, status, start_type, path FROM services",
		Category:    CategoryPersistence,
		Platforms:   []QuerySamplePlatform{PlatformWindows},
	},

	{
		Name:        "etc_passwd",
		Description: "Hash, size, owner, permissions of /etc/passwd — classic file-integrity check.",
		SQL:         "SELECT path, size, mode, uid, gid, mtime, sha256 FROM file WHERE path = '/etc/passwd'",
		Category:    CategoryFileIntegrity,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin},
	},
	{
		Name:        "etc_hosts_contents",
		Description: "Lines of /etc/hosts — quick way to spot tampering or DNS-override mischief.",
		SQL:         "SELECT address, hostnames FROM etc_hosts",
		Category:    CategoryFileIntegrity,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},
	{
		Name:        "windows_hosts_file",
		Description: "Hash and metadata of the Windows hosts file — should rarely change in a managed fleet.",
		SQL:         "SELECT path, size, mtime, sha256 FROM file WHERE path = 'C:\\Windows\\System32\\drivers\\etc\\hosts'",
		Category:    CategoryFileIntegrity,
		Platforms:   []QuerySamplePlatform{PlatformWindows},
	},
	{
		Name:        "certificates_trusted",
		Description: "Trusted certificates in the system store — recent additions can indicate MITM CA installs.",
		SQL:         "SELECT common_name, subject, issuer, not_valid_after, sha1 FROM certificates",
		Category:    CategoryFileIntegrity,
		Platforms:   []QuerySamplePlatform{PlatformLinux, PlatformDarwin, PlatformWindows},
	},

	{
		Name:        "installed_packages_deb",
		Description: "Debian / Ubuntu installed packages with version.",
		SQL:         "SELECT name, version, arch FROM deb_packages",
		Category:    CategoryPackages,
		Platforms:   []QuerySamplePlatform{PlatformLinux},
	},
	{
		Name:        "installed_packages_rpm",
		Description: "RHEL / Fedora / CentOS installed RPM packages with version.",
		SQL:         "SELECT name, version, arch FROM rpm_packages",
		Category:    CategoryPackages,
		Platforms:   []QuerySamplePlatform{PlatformLinux},
	},
	{
		Name:        "installed_apps_macos",
		Description: "macOS .app bundles in /Applications — name, version, bundle id.",
		SQL:         "SELECT name, bundle_identifier, bundle_short_version FROM apps",
		Category:    CategoryPackages,
		Platforms:   []QuerySamplePlatform{PlatformDarwin},
	},
	{
		Name:        "installed_programs_windows",
		Description: "Windows installed programs — name, version, publisher, install_date.",
		SQL:         "SELECT name, version, publisher, install_date FROM programs",
		Category:    CategoryPackages,
		Platforms:   []QuerySamplePlatform{PlatformWindows},
	},
}

QuerySamples is the canonical starter library. ~20 entries spanning the categories above. Operators are expected to read, clone, and adapt these — they are intentionally simple and SELECT-only.

Ordering matters: this is the order the SPA template row renders, so the most-commonly-useful samples sit first.

View Source
var QuerySortableColumns = map[string]string{
	"name":       "name",
	"creator":    "creator",
	"created":    "created_at",
	"type":       "type",
	"expected":   "expected",
	"executions": "executions",
	"errors":     "errors",
}

QuerySortableColumns is the closed set of columns external callers may sort by. Enforced in GetByEnvTargetPaged. Mirrors the SortableColumns convention from pkg/nodes.

View Source
var SavedQuerySortableColumns = map[string]string{
	"name":    "name",
	"creator": "creator",
	"created": "created_at",
	"updated": "updated_at",
}

SavedQuerySortableColumns is the closed set of columns external callers may sort by. Enforced in GetSavedByEnvPaged. Mirrors QuerySortableColumns.

Functions

func GenQueryName

func GenQueryName() string

Helper to generate a random query name

func IsCarveQuery added in v0.5.2

func IsCarveQuery(query string) bool

Helper to check if query is carve

func QueryExpiration

func QueryExpiration(exp int) time.Time

Helper to generate the time.Time for the expiration of a query or carve based on hours

Types

type DistributedQuery

type DistributedQuery struct {
	ID            uint           `gorm:"primarykey" json:"id"`
	CreatedAt     time.Time      `json:"created_at"`
	UpdatedAt     time.Time      `json:"updated_at"`
	DeletedAt     gorm.DeletedAt `gorm:"index" json:"-"`
	Name          string         `gorm:"not null;unique;index" json:"name"`
	Creator       string         `json:"creator"`
	Query         string         `json:"query"`
	Expected      int            `json:"expected"`
	Executions    int            `json:"executions"`
	Errors        int            `json:"errors"`
	Active        bool           `json:"active"`
	Hidden        bool           `json:"hidden"`
	Protected     bool           `json:"protected"`
	Completed     bool           `json:"completed"`
	Deleted       bool           `json:"deleted"`
	Expired       bool           `json:"expired"`
	Type          string         `json:"type"`
	Path          string         `json:"path"`
	EnvironmentID uint           `json:"environment_id"`
	ExtraData     string         `json:"extra_data"`
	Expiration    time.Time      `json:"expiration"`
	Target        string         `json:"target"`
}

DistributedQuery as abstraction of a distributed query.

Explicit JSON tags (rather than relying on Go's default-PascalCase behavior or an external view projection) so /api/v1/queries and /api/v1/carves responses match the SPA's snake_case contract directly. Fields here are equivalent to embedding gorm.Model — same schema and soft-delete semantics — just with field-level json tags.

type DistributedQueryTarget

type DistributedQueryTarget struct {
	gorm.Model
	Name  string `gorm:"index"`
	Type  string
	Value string
}

DistributedQueryTarget to keep target logic for queries

type NodeQuery

type NodeQuery struct {
	gorm.Model
	NodeID  uint   `gorm:"not null;index"`
	QueryID uint   `gorm:"not null;index"`
	Status  string `gorm:"type:varchar(10);default:'pending'"`
}

NodeQuery links a node to a query

type Queries

type Queries struct {
	DB *gorm.DB
}

Queries to handle on-demand queries

func CreateQueries

func CreateQueries(backend *gorm.DB) *Queries

CreateQueries to initialize the queries struct

func (*Queries) Activate

func (q *Queries) Activate(name string, envid uint) error

Activate to mark query as active

func (*Queries) CleanupCompletedQueries

func (q *Queries) CleanupCompletedQueries(envid uint) error

CleanupCompletedQueries to set all completed queries as inactive by environment

func (*Queries) CleanupExpiredCarves

func (q *Queries) CleanupExpiredCarves(envid uint) error

CleanupExpiredCarves to set all expired carves as inactive by environment

func (*Queries) CleanupExpiredQueries

func (q *Queries) CleanupExpiredQueries(envid uint) error

CleanupExpiredQueries to set all expired queries as inactive by environment

func (*Queries) Complete

func (q *Queries) Complete(name string, envid uint) error

Complete to mark query as completed

func (*Queries) Create

func (q *Queries) Create(query *DistributedQuery) error

Create to create new query to be served to nodes

func (*Queries) CreateNodeQueries

func (q *Queries) CreateNodeQueries(nodeIDs []uint, queryID uint) error

CreateNodeQueries to link multiple nodes to a query

func (*Queries) CreateSaved

func (q *Queries) CreateSaved(name, query, creator string, envid uint) error

CreateSaved persists a new saved query. Returns ErrSavedQueryExists when a row with the same (name, env) already exists — the DB unique index `idx_saved_query_name_env` is the authoritative gate, so the handler does not need to win the SavedExists race anymore.

func (*Queries) CreateTarget

func (q *Queries) CreateTarget(name, targetType, targetValue string) error

CreateTarget to create target entry for a given query

func (*Queries) Delete

func (q *Queries) Delete(name string, envid uint) error

Delete to mark query as deleted

func (*Queries) DeleteSaved

func (q *Queries) DeleteSaved(name, creator string, envid uint) error

DeleteSaved removes a saved query owned by (creator, env, name). Retained for backward compatibility with non-API callers.

func (*Queries) DeleteSavedByEnv added in v0.5.2

func (q *Queries) DeleteSavedByEnv(name string, envid uint) error

DeleteSavedByEnv removes a saved query by name within an environment. Returns gorm.ErrRecordNotFound when nothing matched.

func (*Queries) Exists

func (q *Queries) Exists(name string, envid uint) bool

Checks if a query exists in an environment, regardless of the status

func (*Queries) Expire

func (q *Queries) Expire(name string, envid uint) error

Expire to mark query/carve as expired

func (*Queries) Get

func (q *Queries) Get(name string, envid uint) (DistributedQuery, error)

Get to get a query by name

func (*Queries) GetActive

func (q *Queries) GetActive(envid uint) ([]DistributedQuery, error)

GetActive all active queries and carves by target

func (*Queries) GetByEnvTargetPaged added in v0.5.2

func (q *Queries) GetByEnvTargetPaged(envID uint, target, qtype, search string, page, pageSize int, sortColumn string, desc bool) (QueryListPage, error)

GetByEnvTargetPaged returns a page of queries for an env + target, with optional free-text search on name/creator/query, optional sort, and canonical pagination. qtype: StandardQueryType or CarveQueryType.

page is 1-indexed. pageSize is clamped to [1, 500] with default 50.

func (*Queries) GetCarves

func (q *Queries) GetCarves(target string, envid uint) ([]DistributedQuery, error)

GetCarves all carve queries by target (active/completed/all/all-full/deleted/hidden)

func (*Queries) GetNodeQueryBucketed added in v0.5.2

func (q *Queries) GetNodeQueryBucketed(nodeID uint, since time.Time, bucketSeconds int) ([]dbutil.BucketedRow, error)

GetNodeQueryBucketed returns per-bucket row counts for node_queries targeting `nodeID`, since `since`. Same bucketing semantics as the logging-package variants — see pkg/dbutil.BucketExpr for the dialect branching.

func (*Queries) GetNodeQueryTimestamps added in v0.5.2

func (q *Queries) GetNodeQueryTimestamps(nodeID uint, since time.Time) ([]time.Time, error)

GetNodeQueryTimestamps returns just the CreatedAt of every node_query row where this node was the target, since the cutoff. Used by the per-node activity heatmap.

Pluck-style — drags only one column across the wire so the heatmap stays cheap when nodes have many tens of thousands of distributed queries.

func (*Queries) GetQueries

func (q *Queries) GetQueries(target string, envid uint) ([]DistributedQuery, error)

GetQueries all queries by target (active/completed/all/all-full/deleted/hidden)

func (*Queries) GetSaved

func (q *Queries) GetSaved(name, creator string, envid uint) (SavedQuery, error)

GetSaved to get a saved query by name + creator within an environment. Returns gorm.ErrRecordNotFound when no matching row exists — callers can use errors.Is(err, gorm.ErrRecordNotFound) to detect that case.

func (*Queries) GetSavedByCreator

func (q *Queries) GetSavedByCreator(creator string, envid uint) ([]SavedQuery, error)

GetSavedByCreator to get a saved query by creator

func (*Queries) GetSavedByEnv added in v0.5.2

func (q *Queries) GetSavedByEnv(name string, envid uint) (SavedQuery, error)

GetSavedByEnv returns a saved query by name within an environment without scoping by creator — used by env admins who can manage any saved query. Returns gorm.ErrRecordNotFound when no matching row exists.

func (*Queries) GetSavedByEnvPaged added in v0.5.2

func (q *Queries) GetSavedByEnvPaged(envid uint, search string, page, pageSize int, sortColumn string, desc bool) (SavedQueryListPage, error)

GetSavedByEnvPaged returns a page of saved queries for an env, with optional free-text search and an allowlisted sort column. pageSize is clamped to [1, 500]; pageSize <= 0 defaults to 50. page is 1-indexed.

func (*Queries) GetTargets

func (q *Queries) GetTargets(name string) ([]DistributedQueryTarget, error)

GetTargets to retrieve targets for a given query

func (*Queries) Gets

func (q *Queries) Gets(target, qtype string, envid uint) ([]DistributedQuery, error)

Gets all queries by target (active/completed/all/all-full/deleted/hidden/expired)

func (*Queries) IncError

func (q *Queries) IncError(name string, envid uint) error

IncError to increase the error count for this query

func (*Queries) IncExecution

func (q *Queries) IncExecution(name string, envid uint) error

IncExecution to increase the execution count for this query

func (*Queries) NodeQueries

func (q *Queries) NodeQueries(node nodes.OsqueryNode) (QueryReadQueries, bool, error)

func (*Queries) SavedExists added in v0.5.2

func (q *Queries) SavedExists(name string, envid uint) bool

SavedExists reports whether a saved query with the given name exists in the environment, irrespective of creator.

func (*Queries) SetExpected

func (q *Queries) SetExpected(name string, expected int, envid uint) error

SetExpected to set the number of expected executions for this query

func (*Queries) SetNodeQueriesAsExpired added in v0.4.4

func (q *Queries) SetNodeQueriesAsExpired(queryID uint) error

SetNodeQueriesAsExpired marks all pending node queries for a specific distributed query as expired

func (*Queries) UpdateQueryStatus

func (q *Queries) UpdateQueryStatus(queryName string, nodeID uint, statusCode int) error

UpdateQueryStatus to update the status of each query

func (*Queries) UpdateSaved

func (q *Queries) UpdateSaved(name, query string, envid uint) error

UpdateSaved updates the SQL body of an existing saved query identified by (name, env). The creator field is not modified — original ownership stays. Returns gorm.ErrRecordNotFound when the row does not exist.

type QueryListPage added in v0.5.2

type QueryListPage struct {
	Items      []DistributedQuery
	TotalItems int64
}

QueryListPage is the canonical paginated-list result for queries.

type QueryReadQueries

type QueryReadQueries map[string]string

QueryReadQueries to hold all the on-demand queries

type QuerySample added in v0.5.2

type QuerySample struct {
	Name        string                `json:"name"`
	Description string                `json:"description"`
	SQL         string                `json:"sql"`
	Category    QuerySampleCategory   `json:"category"`
	Platforms   []QuerySamplePlatform `json:"platforms"`
}

QuerySample is one starter sample row.

type QuerySampleCategory added in v0.5.2

type QuerySampleCategory string

QuerySampleCategory is the closed set of category tags. Surfaced in the SPA so templates can group; kept as a typed string so a typo at sample-add time becomes a compile error.

const (
	CategoryRecon         QuerySampleCategory = "recon"
	CategoryProcesses     QuerySampleCategory = "processes"
	CategoryUsers         QuerySampleCategory = "users"
	CategoryNetwork       QuerySampleCategory = "network"
	CategoryPersistence   QuerySampleCategory = "persistence"
	CategoryFileIntegrity QuerySampleCategory = "file_integrity"
	CategoryPackages      QuerySampleCategory = "packages"
)

type QuerySamplePlatform added in v0.5.2

type QuerySamplePlatform string

QuerySamplePlatform — a platform tag a sample claims to support. Aligns with pkg/nodes platform buckets (linux / darwin / windows). A sample applicable to every platform tagged with `linux, darwin, windows`.

const (
	PlatformLinux   QuerySamplePlatform = "linux"
	PlatformDarwin  QuerySamplePlatform = "darwin"
	PlatformWindows QuerySamplePlatform = "windows"
)

type SavedQuery

type SavedQuery struct {
	gorm.Model
	Name          string `gorm:"uniqueIndex:idx_saved_query_name_env"`
	Creator       string
	Query         string
	EnvironmentID uint `gorm:"uniqueIndex:idx_saved_query_name_env"`
	ExtraData     string
}

SavedQuery as abstraction of a saved query to be used in distributed, schedule or packs.

Composite unique index on (name, environment_id) — gorm AutoMigrate emits it as `idx_saved_query_name_env`. This is the structural fix for the TOCTOU race in SavedQueryCreateHandler: a concurrent pair of POSTs with the same name + env both pass the SavedExists precheck, both attempt CreateSaved; with the unique index, the second Create returns a duplicate-key error and the handler can map it to 409 cleanly.

type SavedQueryListPage added in v0.5.2

type SavedQueryListPage struct {
	Items      []SavedQuery
	TotalItems int64
}

SavedQueryListPage is the canonical paginated-list result for saved queries.

Jump to

Keyboard shortcuts

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