AI spam classification: the model's opinion as one bounded spam signal, and the llm_prompt Sieve function (AI-1 to AI-28)
The classifier sends only the subject and text, between unforgeable markers after the operator's prompt, to an OpenAI-compatible endpoint the operator configured; nothing is preset. Its answer maps to an LLM_ tag whose score is clamped (+5.0, -1.0 by default) and can never discard or reject on its own; X-Spam-LLM is sanitized, encoded and folded, and a planted one is removed. Failures, timeouts past the ceiling, a full slot or a paused model leave mail flowing untagged. llm_prompt answers trusted scripts, and accounts holding interactAi within an hourly limit. Redirects aren't followed and no content or secret is logged. The limits live in inbuxa:AiLimits. Acceptance tests 1 and 3 to 21; test 2 as the re-enabled shared llm case, whose setup no longer waits on a rules file from a developer's own path; test 22 written as the ignored ai_compat.
This commit is contained in:
@@ -73,6 +73,8 @@ impl JmapAuthorization for AccessToken {
|
||||
GetRequestMethod::MaskedEmail(_) => Permission::SysMaskedEmailGet,
|
||||
// inbuxa: deleted accounts (UD-17)
|
||||
GetRequestMethod::DeletedAccount(_) => Permission::SysAccountGet,
|
||||
// inbuxa: AI call limits, with the classifier's permissions
|
||||
GetRequestMethod::AiLimits(_) => Permission::SysSpamLlmGet,
|
||||
GetRequestMethod::Principal(_) => Permission::JmapPrincipalGet,
|
||||
GetRequestMethod::Quota(_) => Permission::JmapQuotaGet,
|
||||
GetRequestMethod::Blob(_) => Permission::JmapBlobGet,
|
||||
@@ -161,6 +163,14 @@ impl JmapAuthorization for AccessToken {
|
||||
Permission::SysAccountCreate,
|
||||
Permission::SysAccountDestroy,
|
||||
),
|
||||
// inbuxa: AI call limits, with the classifier's permissions
|
||||
SetRequestMethod::AiLimits(s) => validate_set(
|
||||
s,
|
||||
self,
|
||||
Permission::SysSpamLlmUpdate,
|
||||
Permission::SysSpamLlmUpdate,
|
||||
Permission::SysSpamLlmUpdate,
|
||||
),
|
||||
SetRequestMethod::VacationResponse(s) => validate_set(
|
||||
s,
|
||||
self,
|
||||
@@ -269,7 +279,8 @@ impl JmapAuthorization for AccessToken {
|
||||
| MethodObject::VacationResponse
|
||||
| MethodObject::SieveScript
|
||||
| MethodObject::MaskedEmail
|
||||
| MethodObject::DeletedAccount => Permission::JmapEmailChanges,
|
||||
| MethodObject::DeletedAccount
|
||||
| MethodObject::AiLimits => Permission::JmapEmailChanges,
|
||||
// inbuxa: x:MaskedEmail/changes reads what /get reads
|
||||
MethodObject::Registry(object_type) => object_type.get_permission(),
|
||||
},
|
||||
|
||||
@@ -168,6 +168,9 @@ impl RequestHandler for Server {
|
||||
SetResponseMethod::DeletedAccount(set_response) => {
|
||||
set_response.update_created_ids(&mut response);
|
||||
}
|
||||
SetResponseMethod::AiLimits(set_response) => {
|
||||
set_response.update_created_ids(&mut response);
|
||||
}
|
||||
SetResponseMethod::AddressBook(set_response) => {
|
||||
set_response.update_created_ids(&mut response);
|
||||
}
|
||||
@@ -316,6 +319,13 @@ impl RequestHandler for Server {
|
||||
.await?
|
||||
.into()
|
||||
}
|
||||
// inbuxa: inbuxa:AiLimits/get
|
||||
GetRequestMethod::AiLimits(mut req) => {
|
||||
resolve_account_id(&mut req.account_id, method_name.obj, access_token)?;
|
||||
crate::inbuxa::ai_limits::get(self, access_token, *req)
|
||||
.await?
|
||||
.into()
|
||||
}
|
||||
GetRequestMethod::Principal(req) => {
|
||||
self.principal_get(*req, access_token).await?.into()
|
||||
}
|
||||
@@ -550,6 +560,13 @@ impl RequestHandler for Server {
|
||||
.await?
|
||||
.into()
|
||||
}
|
||||
// inbuxa: inbuxa:AiLimits/set
|
||||
SetRequestMethod::AiLimits(mut req) => {
|
||||
resolve_account_id(&mut req.account_id, method_name.obj, access_token)?;
|
||||
crate::inbuxa::ai_limits::set(self, access_token, *req)
|
||||
.await?
|
||||
.into()
|
||||
}
|
||||
SetRequestMethod::AddressBook(mut req) => {
|
||||
resolve_account_id(&mut req.account_id, method_name.obj, access_token)?;
|
||||
access_token.assert_has_access(req.account_id, Collection::AddressBook)?;
|
||||
|
||||
Reference in New Issue
Block a user