Bite #30G — Person Tenant Financial Ownership Refactor - RodrigoMattosoSilveira/EnterpriseRemoteSystems GitHub Wiki

Bite #30G — Person + Tenant Financial Ownership Refactor

Final UI-Only Manual Promotion Test Suite — including 30G.1 / 30G.2 / 30G.3

Branch: 723-bite-30g-person-tenant-financial-ownership-refactor
Source baseline audited: 18324772e144b280248fc6cbf52c42590975d8d6
Required observability patch before using this edition: 723-bite-30g-ui-only-financial-provenance-observability.patch
Promotion candidate SHA: record the exact final committed SHA after all required patches are applied.


1. Manual-test rule for this suite

This is the canonical Bite 30G UI-only manual promotion suite.

For Tests 01–20:

  1. Perform every business operation through the visible ERS application UI.
  2. Verify every assertion from visible UI data.
  3. Do not use SQL, DevTools JavaScript, direct API calls, or database inspection to complete a manual assertion.
  4. DevTools Console/Network may be open for diagnostics only.
  5. If the test says verify X and X is not visible in the UI, STOP and record a UX/observability defect. Do not infer it from fixture knowledge.
  6. Do not manufacture state to compensate for an accidentally consumed receipt, closed Journey, or later-test operation. Preserve the sequential test order.

Database triggers, migrations, ownership hardening, and final referential integrity are verified in the separate Technical Promotion Gate after Test 20. They are not manual UX tests.


2. Preconditions

2.1 Commit the exact candidate

From the ERS repository root:

cd /Users/rodrigosilveira/projects/EnterpriseRemoteSystems

git branch --show-current
git rev-parse HEAD
git status --short

Record:

Branch: ____________________________________________
SHA:    ____________________________________________

The working tree should be clean.

2.2 Automated prerequisite

Before resetting the manual fixture, run:

make local-check

Do not start the manual suite until the automated gate is green.

2.3 Create a fresh deterministic manual-test database

Stop the backend first.

Then run:

python3 \
  scripts/seed-bite30g-final-manual-testdata.py \
  --db-path backend/data/app.db \
  --reset-existing-batch

Expected completion:

Bite 30G final manual fixtures created successfully

The reset logic may restore a compatible clean backup or rebuild a clean database from repository migrations. An incompatible old deterministic backup should be quarantined rather than preventing the seed from completing.

Restart ERS:

make local-backend

Start/restart the frontend using the normal local command.

Use a fresh browser session after every database reset because authentication sessions from the previous database are invalid.

2.4 Common fixture password

Manual-30C-Password!

2.5 Tenants

Tenant A = Byte 28A Manual Test
Tenant B = default / Default Tenant

Always use the application's header Tenant selector. Do not emulate Tenant switching with headers or direct API calls.


3. Deterministic identities and Journey aliases

Operator D — dual-Tenant Tenant Administrator

Login: [email protected]
Role: TENANT_ADMIN in Tenant A and Tenant B

Use Operator D for administrative, accrual, Expense, settlement, Tenant-side receipt acceptance, and Journey closure operations unless the test says otherwise.

Identity A — cross-Journey / cross-Tenant Person

Login: [email protected]
Global Person ID: manual30g-global-person-a

Tenant A:

A.TA.J1 = manual30g-journey-a1-closed
          CLOSED
          historical +125.00 BRL earning
          historical -125.00 BRL settlement
          net Journey balance = 0

A.TA.J2 = manual30g-journey-a2-open
          OPEN
          starts at 0

Work Period = manual30g-work-period-tenant-a

Tenant B:

A.TB.J1 = manual30g-journey-a-tenant-b-open
          OPEN
          starts at +300.00 BRL

Work Period = manual30g-work-period-tenant-b

Identity B — Tenant owes Collaborator

Login: [email protected]
Person ID: manual30g-global-person-b

B.TA.J1 = manual30g-journey-b1-positive
Starting balances:
  +200.00 BRL
  +2.50000000 g

A new B.TA.J2 is created later in this suite.

Identity C — Collaborator owes Tenant

Login: [email protected]
Person ID: manual30g-global-person-c

C.TA.J1 = manual30g-journey-c1-negative
Starting balances:
  -150.00 BRL
  -1.25000000 g

Identity M — mixed settlement directions

Login: [email protected]
Person ID: manual30g-global-person-m

M.TA.J1 = manual30g-journey-m1-mixed
Starting balances:
  +80.00 BRL
  -0.50000000 g

Identity H — historical Account-level self-service

Login: [email protected]
Person ID: manual30g-global-person-h
H.TA.J1 = manual30g-journey-h1-closed

Authentication Account: ACTIVE
Membership: INACTIVE
Tenant Actor: INACTIVE

Historical:
  +75.00 BRL
  -75.00 BRL
  net = 0

Identity R — neutral Expense target

Login: [email protected]
Person ID: manual30g-global-person-r

R.TA.J1 = manual30g-journey-r1-open
Starting balance = 0

Earnings Operator

Login: [email protected]
Role: EARNINGS_OPERATOR in Tenant A

Expected Collaborator authority:

may edit: Sector, Location, Task
may NOT full-edit Collaborator/Journey
may NOT extend Journey

4. Sequential-state discipline

Tests 06–20 mutate one deterministic batch. Run them in order.

Critical boundaries:

Test 11 creates B.TA.J1 receipts.
STOP before accepting them.
Test 12 owns B.TA.J1 wrong-party checks and receipt acceptance.
Test 13 owns B.TA.J1 closure.

Test 17 creates C.TA.J1 receipts.
STOP before accepting them.
Test 18 owns C.TA.J1 wrong-party checks, Tenant acceptance, and closure.

Test 19 must test BOTH wrong-party cases before either mixed-direction receipt
is consumed.

If you perform a later action early, do not manufacture replacement receipts or repair state with SQL. Reset/reseed and replay the affected sequence.


[✔︎] Test 01 — Fresh deterministic fixture is visible through the UI

MUST PASS

Purpose

Confirm the clean fixture is usable from the application before mutating it.

Procedure

  1. Open a fresh browser session.
  2. Sign in as Operator D.
  3. Select Byte 28A Manual Test.
  4. Open Collaborators.
  5. [✔︎] Verify the current/open fixture Journeys are discoverable for Identity A, B, C, M, and R.
  6. Open Identity A / A.TA.J2 → Current Account.
  7. [✔︎] Verify the Person + Tenant A balance is 0.00 BRL.
  8. Return to Collaborators and open Identity B / B.TA.J1.
  9. [✔︎] Inspect Journey Settlement and verify:
    • +200.00 BRL
    • +2.50000000 g
  10. [✔︎] Open Identity C / C.TA.J1 and verify:
    • -150.00 BRL
    • -1.25000000 g
  11. [✔︎] Open Identity M / M.TA.J1 and verify:
    • +80.00 BRL
    • -0.50000000 g
  12. [✔︎] Open Identity R / R.TA.J1 → Current Account and verify the balance is zero.
  13. Switch the header Tenant selector to default / Default Tenant.
  14. Open Identity A / A.TB.J1 → Current Account.
  15. [✔︎] Verify Tenant B starts at +300.00 BRL.
  16. Switch back to Byte 28A Manual Test.

Expected

  • All deterministic records needed by the suite are discoverable through normal UI navigation.
  • Tenant A and Tenant B show their expected independent starting balances.
  • Positive balances are presented as positive; negative balances are presented as negative.
  • No fixture record requires SQL or a direct URL to prove that it exists.

[✔︎] Test 02 — Identity A can inspect current and closed Journey history read-only

MUST PASS

Identity / Tenant

Identity A
Tenant A

Procedure

  1. Sign out Operator D.
  2. Sign in as Identity A.
  3. Select Byte 28A Manual Test.
  4. Click Collaborators.
  5. [✔︎] Verify the page title is My Collaborator Journeys.
  6. [✔︎] Verify A.TA.J2 is present as the current/open Journey.
  7. [✔︎] Verify A.TA.J1 is also present in Journey history and is visibly Closed.
  8. Open A.TA.J1.
  9. [✔︎] Verify Journey Closed and its closing date are visible.
  10. Click Back to My Journeys.
  11. Inspect the Journey controls.
  12. [✔︎] Verify Identity A has no Edit Collaborator, Edit Work Assignment, extension, settlement-administration, or Journey-creation controls.

Expected

  • A current Collaborator can see its own current and closed Journey history.
  • Closed history is not hidden when a later Journey exists.
  • Self-service is read-only.

[x] Test 03 — Person + Tenant financial history crosses Journey boundaries, but A.TA.J2 starts at zero

MUST PASS

Identity / Tenant

Operator D
Tenant A
A.TA.J2 = manual30g-journey-a2-open

Procedure

  1. Sign out as Identity A.
  2. Sign in as Operator D.
  3. Select Byte 28A Manual Test.
  4. Click Collaborators.
  5. Filter/search for 30G Identity A.
  6. The administrative catalog intentionally shows the current/open Journey. Seeing one Identity A row here is expected.
  7. Open the row; it is A.TA.J2.
  8. Click Current Account.
  9. Locate the historical +125.00 BRL earning row.
  10. Verify the row displays:
Person owner:       manual30g-global-person-a
Journey provenance: manual30g-journey-a1-closed
  1. Locate the historical -125.00 BRL settlement row.
  2. Verify it displays the same Person owner and A.TA.J1 Journey provenance.
  3. Click the Journey provenance link on either historical row.
  4. Verify the linked Journey opens and is visibly Journey Closed.
  5. Return to A.TA.J2 Current Account.
  6. Verify the Person + Tenant A net balance is 0.00 BRL.
  7. Return to A.TA.J2's Collaborator page.
  8. Inspect Journey Settlement.
  9. Verify A.TA.J2's own settlement balance is exactly zero in each displayed value unit.

Expected

  • Historical A.TA.J1 entries remain visible in the Person + Tenant Current Account.
  • Both historical rows visibly retain A.TA.J1 provenance.
  • They are not rewritten to A.TA.J2.
  • A.TA.J2 starts at zero.
  • No invented opening Ledger Entry carries A.TA.J1 activity into A.TA.J2.

#[x] Test 04 — Current + Future Earnings uses the selected Journey balance

MUST PASS

Starting state

A.TA.J2 has no own financial activity yet and starts at zero.

Procedure

  1. As Operator D / Tenant A, open Identity A / A.TA.J2 → Current Account.
  2. Click Current + Future Earnings.
  3. Verify the modal explicitly displays:
Journey provenance: manual30g-journey-a2-open
  1. In Current Balances, verify BRL is 0.00.
  2. Verify zero/non-negative balance text is green.
  3. Verify A.TA.J1's historical +125/-125 activity has not become A.TA.J2's current balance.
  4. Inspect the ready/future/projected earnings sections and verify they are presented as projections for the selected Journey rather than Person-history carry-forward.
  5. Close the modal.

Promotion blocker

[x] Any non-zero A.TA.J2 current balance derived solely from A.TA.J1 history.


[x] Test 05 — Same Global Person remains financially isolated by Tenant

MUST PASS

Identity

Identity A exists in Tenant A and Tenant B.

Procedure

  1. As Operator D, select Byte 28A Manual Test.
  2. Open Identity A / A.TA.J2 → Current Account.
  3. [✔︎] Verify Tenant A net balance is 0.00 BRL.
  4. [✔︎] Inspect the Ledger Entries and verify no Tenant B +300.00 BRL row appears.
  5. Use the header Tenant selector to select default / Default Tenant.
  6. Open Identity A / A.TB.J1 → Current Account.
  7. [✔︎] Verify Tenant B balance is +300.00 BRL.
  8. [✔︎] Inspect its ledger and verify the Tenant A A.TA.J1 +125/-125 history does not appear.
  9. Switch back to Byte 28A Manual Test.

Expected

  • The same Global Person does not weaken Tenant confidentiality.
  • Tenant A sees only Tenant A history.
  • Tenant B sees only Tenant B history.

[x] Test 06 — Accrual posting in non-default Tenant A owns Person + Tenant + A.TA.J2 provenance

MUST PASS

Identity / Tenant

Operator D
Tenant A
Work Period = manual30g-work-period-tenant-a
Expected accrual = 50.00 BRL

Procedure

  1. Sign in as Operator D if necessary.
  2. Select Byte 28A Manual Test.
  3. Click Work Periods.
  4. Locate 30G Tenant A accrual ownership.
  5. Open it.
  6. [✔︎] Inspect the Work Period before creating a run.
  7. [✔︎] If useful, open Actual Outcomes and verify Identity A's prepared outcome is Worked; do not modify it.
  8. Click Accrual.
  9. [✔︎] Verify the Accrual page loads normally. 404, Record not found, or tenant not found is a FAIL.
  10. In Accrual Runs, locate the clearly labeled multiline Accrual notes field.
  11. [✔︎] Verify it is comfortably sized for a meaningful sentence.
  12. Enter:
30G FINAL Tenant A accrual
  1. Click Run Accrual.
  2. Inspect the run before posting.
  3. Select the new run if necessary.
  4. [✔︎] Verify Identity A has a READY 50.00 BRL CREDIT item.
  5. On that Accrual item, verify the visible ownership block:
Person owner:       manual30g-global-person-a
Journey provenance: manual30g-journey-a2-open
Tenant:             <selected Tenant A identifier shown by ERS>
  1. [✔︎] Verify Tenant is not default.
  2. Click Post Ready Items.
  3. Verify the success message indicates posted items are visible in Current Accounts.
  4. Navigate Collaborators → Identity A → A.TA.J2 → Current Account.
  5. Locate the new +50.00 BRL accrual row.
  6. [✔︎] Verify it displays:
Person owner:       manual30g-global-person-a
Journey provenance: manual30g-journey-a2-open
  1. [✔︎] Verify Person + Tenant A balance is now +50.00 BRL.
  2. Click Current + Future Earnings.
  3. [✔︎] Verify:
    • Journey provenance = A.TA.J2
    • Current BRL balance = +50.00
    • balance text is green.
  4. Switch to default / Default Tenant.
  5. Reopen Identity A / A.TB.J1 Current Account.
  6. [✔︎] Verify Tenant B remains +300.00 BRL.
  7. Switch back to Tenant A.

Expected

  • Non-default Tenant accrual never falls back to default.
  • Run/item/posting remain owned by Person A + A.TA.J2 + Tenant A.
  • A.TA.J2 changes from 0 to +50 BRL.
  • Tenant B remains unchanged.

[x] Test 07 — Default Tenant B accrual remains correct and independent

MUST PASS

Identity / Tenant

Operator D
Tenant B = default
Work Period = manual30g-work-period-tenant-b
Expected accrual = 70.00 BRL

Procedure

  1. Select default / Default Tenant.
  2. Click Work Periods.
  3. Locate 30G Tenant B accrual regression.
  4. Open it.
  5. Verify the Work Period ID/code shown by the UI corresponds to the Tenant B fixture when those fields are displayed.
  6. Click Accrual.
  7. Verify the page loads without 404/Record not found.
  8. In Accrual notes, enter:
30G FINAL Tenant B accrual
  1. Click Run Accrual.
  2. Inspect the new run before posting.
  3. Verify Identity A has a READY 70.00 BRL CREDIT item.
  4. Verify the item displays:
Person owner:       manual30g-global-person-a
Journey provenance: manual30g-journey-a-tenant-b-open
Tenant:             default
  1. Click Post Ready Items.
  2. Verify posting succeeds.
  3. Navigate Collaborators → Identity A → A.TB.J1 → Current Account.
  4. Locate the new +70.00 BRL row and verify its Person/Journey provenance.
  5. Verify:
Starting Tenant B balance = 300.00 BRL
Posted accrual             =  70.00 BRL
Result                     = 370.00 BRL
  1. Click Current + Future Earnings.
  2. Verify Current Balance is 370.00 BRL, rendered green.
  3. Switch to Byte 28A Manual Test.
  4. Reopen A.TA.J2 Current Account.
  5. Verify Tenant A remains +50.00 BRL.

Expected

  • Default-Tenant accrual remains correct after the non-default-Tenant fix.
  • Tenant B reaches +370 BRL.
  • Tenant A remains +50 BRL.

[✔︎] Test 08 — Expense write uses canonical Person ownership and matching Ledger/Receipt ownership

MUST PASS

Identity / Tenant

Operator D
Tenant A
R.TA.J1
Exact Expense total = 20.00 BRL

Part A — Price List item and dirty-state behavior

  1. Select Byte 28A Manual Test.
  2. Navigate to Price List.
  3. Search/filter for:
MANUAL30G_EXPENSE_20
  1. If it exists with unit price 20.00 BRL, click Edit.
  2. Immediately verify Save Changes is gray and disabled.
  3. Change Description by one character.
  4. Verify Save Changes becomes black and enabled.
  5. Restore the original Description exactly.
  6. Verify Save Changes becomes gray and disabled again.
  7. Leave edit mode without saving.
  8. If the item does not exist, use Add Item and create:
Category:        Canteen
Code:            MANUAL30G_EXPENSE_20
Description:     30G Manual Expense 20 BRL
BRL unit price:  20.00
Sort order:      930

Part B — Create Expense

  1. Navigate to Expenses.
  2. Click New Expense.
  3. In Collaborator, search/select 30G Identity R / R.TA.J1.
  4. Select category Canteen.
  5. Select Real (BRL).
  6. Select 30G Manual Expense 20 BRL.
  7. Set Quantity = 1.
  8. Set Expense Date = today.
  9. In Notes enter:
30G FINAL Expense ownership R.TA.J1
  1. Verify preview:
Unit Price = 20.00 BRL
Quantity   = 1
Total      = 20.00 BRL
  1. Click Create Expense.
  2. On Expense detail, locate Financial Ownership.
  3. Verify:
Person owner:       manual30g-global-person-r
Journey provenance: manual30g-journey-r1-open
Tenant:             <Tenant A identifier shown by ERS>
  1. [✔︎] Inspect Financial Posting and verify the generated Ledger Entry is visible.
  2. Open R.TA.J1 → Current Account.
  3. Locate the Expense debit and verify it repeats Person R / R.TA.J1 provenance.
  4. Open the generated Receipt from the Expense/Current Account UI.
  5. [✔︎] Verify the Receipt displays the same Tenant, Person owner, and Journey provenance.
  6. [✔︎] Verify legacy Expense debit receipt metadata is visibly consistent with an account debit and Collaborator-side receipt handling.

Expected

  • Expense, Ledger Entry, and Receipt visibly agree on Person R + R.TA.J1 + Tenant A.
  • The Expense total is exactly 20 BRL.
  • No hidden Person/Journey reassignment occurs.

[x] Test 09 — Incorrect Expense is cancelled, reversed, and recreated under the correct owner

MUST PASS

Starting state

Test 08 created a 20.00 BRL Expense under R.TA.J1.

A.TA.J2 is currently +50.00 BRL.

Procedure

  1. Remain signed in as Operator D / Tenant A.
  2. Navigate to Expenses.
  3. Locate and open 30G FINAL Expense ownership R.TA.J1.
  4. Verify Financial Ownership shows:
Person owner:       manual30g-global-person-r
Journey provenance: manual30g-journey-r1-open
  1. Click Correct expense.
  2. Verify a required Cancellation reason field appears.
  3. Enter:
Incorrect Collaborator/Journey; expense belongs to Identity A / A.TA.J2.
  1. Click Cancel and recreate.
  2. Verify ERS navigates to Recreate Expense and shows Replacement for cancelled Expense.
  3. Verify the replacement form is prefilled from the cancelled Expense.
  4. Change only the incorrect owner to Identity A / A.TA.J2.
  5. Keep financial inputs unchanged so total remains 20.00 BRL.
  6. Change Notes to:
30G FINAL Expense corrected to A.TA.J2
  1. Click Create Replacement Expense.
  2. On the replacement Expense, verify Financial Ownership:
Person owner:       manual30g-global-person-a
Journey provenance: manual30g-journey-a2-open
  1. Click Open cancelled source.
  2. Verify the source remains owned by Person R / R.TA.J1, is visibly Cancelled, and preserves the cancellation reason.
  3. Navigate Collaborators → Identity R → R.TA.J1 → Current Account.
  4. Verify the original -20.00 BRL debit remains visible with R.TA.J1 provenance.
  5. Verify an equal +20.00 BRL reversal is visible with the same R.TA.J1 provenance.
  6. Verify R.TA.J1 returns to 0.00 BRL.
  7. Navigate Collaborators → Identity A → A.TA.J2 → Current Account.
  8. Verify the replacement -20.00 BRL debit shows A.TA.J2 provenance.
  9. Verify A.TA.J2/Tenant A balance changes from +50.00 to +30.00 BRL, rendered green.
  10. Verify the replacement has its own Receipt.
  11. Open Outstanding Receipts.
  12. Verify a still-open source receipt is not left operationally outstanding after source cancellation. A previously accepted/returned historical source receipt may remain historical evidence.

Expected

  • The incorrect Expense is not edited to another Person/Journey in place.
  • Cancellation preserves history and reverses the original financial effect.
  • The replacement is a distinct Expense owned by Person A + A.TA.J2.
  • R.TA.J1 returns to zero.
  • A.TA.J2 becomes +30 BRL.
  • Receipt lifecycle follows cancellation/recreation cleanly.

[x] Test 10 — Positive Journey balance cannot close; inspection does not create an automatic payout

MUST PASS

Identity / Tenant

Operator D
Tenant A
B.TA.J1
Starting: +200 BRL / +2.5 g

Procedure

  1. Open Collaborators → Identity B → B.TA.J1.
  2. Inspect Journey Settlement.
  3. Verify Tenant owes Collaborator.
  4. Verify +200.00 BRL and +2.50000000 g.
  5. Verify Close Journey is disabled and/or the card says Journey closure is blocked.
  6. Open Current Account.
  7. Record the visible total from:
Showing page … · N ledger entries
  1. Return to B.TA.J1.
  2. Refresh/reopen Journey Settlement without executing any settlement action.
  3. Reopen Current Account.
  4. Verify the visible total N is unchanged.
  5. Verify no new payout/final-settlement row appeared.

Expected

  • Non-zero balance blocks closure.
  • Merely inspecting closure does not create financial activity.
  • Settlement must be an explicit operation separate from Close Journey.

[x] Test 11 — Tenant→Collaborator final settlement zeros positive balances and creates Collaborator receipts

MUST PASS

Procedure

  1. As Operator D / Tenant A, open B.TA.J1.
  2. In Journey Settlement, click Settle Tenant Owed Balance.
  3. Set Effective Date = today.
  4. Complete Confirm reauthentication.
  5. Select reason Final Tenant payment.
  6. Reason text:
30G final Tenant payment for B.TA.J1
  1. Notes:
30G manual promotion Tenant-to-Collaborator settlement
  1. Submit.
  2. Verify BRL and Gold Journey balances are exactly zero.
  3. Verify Balances settled — receipt acceptance pending.
  4. Verify Review outstanding receipts is available.
  5. Verify Close Journey remains disabled.
  6. Verify the redundant generic red Blocking reasons: outstanding receipts message is not shown for the receipt-only state.
  7. Open Current Account.
  8. Locate exactly two new final-settlement rows:
    • 200.00 BRL DEBIT
    • 2.50000000 g DEBIT
  9. On each row verify:
Person owner:       manual30g-global-person-b
Journey provenance: manual30g-journey-b1-positive
Payment direction:  Tenant To Collaborator
Accepting party:    Collaborator
  1. Verify each row says acceptance is still pending and shows Review / accept receipt.
  2. Click Review outstanding receipts.
  3. Verify exactly two B.TA.J1 settlement receipts are outstanding.
  4. Open each Receipt for inspection only.
  5. Verify each Receipt repeats:
    • Tenant
    • Person owner B
    • B.TA.J1 Journey provenance
    • Payment direction = Tenant To Collaborator
    • Accepting party = Collaborator
  6. Return to B.TA.J1 without accepting either receipt.

STOP TEST 11 HERE — DO NOT ACCEPT EITHER RECEIPT. Test 12 owns wrong-party authorization and acceptance.

Expected

  • Exactly two final-settlement debits are created.
  • Both Journey units become zero.
  • Exactly two receipts remain outstanding.
  • Journey remains open.

[x] Test 12 — Wrong party cannot accept B.TA.J1 receipts; Identity B accepts them in-app

MUST PASS

Starting state

Exactly two B.TA.J1 Tenant→Collaborator receipts are outstanding.

Part A — Operator D must not accept

  1. Remain signed in as Operator D / Tenant A.
  2. Open Outstanding Receipts.
  3. Filter/find Identity B.
  4. Open either settlement receipt.
  5. Verify:
Payment direction: Tenant To Collaborator
Accepting party: Collaborator
  1. Locate In-app settlement acceptance.
  2. Verify the page explains that only the designated Collaborator may accept it.
  3. Verify Accept payment and sign receipt is not available to Operator D.
  4. Return to Outstanding Receipts.
  5. Verify both receipts remain outstanding.

Part B — Identity B accepts

  1. Sign out Operator D.
  2. Sign in as Identity B.
  3. Select Tenant A if prompted.
  4. Open Outstanding Receipts.
  5. Verify exactly two B.TA.J1 settlement receipts are present.
  6. Open the first Receipt.
  7. Verify direction/accepting party again.
  8. In Acceptance notes, enter:
Payment received and accepted for 30G promotion test
  1. Click Accept payment and sign receipt.
  2. Verify Accepted in-app and that the acceptance action disappears.
  3. Return to Outstanding Receipts.
  4. Payment received and accepted for 30G promotion testVerify exactly one B.TA.J1 receipt remains.
  5. Open the second Receipt and accept it using the same note.
  6. Return to Outstanding Receipts.
  7. Verify there are no remaining B.TA.J1 outstanding receipts.
  8. Open B.TA.J1 → Current Account.
  9. Verify both final-settlement rows remain historical and say:
Payment direction: Tenant To Collaborator
Accepting party: Collaborator
Final settlement receipt accepted in-app.
  1. Verify neither row shows Review / accept receipt.
  2. Sign out Identity B.
  3. Sign back in as Operator D / Tenant A.

Expected

  • Wrong party cannot accept.
  • Correct Collaborator can accept each receipt.
  • Receipts disappear from Outstanding Receipts only after acceptance.
  • Accepted receipts remain historical and non-actionable.
  • Acceptance cannot be repeated through the UI.

[x] Test 13 — Zero balance + accepted receipts allows close; Close creates no Ledger Entry

MUST PASS

Procedure

  1. As Operator D / Tenant A, reopen B.TA.J1. 2.[x] Verify Ready to close Journey.
  2. Verify BRL and Gold are zero.
  3. Verify the receipt-pending blocker is gone.
  4. Open Current Account.
  5. Record the visible:
Showing page … · N ledger entries
  1. Return to B.TA.J1.
  2. Click Close Journey.
  3. Select reason End-of-journey closure.
  4. Reason text:
30G close B.TA.J1 after receipt acceptance
  1. Notes:
30G manual promotion zero-balance close after receipt acceptance
  1. Complete reauthentication and second-person approval if required.
  2. Submit.
  3. Verify the prominent success state.
  4. Verify Journey Closed and the closed date.
  5. Verify Journey Settlement is no longer rendered.
  6. Reopen the closed Journey's Current Account.
  7. Verify its visible ledger total is still exactly N.
  8. Verify no new payout, repayment, or final-settlement row was created by Close itself.

Expected

  • Zero balance + no outstanding receipts allows closure.
  • Close is a lifecycle transition only.
  • Close creates no financial entry.

[x] Test 14 — New B.TA.J2 starts at zero while B.TA.J1 history remains visible

MUST PASS

Procedure

  1. Remain Operator D / Tenant A.
  2. Navigate to People.
  3. Search for 30G Identity B.
  4. Open Identity B.
  5. Click Create Collaborator.
  6. On New Collaborator, confirm Identity B is selected; otherwise use Find eligible Person by nickname.
  7. Enter:
Journey Start Date: today
Status:             Active
Sector:             30G Manual Sector
Location:           30G Manual Location
Task:               30G Manual Task
Payment Method:     Daily Wages
Payment Value:      45
Notes:              30G B2 after fully settled B1
  1. Click Create Collaborator.
  2. Record the new Journey ID displayed in the URL/page:
B.TA.J2 Journey ID: 714f624d-9472-4d45-8245-f594b65c5e68
  1. Open its Current Account.
  2. Verify B.TA.J1 historical earning/final-settlement rows remain visible.
  3. On those historical rows, verify Journey provenance still identifies B.TA.J1.
  4. Verify Person + Tenant net is zero after B.TA.J1 settlement.
  5. Return to B.TA.J2.
  6. Inspect Journey Settlement and verify all displayed Journey balances start at zero.
  7. Open Current + Future Earnings.
  8. Verify its header Journey provenance identifies the newly created B.TA.J2.
  9. Verify its Current Balance starts at zero.
  10. Verify no opening Ledger Entry was invented to carry B.TA.J1's former +200/+2.5g balance into B.TA.J2.

Expected

  • New Journey creation is available through supported UI.
  • New Journey starts at zero.
  • Prior Journey history remains visible with prior provenance.

[x] Test 15 — Negative debt presents Extend Journey or Record Collaborator Payment

MUST PASS

Identity / Tenant

Operator D
Tenant A
C.TA.J1
Starting: -150 BRL / -1.25 g

Procedure

  1. Navigate Collaborators → Identity C → C.TA.J1.
  2. Inspect Journey Settlement.
  3. Verify Collaborator owes Tenant.
  4. Verify both negative balances.
  5. Verify Extend Journey is available.
  6. Verify Record Collaborator Payment is available.
  7. Verify these balances are not represented as Tenant owes Collaborator.
  8. Verify Close Journey is disabled.
  9. Open Current + Future Earnings if available for this Journey.
  10. Verify negative balance text is red.

Expected

  • Debt direction is unambiguous.
  • The two supported choices are extension or repayment.
  • Negative balances cannot close.

[x] Test 16 — Extend Journey changes timing only; Earnings Operator cannot extend/full-edit

MUST PASS

Part A — Tenant Administrator extension

  1. On C.TA.J1, record the displayed projected end date.
  2. Open Current Account.
  3. Record the visible total:
Showing page … · N ledger entries
  1. Return to C.TA.J1.
  2. Click Extend Journey.
  3. Enter Additional Days = 7.
  4. Verify Current projected end and New projected end are displayed.
  5. Verify the new date is exactly seven days later.
  6. Click Confirm Extension.
  7. Verify the Journey page now shows the extended projected end date.
  8. Inspect Journey Settlement again.
  9. Verify debt is still:
-150.00 BRL
-1.25000000 g
  1. Reopen Current Account.
  2. Verify the visible ledger total is still N.
  3. Verify no payment/settlement row was created by extension.

Part B — Earnings Operator

  1. Sign out Operator D.
  2. Sign in as Earnings Operator: [email protected].
  3. Select Tenant A.
  4. Navigate Collaborators → Identity C → C.TA.J1.
  5. Verify Extend Journey is not available.
  6. Inspect the edit controls.
  7. Verify the Earnings Operator may edit only Sector, Location, and Task through the work-assignment editor.
  8. Verify full Collaborator/Journey edit is not available.
  9. Do not save a destructive change.
  10. Sign out.
  11. Return as Operator D / Tenant A.

Expected

  • Extension changes timing only.
  • Financial history and debt are unchanged.
  • Earnings Operator cannot extend or full-edit.

[x] Test 17 — Collaborator repayment zeros negative balances and creates Tenant-side receipts

MUST PASS

Identity / Tenant

Operator D
Tenant A
C.TA.J1

Procedure

  1. Reopen C.TA.J1.
  2. Click Record Collaborator Payment.
  3. Set Effective Date = today.
  4. Complete Confirm reauthentication.
  5. Select reason Final Collaborator repayment.
  6. Reason text:
30G final Collaborator repayment for C.TA.J1
  1. Notes:
30G manual promotion Collaborator-to-Tenant repayment
  1. Submit.
  2. Verify Journey Settlement now shows BRL = 0 and Gold = 0.
  3. Verify Balances settled — receipt acceptance pending.
  4. Open Current Account.
  5. Locate exactly two new settlement CREDIT rows:
    • 150.00 BRL
    • 1.25000000 g
  6. On each row verify:
Person owner:       manual30g-global-person-c
Journey provenance: manual30g-journey-c1-negative
Payment direction:  Collaborator To Tenant
Accepting party:    Tenant
  1. Open each Receipt for inspection only.
  2. Verify each Receipt repeats Tenant, Person C, C.TA.J1 provenance, direction, and accepting party.
  3. Verify both remain unaccepted/outstanding.
  4. Return to C.TA.J1 without accepting them.

STOP TEST 17 HERE — DO NOT ACCEPT EITHER RECEIPT. Test 18 owns wrong-party authorization, Tenant acceptance, and closure.


[x] Test 18 — Collaborator cannot accept Tenant-designated receipt; Tenant Administrator accepts and closes C.TA.J1

MUST PASS

Part A — wrong party

  1. Sign out Operator D.
  2. Sign in as Identity C.
  3. Select Tenant A.
  4. Open C.TA.J1's Current Account or Outstanding Receipts.
  5. Open one final-settlement Receipt.
  6. Verify:
Payment direction: Collaborator To Tenant
Accepting party: Tenant
  1. In In-app settlement acceptance, verify the page says only the designated Tenant Administrator may accept it.
  2. Verify Accept payment and sign receipt is not available.

Part B — correct party

  1. Sign out Identity C.
  2. Sign in as Operator D / Tenant A.
  3. Open Outstanding Receipts.
  4. Filter/find Identity C.
  5. Open the first receipt.
  6. Verify direction/accepting party again.
  7. In Acceptance Notes enter:
Tenant received and accepted Collaborator repayment
  1. Click Accept payment and sign receipt.
  2. Return to Outstanding Receipts and verify one C.TA.J1 receipt remains.
  3. Open the second and accept it.
  4. Return to Outstanding Receipts and verify no C.TA.J1 receipts remain.
  5. Return to C.TA.J1.
  6. Verify Ready to close Journey.
  7. Open Current Account and record visible ledger total N.
  8. Return to C.TA.J1.
  9. Click Close Journey.
  10. Use reason End-of-journey closure and complete required reauthentication/approval.
  11. Verify C.TA.J1 closes successfully at zero BRL/Gold.
  12. Reopen its Current Account.
  13. Verify visible ledger total remains N.

Expected

  • Collaborator cannot accept Tenant-designated receipts.
  • Tenant Administrator can accept both.
  • Closure is allowed only after both acceptances.
  • Close creates no additional Ledger Entry.

[x] Test 19 — Mixed signs: BRL and Gold settlement directions remain independent

MUST PASS

Identity / Tenant

Operator D
Tenant A
M.TA.J1
Starting:
  BRL +80
  Gold -0.5 g

Part A — settle only positive BRL

  1. Navigate Collaborators → Identity M → M.TA.J1.
  2. Verify both cards appear simultaneously:
    • Tenant owes Collaborator
    • Collaborator owes Tenant
  3. Under Tenant owes Collaborator, click Settle Tenant Owed Balance.
  4. Select reason Final Tenant payment.
  5. Reason text:
30G mixed M.TA.J1 BRL settlement
  1. Complete reauthentication and submit.
  2. Verify:
    • BRL = 0
    • Gold = -0.5 g
  3. Open Current Account.
  4. Verify a new 80.00 BRL DEBIT only.
  5. Verify no Gold DEBIT was created.
  6. Verify row metadata:
Person owner:       manual30g-global-person-m
Journey provenance: manual30g-journey-m1-mixed
Payment direction:  Tenant To Collaborator
Accepting party:    Collaborator

Part B — repay only negative Gold

  1. Return to M.TA.J1.
  2. Under Collaborator owes Tenant, click Record Collaborator Payment.
  3. Select reason Final Collaborator repayment.
  4. Reason text:
30G mixed M.TA.J1 Gold repayment
  1. Complete reauthentication and submit.
  2. Verify:
  • BRL = 0
  • Gold = 0
  1. Open Current Account.
  2. Verify a new 0.50000000 g CREDIT only.
  3. Verify no BRL CREDIT was created.
  4. Verify row metadata:
Person owner:       manual30g-global-person-m
Journey provenance: manual30g-journey-m1-mixed
Payment direction:  Collaborator To Tenant
Accepting party:    Tenant
  1. Do not accept either receipt yet.

Part C — prove both wrong-party cases before consuming either receipt

  1. While still Operator D / Tenant A, open Outstanding Receipts and find Identity M.
  2. Verify exactly two mixed-settlement receipts exist.
  3. Open the BRL Tenant→Collaborator receipt.
  4. Verify Operator D does not have Accept payment and sign receipt.
  5. Return and open the Gold Collaborator→Tenant receipt.
  6. Verify Operator D does have the acceptance control, but do not accept it yet.
  7. Sign out Operator D.
  8. Sign in as Identity M.
  9. Open Outstanding Receipts.
  10. Verify both receipts are still present.
  11. Open the Gold Collaborator→Tenant receipt.
  12. Verify Identity M does not have the acceptance action.
  13. Return and open the BRL Tenant→Collaborator receipt.
  14. Verify Identity M does have the acceptance action.

Part D — correct parties accept

  1. As Identity M, accept the BRL receipt with a meaningful acceptance note.
  2. Return to Outstanding Receipts.
  3. Verify exactly one Identity M receipt remains: the Gold Collaborator→Tenant receipt.
  4. Sign out Identity M.
  5. Sign back in as Operator D / Tenant A.
  6. Open the remaining Gold receipt.
  7. Verify direction/accepting party again.
  8. Accept it with a meaningful Tenant acceptance note.
  9. Return to Outstanding Receipts.
  10. Verify Identity M has no outstanding settlement receipts.
  11. Return to M.TA.J1.
  12. Verify:
BRL = 0
Gold = 0
Outstanding receipts = 0
Ready to close Journey
  1. Open Current Account and record visible ledger total N.
  2. Return to M.TA.J1.
  3. Click Close Journey and complete normal reason/notes/reauthentication.
  4. Verify Journey Closed.
  5. Reopen Current Account and verify ledger total remains N.

Expected

  • BRL and Gold are never netted.
  • No implicit conversion occurs.
  • Positive BRL creates only Tenant→Collaborator settlement.
  • Negative Gold creates only Collaborator→Tenant repayment.
  • Each wrong party is tested before either receipt is consumed.
  • Each correct party can accept only its designated receipt.
  • Receipts disappear only after proper acceptance.
  • Journey closes only after both units are zero and both receipts are accepted.
  • Close creates no financial entry.

[x] Test 20 — Account-level historical financial self-service survives inactive Membership and Actor

MUST PASS

Identity

Identity H
Login: [email protected]
Account ACTIVE
Membership INACTIVE
Actor INACTIVE
H.TA.J1 CLOSED

Procedure

  1. Sign out any current user.
  2. Sign in as Identity H.
  3. Verify authentication succeeds even though there is no usable active Tenant Actor.
  4. Verify the landing page displays exactly the intended user-facing message:
Your personal information is still available
You currently do not have access to work or administrative features. You can still view your personal information and read-only Current Account history below.

5.[x] Verify the message does not expose internal terms such as Tenant Actor, ACTIVE Membership, same-tenant membership, or authorization scope. 6. Open My Person. 7. Verify the Person is Identity H / manual30g-global-person-h. 8. Open My Current Account. 9. [x] Verify Tenant A historical entries are visible:

  • +75.00 BRL
  • -75.00 BRL
  • net 0.00 BRL
  1. Verify Tenant provenance is visibly shown for the balance/history.
  2. Verify no active work or administrative features become available.
  3. Verify Identity H cannot access current Collaborator operational/edit controls merely because historical self-service remains available.

Expected

  • Active Account authentication is independent of an active Tenant Actor.
  • Own Person and read-only financial history remain available.
  • Work/admin capability remains unavailable.
  • Messaging is understandable to a user who does not know ERS authorization internals.

5. UI-only manual promotion checklist

Before leaving the manual phase:

  • Test 01 — fresh deterministic fixture is visible and correct through the UI.
  • Test 02 — Identity A sees current + closed Journey history read-only.
  • Test 03 — Person+Tenant history crosses Journey boundaries; A.TA.J2 starts at zero and provenance is visible.
  • Test 04 — Current + Future Earnings uses selected Journey provenance/balance.
  • Test 05 — same Global Person remains financially isolated by Tenant.
  • Test 06 — non-default Tenant A accrual remains Tenant-scoped and Person/Journey-owned.
  • Test 07 — default Tenant B accrual remains correct and independent.
  • Test 08 — Expense/Ledger/Receipt canonical ownership is visibly consistent.
  • Test 09 — incorrect Expense is cancelled/reversed/recreated rather than reassigned in place.
  • Test 10 — non-zero positive Journey cannot close and inspection creates no payout.
  • Test 11 — Tenant final payment zeros positive balances and creates two Collaborator receipts; receipts remain unaccepted.
  • Test 12 — wrong party rejected; Collaborator self-service acceptance works and is final.
  • Test 13 — zero + accepted receipts allows close; Close creates no Ledger Entry.
  • Test 14 — later Journey starts at zero while prior history/provenance remains visible.
  • Test 15 — negative debt exposes Extend Journey / Record Collaborator Payment.
  • Test 16 — extension changes timing only; Earnings Operator cannot extend/full-edit.
  • Test 17 — Collaborator repayment creates CREDITs and Tenant-side receipts; receipts remain unaccepted.
  • Test 18 — wrong Collaborator rejected; Tenant Administrator accepts; C.TA.J1 closes at zero.
  • Test 19 — mixed BRL/Gold settlement directions and accepting parties remain independent.
  • Test 20 — Account-level historical self-service survives inactive Membership/Actor.

6. Promotion-blocking manual defects

Do not promote Bite 30G if any manual test shows:

  • a closed Journey with a visible non-zero balance;
  • a new Journey inheriting a prior Journey's operational balance;
  • historical Ledger Entries losing their original Journey provenance;
  • Tenant A exposing Tenant B financial history or vice versa;
  • Expense, Accrual Item, Ledger Entry, or Receipt visibly disagreeing on Person/Journey/Tenant ownership;
  • non-default Tenant accrual falling back to default;
  • Close Journey creating a payout, repayment, or other financial row;
  • Tenant→Collaborator settlement using the wrong direction or accepting party;
  • Collaborator→Tenant repayment using the wrong direction or accepting party;
  • BRL and Gold being netted or implicitly converted;
  • a final-settlement receipt remaining actionable after acceptance;
  • an accepted receipt remaining in Outstanding Receipts;
  • the wrong party being able to accept a direction-aware receipt;
  • zero balance with outstanding final-settlement receipts being closable;
  • extension changing financial history;
  • Earnings Operator receiving full Collaborator/Journey edit or extension authority;
  • Collaborator receiving administrative edit authority over its own Journey;
  • Person historical self-service disappearing merely because Membership/Actor is inactive;
  • a required manual assertion being impossible to verify through the UI.

7. Technical Promotion Gate — NOT part of the manual UI suite

Run this only after Tests 01–20 pass.

7.1 Automated gate

make local-check

The final committed SHA must remain green.

7.2 Migration chain

Verify all repository migrations apply successfully from a clean database, including the final 30G migrations through the current migration set.

7.3 Final read-only database verifier

Run:

sqlite3 -header -column backend/data/app.db \
  < bite30g-final-verify.sql

This is a technical integrity gate, not a manual UX test.

Required results include:

  • financial ownership mismatch counts = 0;
  • no closed Journey has non-zero active Ledger balance;
  • receipt direction combinations are canonical;
  • accepted receipts have complete immutable acceptance metadata;
  • every final-settlement Ledger Entry has exactly one Receipt;
  • no Membership has more than one open Journey;
  • final-settlement CHECK constraints support the implemented settlement types;
  • PRAGMA foreign_key_check returns no violations.

The migration/invariant tests remain the authoritative checks for attempts to bypass zero-balance closure, financial-owner immutability, and receipt acceptance/direction guards. Do not reproduce those attacks manually with SQL as part of this suite.


8. Final promotion decision

Bite 30G — including 30G.1, 30G.2, and 30G.3 — is ready for promotion only when:

Tests 01–20:                 PASS through UI only
make local-check:            PASS
clean migration chain:       PASS
final read-only SQL verifier: PASS
foreign-key check:           CLEAN
unexplained HTTP 500s:       NONE
cross-Tenant leakage:        NONE

If a functional assertion cannot be observed through the application UI, that is a product/observability defect to address before promotion rather than a reason to fall back to SQL or DevTools.