Bite 32.4 — Cross‐Tenant Delegated Role Isolation - RodrigoMattosoSilveira/EnterpriseRemoteSystems GitHub Wiki

Bite 32.4 — Cross-Tenant Delegated Role Isolation

Refined Manual Promotion Test Suite

Branch: 891-bite-32-journey-history-work-credit-evidence-and-cross-tenant-role-isolation
Committed HEAD SHA: 055ec8cb535238c328b1dc5e957219ac780b4334


1. Requirement under test

The refined Bite 32.4 rule is:

A Person may have Membership and Collaborator relationships in multiple Tenants.

If that Person holds any other Tenant Role in one Tenant, they are not eligible to receive any other Tenant Role in another Tenant.

Before another Tenant may provision such a Role, the Person must work with the Tenant where the existing Roles are held and have every Role other than Membership and Collaborator explicitly removed.

ERS may inform the provisioning Tenant Administrator that the Person is not eligible, but ERS must not reveal the other Tenant or the Roles held there.

The current UI exposes these non-baseline Tenant Roles:

EARNINGS_OPERATOR
EXPENSE_OPERATOR
TENANT_ADMIN

The automated suite additionally proves that an unknown/future TENANT-scoped Role is governed by the same rule.


2. Promotion rule

Promote Bite 32.4 only if all three manual tests PASS.

Promotion is blocked if any of the following occurs:

  • Membership or Collaborator participation in multiple Tenants prevents legitimate Role provisioning;
  • a Person holding a non-baseline Role in Tenant A can receive a non-baseline Role in Tenant B;
  • removing only some of the Roles held in Tenant A makes the Person eligible in Tenant B;
  • Actor deactivation or other lifecycle state is treated as equivalent to Role removal;
  • removing every non-baseline Role in Tenant A fails to make the Person eligible in Tenant B;
  • the provisioning Tenant learns the other Tenant's name, ID, code, or Role;
  • TENANT_ADMIN behaves differently from operator Roles with respect to the cross-Tenant boundary;
  • multiple non-baseline Roles in the same Tenant are incorrectly prohibited;
  • the refined conflict explanation does not tell the administrator that the Person must work with the other Tenant to have the Roles removed;
  • the new 32.4 conflict text is missing in either supported locale;
  • an unexpected 401, 403, 404, 500, JavaScript exception, or application error occurs.

3. Deterministic LOCAL prerequisites

These tests use the existing deterministic Bite 30G fixture.

The fixture gives us:

Tenant A:
Byte 28A Manual Test

Tenant B:
Default Tenant

and one global Person who already participates normally in both Tenants:

Person:
Ana FinancialContinuity

Login:
[email protected]

Password:
Manual-30C-Password!

Ana has:

Tenant A:
Membership
Collaborator
Tenant Actor

Tenant B:
Membership
Collaborator
Tenant Actor

Initial non-baseline Roles:
none

That makes Ana an appropriate test subject for the refined Bite 32.4 rule.


3.1 Confirm exact HEAD

From the repository root:

git rev-parse HEAD

Expected:

055ec8cb535238c328b1dc5e957219ac780b4334

PASS

The SHA matches exactly.

BLOCK PROMOTION

Do not continue if it differs.


3.2 Create an isolated manual-test database

Stop any running LOCAL backend.

From the repository root:

rm -f \
  backend/data/manual-32-4.db \
  backend/data/manual-32-4.db-wal \
  backend/data/manual-32-4.db-shm \
  backend/data/manual-32-4.db-journal

DB_PATH=backend/data/manual-32-4.db \
  ./scripts/db-migrate.sh

Confirm migration completes through:

000071_cross_tenant_delegated_role_isolation.up.sql

Seed the fixture:

python3 scripts/seed-bite30g-final-manual-testdata.py \
  --db-path backend/data/manual-32-4.db \
  --no-backup

Do not continue if the seed reports an error.


3.3 Identities used

Tenant A Administrator

Person:
Daniela TenantOperator

Login:
[email protected]

Password:
Manual-30C-Password!

Required Tenant:
Byte 28A Manual Test

Tenant B Administrator

Person:
Elisa TenantAdministrator

Login:
[email protected]

Password:
Manual-30C-Password!

Required Tenant:
Default Tenant

Cross-Tenant Person

Person:
Ana FinancialContinuity

Login:
[email protected]

Password:
Manual-30C-Password!

Her Actor displays approximately as:

30G Identity A · Tenant A
30G Identity A · Tenant B

Application Administrator

Login:
[email protected]

Password:
admin123

Required context:
Global administration

3.4 Start LOCAL

Terminal 1:

ERS_DATABASE_PATH=data/manual-32-4.db \
  make local-backend

Terminal 2:

make local-frontend

Open the normal Vite LOCAL URL.

Do not navigate by manually typing ERS application routes.


Test 01 — Membership and Collaborator are baseline; multiple Roles in one Tenant remain valid

Purpose

Prove that the refined invariant does not prohibit either:

Membership / Collaborator in multiple Tenants

or:

multiple non-baseline Roles inside one Tenant

Identity

Sign in as:

[email protected]
Manual-30C-Password!

Confirm selected Tenant:

√ Byte 28A Manual Test

Use:

English (United States)

Part A — Find Ana

  1. In the normal ERS navigation, click Authorization.

  2. √ Confirm the page heading is:

    Tenant Authorization
    
  3. Locate:

    Filter People / Actors
    
  4. Enter:

    [email protected]
    
  5. Locate:

    30G Identity A · Tenant A
    
  6. √ Confirm Ana shows:

    Actor ACTIVE
    Membership ACTIVE
    Collaborator
    
  7. √ Confirm Ana does not display:

    Role in another Tenant
    
  8. √ Confirm the Role selector is enabled.


Part B — Verify the Role selector interaction

  1. √ Before clicking the Role selector, confirm no Role choice list is permanently visible.

  2. Click the Role selector.

  3. √ Confirm the full list opens and contains both:

EARNINGS_OPERATOR
Earnings Operator

EXPENSE_OPERATOR
Expenses Operator
  1. In:
Filter roles

type:

earn
  1. √ Confirm the visible list filters to the Earnings Operator choice.

  2. Press Escape.

  3. √ Confirm the list closes.

  4. Reopen the Role selector.

  5. √ Confirm the complete unfiltered Role list appears again.

This verifies the established ERS combobox behavior.


Part C — Grant Earnings Operator

  1. Select:
EARNINGS_OPERATOR
  1. Confirm the Role list closes.

  2. Click:

Grant Role
  1. Confirm the success message:
Earnings Operator granted.
  1. Under:
Current Role Grants

confirm:

EARNINGS_OPERATOR
Earnings Operator

is present.


Part D — Grant Expenses Operator in the same Tenant

  1. Reopen the Role selector.

  2. Select:

EXPENSE_OPERATOR
  1. Click:
Grant Role
  1. √ Confirm:
Expenses Operator granted.
  1. √ Under Current Role Grants, confirm both are present simultaneously:
EARNINGS_OPERATOR
EXPENSE_OPERATOR
  1. √ Confirm the page does not show:
Role in another Tenant

Expected result

The following state is legal:

Ana

Tenant A
├── Membership
├── Collaborator
├── EARNINGS_OPERATOR
└── EXPENSE_OPERATOR

Tenant B
├── Membership
└── Collaborator

Part E — Confirm Tenant B baseline participation remains intact

  1. Sign out.

  2. Sign in as Ana:

[email protected]
Manual-30C-Password!
  1. Open the Tenant/context selector.

  2. √ Confirm both Tenants are available:

Byte 28A Manual Test
Default Tenant
  1. Select:
Default Tenant
  1. √ Confirm the context changes successfully.

  2. Navigate to People through the normal UI.

  3. √ Confirm Ana can still access her own Person context.

  4. Navigate to Collaborators.

  5. √ Confirm Ana can still access her own Collaborator/Journey context.

  6. Open the Tenant selector again.

  7. Select:

Byte 28A Manual Test
  1. √ Confirm Ana's normal Person/Collaborator participation remains available there too.

PASS

PASS if:

  • Ana starts eligible despite having Membership and Collaborator relationships in both Tenants;
  • both operator Roles can coexist in Tenant A;
  • Ana continues participating normally in Tenant B;
  • no cross-Tenant warning appears merely because Ana belongs to or collaborates with Tenant B.

BLOCK PROMOTION

Block promotion if:

  • Ana is initially ineligible simply because she has Tenant B Membership/Collaborator participation;
  • the second Role in Tenant A is rejected;
  • Tenant B disappears from Ana's normal context selection;
  • Ana loses her Tenant B Membership/Collaborator behavior;
  • ordinary baseline participation is treated as a conflicting Role.

Test 02 — Another Tenant must refuse provisioning until every non-baseline Role is removed

Dependency

Test 01 must have passed.

At the beginning of this test Ana must have:

Tenant A:
EARNINGS_OPERATOR
EXPENSE_OPERATOR

Tenant B:
no non-baseline Role

Part A — Tenant B attempts to provision Ana

  1. Sign out.

  2. Sign in as the Tenant B Administrator:

[email protected]
Manual-30C-Password!
  1. √ Confirm selected Tenant:
Default Tenant
  1. Select:
English (United States)
  1. Navigate to Authorization.

  2. In Filter People / Actors, enter:

[email protected]
  1. Locate:
30G Identity A · Tenant B
  1. √ Confirm Ana still shows normal baseline status:
Actor ACTIVE
Membership ACTIVE
Collaborator
  1. √ Confirm she additionally displays the badge:
Role in another Tenant
  1. √ Confirm the Role selector is disabled.

  2. √ Confirm it displays:

Role selection unavailable
  1. √ Confirm Grant Role is disabled.

Part B — Verify the refined client-facing explanation

  1. Read the warning beneath the Role selector.

  2. √ Confirm it says:

This Person has one or more Roles in another Tenant. They must work with that Tenant to have every Role other than Membership and Collaborator removed before a Role can be assigned here.
  1. √ Confirm the message clearly communicates all three concepts:
a Role exists elsewhere;

the Person must work with that Tenant;

every Role other than Membership and Collaborator must be removed.

Part C — Verify confidentiality

  1. Inspect the entire Ana card.

  2. Confirm it does not reveal:

Byte 28A Manual Test
  1. √ Confirm it does not reveal Tenant A's internal Tenant ID or code.

  2. √ Confirm it does not reveal either:

EARNINGS_OPERATOR
EXPENSE_OPERATOR

as Roles Ana holds elsewhere.

  1. √ Confirm it does not reveal how many other Roles she holds.

√ Expected result

Tenant B is told only:

Ana is currently ineligible because one or more non-baseline Roles exist elsewhere.

Tenant B is not told where or what those Roles are.


Part D — Verify the same explanation in Brazilian Portuguese

  1. Switch the locale to:
Português (Brasil)
  1. √ Confirm the conflict badge becomes:
Função em outro Locatário
  1. √ Confirm the explanatory text becomes:
Esta Pessoa possui uma ou mais Funções em outro Locatário. Ela deve trabalhar com esse Locatário para que todas as Funções, exceto Vínculo e Colaborador, sejam removidas antes que uma Função possa ser atribuída aqui.
  1. √ Confirm this Portuguese message also does not reveal the other Locatário or any Role held there.

  2. Return to:

English (United States)

Part E — Remove only one Role from Tenant A

  1. Sign out.

  2. Sign in as the Tenant A Administrator:

[email protected]
Manual-30C-Password!
  1. Confirm:
Byte 28A Manual Test
  1. Open Authorization.

  2. Search for:

[email protected]
  1. Under Current Role Grants, locate:
EARNINGS_OPERATOR
  1. Click its:
Remove

button.

  1. √ Confirm:
Earnings Operator revoked.
  1. √ Confirm EARNINGS_OPERATOR disappears.

  2. √ Confirm this Role remains:

EXPENSE_OPERATOR

Part F — Verify that partial removal is insufficient

  1. Sign out.

  2. Sign in again as the Tenant B Administrator.

  3. Confirm:

Default Tenant
  1. Open Authorization.

  2. Search for Ana.

  3. √ Confirm the badge still says:

Role in another Tenant
  1. √ Confirm the Role selector remains disabled.

43.√ Confirm Grant Role remains disabled.

  1. √ Confirm the same non-disclosing explanatory message remains.

√ Expected result

Removing one Role is not sufficient because Ana still holds EXPENSE_OPERATOR in Tenant A.


Part G — Remove the final non-baseline Role from Tenant A

  1. Sign out.

  2. Sign in as the Tenant A Administrator.

  3. √ Confirm:

Byte 28A Manual Test
  1. Open Authorization.

  2. Search for Ana.

  3. Under Current Role Grants, remove:

EXPENSE_OPERATOR
  1. √ Confirm:
Expenses Operator revoked.
  1. √ Confirm the page now says:
No current operator Role Grants.

Part H — Tenant B eligibility is now restored

  1. Sign out.

  2. Sign in as the Tenant B Administrator.

  3. Confirm:

Default Tenant
  1. Open Authorization.

  2. Search for Ana.

  3. √ Confirm:

Role in another Tenant

is no longer shown.

  1. √ Confirm the Role selector is enabled.

  2. Open the selector.

  3. Select:

EXPENSE_OPERATOR
  1. Click:
Grant Role
  1. Confirm:
Expenses Operator granted.
  1. √ Confirm Tenant B now shows:
EXPENSE_OPERATOR

under Ana's Current Role Grants.


Part I — Confirm the boundary works in the reverse direction

  1. Sign out.

  2. Sign in as the Tenant A Administrator.

  3. √ Confirm:

Byte 28A Manual Test
  1. Open Authorization.

  2. Search for Ana.

  3. √ Confirm Ana is now blocked in Tenant A.

  4. √ Confirm the badge reads:

Role in another Tenant
  1. √ Confirm neither:
Default Tenant

nor:

EXPENSE_OPERATOR

is disclosed.


Cleanup

  1. Sign out.

  2. Sign in as the Tenant B Administrator.

  3. Open Authorization.

  4. Search for Ana.

  5. Remove her:

EXPENSE_OPERATOR
  1. √ Confirm:
No current operator Role Grants.

This cleanup is required before Test 03.


PASS

PASS if the exact sequence is:

2 Roles in Tenant A
→ Tenant B blocked

1 Role in Tenant A
→ Tenant B still blocked

0 Roles in Tenant A
→ Tenant B eligible

1 Role in Tenant B
→ Tenant A blocked

Role removed from Tenant B
→ boundary released

BLOCK PROMOTION

Block promotion if:

  • Tenant B can provision Ana while either Tenant A Role remains;
  • removing just one of several Roles releases Ana;
  • removing all Roles does not restore eligibility;
  • the warning omits the requirement to work with the other Tenant;
  • the warning implies Membership or Collaborator must be removed;
  • ERS exposes the other Tenant;
  • ERS exposes the other Role;
  • EN-US and pt-BR conflict semantics differ.

Test 03 — TENANT_ADMIN participates in exactly the same cross-Tenant Role boundary

Purpose

Prove that TENANT_ADMIN is not a special exception.

The same rule must apply:

operator Role in Tenant A
→ cannot provision TENANT_ADMIN in Tenant B

TENANT_ADMIN in Tenant B
→ cannot provision operator Role in Tenant A

Dependency

Test 02 cleanup must have completed.

Ana must have no active non-baseline Tenant Role.


Part A — Give Ana a Role in Tenant A

  1. Sign in as:
[email protected]
Manual-30C-Password!
  1. √ Confirm selected Tenant:
Byte 28A Manual Test
  1. Open Authorization.

  2. Search for Ana.

  3. Open the Role selector.

  4. Select:

EARNINGS_OPERATOR
  1. Click:
Grant Role
  1. Confirm:
Earnings Operator granted.

Part B — Inspect Ana as a Tenant Administrator candidate in Tenant B

  1. Sign out.

  2. Sign in as the Application Administrator:

[email protected]
admin123
  1. √ Confirm the current context is:
Global administration
  1. Through the normal administration navigation, open:
Tenants
  1. Locate:
Default Tenant
  1. Open the Default Tenant detail page.

  2. Scroll to:

Tenant Administrators
  1. √ Confirm the section explains:
A Person may participate through Membership and Collaborator relationships in multiple Tenants, but may hold any other Tenant Role in only one Tenant at a time.
  1. Confirm it also explains:
Before assigning a Role here, the Person must work with the Tenant where those Roles are held to have them removed.
  1. √ Confirm Default Tenant currently has one administrator slot occupied:
1 of 2 Tenant Administrator slots is occupied.
  1. Locate:
Unavailable administrator candidates
  1. √ Locate Ana's Tenant B Actor.

√ Expected display:

30G Identity A · Tenant B
  1. √ Confirm Ana is unavailable.

  2. √ Confirm the reason is:

This Person has one or more Roles in another Tenant. They must work with that Tenant to have every Role other than Membership and Collaborator removed before a Role can be assigned here.
  1. Open:
Select an eligible active actor
  1. √ Confirm Ana is not offered as an eligible candidate.

Part C — Verify Tenant Administrator candidate confidentiality

  1. Inspect the unavailable-candidate message.

  2. √ Confirm it does not identify:

Byte 28A Manual Test
  1. √ Confirm it does not identify Tenant A's ID or code.

  2. √ Confirm it does not identify:

EARNINGS_OPERATOR
  1. √ Confirm the Application Administrator learns only that Ana currently has one or more Roles elsewhere and must arrange their removal.

Part D — Remove Tenant A Role

  1. Sign out.

  2. Sign in as the Tenant A Administrator.

  3. Open Authorization.

  4. Search for Ana.

  5. Remove:

EARNINGS_OPERATOR
  1. √ Confirm no current operator Role Grant remains.

Part E — Ana becomes eligible for TENANT_ADMIN in Tenant B

  1. Sign out.

  2. Sign in as the Application Administrator.

  3. Return through the normal UI to:

Tenants
→ Default Tenant
→ Tenant Administrators
  1. √ Confirm Ana is no longer listed as unavailable because of a Role in another Tenant.

  2. Open:

Select an eligible active actor
  1. √ Confirm Ana is now selectable.

  2. Select Ana.

  3. Click:

Assign Admin
  1. Confirm the assignment succeeds.

  2. If a success dialog appears, click:

Continue
  1. √ Confirm Default Tenant now has:
2 of 2 assignments
  1. √ Confirm Ana appears as an assigned Tenant Administrator.

Part F — Tenant B TENANT_ADMIN must now block Tenant A provisioning

  1. Sign out.

  2. Sign in as the Tenant A Administrator.

  3. √ Confirm:

Byte 28A Manual Test
  1. Open Authorization.

  2. Search for Ana.

  3. √ Confirm:

Role in another Tenant

is displayed.

  1. √ Confirm the Role selector is disabled.

  2. √ Confirm Grant Role is disabled.

  3. √ Confirm the warning does not reveal:

Default Tenant
  1. √ Confirm it does not reveal:
TENANT_ADMIN

√ Expected result

√ TENANT_ADMIN behaves exactly like every other non-baseline Tenant Role for cross-Tenant eligibility purposes.


Cleanup

  1. Sign out.

  2. Sign in as the Application Administrator.

  3. Navigate to:

Tenants
→ Default Tenant
→ Tenant Administrators
  1. Locate Ana.

  2. Click:

Revoke
  1. Complete the success dialog if displayed.

  2. √ Confirm Default Tenant returns to:

1 of 2 assignments
  1. √ Confirm Ana is no longer assigned as a Tenant Administrator.

PASS

PASS if:

Tenant A EARNINGS_OPERATOR
→ Tenant B TENANT_ADMIN unavailable

Tenant A Role removed
→ Tenant B TENANT_ADMIN available

Tenant B TENANT_ADMIN assigned
→ Tenant A operator Role unavailable

Tenant B TENANT_ADMIN revoked
→ cross-Tenant Role boundary released

BLOCK PROMOTION

Block promotion if:

  • TENANT_ADMIN bypasses the rule;
  • an operator Role bypasses the rule when TENANT_ADMIN already exists elsewhere;
  • removing the original Role fails to restore eligibility;
  • the candidate explanation reveals the other Tenant or Role;
  • Membership or Collaborator relationships are treated as conflicting Roles.

4. Cases that do not require additional manual testing

Future/unlisted Tenant Roles

No manual synthetic Role test is required.

The current UI exposes only:

EARNINGS_OPERATOR
EXPENSE_OPERATOR
TENANT_ADMIN

The committed automated backend and migration tests create an unenumerated future TENANT-scoped Role and prove that it is automatically governed by the same invariant.

This is stronger than adding test-only Role data manually.


Lifecycle suspension

No manual lifecycle-suspension test is required.

Automated coverage proves:

active Role Grant
+
lifecycle_suspended = true

still reserves the Person to that Tenant.

The Person becomes cross-Tenant eligible only after explicit Role Grant revocation.


Direct SQL bypass

No manual SQL test is required.

Migration 000071 already has deterministic coverage for:

cross-Tenant INSERT
cross-Tenant UPDATE/reactivation
existing conflicting data during migration

5. DevTools / API / SQL

None required.

All promotion acceptance steps above are performed through the normal ERS UI.

The only command-line operations are:

fixture setup
migration
backend startup
frontend startup

6. Final promotion checklist

[x] Exact ZIP/SHA verified
[x] make local-check passes — reported by tester
[x] Feature-branch CI passes — reported by tester

[ ] Test 01 — baseline multi-Tenant participation + same-Tenant multi-role — PASS
[ ] Test 02 — all Roles must be removed before another Tenant can provision — PASS
[ ] Test 03 — TENANT_ADMIN follows the same cross-Tenant boundary — PASS

If all three tests PASS and no new authorization, confidentiality, I18N, or usability defect is observed, Bite 32.4 — Cross-Tenant Delegated Role Isolation is ready for promotion.


7. Promotion-critical business statement

Before promotion, the observed application behavior should be explainable to a prospective client in exactly these terms:

A Person can be a Member and Collaborator of multiple Tenants. However, once a Tenant gives that Person any additional Role, another Tenant cannot give the Person another Role until the Person works with the first Tenant to have all of those additional Roles removed. ERS tells the second Tenant that the Person is not currently eligible, but ERS does not reveal which other Tenant the Person works with or which Roles they hold there.