feat: setup logs retention by max file size
This commit is contained in:
1 parent
70c8492f4f
commit
f914eae3c5
44 files changed
+2316
-161
No files matched your search
@@ -72,3 +72,51 @@ Settings (mount SettingsView, GET /v1/settings mocked with the five-key body):
|
||||
- [ ] Home at 1440 and 390 px, light and dark: 420 px column in the far-right of the full content width, 16 px gap, row clamping, "View all" 44 px touch target; the article column fills the remaining width and still reads well.
|
||||
- [ ] Keyboard and focus: Home tab order "New article", article rows, "View all"; Settings select, Apply, Cancel in order and focus back on the select after Cancel.
|
||||
- [ ] Hover, focus rings, the 2 s "Saved" fade and reduced motion.
|
||||
|
||||
## Retention size limit extension
|
||||
|
||||
Spec: rule "Retention size limit" in activity_home_card_and_retention.feature. Items 14 to 25 above are updated for the widened mock body (activity_retention_max_gb, activity_log_size_bytes) and the new helper and alert copy.
|
||||
|
||||
Implementation note for coder (informational, not a QA assertion):
|
||||
- audit.Settings gains RetentionMaxGB; the settings use case result carries LogSizeBytes from audit.Repository.SizeBytes.
|
||||
- audit.SizeOptions() is [0, 1, 5, 10, 25, 50]; invalid values return ErrInvalidRetention.
|
||||
- audit.Repository gains SizeBytes() (int64, error) and DeleteOldest(limit int, before time.Time) (int, error).
|
||||
- audit.SettingsRepository.SaveRetention takes days and max_gb; the model and mapper gain retention_max_gb.
|
||||
- The cleanup use case runs the age step when days > 0, then loops DeleteOldest batches with SizeBytes until the log fits or a batch removes 0; the cutoff is the 24 h guard.
|
||||
- The handler request struct is a partial with pointer fields and validate tags; an empty object is rejected.
|
||||
- settingsResponse gains activity_retention_max_gb and activity_log_size_bytes. Update the settings_page tests that count keys.
|
||||
|
||||
### Go (httptest, fakes)
|
||||
- G11. GET key set is exactly the seven keys; max_gb and size_bytes carry the fake's values; a fresh fake gives 90, 0, 0.
|
||||
- G12. GET next-cleanup table: (90, 0), (90, 5), (0, 5) are non-null; (0, 0) is JSON null with the key present.
|
||||
- G13. PATCH table: size alone, age alone, both, Forever plus size, size 0 with Forever (next becomes null); the fake repository holds the pair.
|
||||
- G14. PATCH invalid: sizes 2, -1, 100, 5.5, "5", null, mixed with a valid age, {}, not JSON; each 400 with the BodyErrorMessage text and nothing saved. Non-owner 403, no cookie 401.
|
||||
- G15. No-op PATCH of both saved values: 200, no save, no event.
|
||||
- G16. Audit params table for the three bodies (age, size, both).
|
||||
- G17. Cleanup use case with a fake events repository that has a size model: age then size, Forever plus size, Forever with no size (ran=false, no calls), size already met (no DeleteOldest), the guard stops at 24 h with 0 removed and no error, DeleteOldest error propagates and leaves the last cleanup unchanged, total removed in the event params and in SaveLastCleanup, the batch loop terminates when a batch removes 0.
|
||||
- G18. CleanupDue table unchanged; Tick runs for Forever when a size limit is set.
|
||||
- G19. Domain: SizeOptions validation; next-cleanup is nil only when both are 0.
|
||||
- G20. Persistence on in-memory SQLite (extend test/activity_persistence_test.go): SizeBytes with multi-byte text, the empty table, after delete; DeleteOldest with the limit and the guard; the migrated model has retention_max_gb defaulting to 0.
|
||||
- G21. The interface-shape test is updated to the six methods.
|
||||
- G22. A SizeBytes error propagates and the handler answers 500 "Internal server error".
|
||||
|
||||
### SPA (Vitest), extending web/src/views/__tests__/SettingsRetention.spec.ts
|
||||
- 26. Default 90 days or 5 GB; Age only; Size only (forever); Forever without a size: selects, helpers, "Currently 3.2 GB.", the "or" divider, the lines.
|
||||
- 27. Size formatting table (3.2, "Less than 0.1 GB", 5.0); 1024^3 base.
|
||||
- 28. Larger size or No size limit: one PATCH with only the size key, "Saving…" then "Saved" (fake timers).
|
||||
- 29. Smaller size, and a size when none was set: no PATCH, warning copy, Apply sends one PATCH, Cancel reverts.
|
||||
- 30. One warning at a time; a longer or larger choice drops it.
|
||||
- 31. Save errors (500, 400, 403, network): only the size select reverts; Try again re-sends the same body without re-confirming; 403 refreshes the session and the card disappears.
|
||||
- 32. Offline disables both selects and Apply and Cancel; 401 is global.
|
||||
- 33. French parity for the new strings; lib/activitySentence.spec.ts covers the size-change sentence in English and French.
|
||||
|
||||
### Visual (task visual:check)
|
||||
The board draws the card in group "Settings: Retention" with the states 'Age only (no size limit)' and 'Size only (forever)'. In settings.md the states are bullets, not headings, so confirm on the first run whether the tool iterates them. Setups use the board's own sample data (5 GB, 3.2 GB) and the owner /v1/settings mock gets the widened body. Clock-sensitive states stay skip: 'clock-sensitive'. No exception beforehand.
|
||||
|
||||
### Manual verification
|
||||
- [ ] Real SQLite file: activity_log_size_bytes grows as events are added and falls after a forced cleanup.
|
||||
- [ ] Forced cleanup with a small limit removes the oldest events and leaves the last 24 h.
|
||||
- [ ] Optional: SizeBytes on real MySQL and PostgreSQL.
|
||||
- [ ] Real PATCH as owner for each option, as admin 403, as owner with 2 GB 400.
|
||||
- [ ] Keyboard order: age select, size select, Apply, Cancel; focus returns to the triggering select after Cancel.
|
||||
- [ ] 1440 and 390 px, light and dark: the "or" divider and the 160 px or full-width size select as drawn in the board.
|
||||
Reference in new issue
Block a user