Use this skill for concrete user-account work.
First Check
- Call
const info = await space.api.userSelfInfo(). - Confirm
info.groups.includes("_admin") === true. - Prefer logical app paths derived from the standard layer rules, not guessed disk paths.
Canonical User Tree
L2/<username>/is the user's logical root.L2/<username>/user.yamlstores user metadata such asfull_name.L2/<username>/meta/password.jsonstores the backend-sealed SCRAM verifier.L2/<username>/meta/logins.jsonstores signed session verifiers.L2/<username>/mod/is that user's customware module root.
There is no separate user registry file. The watched user index is derived from files under L2/<username>/.
Path Rules
- Use logical paths such as
L2/alice/user.yaml. - When writable storage is relocated under
CUSTOMWARE_PATH, these logical paths stay the same. fileWrite(".../")creates a directory because the path ends with/.- Do not hand-craft
meta/password.jsonor individual session entries. Usepassword_generatefor password records and only write{}when revoking sessions.
Create A User
Use a normalized username segment such as alice, ops_bot, or qa-team-1.
const username = "alice";
const fullName = "Alice Example";
const password = "replace-me";
const verifier = await space.api.call("password_generate", {
method: "POST",
body: { password }
});
return await space.api.fileWrite({
files: [
{ path: `L2/${username}/` },
{ path: `L2/${username}/mod/` },
{
path: `L2/${username}/user.yaml`,
content: space.utils.yaml.stringify({ full_name: fullName })
},
{
path: `L2/${username}/meta/password.json`,
content: `${JSON.stringify(verifier, null, 2)}\n`
},
{
path: `L2/${username}/meta/logins.json`,
content: "{}\n"
}
]
});
Update User Metadata
Read user.yaml, parse it, mutate the fields you need, and write it back.
const path = "L2/alice/user.yaml";
const current = await space.api.fileRead(path);
const config = space.utils.yaml.parse(current.content || "");
config.full_name = "Alice Example";
return await space.api.fileWrite(path, space.utils.yaml.stringify(config));
Reset A Password
Generate a fresh sealed verifier first, then overwrite meta/password.json.
const verifier = await space.api.call("password_generate", {
method: "POST",
body: { password: "new-password" }
});
return await space.api.fileWrite(
"L2/alice/meta/password.json",
`${JSON.stringify(verifier, null, 2)}\n`
);
Revoke Sessions
Overwrite L2/<username>/meta/logins.json with {}.
return await space.api.fileWrite("L2/alice/meta/logins.json", "{}\n");
When resetting a password, prefer writing the new verifier and clearing logins.json in the same batch. Do not attempt to preserve or invent individual session entries.
Remove A User
Deleting L2/<username>/ removes the local account tree:
return await space.api.fileDelete("L2/alice/");
Deleting a user root does not rewrite L1/*/group.yaml automatically. If the user should disappear from memberships or manager lists too, load admin-user-management/groups and remove that username from the affected group configs.
Guest Accounts
guest_createis the dedicated endpoint for guest creation when the runtime allows it.- Do not hand-roll a
guest_account unless the user explicitly wants a normal local user whose name happens to start that way.
CLI Reference
Backend equivalents exist for operators outside the browser:
node space user create <username> --password <password> [--full-name <name>]node space user password <username> --password <password>
From the overlay agent, prefer the browser APIs above.