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

489 commits

Author SHA1 Message Date
Fimeg
1b307b08eb helper: cast openat mode for darwin
mode_t is u16 on macOS and a variadic argument promotes to at least c_uint, so aarch64-apple-darwin failed E0617 while every Linux target built clean.

The cast is a no-op where mode_t is already u32.
2026-09-03 18:49:08 -04:00
Fimeg
87038170ac desktop: point qmlls at a relative build dir
The tracked buildDir was an absolute path into a worktree that no longer exists, so the setting was already dead.

It is also what the release workflow's public-history gate rejects; relative to desktop/ it resolves in any checkout.
2026-09-03 18:49:01 -04:00
Fimeg
213918f1a2 raf: record the standalone pacman boundary
Pacman now has one local envelope path from Desktop intent to a joined helper receipt.

Name the same-host authority limit, missing fleet delivery, and unsupported Arch advisory mapping without painting them green.
2026-09-01 14:14:00 -04:00
Fimeg
7472d21c42 standalone: carry pacman through local authority
Give a standalone Agent a durable identity and one signed pacman envelope path through the helper.

Every archive and detached signature crosses root custody before mutation. Fleet credentials still refuse the local minter.
2026-09-01 14:12:39 -04:00
Fimeg
776405b618 desktop: normalize the native console QML
Keep the mechanical Qt formatter change separate from the machine-software and authorization work that follows.
2026-09-01 09:29:47 -04:00
Fimeg
6854509c57 merge: join pacman custody to Desktop
The helper now accepts verified pacman envelopes on the same line as the native console. This preserves the three reviewed custody fixes; it does not yet teach the Agent to resolve and mint pacman closures.
2026-09-01 08:30:23 -04:00
Fimeg
f487de554a desktop: become the machine console
Qt/QML now carries 11 local views while the Agent owns observation and intent. Tauri, WebKit, and the second React desktop build leave together. Linux ships first; Windows waits for a native Qt runner.
2026-09-01 08:29:58 -04:00
Fimeg
b056ab5199 publish: adopt the intermediate cut the forge already holds
Forgejo carries f5eb83ca, an earlier cut of the mutation contract that this
history amended rather than continued, so the publication gate's fast-forward
check refuses. Recording it as an ancestor keeps the newer tree and lets the
exact tested SHA publish. Nothing in that commit is absent here.
2026-09-01 08:15:25 -04:00
Fimeg
102ea23058 processes: read the capabilities the readme already claimed
CapEff was never collected — "sockets, capabilities, namespaces" meant the
collection limits, and a reader has no way to know that. The mask is read on
the list scan and expanded to names only on drill-down, because a fully
privileged process holds all 41 and nobody reads that on 300 rows.

Docker's documented default mask a80425fb decodes to exactly its fourteen.
2026-08-31 22:44:18 -04:00
Fimeg
23b2d5c3c2 readme: clone from the forge that still gets pushed
The quick start pointed at codeberg, which the release job stopped pushing
to; it has been frozen at July 6 while public moved on. A stranger following
the readme was cloning a dead snapshot.
2026-08-31 22:41:53 -04:00
Fimeg
d1670cfd6a processes: attribute each pid to its unit or container
/proc/[pid]/cgroup gives the join the process list never had: systemd unit,
container id, runtime. Both cgroup generations, both cgroup drivers, docker,
podman, containerd, crio and lxc. On a 321-process desktop every userland
process attributes; the 172 that do not are kernel threads.

The kernel's id is full-length and the docker inventory reports twelve
characters, so the join is a prefix, not equality. RAF carries the rule.
2026-08-31 22:40:52 -04:00
Fimeg
ffa7afbb58 desktop: put this computer health first
The Agent now owns one local view of machine health and top processes. RedFlag opens at dashboard scale, names itself plainly, and renders that evidence before updates.\n\nCI now compiles the Tauri bridge before release day.
2026-08-31 21:20:00 -04:00
Fimeg
3ecec1f547 fix(helper): close pacman custody gaps 2026-08-31 21:09:07 -04:00
Fimeg
d089435c2f fix(helper): box envelope verification errors 2026-08-31 21:03:12 -04:00
Fimeg
fb53568d37 feat(helper): execute verified pacman envelopes 2026-08-31 20:43:19 -04:00
Fimeg
320ad46e00 feat(helper): accept dormant mutation envelopes
Cut 2 adds a verify-envelope path beside the closure-token executor. The helper parses an envelope, binds it to the independently provisioned agent identity, validates time and lifetime bounds, selects the trusted key, verifies the signed contract, checks backend payload shape, and then refuses with backend_not_migrated.

Every path emits an unsigned MutationReceipt. No backend executes, no replay slot is consumed, and no artifact-custody claim is made until the first existing backend migrates.
2026-08-26 18:39:41 -04:00
Fimeg
517f1aca20 feat: pin complete mutation authority contract
Cut 1 completes the dormant MutationEnvelope contract without changing any runtime path. Bind target_id to the provisioned agent identity, require canonical UUID v4 authorization IDs, cap authorization lifetime at the fleet TTL, and add an unsigned MutationReceipt carrying the audit join.

Server, Agent, and helper share the same canonical bytes, key identity, receipt digest, and Ed25519 golden vectors. Current APT/DNF and Windows execution remains untouched.
2026-08-26 18:39:29 -04:00
Fimeg
f5eb83ca94 feat: pin mutation manifest authority bytes
Introduce a dormant MutationEnvelope beside the current closure token. Server, Agent, and helper now agree on length-prefixed manifest and authorization bytes, with one shared fixture pinning the hash, key identity, and Ed25519 signature.\n\nExecutor-affecting provenance, location, target, backend, and backend payload now have a signed home before any runtime path migrates. Exact duplicates stay visible in the hash; ordering does not. Current APT/DNF and Windows behavior remains untouched.
2026-08-26 16:07:19 -04:00
Fimeg
c3037655cd docs: bind the supply-chain claims to the helper 2026-08-25 08:26:05 -04:00
Fimeg
14d4730c76 ci: make the publication gate rerunnable 2026-08-20 16:06:20 -04:00
Fimeg
7427174d99 deps: lift patched public floors
CI found nine reachable Go issues and a high Axios advisory. Move to the published fixed floors and retire three stale Docker exceptions.
2026-08-20 13:14:28 -04:00
Fimeg
f6b03f40c6 ci: publish and verify forgejo releases
Tags now cross only after the release gates. Public assets are read back anonymously and hashed; the Rust Action pin now names its advertised stable commit.
2026-08-20 12:40:47 -04:00
Fimeg
95a6ec0511 ci: remove codeberg release pushpoints 2026-08-20 12:12:15 -04:00
Fimeg
5e15595f8d ci: publish only to forgejo 2026-08-20 12:07:56 -04:00
Fimeg
de0e70079a ci: gate and verify public releases 2026-08-20 12:02:35 -04:00
Fimeg
9f47d782af fix(BUG-001): canonicalize pip package type in gate decisions
Server gate functions only recognized 'pypi', while the agent reports
'pip'. This made NeedsCapabilityGate('pip') return false, silently
routing pip installs through the legacy un-gated path.

All four gate functions now accept 'pip' with 'pypi' retained as an
alias for existing DB records.
2026-08-12 20:36:08 -04:00
Fimeg
1f75bfd23a device-type: layered detection + laptop/vm/container types
Replaces the flat battery x display matrix (which misclassified laptops
as phones) with layered detection: container -> vm -> SMBIOS chassis ->
ARM fallback. Adds laptop, vm, container device types across agent,
migration 062, server validation, web icons/types.
2026-07-12 14:55:04 -04:00
Fimeg
a700edccc6 release.sh: origin remote + single-tag push
auto-detect gitea-local vs origin (RELEASE_REMOTE override); push only
the release tag instead of --tags, which choked on divergent legacy tags.
2026-07-12 14:54:45 -04:00
Fimeg
ff2f30f47a v0.2.9.3: device classification + ARM support — Pixel 3 lands
DEVICE-002: ARM machine-ID fallback — device-tree model + /etc/machine-id
combo, then /proc/cpuinfo Serial (all-zero rejected), before the weak
hostname fallback. Hardware-bound IDs on DMI-less devices.

DEVICE-001: agent detects device_type (server/desktop/phone/tablet) from
/sys signals — system battery (scope=Device peripherals excluded, UPS
excluded), DRM connector state, framebuffer min-dimension for phone/tablet
split. Reports device_type/device_model/os_distro in registration and
system-info paths.

SERVER-001: migration 061 — device_type, device_type_manual (operator
override, never agent-written), device_model, os_distro on agents.
effective_device_type computed into every serialized agent.

SERVER-002: PUT /admin/agents/:id/device-type — set/clear override,
enum-validated, journaled.

WEB-001: device-type icons + fleet filter, device model in list, detail
header badge with reclassify dropdown, os_distro surfaced.

INSTALL-003: arm64 install path unblocked — helper (required manifest
component) now cross-built aarch64-unknown-linux-musl via rust-lld in the
server image, signed at boot (helperArches += arm64), listed in the release
manifest. Install template already handled uname -m and pacman.

Plus in-flight: desktop tray wiring, enrollment page polish, CI workflow
updates, RAF session-broker/pacman-scanner docs, native installer scaffold.
2026-07-06 18:21:23 -04:00
Fimeg
b3d946b84f fix: add Docker daemon-side vulns to allowlist
Add GO-2026-5617, GO-2026-5668, and GO-2026-5746 to .govulncheck-allow.
These are all daemon-side Docker/Moby vulnerabilities that don't affect
RedFlag because it uses the Docker client only for Ping, SecretList,
and container scanning — never for docker cp, archive operations, or
AuthZ paths.

Also update SECURITY.md to document all accepted exceptions in a table.
2026-06-29 16:35:04 -04:00
Fimeg
0d260f4903 nightly: use target_commitish for previous SHA detection instead of body parsing 2026-06-29 16:04:52 -04:00
Fimeg
467a994649 enforce signed tags in release gate; add allowed signers 2026-06-29 15:51:55 -04:00
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