ERS Person, Collaborator, Authorization, and Authentication Model - RodrigoMattosoSilveira/EnterpriseRemoteSystems GitHub Wiki
ERS separates five concepts that are often combined in simpler applications:
Person β the real human being and their personal record.
Collaborator Journey β a period during which that Person works for a tenant.
Authorization Actor β the identity to which ERS assigns roles and permissions.
Authentication Account β the login credentials that authenticate as one Actor.
Session β a temporary authenticated browser connection for one account.
Authorization itself is not one record. It consists of:
Authorization Actor
Role
Permission
RoleβPermission assignment
ActorβRole Grant
Authorization Audit Log
The central relationship is:
Human/operational identity Access identity
Tenant
β
βββ Person
β β
β βββ Collaborator Journey
β
βββ Authorization Actor
β
βββ Actor Role Grant ββ Role ββ Role Permission ββ Permission
β
βββ Authentication Account
β
βββ Authentication Session
βββ Password Reset Token
A more precise cardinality model is:
Tenant 1 βββββββββββββββ 0..* Person
Person 1 βββββββββββββββ 0..* Collaborator Journey
but normally no more than one active journey
Authorization Actor 1 β 0..* Actor Role Grant
Role 1 ββββββββββββββββ 0..* Actor Role Grant
Role * ββββββββββββββββ * Permission
through Role Permission
Authorization Actor 1 β 0..1 Authentication Account
Authentication Account 1 β 0..* Session
Authentication Account 1 β 0..* Password Reset Token
A Tenant is the organizational and data-isolation boundary.
Examples might include:
Tenant A
Tenant B
Default Tenant
A tenant owns or scopes operational records such as:
People
Collaborator Journeys
Reference Data
Expenses
Price Lists
Gold Prices
Work Periods
Work Period Assignments
Gold Production
Current Accounts and ledger entries
Receipts
Accruals and settlements
Tenant settings
The major operational domains have been corrected to use the selected tenant consistently.
A tenant has:
Immutable internal
idHuman-readable
codeName
Description
Active state
The tenant ID, not the tenant code, is the authorization and API scope identifier.
A tenant can be:
Active and operational
Active but without a Tenant Administrator
Inactive
Deactivating a tenant preserves its historical records.
An inactive tenant generally remains readable for audit purposes, but ordinary tenant-scoped writes are blocked.
Tenant-scoped role grants reference one real tenant ID.
Application-scoped grants use:
*
The * value means application-wide scope. It is not an actual tenant.
A Person is the authoritative record for a real human being within one tenant.
It answers:
Who is this human being?
It does not by itself mean that the Person:
works for the organization;
has system permissions;
has a login;
can authenticate.
A Person contains:
Tenant
First name
Last name
Nickname
CPF
RG
Cellular number
Email
Address
Bank information
PIX key
Emergency contact
Person status
Notes
Profile-completion state
CPF, RG, cellular, email, and PIX uniqueness are tenant-scoped.
The same real human could technically have separate Person records in separate tenants, although each record is independently tenant-owned.
A Person has a calculated profile-completion state:
PERSONAL_ONLY
INCOMPLETE
COMPLETE
The calculation considers:
Address section
Bank section
Emergency-contact section
The Person can become a Collaborator only when:
canCreateCollaborator = true
which normally corresponds to a complete profile.
These are different concepts:
Person status is tenant reference data, such as active or discontinued.
Profile completion indicates whether the required information has been supplied.
Collaborator eligibility indicates whether a journey may be created.
A Person:
belongs to exactly one tenant;
may have no Collaborator Journeys;
may have multiple historical Collaborator Journeys;
may be linked to an Authorization Actor;
does not require an Authorization Actor;
does not require an Authentication Account.
The interface commonly calls this record a Collaborator, but the underlying domain and table represent a Collaborator Journey.
It answers:
During what period, and under what working arrangements, is this Person collaborating with the tenant?
A Collaborator is therefore not a second human record. It is an operational journey attached to a Person.
Person
βββ Collaborator Journey
Every Collaborator Journey must reference:
one Person;
in the same tenant;
with a sufficiently complete profile.
A Person cannot normally have more than one open or active journey at the same time.
After a journey is closed, the same Person may later begin a new journey. This preserves historical employment or collaboration periods instead of overwriting the earlier one.
The journey contains:
Tenant
Person
Journey start date
Default end date
Extension days
Projected end date
Payment method
Payment configuration
Planning availability
Sector
Location
Task
Collaborator status
Notes
Closing timestamp
The standard default end date is calculated as:
journey start date + 90 days
The projected end date is:
default end date + extension days
Depending on the selected payment method, a journey can contain:
Fixed monthly BRL amount
Daily BRL amount
Gold commission percentage
Time-off gold split percentage
Sick-day replacement gold amount
These are separate:
Person status describes the humanβs Person record.
Collaborator status describes a particular journey.
closedAtindicates that the journey has ended.Planning availability describes whether the journey is operationally available for planning.
The Collaborator Journey, rather than the Person directly, is generally referenced by:
Work Period Assignments
Earnings and accruals
Expenses
Ledger entries
Current Account
Receipts
Journey settlements
Gold-production allocations
This is important because financial and operational history belongs to the specific journey under which it occurred.
An Authorization Actor is the persisted security identity used for authorization and audit attribution.
It answers:
Whose authority is being exercised?
The Actor is not the password account and is not necessarily a Person or Collaborator.
An Actor contains:
Internal actor record ID
Unique actor key
Display name
Optional Person ID
Optional Collaborator Journey ID
Active state
Timestamps
Example:
Actor record ID: 7520...
Actor key: maria-expenses
Display name: Maria Silva
Person ID: person-123
Collaborator ID: journey-456
Active: true
An Actor may be linked to:
a Person;
a Collaborator Journey;
both;
neither.
An application recovery administrator such as bootstrap-admin can exist as an Actor without representing a Person or Collaborator.
A normal employee self-service Actor would normally be linked to the relevant Person and possibly the relevant Collaborator Journey.
person_id and collaborator_id are optional on the Actor.
The current database schema does not impose uniqueness on those columns. Therefore, it technically permits more than one Actor to reference the same Person or Collaborator Journey.
The intended operational practice should normally be:
one enduring Actor per real system identity
unless there is a deliberate reason to separate security identities.
An Actor can be active or inactive independently from:
the Person;
the Collaborator Journey;
the Authentication Account;
its role grants.
An inactive Actor cannot successfully operate through an authentication session.
Deactivating an Actor removes its ability to exercise all its grants without deleting the Actor or its history.
Authorization determines what an Actor may do.
It answers:
What may this Actor do, and in which tenant?
Authorization is composed of several records.
A Role is a named bundle of permissions.
Current principal roles include:
APPLICATION_ADMIN
TENANT_ADMIN
EARNINGS_OPERATOR
EXPENSE_OPERATOR
PERSON
A Role contains:
Code
Label
Description
Scope type
Active state
A Permission represents one allowed capability.
Examples include:
people.read
people.create
people.update
people.self.read
people.self.update
collaborators.read
collaborators.create
collaborators.update
collaborators.self.read
planning.read
planning.create
planning.update
expenses.read
expenses.create
authz.read
authz.manage
A wildcard permission is represented by:
*
A Role Permission associates a Role with a Permission.
This produces a many-to-many relationship:
Role * βββββ * Permission
An administrator ordinarily assigns Roles to Actors, not individual Permissions directly.
An Actor Role Grant assigns one Role to one Actor in one scope.
It contains:
Actor ID
Role ID
Tenant ID or
*Active state
Example:
Actor: maria-expenses
Role: EXPENSE_OPERATOR
Tenant: tenant-a
Active: true
The grant is the record that actually gives the Actor access.
An application role must use:
tenantId = *
A tenant-scoped or self-scoped role must use a real tenant ID.
Examples:
APPLICATION_ADMIN @ *
TENANT_ADMIN @ tenant-a
EXPENSE_OPERATOR @ tenant-a
PERSON @ tenant-a
One Actor may have:
multiple roles in one tenant;
the same role in multiple tenants;
different roles in different tenants.
Example:
Maria:
EXPENSE_OPERATOR @ tenant-a
TENANT_ADMIN @ tenant-b
Revoking a grant:
deactivates that specific role assignment;
does not delete the Actor;
does not delete the Authentication Account;
does not necessarily remove the Actorβs other roles in the same tenant;
does not remove roles in other tenants.
To remove all access to a tenant, every applicable grant for that tenant must be revoked.
Effective permissions are calculated from:
active Actor
- active Actor Role Grants
- active Roles
- Role Permissions
- selected tenant
Conceptually:
effective permissions =
union of permissions from all applicable active grants
A global Application Administrator grant applies across active tenants.
A tenant grant applies only to its recorded tenant.
Application-wide wildcard access
May manage tenants
May manage authorization
May manage authentication accounts
May operate across tenant data
Default workspace:
/people
Tenant-wide wildcard access in the assigned tenant
May administer operational data in that tenant
Must not manage application-wide Authentication or Tenant administration
Default workspace:
/people
Primary access includes:
Collaborators
Work periods and planning
Gold production
Earnings-related functions
Current-account summary where required
Default workspace:
/collaborators
Primary access includes:
Collaborators
Expenses
Outstanding receipts
Gold prices
Price lists
Required reference-data reads
It has reference_data.read for operational forms, but not reference_data.manage.
Default workspace:
/collaborators
The PERSON role is intended for self-service access, including:
Own Person record
Own linked Collaborator record
Own Current Account
Own assignments
Own receipts
The backend authorization model contains these self-service permissions, but the full browser βMy profileβ experience remains an identified gap.
An Authentication Account is the login record.
It answers:
How does someone prove that they are a particular Authorization Actor?
It contains:
Account ID
Actor ID
Normalized login
Password hash
Active state
Must-change-password state
Last-login timestamp
Password-changed timestamp
Creation and update timestamps
Each Authentication Account belongs to exactly one Actor.
The database enforces:
one Authentication Account per Authorization Actor
An Actor can have:
zero or one Authentication Account
An account cannot be moved to another Actor. The Actor link is immutable.
These are different identifiers:
Actor key: maria-expenses
Login: [email protected]
The Actor key identifies the authorization identity.
The login identifies the authentication account.
They do not have to be equal.
ERS permits an account to be created only when the Actor has effective access.
The Actor must have:
Active Actor state
At least one active Role Grant
An active Role
An active tenant, or a valid application-wide grant
This rule is enforced by the backend, and the Authentication administration selector excludes Actors without usable tenant access.
The selector also excludes Actors already linked to an account.
The Authentication Account has an active state separate from Actor active state.
Successful authentication requires both:
Authentication Account active
AND
Authorization Actor active
Deactivating an account:
blocks future login;
revokes its active sessions;
invalidates unused password-reset tokens;
does not remove the Actor;
does not remove Role Grants;
does not delete historical account information.
Reactivation does not restore an earlier session. The user must log in again.
Authentication accounts are historical security records and cannot be hard-deleted.
Their Actor link is also immutable.
A Session represents one authenticated login instance.
It answers:
Is this browser currently authenticated as the accountβs Actor?
A Session contains:
Session ID
Account ID
Hash of the opaque session token
Expiration
Last-seen time
Revocation time
User-agent metadata
IP-address metadata
Creation and update timestamps
The browser receives the raw session token in an HTTP-only cookie.
The database stores only a cryptographic hash of that token.
For every protected request, ERS effectively validates:
Session exists
AND Session is not expired
AND Session is not revoked
AND Authentication Account is active
AND Authorization Actor is active
After that, authorization resolves applicable grants and permissions for the selected tenant.
Normal browser requests do not select their Actor.
The chain is:
Session cookie
β Authentication Account
β Authorization Actor
β Role Grants
β Roles
β Permissions
The session-linked Actor is authoritative.
The selected tenant is a request context, not a login identity.
The browser may send:
X-Tenant-ID
but this is only a tenant-selection hint.
The server verifies that the sessionβs Actor has an applicable grant.
Therefore:
X-Tenant-ID does not grant tenant access.
A user may select only active tenants covered by their effective grants.
An Application Administrator with a global * grant may select any active tenant.
Changing the selected tenant:
changes the operational scope;
clears tenant-bound frontend query state;
does not change the Actor;
does not create a new Authentication Account;
does not by itself change the userβs Roles.
A Password Reset Token is a short-lived, one-time credential associated with an Authentication Account.
It contains:
Token record ID
Account ID
Hash of the reset token
Expiration
Used timestamp
Creation timestamp
Only the token hash is persisted.
The raw token is shown once to the authorized administrator for controlled delivery.
Issuing a new reset token invalidates earlier unused tokens for that account.
Completing a reset:
validates the token;
checks that it is unused and unexpired;
checks that the account and Actor are active;
updates the password hash;
clears
mustChangePassword;marks reset tokens as used;
revokes existing sessions;
requires a fresh login.
The current reset lifecycle returns the user to login using the authoritative account login, and the old password must no longer work.
An Authorization Audit Log records security-relevant decisions and administrative operations.
It can contain:
Event time
Actor key or Actor record ID
Tenant
Permission
Operation
Target type
Target ID
Decision
Reason
Metadata
Request method
Request path
Examples include:
Account creation
Account activation or deactivation
Password-reset-token issuance
Actor activation or deactivation
Role grant assignment
Role grant revocation
Sensitive authorization decisions
Audit records are immutable.
The audit Actor should be the same authoritative session Actor used for route authorization.
Reference Data supplies tenant-specific controlled values used by People and Collaborator Journeys.
Examples include:
Person status
Collaborator status
Payment method
Sector
Location
Task
Expense category
Value unit
Reference Data belongs to one tenant.
A Person or Collaborator Journey may reference only suitable Reference Data belonging to the same tenant.
For example:
Person.status
β reference_data.type = person_status
Collaborator.status
β reference_data.type = collaborator_status
Collaborator.paymentMethod
β reference_data.type = method
This prevents one tenantβs operational records from using another tenantβs configuration.
ERS intentionally maintains several independent active-state controls.
| Layer | Meaning when inactive |
|---|---|
| Tenant | Normal tenant writes are blocked |
| Person status | The Personβs business status is inactive/discontinued |
| Collaborator status or closedAt | The working journey is not active |
| Authorization Actor | All authority exercised by that Actor is blocked |
| Role | The Role cannot provide effective permissions |
| Actor Role Grant | That particular role assignment is unavailable |
| Authentication Account | Login is blocked and sessions are revoked |
| Session | That browser login is expired or revoked |
| Password Reset Token | The token cannot be used |
Avoid using βuserβ when a more precise term is available. Depending on context, βuserβ might mean:
Person
Collaborator
Actor
Authentication Account
Current Session
A Person is a human.
A Collaborator Journey is a Person working for a tenant during a defined period.
An Authorization Actor is the security identity that receives Roles.
A Role contains Permissions.
An Actor Role Grant assigns a Role to an Actor for one tenant or globally.
An Authentication Account supplies login credentials for exactly one Actor.
A Session proves that a browser authenticated through that Account.
The selected tenant identifies where the Actor wants to operate.
Authorization verifies whether the Actorβs active grants provide the required
Permission in that selected tenant.
Audit logs preserve who exercised that authority and what decision was made.