> ## Documentation Index
> Fetch the complete documentation index at: https://docs.impellabs.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# End users

> Your users, as principals the platform can answer safely.

Some products put the assistant in front of **their own users** rather than in
front of the public: a learner asking about their course, a parent asking how
their child is doing, a rep asking about the accounts they own.

That is a different problem from a website visitor. A visitor is anonymous and
every answer is public. A named user has material that is theirs, and material
that belongs to somebody else standing right next to them.

<Warning>
  If your product has end users who must not see each other's data, read this
  page and [Permissions](/concepts/permissions) before you connect anything.
  The default for a workspace is that everything in it is answerable — which is
  correct for a shop and wrong for a school.
</Warning>

## A principal is one of your users

You register them by **your** id. The platform stores no vertical vocabulary:

```json theme={null}
{
  "external_id": "stu_88120",
  "kind": "student",
  "display_name": "Aarav S",
  "attributes": { "branch": "kochi", "batch": "2024-B" }
}
```

`kind` is a slug **you** choose. The platform never branches on its value, so
`student`, `vice_principal` and `account_manager` are all equally ordinary. A
school with six staff levels and a CRM with two do not need different releases.

<Note>
  `attributes` is for prompting and reporting only. It is **never** consulted
  to decide what someone may see — that is what a grant is for. A JSON blob
  that quietly becomes a permission system is a permission system nobody can
  audit.
</Note>

### Principals are not leads

The platform already models a **customer** (a person) and a **lead** (a sales
record) — see [Identity](/concepts/identity). A principal is neither.

A lead requires a phone number, dedupes on it, and carries `do_not_call`.
Registering eight hundred students as leads would poison every one of those
behaviours. They stay separate, and a principal may optionally point at a
customer when the same human is both — a parent who also enquired about fees.

## One person, many channels

An identity maps a channel handle to a principal, so the same person reached on
WhatsApp and on the web is one principal rather than two.

```
Principal  stu_88120
 ├── identity  partner   · stu_88120     (verified)
 ├── identity  email     · a@example.com (verified)
 └── identity  whatsapp  · 9198…         (unverified)
```

<Warning>
  An **unverified** identity never contributes a grant. Anyone can claim a
  phone number; only an identity your backend asserted over an authenticated
  call, or one the platform actually verified, may stand behind access to
  somebody's records.
</Warning>

## The session token

Your backend mints a short-lived token for the user whose browser is about to
talk to the assistant. The browser presents it; it cannot mint its own.

```bash theme={null}
X-Tegain-Subject: <token>
```

Deliberately **not** the `Authorization` header, so a session token can never
be mistaken for a workspace key (`tgcc_…`) or a partner key (`tgpk_…`), and a
mix-up cannot silently escalate.

| Property         | Value                                       |
| ---------------- | ------------------------------------------- |
| Algorithm        | HS256, `typ: tgs+jwt`                       |
| Default lifetime | 15 minutes                                  |
| Maximum lifetime | 1 hour                                      |
| Refresh ceiling  | 12 hours, then your backend must mint again |

### It carries no entitlements

The token names a person. What that person may reach is read from the database
on every request instead.

<Note>
  This is the decision the rest of the design hangs on, and the reason is
  revocation: a grant withdrawn at 10:00 stops applying at 10:00, not whenever
  a token happens to expire. A learner enrolled in forty units would also carry
  forty ids in a header on every request, and a credential sitting in a browser
  should have the smallest blast radius available. "Names a person" is smaller
  than "enumerates their access".
</Note>

A token does carry the user's role names, for readable logs. Those are
telemetry and are never read to decide access.

### Refreshing cannot widen access

A live token can be exchanged for a fresh one until the refresh ceiling. The
replacement is built from the stored record, never from the presented claims —
so a withdrawn grant does not survive a refresh, and a tampered token that
somehow verified would still only get back what the database says.

## Asking about somebody else

A parent's session is *about* their child. The asker and the subject are
different people, and both matter:

* **Knowledge** is filtered by the **asker**. A parent reads the parent
  handbook, not the marking scheme.
* **Records** are reachable for the **subject**, and only where an explicit
  grant says so.

The two never merge. A parent allowed to ask how their child is doing does not
thereby inherit the child's coursework. If you want that, grant it explicitly —
one line in your sync, and auditable afterwards.

<Card title="How access is actually decided" icon="lock" href="/concepts/permissions">
  Grants, roles, deny rules, and what retrieval does with them.
</Card>
