-
v0.6.3
Stablereleased this
2026-09-30 17:33:11 +00:00 | 82 commits to main since this release- Pages move the way their addresses do. Deeper in the address comes in from the right, back up comes in from the left, and a page at the same depth comes from below or above, with the index on top. The cards on screen leave as layers of their own, one after another, and the next page's cards arrive the same way. The old page stays on screen until the new one has loaded, where it used to go blank in between. Only transforms and opacity are animated, through the browser's View Transitions (
public/page-motion.js, before the router). Browsers without them, and anyone who asks for reduced motion, navigate as before. - A record that carries a picture, in a list with no buttons, is shown as a card: the picture, the first field as the heading, the rest under it, with no field names, state or time. Cards are shown in the order they were put up. On a desk, the same picture is a thumbnail.
- Trainer:
valuesin a plan andpresents: trueon a need make a "who we are" card on the front door. The business's own statements are carried word for word, beside every record the need presents: the people who work there, entered from inside, each with apicturefield (a file that only takes JPEG, PNG or WebP) that shows as their portrait. A public list keeps the form's field order, so the first field heads each row.
Downloads
- Pages move the way their addresses do. Deeper in the address comes in from the right, back up comes in from the left, and a page at the same depth comes from below or above, with the index on top. The cards on screen leave as layers of their own, one after another, and the next page's cards arrive the same way. The old page stays on screen until the new one has loaded, where it used to go blank in between. Only transforms and opacity are animated, through the browser's View Transitions (
-
v0.6.2
Stablereleased this
2026-09-30 15:39:57 +00:00 | 88 commits to main since this release- The header knows who is here: on a site with sign-in, a link top right to sign in, or the person's name and the way out. A page with a
slideshowgets the wordmark as a bar of its own, the strip full width under it, and the question after. - "My cases":
where: { field: email, equals: "{user.email}" }lists the records that carry the signed-in person's own address, filled from the session and never from the caller; nobody signed in matches nothing. An attachment is fetched only through a list that shows its record, so a list of my cases opens my files and nobody else's. - A stored file on a listed record shows as the name it was sent with and opens from the row, for whoever the list shows the record to. It used to show as its storage key, a string nobody could open.
- Form controls scale with the text around them (em, not rem): fields, pills, buttons and labels follow a site's body size. The date picker's calendar icon is the size of the text beside it, and the file picker's button takes the field's colours instead of the browser's.
KANIDM_GROUP_PREFIX: a site on a Kanidm it shares with others keeps plain group names in its content; the prefix is put on when portal adds or removes a member, and the client's claim map takes it off.- Fixed:
mapsnever reached the browser (serde(skip)), so a page with a map drew it on the server and dropped it on hydration.
Downloads
- The header knows who is here: on a site with sign-in, a link top right to sign in, or the person's name and the way out. A page with a
-
v0.6.1
Stablereleased this
2026-09-30 15:19:37 +00:00 | 95 commits to main since this release-
Trainer:
documentsin a plan. A text the site carries word for word (bylaws, terms) becomes a page of its own where every section is one alternative: its heading the card's, its paragraphs the card's words, from a markdown file beside the plan. No model touches it. -
slideshowon a page: a strip of pictures the full width of the screen under the question,max_heightin svh, each picture with its caption laid over it. Swiper when the bundle has loaded, a sideways-scrolling row before./site/servesjpeg, and lets a browser keep photographs for an hour. -
The release's bare binary is named
portal-x86_64-linux(it wasportalin 0.6.0 only). Gitea lists assets by name, and deploy scripts that take the first asset got the binary instead of the tarball.
Downloads
-
-
v0.6.0
Stablereleased this
2026-09-30 13:33:17 +00:00 | 104 commits to main since this release- One binary. The lint (uhhm/iris) and the trainer (uhhm/portal-trainer) are commands of
portal:portal serve(the default),portal lint, andportal plan,build,answer,rate,prefer,score,simulate,compare,report,generate. Same source, same version, so the site, the lint and the trainer never disagree about what content means; both histories are merged in. The release attaches the bareportalbinary beside the tarball, so a content repo's CI downloads it and runsportal lint. No more iris releases; the pins that exist keep working. The trainer'splans/,intakes/,engines/,sectors/and its reference prompt live here now; itsruns/stay in uhhm/portal-trainer. Docs gained "Training a site" and "The lint".
Downloads
- One binary. The lint (uhhm/iris) and the trainer (uhhm/portal-trainer) are commands of
-
v0.5.10
Stablereleased this
2026-09-30 12:10:06 +00:00 | 223 commits to main since this release- The lint lets an invite form collect a required
phonein place of a requiredemail: memberships know a person by number first.
Downloads
- The lint lets an invite form collect a required
-
v0.5.9
Stablereleased this
2026-09-30 12:06:58 +00:00 | 225 commits to main since this release- With memberships as the people backend and a Kanidm token still set, an invite makes the Kanidm account as well (no group, the one-time link in the mail): Kanidm makes people, portal makes members, and a site can switch to memberships before its sign-in provider is one everyone already has.
Downloads
-
v0.5.8
Stablereleased this
2026-09-30 11:40:13 +00:00 | 229 commits to main since this release- Fixed: 0.5.7 asked every provider for the
phoneNumberscope, and Kanidm denies a sign-in that asks for a scope the person does not hold, so nobody could sign in. The scope is asked for only withOIDC_EXTRA_SCOPES=phoneNumber(Vipps). 0.5.7 must not be deployed on a Kanidm site.
Downloads
- Fixed: 0.5.7 asked every provider for the
-
v0.5.7
Stablereleased this
2026-09-30 11:33:15 +00:00 | 232 commits to main since this release- Memberships: groups kept by portal itself (
src/memberships.rs,docs/memberships.md). A membership is a case in the built-inportal_membershipsbucket -invitedby a desk, agrants, the seed or the responsible pass;activefrom the person's first sign-in, when the provider's subject, phone number or address matches;removedby a desk. A person is their phone number first (+4791234567,PHONE_COUNTRYfor bare numbers), their address second, the provider's subject third, and one record per group and person however it was keyed. At sign-in the active memberships join thegroupsclaim, so Cedar sees the same parents as before.PEOPLE_BACKEND=membershipsswitches a site; unset, aKANIDM_API_TOKENmeans Kanidm and no token means memberships.SEED_ADMIN_PHONEseeds by number. The sign-in asks for thephoneNumberscope and readsphone_numberfrom userinfo. - The NATS access service answers for a person named by
sub,phoneoremailwith no groups listed: their memberships are looked up first. who_for(the person agrantsis about) takesnavnas well asname, and a phone number in place of an address.- The invite mail for someone who needs no link says where to sign in.
Downloads
- Memberships: groups kept by portal itself (
-
v0.5.6
Stablereleased this
2026-09-30 06:18:41 +00:00 | 238 commits to main since this release- A group may hold a page's responsibility:
responsible: { name, contact, group: styret }. No account or mail for the inbox, and any signed-in member of the group gets the suggest-a-change card. Before this, a board's shared address was onboarded as a person.
Downloads
- A group may hold a page's responsibility:
-
v0.5.5
Stablereleased this
2026-09-30 05:51:07 +00:00 | 243 commits to main since this release- One record answers another, from a list.
linkon a resource puts a link on every listed record to a page about it ({id},{field}), a state mail'stomay be a field of the record this one belongs to ({notice.email}, and{notice.field}in the text), andvalue: "{user.email}"fills a field from the session and hides it, so a signed-in person is not asked who they are. Together they make a board: a notice is listed with "answer this", the answer page's form carries the notice's id, and the mail goes to whoever posted it. The lint requires the record field the mail reaches through. - The way down the tree is the line at the foot of the page and nothing else. The arrow fixed at the left edge, which 0.5.3 added beside it, is gone: it followed the reader down every page to offer something the foot already does.
Downloads
- One record answers another, from a list.