Skip to content

feat(inbox): ActionInboxSource::{Payroll, Governance} with SoD - #899

Open
jason931225 wants to merge 4 commits into
mainfrom
lane/pr6a-inbox-payroll-governance
Open

feat(inbox): ActionInboxSource::{Payroll, Governance} with SoD#899
jason931225 wants to merge 4 commits into
mainfrom
lane/pr6a-inbox-payroll-governance

Conversation

@jason931225

Copy link
Copy Markdown
Collaborator

Draft. Independent review required before merge (payroll SoD / four-eyes).

Candidate SHA: f112f103d4dd9b54461e939b0348845f45c78333
Base: ee018af6c01c79e7f642621b35fc56a4121a2212

Adds ActionInboxSource::{Payroll, Governance}. List only — no PayRun HTML, no inline decide, no migration.

  • Payroll: SUBMITTED runs where submitted_by <> caller and caller passes authorize_org_wide(PayrollRunManage). Branch ADMIN sees an empty source, not 403.
  • Governance: open pending four-eyes requests where requested_by <> caller, gated authorize_org_wide(RoleManage) to match decide REST.

Tests

  • cargo test -p console-action-inbox-application --lib — 13/13
  • pgtest.sh cargo test -p console-app --test action_inbox_api — 10/10 (includes submitter/other EXECUTIVE/branch ADMIN SoD)
  • payroll + governance adapter runtime-role tests — 5 + 9

HOLDs

  • No covering index (serialized migration writer).
  • Built-in EXECUTIVE does not see governance inbox items (RoleManage).
  • Same-person four-eyes remains decide-time, not a list filter.

Disjoint from #897 directory, #898 canonical list/get, GATE/AUTH/FE, #895.

@jason931225
jason931225 force-pushed the lane/pr6a-inbox-payroll-governance branch 2 times, most recently from 7dd2571 to 3f77331 Compare August 26, 2026 06:51
github-merge-queue Bot pushed a commit that referenced this pull request Aug 26, 2026
…#926)

Draft. Do not merge.

## Outcome

New disjoint test-only lane from `origin/main` (`2f99f9ea`). Exclusive
write:
`backend/crates/payroll/adapter-postgres/tests/pay_run_port_as_runtime_role.rs`.
No new `#[test]` function. Does not edit `pay_run.rs` or `lib.rs`
(#899).

Holes closed in existing tests:

- `a_decider_who_submitted_the_run_is_refused`: after SoD refuse the run
stays `SUBMITTED` (already asserted) and `decided_by` stays null; the
error is `Lifecycle(SodViolation)` and does not include coworker payroll
won amounts that actually exist on the run (`4_192_837` / `3_508_126`).
- `a_foreign_tenant_is_invisible_and_unwritable_to_the_runtime_role`:
`SubmitRun` / `DecideRun` on the foreign primary key through the
this-org runtime port is omit (`Lifecycle(NotFound)`), with no write
(status / `submitted_by` / `decided_by` / receipts unchanged). The
foreign row is first placed in `CALCULATED` / `SUBMITTED` so a visible
id would write rather than `InvalidState`.

## Verification

```
tools/lanes/pgtest.sh "$PWD" env SQLX_OFFLINE=true cargo test -p console-payroll-adapter-postgres --test pay_run_port_as_runtime_role a_decider_who_submitted_the_run_is_refused -- --nocapture
# 1 passed; 0 failed; 14 filtered out

tools/lanes/pgtest.sh "$PWD" env SQLX_OFFLINE=true cargo test -p console-payroll-adapter-postgres --test pay_run_port_as_runtime_role a_foreign_tenant_is_invisible_and_unwritable_to_the_runtime_role -- --nocapture
# 1 passed; 0 failed; 14 filtered out
```

Discovered in this binary: 15 tests. Executed here: 2 (the two extended
functions). No tests skipped, deleted, or quarantined.

## merge-tree

- vs `origin/main` (`2f99f9ea`): CLEAN
- pairwise vs PRs 897–910: CLEAN (no conflicted paths)
- #899 also writes `payroll/adapter-postgres/src/lib.rs` and
`payroll_rls_surfaces_as_runtime_role.rs`; this lane does not.

## HOLDs

- Independent adversarial review before merge (payroll SoD / tenant
omit).
- Test-only; no production writer change. Passing local tests are
unpublished evidence.
- Not merged, not released, no production authority.
@jason931225

Copy link
Copy Markdown
Collaborator Author

Status after working the 16-PR queue:

jason931225 added a commit that referenced this pull request Aug 26, 2026
…inds

Required / CI clippy -D warnings failed on directory OpenAPI tests
(clippy::manual_contains). ActionInboxItem.kind payroll/governance belongs
to #899, not this directory-phone omit. Probe unchanged: directory people
JSON has no phone key; UserSummary.phone stays.
Workbench composition reuses PgActionInboxSources via list_complete_action_inbox.
Extend the existing payroll SoD test so an EXECUTIVE submitter still does not
see their own SUBMITTED run through that path, while another EXECUTIVE does.
Governance pending company.*/hr.*/payroll.* items stay hidden from the
requester on both /me/action-inbox and workbench; a distinct natural
person with RoleManage sees them.

MyPayrollLine remains readiness (hours + *_source_present): list_my_lines
selects no *_won column, and the runtime RLS suite asserts the JSON
projection has no key containing "won".
Restack onto origin/main 9420ab0 (#897). ActionInboxSource on trunk is
still four variants; Payroll/Governance plus org-wide SoD omit is the
named hole. check-executed-tests --update after the new sqlx tests.
@jason931225
jason931225 marked this pull request as ready for review August 26, 2026 13:26
@jason931225
jason931225 force-pushed the lane/pr6a-inbox-payroll-governance branch from 9d4b3b6 to 00c4544 Compare August 26, 2026 13:26
@jason931225
jason931225 enabled auto-merge August 26, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant