Files
inbuxa-server/crates/jmap-proto/src/object/inbuxa_log_settings.rs
T
jcoffey-dev 1d5a49409f
ci / fork-checks (pull_request) Successful in 2m28s
ci / build (pull_request) Successful in 3m47s
Keep rotated log files for a set number of days
Personal-data catalog spec, default D1 (settled 2026-09-28): log files
were never deleted. inbuxa:LogSettings.keepForDays says how many days
rotated log files are kept; unset (null) keeps every file, as before,
and a new install sets 30 days.

It is a fork-owned setting, stored under T + l as audit retention is,
not a field on x:TracerLog: that object is also stored inside
x:Bootstrap with a field after it, so a new field would change
x:Bootstrap's stored format. Server-level, with the tracers'
permissions (sysTracerGet, sysTracerUpdate); changes are in the audit
log, before and after.

Log files are local, so every node deletes its own: hourly, and at once
when the setting changes on that node. Only regular files named
<prefix>.<something> in each enabled log tracer's directory, last
changed more than the limit ago, are removed; the file being written is
never that old, and nothing else in the directory is touched. Minimum
one day. The catalog classifies inbuxa:LogSettings and points the log
file's retention at it.

Tested: unit tests for the file rule (only this log's old files; the
current file, other files and directories stay) and a purge on disk;
the system suite, which reads, sets, refuses zero, restores null and
checks the audit records; fork checks.
2026-09-28 08:23:36 -07:00

154 lines
3.3 KiB
Rust

/*
* SPDX-FileCopyrightText: 2026 Coffey Labs
*
* SPDX-License-Identifier: AGPL-3.0-only
*/
//! `inbuxa:LogSettings/get` and `/set` under `urn:inbuxa:jmap`: how long
//! rotated log files are kept (personal-data catalog spec, D1). A singleton,
//! id `singleton`.
use crate::object::{AnyId, JmapObject, JmapObjectId};
use jmap_tools::{Element, Key, Property};
use std::{borrow::Cow, str::FromStr};
use types::id::Id;
#[derive(Debug, Clone, Default)]
pub struct LogSettings;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum LogSettingsProperty {
Id,
KeepForDays,
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum LogSettingsValue {
Id(Id),
}
impl Property for LogSettingsProperty {
fn try_parse(_: Option<&Key<'_, Self>>, value: &str) -> Option<Self> {
LogSettingsProperty::parse(value)
}
fn to_cow(&self) -> Cow<'static, str> {
match self {
LogSettingsProperty::Id => "id",
LogSettingsProperty::KeepForDays => "keepForDays",
}
.into()
}
}
impl LogSettingsProperty {
fn parse(value: &str) -> Option<Self> {
hashify::tiny_map!(value.as_bytes(),
b"id" => LogSettingsProperty::Id,
b"keepForDays" => LogSettingsProperty::KeepForDays,
)
}
}
impl FromStr for LogSettingsProperty {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
LogSettingsProperty::parse(s).ok_or(())
}
}
impl Element for LogSettingsValue {
type Property = LogSettingsProperty;
fn try_parse<P>(key: &Key<'_, Self::Property>, value: &str) -> Option<Self> {
match key {
Key::Property(LogSettingsProperty::Id) => {
Id::from_str(value).ok().map(LogSettingsValue::Id)
}
_ => None,
}
}
fn to_cow(&self) -> Cow<'static, str> {
match self {
LogSettingsValue::Id(id) => id.to_string().into(),
}
}
}
impl JmapObject for LogSettings {
type Property = LogSettingsProperty;
type Element = LogSettingsValue;
type Id = Id;
type Filter = ();
type Comparator = ();
type GetArguments = ();
type SetArguments<'de> = ();
type QueryArguments = ();
type CopyArguments = ();
type ParseArguments = ();
const ID_PROPERTY: Self::Property = LogSettingsProperty::Id;
}
impl From<Id> for LogSettingsValue {
fn from(id: Id) -> Self {
LogSettingsValue::Id(id)
}
}
impl JmapObjectId for LogSettingsValue {
fn as_id(&self) -> Option<Id> {
match self {
LogSettingsValue::Id(id) => Some(*id),
}
}
fn as_any_id(&self) -> Option<AnyId> {
match self {
LogSettingsValue::Id(id) => Some(AnyId::Id(*id)),
}
}
fn as_id_ref(&self) -> Option<&str> {
None
}
fn try_set_id(&mut self, new_id: AnyId) -> bool {
if let AnyId::Id(id) = new_id {
*self = LogSettingsValue::Id(id);
true
} else {
false
}
}
}
impl JmapObjectId for LogSettingsProperty {
fn as_id(&self) -> Option<Id> {
None
}
fn as_any_id(&self) -> Option<AnyId> {
None
}
fn as_id_ref(&self) -> Option<&str> {
None
}
fn try_set_id(&mut self, _: AnyId) -> bool {
false
}
}