Old key stays is_active=true after SetPrimaryKey with no TTL or auto-deprecate.
README now says what actually exists: operator promotes new key, then explicitly
deprecates the old one. No sliding-window automation yet.
RAF/SUPPLY_CHAIN_GATE_PLAN.md unblocked — the architectural thesis for the
capability-token model. Updated to reflect agent-self upgrade path, OSV
expansion, and current verification state.
README Status section rewritten: "implemented and locally exercised, not
production-proven" replaces the misleading "working in production" header.
Honest gaps listed (GATE-002, CRITICAL-004).
Trust model: refresh-token rotation paragraph now states the 90-day expiry.
OPERATIONS.md (operator runbook) whitelisted in .gitignore — useful for
anyone deploying RedFlag.
SEC-001: Registration tokens stored as SHA-256 hashes. Migration 046 adds
token_hash column, backfills from plaintext, drops token column. All queries
use hash. Token plaintext shown once at creation (reveal panel in UI), never
retrievable again. Follows the refresh-token pattern.
SEC-005: README "no sanitization" claims corrected — code correctly sanitizes
against log injection (ANSI stripping, control char replacement, truncation).
Wording updated to match reality.
SEC-008: Command creation with idempotency_key uses ON CONFLICT DO NOTHING
instead of blind insert. Prevents duplicate command execution.
Trust model: Ed25519 key rotation documented — signing_keys table supports
multiple concurrent active keys with a sliding window for zero-downtime
rotation. OSV.dev ecosystem coverage updated (apt, dnf added).
No unsigned binary path: build refuses when signing is disabled, downloads
return 404 when no signed package resolves. Signed release manifest endpoint,
installer verifies manifest signature and pins binary hash, Windows token
mandatory, Rust helper verify-binary.
Migration 033 adds the 'received' status to agent_commands so the server can
distinguish "agent confirmed receipt" from "sent but may be lost in flight."
Stuck-command re-issuance now excludes received commands — the TimeoutService
handles the longer timeout for those (default 30m) vs the per-poll re-issuer
(sent/pending at 5m).
The agent side: disk-persists executed command IDs to survive restart (closes
the in-memory-only dedup gap), reports received_command_ids on each check-in so
the server transitions sent→received before issuing new work, and authenticates
binary downloads with JWT+X-Machine-ID (was unauthenticated http.Get — would
401 in production).
TimeoutService extended with reconcileAgentUpdates: clears is_updating when
current_version matches updating_to_version (success), or after a 15m threshold
(timeout, with system_event) so the dashboard never shows "updating" forever.
isVersionUpgrade replaced with utils.IsNewerVersion (no panic on 2-part
versions, no false-reject on 4-part).
MarkCommand* failures elevated from [WARNING] to [ERROR] + should_retry
response hint so agents know to re-deliver results (silent drops were ETHOS #1
violations).
Fixes: build broken on public since eac8a012 (command.go accidentally emptied).
- Version bump to 0.2.0, changelog with all new features
- Fix Quick Start ports (3000→31336)
- Fix architecture diagram ports (3000/8080→31336/31337)
- Add new features to list: key rotation, replay protection,
maintenance windows, supply chain checks
- Update Known Issues to be honest about gaps
- Update competitive position section
The pre-v0.1.20 upgrade note had vented frustration in it. Same substance
(uninstall + reinstall is the supported path; reach out for large fleets),
without the curt phrasing.
Complete RedFlag codebase with two major security audit implementations.
== A-1: Ed25519 Key Rotation Support ==
Server:
- SignCommand sets SignedAt timestamp and KeyID on every signature
- signing_keys database table (migration 020) for multi-key rotation
- InitializePrimaryKey registers active key at startup
- /api/v1/public-keys endpoint for rotation-aware agents
- SigningKeyQueries for key lifecycle management
Agent:
- Key-ID-aware verification via CheckKeyRotation
- FetchAndCacheAllActiveKeys for rotation pre-caching
- Cache metadata with TTL and staleness fallback
- SecurityLogger events for key rotation and command signing
== A-2: Replay Attack Fixes (F-1 through F-7) ==
F-5 CRITICAL - RetryCommand now signs via signAndCreateCommand
F-1 HIGH - v3 format: "{agent_id}:{cmd_id}:{type}:{hash}:{ts}"
F-7 HIGH - Migration 026: expires_at column with partial index
F-6 HIGH - GetPendingCommands/GetStuckCommands filter by expires_at
F-2 HIGH - Agent-side executedIDs dedup map with cleanup
F-4 HIGH - commandMaxAge reduced from 24h to 4h
F-3 CRITICAL - Old-format commands rejected after 48h via CreatedAt
Verification fixes: migration idempotency (ETHOS #4), log format
compliance (ETHOS #1), stale comments updated.
All 24 tests passing. Docker --no-cache build verified.
See docs/ for full audit reports and deviation log (DEV-001 to DEV-019).