Watch
1
0
Fork
You've already forked RedFlag
0
Commit graph RedFlag/server
Author SHA1 Message Date
Fimeg
7269d25823 fix: route audit misclassified inlined AuthMiddleware — server refused boot
The compiler inlines middleware.AuthMiddleware across packages, renaming
its closure to "<caller>.AuthMiddleware.func1" — the package-qualified
match ("middleware.AuthMiddleware") never hit, every agent-JWT route
was flagged as naked, and AuditAndExit refused boot (122 container
restarts overnight). Classify on bare names, web before agent since
WebAuthMiddleware contains AuthMiddleware. Regression test now uses the
real production middleware instead of a same-package fake.
2026-06-11 07:59:13 -04:00
Fimeg
6c3461cdf9 feat: rate limiter startup grace penalty (SEC-004)
The limiter is in-memory; a restart clears all counters, so an attacker
who can force one gets a fresh budget. For 60s after boot every limit
runs at half its configured budget (min 1), making a restart strictly
worse for the attacker while per-key limits keep reconnecting agents
comfortable. Restart semantics documented in OPERATIONS.md §6.
2026-06-11 04:29:50 -04:00
Fimeg
1c4b363375 fix: registration token moves from install URL to X-Registration-Token header (SEC-002)
A token in the query string leaks to shell history, process lists, and
server access logs. The install endpoint now reads X-Registration-Token;
a query-string token is refused with guidance and is never echoed back
or logged. Server-built and web-UI install commands updated (curl -H,
irm -Headers).
2026-06-11 04:25:32 -04:00
Fimeg
0abff08a9d fix: clear selected_version on transition to installed
A version pinned at approval (selected_version) survived the install,
so the next scan compared against the stale pin and plain Approve became
a no-op after the first install. Clear the pin and its metadata source
marker inside the transition tx once the package reaches installed;
subsequent scans track latest available again.
2026-06-11 04:20:20 -04:00
Fimeg
c33b62489e feat: boot-time route audit — ETHOS #2 enforced structurally
Walk every Gin radix tree at startup, classify each route's handler chain
(agent JWT / web JWT / metrics token), and refuse to boot if any route
lacks auth and is not on the explicit public allowlist. Adding a path to
PublicPathSet is a reviewable act.

Covers param routes, nested groups, and per-method trees (tested).
2026-06-11 04:20:08 -04:00
Fimeg
c71fc093db refactor: vulnerability → security advisory terminology
Rename CVE/vulnerability language to advisory/threat/fix across the stack:
- Dashboard: installed_cve_count→open_threat_count, security_update_count→available_fix_count
- Update detail: Known Vulnerabilities→Security Advisories
- AdvisoryType() helper for human-readable advisory ID prefixes
- clearVulnsOnInstall on installed transition with per-advisory security event logging
- StatsHandler takes checkInInterval for online/offline threshold
- AttentionPanel re-keyed on open-threats / available-fixes
2026-06-11 02:01:43 -04:00
Fimeg
5683bc15a4 feat: Wazuh queue-socket event emitter (INTEG-001)
Outbound-only: no listener, no control surface — RedFlag's journal is
authoritative, Wazuh is a best-effort mirror. DGRAM to the local agent's
queue socket, ECS-formatted, rule IDs mapped from security event types.
Opt-in via REDFLAG_WAZUH_ENABLED=true; disabled = socket never opened.

- Sink interface on SecurityLogger (mirror after journal write)
- Write deadline + one reconnect, then drop-count with rate-limited log
- 3 tests: frame/ECS shape, absent-socket non-blocking, unknown→generic
2026-06-11 02:01:43 -04:00
Fimeg
aff48376b9 v0.2.8.0 — changelog + version lockstep bump 2026-06-11 02:01:43 -04:00
Fimeg
8b1884eadc fix: nil logger on Windows scan path, rpmEVRAhead equal-version false positive, desktop-self replay token burned before install
- NewOrchestrator initialises a log-only TeeLogger (nil buffer) so the
  Windows service path never carries a nil logger into executeScan
- rpmEVRAhead returns false when all epoch/version/release components
  compare equal; adds test cases for "0:2.0-1" vs "2.0-1" normalisation
- processDesktopSelfToken splits replayCheckAndRecordAgent into
  replayCheckAgent (before install) + recordAgentTokenConsumed (after
  successful install) so a transient install failure does not permanently
  consume the token
- Comments on helperSelfStagingPath (Go) and DEFAULT_HELPER_SELF_SOURCE
  (Rust) name each other as the cross-language counterpart
2026-06-11 02:01:43 -04:00
Fimeg
2da1e92fe9 feat: setup accepts operator-supplied signing keypair + validation
Extract serverSetupRequest type and resolveSetupSigningKeys(): when no keys
are provided the server generates a fresh Ed25519 pair (existing behaviour);
when a private key is provided it is validated and the public key derived from
it (public key may be omitted or supplied for cross-check). Mismatched pairs
are rejected 400. Remove configure-secrets route from welcome-mode router
(was only usable with Docker socket mounted, unreachable in that mode).
Add inferPublicURL() helper to fill publicURL from X-Forwarded-* headers when
the operator omits it. pq.QuoteLiteral() used for password in ALTER USER.
Tests: generate-when-missing, use-provided-pair, reject-mismatched-pair.
2026-06-11 02:01:43 -04:00
Fimeg
244d9091ee feat: process explorer — on-demand /proc scanning with full osquery parity
Agent-side: reads /proc for all PIDs with 25+ fields (identity, resources,
state, disk I/O, elevation) plus related data on drill-down (open files,
sockets, pipes, env keys, memory map, namespaces, listening ports). Pure
/proc reads, no subprocess spawns.

Server-side: dedicated tables (agent_process_snapshots, agent_processes,
agent_process_related) with JSONB for related data. On-demand scan via
scan_processes command, last-10-snapshot retention. Four endpoints:
report, get latest, get detail, trigger scan.

UI: new Processes tab in agent detail with sortable/filterable table,
search by name/cmdline, state/user filters, and ProcessDetailModal with
tabs for Overview, Network, Files, Environment, Memory, Namespaces.
2026-06-11 02:01:43 -04:00
Fimeg
b9e083c4f7 test+fix: supply-chain consumer/OSV coverage; local-approve and update handler work
OSV fail-closed paths, safeTokenFilename traversal, bind check,
disallowed package types covered in agent/internal/supplychain.
Artifact hash resolution and dnf scanner test fixes. Server update
handlers extended for the local-approve flow with OSV version test
coverage.
2026-06-11 02:01:42 -04:00
Fimeg
4896fb6856 ci: Gitea Actions pipeline — release gate, embedded UI build, guided release script
ci.yml: vet, race tests, clippy, full web build, AI-attribution and
action-pin enforcement. release.yml: gate job verifies tag against
versions.go/docker-compose/Cargo/CHANGELOG, forward-only and on public,
before anything builds; web UI staged into the embed path (gitignored
dist made a bare go build ship an empty dashboard); binaries and docker
image must self-report the tag; release created via Gitea's own API.
scripts/release.sh is the operator path: checks runner, secret, branch,
versions, changelog — asks before every mutation, watches the run after.
bump-version.sh gains current-version display, dirty-tree warning,
duplicate check, changelog check, confirmation. build-secure-agent.sh
retired (bare go build, no version injection, single Makefile caller).
2026-06-11 02:01:42 -04:00
Fimeg
2f3363cbce feat: post-upgrade attestation — new binary proves the swap took
Old binary drops a marker (command_id, from/to) once the swap is
committed, on both the helper path and the legacy path. New binary
checks it at startup: running >= target just clears the marker
(check-in confirm still owns success); short of target means the swap
failed or rolled back, so it files a failed update_agent report under
the original command_id and the server clears is_updating right away
instead of sitting out the stuck-update timeout. Marker survives
failed reports for retry, drops on 409 or after 24h.
2026-06-11 02:01:42 -04:00
Fimeg
2084019be7 fix: grant CAP_SYS_PTRACE on agent binary for display/process discovery
The agent runs as redflag-agent user and cannot read /proc/[pid]/environ
from the logged-in user's session processes (owner-only permissions).
Without this, discoverSessionDisplay() finds nothing — screenshot fails
on Wayland because XDG_RUNTIME_DIR/WAYLAND_DISPLAY are never discovered.

- Installer: setcap cap_sys_ptrace=eip after placing the binary
- Helper (agent self-update): restore setcap after atomic replace,
  since rename() creates a new inode and strips file capabilities

Non-fatal if setcap is unavailable — agent degrades gracefully,
just loses screenshot and per-process telemetry.
2026-06-11 02:01:42 -04:00
Fimeg
411f25b1b7 v0.2.7.0 2026-06-11 02:01:42 -04:00
Fimeg
aeff8a67a8 fix: desktop build uses Node 20 stage; tray installs + autostarts by default 2026-06-10 09:45:24 -04:00
Fimeg
1241c1ef01 feat: embed web UI in server binary + local trigger-scan write endpoint
Server becomes self-contained: web/dist embedded via go:embed
(server/internal/webui), SPA served from the binary with JSON-404 guard on
/api paths, nginx web container removed from compose (31336 now maps to the
server). Clean checkouts without the UI copy build API-only.

Agent local API gains its first write endpoint, POST /v1/actions/trigger-scan
(FEAT-002 write path): group-ACL authorized, single-flight, 202/409/503
semantics. Registered agents run the same HandleScanUpdates path as a signed
scan command (empty command_id, no ack tracking); standalone agents scan
through the orchestrator into the local read model only. Also repairs
localapi tests left uncompilable by the desktop-provider parameter.
2026-06-10 08:38:18 -04:00
Fimeg
c3d84ec7f9 feat: UI primitives + agent version bump
- PageState, Modal, Pagination, StatCard primitives
- Migrated Dashboard, Updates, LiveOperations, Agents, Docker, TokenManagement
- AgentUpdate, AgentUpdatesModal now use Modal primitive
- Version bump to 0.2.6.9
2026-06-08 19:40:06 -04:00
Fimeg
7cbf174652 feat: unified event timeline, desktop bundling, UI primitives
Unified timeline:
- client_errors bridge to system_events (component='client')
- Admin action audit middleware on /admin/* routes
- History page filters: type, severity dropdowns
- ChatTimeline accepts externalType/externalSeverity props

Desktop app bundling:
- Docker: Tauri builder stage (Rust + Node + webkit2gtk)
- Server signs desktop binary at startup, serves via /api/v1/desktop/:arch
- Install script downloads + verifies desktop binary (Step 7c)
- Agent spawns desktop as child process, monitors + restarts on crash
- Desktop config: enabled, max_restarts, restart_delay_sec
- Session detection: /proc environ scan (Linux), query session (Windows)
- Desktop health: POST /v1/desktop every 30s from tray app
- /v1/status includes desktop running/pid/enabled state

UI primitives:
- Modal, PageState, Pagination, StatCard components
- Dashboard, Updates, Agents pages refactored to use primitives
- Novell aesthetic preserved throughout
2026-06-08 19:09:58 -04:00
Fimeg
c0a717ab26 fix: README, .env.example, ErrorBoundary, client-logger, HEALTHCHECK, Docker hygiene
- README: version v0.2.6.8, corrected stale gate claim, updated changelog
- .env.example: merged two competing files into one, deleted bootstrap duplicate
- ErrorBoundary: new component wrapping app, prevents white-screen crashes
- Layout sidebar: version display from /api/health, Docs link to GitHub
- client-logger: debug/trace logger gated behind localStorage.redflag_debug=1,
  routes through existing /logs/client-error server endpoint (ETHOS #1)
- All web console.log calls rerouted through client-logger instead of deleted
- Server health endpoint returns version field
- Server accepts client_debug/client_trace in error_type validation
- Dockerfiles: pinned alpine:latest->3.21, nginx:alpine->1.27-alpine,
  added HEALTHCHECK directives
- docker-compose: healthcheck blocks for server and web services
- .dockerignore: created to slim Docker build context
2026-06-08 18:23:39 -04:00
Fimeg
ab6fc48925 feat: v0.2.6.8 — dark/light tray app theme, version bump
LocalAgentApp: dark default with ☀/☾ toggle; palette-driven inline
styles (DARK/LIGHT objects) so both modes work without Tailwind dark
mode configuration. Dense Novell-style layout: status strip, section
headers with red accent bar, monospace identifiers, dot indicators per
scanner status. No Tailwind class changes — web/package-lock.json
untouched.

Version bump 0.2.6.7 → 0.2.6.8.
2026-06-08 17:22:01 -04:00
Fimeg
ffffe9b956 feat: FEAT-002 local agent API, desktop tray spine, screenshot handler
Slices 1-3 of the local agent IPC surface:
- Read model (local_status.go, loop wired): update counts, scanner status,
  check-in state, token receipt counts — no token material exposed
- Local IPC (localapi/): Unix socket (group=redflag-local, 0660) + Windows
  named pipe (SDDL: LocalSystem/Admins/RedFlagLocal); five read-only endpoints
- `redflag-agent -local-status` CLI probe of the local API surface
- Screenshot capture handler (screenshot.go, dispatch wired)
- Tauri desktop spine (desktop/): tray icon, left-click window, local IPC reader
- Desktop React entry (web/src/desktop/LocalAgentApp.tsx, index.desktop.html,
  vite.desktop.config.ts)
- Installer group provisioning: linux.sh creates redflag-local, sets
  SupplementaryGroups; windows.ps1 creates RedFlagLocal security group
- Server-side: screenshot receipt handler on agents, updates handler additions
- web/package.json: @tauri-apps/api + tauri CLI dev dep added
2026-06-08 17:08:58 -04:00
Fimeg
b0e2a77528 fix: pin installed version instead of clearing on install
After successful install (confirm_dependencies or capability receipt),
pin the installed version as selected_version instead of clearing it.
This prevents subsequent scans from silently advancing to a newer
unapproved version. The pin is the enforcement mechanism.
2026-06-08 16:07:33 -04:00
Fimeg
7d089ab5d2 v0.2.6.7 — GATE-006 D, version row OSV check
- evaluateSupplyChainHold checks version row osv_status for target
  version, closing hole where we OSV-check one version but install
  another.
- confirm_dependencies uses TransitionByPackageFrom with source-state
  guard (StatusInstalling → Installed/Failed).
- Clears pinned version on successful install.
- Version bump to v0.2.6.7.
2026-06-08 16:01:05 -04:00
Fimeg
14cd0884b4 fix: consolidate heartbeat, lower dashboard polling
- useHeartbeatStatus reads from agent metadata (single source of
  truth) instead of separate endpoint (eliminated split-brain).
- Online/offline threshold fixed to 10min to match server (was 15min).
- Dashboard polling lowered from 30s to 15s.
- Toggle feedback: invalidate agent queries immediately, clear
  loading state after 2s.
- Removed command-table fallback from GetHeartbeatStatus endpoint,
  dead helper functions, and unused GetRecentHeartbeatCommands.
2026-06-08 16:01:01 -04:00
Fimeg
f83f5a0960 fix: Windows install path — ACL repair, host/port, CRLF
- Install script repairs config ACL before detection (unreadable
  config.json caused false 'not installed' and 409 re-registration).
- Config permissions use stable SIDs (SYSTEM, LOCAL SERVICE,
  Administrators) instead of localized account names.
- Install URL preserves port for non-localhost hosts.
- Server bind address vs reachable host distinction fixed.
- Windows install script served as CRLF.
- Installer tolerates missing Ed25519 verifier.
2026-06-08 16:00:01 -04:00
Fimeg
8ced1d5a47 fix: make Windows installer tolerate missing Ed25519 verifier 2026-06-08 10:47:07 -04:00
Fimeg
7ae7429878 fix: bake reachable host into install script, not server bind addr
getServerURL returned localhost:31337 (the server's own bind address), so
a remote agent's binary/manifest/config fetches pointed at itself and
failed with "Unable to connect". Prefer the host the client actually
reached us on (Host + X-Forwarded-Proto, which nginx forwards), falling
back to PublicURL then the configured bind addr. Also set charset=utf-8 so
irm stops mangling the ✓/⚠ glyphs.
2026-06-08 09:15:26 -04:00
Fimeg
495d5fb3a7 fix: serve Windows install script as CRLF
Windows PowerShell 5.1's parser chokes on here-strings in LF-only .ps1
files — the embedded config template blew up with a cascade of
"Unexpected token ':'". Convert the windows script to CRLF at serve time
(parses clean in 5.1 and 7; .ps1 should be CRLF anyway). Linux stays LF.
2026-06-08 09:07:43 -04:00
Fimeg
f811b47e0b fix: Windows one-liner self-authenticates again (irm | iex)
The Windows installer relied on a Mandatory=$true -Token param, but the
one-liner ran the script with no -Token -> PowerShell dropped to an
interactive prompt and the install looked hung.

Bake the token/server into the rendered script like the Linux template
already does, drop param() and #Requires (both no-op under iex; runtime
admin check still enforces elevation), and switch the command to
'irm ... | iex' so the body actually pipes. -Token/-Server/-Skip become
RF_TOKEN/RF_SERVER/RF_SKIP_SERVICE_INSTALL env overrides.
2026-06-08 08:44:27 -04:00
Fimeg
40f57edefc v0.2.6.4 2026-06-08 08:14:24 -04:00
Fimeg
b09453e849 install the version that cleared the soak window, not the bleeding edge
the supply-chain check was judging available_version while the gate could
install a different one. re-run OSV against the version we actually install
(operator-pinned, else gated), and auto-pin the newest soak-aged clean
version when the gate's enforced — forward-only, operator force-pin wins.
2026-06-08 08:14:20 -04:00
Fimeg
f136c12902 shed agent writes when the db pool runs dry
last half of S8. the pool bump and bounded background took most of the pressure
off, but a full fleet can still pin every connection. now there's a valve:

- middleware reads db.DB.Stats(); at the saturation threshold it answers 503 +
  retry-after instead of letting writes queue into a deadlock
- fails open — unlimited pool never sheds, default only trips at 100% in-use.
  tunable via REDFLAG_DB_SHED_UTILIZATION and _RETRY_AFTER_SECONDS
- wired to the agent write group only. health, metrics, auth, register/renew
  and the dashboard stay reachable so you can still watch it and log in while
  it's hot

table-driven test across the branches, race clean.
2026-06-07 21:16:53 -04:00
Fimeg
cf061a13a1 seal the settings path so secrets land encrypted
the encrypt/decrypt hooks existed but the write path wrote values straight to
the column, so a sensitive setting would have gone in as plaintext. closed it:

- sensitive values serialize + encrypt before they persist (base64 aes-gcm over
  the json), and updates now carry the is_encrypted flag through
- non-sensitive settings are untouched — still plain json, same as before
- audit log redacts sensitive old/new values instead of recording them raw

round-trip test proves sensitive values never hit the column in plaintext and
still decrypt back; non-sensitive stay readable. no backfill needed — nothing
writes secrets through this path yet, the defaults are empty.

builds clean, vet quiet, tests pass.
2026-06-07 21:16:39 -04:00
Fimeg
f7882241c7 give the system a window you can scrape, and patch a migration that couldn't run twice
OBS-001A: an authenticated /metrics so something other than a human reading
logs can watch the box. no new dep — emits prometheus text straight from the
counters we already keep:

- /metrics behind a dedicated bearer token (sha-256 hash stored, plaintext only
  from REDFLAG_METRICS_TOKEN for bootstrap). constant-time compare, rotates
  without a restart, disabled by default, never an open route
- exports db pool, taskrunner snapshot, scheduler + queue, breaker state, and
  the deferred-advisory count — read live on each scrape, bounded labels only
- settings + migration 054 for observability.metrics_enabled / _token_hash

also fixed migration 046 — it added a column and an index without IF NOT EXISTS
and backfilled off a column it then drops, so it couldn't survive a second run.
guarded every step; the idempotency lint is green again. only the migrations
the runner hasn't recorded see the change, so live dbs don't care.

builds clean, vet quiet, new tests pass.
2026-06-07 20:59:29 -04:00
Fimeg
ae411cf5d4 say it out loud when the advisory feed goes dark
the breaker fails open so a down osv never blocks a patch — good — but the
auto-confirm gate is fail-closed, so a dark feed quietly stops auto-approval
and parks packages unvetted. that truth was sitting in the logs where nobody
looks. now it's a banner.

- /api/v1/health/advisory: breaker state + count of deferred packages
  (self-healing — a successful recheck clears the flag) + a degraded flag
- amber bar in the layout, only when degraded: "feed offline, auto-approval
  suspended, manual still works." says feed-down isn't patching-down
- narrow slice of the gate-visibility work; the full posture panel stays in
  its own session

builds clean, tsc's happy.
2026-06-07 20:17:18 -04:00
Fimeg
e99ad6e8c7 gave the server a breaker so a sulking upstream can't drag it down
osv.dev or repology going dark used to mean every check sat there burning its
30s timeout, one after another. now there's a breaker (ported the agent's, it's
already proven) wrapping both:

- osv: one breaker over the batch + single-query paths. trips after 5 fails in
  a minute, fails open while tripped — an unreachable advisory feed never blocks
  a patch. that's the whole sovereignty bet
- repology: same deal, best-effort, 404 doesn't count against it
- both visible at /health/tasks so you can see them trip and heal

db-pool shedding (503 + retry-after) is the other half — left it for later, the
pool bump + bounded background already took most of that pressure off.

race detector's clean.
2026-06-07 19:45:36 -04:00
Fimeg
d25f6ea030 swept the cobwebs, stopped re-dialing the same three hosts
three more off the scale list:

- rate-limit map now gets swept on a cadence (taskrunner.Every) instead of
  growing forever — nobody was calling the cleanup. first old ticker moved
  onto the runner
- subsystem load was one db query per agent at startup; now it's a single
  ANY($1) for all the online ones. 100 agents, 1 query
- outbound http clients (osv, registries, upstream, agent) were inheriting
  the stock transport that keeps 2 idle conns per host — so every scan burst
  re-dialed. shared tuned transport now, 10 per host, 90s idle

builds clean both modules.
2026-06-07 19:35:32 -04:00
Fimeg
82018bfb80 taught the rocks to stop tripping over each other under load
server was sized for a campfire, not a fleet. 25 db connections, every agent
report flinging goroutines into the void, the syncer plodding one repo at a
time while clutching a lock nobody needed. loosened the choke points:

- db pool 25 -> 100 + connection lifetime, all env-tunable
- bounded pool for the report-path fire-and-forget work; /health/tasks to
  watch it breathe. no more unbounded goroutine spray per report
- upstream syncer runs concurrent now, dropped the dead mutex around repology
  fetches, reconciler single-flights instead of locking through the whole crawl
- scheduler caps jobs per tick so an aligned fleet can't stampede the db
- swatted a context-cancel bug that was quietly killing immediate syncs

builds clean, race detector's calm.
2026-06-07 19:17:08 -04:00
Fimeg
5b1a16ca3e v0.2.6.2 — osv scans moved to detection, soak gate grew up
approval stopped re-scanning osv; it just reads what detection already
found. soak gate + age gate are real settings now (env→db→default), and
the dead soak-override column + table got composted.
2026-06-07 14:44:41 -04:00
Fimeg
b82649967e RECONCILE-001: scan-set closure (close-by-absence) + v0.2.6.1
Treats each ecosystem scan as the authoritative full set for that
(agent, ecosystem) pair. Packages absent from a successful scan that
are still in a waiting state (pending/approved) are closed to installed
with out-of-band provenance — no operator action required.

State machine:
- Added pending/approved → installed edges (out-of-band resolution path)
- Added installed → pending edge (reactivation when a new version reappears)
- ReconcileFromScan updated to match: installed now reopens, ignored/failed preserved

Server (ReportUpdates):
- closeScanAbsentRows goroutine: diff waiting rows against reported set,
  transition absent rows via transitionStatus (guarded UPDATE, idempotent)
- Provenance stamping: redflag_receipt if a consumed capability token exists,
  out_of_band otherwise
- System event emitted per closure for audit trail
- scanEcosystemSupported gate: dnf/apt only; failed/partial scans never close rows

Agent:
- UpdateReport extended with Ecosystem + ScanSucceeded fields
- APT/DNF scan handlers now always report on successful scan (even 0 updates)
- HandleScanAPT/DNF/Updates: report failure is non-fatal (transport problem,
  scan succeeded locally)

Queries:
- GetTrackedNonResting: scoped to pending/approved only — in-flight states
  (checking_dependencies, pending_dependencies, installing) are orchestrator-owned
- TransitionByID: routes closure through the state machine
- HasConsumedTokenForUpdate: provenance check for the reconciler
- UpdateCurrentStateInTx SQL CASE: installed now reopens to pending on re-scan

Tests: reconcile_test.go (5 unit tests including load-bearing
TestWaitingStatesResolveOutOfBand), reconcile_test.go handler tests (7 sub-tests).

Bump: v0.2.6.1
2026-06-06 20:46:29 -04:00
Fimeg
b346c1386e v0.2.6.0 2026-06-05 21:34:12 -04:00
Fimeg
1ec7999d8f fix: code review batch 1 + dead store setting
- #1: ReconcileAll goroutine uses context.Background, not request ctx
- #4: InstallVersion now checks maintenance window before dry-run
- #5+#23: tickAliases fetches stale slugs once before loop; rename shadowing var
- #6: UpsertReconciled sql.ErrNoRows on manual conflict is a no-op, not a warn
- #7: normalizeRepoToEcosystem uses ordered slice, not non-deterministic map
- #8: MatchByContainer ILIKE escapes % and _ metacharacters via REPLACE
- #9: EnqueueDryRun uses target_version key for selected_version, keeps available_version for freshness
- #13: InstallVersion drops second GetUpdateByID, mutates struct locally
- #14: EnrichFromMetadata reserved map is package-level var, not per-call alloc
- #21: recordGateOverride shared helper; recordSupplyChain/SoakOverride delegate to it
- store.ts: remove dead notificationsEnabled setting (no callers outside store)
2026-06-05 21:26:44 -04:00
Fimeg
f005255e68 feat: docker enrichment pipeline, package detail, update history pagination 2026-06-05 21:18:06 -04:00
Fimeg
d1424e8377 feat: FEAT-002 metadata pipeline, GATE-005 soak gate, BRIDGE-001 auto-discovery
FEAT-002: Server-side metadata pipeline
- ReportUpdates merges PackageDescription/CVEList/KBID/SizeBytes into metadata JSONB
- UpdateCurrentStateInTx uses JSONB merge (||) instead of replace
- Fixes current_version bug (missing EXCLUDED.current_version)
- EnrichFromMetadata() on UpdateState populates display fields from metadata
- mergedVulnerabilities() deduplicates agent CVEs with OSV.dev results
- VulnerabilityEntry struct for unified vulnerability representation

GATE-005: Version soak-gate
- Migration 050: selected_version column, version_soak_overrides table
- soak_gate.go: SoakGateConfig/EvaluateSoakGate (14-day default, block enforcement)
- POST /updates/:id/install-version endpoint with soak evaluation
- EnqueueDryRun reads COALESCE(selected_version, available_version)
- Override journals to system_events (recordSoakOverride)

BRIDGE-001: Tracked software auto-discovery
- Migration 051: repology_slug/container_image_pattern/binary_probe on tracked_software,
  repology_aliases table, match_method/package_name on agent_tracked_software
- RepologyCache: fetches /api/v1/project/{slug}/packages, normalizes repos to ecosystems
- ReconciliationQueries: MatchByRepology/MatchByContainer/MatchByExactName
- Reconciler: cascade matching service with hourly loop, hooks into ReportUpdates
- UpsertReconciled: preserves manual operator bindings
- COMMON_SEEDS updated with repology_slug values
- Syncer updated with 24h alias refresh ticker
2026-06-05 17:43:11 -04:00
Fimeg
938d0bee35 v0.2.5.2 2026-06-05 16:37:56 -04:00
Fimeg
cad1554d94 feat: SETTINGS-001 reversible token encryption + one-liner restore
Reversible AES-256-GCM encryption for registration tokens so the
install one-liner can auto-fill the token value again. Migration 049
adds token_encrypted column; token_hash kept for lookup.

AgentManagement.tsx gets platform cards (Linux, Windows; macOS = soon)
with generateInstallCommand for all platforms. Inert until backend lands.

system_event_logger.go extracted from deleted event_stream.go —
SystemEventLogger survives, unified substrate does not.

security_settings_service.go and secrets_manager.go simplified.
2026-06-05 16:17:47 -04:00
Fimeg
4ccbf8c5fd fix: heartbeat auto-queue treats duplicate-pending as benign (ETHOS #4)
queueSystemHeartbeat now checks for the unique violation on
idx_agent_pending_subsystem and logs at INFO instead of WARN.
A duplicate means the desired heartbeat is already in flight —
not a failure. Suppresses the scary WARN on every rapid-polling
enable where a heartbeat was already pending.
2026-06-05 16:17:36 -04:00
Fimeg
5d7babff22 fix: History 500, rename to GetFleetActivity, remove dead unified substrate
GetFleetActivity replaces GetAllUnifiedHistory — filters now apply once on
the outer aliased result instead of per-arm, fixing the agent_id ambiguity
when the logs arm joins update_packages (the 500).

Three new UNION arms: update_events, update_version_history, system_events.
Package name joined to update_logs via update_package_id.

Dead code removed: event_stream.go (handler + service), UnifiedEventTimeline.tsx,
useEvents.ts — orphaned from the abandoned unified path (HANDOFF-2026-06-05).
SystemEventLogger extracted to system_event_logger.go (unstaged, next commit).
2026-06-05 16:17:27 -04:00