V4 migration drops the device_id primary key and adds an auto-generated
id BIGSERIAL as the PK. device_id becomes a unique nullable column.
Agents that don't send a numeric deviceId can now save posture reports.
Controller GET /{deviceId} now uses findByDeviceId instead of findById.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All named enum types (threat_severity, attack_phase, event_type, ioc_type,
ioc_source, confidence_level, sequence_type, auto_response_action,
os_eol_status) have been converted to VARCHAR via V3 migration. Hibernate
@Enumerated(EnumType.STRING) binds values as character varying which
PostgreSQL rejects without explicit casts on both INSERT and SELECT.
Reverts the native @Query workarounds added in the previous two commits —
simple derived query methods now work correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PostgreSQL named enum types require explicit casts that Hibernate's
derived query methods don't generate. Replace countByOsEolStatus and
findByOsEolStatusOrderByPostureScoreAsc with native @Query variants that
CAST(:status AS os_eol_status). Same pattern already applied to severity.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds per-device security posture reports and compliance dashboard. Agents POST
posture data (disk encryption, audit policy, image hashes, OS version/EOL) to
POST /api/aria/posture/report (service-secret authenticated). DevicePostureService
upserts the record and calculates a 0–100 posture score using a penalty model:
disk encryption off −25, audit policy off −20, OS EOL −20, image hash drift −20,
whitelist off −10, stale check −5/day (capped at −15). REST API adds GET /posture
(filterable by EOL status and score band) and GET /posture/{deviceId}. Stats
endpoint gains lowPostureCount (<50) and eolDeviceCount. Dashboard reorganised
into Threat Activity and Compliance rows. Device Posture SPA view enables the
previously-disabled nav item with score bar, EOL badges, and full detail panel.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>