Organizations and Location Belong in Identity
Once Person and User Account are separated, organization membership stops looking like a boolean on a profile row.
A person can be an employee of one company, a contractor of another, and a customer of a third — while using one or more user accounts. Location is not “address string on user” either: devices, people, and orgs all sit in geography.
This chapter is the context layer of the book: who someone is at work, and where things happen.
Organization is not a user with a flag
Organizations have their own lifecycle: industry, type, legal name, tax id, parent org for hierarchies, status history.
Organization
├── parent (optional hierarchy)
├── industry / type
├── legal identity fields
└── status + history
Employees are the relationship between Person and Organization — with position, department, hire window, and org-scoped contacts.
That mirrors the citizenship lesson: membership is a relationship aggregate, not organization_id alone on Person forever.
Why employee contacts are separate
Work email and work phone are not the same channels as personal contacts on a user account. Modeling organization-employee contacts keeps verification and disclosure boundaries sane when someone leaves a company.
Location as a domain, not a text column
Geo in this service is structured:
| Layer | Role |
|---|---|
| Country / subdivision / city | Reference data |
| Location | Point-ish entity with encrypted coordinates |
| Search / proximity tokens | Blind lookup without plaintext coords in indexes |
| Device session geo hints | Risk and context, not a second address book |
Device sessions can reference country, subdivision, and city. Locations can store encrypted coordinates plus search tokens (rounded coords, proximity hashes) so “near me” features do not require decrypting the world on every query.
What this prevents
| Shortcut | Bill that arrives later |
|---|---|
company_name on users | Mergers, legal names, multi-entity employers |
One address text field | Normalization, privacy, proximity search |
| Roles only on JWT claims | No hire/leave history, no org tree |
| Orgs in another service too early | Split-brain identity for the same human |
Status history as a pattern
Persons, contacts, sessions, organizations, employees — many aggregates carry status plus a history table driven by shared trigger patterns. Identity is not only the current row; it is why and when state changed.
That matters for KYC, support, and security investigations more than for pretty profile pages.
Takeaway
Identity is the place where real-world structure meets system access. Organizations and geography are part of that structure. Pushing them out as afterthoughts recreates the flat users table — just with more JSON.
Next
The backend can be correct and the product still broken if the edge mishandles two cookie layers. The last chapter is the Next.js session edge.
Continue with Frontend Session Edge.