Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7bebd454d | ||
|
|
282ad5fc13 | ||
|
|
133d41df36 | ||
|
|
c4a6e4d117 | ||
|
|
f59a9de4dc | ||
|
|
083f22d6fb |
No files matched your search
+1
-1
@@ -36,7 +36,7 @@ to Stalwart Labs with credit to you, and you'll be told that has happened.
|
||||
This repository is the mail server. The web front ends have their own:
|
||||
|
||||
- [inbuxa-admin](https://git.coffeylabs.org/inbuxa/inbuxa-admin)
|
||||
- [ihasmail-inbuxa](https://git.coffeylabs.org/inbuxa/ihasmail-inbuxa)
|
||||
- [inbuxa-webmail](https://git.coffeylabs.org/inbuxa/inbuxa-webmail)
|
||||
|
||||
Upstream's own security documents are kept in `.github-upstream/` for
|
||||
reference. They describe Stalwart Labs' process, not this project's.
|
||||
@@ -14,7 +14,7 @@
|
||||
//! application names another;
|
||||
//! - INBUXA Admin hosted elsewhere, as `inbuxa-admin`, when `INBUXA_ADMIN_URL`
|
||||
//! is set;
|
||||
//! - ihasmail-inbuxa, as the confidential client `ihasmail-inbuxa`, when
|
||||
//! - inbuxa-webmail, as the confidential client `ihasmail-inbuxa`, when
|
||||
//! `INBUXA_WEBMAIL_URL` and `INBUXA_WEBMAIL_CLIENT_SECRET` are set.
|
||||
//!
|
||||
//! inbuxa: the environment variables stand in for `x:FrontEnds` (C-4) until
|
||||
@@ -22,7 +22,7 @@
|
||||
//! it instead.
|
||||
//!
|
||||
//! A missing client is created. An existing one gains any redirect URI it
|
||||
//! lacks and, for ihasmail-inbuxa, the configured secret; nothing an operator
|
||||
//! lacks and, for inbuxa-webmail, the configured secret; nothing an operator
|
||||
//! added is removed.
|
||||
|
||||
use directory::core::secret::{hash_secret, verify_secret_hash};
|
||||
|
||||
@@ -176,16 +176,23 @@ impl TlsaLookup for Server {
|
||||
return mail_auth::common::resolver::mock_resolve(key.as_ref());
|
||||
}
|
||||
|
||||
let tlsa_lookup = match self
|
||||
.core
|
||||
.smtp
|
||||
.resolvers
|
||||
.dnssec
|
||||
.resolver
|
||||
.tlsa_lookup(Name::from_str_relaxed(key.as_ref())?)
|
||||
// Through `validated_lookup`, like the MX and address lookups: a TLSA
|
||||
// name that is a signed CNAME to a name with no TLSA record (seen at
|
||||
// `_25._tcp.mail.usefulinsight.com`, behind Hetzner's resolvers) is
|
||||
// otherwise called bogus, and the message waits on it until it
|
||||
// expires.
|
||||
let tlsa_lookup = match validated_lookup(
|
||||
&self.core.smtp.resolvers.dnssec.resolver,
|
||||
self.core.smtp.resolvers.dns.resolver(),
|
||||
Name::from_str_relaxed(key.as_ref())?,
|
||||
RecordType::TLSA,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(tlsa_lookup) => tlsa_lookup,
|
||||
// A TLSA record proved to sit in an unsigned zone is no DANE
|
||||
// policy at all.
|
||||
Ok(validated) if validated.insecure => return Ok(TlsaResult::Missing),
|
||||
Ok(validated) => validated.lookup,
|
||||
Err(err) => {
|
||||
if let Some(denial) = NegativeAnswer::from_error(&err) {
|
||||
return Ok(if denial.dnssec_status == DnssecStatus::Bogus {
|
||||
@@ -436,7 +443,8 @@ impl TlsaLookup for Server {
|
||||
// record in the DS reply, and public resolvers often send none.
|
||||
// - A signed CNAME to a signed name without the record type queried. Hickory
|
||||
// checks the denial of existence against the name first asked for, not the
|
||||
// target's, and rejects it.
|
||||
// target's, and rejects it. TLSA lookups hit this too: a TLSA name that is
|
||||
// a CNAME to the zone apex, with no TLSA there, held mail to it for a week.
|
||||
//
|
||||
// When hickory says bogus, check the answer again with lookups it gets right.
|
||||
// A signed CNAME is followed and the lookup repeated at its target. Otherwise
|
||||
@@ -869,4 +877,56 @@ mod tests {
|
||||
assert!(validated.insecure);
|
||||
assert!(!validated.lookup.answers().is_empty());
|
||||
}
|
||||
|
||||
// Needs the network: a TLSA name that is a signed CNAME to the zone apex,
|
||||
// which has no TLSA record. Cloudflare's resolver answers with a compact
|
||||
// denial at the name itself; Hetzner's (and others) follow the CNAME, and
|
||||
// hickory then calls the answer bogus. Point the lookup at a resolver that
|
||||
// follows it with INBUXA_TEST_DNS_TCP=<ip:port> (TCP), for instance over
|
||||
// an SSH tunnel to 185.12.64.2:53 from a Hetzner host.
|
||||
#[tokio::test]
|
||||
#[ignore]
|
||||
async fn validated_lookup_follows_signed_cname_for_tlsa() {
|
||||
use mail_auth::hickory_resolver::{
|
||||
config::{CLOUDFLARE, ConnectionConfig, NameServerConfig, ResolverConfig, ResolverOpts},
|
||||
net::runtime::TokioRuntimeProvider,
|
||||
};
|
||||
|
||||
let config = match std::env::var("INBUXA_TEST_DNS_TCP") {
|
||||
Ok(addr) => {
|
||||
let addr: std::net::SocketAddr = addr.parse().unwrap();
|
||||
let mut ns = NameServerConfig::new(addr.ip(), true, vec![ConnectionConfig::tcp()]);
|
||||
if let Some(c) = ns.connections.first_mut() {
|
||||
c.port = addr.port();
|
||||
}
|
||||
ResolverConfig::from_parts(None, vec![], vec![ns])
|
||||
}
|
||||
Err(_) => ResolverConfig::udp_and_tcp(&CLOUDFLARE),
|
||||
};
|
||||
let build = |validate: bool| {
|
||||
let mut opts = ResolverOpts::default();
|
||||
opts.validate = validate;
|
||||
opts.num_concurrent_reqs = 1;
|
||||
opts.cache_size = 0;
|
||||
TokioResolver::builder_with_config(config.clone(), TokioRuntimeProvider::default())
|
||||
.with_options(opts)
|
||||
.build()
|
||||
.unwrap()
|
||||
};
|
||||
let (dnssec, plain) = (build(true), build(false));
|
||||
let query = name("_25._tcp.mail.usefulinsight.com.");
|
||||
|
||||
let direct = dnssec.lookup(query.clone(), RecordType::TLSA).await;
|
||||
eprintln!("hickory alone: {:?}", direct.as_ref().err().map(|e| e.to_string()));
|
||||
|
||||
let err = match validated_lookup(&dnssec, &plain, query, RecordType::TLSA).await {
|
||||
Ok(validated) => panic!("expected no TLSA record, got {:?}", validated.lookup.answers()),
|
||||
Err(err) => err,
|
||||
};
|
||||
let denial = NegativeAnswer::from_error(&err).expect("a denial of existence");
|
||||
assert_eq!(denial.response_code, ResponseCode::NoError);
|
||||
assert_ne!(denial.dnssec_status, DnssecStatus::Bogus);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ fn legacy_setting(name: &str, is_set: impl Fn(&str) -> bool) -> Option<String> {
|
||||
#[macro_export]
|
||||
macro_rules! brand_version {
|
||||
() => {
|
||||
"2026.9.30.2"
|
||||
"2026.10.5"
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -618,7 +618,7 @@ the tenant administrators' own view is not yet recorded
|
||||
|
||||
## 8. Open decisions
|
||||
|
||||
- The INBUXA fork of ihasmail is **ihasmail-inbuxa** (named 2026-09-18). Open: its repository, and how it tracks
|
||||
- The INBUXA fork of ihasmail is **inbuxa-webmail** (named ihasmail-inbuxa on 2026-09-18, renamed 2026-10-05). Open: how it tracks
|
||||
public ihasmail (§5).
|
||||
- Product name: whether the shipped product is called inbuxa-server or
|
||||
something else inside the INBUXA brand.
|
||||
|
||||
+19
-19
@@ -7,11 +7,11 @@ Status: draft, 2026-09-18. Expands SPEC.md §5.2.
|
||||
| Party | What it is | How it reaches the server |
|
||||
|---|---|---|
|
||||
| **inbuxa-server** | The mail server | — |
|
||||
| **ihasmail-inbuxa** | The INBUXA fork of ihasmail: a Node server and a web app. Public ihasmail stays Stalwart-facing and isn't party to this (SPEC.md §5) | Its **Node server** calls inbuxa-server, server to server. The browser only ever talks to ihasmail-inbuxa |
|
||||
| **inbuxa-webmail** | The INBUXA fork of ihasmail: a Node server and a web app. Public ihasmail stays Stalwart-facing and isn't party to this (SPEC.md §5) | Its **Node server** calls inbuxa-server, server to server. The browser only ever talks to inbuxa-webmail |
|
||||
| **INBUXA Admin** (`inbuxa-admin`) | A static web app, a fork of Stalwart WebUI | The **browser** calls inbuxa-server directly, cross-origin |
|
||||
|
||||
That split decides most of what follows. Cross-origin rules matter only for
|
||||
INBUXA Admin. Token custody matters most for ihasmail-inbuxa, which holds
|
||||
INBUXA Admin. Token custody matters most for inbuxa-webmail, which holds
|
||||
tokens on its server for people who aren't there.
|
||||
|
||||
## What upstream does today
|
||||
@@ -45,7 +45,7 @@ Observed in the source at `v0.16.22` and against a running inbuxa-server on
|
||||
- **Endpoint gating:** `x:Http.allowedEndpoints` is an expression that can
|
||||
refuse endpoints by path and client IP. JMAP administration shares `/jmap`
|
||||
with everything else, so it can't separate admin calls on its own.
|
||||
- **ihasmail today** (public, and so the starting point for ihasmail-inbuxa)
|
||||
- **ihasmail today** (public, and so the starting point for inbuxa-webmail)
|
||||
signs in with HTTP Basic auth and keeps the password sealed in its session
|
||||
store (`sealedCredentials: {username, password}`), sending it on every
|
||||
upstream call. It registers JMAP push subscriptions to its own URL, and reads
|
||||
@@ -76,7 +76,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
(LP-19). Added 2026-09-21.
|
||||
- **C-2.** Each front end states the contract versions it supports and checks
|
||||
`contract` after signing in. Outside its range it stops, with a message
|
||||
naming both versions. For ihasmail-inbuxa this replaces public ihasmail's
|
||||
naming both versions. For inbuxa-webmail this replaces public ihasmail's
|
||||
"Stalwart 0.16 or later" check.
|
||||
- **C-3.** A breaking change to anything in this document bumps `contract`.
|
||||
Adding optional fields doesn't.
|
||||
@@ -117,7 +117,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
- **`inbuxa-admin`**: a public client (no secret), authorization code with
|
||||
PKCE S256, redirect URI `{adminUrl}/oauth/callback`.
|
||||
- **`ihasmail-inbuxa`**: a confidential client with a secret held by the
|
||||
ihasmail-inbuxa server, authorization code with PKCE S256, redirect URI
|
||||
inbuxa-webmail server, authorization code with PKCE S256, redirect URI
|
||||
`{webmailUrl}/api/auth/callback`.
|
||||
INBUXA Admin's `<meta name="oauth-client-id">` is set to `inbuxa-admin`.
|
||||
Served by the server itself it uses the web interface's client,
|
||||
@@ -159,7 +159,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
- **C-8.** People sign in on **the server's own sign-in page** (`/login`,
|
||||
already INBUXA-branded), never on a front end's form. Two-factor happens
|
||||
there, on the page's existing one-time-code step. Front ends never see a
|
||||
password. ihasmail-inbuxa's own sign-in form is retired in favor of a
|
||||
password. inbuxa-webmail's own sign-in form is retired in favor of a
|
||||
redirect.
|
||||
- **C-9.** **Consent for anything that isn't first-party.** When a client other
|
||||
than the two first-party ones asks to sign someone in, the sign-in page names
|
||||
@@ -170,10 +170,10 @@ Each has an ID, and tests name the IDs they check.
|
||||
|
||||
### Tokens
|
||||
|
||||
- **C-10.** ihasmail-inbuxa holds tokens, never passwords. It keeps the access
|
||||
- **C-10.** inbuxa-webmail holds tokens, never passwords. It keeps the access
|
||||
and refresh token for each session sealed in its session store, where it now
|
||||
keeps sealed credentials, and refreshes the access token before it expires.
|
||||
The browser still holds only ihasmail-inbuxa's own session cookie. Public
|
||||
The browser still holds only inbuxa-webmail's own session cookie. Public
|
||||
ihasmail's "the browser never holds a credential" property is kept.
|
||||
- **C-11.** INBUXA Admin holds its tokens in the browser, as upstream WebUI
|
||||
does, since it has no server of its own. So admin tokens are short-lived
|
||||
@@ -193,9 +193,9 @@ Each has an ID, and tests name the IDs they check.
|
||||
A revoked token stops working on its next use, and never later than one
|
||||
access-token lifetime.
|
||||
- **C-13.** Grants are listed per account (client, device description, created,
|
||||
last used, IP), so ihasmail-inbuxa's "your sessions" screen shows server-side
|
||||
last used, IP), so inbuxa-webmail's "your sessions" screen shows server-side
|
||||
truth. Lifetimes, all configurable: access tokens 1 hour and refresh 30 days
|
||||
for ihasmail-inbuxa; access tokens 15 minutes and refresh 8 hours for
|
||||
for inbuxa-webmail; access tokens 15 minutes and refresh 8 hours for
|
||||
`inbuxa-admin`.
|
||||
|
||||
### Cross-origin
|
||||
@@ -237,7 +237,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
scope `inbuxa:admin`, which only that client is ever granted. An admin
|
||||
account signing in through a mail client can't administer the server with
|
||||
that token, even though the account could.
|
||||
- **C-19.** ihasmail-inbuxa's own administration (accounts, domains, groups,
|
||||
- **C-19.** inbuxa-webmail's own administration (accounts, domains, groups,
|
||||
lists, roles, tenants, the dashboard) uses the scope `inbuxa:account-admin`,
|
||||
granted only to `ihasmail-inbuxa`, and limited to those object types, plus
|
||||
`x:Metric` get and query for the dashboard's message cards (monitoring
|
||||
@@ -250,7 +250,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
|
||||
### Push
|
||||
|
||||
- **C-22.** Unchanged from public ihasmail: ihasmail-inbuxa registers JMAP push
|
||||
- **C-22.** Unchanged from public ihasmail: inbuxa-webmail registers JMAP push
|
||||
subscriptions to its own URL, with VAPID for browser notifications. The only
|
||||
difference is that it authenticates with its token rather than the password.
|
||||
|
||||
@@ -279,7 +279,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
`INBUXA_HTTP_BASIC_AUTH=all`; `dav`, the default, is this rule. Any other
|
||||
value logs a warning and keeps the default. The setting moves to the
|
||||
registry with `x:FrontEnds` (C-4).
|
||||
ihasmail-inbuxa confirms a typed password, which it does before creating
|
||||
inbuxa-webmail confirms a typed password, which it does before creating
|
||||
an app password, on `/api/auth` as its own client, to its registered
|
||||
redirect URI, with a PKCE challenge whose verifier it discards. A
|
||||
"two-factor code needed" answer counts as confirmed, since the server gives
|
||||
@@ -294,7 +294,7 @@ Each has an ID, and tests name the IDs they check.
|
||||
didn't register refused.
|
||||
Observed before the change, in INBUXA's production logs from 2026-09-20 to 2026-09-29:
|
||||
every HTTPS password sign-in was the operator's own, apart from
|
||||
ihasmail-inbuxa's password sign-in on 2026-09-22, before it moved to OAuth.
|
||||
inbuxa-webmail's password sign-in on 2026-09-22, before it moved to OAuth.
|
||||
The logs don't say whether a sign-in used a Basic header or the sign-in
|
||||
page.
|
||||
|
||||
@@ -304,8 +304,8 @@ Each has an ID, and tests name the IDs they check.
|
||||
(SPEC.md §6.2). In bootstrap mode, CORS is permissive (C-16) and the
|
||||
recovery administrator applies.
|
||||
2. It sets `x:FrontEnds` (webmail and admin URLs, the public URL), which
|
||||
registers both first-party clients (C-6). For ihasmail-inbuxa it returns the
|
||||
client secret once, for the installer to write into ihasmail-inbuxa's
|
||||
registers both first-party clients (C-6). For inbuxa-webmail it returns the
|
||||
client secret once, for the installer to write into inbuxa-webmail's
|
||||
environment.
|
||||
3. After the restart out of bootstrap, CORS follows C-14, registration is
|
||||
required (C-5), and the recovery administrator is ignored (SPEC.md §6.2).
|
||||
@@ -376,7 +376,7 @@ client and reload settings. This is the state C-5 and C-6 make the default.
|
||||
5. The phishing flow in the security note fails at step 1, and a registered
|
||||
third-party client with a non-first-party redirect shows the consent page
|
||||
(C-9).
|
||||
6. ihasmail-inbuxa signs in without ever handling a password. Its session
|
||||
6. inbuxa-webmail signs in without ever handling a password. Its session
|
||||
store holds tokens only (C-8, C-10).
|
||||
7. Revoking one grant stops that session within one access-token lifetime,
|
||||
leaves others working, and "sign out other sessions" keeps the current one
|
||||
@@ -388,7 +388,7 @@ client and reload settings. This is the state C-5 and C-6 make the default.
|
||||
10. In bootstrap mode, INBUXA Admin reaches the server from any origin (C-16).
|
||||
11. An admin account's token from a third-party mail client can't read
|
||||
`x:NetworkListener`. The same account through `inbuxa-admin` can (C-18).
|
||||
12. ihasmail-inbuxa's token can manage accounts and tenants but not listeners
|
||||
12. inbuxa-webmail's token can manage accounts and tenants but not listeners
|
||||
or certificates (C-19).
|
||||
13. With `adminNetworks` set, an `inbuxa:admin` request from outside is refused
|
||||
(C-20).
|
||||
@@ -402,4 +402,4 @@ client and reload settings. This is the state C-5 and C-6 make the default.
|
||||
2. The consent page's wording and whether it remembers a decision per client.
|
||||
3. API keys and app passwords with explicit scopes (C-21): what upstream's
|
||||
`x:ApiKey` already supports, to observe before specifying.
|
||||
4. Whether ihasmail-inbuxa's secret should rotate, and how.
|
||||
4. Whether inbuxa-webmail's secret should rotate, and how.
|
||||
@@ -584,7 +584,7 @@ Three consequences:
|
||||
name whose DNS points at the mail addresses.
|
||||
- Whether the front ends need anything at cutover, or follow separately
|
||||
(SPEC.md §5). The rehearsal does not start them.
|
||||
- Whether ihasmail-inbuxa and INBUXA Admin behave under real use, rather
|
||||
- Whether inbuxa-webmail and INBUXA Admin behave under real use, rather
|
||||
than at first sign-in. Both were verified as far as signing in and, for the
|
||||
webmail, mail flowing.
|
||||
- The checks only users can make: the second account, the mailbox comparison
|
||||
|
||||
@@ -353,7 +353,7 @@ adds at most 2.
|
||||
|
||||
## ihasmail changes
|
||||
|
||||
These go in the INBUXA fork of ihasmail, ihasmail-inbuxa, never in public
|
||||
These go in the INBUXA fork of ihasmail, inbuxa-webmail, never in public
|
||||
ihasmail, which stays Stalwart-facing (SPEC.md §5).
|
||||
|
||||
- **Reading:** when a message has an `X-Spam-LLM` header, the message details
|
||||
|
||||
@@ -275,7 +275,7 @@ Each requirement has an ID, and tests name the IDs they check.
|
||||
|
||||
## ihasmail changes
|
||||
|
||||
These go in the INBUXA fork of ihasmail, ihasmail-inbuxa, never in public
|
||||
These go in the INBUXA fork of ihasmail, inbuxa-webmail, never in public
|
||||
ihasmail, which stays Stalwart-facing (SPEC.md §5).
|
||||
|
||||
- **Administration, Domains:** a logo field on each domain. Upload a PNG, JPEG
|
||||
@@ -389,7 +389,7 @@ files carry hooks marked `inbuxa:`. Acceptance tests 1 to 17 pass as
|
||||
`tests/src/system/branding.rs`.
|
||||
|
||||
- **BT-1 to BT-26:** built.
|
||||
- **ihasmail changes** belong to ihasmail-inbuxa and aren't part of this
|
||||
- **ihasmail changes** belong to inbuxa-webmail and aren't part of this
|
||||
repository.
|
||||
- **Test 18 (compat)** is written as `branding_compat`, ignored, and unrun
|
||||
until a copy of INBUXA's data is provided. INBUXA holds no logos or
|
||||
|
||||
@@ -14,7 +14,7 @@ Written for the record SPEC.md §3 rule 3 asks for. Sources, and nothing else:
|
||||
|---|---|---|
|
||||
| This repository at `0502eb4` (2026-09-28): `crates/smtp/src/inbound/data.rs`, `crates/smtp/src/queue/`, `crates/jmap/src/submission/set.rs`, `crates/common/src/scripts/`, `vendor/sieve-rs`, `resources/schema/schema.json.gz` | AGPL-3.0-only | Where a check can run, what the queue stores, what a sender sees on a refusal |
|
||||
| inbuxa-admin at `b82904c` | AGPL-3.0-only | Where the pages go |
|
||||
| ihasmail-inbuxa (the webmail) at `290bc63` | AGPL-3.0-or-later | How a refused send reaches the person sending |
|
||||
| inbuxa-webmail (the webmail) at `290bc63` | AGPL-3.0-or-later | How a refused send reaches the person sending |
|
||||
| `inbuxa-drafts/queue/dlp.md`, `rule-builder.md` | Own | What John asked for and settled |
|
||||
| The personal-data catalog spec and the audit-hold-lock spec | Own | Roles, the audit log, legal holds, the catalog check |
|
||||
| RFC 5321, RFC 3463 (enhanced status codes), RFC 8620/8621 (JMAP) | Public | Refusal codes and the submission error shape |
|
||||
@@ -385,7 +385,7 @@ first). The inspection limit caps the worst case.
|
||||
Every form previews the rule in words ("If a recipient is outside and the
|
||||
message contains 5 or more card numbers, hold it for review").
|
||||
|
||||
## 4. Webmail (ihasmail-inbuxa)
|
||||
## 4. Webmail (inbuxa-webmail)
|
||||
|
||||
- A warning dialog: the notice, a reason field, **Send anyway** and **Edit
|
||||
message**.
|
||||
|
||||
@@ -291,7 +291,7 @@ upstream files carry hooks marked `inbuxa:`. Acceptance tests 1 to 11 pass as
|
||||
`createdBy`. The server-set name is **deferred** until sign-in goes through
|
||||
OAuth (contract C-8): with Basic auth there's no client name, so a mask
|
||||
created through the Fastmail API has none.
|
||||
- **ihasmail changes** belong to ihasmail-inbuxa and aren't part of this
|
||||
- **ihasmail changes** belong to inbuxa-webmail and aren't part of this
|
||||
repository.
|
||||
- **Test 12 (compat)** is written as `masked_email_compat`, ignored, and unrun
|
||||
until a copy of INBUXA's data with masks made on it is provided. Its doc
|
||||
|
||||
@@ -411,7 +411,7 @@ unchanged.
|
||||
|
||||
## ihasmail changes
|
||||
|
||||
These go in ihasmail-inbuxa, not public ihasmail, which stays Stalwart-facing
|
||||
These go in inbuxa-webmail, not public ihasmail, which stays Stalwart-facing
|
||||
(SPEC.md §5).
|
||||
|
||||
- The dashboard already reads `x:Metric` for received, sent and memory. Keep
|
||||
|
||||
@@ -336,9 +336,9 @@ called from `system_tests` with no gate.
|
||||
- **MT-1 to MT-18, MT-20 to MT-23:** built.
|
||||
- **MT-19, MT-19a:** built, except the submission-time warning, **deferred**
|
||||
(see MT-19a) until the contract defines a warnings shape.
|
||||
- **ihasmail changes** (the section above) belong to ihasmail-inbuxa and
|
||||
- **ihasmail changes** (the section above) belong to inbuxa-webmail and
|
||||
aren't part of this repository. Its branding and quota warnings wait for
|
||||
ihasmail-inbuxa.
|
||||
inbuxa-webmail.
|
||||
- **Test 15 (compat)** is written as `tenant_compat`, ignored, and unrun until
|
||||
a copy of INBUXA's data is provided. Its doc comment says how to run it.
|
||||
- **Known limits, not requirements of this spec:**
|
||||
|
||||
@@ -412,7 +412,7 @@ check it and the fork keeps it.
|
||||
|
||||
## ihasmail changes
|
||||
|
||||
These go in ihasmail-inbuxa, the INBUXA fork of ihasmail, never in public
|
||||
These go in inbuxa-webmail, the INBUXA fork of ihasmail, never in public
|
||||
ihasmail, which stays Stalwart-facing (SPEC.md §5).
|
||||
|
||||
- **Domain editor:** a directory picker offering "server default" and the
|
||||
|
||||
@@ -679,7 +679,7 @@ SCIM error documents (RFC 7644 §3.12): `schemas`
|
||||
|
||||
## ihasmail changes
|
||||
|
||||
These go in ihasmail-inbuxa, not public ihasmail, which stays
|
||||
These go in inbuxa-webmail, not public ihasmail, which stays
|
||||
Stalwart-facing (SPEC.md §5).
|
||||
|
||||
- **Domains:** an "Allow SCIM provisioning" switch on the domain form. Turning
|
||||
|
||||
@@ -276,7 +276,7 @@ marked `inbuxa:`. Acceptance tests 1 to 15 pass as
|
||||
`tests/src/system/undelete.rs`, with `/changes` and the `/query` filters.
|
||||
|
||||
- **UD-1 to UD-17a:** built.
|
||||
- **ihasmail changes** belong to ihasmail-inbuxa and aren't part of this
|
||||
- **ihasmail changes** belong to inbuxa-webmail and aren't part of this
|
||||
repository.
|
||||
- **Test 16 (compat)** is written as `undelete_compat`, ignored, and unrun
|
||||
until a copy of INBUXA's data with archived items made on it is provided.
|
||||
|
||||
@@ -103,7 +103,7 @@ conflicts.
|
||||
|
||||
1. Every requirement MT-1 to MT-23 is implemented, or deliberately deferred
|
||||
with a line in the spec saying so. The branding and quota warnings for
|
||||
ihasmail can wait for ihasmail-inbuxa.
|
||||
ihasmail can wait for inbuxa-webmail.
|
||||
2. Acceptance tests 1 to 14 pass as integration tests
|
||||
(`tests/src/system/tenant.rs`), with the `pending-rebuild` gate removed
|
||||
from the tenant call.
|
||||
|
||||
@@ -12,7 +12,7 @@ Boots the debug binary and checks that:
|
||||
- DAV still takes Basic, and its 401 still offers it;
|
||||
- a token from the sign-in endpoint (`/api/auth`, the password in the body)
|
||||
and the token endpoint works on JMAP: the path the front ends use, and the
|
||||
one ihasmail-inbuxa's password check relies on;
|
||||
one inbuxa-webmail's password check relies on;
|
||||
- INBUXA_HTTP_BASIC_AUTH=all puts Basic back everywhere, an unknown value
|
||||
keeps the default with a warning, and recovery mode accepts Basic.
|
||||
|
||||
@@ -64,7 +64,7 @@ def start(env=None):
|
||||
"-p", f"127.0.0.1:{PORT}:8080",
|
||||
# A debug build's workers need more than the default stack.
|
||||
"-e", "RUST_MIN_STACK=16777216",
|
||||
# Registers inbuxa-admin and ihasmail-inbuxa (C-6).
|
||||
# Registers inbuxa-admin and inbuxa-webmail (C-6).
|
||||
"-e", f"INBUXA_ADMIN_URL={ADMIN_URL}", "-e", f"INBUXA_WEBMAIL_URL={WEBMAIL_URL}"]
|
||||
env_file = f"{DIR}/secrets/basic-env"
|
||||
with open(env_file, "w") as f:
|
||||
@@ -243,7 +243,7 @@ def main():
|
||||
status, _, _ = request("/api/account", f"Bearer {access}")
|
||||
check(status == 200, f"a token works on /api/account ({status})")
|
||||
|
||||
# ihasmail-inbuxa's password check before an app password: its own client,
|
||||
# inbuxa-webmail's password check before an app password: its own client,
|
||||
# its registered redirect URI, a verifier it throws away.
|
||||
for password, want in ((user_pw, "authenticated"), ("not-the-password", "failure")):
|
||||
got = sign_in(user, password, "ihasmail-inbuxa", WEBMAIL_REDIRECT, secrets.token_urlsafe(48))
|
||||
|
||||
Reference in new issue
Block a user