{
  "schema": "leumas.docs.page/1",
  "id": "how-to:accounts",
  "slug": "how-to/accounts",
  "kind": "pages",
  "bucket": "how-to",
  "title": "Build-knowledge — accounts: creating one, and which door your install opens",
  "name": "accounts",
  "eyebrow": "build knowledge",
  "chip": null,
  "summary": "The rule behind the table: password signup is open everywhere except the public platform. The deployment's role decides it, and an operator can override it with LEUMAS_PUBLIC_SIGNUP.",
  "keywords": [
    "accounts",
    "sign in",
    "google sign-in",
    "create an account",
    "first run",
    "leumas accounts",
    "how to create a leumas account",
    "password signup"
  ],
  "audience": "both",
  "funnel": {
    "product": null,
    "cta": null
  },
  "body": "# Build-knowledge — accounts: creating one, and which door your install opens\n\n> There are exactly four ways an account comes into existence, and **which one is available is\n> decided by the deployment, not by a setting you pick**. Knowing which kind of Leumas you are\n> looking at answers almost every question about signing in.\n\n## Which Leumas am I looking at?\n\n| You are on | What it is | How you get an account |\n|---|---|---|\n| `leumas.tech` | The public platform, run by Leumas | **Continue with Google.** The password form is closed here |\n| `studio.leumas.tech` | The same platform's Studio | The same Google account |\n| **Leumas Studio on your own machine** | The desktop app — your own instance, your own database | The **first-run wizard**, then email + password for anyone you add |\n| Your own server running Leumas | A self-hosted install | Same as the desktop app |\n\nThe rule behind the table: password signup is open **everywhere except the public platform**. The\ndeployment's role decides it, and an operator can override it with `LEUMAS_PUBLIC_SIGNUP`.\n\n## Creating an account on leumas.tech\n\nUse **Continue with Google**. There is no password form to find, and asking for one returns a refusal\nthat says so: *\"Accounts here are created with Google — use 'Continue with Google'.\"*\n\nTwo things surprise people, and both are deliberate:\n\n**You get a member account, never an admin one.** Signing in with Google grants exactly one role,\n`user`. On a desktop install the first account becomes that install's administrator — but applying\nthat rule to a public platform would mean the first stranger to click the button owned the instance.\n\n**Staff accounts cannot use Google at all.** An account holding `admin` or `leumas_staff` is\nrefused at the Google door — before any write, and before any cookie is set — and sent back with\n`staff_password_only`. Those accounts sign in with a password. This is one-directional on purpose:\nit stops a staff identity being reachable through an external provider.\n\nSign-in is also **origin-locked**. Only the platform's own front doors may start a Google sign-in;\na tenant's subdomain never can, and a guard asserts that refusal still happens.\n\nAlready have a password account from before Google sign-in existed? **Signing in still works.** Only\n*signup* is closed on the platform, never login.\n\n## Creating an account in Leumas Studio (your own copy)\n\nThe first time you open Studio it does not show you the app. It checks two things — whether this\ninstall has a licence, and whether it has any accounts yet — and shows a first-run wizard until both\nare answered. Which wizard you get depends on how the build was made:\n\n**One step, if your Studio points at the Leumas platform.** Enter the email and password of your\nleumas.tech account. Studio verifies it against the platform, saves the licence for this device, and\nsigns you in. There is no licence key to find and no second password to choose.\n\n**Two steps, otherwise.** Enter a licence key in the form `LEUMAS-XXXX-XXXX-XXXX-XXXX`, then create\nthe local administrator. That account **lives only on that machine** and controls that Studio.\n\nEither way the account you end up with is that instance's `admin`. Adding teammates afterwards uses\nthe ordinary email-and-password signup, which is open on a desktop install.\n\n## What protects the first-run wizard\n\nOnly one thing, and it is worth understanding rather than trusting: **the wizard is available only\nwhile the account table is completely empty.** The check is re-run inside the same transaction that\ncreates the account, so two people racing it cannot both win. Once one account exists, it is a hard\nrefusal for everyone — including whoever ran it: *\"already set up — an account exists on this\ninstance.\"*\n\nOn the desktop app there is a second, stronger protection that is easy to miss: **the Studio API\nbinds to loopback only.** Nothing on the network can reach it, so \"a stranger\" would already have to\nbe sitting at your keyboard.\n\n[warning] **That protection is a property of the desktop build, not of the wizard.** If you run the API\nyourself on a public address with seeding disabled, the empty-table race is all that stands between\nthe internet and the first-run wizard, and the endpoint that reports \"setup needed\" is public. Bind\nit to loopback, put it behind something that authenticates, or complete the wizard immediately.\n\nPasswords must be at least ten characters. That is enforced on the wizard and on signup alike.\n\n## The roles, and what they actually mean\n\n| Role | Means | Granted by |\n|---|---|---|\n| `user` | A member | Every signup path |\n| `admin` | **This instance's** administrator — not \"Leumas the company\" | The first-run wizard, or the boot seed |\n| `leumas_staff` | The vendor axis: Leumas staff, on the control plane | The seed, and only on a control-plane deployment |\n| `developer`, `verifier` | Narrower grants used by specific surfaces | — |\n\n`admin` holds every permission that exists on its own instance. That is precisely why staff is\nchecked by **role** and never by permission — an instance administrator having \"all permissions\"\nmust not become a way to hold vendor authority.\n\n`leumas_staff` refuses to be granted on any deployment that is not the control plane, and the\nread-side check requires it too. A control-plane backup restored onto a customer's machine therefore\ndoes not hand that customer a vendor account.\n\n**There is no \"promote a user to admin\" screen, and no endpoint that grants a role.** The admin API\ncan list, read, patch and delete users, grant and revoke membership, and adjust tokens — but role\nassignment happens at signup and at seed time only. If you need a second administrator today, that\nis a gap, not a setting you have failed to find.\n\n## Signing in from a site you host\n\nA website served by Imperium on a Leumas subdomain is **same-origin with the API**, because the\nworker forwards `/auth`, `/membership`, `/tokens` and `/entitlements` to it while preserving the\nvisitor's host and cookies. A page on your site can therefore read the visitor's session with no\nconfiguration and no API key — which is the whole reason the hosting lane is shaped that way.\n\n## Related\n\n- [Imperium hosting](imperium-hosting.md) — putting a site on the internet once you have an account.\n",
  "source": {
    "path": "shared/services/knowledge/build-knowledge/accounts.md",
    "blobSha": "",
    "commit": "",
    "committedAt": "",
    "provenance": "no-git",
    "bytes": 6524,
    "hash": "07ccae81fb370aab3807b8bd9feca341792a29e5"
  },
  "urls": {
    "html": "/p/how-to/accounts",
    "json": "/docs/how-to/accounts.json",
    "md": "/docs/how-to/accounts.md"
  },
  "links": {
    "composes": [],
    "usedBy": [],
    "product": [],
    "howTo": [],
    "skills": []
  }
}
