The problem. The mesh-sdk harness trusted its memory of what it applied (hq issue 120). A backend that loses a consumer's login while the provisioner keeps running is never provisioned again, and nothing reports it. redis is the live case: its ACL users are in memory, and a server restart erases them.
The change. All nine credential providers implement the optional holds(p) from mesh-sdk 0.1.1. The harness asks it every minute and re-applies on false.
The rule for every check:
It is read-only.
It checks the mesh's password as the consumer presents it, or compares it without logging in.
It returns false only when the backend says the credential is absent or wrong.
It throws for anything else (unreachable, a timeout), so the harness keeps the consumer rather than re-applying.
provider
how it checks
redis
ACL GETUSER: the user exists, is on, and holds the SHA-256 of the password
postgres
psql as the consumer to its database
mssql
PWDCOMPARE against sys.sql_logins, the database exists, and IS_ROLEMEMBER('db_owner')
mongodb
mongosh as the consumer (authSource is its database), and connectionStatus roles include dbOwner
minio
a signed HEAD of the bucket, signed with the consumer's access key and secret
lavinmq
the stored salted SHA-256 is recomputed with the password, and .* permissions on its vhost
mosquitto
a raw MQTT CONNECT as the consumer (CONNACK 0 / 4 / 5), then the client still holds its role
mailu
the admin API says the user exists and is enabled, then doveadm auth test in the imap container, with the password passed through the exec environment
gitea
basic auth on /api/v1/user as the consumer, plus membership of the packages team
Verified so far
All nine typecheck against the mesh-sdk 0.1.1 build.
Against real servers (throwaway local containers, since removed):
redis 7: correct for absent, present, wrong password, disabled and deleted. A restart erasing ACL users was reproduced.
lavinmq: correct for absent, present, wrong password, missing permission, recreated and removed.
gitea 1.22: correct for no org, absent, not in the team, present, wrong password and deleted.
minio (pgsty/minio, the image this module uses): correct for key absent, present, wrong secret, bucket gone and key gone.
postgres 16: not verified. The probe ran over a connection the image trusts without a password, so it accepted a wrong password. Correct for no login, no connect privilege, dropped, and unreachable (it throws). The password case must be re-run over a connection that checks passwords.
Still to verify in the lab: postgres (the password case), mssql, mongodb, mosquitto and mailu.
Merge order. mesh-sdk #7 first, so 0.1.1 is published. Don't merge this until the lab has verified the rest.
**The problem.** The mesh-sdk harness trusted its memory of what it applied (hq issue 120). A backend that loses a consumer's login while the provisioner keeps running is never provisioned again, and nothing reports it. redis is the live case: its ACL users are in memory, and a server restart erases them.
**The change.** All nine credential providers implement the optional `holds(p)` from mesh-sdk 0.1.1. The harness asks it every minute and re-applies on `false`.
**The rule for every check:**
- It is read-only.
- It checks the mesh's password as the consumer presents it, or compares it without logging in.
- It returns `false` only when the backend says the credential is absent or wrong.
- It throws for anything else (unreachable, a timeout), so the harness keeps the consumer rather than re-applying.
| provider | how it checks |
|---|---|
| redis | `ACL GETUSER`: the user exists, is on, and holds the SHA-256 of the password |
| postgres | `psql` as the consumer to its database |
| mssql | `PWDCOMPARE` against `sys.sql_logins`, the database exists, and `IS_ROLEMEMBER('db_owner')` |
| mongodb | `mongosh` as the consumer (authSource is its database), and `connectionStatus` roles include `dbOwner` |
| minio | a signed `HEAD` of the bucket, signed with the consumer's access key and secret |
| lavinmq | the stored salted SHA-256 is recomputed with the password, and `.*` permissions on its vhost |
| mosquitto | a raw MQTT CONNECT as the consumer (CONNACK 0 / 4 / 5), then the client still holds its role |
| mailu | the admin API says the user exists and is enabled, then `doveadm auth test` in the imap container, with the password passed through the exec environment |
| gitea | basic auth on `/api/v1/user` as the consumer, plus membership of the `packages` team |
**Verified so far**
- **All nine typecheck** against the mesh-sdk 0.1.1 build.
- **Against real servers** (throwaway local containers, since removed):
- **redis 7:** correct for absent, present, wrong password, disabled and deleted. A restart erasing ACL users was reproduced.
- **lavinmq:** correct for absent, present, wrong password, missing permission, recreated and removed.
- **gitea 1.22:** correct for no org, absent, not in the team, present, wrong password and deleted.
- **minio** (`pgsty/minio`, the image this module uses): correct for key absent, present, wrong secret, bucket gone and key gone.
- **postgres 16:** not verified. The probe ran over a connection the image trusts without a password, so it accepted a wrong password. Correct for no login, no connect privilege, dropped, and unreachable (it throws). The password case must be re-run over a connection that checks passwords.
**Still to verify in the lab:** postgres (the password case), mssql, mongodb, mosquitto and mailu.
**Merge order.** mesh-sdk #7 first, so 0.1.1 is published. Don't merge this until the lab has verified the rest.
The server keeps ACL users in memory only, so a restart forgets every
consumer while the provisioner keeps running (hq issue 120). holds()
checks ACL GETUSER for the user, enabled, with the mesh's password, so
the harness makes a forgotten user again. Needs mesh-sdk 0.1.1.
holds() for postgres, mssql, mongodb, minio, lavinmq, mosquitto, mailu
and gitea, so the harness makes again a login the backend lost (hq issue
120). Each checks the mesh's password as the consumer presents it, or
compares it read-only, and returns false only when the backend says the
credential is absent or wrong; an unreachable backend throws.
jschoubben
changed title from redis: say whether it still holds a consumer's ACL user (hq issue 120) to Every credential provider says whether it still holds a consumer (hq issue 120)2026-09-25 23:10:06 +00:00
create re-enables what holds refuses (mssql login, mosquitto client,
mailu mailbox, gitea user) and clears an expired postgres password, so
no disabled account loops. mssql and mongodb checks take the password
from the environment, never argv; mosquitto_ctrl failures no longer
repeat -P. mosquitto reads 'could not ask' as an error, not absence.
mailu checks existence and enabled only: its imap passdb cannot verify
a password. mssql checks the user's SID; gitea pages teams at 50.
ALTER USER ... WITH LOGIN runs only when the user's SID is not the
login's, so an already-mapped user is left alone. The provisioner
enables a mailbox through its own method; the password tool an
operator uses keeps changing the password only.
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.
The problem. The mesh-sdk harness trusted its memory of what it applied (hq issue 120). A backend that loses a consumer's login while the provisioner keeps running is never provisioned again, and nothing reports it. redis is the live case: its ACL users are in memory, and a server restart erases them.
The change. All nine credential providers implement the optional
holds(p)from mesh-sdk 0.1.1. The harness asks it every minute and re-applies onfalse.The rule for every check:
falseonly when the backend says the credential is absent or wrong.ACL GETUSER: the user exists, is on, and holds the SHA-256 of the passwordpsqlas the consumer to its databasePWDCOMPAREagainstsys.sql_logins, the database exists, andIS_ROLEMEMBER('db_owner')mongoshas the consumer (authSource is its database), andconnectionStatusroles includedbOwnerHEADof the bucket, signed with the consumer's access key and secret.*permissions on its vhostdoveadm auth testin the imap container, with the password passed through the exec environment/api/v1/useras the consumer, plus membership of thepackagesteamVerified so far
pgsty/minio, the image this module uses): correct for key absent, present, wrong secret, bucket gone and key gone.Still to verify in the lab: postgres (the password case), mssql, mongodb, mosquitto and mailu.
Merge order. mesh-sdk #7 first, so 0.1.1 is published. Don't merge this until the lab has verified the rest.
redis: say whether it still holds a consumer's ACL user (hq issue 120)to Every credential provider says whether it still holds a consumer (hq issue 120)