Watch
1
0
Fork
You've already forked RedFlag
0
Commit graph

457 commits

Author SHA1 Message Date
Fimeg
bf7930f1fe v0.2.9.1: wire pacman scanner, GATE-006 TODO 2026-06-29 15:11:12 -04:00
Fimeg
35732a63fd fix(GATE-005): harden helper trusted-input — argv separator + UUID v4 request_id
- apt build_plan: add POSIX '--' before user-derived name=version tokens
- dnf build_plan: add POSIX '--' before user-derived name-version token
- validate_mint_request: enforce canonical UUID v4 on request_id at intake
- RAF components/04: document '--' separator in pipeline step 7
- RAF security/05: document hardened argv contract + UUID v4 validation
- RAF flows/03: add stale banner (5 deviations from current code)

14 tests pass. Deferred: artifact_path staging root, name/version charset
regex (both need design decisions — see task file).
2026-06-17 22:07:36 -04:00
Fimeg
4e08deef8c fix: un-gitignore helpers.go, fix event buffer race
helpers.go was gitignored as "stale WIP" but defines BufferSystemEvent
called by committed code in install.go and loop.go — CI broke because
the file never shipped.

buffer.go GetBufferedEvents: re-atomic the read+clear under one lock
hold; the refactor split into ReadBufferedEvents+Clear introduced a
window where BufferEvent could write events that Clear then deletes.
2026-06-15 22:13:34 -04:00
Fimeg
7035da041d build: fetch the Windows tray from release, don't cross-compile it
from-source builds have no business pulling a 9GB MSVC sysroot for one Tauri
exe. CI builds it once; the server image downloads the signed artifact and
hash-checks it against the manifest. no release / offline -> no tray, server
404-skips. also: make rebuild/up/down/logs so `up -d build` stops biting.
2026-06-15 21:46:36 -04:00
Fimeg
865d82ded0 web: wire Agents <-> Enrollment, back on the steel-blue theme
deep-link a chosen key into the install panel, drop the emoji.
2026-06-15 21:12:33 -04:00
Fimeg
99d97a07ee v0.2.9.0 — Windows desktop tray ships; unified Agents & Enrollment page
Desktop:
- Windows tray cross-compiled (cargo-xwin), installed with per-user
  autostart Run key; tray actions trigger_scan/approve_update wired to
  the local API
- Linux tray off the service child-spawn path — XDG autostart only, kills
  the double-launch
- signalDesktopRestart no longer no-ops on Windows (taskkill /F /IM)
- server serves /desktop/:platform/:arch

Web:
- TokenManagement + AgentManagement folded into one Agents & Enrollment
  settings page (useRegistrationTokens hook)

Agent/server:
- platform-aware self-update staging (constants/paths.go), no more
  hardcoded /var/lib/redflag
- consumer helper gated: sudo systemd-run on Linux, child proc elsewhere
- migration 060 drops the never-used token_seats table
- droppage of dead constructors and orphaned windows.go service methods
2026-06-15 20:51:44 -04:00
Fimeg
e8cd4de44f upstream: keep drift detection-only 2026-06-15 12:24:44 -04:00
Fimeg
9e4d59695f upstream: track prereleases per row; rename gitea adapter to forgejo
Most forges hand back a "latest stable" that ignores prereleases. Fine
until something ships only prereleases for a stretch — us, through
alpha, where every tag under v0.3.0 goes out as a prerelease. Against
that, /releases/latest either freezes or returns nothing, and the
dashboard reads like nothing's moving.

Add a per-row track_prereleases flag. When it's on, the forgejo adapter
walks the full release list and considers prereleases when picking the
highest version; off (the default) keeps stable-only behavior, so the
other adapters don't change. Seed our own self-row on so we stop
looking frozen.

Renamed gitea_releases to forgejo_releases while in there — the wire
format is Forgejo's, Codeberg runs it, and the old name was a misnomer.
Legacy source="gitea" rows still resolve through an alias.
2026-06-15 12:10:12 -04:00
Fimeg
a859fabedf nightly: drop the server binary — agent+helper only, server installs via verified channel 2026-06-15 10:26:43 -04:00
Fimeg
eb79af448e v0.2.8.4 — releases publish as prerelease until v0.3.0 (alpha) 2026-06-15 09:58:24 -04:00
Fimeg
d9ba008f67 raf: sync docs to code + relative cross-reference links
Handler/migration counts, calculateBackoff -> calculateDelay, machine-id
binding (cross-platform machineid + fallbacks, not hostname), last-reviewed
dates, and made [[cross-references]] relative so they resolve.
2026-06-15 09:39:34 -04:00
Fimeg
1d84fd46a7 web: primary -> steel blue, split from danger (C5)
primary was byte-identical to danger (both red), so every focus ring, toggle,
tab and link read as an error. primary is now steel #336699 (red lives on as
danger). Walked the stray hard-coded interactives onto the token — StackDriftPanel,
software-binding buttons/links, retry CTA — and left the destructive reds alone.
2026-06-15 09:37:48 -04:00
Fimeg
f340c0d084 web: log errors at the boundary, ditch the toast-logging wrapper (C6)
API errors already log via the axios interceptor — wrapping 78 toast calls
would just double-log and turn validation prompts into noise. Wrapper gone;
ErrorBoundary + window error/rejection handlers log to clientErrorLogger,
skipping axios errors so the log POST can't loop. setupApiInstance logs now too.
2026-06-15 09:28:31 -04:00
Fimeg
f04fbe8b1f web: fix 13 dashboard criticals from the UI/UX audit
- confirm-deps used a raw fetch with no auth headers -> API layer
- retry/cancel had two copies with divergent invalidation (one hit a dead
  ['active'] key); unified in useCommands, bulk-approve now refreshes counts
- Docker stat-card filter was sent server-side where it mapped to the severity
  column and matched nothing; moved client-side with two distinct values
- wired dead Quick Actions buttons, notification deep-links, ws reconnect+backoff
- useMemo side-effect -> useEffect, agent-events dedup, stale-closure toast
- dropped dead agent memory block, labeled security health as fleet-wide
- maintenance banner claimed installs are "blocked"; they wait for the window
2026-06-15 09:07:19 -04:00
Fimeg
cc19854941 security: latch /admin group behind RequireAdmin (SEC-026)
The /admin group rode on webAuthMW + audit only; just the securitySettings
sibling checked the role. Inert today (login mints role=admin), live the day
RBAC lands — one group-level gate beats per-route annotations to forget.
2026-06-15 09:07:19 -04:00
Fimeg
7d47b0769d gate: route desktop updates through the helper
Desktop self-updates ran in the agent process with their own replay
file. They now go through the privileged helper like agent and helper
self-updates, so the agent performs no binary mutation and keeps no
replay state of its own. The desktop app is a status surface only.
2026-06-14 14:24:29 -04:00
Fimeg
c35ad89b92 gate(executor): constant-time hash compare in the privileged helper
Compare artifact and closure hashes in constant time via subtle::ConstantTimeEq at the three verify sites, closing a timing oracle on the privileged executor. subtle is added as an explicit dep (was only transitive).
2026-06-14 12:57:04 -04:00
Fimeg
0b1b8124b0 crypto: forward-only key-path ceiling + OSV resilience + token serialization
SEC-028 -- a rotated-out server signing key must stop being trusted even when the agent cannot phone home. pubkey.go: bounded stale-cache window on public-key fetch failure; past the window (or when cache age is unknown) it fails closed instead of trusting the cached key indefinitely. Window length is operator policy (command_signing.stale_key_max_age_hours, default 168h/7d) delivered fleet-wide via GET /agents/:id/config; the [1h, 30d] clamp and the existence of the ceiling are doctrine, not knobs. verification.go: CheckKeyRotation refuses when the named key_id is not in the server active set (no primary fallback), and applies the same bounded-stale ceiling to the active-set fetch-failure path so key_id'd commands are no weaker than keyless ones. Server carries the default + 1-720h validation; web surfaces it in Security Settings.

SEC-029 -- the standalone OSV.dev client retries transient transport/5xx/429 with exponential backoff and trips a process-wide circuit breaker after a run of failures, fast-failing to 'unreachable'. Verdict semantics unchanged and still fail-closed; the resilience only stops a transient scanner blip from forcing an operator override.

GATE-004 #4 -- Consumer.ProcessToken holds a mutex so the replay-state guards are never raced by a concurrent caller. Today's single caller (the poll loop) never overlaps; this enforces the one-token-at-a-time invariant for future callers (local-API trigger, retry worker).

RAF/verification/03 and RAF/security/05 document the key-path and OSV changes. ETHOS #3, #4; forward-only doctrine.
2026-06-14 12:57:04 -04:00
Fimeg
e0765c29f4 supply-chain: honest self-attestation posture (dep-scan, build provenance, install guard)
dep-scan.sh: capture govulncheck's real exit code and feed the reachability gate only on exit 0 (clean) or 3 (vulns found). Any other exit (crash, timeout, 137) is now INFRA, so a truncated-but-parseable JSON stream can no longer parse clean and yield a falsely attested posture. npm ci / npm audit / cargo audit stderr is captured and surfaced on failure (no more 2>/dev/null).

Dockerfile: the posture-builder stage no longer curl|sh's rustup.rs. The Rust toolchain is COPY --from=rust:1-bookworm (canonical official image, same base as desktop-builder) with RUSTUP_HOME/CARGO_HOME set -- stronger provenance than TLS-TOFU rustup, no pipe-to-shell inside the stage that produces the attestation. docker compose build will validate the new layer.

linux.sh.tmpl: guard the posture check under set -e so an un-attested (exit 3) or blocked (exit 4) verdict degrades honestly instead of aborting the install before POSTURE_RC is captured.

ETHOS #1 (errors are history), #3 (assume failure). CI-002 + CI-003.
2026-06-14 12:56:42 -04:00
Fimeg
8ee6d001f3 desktop: drop tauri.conf.json version field, inherit from the crate
4-octet isn't valid semver, so Tauri's build refused it — cargo build died
before it started. desktop/Cargo.toml is the single source now; the release
gate and bump-version stop touching the field.
2026-06-14 11:48:42 -04:00
Fimeg
e2dab2845a supply-chain: gate our own deps, ship the verdict signed
dep-scan.sh gates go/npm/cargo on push and bakes an attested posture into the
release — embedded in the server, signed into the manifest. Reasoning and the
two Moby exceptions are in SECURITY.md.

(posture-builder runs rustup; bookworm's cargo is too old for cargo-audit.)
2026-06-14 11:43:23 -04:00
Fimeg
938a8f6dbb desktop: version 0.1.0 -> 0.2.8.2, into the lockstep
desktop sat at the 0.1.0 stub while everything else moved to 0.2.8.2, so the
release gate's version lockstep would reject any tag. bump-version.sh already
covers desktop (steps 5/6) — this is the one-time catch-up it couldn't do as a
no-op. Cargo.toml 3-part (0.2.8), tauri.conf.json 4-octet (0.2.8.2).
2026-06-13 20:10:47 -04:00
Fimeg
27fe605d78 ci: versioned releases publish to codeberg; drop orphaned gitea image push
Codeberg is the public distribution endpoint, so the release job now creates
the release there too — same artifacts as gitea, server image excluded (server
ships as docker-compose build from source). The docker job that built and pushed
redflag-server to the private gitea registry is gone: nothing pulled it once the
install checkoff started reading the running container, and as a publish gate it
could block a public release on a private-registry hiccup.

README clone URL -> codeberg; Dockerfile builds ./cmd/server/ as a package.
2026-06-13 19:58:35 -04:00
Fimeg
23e9c37953 fix(install): server checkoff reads running container, never pulls a registry
The docker-component checkoff ran 'docker run 10.10.20.120:4455/fimeg/redflag'
to read a version string — reaching the private Gitea registry from every
install, and 'grep redflag' matched unrelated containers. Verify the running
redflag-server container's --version locally instead; agent-only hosts skip
cleanly. (INSTALL-001)
2026-06-13 16:17:55 -04:00
Fimeg
e5f8444482 ci: validate wiuf-docker runner (gitea official image) 2026-06-13 10:13:11 -04:00
Fimeg
ada246764c ci: validate wiuf-docker runner 2026-06-13 09:43:52 -04:00
Fimeg
9be8aba073 fix: dashboard populates Updates-by-Type and gives honest severity bars
The stats handler initialized updates_by_type but never filled it, so the
"Updates by Type" card always rendered empty (Codeberg #10). Add
UpdateQueries.GetUpdatesByType (grouped by package_type, non-terminal scope)
and wire it into GetDashboardStats.

Severity bars were sized against total_updates (all statuses) while the
severity counts are scoped to non-terminal rows — a scope mismatch. Bars now
size against the sum of the scoped severity values, so they form a true
breakdown that always sums to 100% and never overflows.

Also closed the silent error-swallows in GetDashboardStats: each sub-count
failure is now logged [ERROR] [server] [stats] instead of vanishing.
2026-06-13 08:23:20 -04:00
Fimeg
b8cdb91a21 ci: nightly alpha channel + hand profile readme to profile-engine 2026-06-12 19:48:54 -04:00
Fimeg
0e1a375af6 ci: fix codeberg secret name typo, escape badge date, guard profile step 2026-06-12 18:57:48 -04:00
Fimeg
8c7e6a4d76 ci: sync-codeberg also stamps .profile README with badges + activity 2026-06-12 16:49:40 -04:00
Fimeg
6a59d46631 fix: escape docker container check from Go template parser
docker ps --format '{{.Names}}' gets eaten by text/template before
Docker sees it. Use docker container ls + grep instead.
2026-06-12 15:38:38 -04:00
Fimeg
0dbf4432dd ci: sync-codeberg job — auto-push public to codeberg when CI passes 2026-06-12 15:23:46 -04:00
Fimeg
88b612c77e feat: component manifest drives installs, checkoff, and desktop lockstep
INSTALL-001: manifest schema with components+artifacts, CI generation
in release gate, manifest-driven install template with --guided and
--checkoff modes, post-install provisioning checks, desktop joins
version lockstep (bump-version.sh + CI build + gate enforcement).

Setup.tsx reduced to primitives (FormSection, TextField, Alert).
2026-06-12 15:23:15 -04:00
Fimeg
0669b4d6b1 web: completed is green everywhere; typed-confirmation actually gates
CommandStatusBadge joins the inline timelines (Casey ruling). SecuritySettings CONFIRM/RESET input was theater — border colors changed, Confirm worked regardless. Now controlled state, button disabled until the phrase matches.
2026-06-12 14:35:27 -04:00
Fimeg
6fb7e7c81f web: shared timestamp formatters + PageState adoption; Agents test gets ConfirmProvider
formatUnixTime/formatTimeOnly into utils (ProcessDetailModal's formatTime was never a duration). RateLimiting loading state onto PageState; six candidate sites correctly left alone as section/inline loaders. Agents.test.tsx wraps in ConfirmProvider — the 31c4ae74 conversion broke it and nobody ran the full suite.
2026-06-12 14:25:32 -04:00
Fimeg
8c396c1f7a web: hand-rolled modal overlays onto the Modal primitive
Five sites converted (LiveOperations, AgentUpdatesEnhanced x2, SecurityEvents, ProcessDetailModal, SecuritySettings); Layout's sidebar backdrop is a drawer, not a modal — left alone. Modal grows maxHeight + Body scrollable.
2026-06-12 14:18:52 -04:00
Fimeg
31c4ae74e5 web: ConfirmDialog primitive — window.confirm is gone
ConfirmProvider + useConfirm, 11 call sites converted (4 more than expected). Danger variant: red button, Enter inert, cancel takes focus — a stray Enter can never destroy. Modal now yields focus to autoFocus children.
2026-06-12 14:11:16 -04:00
Fimeg
d75939cb6a web: status/severity colors get one truth table
statusColors.ts in primitives — 9 domains, kept distinct on purpose. Eight files stop hand-rolling switches. Known discrepancy documented in place: CommandStatusBadge paints completed gray, both inline command timelines paint it green.
2026-06-12 14:01:00 -04:00
Fimeg
e0f2dd8b07 tests: drop unused React imports breaking tsc 2026-06-12 13:41:11 -04:00
Fimeg
415f229b8f web: server status awareness — version header, disconnect overlay, update banner
X-RedFlag-Version on every response; axios interceptor tracks connection state, no dedicated health poll. Recovered from stash — never meant to be parked.
2026-06-12 13:41:11 -04:00
Fimeg
8d54fec8eb raf: desktop component + local trust boundary + fleet-join maintainability
- components/05-desktop.md: the tray as credential-less localapi client; no-token surface marked as open decision (peer identity unanswered), not doctrine
- trust-boundaries: Local boundary section — the kernel is the middleware, group stamping at login is the sharp edge
- standalone-authority: fleet join must stay idempotent, single-source gated, and tested in both directions
2026-06-12 13:26:54 -04:00
Fimeg
71fe075f65 desktop: fix tray icon depth, entry routing, socket error UX
- icon.png 16-bit -> 8-bit RGBA (tray panicked on data size)
- devUrl + dist rename so the desktop entry actually loads (release served 404, dev served the fleet login)
- permission denied on the localapi socket now explains group membership / re-login instead of os error 13
2026-06-12 13:19:51 -04:00
Fimeg
070148f1f5 test: set issuer claim in auth verify test tokens
Now mandatory after the JWT issuer grace period closed.
2026-06-11 20:58:28 -04:00
Fimeg
7670594ac3 sec: issuer claim mandatory — grace period closed
Grace shipped 2026-05-21 for pre-issuer tokens; forward-only removal.
Empty issuer now rejects like a wrong one.
2026-06-11 20:50:27 -04:00
Fimeg
2b1189aaa2 sec: hash failure now blocks approval — fail closed
Hash registry is the tamper gate; approving without it was fail-open.
Empty hash with no error (no artifact) still passes.
2026-06-11 20:48:05 -04:00
Fimeg
6a4be4d12f refactor: timeout + reconciler tickers onto bgRunner
Last two raw tickers; now they get shutdown, panic isolation,
and /health/tasks like everything else.
2026-06-11 20:48:04 -04:00
Fimeg
1af5a9a184 test: guard test learns the bgRunner.Every pattern
Ticker consolidation moved refresh_token_cleanup into the taskrunner;
the source-grep guard only knew go func/ticker.
2026-06-11 20:39:32 -04:00
Fimeg
6cec9aa8ac test: atomic counter in notifier countingSink
Dispatch fires sinks in goroutines; the plain-int counter tripped
go test -race. CI red since the notification bell landed.
2026-06-11 20:27:28 -04:00
Fimeg
dee6149c06 bump: v0.2.8.2
Version lockstep across server, agent, docker-compose, helper.
2026-06-11 20:25:08 -04:00
Fimeg
a944479085 changelog: backfill v0.2.8.1, add v0.2.8.2 2026-06-11 20:24:33 -04:00