Subject: Introduce contributor badges

From: Christoph Berg <[email-masked]>
Date: Mon, 19 Jan 2026 17:28:11 +0100

Over the holidays, I used the time to implement the badges idea. We've
discussed in the team and we are happy with how it looks like now, and
I'm attaching the version with the changes from the last contributors
team meeting.

The technical description is in the commit message, so I'm not
duplicating that here. It's obviously a larger patch, but since the
badges are new, I'm not sure it's possible to split it up.

To make rollout less disruptive, we could deploy everything, but leave
out the part that creates links to the new parts
(pgweb/util/contexts.py, anything else?). That way we could test
everything, prefill some initial badges and badge holders, and put in
the links once everything is confirmed to work.

I also plan to present the design at the dev meeting in Brussels.

Re: Magnus Hagander
> If they are not based on the recognized contributors, they should probably
> not be part of that in the data model either. But in particular, we
> shouldn't start creating empty contributor profiles before we even *knoiw*
> that it would.

That part works like this in the patch:
- badges are awarded to users (not to contributors)
- users who have at least one badge are offered to create a profile
  page (creates the contributors object)
- these users can then fill in the data fields

> So any user without any confirmation can just add themselves as a
> contributor, without even moderation, and publish data? That sounds like a
> *really* bad idea, tbh.
> 
> If it's data published by users where we have at one point added them to
> the contributors list and therefore pre-moderated to some point that is
> reasonable. But allowing random people to add records and then edit them
> and then it turns out to be published is going to be a hard no -- we've
> spent many hundreds of hours dealing with that on the wiki for example, and
> we will definitely not open up another venue for that. If it's things that
> not-specifically-approved users can add, then it *must* be moderated.

The moderation part is that people have to convince a badge-issuing
organisation to add their pg.o account as badge holder. This is
possibly a lot of organisations and people, but everyone involved
should be a recognised community member. Also, the worst harm would be
that could publish a random text on a ..../username/ sub-page that is
easily deleted again if we monitor changes. (Afaict any changes to
contributor objects are mailed somewhere. Not sure if that includes
the bio part already, but it could certainly made to be.)

> The latest one that includes that field. Doing that makes the "manage.py
> makemigration" no longer think there are any changes and stop emitting
> anything for that object.

I haven't included the migrations in the patch yet, will do that after
review of the general feature.

> > As for the questions - I think we should absolutely do opt-in, and I do
> > think it makes sense to auto-opt-in the current major contributors since
> > "it's been like that forever and they haven't complained", but listing the
> > others and in a more visible way there are sure to be some who might not
> > want it. In particular, maybe we should make the listing of *email* a
> > separate opt-in/opt-out? That is you can opt-out of being listed
> > completely, or you can say "list me, but not my email"?
> >
> > So there would be a separate opt-in for being listed on the recognized
> > contributor page and for having a public individual contributor
> > profile? And we would only auto opt-in major contributors to the
> > public individual contributor profiles?
> 
> When writing that I was not aware that you were intending to have both a
> "recognized contributor" and a "self-claimed contributor". That does change
> it a bit. If it's a self-claimed contributor then it doesn't make much
> sense to opt-out.

The listing is opt-in. If the user never clicks the "create a profile
page" button, their name is not shown. Not even in the list of badge
holders on the badge page.

Once we have this system, the expectation would be that anyone who
we'd want to promote to a recognized contributor would already have a
profile page created. (If not, we should ask them first why.)

> I think Christoph made a good point about this -- once the contributor
> profile requires an account, which it does in order to get published here,
> they can opt out by just changing their email to being empty. It's only for
> contributors that do not have an account connected that *we* need the email
> (so we can reach them), but with the discussed plan those wouldn't be
> listed anyway  since a username is needed in order to get listed. So that
> should leave us without needing a separate opt-out.

Contributor.email is currently still "null=False, blank=True", should
probably change that to null=True.

> Per above, if it is a field that any user can directly edit and it goes to
> publication, it must be moderated. That's a hard requirement. Before we
> made the whole "make me an editor" requirement for the wiki, for examples,
> we had upwards of 10,000 new accounts signed up every day just to post spam
> when it hit the peak.
> 
> We might need to add more moderators for it, but it needs to be moderated :)

(See above) Even if that's people who have already proven to have
contributed something useful?

> What does it mean that we would get notifications for them? Is "we"
> > the contributors committee?
> 
> Right now, there's just the one moderation team and address that gets it
> for all types of objects. But it would probably be relatively easy to split
> that up so there could be multiple moderation-and-notification teams.

That might make sense. Or some of the contributors team members get an
extra job at pgweb moderation...

Christoph

---

From: Andrey Borodin <[email-masked]>
Date: Tue, 20 Jan 2026 16:56:03 +0500

> On 19 Jan 2026, at 21:28, Christoph Berg <[email-masked]> wrote:
> 

Thanks for working on this! Looks great!
I've setup preview version to test how things will look like. There's some generated sample data.

http://89.169.141.31:8000/community/people/alice/
ogin:moderator pwd:moderator123 
orgmanager1 manager123 
orgmanager2 manager123 
alice alice123 -- Has 3 badges + profile page
bob bob123 -- Has 2 bandges
charlie charlie123 -- 2 badges, without profile

I'm slightly worried that user does not approve their badges.
Also do we plan to add a page where user can claim a badge so org admin can approve their claim?

And I find it a bit oxymoron: "Basic contributor, not recognized"

Best regards, Andrey Borodin.

---

From: Christoph Berg <[email-masked]>
Date: Tue, 20 Jan 2026 13:11:13 +0100

Re: Andrey Borodin
> http://89.169.141.31:8000/community/people/alice/

Thanks, that makes review a bit easier for everyone else I guess.

The "people" page there has a problem:
http://89.169.141.31:8000/community/people/
It's not happening here, so I can't say if that's a bug in the patch.

> I'm slightly worried that user does not approve their badges.

The idea is that the badge itself needs approval and then is trusted.
So I think the worst thing that could happen is that someone
legitimately creates a "PostgreSQL Conf Antarctica Speaker", awards it
to you, but you don't want to publicly admit that you've been there.
Anything I'm missing?

> Also do we plan to add a page where user can claim a badge so org admin can approve their claim?

I think the basic workflow is that people contribute, an organisation
creates a badge for it and awards it to these people. For example,
after the PG19 release, we would create a "PostgreSQL 19 Contributor"
badge and award it to everyone listed in the release notes. Similarly
for conference speakers.

Maybe the other way round shouldn't be too easy so badge issuers don't
get flooded with requests. That's why we put the email link there.

Perhaps we need to make sure all approved badges have clear criteria
for badge holders. For example, "Has said something useful on the
mailing list" would be very fuzzy and invite request spam too much.

> And I find it a bit oxymoron: "Basic contributor, not recognized"

That's there to make the distinction to recognized contributors clear.
Better suggestions welcome.

Christoph

---

From: Christoph Berg <[email-masked]>
Date: Tue, 20 Jan 2026 13:52:59 +0100

Re: To Andrey Borodin
> It's not happening here, so I can't say if that's a bug in the patch.

My mail client recoded the attachment as latin1. I'll replace the "·"
there by &middot; , that's cleaner anyway.

Christoph

---

From: Christoph Berg <[email-masked]>
Date: Fri, 23 Jan 2026 11:14:42 +0100

Re: To Andrey Borodin
> there by &middot; , that's cleaner anyway.

New version attached, with ^ this change and rebased.

Christoph

---

From: Christoph Berg <[email-masked]>
Date: Fri, 23 Jan 2026 20:03:44 +0100

More polishing done, now including the database migration script.

Christoph

---

From: Christoph Berg <[email-masked]>
Date: Fri, 24 Apr 2026 18:45:45 +0200

New version attached. Not much change, the biggest one is perhaps that
lists of badges are no longer rendered as html table, but in a CSS
grid. Everything seems to work as it should now.

My plan is to commit this, minus the menu change in
pgweb/util/contexts.py. That way, we can create the first badges and
check if everything really works without things already being visible
to users (unless they know the URLs).

Christoph

---

From: Christoph Berg <[email-masked]>
Date: Fri, 24 Apr 2026 18:47:38 +0200

Re: To [email-masked]
> grid. Everything seems to work as it should now.

Well, attached now.

Christoph

---

From: Magnus Hagander <[email-masked]>
Date: Mon, 27 Apr 2026 13:46:58 +0200

> to users (unless they know the URLs).
Given the fairly substantial concerns raised ofer this during in-person
discussions at FOSDEM, please do *not* commit this until you have signoff
from those involved. (It might be that it's fine, but given the concerns
and discussions around it, let's make sure those are resolved).

//Magnus

---

From: Christoph Berg <[email-masked]>
Date: Tue, 28 Apr 2026 15:06:14 +0200

Re: Magnus Hagander

I said in the other thread:

> The last result (from the lunch discussion in Brussels) was that we
> need handling of retired people from "permanent" badges like "Sysadmin
> Team". That's not included yet, but in the team, we concluded that
> instead of some complicated date range handling (perhaps that's what
> you remember as plenty?) we can just add a single boolean "retired"
> flag. We don't have that yet, but that's not a big blocker.

I've now implemented retiring from badges. Internally it's tracked by
filling in a date_retired field, but in order not to overcomplicate
the user interface, it's treated as a boolean. Retirees still show up
in badge listing, but are marked as retired.

Removing people from badges is now a two-stage process, retire them
and then remove them. To un-retire someone, add their email address
again (which NULLs the date_retired field).

I'm attaching that as a separate commit for better review. It would
get squashed before committing, of course.

I believe that addresses the concerns from Brussels, or was there
anything else?

Christoph