Skip to content

plugin-auth: both remedies in the no_sign_in_account_at_boot report are unexecutable as written — and one of them silences the report #15588

Description

@claude

Found while measuring the recovery path for #14495 (docs card); filed unassigned and unlabeled for triage.

boot-sign-in-reachability.ts (landed for #14353) ends its error line with two remedies. Measured on the exact population the report fires on — real ObjectQL over better-sqlite3, three human sys_user rows, zero sys_account rows, NODE_ENV=test, default invite_only — neither remedy does what its sentence says.

Remedy (2): "OPEN THE AUDIENCE POSTURE ... so an existing person can register their own login"

An existing person cannot.

POST /sign-in/email  -> 403 {"code":"EMAIL_NOT_VERIFIED"}

On a deployment with no mail transport wired — which is the shape a locked-out self-hosted install usually is — remedy (2) therefore produces no login at all.

Remedy (1): "write a sys_account credential row for one of the existing sys_user rows directly against the store"

The row shape is public; the format of the secret in its password column is the platform's own. A row carrying a plaintext password authenticates nothing:

POST /sign-in/email  -> 401 {"code":"INVALID_EMAIL_OR_PASSWORD"}

…and it SILENCES this very diagnostic, because probeSignInAccountsPresence asks only whether any sys_account row exists:

probeSignInReachability -> {"humanUsers":"present","signInAccounts":"present"}

So the operator's first attempt at the named remedy turns the loud dead end back into the silent one it was written to end, with nobody able to sign in.

What does work (measured, same population)

Insert one pending sys_invitation row (email — an address the directory does not already hold, status: 'pending', a future expires_at, inviter_id of any existing sys_user), then have that person register through the ordinary sign-up endpoint. The invitation carve-out admits that one creation under every posture, no door is widened, no mail transport is needed: sign-up 200, sign-in 200. On the single posture the next boot's bootstrapPlatformAdmin then promotes that account holder (adminPromoted: true).

That path is now documented on content/docs/deployment/self-hosting.mdx by #14495's PR. This card is the runtime half: the message an operator reads at boot should name a remedy that works, and should not describe one whose first step blinds the check.

Suggested acceptance

The report's remedy text names the invitation row as the primary way out, states that a hand-written credential row must carry the platform's own password hash (and that writing one silences this report), and states that widening the audience posture forces email verification. Message-text only — no admission semantics move, exactly as #14353 scoped itself.

Refs: #14353 (this diagnostic) · #14349 (option A, ruled) · #14495 (the docs half) · #15587 (the phantom 200).


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions