mirror of
https://github.com/HeyPuter/puter.git
synced 2026-09-30 00:56:50 +00:00
feat: a team seat needs no email address, and is never asked to confirm one
PUT-1792. Two separate problems, both from treating a provisioned account like a self-registered one. `email` was required, so an admin creating ten seats had to invent ten addresses and then keep track of ten uniqueness constraints -- for accounts that sign in by username and never use the address. It is now optional at every layer, and the add-account form does not ask for it at all: username is the only thing a seat needs. `requires_email_confirmation` was set to true, with the reasoning that an admin-supplied address is unverified. True, but `requireVerifiedAccount` turns away on exactly `requires_email_confirmation && !email_confirmed`, so a freshly created seat was asked to confirm an address it may not hold and could not use the product until it did. The team creating the account is the trust anchor, not the mailbox, so this is now false either way. An address is still accepted and still stored when given, because the notices are worth delivering. `#notifyUser` already returned early on a missing address, so `team_account_created`, `team_account_disabled`, `team_password_reset` and `team_closed` degrade quietly with no new branching -- the temporary password is in the API response, which is the documented delivery. `idx_user_owned_email` is partial and skips password-null rows, so omitting the address sidesteps it rather than creating a collision surface. Two seats with no address do not conflict, and there is a test for it. Docs now say an emailless seat is recoverable only through its team's owner. That falls out of the design rather than being a limitation of this change, but it should be written down rather than discovered. Falsified: putting `requires_email_confirmation: true` back fails "never demands confirmation, with or without an address" with `expected true to be false`, and nothing else. 164 team tests, 40 SDK tests, typecheck clean.
This commit is contained in:
@@ -28,9 +28,13 @@ The team's identifier.
|
||||
|
||||
The username for the new account. Usernames come from the same pool as ordinary sign-ups, so it must be free across the whole of Puter.
|
||||
|
||||
#### `options.email` (String) (required)
|
||||
#### `options.email` (String) (optional)
|
||||
|
||||
The address the member is reachable at. It must not already own an account. The address came from the administrator rather than its holder, so the account is created needing email confirmation.
|
||||
Where the team's notices about this account are delivered. These accounts sign in by **username**, so an address is not needed and the form does not ask for one.
|
||||
|
||||
Supply it only if you want `team_account_created`, `team_account_disabled` and `team_password_reset` to reach the member; if you leave it out, those notices are simply not sent and the temporary password in the return value is the only delivery. If given, it must not already own an account.
|
||||
|
||||
The account is never asked to confirm the address — the team creating it is the trust anchor — so it can be used immediately either way. An account with no address is recoverable only through its team's owner, via `resetPassword`.
|
||||
|
||||
## Return value
|
||||
|
||||
@@ -53,7 +57,6 @@ Rejects with `username_already_in_use` — with free alternatives in `fields.sug
|
||||
const name = 'member' + Math.random().toString(36).slice(2, 8);
|
||||
const account = await puter.teams.createMember(team.uid, {
|
||||
username: name,
|
||||
email: `${name}@example.com`,
|
||||
});
|
||||
// Shown once; hand it over out of band.
|
||||
puter.print(`${account.username}: ${account.temporaryPassword}`);
|
||||
|
||||
Reference in New Issue
Block a user