[04] slice E2 licensing collection CRUD (D31)

FeatureSecurityService
Shipped
July 4, 2026 at 2:15 AM UTC
Author
Kamo
Commit
addc23c

The first COLLECTION config domain (doc-04 §3.2 LicensingEntry, many-per-profile) — a new id-keyed write shape on the same audit spine as the singletons: - **************** / updateLicense / deleteLicense: profileVersion bump + §4b.1 validate-or-rollback + WORM change-log per row; identity server-stamped. Update/delete resolve the row by id then fail-closed 404 (NoSuchRowException) if it is not the operator org's profile's — no cross-profile existence oracle. - deleteLicense is a HARD delete (audited {"deleted":true,row}) because LicensingResolver reads entries UNFILTERED by record state — a soft flag would still count as licensed; to expire without deleting, set expiryDate to the past. - MlosConfigController: GET /licensing (list, effectiveToday computed via isEffectiveOn(today), never stored), POST /licensing, PUT /licensing/{id} (update, or remove via {active:false} — the config proxy has no DELETE verb); ISO-date + enum + expiry>=effective validation; NoSuchRowException->404. Investors (+3 children) and RiskOverlay reuse this shape in later slices. 6 tests.

All changes

Like what you see shipping?

Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.

Start Free ForeverView Pricing