mesh-mail: say mail events on its own stream MAIL, granted per account by grants (hq ADR 0363)
mesh/delivery checking
mesh/merge-gate out of date: judged against trunk fadf5025cc5a, the trunk is now 2edef5a00ae0; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk fadf5025cc5a, the trunk is now 2edef5a00ae0; judged again on a recheck or when it is merged
mesh/delivery checking
mesh/merge-gate out of date: judged against trunk fadf5025cc5a, the trunk is now 2edef5a00ae0; judged again on a recheck or when it is merged
mesh/repo-check out of date: judged against trunk fadf5025cc5a, the trunk is now 2edef5a00ae0; judged again on a recheck or when it is merged
ADR 0359 asked for a stream of its own and a bus grant from the module's grants; ADR 0363 built both. The events leave the shared EVENTS stream, and one family pattern per change replaces the literal per-account emits, so a new account changes no manifest.
This commit is contained in:
@@ -14,7 +14,9 @@ This is the first stage: accounts of the kind `imap`, read-only. Nothing here fl
|
||||
(`s3-bucket`, from `minio`).
|
||||
- **Says each change.** A message added, its flags changed, or removed is said as the event
|
||||
`mail.<account>.message.<added|changed|removed>`: account, folder, uid, message id, date, sender, recipients,
|
||||
subject, size, flags and attachment references; never the body, never an attachment's bytes. The first look at a
|
||||
subject, size, flags and attachment references; never the body, never an attachment's bytes. The events go to the
|
||||
module's own stream `MAIL`, kept seven days, never to the shared EVENTS stream (novox/hq ADR 0363); a module hears an
|
||||
account's part only when its `consumes` names mesh-mail and the setting `grants` names it for that account. The first look at a
|
||||
folder indexes what is there and says nothing: the bus hears what changed since the watch began. The keeper writes
|
||||
each event in the same step as the change it says; the bundle says it through the runtime and removes it once the
|
||||
bus took it.
|
||||
@@ -34,7 +36,8 @@ This is the first stage: accounts of the kind `imap`, read-only. Nothing here fl
|
||||
more password; no code changes. `user` signs in under another name than the address.
|
||||
|
||||
`grants` — per account, who may read its mail: a module's name (on every machine), `<machine>.<module>`, or
|
||||
`person.<name>`. Nobody by default.
|
||||
`person.<name>`. Nobody by default. It restricts the stream `MAIL` on the bus (a person's entry grants nothing there)
|
||||
and the tools `mail_search` and `mail_read`.
|
||||
|
||||
The password of an account is the own secret `mail-credential-<account>`, given at the desk; the mesh never makes one.
|
||||
|
||||
|
||||
@@ -21,11 +21,20 @@ type manifest struct {
|
||||
OwnSecrets map[string]map[string]string `json:"own-secrets"`
|
||||
Tools []string `json:"tools"`
|
||||
Emits []string `json:"emits"`
|
||||
Consumes []string `json:"consumes"`
|
||||
Invokes []string `json:"invokes"`
|
||||
Claims []json.RawMessage `json:"claims"`
|
||||
Resources []map[string]any `json:"resources"`
|
||||
Build struct {
|
||||
Streams []struct {
|
||||
Name string `json:"name"`
|
||||
Events []string `json:"events"`
|
||||
MaxAgeDays int `json:"max-age-days"`
|
||||
Grant struct {
|
||||
Config string `json:"config"`
|
||||
Events string `json:"events"`
|
||||
} `json:"grant"`
|
||||
} `json:"streams"`
|
||||
Consumes []string `json:"consumes"`
|
||||
Invokes []string `json:"invokes"`
|
||||
Claims []json.RawMessage `json:"claims"`
|
||||
Resources []map[string]any `json:"resources"`
|
||||
Build struct {
|
||||
Artifacts []struct {
|
||||
From string `json:"from"`
|
||||
Binary string `json:"binary"`
|
||||
@@ -72,12 +81,15 @@ func TestTheManifestSaysWhatTheCodeDoes(t *testing.T) {
|
||||
if !reflect.DeepEqual(m.Tools, names) || !reflect.DeepEqual(names, []string{"mail_accounts", "mail_search", "mail_read", "mail_health"}) {
|
||||
t.Fatalf("tools %v, the code serves %v", m.Tools, names)
|
||||
}
|
||||
var emits []string
|
||||
// Its events go to its own stream MAIL, kept a week, each account's part heard only by the consumers the trusted
|
||||
// config value grants names for it (ADR 0359 §2, §4; ADR 0363): none on the shared EVENTS stream.
|
||||
var events []string
|
||||
for _, c := range Changes {
|
||||
emits = append(emits, EventKey("mesh", c))
|
||||
events = append(events, EventKey("*", c))
|
||||
}
|
||||
if !reflect.DeepEqual(m.Emits, emits) {
|
||||
t.Fatalf("emits %v, the code says %v for the account mesh", m.Emits, emits)
|
||||
if len(m.Emits) != 0 || len(m.Streams) != 1 || m.Streams[0].Name != "mail" || !reflect.DeepEqual(m.Streams[0].Events, events) ||
|
||||
m.Streams[0].MaxAgeDays != 7 || m.Streams[0].Grant.Config != "grants" || m.Streams[0].Grant.Events != "mail.{key}.**" {
|
||||
t.Fatalf("emits %v, streams %+v; the code says %v", m.Emits, m.Streams, events)
|
||||
}
|
||||
// It reads its own mail and calls nothing, consumes nothing and claims no seat.
|
||||
if len(m.Consumes)+len(m.Invokes)+len(m.Claims) != 0 {
|
||||
|
||||
@@ -31,10 +31,20 @@
|
||||
"mail_read",
|
||||
"mail_health"
|
||||
],
|
||||
"emits": [
|
||||
"mail.mesh.message.added",
|
||||
"mail.mesh.message.changed",
|
||||
"mail.mesh.message.removed"
|
||||
"streams": [
|
||||
{
|
||||
"name": "mail",
|
||||
"events": [
|
||||
"mail.*.message.added",
|
||||
"mail.*.message.changed",
|
||||
"mail.*.message.removed"
|
||||
],
|
||||
"max-age-days": 7,
|
||||
"grant": {
|
||||
"config": "grants",
|
||||
"events": "mail.{key}.**"
|
||||
}
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user