package httpapi import ( "time" "cloudipvalidator/internal/db" ) // DTOs for the admin queue-management and dynamic-config endpoints // (/api/v1/admin/ips, /api/v1/admin/config/*). Unlike the older read-only // admin endpoints (which marshal internal/db model structs directly, in // PascalCase), these use explicit snake_case JSON tags to match the // agent/prober DTO convention. type submitIPsRequest struct { Addresses []string `json:"addresses"` } type submitIPsResponse struct { Added []string `json:"added"` Requeued []string `json:"requeued"` Reordered []string `json:"reordered"` SkippedInProgress []string `json:"skipped_in_progress"` } type deleteIPsRequest struct { Addresses []string `json:"addresses"` } type deleteIPsResponse struct { Deleted []string `json:"deleted"` NotFound []string `json:"not_found"` } type clearQueueResponse struct { Deleted []string `json:"deleted"` Count int `json:"count"` } type scanIPsResponse struct { ScannedFree int `json:"scanned_free"` Added []string `json:"added"` Requeued []string `json:"requeued"` Reordered []string `json:"reordered"` SkippedInProgress []string `json:"skipped_in_progress"` } // scanStatusDTO is the progress/status object of the background floating-IP // scan job (POST/GET /api/v1/admin/ips/scan). state is one of // idle|clearing|listing|enqueuing|done|error|cancelled; "idle" means no scan // has run in this control-api process yet. type scanStatusDTO struct { State string `json:"state"` Running bool `json:"running"` DryRun bool `json:"dry_run"` Pages int `json:"pages"` Discovered int `json:"discovered"` Free int `json:"free"` Added int `json:"added"` Requeued int `json:"requeued"` Reordered int `json:"reordered"` SkippedInProgress int `json:"skipped_in_progress"` StartedAt *time.Time `json:"started_at"` FinishedAt *time.Time `json:"finished_at"` Error string `json:"error"` } // ipsPageResponse / registryPageResponse are the paginated envelopes returned // by GET /admin/ips and GET /admin/registry when `limit` is given; total is // the number of rows matching the filters (before limit/offset). type ipsPageResponse struct { Items []db.IPQueueItem `json:"items"` Total int `json:"total"` Limit int `json:"limit"` Offset int `json:"offset"` } type registryPageResponse struct { Items []registryDTO `json:"items"` Total int `json:"total"` Limit int `json:"limit"` Offset int `json:"offset"` } // registryDTO is one row of the durable per-address registry — see // db.RegistrySummary. type registryDTO struct { IPAddress string `json:"ip_address"` FirstSeenAt time.Time `json:"first_seen_at"` LastSeenAt time.Time `json:"last_seen_at"` TotalCycles int `json:"total_cycles"` LastResult string `json:"last_result"` LastCheckedAt *time.Time `json:"last_checked_at"` InQueue bool `json:"in_queue"` CurrentState string `json:"current_state"` // LastCycleID is the cycle counted by Egress and Ingress (0 = no checks). LastCycleID int `json:"last_cycle_id"` Egress levelResultDTO `json:"egress"` Ingress levelResultDTO `json:"ingress"` } // levelResultDTO is "ok of total" recorded checks of one level in the last // cycle, split by check family (tcp-22 and tcp-443 are both "tcp"). type levelResultDTO struct { Total int `json:"total"` OK int `json:"ok"` ByType []typeStatDTO `json:"by_type"` } type typeStatDTO struct { Type string `json:"type"` Total int `json:"total"` OK int `json:"ok"` } type validatorDTO struct { ValidatorID string `json:"validator_id"` Hostname string `json:"hostname"` OSPortID string `json:"os_port_id"` State string `json:"state"` LastHeartbeatAt *time.Time `json:"last_heartbeat_at"` } type createValidatorRequest struct { ValidatorID string `json:"validator_id"` OSPortID string `json:"os_port_id"` } type updateValidatorRequest struct { OSPortID string `json:"os_port_id"` } type siteDTO struct { Index int `json:"index"` SiteID string `json:"site_id"` Hostname string `json:"hostname"` State string `json:"state"` LastHeartbeatAt *time.Time `json:"last_heartbeat_at"` } type putSiteRequest struct { SiteID string `json:"site_id"` } type targetGroupDTO struct { Name string `json:"name"` Targets []string `json:"targets"` } type putTargetGroupRequest struct { Targets []string `json:"targets"` } type checkTypeDTO struct { Name string `json:"name"` Enabled bool `json:"enabled"` Targets []string `json:"targets"` } type putCheckTypeRequest struct { Enabled bool `json:"enabled"` Targets []string `json:"targets"` } // orchestratorSettingsDTO doubles as both the GET response and the PUT // request body for /api/v1/admin/config/orchestrator — a single-field DTO, // same shape both ways, like putSiteRequest/siteDTO. type orchestratorSettingsDTO struct { FIPSettleSeconds int `json:"fip_settle_seconds"` HistoryRetentionCycles int `json:"history_retention_cycles"` } // inboundChecksDTO doubles as both the GET response and the PUT request // body for /api/v1/admin/config/inbound-checks. Same field shape as // proberAssignment.Ports/ICMP (dto.go). type inboundChecksDTO struct { Ports []int `json:"ports"` ICMP bool `json:"icmp"` } // autoCycleDTO is the status+parameters object returned by every // /api/v1/admin/auto-cycle endpoint. Times are RFC3339 (null when unset). type autoCycleDTO struct { Enabled bool `json:"enabled"` IntervalSeconds int `json:"interval_seconds"` MaxRunSeconds int `json:"max_run_seconds"` Phase string `json:"phase"` RunStartedAt *time.Time `json:"run_started_at"` NextRunAt *time.Time `json:"next_run_at"` LastRunStartedAt *time.Time `json:"last_run_started_at"` LastRunFinishedAt *time.Time `json:"last_run_finished_at"` LastOutcome string `json:"last_outcome"` LastError string `json:"last_error"` LastScannedFree int `json:"last_scanned_free"` RunsTotal int `json:"runs_total"` } // putAutoCycleRequest is the PUT body. Pointers make the update partial: // an omitted field keeps its current value. type putAutoCycleRequest struct { IntervalSeconds *int `json:"interval_seconds"` MaxRunSeconds *int `json:"max_run_seconds"` }