Clean up
This commit is contained in:
@@ -6,10 +6,11 @@
|
||||
//! it is always compiled and the Extism dependency stays in the infrastructure
|
||||
//! layer.
|
||||
//!
|
||||
//! Privacy note: the `user.login` payload includes the user's email — PII handed
|
||||
//! to untrusted plugins with no permission gate in M0. This is acceptable only
|
||||
//! because plugins are admin-installed today; when the permissions system lands,
|
||||
//! sensitive payload fields should be gated behind a granted permission.
|
||||
//! Privacy note: the `user.login` payload is deliberately minimal — an opaque
|
||||
//! `user_id` plus two non-identifying booleans (`first_login`, `is_external`).
|
||||
//! It carries no email or username, so no PII reaches untrusted plugins in M0.
|
||||
//! When the permissions system lands, richer fields (email, username) can be
|
||||
//! added back behind a granted permission.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -46,8 +47,6 @@ impl UserLifecycleHook for PluginUserLifecycleHook {
|
||||
invocation_id: Uuid::new_v4().to_string(),
|
||||
payload: serde_json::json!({
|
||||
"user_id": user.id().to_string(),
|
||||
"username": user.username(),
|
||||
"email": user.email(),
|
||||
"first_login": user.last_login_at().is_none(),
|
||||
"is_external": user.is_external(),
|
||||
}),
|
||||
@@ -126,10 +125,15 @@ mod tests {
|
||||
let ev = &events[0];
|
||||
assert_eq!(ev.name, EVENT_USER_LOGIN);
|
||||
assert_eq!(ev.user_id.as_deref(), Some(user.id().to_string().as_str()));
|
||||
assert_eq!(ev.payload["email"], "alice@example.com");
|
||||
assert_eq!(ev.payload["username"], "alice");
|
||||
assert_eq!(ev.payload["user_id"], user.id().to_string());
|
||||
assert_eq!(ev.payload["first_login"], true); // last_login_at is None
|
||||
assert_eq!(ev.payload["is_external"], false);
|
||||
// Minimal payload: no PII fields.
|
||||
assert!(ev.payload.get("email").is_none(), "must not leak email");
|
||||
assert!(
|
||||
ev.payload.get("username").is_none(),
|
||||
"must not leak username"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -104,11 +104,15 @@ pub struct PluginLogQueryDto {
|
||||
}
|
||||
|
||||
/// Per-plugin retention policy (request + response body).
|
||||
///
|
||||
/// Both limits are accepted as-is, including `0`, which means "purge all rotated
|
||||
/// segments on the next sweep" (the active log file is never touched). This is
|
||||
/// intentional — an operator can deliberately keep nothing.
|
||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ToSchema)]
|
||||
pub struct PluginRetentionDto {
|
||||
/// Delete rotated segments older than this many days.
|
||||
/// Delete rotated segments older than this many days. `0` = keep none.
|
||||
pub retention_days: u32,
|
||||
/// Aggregate byte ceiling on kept segments for the plugin.
|
||||
/// Aggregate byte ceiling on kept segments for the plugin. `0` = keep none.
|
||||
pub max_bytes: u64,
|
||||
}
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ pub enum PluginMgmtError {
|
||||
/// The bundle failed manifest or runtime validation. Carries the stable
|
||||
/// reason key from `ManifestError::reason()` / `InvokeOutcome::reason()`,
|
||||
/// plus a few install-only keys (`bad_id`, `bad_entrypoint`, `bad_zip`,
|
||||
/// `no_manifest_in_zip`, `entrypoint_not_in_zip`).
|
||||
/// `no_manifest_in_zip`, `entrypoint_not_in_zip`, `too_large`).
|
||||
Rejected(&'static str),
|
||||
/// A filesystem error while writing or removing the plugin.
|
||||
Io(String),
|
||||
|
||||
Reference in New Issue
Block a user