- Ya
- 24 Agosti 2026, 21:02 UTC
- Mwandishi
- Kamo
- Ahadi ya
- 8e02ec0
Signing in was two questions fused into one query. "Are these credentials good" is answered by the users row -- the password lives there, so it was never org-scoped. "May this account enter that workspace" is answered by the members rows. ACCOUNT_QUERY_PREFIX INNER JOINs both memberships, so the hostname was only ever supplying the second answer, and a member with no resolvable host could not be asked the first. Adds authenticateUser(identifier, password), authorizeIntoOrg(userId, orgId) and enterableOrgs(userId) alongside the existing three-arg method, which is untouched. Pushing deploys, and that method is the live login path for every organization, so it keeps its own query until nothing calls it. The distinction worth protecting is absent-versus-inactive. The joined query gives a non-member zero rows and the generic "user does not exist or password is incorrect" -- it never confirms the account is real. A membership that exists but is switched off gets its own sentence. authorizeIntoOrg looks the two memberships up separately so it can tell those apart and reproduce both, rather than collapsing them into one message that would either leak that an account exists or hide why a real member cannot get in. enterableOrgs returns the enterable set, not the membership set: an org appears only when the user also holds an active membership in whoever provides its security, so the picker cannot offer a workspace that authorizeIntoOrg would then refuse. m.is_active is the record-state column behind **************** so that gate comes along with it. Also stamps users.last_org_id on a real sign-in, following the rule last_login already documents: impersonation and enter-as do not stamp, because recording an administrator-driven destination would make the picker open somewhere the member never chose. 886 tests pass.