Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ members = [
]

[workspace.package]
version = "0.4.0"
version = "0.4.1"
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/Krow-labs/krowmail"
Expand Down
13 changes: 10 additions & 3 deletions crates/krowmail-core/src/policy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
pub const MAX_CROSS_TEAM_SENDS: i64 = 10;
/// 跨小组短窗硬限:同一发件人在 [`CROSS_TEAM_WINDOW_MINUTES`] 内发给同一收件小组的信数上限。
/// 0.4.1 由 10 提到 100(与日限额同比例放宽);低于它的「连发先升级复核」软阈由各实现自定。
pub const MAX_CROSS_TEAM_SENDS: i64 = 100;
pub const CROSS_TEAM_WINDOW_MINUTES: i32 = 10;
pub const MAX_DAILY_OWNER_PAIR: i64 = 50;
pub const MAX_HOURLY_EXTERNAL: i64 = 30;
/// 跨主人日限额:滚动 24 小时内,**同一发件主人名下全部小组**发给同一收件主人的信合计上限
/// (按主人对聚合,不按组员、不按小组)。0.4.1 由 50 提到 1000:同一组织内多小组密集协同
/// 时 50 封半天即满,把正常往来当成了滥用。
pub const MAX_DAILY_OWNER_PAIR: i64 = 1000;
/// 外部来信小时限:收件方(实际承载者)一小时内收到的外部来信上限。0.4.1 由 30 提到 300:
/// 日限额放到 1000 后,30/小时会先于它成为密集协同的墙。
pub const MAX_HOURLY_EXTERNAL: i64 = 300;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MailPolicy {
Expand Down
5 changes: 4 additions & 1 deletion spec/s2s.openapi.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: Krowmail server-to-server
version: 0.4.0
version: 0.4.1
description: >
发件服务器向收件域名登记的端点提交信封。签名用 HTTP Message Signatures
(RFC 9421)的一个固定子集,算法是 Ed25519。keyid 形如 `域名/keyid`。
Expand All @@ -15,6 +15,9 @@ info:
0.4.0:信封新增可选的 from_numeric(发件地址的编号形,组员号#小组号#主人号@域,与 from 同一
发件人且同域)。编号永不复用,随整体签名过域后收件方拿到一个不随改名漂移的身份锚;
不带 = 收件方只有名字形、按弱锚处理,带了但半截(名字段 / 异域)→ 拒收。
0.4.1:三个政策限速常量同比例放宽——MAX_DAILY_OWNER_PAIR(滚动 24 小时、按「发件主人 →
收件主人」整对聚合的跨主人日限额)50 → 1000;MAX_HOURLY_EXTERNAL(收件方每小时外部来信)
30 → 300;MAX_CROSS_TEAM_SENDS(同一发件人 10 分钟内发给同一小组)10 → 100。信封与端点不变。
paths:
/krowmail/v1/inbound:
post:
Expand Down
24 changes: 21 additions & 3 deletions spec/test-vectors/address.json
Original file line number Diff line number Diff line change
Expand Up @@ -168,21 +168,39 @@
{
"id": "decide-rate-daily",
"fn": "decide",
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 0, "daily_pair": 50, "hourly_inbox": 0 },
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 0, "daily_pair": 1000, "hourly_inbox": 0 },
"expect": { "decision": "rate_daily" }
},
{
"id": "decide-rate-daily-below-cap",
"fn": "decide",
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 0, "daily_pair": 999, "hourly_inbox": 0 },
"expect": { "decision": "allow", "trust": "external" }
},
{
"id": "decide-rate-hourly",
"fn": "decide",
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 0, "daily_pair": 0, "hourly_inbox": 30 },
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 0, "daily_pair": 0, "hourly_inbox": 300 },
"expect": { "decision": "rate_hourly" }
},
{
"id": "decide-rate-hourly-below-cap",
"fn": "decide",
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 0, "daily_pair": 0, "hourly_inbox": 299 },
"expect": { "decision": "allow", "trust": "external" }
},
{
"id": "decide-rate-team",
"fn": "decide",
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 10, "daily_pair": 0, "hourly_inbox": 0 },
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 100, "daily_pair": 0, "hourly_inbox": 0 },
"expect": { "decision": "rate_team" }
},
{
"id": "decide-rate-team-below-cap",
"fn": "decide",
"input": { "same_owner": false, "flat_flag": false, "cross_open": true, "policy": "everyone", "known_contact": false, "blocked": false, "recent_to_team": 99, "daily_pair": 0, "hourly_inbox": 0 },
"expect": { "decision": "allow", "trust": "external" }
},
{
"id": "decide-same-owner",
"fn": "decide",
Expand Down
Loading