Feature specs 4-9: observations from INBUXA's live server
This commit is contained in:
@@ -460,3 +460,25 @@ Not for observation, but open:
|
||||
schema. A later addition in the fork's namespace if asked for.
|
||||
9. A "test this model" action for INBUXA Admin. Useful, not required.
|
||||
10. The name of the fork's limits singleton, with the namespace (SPEC.md §8).
|
||||
|
||||
## Observed
|
||||
|
||||
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart
|
||||
0.16.22), read-only, as a server-level administrator and the throwaway test
|
||||
account. No upstream code was read.
|
||||
|
||||
1. **Configured models** (open question 1). No `x:AiModel` exists and
|
||||
`x:SpamLlm` is `Disable`. Compat test 22 carries only the tags below.
|
||||
2. **`LLM_*` tags** (open question 2). Twelve entries, all `Score`, for every
|
||||
category and confidence: `HIGH` 3.0, `MEDIUM` 2.0, `LOW` 0.5 for
|
||||
`UNSOLICITED`, `COMMERCIAL` and `HARMFUL`, and −3.0, −2.0, −0.5 for
|
||||
`LEGITIMATE`. AI-13's clamp (+5.0, −1.0) cuts only the `LEGITIMATE`
|
||||
`HIGH` and `MEDIUM` scores.
|
||||
3. **`X-Spam-LLM`** (open question 3). Not observable: the classifier has
|
||||
never run on INBUXA.
|
||||
4. **`interactAi`** (open question 5). Ordinary accounts hold it: the test
|
||||
account's effective permissions include it, through the default `User`
|
||||
role. This repository's defaults match what upstream ships. The public
|
||||
permissions table is out of date.
|
||||
|
||||
Questions 4, 6 and 7 need a model configured, so they stay open.
|
||||
|
||||
@@ -378,3 +378,41 @@ the operator's approval first, as with the other features' probes.
|
||||
8. **INBUXA Admin's logo.** Upstream documents that its web interface picks its
|
||||
logo by request hostname. Check in `inbuxa-admin` (an ordinary AGPL fork,
|
||||
SPEC.md §5) whether it calls `/logo`, so it keeps working against BT-5.
|
||||
|
||||
## Observed
|
||||
|
||||
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart
|
||||
0.16.22), read-only, as a server-level administrator and the throwaway test
|
||||
account. No upstream code was read.
|
||||
|
||||
1. **What INBUXA holds** (open question 1). `x:Enterprise.logoUrl`, all three
|
||||
templates and every tenant logo are null. Six of nine domains had a logo:
|
||||
four held the same `https:` URL, pointing at a retired website that now
|
||||
answers with an HTML page, and two held the literal string `admin`. With
|
||||
the operator's approval, the four URL logos were removed the same day (a
|
||||
write). The two `admin` values remain. BT-4 skips them as unusable, and
|
||||
upstream already answers `404` for those domains.
|
||||
2. **Upstream fetches URL logos itself** (open questions 2 and 3). While the
|
||||
URL logos were set, `GET /logo` returned `200 text/html`: the retired
|
||||
site's page, served from the mail server's own origin with no
|
||||
`X-Content-Type-Options` and no CSP. So upstream fetches the URL on the
|
||||
server side and passes on whatever comes back, content type included.
|
||||
BT-7 (never fetch) and BT-8 (sandbox what is served) are deliberate
|
||||
differences, and this is why.
|
||||
3. **`/logo` shape.** `/logo` with no parameter used the request's host, and
|
||||
`?domain=` selected a domain. `/logo/<domain>` answered the same as
|
||||
`/logo`, so the path segment is ignored. An unknown domain, a domain with
|
||||
an unusable value, and (after the removal) every domain answered `404`
|
||||
with `application/problem+json`. No caching headers were sent. BT-5 keeps
|
||||
`/logo?domain=` and `404`, and adds its own headers.
|
||||
4. **Reload** (open question 4). Removing the logos took effect on the very
|
||||
next `/logo` request, with no settings reload.
|
||||
5. **RSVP page headers** (open question 6). `GET /calendar/rsvp` sends only
|
||||
`Content-Type: text/html; charset=utf-8` and
|
||||
`Cache-Control: no-store, no-cache, must-revalidate`: no CSP and no
|
||||
`Referrer-Policy`. BT-21's headers are a difference.
|
||||
6. **The stored `fromName`** (open question 7). INBUXA stores
|
||||
`INBUXA Calendar` as a value already. Nothing to change at cutover.
|
||||
|
||||
Not settled: open question 5 (invalid templates on write) needs a write, and
|
||||
question 8 is a check in `inbuxa-admin`, not on the server.
|
||||
|
||||
@@ -508,3 +508,55 @@ these needs a write.
|
||||
`sysMetric*` or live permission, and whether a tenant view of its own
|
||||
domains' traces is wanted (MON-31).
|
||||
12. Size of INBUXA's `o` and `x` subspaces, to check MON-19's estimate.
|
||||
|
||||
## Observed
|
||||
|
||||
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart
|
||||
0.16.22), read-only, as a server-level administrator and the throwaway test
|
||||
account. No upstream code was read.
|
||||
|
||||
1. **Settings** (open question 6). `holdTracesFor` 30 days, `holdMetricsFor`
|
||||
90 days, `metricsCollectionInterval` hourly at minute 0, `indexTelemetry`
|
||||
on with `eventType`, `queueId` and `keywords` indexed. Tracing and metrics
|
||||
stores are both `Default`. No `x:Alert` exists (open question 10).
|
||||
2. **Traces** (open questions 1 to 3). 395 stored, the oldest exactly one day
|
||||
old, although retention is 30 days. Why is unexplained: the history may
|
||||
have been cleared a day earlier. Worth checking before cutover, since
|
||||
metrics go back 24 days. Each trace is one message's journey: 4 to 44
|
||||
events (10 on average), mostly delivery, queue, SMTP and authentication
|
||||
results. Every stored inbound SMTP session reached `MAIL FROM` (82 of 82),
|
||||
so connection-only sessions aren't stored, which matches MON-11. Events
|
||||
carry `event`, `timestamp` and typed `keyValues`. There is no level field
|
||||
and no raw I/O (MON-12). `to` is a string. No stored trace had more than
|
||||
one recipient, so MON-14's multi-recipient case wasn't seen.
|
||||
3. **Trace queries** (open question 8). `timestampAfter` and `after` are
|
||||
refused with `unsupportedFilter`. The accepted filters weren't listed
|
||||
further.
|
||||
4. **Metrics** (open questions 4 and 5). 10,755 samples over 597 hourly ticks
|
||||
since 2026-08-25, with no gaps: 5,598 `Counter`, 4,025 `Histogram` and
|
||||
1,132 `Gauge`. Histograms are stored for eight metrics: delivery attempt
|
||||
and total time, DNS lookup time, ingest time, and blob and data store
|
||||
read and write times. Gauges are `queue.count` and `server.memory`. Only
|
||||
four metrics appear in every tick, so a counter with nothing to report
|
||||
isn't stored for that tick. Counter values read as per-interval
|
||||
increases, not running totals. `queue.count` moved between 20 and 30 over
|
||||
the last eight hours, so it tracks the queue. Whether it's right straight
|
||||
after a restart wasn't tested.
|
||||
5. **Live telemetry** (open question 9).
|
||||
- `GET /api/token/tracing` and `/api/token/metrics` answer `200` with the
|
||||
token as a bare 90-byte body and no content type.
|
||||
- The streams are `GET /api/live/tracing` and `/api/live/metrics`, with
|
||||
the token in the `token` query parameter. The same token in an
|
||||
`Authorization: Bearer` header is refused (`401`).
|
||||
- Both answer `text/event-stream`. Tracing sends
|
||||
`event: ping` with `data: {"interval": 30000}` while idle. Metrics sends
|
||||
`event: metrics` with a JSON array of `{metric, @type, count}` holding
|
||||
totals since the server started.
|
||||
- `/api/telemetry/traces/live` and `/api/telemetry/metrics/live` don't
|
||||
exist upstream (`404`). The aliases in "Interfaces" are the fork's own.
|
||||
6. **Tenant administrators** (open question 11). The default
|
||||
`Tenant Administrator` role holds 50 permissions and none for telemetry.
|
||||
The `System Administrator` role holds all of them, live ones included.
|
||||
|
||||
Not settled: open question 7 (null retention) needs a write, and question
|
||||
12 (subspace sizes) needs access to the store itself.
|
||||
|
||||
@@ -534,3 +534,19 @@ data.
|
||||
`auth/mod.rs` and 2 from `cache/principals.rs`. This spec doesn't say what
|
||||
they did and doesn't need to. The rules they may have enforced (quota,
|
||||
SCIM authority, tenant checks) are specified here from other sources.
|
||||
|
||||
## Observed
|
||||
|
||||
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart
|
||||
0.16.22), read-only, as a server-level administrator and the throwaway test
|
||||
account. No upstream code was read.
|
||||
|
||||
1. **The cutover check passes.** INBUXA has no external directory
|
||||
(`x:Directory` is empty), `x:Authentication.directoryId` is null, and all
|
||||
nine domains have `directoryId` null. The fork ignoring `directoryId` today
|
||||
changes nothing for INBUXA.
|
||||
2. **Tenant domains** (open question 7). INBUXA has no tenants, so no tenant
|
||||
domain relies on a default. DIR-23 stands as written.
|
||||
|
||||
Open question 2 (the `requireAudience` default) needs a directory to be
|
||||
created, so it stays open.
|
||||
|
||||
@@ -521,3 +521,13 @@ and PostgreSQL), to show members of different kinds work together (ST-16).
|
||||
- **`LookupStore::RedisSentinel` has no build arm** in `build/lookup.rs`. It's
|
||||
outside this feature. Check a stock build to see whether a sentinel lookup
|
||||
store works at all.
|
||||
|
||||
## Observed
|
||||
|
||||
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart
|
||||
0.16.22), read-only, as a server-level administrator and the throwaway test
|
||||
account. No upstream code was read.
|
||||
|
||||
INBUXA runs a single RocksDB data store, with the default blob, in-memory
|
||||
and search stores. No replicas, and no sharded stores. Nothing to carry
|
||||
over, and nothing here affects its cutover.
|
||||
|
||||
@@ -839,3 +839,28 @@ removed suites (`auth`, `bulk`, `discovery`, `groups`, `limits`, `query`,
|
||||
14. **`SCIM_DOMAIN` and `HTTP_PORT` in the test helpers.** The surviving
|
||||
tests imply `scim.example.com` and port 8899 (from addresses and URLs in
|
||||
them). Confirm when rebuilding `mod.rs`.
|
||||
|
||||
## Observed
|
||||
|
||||
Settled on 2026-09-18 against INBUXA's live Enterprise server (Stalwart
|
||||
0.16.22), read-only, as a server-level administrator and the throwaway test
|
||||
account. No upstream code was read.
|
||||
|
||||
1. **SCIM isn't used** (open question 2). No domain has
|
||||
`allowScimProvisioning` on, and none of the 8 accounts has an
|
||||
`externalId`. Cutover has nothing to carry.
|
||||
2. **Discovery is anonymous.** `/scim/v2/ServiceProviderConfig`, `/Schemas`
|
||||
and `/ResourceTypes` answer `200` with no credentials, as
|
||||
`application/scim+json`. `/scim/v2/Users` without credentials answers
|
||||
`401` with `WWW-Authenticate: Bearer realm="Stalwart SCIM"`.
|
||||
3. **What upstream advertises:** PATCH, Bulk (1,000 operations, 1 MiB),
|
||||
filtering (`maxResults` 200), sorting and ETags supported; password change
|
||||
not supported; pagination by index and by cursor, index by default, page
|
||||
size 100, at most 200. One authentication scheme, `oauthbearertoken`,
|
||||
described as an API key presented as a bearer token. `interopProfileConformant`
|
||||
is `false`. `/ResourceTypes` lists `User` and `Group` with no schema
|
||||
extensions, which matches this spec's decision. `documentationUri` points at
|
||||
upstream's documentation. The fork points it at its own.
|
||||
|
||||
The per-account behaviors (open questions 3 and 5 to 9) need an API key and
|
||||
a SCIM-enabled domain, so they stay open.
|
||||
|
||||
Reference in New Issue
Block a user