Invites and suggestions are cases; the responsible follow the content
Test / test (pull_request) Successful in 56s
Test / test (pull_request) Successful in 56s
Five things the first cut of accounts-from-content left open. The first person and the responsible people are set up side by side, and both try again a minute apart: a seed that waited twenty minutes on Kanidm used to hold everyone else up, and a responsible person who failed waited for the next restart. The responsible are gone over again whenever the content changes. watch_for_reload publishes portal.content.reloaded once new content is in place, and seed.rs listens. Being responsible ends when the content stops saying so: someone no page names any more leaves RESPONSIBLE_GROUP in the same pass, if portal is who put them there (Invited.already_member). The account stays. An invite keeps itself current. portal_invites has an expired state; signing in closes a person's invites, a sweep moves the ones whose link ran out, and a desk's move from expired back to open makes a fresh link and mails it. Invites made at start are on file with the desks'. A suggested edit is a case in the built-in portal_edit_suggestions bucket, the person who made it is mailed at each move, and the card lists what they sent and where it stands. Found on the way, against Kanidm 1.11.2: a link's end comes as seconds since the epoch, which portal did not read, so invite mails said "until" and nothing; and a mail search answered with a 5xx was taken for a refusal. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GT37Z1Xtfd9pUuQtMTg6Yt
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
7a50ce77b2
commit
ef4789f9b2
+62
-8
@@ -104,11 +104,18 @@ At start, portal:
|
||||
questions, with their link. With `RESPONSIBLE_GROUP` they all join
|
||||
it; someone who already had an account is added without a mail.
|
||||
|
||||
Kanidm may still be starting beside portal, so the first person's
|
||||
invite is tried again a minute apart, up to twenty times. A responsible
|
||||
person who could not be set up is left for the next start. The log says
|
||||
The two run side by side. Kanidm may still be starting beside portal,
|
||||
so each is tried again a minute apart, up to twenty times. The log says
|
||||
what happened, per person.
|
||||
|
||||
The second happens again **whenever the content changes**, so a new
|
||||
page naming a new person sets them up without a restart. And it works
|
||||
both ways: someone the content has stopped naming leaves
|
||||
`RESPONSIBLE_GROUP` in the same pass, and with it whatever else that
|
||||
group opens. Only if portal is who put them there - a person who was in
|
||||
the group before is left in it - and their account stays, since it is
|
||||
theirs.
|
||||
|
||||
## 5. The rest come in from the desks
|
||||
|
||||
From here nobody touches Kanidm:
|
||||
@@ -119,16 +126,60 @@ From here nobody touches Kanidm:
|
||||
in `aggregates.yaml` puts the person a case is about into that group
|
||||
when the case arrives there - an approved committee application that
|
||||
*is* the membership.
|
||||
- **A new page with a new responsible person** gets them an account at
|
||||
the next start.
|
||||
- **A new page with a new responsible person** gets them an account
|
||||
when the page goes live.
|
||||
|
||||
### An invite that nobody used
|
||||
|
||||
A link lives a day. Every invite - a desk's, and the ones portal made
|
||||
at start - is a case in `portal_invites`, and keeps itself current:
|
||||
|
||||
| state | means | how it gets there |
|
||||
|---|---|---|
|
||||
| `open` | the link is waiting | the invite was sent, or sent again |
|
||||
| `done` | the person is in | they signed in to the site; or a desk says so |
|
||||
| `expired` | the link ran out unused | a sweep, every ten minutes |
|
||||
|
||||
A desk that lists the bucket offers the way back with a transition from
|
||||
`expired` to `open`. Pressing it makes a fresh link and mails it:
|
||||
|
||||
```yaml
|
||||
resource:
|
||||
source: { kind: kv, bucket: portal_invites }
|
||||
requires_group: styret
|
||||
transitions:
|
||||
- { from: open, to: done, label: Is in }
|
||||
- { from: expired, to: open, label: Send again }
|
||||
- { from: expired, to: done, label: Is in }
|
||||
```
|
||||
|
||||
## 6. What the people who ask the questions can do
|
||||
|
||||
Signed in, a person a page names as responsible sees a card at the
|
||||
foot of their own pages to suggest a change. The server checks it is
|
||||
really them; the suggestion is kept (`portal_edit_suggestions`),
|
||||
announced (`portal.edits.suggested`), and mailed to the site's inbox
|
||||
with them as reply-to, so answering it answers them.
|
||||
really them, and the suggestion is mailed to the site's inbox with them
|
||||
as reply-to, so answering it answers them.
|
||||
|
||||
It is also a case, in the built-in `portal_edit_suggestions` bucket, so
|
||||
it does not depend on somebody reading that inbox. Give a desk the
|
||||
list, and whoever sits there takes it up and settles it:
|
||||
|
||||
```yaml
|
||||
resource:
|
||||
source: { kind: kv, bucket: portal_edit_suggestions }
|
||||
requires_group: styret
|
||||
transitions:
|
||||
- { from: open, to: discussed, label: Looking at it }
|
||||
- { from: open, to: done, label: Changed }
|
||||
- { from: open, to: declined, label: Will not change }
|
||||
- { from: discussed, to: done, label: Changed }
|
||||
- { from: discussed, to: declined, label: Will not change }
|
||||
```
|
||||
|
||||
The person who suggested it is mailed at each move, in the site's
|
||||
language, and the card on their page lists what they have sent and
|
||||
where each one stands. A content repo that declares the bucket itself
|
||||
in `aggregates.yaml`, with a `mail:` on a state, sends that instead.
|
||||
|
||||
Their group can also be the way into other tools. The vel's
|
||||
`redaktor` group signs in to the project Gitea with the same account:
|
||||
@@ -143,4 +194,7 @@ a second OAuth2 client scoped to that group alone.
|
||||
| `Item not found` setting the login page's name or logo | those are system settings only `admin` may change, not `idm_admin` - or the CLI and server versions differ |
|
||||
| accounts are made but nobody is mailed | `site.yaml` has no `mail.from`, or gdo is not running on the host |
|
||||
| someone responsible never got a mail | they already had an account (they are only added to `RESPONSIBLE_GROUP`), or their `contact` is not an email address |
|
||||
| an invite stays `open` though the person has set a passkey | Kanidm does not show a passkey to the onboarding account; it becomes `done` when they sign in to the site |
|
||||
| "send again" is not on the desk | the list has no `{ from: expired, to: open }` transition, or the content declares `portal_invites` itself without an `expired` state |
|
||||
| someone left a page and is still in `RESPONSIBLE_GROUP` | they were in the group before portal added them, so it is not portal's to undo |
|
||||
| the first person was invited twice | it cannot be, per address and group; changing `SEED_ADMIN_EMAIL` or `SEED_GROUP` invites the new pair |
|
||||
|
||||
Reference in New Issue
Block a user