Closes#207. The last of the three tiers, and the only one that remembers anything.
What it is for
An admin turns a setting on for people who are already here — which a default cannot do, since a default only seeds an account that has none — while still leaving them the last word, which enforcement does not allow. The difference between the two is entirely in the remembering.
Ids, not a high-water mark. Each change carries its own version and an account stores the set it has had. A change dated earlier than one already applied is therefore not silently skipped — an admin backfilling one gets it applied. The reporter's analogy is a schema migration and this is that shape.
Per account, not per device. ihasmail's settings are not browser-local — they live in a file in the reader's own JMAP Files with the browser holding a cache — so signing in on a phone does not apply everything a second time. I had this wrong when I first reasoned about the tier and checked before building.
A change reaches somebody who had already decided otherwise. Confirmed as intended on the issue: the point is to reach everybody who is already here. It applies once, and their next decision sticks. This is the one case where the power is indistinguishable from enforcement to the person on the receiving end, which is why it was worth confirming rather than assuming.
One write for however many are pending, since each would otherwise push a settings file of its own — a first sign-in against a policy with four changes would write four.
Enforced still outranks it, being applied after. A change whose settings this build does not have at all is dropped rather than recorded as applied, or it would never run on the ihasmail that does have them.
The reader is told. A setting moving under somebody without a word is the part of this worth being uneasy about, so the count is toasted with a way into Settings.
README
The Docker half, which was asked for directly: a mounted policy file with :ro, the same thing as environment variables for an immutable deployment with no volume, a compose fragment, a table of the three powers, and the fact that a policy is read once at startup so editing it means restarting the container — deliberately no reload signal.
Tests
Nine more (21 in the file): applying an unseen change, remembering it so a second sign-in does not repeat it, reaching an account that had chosen otherwise, applying only what is new while keeping the record, not skipping a back-dated change, one write for several, enforced outranking a change, and an all-unknown change dropped rather than recorded.
npm run typecheck, npm test (977 web + 122 server), npm run build, i18n:check pass. One new plural in all nine catalogues.
Note
Nothing is configured by default. An installation that sets none of these — ihasmail.com included — behaves exactly as it always has.
Closes #207. The last of the three tiers, and the only one that remembers anything.
## What it is for
An admin turns a setting on for people who are **already here** — which a default cannot do, since a default only seeds an account that has none — while still leaving them the last word, which enforcement does not allow. The difference between the two is entirely in the remembering.
```json
{
"changes": [
{ "version": "20260902084513", "settings": { "externalSenderBanner": true } }
]
}
```
## The decisions
**Ids, not a high-water mark.** Each change carries its own `version` and an account stores the set it has had. A change dated earlier than one already applied is therefore not silently skipped — an admin backfilling one gets it applied. The reporter's analogy is a schema migration and this is that shape.
**Per account, not per device.** ihasmail's settings are not browser-local — they live in a file in the reader's own JMAP Files with the browser holding a cache — so signing in on a phone does not apply everything a second time. I had this wrong when I first reasoned about the tier and checked before building.
**A change reaches somebody who had already decided otherwise.** Confirmed as intended on the issue: the point is to reach everybody who is already here. It applies once, and their next decision sticks. This is the one case where the power is indistinguishable from enforcement to the person on the receiving end, which is why it was worth confirming rather than assuming.
**One write for however many are pending**, since each would otherwise push a settings file of its own — a first sign-in against a policy with four changes would write four.
**Enforced still outranks it**, being applied after. A change whose settings this build does not have *at all* is dropped rather than recorded as applied, or it would never run on the ihasmail that does have them.
**The reader is told.** A setting moving under somebody without a word is the part of this worth being uneasy about, so the count is toasted with a way into Settings.
## README
The Docker half, which was asked for directly: a mounted policy file with `:ro`, the same thing as environment variables for an immutable deployment with no volume, a compose fragment, a table of the three powers, and the fact that a policy is read once at startup so editing it means restarting the container — deliberately no reload signal.
## Tests
Nine more (21 in the file): applying an unseen change, remembering it so a second sign-in does not repeat it, reaching an account that had chosen otherwise, applying only what is new while keeping the record, not skipping a back-dated change, one write for several, enforced outranking a change, and an all-unknown change dropped rather than recorded.
`npm run typecheck`, `npm test` (977 web + 122 server), `npm run build`, `i18n:check` pass. One new plural in all nine catalogues.
## Note
Nothing is configured by default. An installation that sets none of these — ihasmail.com included — behaves exactly as it always has.
**Merged** 2026-09-02 as coffey-labs/ihasmail@cff7f6c11b39
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #207. The last of the three tiers, and the only one that remembers anything.
What it is for
An admin turns a setting on for people who are already here — which a default cannot do, since a default only seeds an account that has none — while still leaving them the last word, which enforcement does not allow. The difference between the two is entirely in the remembering.
The decisions
Ids, not a high-water mark. Each change carries its own
versionand an account stores the set it has had. A change dated earlier than one already applied is therefore not silently skipped — an admin backfilling one gets it applied. The reporter's analogy is a schema migration and this is that shape.Per account, not per device. ihasmail's settings are not browser-local — they live in a file in the reader's own JMAP Files with the browser holding a cache — so signing in on a phone does not apply everything a second time. I had this wrong when I first reasoned about the tier and checked before building.
A change reaches somebody who had already decided otherwise. Confirmed as intended on the issue: the point is to reach everybody who is already here. It applies once, and their next decision sticks. This is the one case where the power is indistinguishable from enforcement to the person on the receiving end, which is why it was worth confirming rather than assuming.
One write for however many are pending, since each would otherwise push a settings file of its own — a first sign-in against a policy with four changes would write four.
Enforced still outranks it, being applied after. A change whose settings this build does not have at all is dropped rather than recorded as applied, or it would never run on the ihasmail that does have them.
The reader is told. A setting moving under somebody without a word is the part of this worth being uneasy about, so the count is toasted with a way into Settings.
README
The Docker half, which was asked for directly: a mounted policy file with
:ro, the same thing as environment variables for an immutable deployment with no volume, a compose fragment, a table of the three powers, and the fact that a policy is read once at startup so editing it means restarting the container — deliberately no reload signal.Tests
Nine more (21 in the file): applying an unseen change, remembering it so a second sign-in does not repeat it, reaching an account that had chosen otherwise, applying only what is new while keeping the record, not skipping a back-dated change, one write for several, enforced outranking a change, and an all-unknown change dropped rather than recorded.
npm run typecheck,npm test(977 web + 122 server),npm run build,i18n:checkpass. One new plural in all nine catalogues.Note
Nothing is configured by default. An installation that sets none of these — ihasmail.com included — behaves exactly as it always has.
Merged 2026-09-02 as coffey-labs/ihasmail@cff7f6c11b
Rebuilt from: git history, session transcript.