---
title: Companies and users
section: Install and operate
order: 41
summary: Running more than one company on an install, letting more than one person sign in, and using the activity log to see who changed what.
---

These are two separate settings. Multi-company means one person keeping several
companies on a private install, and says nothing about sharing it or putting it
on a network. Multi-user means several people signing in to the same
self-hosted install, and each of them can work in all of its companies.

## More than one company

Each company is walled off from the others. Evidence, journals, knowledge
documents, calculations, and conversations all belong to one company, and none
of it is copied between them. A new company starts empty: no documents,
knowledge, mappings, accounts, journals, assumptions, forecasts, or
conversations.

### Switching companies

The account menu lists the companies you can open, with the current one
marked. Pick another and everything company-specific reloads: conversations,
documents, knowledge, accounting, calculations, usage, and settings.

Your current company is remembered in an HTTP-only, same-site cookie. The
cookie only records a preference; it doesn't grant access. Access is checked on
every request, and if the cookie points at a company you can't open (or one
that no longer exists), you land on the first company you can.

### Adding a company

Choose **New company** in the account menu and enter a name and base currency.
Balsa creates the company and your membership in a single transaction,
switches to it, and opens its empty onboarding screen.

### COMPANIES

You can also list companies ahead of time in `COMPANIES`, as comma-separated
`Name` or `Name:CUR` entries:

```bash
COMPANIES=Acme Holdings:USD,Beta GmbH:EUR
```

They're created for the install's owner on first sign-in, and the first one
becomes the default. If you add names later, they're created at the next
sign-in. Editing or removing an entry won't rename or delete an existing
company; changing the list only ever adds.

### How companies are kept apart

There are two layers. First, the application checks that any record id sent in
a request belongs to the current company before using it. Second, PostgreSQL
row level security enforces the company scope when a transaction sets it. The
current policies permit unscoped access when no scope is set, so application
ownership checks remain necessary. Database enforcement also requires a
non-superuser role without `BYPASSRLS`. See [Security](/docs/security/).

## More than one person

Set `AUTH_MODE=better-auth` and choose an `AUTH_SIGN_UP_CODE`. Share the code
with the people who should have access, turn on `AUTH_ALLOW_SIGN_UP` while they
register, then turn it off again.

Be clear about what signing up gets someone. On a self-hosted install, every
registered user can open every company, including ones created later, and can
create new companies. There's no step where you add someone to a company; a
second user sees the same list as the first. There are no invitations and no
way to give someone narrower access.

So letting someone register means giving them every company's financial data on
that server. If that's not what you want, run separate installs.

Balsa doesn't send email. The sign-up code controls who can register, and
anyone registered can work in the install.

### Roles

Each membership has a role, `owner` or `member`. Owner-only routes are checked
on the server and return 403; they aren't just hidden in the UI.

| Right | Owner | Member |
| --- | --- | --- |
| All financial work: evidence, chat, knowledge, journals, close, forecasts | yes | yes |
| Company settings (name, currency, favicon) | yes | no |
| Reset (delete) the company | yes | no |
| Create a new company | yes | yes |

On a self-hosted install today, every membership is an owner membership, so the
member column doesn't come into play. The server-side check is there so that
hiding a button isn't the only protection, and so it's ready if membership ever
becomes per-company.

## Activity log

Since everyone on an install has the same access, the log is how you tell who
did what. Each meaningful change records who made it, how it came in, what the
action was, which record it touched, a summary, and the before and after
values. When the change runs in a transaction, the log entry is written in that
same transaction, so both are saved or neither is.

The `via` field shows how a change came in:

- `ui`: someone did it directly.
- `agent`: the agent did it at someone's request, and it's attributed to that
  person.
- `worker`: a background job did it, with no person attached.

Logged actions include approving or rejecting evidence, applying or rejecting a
decision, answering a review question, posting and reversing journals, closing
and reopening periods, creating or changing a policy, changing company
settings, creating a company, and editing knowledge.

**Activity** in the account menu shows the current company's log, newest first,
with each person's name and email. Only members of that company can see it.

Records also store their own author, separate from the log. Decisions, resolved
review items, economic items, closed periods, and knowledge documents each note
who acted, and traces that show an approval or decision show that person's name.

Resetting a company deletes its log along with everything else.


## Review ownership is separate from access

A financial work review records its preparer, assigned reviewer and exception
owners. Only the assigned reviewer can sign a submitted report, even on an
installation where users have owner memberships. The preparer or a company owner
can manage assignments. Self-review requires explicit acknowledgement.

These assignments organize accountability; they do not hide company data from
other admitted users. See [Reviews and sign-off](/docs/reviews-and-signoff/).
