Repository navigation
Commit 8e500f2
fix(plugin-auth): name a remedy that works in the no-sign-in boot report (#15720)
* wip(plugin-auth): #15588 remedy text + behavioural pins
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* fix(plugin-auth): name a remedy that works in the no-sign-in boot report
The `no_sign_in_account_at_boot` report fires on the deployment nobody can
sign in to: human `sys_user` rows, zero `sys_account` rows. It ended with two
remedies, and measured on the exact population it fires on, neither did what
its sentence said.
"Open the audience posture so an existing person can register their own login"
produced no login: every posture other than `invite_only` forces
`requireEmailVerification` on, so a login registered that way is refused
`EMAIL_NOT_VERIFIED` at first sign-in, and a locked-out self-hosted install is
usually the shape with no mail transport wired.
"Write a `sys_account` credential row directly against the store" was worse
than useless. The `password` column carries a secret in the platform's own
hash format, so a plaintext one authenticates nothing — and
`probeSignInAccountsPresence` asks only whether ANY `sys_account` row exists,
so writing one turns this very report off. The operator's first attempt at the
named remedy turned the loud dead end back into the silent one the report was
written to end.
The line now names the path measured to work: one pending `sys_invitation` row
written directly against the store, then an ordinary sign-up. The invitation
carve-out admits that one creation under every posture, so no door is widened
and no mail transport is needed. The other two are still named, as the two
things that look like remedies and are not.
Message text only — no admission semantics move, exactly as the diagnostic's
own card scoped itself. The probe is untouched; tightening it would move that
card's diagnostic semantics and is deliberately not done here.
Each clause is pinned against the behaviour it describes rather than string-
matched: the invitation carve-out is driven across the whole `AUDIENCE_POSTURES`
vocabulary with an un-invited control, the self-silencing claim is driven
through the real probe with a hand-written plaintext credential row, and the
forced-verification claim is read off `getPublicConfig()`'s wiring mirror with
an `invite_only` control. Every new pin was mutation-checked.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* fix(plugin-auth): scope the no-mail-transport rider on the invitation remedy
Clause-② review F1: the rider was FALSE on a reachable population. The
invitation carve-out is an ADMISSION verdict, not a verification bypass, so
the forced-verification mechanism this same line warns about for remedy (b)
applies to the INVITED login too. Measured by the reviewer on `open` and on
`email_domain` with a pending invitation: sign-up 200 with emailVerified
false, sign-in 403 EMAIL_NOT_VERIFIED — and the created row makes
probeSignInAccountsPresence answer 'present', so the report goes silent. An
operator following the PRIMARY remedy on a widened posture therefore got no
login and turned this report off: the loud-dead-end-to-quiet-dead-end
transition remedy (a) warns about, delivered by the remedy the card
commissioned.
The rider is now scoped to the default posture and carries the ordering the
reviewer measured to work — close a widened posture back to `invite_only`
BEFORE the invited person registers. All three copies (the string literal,
the block comment, the changeset) are aligned again.
Also folded in from the same review:
- N2: the invitation `email` must be stored LOWERCASE. `hasPendingInvitationFor`
searches `where: { email: target.toLowerCase() }`, so a mixed-case row is
never found and the sign-up is refused SELF_REGISTRATION_CLOSED — a silent
dead end the line was sending operators into.
- N1: `(INVALID_EMAIL_OR_PASSWORD)` is row-shape-dependent — an issuer-less
hand-written row answers 401, a fully-shaped one with a plaintext password
answers 500. Widened to "a 401 or a 500 depending on the row shape, never a
session", which holds for both.
- N3: dropped the "next boot" timing claim; under `single` the holder is
usually promoted at the sign-up itself. The outcome is unchanged, so the
line now states the outcome and not the timing.
Five new pins, because the clause that was wrong is the one nothing guarded:
the scoped phrasing itself; a widened posture admitting the invited creation
AND still forcing verification on it (the two mechanisms driven together,
since the false claim was that the first cancels the second); only the default
posture being mail-transport-free; the structural fact that an admission
verdict carries no field that could exempt verification; and N5 — every
widening posture in `AUDIENCE_POSTURES` is named in the message, read off the
vocabulary so a fourth one cannot leave the line silently stale.
⛔ Still message-text only: no admission semantics, no probe change, sign-up
path untouched.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
* fix(plugin-auth): say remedy (b) cannot recover an EXISTING person at all
Input from #15587's dev, who searched before concluding it: that fix does not
make this remedy true, it makes it fail HONESTLY — the person still cannot
register a login, and for an EXISTING person that is by design, not by defect
(#14349 is closed on option A, the door stays shut, which the line above
already cites).
The previous wording rested entirely on forced email verification. That is the
story for a NEW address. The operator reading this line is usually trying to
recover somebody the directory already holds, and for them the posture is not
the lever at all: self-registration is a user-CREATION path, so it cannot hand
a login to an address that already carries a `sys_user` row, whatever the
posture. Both failures are real; they are different failures, and the more
likely one was missing.
⛔ Stated in MECHANISM terms, deliberately. #15587 is a draft under review, so
this line asserts no wire status for that refusal — the M2 pin that forbids
USER_ALREADY_EXISTS / "answers 200" / "persists nothing" / "no new row" in
this message stays green, and the new clause is written to keep it that way.
Two more pins: the gate ADMITS this address under `open` with no invitation at
all — which is what shows the posture is not what stops an existing person,
since whatever refuses them sits downstream of it — and the message states the
mechanism rather than a status code.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XpTx2tbq3pZRYAdoGt6E6Y
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent d21ddbb commit 8e500f2
3 files changed
Lines changed: 378 additions & 10 deletions
File tree
- .changeset
- packages/plugins/plugin-auth/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
Lines changed: 281 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
29 | 35 | | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
30 | 42 | | |
31 | 43 | | |
32 | 44 | | |
| |||
117 | 129 | | |
118 | 130 | | |
119 | 131 | | |
120 | | - | |
| 132 | + | |
121 | 133 | | |
122 | | - | |
123 | | - | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
124 | 145 | | |
125 | 146 | | |
126 | 147 | | |
127 | 148 | | |
128 | 149 | | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
129 | 183 | | |
130 | 184 | | |
131 | 185 | | |
| |||
163 | 217 | | |
164 | 218 | | |
165 | 219 | | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
166 | 444 | | |
167 | 445 | | |
168 | 446 | | |
| |||
0 commit comments