Eight conflicted files resolved, plus the lock file and the schema:
- crates/services/src/task_manager/spam_classifier.rs: upstream's rules
update now replaces existing rules, DNSBL servers, lookups and file
extensions, keeping only whether each is on. Taken, with one difference:
an object an admin edited is kept as it is. Every object an update writes
is fingerprinted (content without `enable`, SHA-256, stored under
SUBSPACE_INBUXA "Sf"), and only one that still matches is replaced.
Scores are never replaced, as upstream has it. The AU-1.10 summary record
now names what was added, replaced and kept, and the bundled rules are
marked applied only when the update fully succeeded, so a failure runs
again on the next start. The marker becomes "3.0.2+2", which runs the
update once on upgrade to fingerprint every rule still as bundled.
- crates/common/src/network/autoconfig/autodiscover.rs: upstream's rewrite
(implicit TLS first, labeled SSL), with the per-protocol switches (LP-7,
LP-14a) passed in as a filter.
- crates/store/src/backend/mysql/{search,write}.rs: upstream's chunked
deletes (no unbounded first DELETE, stop on a short chunk, halve the
chunk on the new chunk-too-large errors) inside the fork's query timeout.
- crates/smtp/src/lib.rs: the fork's queue spawn kept. It already fixed the
stall upstream fixes here (a node without outboundMta stops accepting
mail at about 1024 queued messages), and follows role changes live.
- crates/jmap/src/registry/mapping/bootstrap.rs: the log path stays
/var/log/inbuxa/; upstream's PowerDNS mapping taken.
- crates/main/Cargo.toml: the AGPL-only license kept, version 0.16.24.
- tests/src/jmap/principal/get.rs: the fork's capabilities kept.
- resources/schema/schema.json.gz: merged as JSON; upstream relabeled the
vendor Sieve extensions "(Stalwart)", kept as "(vnd.inbuxa)".
- Cargo.lock: upstream's, with the fork's crates added by Cargo.
Also:
- tests/src/smtp/inbound/spam_rules_kept.rs: an edited rule survives an
update, an unedited one is updated, rules from before fingerprints are
handled, and the audit summary says so. Upstream's own spam_rules test
passes unchanged.
- tests/src/smtp/reporting/reschedule.rs moves to port 19058; upstream's
new spam_rules test took 19057.
- tools/fork/renames.py renames the "(Stalwart)" labels and the default
log path, so neither conflicts again.
- tools/fork/notice-check.py compares against the newest snapshot in the
checked-out history instead of the upstream branch head, so moving the
branch no longer fails other open pull requests.
- tests/src/directory/issuer.rs (since v0.16.23) stays out, and is on the
build check's known list: it tests issuer-based directory routing, which
the fork doesn't have (DIR-2).
- Strip report: docs/fork/strip-reports/v0.16.24.{md,json}.
21 KiB
Strip report: upstream v0.16.24 (af37a2349817)
- Enterprise-only files removed or emptied: 63
- Enterprise-only snippets removed: 118 in 50 files
- Cargo edits turning
enterpriseoff: 25 - Dangling module declarations removed: 5
- Verification: 3 problems
- Left for the rebuilt features to replace: 19
enterprisefeature gates in 18 files; 0is_enterprise_edition()checks in 0 files - Third-party code: 14 files, 0 not in THIRD-PARTY.md
- Renamed identifiers: 62 in 18 files
- Build check: 3 errors, 16 expected errors in 7 rebuilt-feature tests, 14 imports left unused
- Upstream schema flags 9 objects and 30 fields as Enterprise
Removed files
crates/common/src/enterprise/alerts.rscrates/common/src/enterprise/config.rscrates/common/src/enterprise/license.rscrates/common/src/enterprise/llm.rscrates/common/src/enterprise/masked.rscrates/common/src/enterprise/mod.rscrates/common/src/telemetry/metrics/store.rscrates/common/src/telemetry/metrics/test_data.rscrates/common/src/telemetry/tracers/store.rscrates/http/src/api/telemetry.rscrates/jmap/src/registry/mapping/archived_item.rscrates/jmap/src/registry/mapping/masked_email.rscrates/jmap/src/registry/mapping/telemetry.rscrates/scim-proto/src/attributes.rscrates/scim-proto/src/etag.rscrates/scim-proto/src/filter.rscrates/scim-proto/src/json.rscrates/scim-proto/src/lib.rscrates/scim-proto/src/message/bulk.rscrates/scim-proto/src/message/error.rscrates/scim-proto/src/message/list.rscrates/scim-proto/src/message/mod.rscrates/scim-proto/src/message/patch.rscrates/scim-proto/src/message/search.rscrates/scim-proto/src/path.rscrates/scim-proto/src/schema/group.rscrates/scim-proto/src/schema/mod.rscrates/scim-proto/src/schema/spc.rscrates/scim-proto/src/schema/user.rscrates/scim/src/auth.rscrates/scim/src/bulk.rscrates/scim/src/context.rscrates/scim/src/discovery.rscrates/scim/src/error.rscrates/scim/src/groups/get.rscrates/scim/src/groups/mod.rscrates/scim/src/groups/patch.rscrates/scim/src/groups/set.rscrates/scim/src/lib.rscrates/scim/src/query/cursor.rscrates/scim/src/query/mod.rscrates/scim/src/request.rscrates/scim/src/users/get.rscrates/scim/src/users/mod.rscrates/scim/src/users/patch.rscrates/scim/src/users/set.rscrates/spam-filter/src/analysis/llm.rscrates/store/src/backend/composite/mod.rscrates/store/src/backend/composite/read_replica.rscrates/store/src/backend/composite/sharded_blob.rscrates/store/src/backend/composite/sharded_lookup.rscrates/trc/src/serializers/binary.rstests/src/directory/oidc.rstests/src/scim/auth.rstests/src/scim/bulk.rstests/src/scim/discovery.rstests/src/scim/groups.rstests/src/scim/limits.rstests/src/scim/mod.rstests/src/scim/query.rstests/src/scim/users.rstests/src/system/archiving.rstests/src/system/tenant.rs
Removed snippets
crates/common/src/auth/authentication.rs: 3crates/common/src/auth/mod.rs: 2crates/common/src/auth/permissions.rs: 1crates/common/src/cache/directory.rs: 6crates/common/src/cache/invalidate.rs: 1crates/common/src/cache/principals.rs: 2crates/common/src/cache/reload.rs: 1crates/common/src/config/mod.rs: 2crates/common/src/config/telemetry.rs: 4crates/common/src/lib.rs: 2crates/common/src/manager/boot.rs: 1crates/common/src/network/mta.rs: 1crates/common/src/scripts/plugins/llm_prompt.rs: 1crates/common/src/storage/quota.rs: 2crates/common/src/telemetry/metrics/mod.rs: 1crates/common/src/telemetry/metrics/prometheus.rs: 1crates/common/src/telemetry/mod.rs: 1crates/common/src/telemetry/tracers/mod.rs: 1crates/http/src/api/mod.rs: 4crates/http/src/auth/permissions.rs: 1crates/http/src/request.rs: 4crates/jmap/src/registry/get.rs: 1crates/jmap/src/registry/mapping/mod.rs: 1crates/jmap/src/registry/mapping/principal.rs: 3crates/jmap/src/registry/mapping/queued_message.rs: 1crates/jmap/src/registry/mapping/task.rs: 1crates/jmap/src/registry/mod.rs: 1crates/jmap/src/registry/query.rs: 1crates/jmap/src/registry/set.rs: 2crates/main/src/main.rs: 1crates/services/src/task_manager/alarm.rs: 1crates/services/src/task_manager/imip.rs: 1crates/services/src/task_manager/index.rs: 2crates/services/src/task_manager/maintenance.rs: 3crates/services/src/task_manager/scheduler.rs: 8crates/spam-filter/src/analysis/mod.rs: 1crates/spam-filter/src/analysis/score.rs: 2crates/store/src/backend/mod.rs: 1crates/store/src/backend/mysql/main.rs: 1crates/store/src/backend/postgres/main.rs: 1crates/store/src/build/blob.rs: 2crates/store/src/build/lookup.rs: 1crates/store/src/build/memory.rs: 2crates/store/src/dispatch/blob.rs: 6crates/store/src/dispatch/lookup.rs: 10crates/store/src/dispatch/mod.rs: 1crates/store/src/dispatch/search.rs: 6crates/store/src/dispatch/store.rs: 8crates/store/src/lib.rs: 6crates/trc/src/serializers/mod.rs: 1
Dangling module declarations removed
crates/common/src/telemetry/metrics/mod.rs:12:mod test_data(#[cfg(any(feature = "dev_mode", feature = "test_mode"))] / pub mod test_data;)tests/src/directory/mod.rs:11:mod oidc(pub mod oidc;)tests/src/lib.rs:27:mod scim(#[cfg(test)] / pub mod scim;)tests/src/system/mod.rs:8:mod archiving(pub mod archiving;)tests/src/system/mod.rs:19:mod tenant(pub mod tenant;)
Cargo edits
crates/main/Cargo.toml:50:default = ["rocks", "enterprise"]→default = ["rocks"]tests/Cargo.toml:22:store = { path = "../crates/store", features = ["test_mode", "enterprise"] }→store = { path = "../crates/store", features = ["test_mode"] }tests/Cargo.toml:24:directory = { path = "../crates/directory", features = ["test_mode", "enterprise"] }→directory = { path = "../crates/directory", features = ["test_mode"] }tests/Cargo.toml:25:coordinator = { path = "../crates/coordinator", features = ["test_mode", "enterprise"] }→coordinator = { path = "../crates/coordinator", features = ["test_mode"] }tests/Cargo.toml:26:jmap = { path = "../crates/jmap", features = ["test_mode", "enterprise"] }→jmap = { path = "../crates/jmap", features = ["test_mode"] }tests/Cargo.toml:35:http = { path = "../crates/http", features = ["test_mode", "enterprise"] }→http = { path = "../crates/http", features = ["test_mode"] }tests/Cargo.toml:37:scim = { path = "../crates/scim", features = ["test_mode", "enterprise"] }→scim = { path = "../crates/scim", features = ["test_mode"] }tests/Cargo.toml:39:services = { path = "../crates/services", features = ["test_mode", "enterprise"] }→services = { path = "../crates/services", features = ["test_mode"] }tests/Cargo.toml:41:smtp = { path = "../crates/smtp", features = ["test_mode", "enterprise"] }→smtp = { path = "../crates/smtp", features = ["test_mode"] }tests/Cargo.toml:42:common = { path = "../crates/common", features = ["test_mode", "enterprise"] }→common = { path = "../crates/common", features = ["test_mode"] }tests/Cargo.toml:44:email = { path = "../crates/email", features = ["test_mode", "enterprise"] }→email = { path = "../crates/email", features = ["test_mode"] }tests/Cargo.toml:45:spam-filter = { path = "../crates/spam-filter", features = ["test_mode", "enterprise"] }→spam-filter = { path = "../crates/spam-filter", features = ["test_mode"] }tests/Cargo.toml:46:trc = { path = "../crates/trc", features = ["enterprise"] }→trc = { path = "../crates/trc", features = [] }tests/Cargo.toml:47:managesieve = { path = "../crates/managesieve", features = ["test_mode", "enterprise"] }→managesieve = { path = "../crates/managesieve", features = ["test_mode"] }.github/workflows/ci.yml:341:cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise"→cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats".github/workflows/ci.yml:379:# cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "foundationdb s3 redis nats enterprise"→# cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "foundationdb s3 redis nats".github/workflows/ci.yml:386:cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise"→cargo build --release --target ${{matrix.target}} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats".github/workflows/ci.yml:442:cargo build --release -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise"→cargo build --release -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats"Dockerfile:22:RUN RUSTFLAGS="$(cat /flags.txt)" cargo chef cook --target "$(cat /target.txt)" --release --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise" --recipe-path /recipe.json→RUN RUSTFLAGS="$(cat /flags.txt)" cargo chef cook --target "$(cat /target.txt)" --release --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats" --recipe-path /recipe.jsonDockerfile:24:RUN RUSTFLAGS="$(cat /flags.txt)" cargo build --target "$(cat /target.txt)" --release -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise"→RUN RUSTFLAGS="$(cat /flags.txt)" cargo build --target "$(cat /target.txt)" --release -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats"Dockerfile.build:111:RUSTFLAGS="-L /usr/lib" cargo chef cook --recipe-path recipe.json --zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "foundationdb s3 redis nats enterprise"; \→RUSTFLAGS="-L /usr/lib" cargo chef cook --recipe-path recipe.json --zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "foundationdb s3 redis nats"; \Dockerfile.build:119:cargo chef cook --recipe-path recipe.json --zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise"→cargo chef cook --recipe-path recipe.json --zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats"Dockerfile.build:132:RUSTFLAGS="-L /usr/lib" cargo zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "foundationdb s3 redis nats enterprise" && \→RUSTFLAGS="-L /usr/lib" cargo zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "foundationdb s3 redis nats" && \Dockerfile.build:142:cargo zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats enterprise" && \→cargo zigbuild --release --target ${TARGET} -p stalwart --no-default-features --features "sqlite postgres mysql rocks s3 redis azure nats" && \Dockerfile.fdb:56:RUN cargo build -p stalwart --no-default-features --features "foundationdb s3 redis azure nats enterprise" --release→RUN cargo build -p stalwart --no-default-features --features "foundationdb s3 redis azure nats" --release
Flagged Enterprise in upstream's schema
Objects: x:AiModel, x:Alert, x:ArchivedItem, x:MaskedEmail, x:MetricsStore, x:SpamLlm, x:Tenant, x:Trace, x:TracingStore
Fields: x:AcmeProvider.memberTenantId, x:ArfExternalReport.memberTenantId, x:Authentication.defaultTenantRoleIds, x:CalendarAlarm.template, x:CalendarScheduling.emailTemplate, x:CalendarScheduling.httpRsvpTemplate, x:DataRetention.archiveDeletedAccountsFor, x:DataRetention.archiveDeletedItemsFor, x:DataRetention.holdMetricsFor, x:DataRetention.holdTracesFor, x:DataRetention.metricsCollectionInterval, x:Dkim1Signature.memberTenantId, x:Dkim2Signature.memberTenantId, x:DmarcExternalReport.memberTenantId, x:Domain.allowScimProvisioning, x:Domain.directoryId, x:Domain.logo, x:Domain.memberTenantId, x:Email.maxMaskedAddresses, x:Enterprise.logoUrl, x:GroupAccount.externalId, x:LdapDirectory.memberTenantId, x:MySqlStore.readReplicas, x:OidcDirectory.memberTenantId, x:PostgreSqlStore.readReplicas, x:Search.indexTelemetry, x:Search.indexTracingFields, x:SqlDirectory.memberTenantId, x:TlsExternalReport.memberTenantId, x:UserAccount.externalId
Third-party code
Comments in the stripped tree that name another copyright holder, another license, or a source the code came from. Files marked new aren't in THIRD-PARTY.md yet.
crates/common/src/network/acme/directory.rs- 7: Adapted from rustls-acme (https://github.com/FlorianUekermann/rustls-acme), licensed under MIT/Apache-2.0.
crates/common/src/network/acme/jose.rs- 7: Adapted from rustls-acme (https://github.com/FlorianUekermann/rustls-acme), licensed under MIT/Apache-2.0.
crates/common/src/network/acme/order.rs- 7: Adapted from rustls-acme (https://github.com/FlorianUekermann/rustls-acme), licensed under MIT/Apache-2.0.
crates/common/src/scripts/functions/text.rs- 239: MIT licensed.
- 241: Copyright (c) 2016 Titus Wormer [email protected]
crates/common/src/telemetry/tracers/journald.rs- 70: SPDX-FileCopyrightText: 2018 Benjamin Saunders [email protected]
- 71: SPDX-License-Identifier: MIT
crates/imap-proto/src/utf7.rscrates/jmap/src/registry/mapping/log.rs- 341: SPDX-FileCopyrightText: 2017 Michael Coyne [email protected]
- 343: SPDX-License-Identifier: MIT
- 346: Adapted from https://github.com/mjc-gh/rev_lines/blob/main/src/lib.rs
crates/jmap-proto/src/types/date.rscrates/nlp/src/tokenizers/japanese.rs- 73: Ported from https://github.com/woxtu/rust-tinysegmenter, MIT license
crates/nlp/src/tokenizers/types.rs- 738: Credits: test suite from linkify crate
crates/registry/src/types/datetime.rscrates/store/src/backend/postgres/tls.rs- 7: Credits: https://github.com/jbg/tokio-postgres-rustls
crates/types/src/id.rs- 69: From https://github.com/archer884/crockford by J/A [email protected]
- 70: License: MIT/Apache 2.0
crates/utils/src/glob.rs- 107: Credits: Algorithm ported from https://research.swtch.com/glob
Renamed identifiers
"URL to download spam filter rules from" → "URL to download spam filter rules from. Empty uses the rules bundled with the server.":resources/schema/schema.json.gz(1)"spamFilterRulesUrl":"https://github.com/stalwartlabs/spam-filter/releases/latest/download/spam-filter-rules.json.gz", →:resources/schema/schema.json.gz(1)"stalwart" → "inbuxa":resources/schema/schema.json.gz(15)"stalwart".to_string() → "inbuxa".to_string():crates/jmap/src/registry/mapping/bootstrap.rs(1),crates/registry/src/schema/structs_impl.rs(12)STALWART_SPAM_ → INBUXA_SPAM_:crates/common/src/manager/mod.rs(2)spam_filter_rules_url: Some("https://github.com/stalwartlabs/spam-filter/releases/latest/download/spam-filter-rules.json.gz".to_string()), → spam_filter_rules_url: None,:crates/registry/src/schema/structs_impl.rs(1)stalwart-webui → inbuxa-webui:crates/common/src/manager/application.rs(3)urn:stalwart: → urn:inbuxa::crates/dav/src/common/lock.rs(1),crates/dav/src/common/uri.rs(5),tests/src/webdav/lock.rs(2)urn:stalwart:jmap → urn:inbuxa:jmap:registry:crates/jmap-proto/src/request/capability.rs(3),tests/resources/scripts/stress_test_prepare.py(1),tests/src/jmap/principal/get.rs(2),tests/src/utils/jmap.rs(1)vnd.stalwart → vnd.inbuxa:resources/schema/schema.json.gz(2)vnd.stalwart. → vnd.inbuxa.:crates/registry/src/schema/enums_impl.rs(4),tests/resources/jmap/sieve/test_mailbox.sieve(1),tests/resources/smtp/sieve/awl.sieve(1),tests/resources/smtp/sieve/awl_include.sieve(1),tests/resources/smtp/sieve/stage_mail.sieve(1),tests/resources/smtp/sieve/stage_rcpt.sieve(1)
Build check
Errors mean shared code calls something the strip removed: usually a dual-licensed file that only serves an Enterprise feature. Drop or rework it in the merge into main, never on upstream.
- error
tests/src/directory/issuer.rs:8: unresolved importcrate::directory::oidc - error
tests/src/directory/issuer.rs:67: the size for values of typestrcannot be known at compilation time - error
tests/src/directory/issuer.rs:74: the size for values of typestrcannot be known at compilation time - unused
crates/common/src/cache/invalidate.rs:20: unused imports:registry::RegistryQueryandroaring::RoaringBitmap - unused
crates/common/src/cache/principals.rs:31: unused import:MaskedEmail - unused
crates/common/src/cache/principals.rs:41: unused import:now - unused
crates/common/src/network/mta.rs:27: unused import:structs::MaskedEmail - unused
crates/common/src/network/mta.rs:36: unused import:now - unused
crates/common/src/network/mta.rs:39: unused import:types::id::Id - unused
crates/common/src/scripts/plugins/llm_prompt.rs:7: unused import:compiler::Number - unused
crates/common/src/scripts/plugins/llm_prompt.rs:8: unused import:std::time::Instant - unused
crates/common/src/scripts/plugins/llm_prompt.rs:9: unused imports:AiEventandSecurityEvent - unused
crates/jmap/src/registry/mapping/principal.rs:24: unused imports:RegistryObjectCounterandRegistryQuery - unused
crates/jmap/src/registry/mapping/queued_message.rs:25: unused import:ObjectType - unused
crates/jmap/src/registry/mapping/queued_message.rs:43: unused import:RegistryQuery - unused
crates/services/src/task_manager/index.rs:14: unused imports:ObjectTypeandProperty - unused
crates/services/src/task_manager/index.rs:32: unused import:blob_hash::BlobHash
Expected: upstream's tests of features the fork rebuilt on main (tools/fork/build-check-known.txt).
tests/src/directory/mod.rs:19: cannot find module or crateoidcin this scopetests/src/smtp/inbound/antispam.rs:17: cannot findenterpriseincommontests/src/smtp/inbound/antispam.rs:49: unresolved importspam_filter::analysis::llmtests/src/smtp/inbound/antispam.rs:661: no method namedspam_filter_analyze_llmfound for reference&common::Serverin the current scopetests/src/system/mod.rs:63: cannot find module or cratetenantin this scopetests/src/system/mod.rs:70: cannot find module or cratearchivingin this scopetests/src/telemetry/alerts.rs:89: no method namedprocess_alertsfound for structcommon::Serverin the current scopetests/src/telemetry/metrics.rs:8: unresolved importcommon::telemetry::metrics::storetests/src/telemetry/metrics.rs:33: no method namedinsert_test_metricsfound for structcommon::Serverin the current scopetests/src/telemetry/metrics.rs:190: no method namedpurge_metricsfound for reference&store::Storein the current scopetests/src/telemetry/tracing.rs:8: unresolved importcommon::telemetry::tracers::storetests/src/telemetry/tracing.rs:35: no method namedpurge_spansfound for reference&store::Storein the current scopetests/src/telemetry/tracing.rs:89: no method namedpurge_spansfound for reference&store::Storein the current scopetests/src/telemetry/tracing.rs:152: no method namedpurge_spansfound for reference&store::Storein the current scopetests/src/telemetry/webhooks.rs:11: unresolved importcommon::telemetry::tracers::storetests/src/telemetry/webhooks.rs:123: no method namedpurge_spansfound for reference&store::Storein the current scope
Problems
- tests/src/directory/issuer.rs:8: does not compile: unresolved import
crate::directory::oidc - tests/src/directory/issuer.rs:67: does not compile: the size for values of type
strcannot be known at compilation time - tests/src/directory/issuer.rs:74: does not compile: the size for values of type
strcannot be known at compilation time