How accounts and tenants relate, the roles inside a tenant, and how tenants are kept apart.
An account belongs to a person; a tenant is an organisation, a team or a project. A membership joins the two, and one account can belong to several tenants. The role is decided per membership, so the same person can be an owner in one tenant and an ordinary member in another.
The role is per membership and comes back as TenantService/ListMyTenants in tenants[].myRole.
| Value | Called | What it means |
|---|---|---|
OWNER | Owner | Runs the tenant: invites, role changes, removals, settings and API keys |
MEMBER | Member | Belongs to the tenant. Looks after their own settings |
Only the tenant the session has selected is ever operated on. The selection lives on the session and is changed with TenantService/SelectTenant. Other tenants' data does not appear in listings and cannot be fetched by naming an id directly.
The boundary is applied at the database query, so there is nothing to filter on your side. If the membership goes away, the selection reads as "none" from the next request onwards.
# Tenants this account belongs to, and its role in each
curl -X POST https://api.albos.org/auth.v1.TenantService/ListMyTenants \
-H "Content-Type: application/json" \
-H "X-API-Key: ca_..." -d '{}'
{
"tenants": [
{ "id": "...", "name": "A社", "myRole": "OWNER",
"memberCount": 12, "maxMembers": 50, "memberLeaveMode": "FREE" }
],
"selectedTenantId": "...",
"remainingTenantAllowance": 2
}| Operation | Owner | Member |
|---|---|---|
| Signing in to the dashboard | ○ | ○ |
| Authenticating through the API | ○ | ○ |
| Inviting members | ○ | — |
| Changing roles and removing members | ○ | — |
| Changing the tenant name and how members leave | ○ | — |
| Setting the security policy | ○ | — |
| Issuing and revoking API keys | ○ | — |
| Deleting the tenant | ○ | — |
| Posting announcements to the tenant | ○ | — |
| Leaving the tenant | ○ | ○ |
| Editing your own profile | ○ | ○ |
| Managing your own second factor and sessions | ○ | ○ |
| Deleting your own account | ○ | ○ |
| Item | Default | Code when exceeded |
|---|---|---|
| Tenants one account may create | 3 | resource_exhausted |
| Members in one tenant | 50 | resource_exhausted |
| Outstanding invitations | 50 per account | resource_exhausted |
An owner invites by entering an email address in the dashboard. The invited person joins by signing in with the Google account for that address. No password is set.
| Step | What happens |
|---|---|
| 1. Issue | The owner enters an address; the link appears straight away |
| 2. Hand over | Sent by email when delivery is configured; otherwise pass the link on yourself |
| 3. Join | The invited person signs in with Google and joins as a member |
| 4. Promote (if needed) | The owner changes them to OWNER from the member list |
Every tenant has a QR code, and whoever scans it can ask to join. Unlike an invitation sent to a named address, joining this way needs the owner's approval.
| Step | What happens |
|---|---|
| 1. Show | The owner shows or sends the QR code from tenant settings |
| 2. Scan | The join page opens and names the tenant |
| 3. Request | They sign in with Google and apply; an account is created if they have none |
| 4. Approve | The owner approves the request from the member list |
The code carries nothing but the tenant's id and is not a secret. Because approval sits in the way, a code that reaches the wrong hands produces a request, not a membership. It therefore has no expiry and no usage limit; stop accepting requests from tenant settings when you want it closed.
| Route | Approval | Why |
|---|---|---|
| Invited by the owner | Not needed | Naming the address is already the owner deciding who it is |
| QR code | Needed | Nobody knows who scanned it, so the owner decides against a real account |
From "Tenant settings" in the dashboard, an owner can set rules that apply to the members of their own tenant. Everything starts at the default, and nothing changes until it is set.
| Item | What happens | When it applies |
|---|---|---|
| Permitted email domains | Only addresses on those domains may join | When an invitation is issued and accepted |
| Password requirements | Minimum length, upper case, digits, symbols | When a password is set, changed or reset |
| Session lifetime | In days (14 by default) | At sign-in |
Signing in says who somebody is. It does not say that the person at the keyboard right now is still them. For the screens that reach other people's names and contact details, and for the operations that cannot be undone, the account is asked for its authenticator code once more.
| When | What is asked |
|---|---|
| Opening the member list, tenant settings or API keys | A code, once per sign-in |
| Deleting a tenant, handing over ownership, issuing a key, changing a password | A code from within the last 15 minutes |
| Inviting a member, approving a join request | A sign-in the provider vouched for, or a password sign-in that cleared a code |
A key is fixed to the tenant it was issued for. Unlike a person's session it cannot switch tenants, so a leaked key cannot reach around into another one. Issue a separate key per tenant.
| Rule | Detail |
|---|---|
| What it may do | READ_ONLY by default — verifying tokens and reading membership. READ_WRITE has to be chosen when the key is issued. |
| How long it lasts | 30 days if you do not say, 90 at the most. There is no key without an expiry. |
| Replacing one | Issue the new key, move the integration over, then revoke the old one. Every plan allows at least two at once so this needs no downtime. |
| Rate limit | Counted per key, separately from the per-address limit. |
Issuing and revoking keys, and changing the issuer's own password or deleting their account, cannot be done with a key.
The service operator holds separate administrative accounts for incidents and enquiries. Those accounts do not belong to any tenant. They cannot create one and cannot accept an invitation, so nobody supervising a tenant is also party to it.
What the operator does to an account is recorded with the target, the time and who did it, and cannot be deleted.