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.
|
schema. A later addition in the fork's namespace if asked for.
|
||||||
9. A "test this model" action for INBUXA Admin. Useful, not required.
|
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).
|
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
|
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,
|
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.
|
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
|
`sysMetric*` or live permission, and whether a tenant view of its own
|
||||||
domains' traces is wanted (MON-31).
|
domains' traces is wanted (MON-31).
|
||||||
12. Size of INBUXA's `o` and `x` subspaces, to check MON-19's estimate.
|
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
|
`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,
|
they did and doesn't need to. The rules they may have enforced (quota,
|
||||||
SCIM authority, tenant checks) are specified here from other sources.
|
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
|
- **`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
|
outside this feature. Check a stock build to see whether a sentinel lookup
|
||||||
store works at all.
|
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
|
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
|
tests imply `scim.example.com` and port 8899 (from addresses and URLs in
|
||||||
them). Confirm when rebuilding `mod.rs`.
|
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