StackTrading Docs

SRS: UC_4.16.2 — Career & HR Widget (LIVE)

UC_4.16.2: Career & HR Widget (LIVE)

FieldValue
BA in ChargeAnh Hoang
Date Created2026-08-26
Versionv1
Document ReferencesRFQ_ Stack Trading Prop Tech V7.pdf (§Endpoint HR Integration, §Endpoint Current Level Detail — Payout Routing, §3rd-Party Stack — HR & Payroll) · RFQ_ Website and Dashboard Implementation V7.pdf (§Part C — Career & HR Widget) · Zapier Integration V7.pdf (§Flow 6 — Level 6 Transition, §Flow 8 — Pay Raise, §Flow 13 — Time-Off Management, §Flow 34 — Rippling Payroll Execution, §Flow 35 — Rippling PTO Approval, §Flow 36 — Retainer Execution, §Table A / §Table B — Base_Income, Base_Income_Flex, Base_Income_Type, DTO_Days, Level Title) · QnA from clients — STAGE 2 Settings + Career + Viral §10 Career & HR Widget ([HR-DEF-01]) · Client instruction relayed to BA, 2026-08-26 (button rules for [Manage Payouts] and [View in Rippling]) · Client design frame — Career tab, 2026-08-26

Document References

#Original DocumentKey Sections Used
1RFQ_ Stack Trading Prop Tech V7.pdf§Endpoint HR IntegrationGET, input user_id, output {vacation_days: int, next_pay_date: "YYYY-MM-DD", base_salary_annualized: float, benefits_estimate: float, compensation_track: string}, logic "Server-side Integration: Reads compensation_track from Users table. If User is W2: Query the Rippling API to fetch real-time HR data for W-2 traders. If User is Level 6 or higher contractor: Query the SQL Database for the retainer amount." · §Endpoint Current Level DetailGET, input user_id, output includes Level, Title, Salary, PTO, payout_portal_url, and the Payout Routing rule: "Evaluate the user's Level and W-2 status. IF user is Level 1 through 5 (Global) OR Level 6+ (International Contractor): populate payout_portal_url with the static Dots login URL. IF user is Level 6+ (US W-2): populate payout_portal_url with the Rippling employee portal URL." · §3rd-Party Stack — "HR & Payroll — Rippling — 'Zero-Entry Onboarding' to pre-fill W-2 employee…"
2RFQ_ Website and Dashboard Implementation V7.pdf§Part C — "Career & HR Widget: Displaying Vacation Days, Next Pay Date, and Latest Certificate (Data from Rippling), Manage Payouts (payout_portal_url string provided within the backend's Current Level Detail payload upon dashboard load. Executes a standard target="_blank" redirect to open the static vendor URL in a new browser tab)" · the same paragraph continues into the red Resign & Close Account button — owned by UC_4.17.2, not by this UC
3Zapier Integration V7.pdf§Flow 6 — Level 6 Transition (Path A USA: Checkr gate → Offer Configurator → Comp_Track + Standard_Hours written to SQL → Rippling /events/hr/v1/worker.hire → W-2 offer; Path B International: contractor retained, Dots payout profile validated, International Base = Base_Income_Flex, "No Rippling API action is required") · §Flow 8 — Pay Raise (Base_Income vs Base_Income_Flex selection by compensation_track, Base_Income_Type Hourly/Annual retainer maths, Path A modifies the Rippling compensation rate, Path B modifies the Dots recurring payout) · §Flow 13 — Time-Off Management (Path A USA W-2 Paid DTO: "Check Used_DTO vs. DTO_Days allowance via Rippling API"; Path B International: unpaid hiatus, no limit) · §Flow 34 — Rippling Payroll Execution, trigger "Webhook from Rippling (Bi-Weekly/Monthly Payroll Run Cleared)" · §Flow 35 — Rippling PTO Approval · §Flow 36 — Retainer Execution, trigger "Webhook from Dots (Monthly Retainer Processed)" · §Table A (Forex) / §Table B (Futures) — Level Title, Base_Income, Base_Income_Flex, Base_Income_Type, DTO_Days, Severance_Pay
4QnA from clients — STAGE 2: Level-Up & Certificate, Settings, Career & HR§10 Career & HR Widget (UC_4.16.2) — [HR-DEF-01] ✅ confirmed by Adrian Stack, 2026-08-15, verbatim: "This is managed in Rippling, do not worry about it. You are just reading in the current value in this screen." · the same section records the panel as LIVE only ("a SIM/Evaluation trader has no Rippling record") and carries three BA-raised open points — the source field for the PTO value, the refresh cadence, and the unreachable/no-record state
5Client instruction relayed to BA, 2026-08-26[Manage Payouts]"If the Trader is a W2 Employee, you can hide this button. If not a W2 employee, this should link to Dots login page, in another tab." · [View in Rippling]"It opens Rippling on another Tab. Probably the employees homepage when the login. Link to the rippling login page."
6Client design frame — Career tab, 2026-08-26The tile layout and every on-screen string quoted in §9: Employment status + W-2 Employee badge · Current level / Lvl 8 / Trader · Base salary / $52,000 / Annualized · Benefits / ~$13K / Health, dental, vision (annualized) · Vacation days / 10 / 10 days PTO (Levels 6-13) · Next pay date / Mar 21 / Bi-weekly direct deposit · [Manage Payouts] · [View in Rippling ↗] · the Latest certificate panel (owned by UC_4.16.1). ⚠️ Not yet checked into References/Wireframe/ — see §10 item 11

1. Overview

FieldContent
IDUC_4.16.2
Use CaseCareer & HR Widget (LIVE)
DescriptionSpecifies the Career tab of the LIVE trader Dashboard as a read-only mirror of the trader's employment record — the Employment status badge, the Current level, Base salary, Benefits, Vacation days and Next pay date tiles, and the two outbound actions [Manage Payouts] and [View in Rippling]. Every value on this tab is displayed, never computed and never written: the source of truth is Rippling for a W-2 employee and the SQL retainer record / Dots for a contractor, and the dashboard renders whatever the backend returns from them (Ref: [HR-DEF-01], BR_4.16.2.2, BR_4.16.2.12). Scope boundary — three exclusions: (a) the Latest certificate panel on the same tab, its motion and its share controls belong to UC_4.16.1; (b) how a payout is calculated, scheduled, approved, split or executed — the Dots/Rippling payout mechanics themselves — belongs to STAGE 5: PAYOUT & WITHDRAWAL, and this UC specifies only that a button exists, when it renders and where it navigates (Ref: BR_4.16.2.9); (c) the red Resign & Close Account button on the same screen belongs to UC_4.17.2. What this UC does own end-to-end is the display contract: which endpoint feeds which tile, what each tile renders in every state, and what the two buttons do.
Zapier FlowNone is triggered by this tab — it is a pure read surface. Context only, as the producers of the data it renders: Flow 6 (Level 6 Transition) creates the Rippling worker record on the US W-2 path and keeps the Dots contractor profile on the International path, and writes Comp_Track + Standard_Hours to SQL · Flow 8 (Pay Raise) is what makes base_salary_annualized change · Flow 13 (Time-Off Management) is what makes vacation_days change — the request is filed inside Rippling, never here (Ref: BR_4.16.2.7) · Flow 34 (Rippling Payroll Execution) and Flow 36 (Retainer Execution) are what make next_pay_date roll forward · Flow 35 (Rippling PTO Approval) mirrors an approved PTO request into the immutable ledger
Zapier TableTable A (Forex) and Table B (Futures)Level Title (feeds the Current level sub-label), Base_Income / Base_Income_Flex / Base_Income_Type (the contracted rate behind base_salary_annualized), DTO_Days (the level's PTO allowance behind the Vacation days caption). Read server-side only; the frontend never queries a Zapier Table (Ref: BR_4.16.2.5, BR_4.16.2.7)
3rd PartyRippling — HR & Payroll system of record for W-2 employees: PTO balance, accrual and approval, payroll cycle, benefits enrolment. Owns all of it; the dashboard reads and deep-links only (Ref: [HR-DEF-01]) · Dots — payout portal for contractors (Levels 1–5 Global, and Level 6+ International Contractors), reached through [Manage Payouts] (Ref: BR_4.16.2.9)

Tiles covered by this UC (client design frame, 2026-08-26):

#Tile / ControlFed byRef
1Employment status + track badgecompensation_track + the W-2 discriminatorBR_4.16.2.3
2Current levelLvl [N] + [Title]GET /current-level-detailLevel, TitleBR_4.16.2.4
3Base salary — amount + cadence captionGET /hr-integrationbase_salary_annualizedBR_4.16.2.5
4Benefits — estimate + coverage captionGET /hr-integrationbenefits_estimateBR_4.16.2.6
5Vacation days — balance + allowance captionGET /hr-integrationvacation_daysBR_4.16.2.7
6Next pay date — date + cadence captionGET /hr-integrationnext_pay_dateBR_4.16.2.8
7[Manage Payouts]GET /current-level-detailpayout_portal_urlBR_4.16.2.9
8[View in Rippling ↗]Static Rippling URL, environment configBR_4.16.2.10
9Latest certificate panelOut of scope. Ref: UC_4.16.1 §9.2

2. Trigger

  • The trader activates the Career tab in the persistent sidebar (Ref: UC_4.1.2 §2), and the Career tab mounts.
  • The trader returns to an already-mounted Career tab after the dashboard reconnects its WebSocket, or re-activates the browser tab — both re-run the same fetch (Ref: BR_4.16.2.14).

3. Pre-conditions

  • The trader is authenticated and the account type is LIVE. A SIM trader has no Career tab at all — Career & HR data only exists once the trader is contracted, and a SIM/Evaluation trader has no Rippling and no Dots record (Ref: [HR-DEF-01], BR_4.16.2.1).
  • The trader has an employment record the backend can resolve: either a Rippling worker record (created by Flow 6 Path A on the US W-2 path, or at Level 1 for the ICA), or an active Dots contractor payout profile with a retainer row in SQL (Flow 6 Path B, International). Which one exists determines the whole rendering of this tab (Ref: BR_4.16.2.3).
  • GET /current-level-detail and GET /hr-integration are reachable for the logged-in user_id. Neither is a precondition for the other — each tile degrades independently (Ref: BR_4.16.2.13).

4. Post-conditions

  • The Career tab shows the trader's employment record as it stood at the moment of the fetch. No server state has changed — this tab issues no write of any kind (Ref: BR_4.16.2.12).
  • If the trader activated [Manage Payouts] or [View in Rippling], a new browser tab has been opened at the vendor and the Dashboard tab is untouched and still authenticated (Ref: BR_4.16.2.11).

5. Basic Flow — Career tab load (W-2 employee)

  1. The trader activates the Career tab. The tab mounts with every tile in its skeleton/loading state (Ref: BR_4.16.2.13).
  2. The frontend issues GET /current-level-detail with the authenticated user_id. The response supplies Level, Title and payout_portal_url for this tab (the remaining fields of that payload feed other widgets and are ignored here). Ref: BR_4.16.2.4, BR_4.16.2.9.
  3. In parallel, the frontend issues GET /hr-integration with the same user_id. Ref: BR_4.16.2.2.
  4. Server-side, GET /hr-integration reads compensation_track from the Users table, resolves the trader as W-2, and queries the Rippling API for the real-time HR values. It returns {vacation_days, next_pay_date, base_salary_annualized, benefits_estimate, compensation_track}. Ref: BR_4.16.2.2.
  5. The frontend resolves the employment status from the returned discriminator and renders the badge W-2 Employee. Ref: BR_4.16.2.3.
  6. The three-across header row renders: Current level = Lvl [Level] with [Title] beneath (Ref: BR_4.16.2.4) · Base salary = base_salary_annualized formatted per Ref: CR-11 with the caption Annualized (Ref: BR_4.16.2.5) · Benefits = benefits_estimate with the caption Health, dental, vision (annualized) (Ref: BR_4.16.2.6).
  7. The left column renders Vacation days = vacation_days with the allowance caption derived from the level's DTO_Days band, and Next pay date = next_pay_date formatted per Ref: CR-08 with the caption Bi-weekly direct deposit. Ref: BR_4.16.2.7, BR_4.16.2.8.
  8. [Manage Payouts] is not rendered — the trader is a W-2 employee, and Rippling already carries their pay. Ref: BR_4.16.2.9.
  9. [View in Rippling ↗] renders and, on activation, opens the Rippling employee portal in a new browser tab; if there is no live Rippling session in that browser, Rippling presents its own login page and lands the trader on the employee homepage afterwards. The Dashboard tab keeps its session. Ref: BR_4.16.2.10, BR_4.16.2.11.
  10. The Latest certificate panel to the right mounts independently — Ref: UC_4.16.1 §6.

6. Alternative Flow — Career tab load (contractor)

Applies when the trader is not a W-2 employee: Levels 1–5 (Global) and Level 6+ International Contractors. Steps 1–3 and 10 are identical to §5; only the differences are listed.

  1. Server-side, GET /hr-integration reads compensation_track and does not find a W-2 trader. For a Level 6+ contractor it queries the SQL Database for the retainer amount instead of calling Rippling; the retainer is the Base_Income_Flex rate written by Flow 6 Path B. Ref: BR_4.16.2.2, BR_4.16.2.5.
  2. The badge renders as the contractor variant rather than W-2 Employee. Ref: BR_4.16.2.3.
  3. Benefits has no W-2 benefits package behind it and renders its empty state rather than a figure. Ref: BR_4.16.2.6.
  4. Vacation days — an international contractor takes an unpaid hiatus with no day limit (Flow 13 Path B), not a paid DTO balance, and DTO_Days for Levels 1–5 is 0 in both Table A and Table B. The tile renders its non-W-2 state. Ref: BR_4.16.2.7.
  5. Next pay date carries the contractor cadence caption — the monthly retainer paid through Dots (Flow 36) — not Bi-weekly direct deposit. Ref: BR_4.16.2.8.
  6. [Manage Payouts] is rendered and, on activation, opens the Dots login page in a new browser tab, using the payout_portal_url returned at step 2 of §5. Ref: BR_4.16.2.9, BR_4.16.2.11.

7. Exceptional Flow

  • GET /hr-integration fails or times out → the four HR tiles (Base salary, Benefits, Vacation days, Next pay date) enter their error state and Ref: TE-SYS-01 is shown once for the tab. Current level, the two buttons and the Latest certificate panel are unaffected — they do not depend on this call. Ref: BR_4.16.2.13.
  • GET /current-level-detail fails or times outCurrent level enters its error state and [Manage Payouts] is not rendered, because its destination URL is unknown; the four HR tiles are unaffected. Ref: BR_4.16.2.13.
  • Rippling is unreachable from the backend while the endpoint itself answers → the endpoint returns the affected fields as null rather than failing the whole call, and each affected tile renders its empty state individually. A null is an empty state, never a zero — rendering 0 vacation days when the balance is merely unknown is a defect. Ref: BR_4.16.2.13.
  • The trader has no employment record yet — LIVE and contracted, but the Rippling worker or the SQL retainer row has not been provisioned (Flow 6 still mid-flight, or a Level 1–5 trader who has no salaried record at all) → every affected tile renders its empty state; the tab itself still mounts and the certificate panel and [View in Rippling] still work. Ref: BR_4.16.2.13.
  • payout_portal_url is absent or empty for a non-W-2 trader[Manage Payouts] is not rendered. It is never rendered pointing at nothing, and never rendered disabled. Ref: BR_4.16.2.9.
  • The browser blocks the new tab (pop-up blocker) on either button → the Dashboard state is unchanged and no error is raised by the application; recovery is the browser's own pop-up prompt. Ref: BR_4.16.2.11.

8. Business Rules

BR_4.16.2.1: LIVE Only — and This UC Owns the HR Tiles Only

  • The Career tab exists only for a LIVE trader. Career & HR data comes into being when the trader is contracted; a SIM/Evaluation trader has no Rippling record and no Dots payout profile, so the tab is not reachable for them at all (Ref: [HR-DEF-01]).
  • Within the tab, this UC specifies the Employment status badge, the Current level, Base salary, Benefits, Vacation days and Next pay date tiles, and the [Manage Payouts] and [View in Rippling] buttons.
  • Not owned here: the Latest certificate panel, its motion, its share targets, the Redacted version toggle, [View], [Download] and [Replay] → Ref: UC_4.16.1. The payout calculation, schedule, approval, profit-split and execution behind [Manage Payouts]STAGE 5: PAYOUT & WITHDRAWAL. The red Resign & Close Account button → UC_4.17.2. The promotion mechanics that change Level and Base salarySTAGE 6: CAREER PATH & PROFESSIONALIZATION (Flow 4, Flow 6, Flow 8).

BR_4.16.2.2: Read-Only Mirror — Two Endpoints, One Load, No Polling

The tab is fed by exactly two backend reads, both issued once when the tab mounts:

#EndpointInputOutput consumed by this UCServer-side logic
1GET /hr-integrationuser_id (from the session; never a client-supplied parameter)vacation_days (int) · next_pay_date (YYYY-MM-DD) · base_salary_annualized (float) · benefits_estimate (float) · compensation_track (string)Reads compensation_track from the Users table. If the user is W-2 → queries the Rippling API for real-time HR data. If the user is a Level 6+ contractor → queries the SQL Database for the retainer amount.
2GET /current-level-detailuser_idLevel (int) · Title (string) · payout_portal_url (string)Returns the trader's current status. Payout Routing: evaluates Level and W-2 status → Level 1–5 (Global) or Level 6+ (International Contractor) ⇒ static Dots login URL; Level 6+ (US W-2) ⇒ Rippling employee portal URL.
  • The two calls are independent and parallel. Neither blocks the other, and a failure in one degrades only its own tiles (Ref: BR_4.16.2.13).
  • GET /current-level-detail is the same call the dashboard already makes on load for the header and the Bento Grid. The Career tab reuses that response and does not issue a second identical request.
  • The frontend performs no calculation on any returned value — no accrual, no proration, no annualisation, no balance arithmetic. It formats and displays exactly what the backend returns (Ref: [HR-DEF-01]).
  • The frontend never calls Rippling or Dots directly, and never reads a Zapier Table. Both are server-side integrations behind GET /hr-integration; the browser holds no vendor credential.

BR_4.16.2.3: Employment Status Resolution

The Employment status badge is resolved from the trader's compensation arrangement, not from their level alone:

TraderBadgecompensation_trackPay instrument
Level 6+, USA, Track A (Full Benefits)W-2 EmployeeStandardRippling payroll (Base_Income)
Level 6+, USA, Track B (Flex Cash)W-2 EmployeeFlexRippling payroll (Base_Income_Flex)
Level 6+, International ContractorContractor variantFlex (International defaults to Base_Income_Flex)Dots monthly retainer
Level 1–5, GlobalContractor variant— (no salaried record; Base_Income = $0 in Table A/B for Levels 1–3)Dots, per-payout
  • ⚠️ compensation_track alone cannot resolve this badge. It separates Standard from Flex, but a US Track B trader and an International contractor both carry Flex while being a W-2 employee and a contractor respectively. A dedicated W-2 discriminator is required in the GET /hr-integration response — the same gap Current Level Detail already implies by saying "Evaluate the user's Level and W-2 status". Written here as an explicit field; the exact name and values are pending (Ref: §10 item 1, and the identical open point at UC_4.16.1 §10 item 8).
  • The badge is the single switch for the rest of the tab: it drives the Benefits state (BR_4.16.2.6), the Vacation days state (BR_4.16.2.7), the Next pay date caption (BR_4.16.2.8) and the visibility of [Manage Payouts] (BR_4.16.2.9). It must therefore be resolved before those tiles render, and all five must agree — a W-2 Employee badge shown next to a visible [Manage Payouts] is a contradiction.

BR_4.16.2.4: Current Level Tile

  • Renders Lvl [Level] as the primary value and [Title] as the sub-label, both taken verbatim from GET /current-level-detail.
  • Title is the level's Level Title from Table A (Forex) or Table B (Futures), resolved server-side by the trader's asset class — Associate Trader (L1–5) · Trader (L6–9) · Senior Trader 1 (L10–13) · Senior Trader 2 (L14–17) · Principal Trader (L18–21) · Managing Principal Trader (L22–24). The frontend does not re-derive the title from the level number.
  • This tile shows the level the trader currently holds. It is not a progress bar and carries no next-level target — that belongs to the Level Progression widget (Ref: UC_4.12.6) and the Bento Grid career map.
  • The value changes only when a promotion completes (Flow 4, or Flow 3H for the first SIM → LIVE transition). This tab does not listen for LEVEL_PROMOTION; it will show the new level at the next load (Ref: BR_4.16.2.14).

BR_4.16.2.5: Base Salary Tile

  • Renders base_salary_annualized from GET /hr-integration, formatted per Ref: CR-11 (thousands separator, max 2 decimals, full value on hover), with the static caption Annualized.
  • The figure is annualised on the server, whatever the underlying contract shape. Table A/B carry Base_Income_Type = Hourly for the lower salaried levels and Annual from the mid levels upward; Flow 8 already defines the conversion (HourlyRate × ((Standard_Hours × 52) / 12) monthly). The frontend never converts an hourly rate. It displays the annualised number the endpoint returns.
  • Which rate is behind the figure follows the track, and is resolved server-side: compensation_track == 'Standard'Base_Income; compensation_track == 'Flex'Base_Income_Flex; an International contractor always resolves to Base_Income_Flex.
  • [If base_salary_annualized is null or the trader has no salaried record] (typically Levels 1–5, where Base_Income is $0) → the tile renders its empty state, not $0.00 (Ref: BR_4.16.2.13).
  • The value changes only through Flow 8 (Pay Raise) or Flow 6 (Level 6 Transition). Nothing on this tab can alter it.

BR_4.16.2.6: Benefits Tile

  • Renders benefits_estimate from GET /hr-integration, formatted per Ref: CR-11, with the caption Health, dental, vision (annualized).
  • The value is an estimate of the employer-funded benefits package, owned by Rippling, produced by the benefits enrolment the trader completed in Flow 6 Path A, Track A (Full Benefits). The dashboard does not price, itemise or explain it, and offers no enrolment or change action — those live in Rippling, reached through [View in Rippling] (BR_4.16.2.10).
  • [If the trader is on Track B (Flex Cash) or is a contractor] → there is no benefits package. The tile renders its empty state. Flow 6 makes benefits enrolment conditional on Track A only, so a Flex trader having a benefits_estimate figure is a data error, not a display case.
  • [If benefits_estimate is null] → empty state, never $0.00 (Ref: BR_4.16.2.13).

BR_4.16.2.7: Vacation Days Tile — Read-Only, Rippling Owns It

  • Renders vacation_days from GET /hr-integration as the primary integer value, with a caption naming the level's allowance.
  • 🔴 No PTO write path exists anywhere in this product. Client-confirmed 2026-08-15 ([HR-DEF-01]), verbatim: "This is managed in Rippling, do not worry about it. You are just reading in the current value in this screen." Concretely: no PTO logging UI, no request form, no approval workflow, no accrual calculation, no balance arithmetic, and no PTO write endpoint. A trader who wants time off files it inside Rippling, reached via [View in Rippling].
  • The allowance behind the caption is DTO_Days from Table A / Table B, banded by level. Resolved server-side; the frontend does not hold the band table:
Level bandDTO_DaysCaption shape (design frame)
1 – 50No paid allowance — see the non-W-2 state below
6 – 131010 days PTO (Levels 6-13)
14 – 211515 days PTO (Levels 14-21)
22 – 242020 days PTO (Levels 22-24)
  • [If the trader is an International Contractor] → they have no paid DTO. Flow 13 Path B grants an unpaid hiatus with no day limit, which is not a balance and cannot be rendered as an integer. The tile renders its non-W-2 state rather than a number (Ref: §10 item 4).
  • [If the trader is Level 1–5]DTO_Days is 0. The tile renders its empty state.
  • The displayed balance is the remaining balance as Rippling reports it (Flow 13 Path A checks Used_DTO against DTO_Days inside Rippling). Whether the endpoint returns remaining or entitled days is the single most consequential ambiguity on this tile (Ref: §10 item 3).

BR_4.16.2.8: Next Pay Date Tile

  • Renders next_pay_date from GET /hr-integration — an ISO YYYY-MM-DD value on the wire (Ref: CR-08) — displayed in the short human form shown in the design frame (Mar 21), with a caption naming the pay cadence.
  • The cadence caption follows the pay instrument, resolved from BR_4.16.2.3:
TraderProducerCaption
W-2 employeeFlow 34 — Rippling Payroll Execution, trigger "Bi-Weekly/Monthly Payroll Run Cleared"Bi-weekly direct deposit (design frame)
Level 6+ International ContractorFlow 36 — Retainer Execution, trigger "Dots (Monthly Retainer Processed)"Monthly retainer via Dots
Level 1–5No recurring salary cycleEmpty state
  • The date is read, not computed. The frontend does not derive the next date from a cycle length, a last-paid date or a calendar rule; it renders the date the endpoint returns, and if the endpoint returns null the tile renders its empty state (Ref: BR_4.16.2.13).
  • The tile is display-only — it is not a link to a payslip, a payout history or a ledger entry. Those belong to STAGE 5: PAYOUT & WITHDRAWAL.
  • ⚠️ The design frame's caption Bi-weekly direct deposit is a fixed string in the mockup, while Flow 34's trigger admits both Bi-Weekly and Monthly payroll runs. Written here as driven by the actual cycle, not hardcoded (Ref: §10 item 5).

BR_4.16.2.9: [Manage Payouts] — Hidden for W-2, Dots for Everyone Else

  • Visibility (client instruction, 2026-08-26): [If the trader is a W-2 Employee] → the button is not rendered at all — hidden, not disabled, not greyed. [If the trader is not a W-2 Employee] → the button renders.
  • Destination: the Dots login page, opened in a new browser tab (Ref: BR_4.16.2.11). The URL is the payout_portal_url string carried in the GET /current-level-detail payload on dashboard load — "a standard target="_blank" redirect to open the static vendor URL in a new browser tab". It is a static vendor URL, not a per-trader deep link and not an SSO hand-off; Dots authenticates the trader itself.
  • ⚠️ This supersedes the RFQ's Payout Routing for the US W-2 branch. RFQ_ Stack Trading Prop Tech V7.pdf specifies payout_portal_url = the Rippling employee portal URL when the trader is Level 6+ US W-2. Under the client's 2026-08-26 instruction the button never renders for a W-2 trader, so that branch is never consumed by this tab and Rippling is reached exclusively through [View in Rippling] (BR_4.16.2.10). The backend may keep populating the field for other consumers; this UC ignores it whenever the trader is W-2 (Ref: §10 item 6).
  • [If the trader is not W-2 and payout_portal_url is absent, empty or null] → the button is not rendered. A payout button pointing at nothing is worse than no button.
  • Scope: this BR governs whether the button appears and where it points, nothing more. Payout eligibility, the profit split, the payout schedule, minimum thresholds, approval and execution are owned by STAGE 5: PAYOUT & WITHDRAWAL.

BR_4.16.2.10: [View in Rippling] — Always Available, Opens the Rippling Portal

  • The button renders on the Career tab and, on activation, opens Rippling in a new browser tab (Ref: BR_4.16.2.11).
  • Destination: the Rippling login page. Rippling handles its own authentication and lands the trader on the employee homepage once logged in; if the browser already holds a live Rippling session, the trader arrives at the homepage directly. There is no SSO hand-off, no token in the URL and no deep link into a specific Rippling screen from our side.
  • This is the only route by which a trader acts on anything shown on this tab — requesting time off, changing benefits elections, downloading a payslip, updating tax or bank details. All of it happens inside Rippling (Ref: [HR-DEF-01], BR_4.16.2.7).
  • The URL is an environment configuration value, not a per-trader value from an endpoint. It therefore renders even when both endpoints of BR_4.16.2.2 fail.
  • ⚠️ The client's instruction gave no visibility condition for this button, so it is written as always rendered on the Career tab. That leaves an international contractor — who has a Rippling record for their ICA but no Rippling payroll, PTO or benefits — with a button into a portal that shows them almost nothing (Ref: §10 item 7).

BR_4.16.2.11: Outbound Vendor Navigation Standard

Applies to both [Manage Payouts] and [View in Rippling]:

  • Navigation is a standard target="_blank" new-tab open. The Dashboard tab is never replaced, never reloaded and never logged out; the trader returns to it with their session, their WebSocket state and their open positions untouched.
  • The outbound link carries rel="noopener noreferrer" — the vendor tab must not obtain a handle on the Dashboard window.
  • No credential, token, user_id or PII is ever appended to the vendor URL. Both destinations are static vendor URLs and both vendors authenticate the trader themselves.
  • The application shows no interstitial, no confirmation modal and no toast for either navigation.
  • [If the browser's pop-up blocker suppresses the new tab] → nothing happens in the Dashboard, no application error is raised, and recovery is entirely the browser's own pop-up prompt.

BR_4.16.2.12: No Write Path From This Tab

  • The Career tab issues GET requests only. There is no POST, PUT, PATCH or DELETE behind any tile or control specified in this UC.
  • Nothing on this tab is editable, and nothing on it is a form field. Every tile is a label; the only interactive elements are the two outbound buttons.
  • The trader cannot log PTO, request time off, change their track, change their hours, change their benefits elections, trigger a payout or edit their pay details from here — every one of those is a Rippling or Dots action, or a Zapier flow that runs without dashboard involvement (Flow 6, Flow 8, Flow 13).
  • Consequence for QC: no test on this tab should ever assert a state change on the server. A change observed after visiting this tab means a defect.

BR_4.16.2.13: Per-Tile Degradation — Loading, Empty, Error

Each tile resolves its own state independently. The tab never blocks as a whole and never renders a full-screen error:

StateWhenWhat renders
LoadingBetween mount and the response of the endpoint feeding the tileSkeleton placeholder in the tile's own slot. The tile keeps its grid position — the layout must not reflow when values arrive.
EmptyThe field is null, or the trader's arrangement has no such value (contractor benefits, Level 1–5 salary, Level 1–5 PTO)The tile's empty state. Never a substituted 0, $0.00 or a fabricated date — an unknown value and a zero value are different facts and must not look alike.
ErrorThe endpoint feeding the tile returned an error, timed out, or the network is unavailableThe tile's error state, plus Ref: TE-SYS-01 shown once per tab load, not once per failed tile.
  • The blast radius of each failure is fixed: GET /hr-integration failing affects only Base salary, Benefits, Vacation days and Next pay date. GET /current-level-detail failing affects only Current level and [Manage Payouts]. Neither affects the Latest certificate panel, which has its own endpoint and its own error handling (Ref: UC_4.16.1 §7).
  • [View in Rippling] renders in every state, including total endpoint failure — its URL is configuration, not data. This is deliberate: when the dashboard cannot show the trader their HR data, the escape hatch to the system that owns it must still work.
  • There is no retry button and no auto-retry on this tab. Recovery is re-entering the tab (Ref: BR_4.16.2.14).
  • ⚠️ The exact copy for the empty and error states of each tile is not specified by any client source and is written here as a state, not as a string (Ref: §10 item 8).

BR_4.16.2.14: Refresh Cadence and Staleness

  • The two reads of BR_4.16.2.2 fire on tab mount. There is no polling interval, no WebSocket subscription and no push event for HR data — none of these values changes on a trading timescale. vacation_days moves when Rippling approves a request, next_pay_date on a payroll run, base_salary_annualized on a promotion.
  • The data is therefore a snapshot as at the last load, and is refreshed by: re-entering the Career tab from another tab, reloading the Dashboard, or a WebSocket reconnect that re-runs the dashboard load (Ref: CR-14).
  • A trader who is promoted while sitting on the Career tab keeps seeing the old level and the old salary until they leave and return. This UC does not listen for LEVEL_PROMOTION — the promotion cinematic force-redirects the trader to the Command tab anyway (Ref: UC_4.16.1 §5 step 2), so the Career tab is re-mounted on the trader's own return.
  • Whether the backend calls Rippling live on every request or serves a cached value, and the TTL if cached, is a backend decision that changes what "current" means on this screen and is not yet ruled (Ref: §10 item 2).

BR_4.16.2.15: Display Formatting Standards

  • Monetary values (Base salary, Benefits) — Ref: CR-11: comma thousands separator, max 2 decimal places, full value in a tooltip on hover (Ref: CR-10). The design frame's abbreviated form ~$13K for Benefits is an approximation by design intent, and the tooltip must still carry the exact figure (Ref: §10 item 9).
  • Dates (Next pay date) — transported as ISO YYYY-MM-DD per Ref: CR-08 and rendered in the short human form of the design frame.
  • Integers (Vacation days) — rendered as a plain integer with no unit suffix on the primary value; the unit lives in the caption beneath.
  • Overflow — every tile value and caption uses wrap text. No tile value is ever truncated with an ellipsis: a truncated salary or a truncated pay date is unreadable rather than merely compressed.

9. Screen Description

Career tab, LIVE trader. The Latest certificate panel occupying the right-hand region of the same screen is not described here — Ref: UC_4.16.1 §9.2. The persistent header (Days remaining, Squawk box, Daily loss limit, Close in, notifications) and the persistent sidebar are Ref: UC_4.1.1 and UC_4.1.2.

No.Field NameField TypeDisplaying rule / Behaviour rule
1Employment statusLabel + BadgeDisplaying rule:- Static label Employment status followed by the resolved badge — W-2 Employee for a W-2 trader, the contractor variant otherwise. Ref: BR_4.16.2.3.- Rendered at the top of the tab, above the three-across tile row, and present in every state of the tab.- [If the W-2 discriminator is unresolved or the trader has no employment record] → badge renders its empty state; the label stays. Ref: BR_4.16.2.13.- Overflow: Wrap text.Behaviour rule:- Read-only, not clickable, no tooltip.- Impact: this badge is the switch that decides rows 4, 5, 6 and 8. It must be resolved before those rows render. Ref: BR_4.16.2.3.
2Current levelLabelDisplaying rule:- Card label Current level; primary value Lvl [Level]; sub-label [Title] (e.g. Trader). Both from GET /current-level-detail. Ref: BR_4.16.2.4.- [If GET /current-level-detail fails] → error state; the HR tiles in rows 4–7 are unaffected. Ref: BR_4.16.2.13.- Overflow: Wrap text.Behaviour rule:- Read-only. Not a link to the Bento Grid career map and not a progress control.
3Base salaryLabelDisplaying rule:- Card label Base salary; primary value base_salary_annualized formatted per Ref: CR-11; sub-label Annualized. Ref: BR_4.16.2.5.- [If null / no salaried record — typically Levels 1–5] → empty state, never $0.00. Ref: BR_4.16.2.13.- Overflow: Wrap text.Behaviour rule:- Read-only. Hover shows the full value per Ref: CR-10.
4BenefitsLabelDisplaying rule:- Card label Benefits; primary value benefits_estimate formatted per Ref: CR-11; sub-label Health, dental, vision (annualized). Ref: BR_4.16.2.6.- [If the trader is on Track B (Flex Cash) or is a contractor] → empty state; there is no benefits package to estimate.- Overflow: Wrap text.Behaviour rule:- Read-only. No enrolment, no breakdown, no link — benefits are changed inside Rippling via row 9. Ref: BR_4.16.2.10.
5Vacation daysLabelDisplaying rule:- Card label Vacation days with its icon; primary value vacation_days as a plain integer; caption naming the level band allowance, e.g. 10 days PTO (Levels 6-13). Ref: BR_4.16.2.7.- [If the trader is an International Contractor] → non-W-2 state — unpaid hiatus has no day limit and cannot render as a balance.- [If Level 1–5]DTO_Days is 0 → empty state.- Overflow: Wrap text.Behaviour rule:- 🔴 Read-only. There is no PTO logging, request or approval control anywhere on this tab. Time off is requested inside Rippling via row 9. Ref: [HR-DEF-01], BR_4.16.2.7, BR_4.16.2.12.- Impact: none. No request is issued and no state is written by this tile.
6Next pay dateLabelDisplaying rule:- Card label Next pay date with its icon; primary value next_pay_date rendered short-form (e.g. Mar 21); caption naming the cadence — Bi-weekly direct deposit for W-2, the Dots monthly retainer for an international contractor. Ref: BR_4.16.2.8, CR-08.- [If null / no recurring cycle — Levels 1–5] → empty state, never a fabricated date.- Overflow: Wrap text.Behaviour rule:- Read-only. Not a link to a payslip, a payout history or a ledger entry — those belong to STAGE 5.
7Manage PayoutsButtonDisplaying rule:- Label Manage Payouts, in the action row at the foot of the left column.- [If the trader is a W-2 Employee]not rendered — hidden, not disabled. Ref: BR_4.16.2.9.- [If the trader is not W-2 and payout_portal_url is absent/empty/null]not rendered.- [Otherwise] → rendered.Behaviour rule:- On activation: opens the Dots login page — the static payout_portal_url from GET /current-level-detail — in a new browser tab with rel="noopener noreferrer". No interstitial, no confirmation, no toast. Ref: BR_4.16.2.9, BR_4.16.2.11.- Impact: none server-side. No request is issued, no state is written; the Dashboard tab keeps its session and its WebSocket. Payout mechanics on the far side of the link are owned by STAGE 5: PAYOUT & WITHDRAWAL.
8View in RipplingButton (with external-link icon)Displaying rule:- Label View in Rippling with a trailing external-link icon, beside row 7 in the same action row.- Always rendered on the Career tab, including when both endpoints fail — its URL is environment configuration, not response data. Ref: BR_4.16.2.10, BR_4.16.2.13.Behaviour rule:- On activation: opens the Rippling login page in a new browser tab with rel="noopener noreferrer"; Rippling authenticates the trader and lands them on the employee homepage. If a live Rippling session already exists in that browser, the trader arrives at the homepage directly. No SSO hand-off, no token in the URL. Ref: BR_4.16.2.10, BR_4.16.2.11.- Impact: none server-side. This is the only route from this tab to any HR action — time off, benefits, payslips, tax and bank details. Ref: [HR-DEF-01].

10. Open Items Pending Client / BE Confirmation

#ItemWritten in this UC asWhy it needs a rulingSeverity
1No field distinguishes a US W-2 employee from an International Contractor. GET /hr-integration returns compensation_track (Standard / Flex) only, yet Current Level Detail's own Payout Routing says "Evaluate the user's Level and W-2 status" — implying a discriminator that is never named in any payload. A US Track B trader and an International contractor both carry Flex.Written as an explicit W-2 discriminator field in the GET /hr-integration response, name and values TBD (Ref: BR_4.16.2.3)Without it the Employment status badge cannot be resolved, [Manage Payouts] cannot decide whether to render, and Benefits / Vacation days / Next pay date cannot pick their state. Four tiles and one button all fail on the same missing field. Blocking for BE. Same gap as UC_4.16.1 §10 item 8.🔴
2Refresh cadence of the Rippling read is unspecified — live API call per request, or a cached value with a TTL? Raised by BA on 2026-08-15 in the STAGE 2 QnA and never put to the client.Written as fetch-on-mount, no polling, snapshot semantics (Ref: BR_4.16.2.14)Decides what "current" means on this screen and whether a Rippling rate-limit or outage is visible to the trader. Also decides whether a trader who books PTO in Rippling sees the new balance on their next tab visit or hours later. Blocking for BE.🔴
3Does vacation_days carry the remaining balance or the entitled allowance? Flow 13 Path A checks Used_DTO against DTO_Days, so both numbers exist in Rippling. The design frame shows 10 above the caption 10 days PTO (Levels 6-13) — the two numbers are identical there, which hides the ambiguity entirely.Written as the remaining balance (Ref: BR_4.16.2.7)If it is the entitlement, a trader who has used 8 of 10 days still reads 10 and plans against a balance they do not have. Blocking for BE.🔴
4What does Vacation days show for an International Contractor? Flow 13 Path B gives an unpaid hiatus with "No limit on requested days" — not a balance.Written as a distinct non-W-2 state, copy not specified (Ref: BR_4.16.2.7)Rendering 0 would read as "you have no time off", which is the opposite of the truth. Rendering the tile at all may be wrong.🟡
5Is the pay cadence caption fixed or derived? The design frame hardcodes Bi-weekly direct deposit, but Flow 34's trigger is "Bi-Weekly/Monthly Payroll Run Cleared" and an international contractor is on a monthly Dots retainer (Flow 36).Written as derived from the trader's actual cycle, with the frame's string as the W-2 case (Ref: BR_4.16.2.8)A monthly-paid trader told they are paid bi-weekly is a payroll support ticket. Needs either a cadence field in the payload or a confirmed rule.🟡
6payout_portal_url for a W-2 trader is now dead data. The RFQ populates it with the Rippling employee portal URL for Level 6+ US W-2, but the client's 2026-08-26 instruction hides [Manage Payouts] for exactly that group.Written per the client instruction — the button is hidden for W-2 and the field is ignored in that case (Ref: BR_4.16.2.9)Confirm whether the backend should stop populating the Rippling branch, or whether another consumer still needs it. Also confirms nothing else on the dashboard renders a payout link for W-2 traders.🟡
7Should [View in Rippling] render for a non-W-2 trader? Flow 6 Path B states "No Rippling API action is required, as the International Contractor signed their agreement at Level 1" — so they have a Rippling record for the ICA, but no payroll, no PTO and no benefits inside it. The client's instruction gave no visibility condition.Written as always rendered (Ref: BR_4.16.2.10)A contractor clicking through to an employee portal that shows them nothing is a confusing dead end; hiding it removes their route to their signed ICA. Either answer is defensible — the client must pick.🟡
8Empty-state and error-state copy is not specified for any tile. No client source gives a string for "no benefits package", "no salaried record", "PTO unavailable" or "Rippling unreachable".Written as states with an explicit prohibition on substituting 0 / $0.00 / a fabricated date (Ref: BR_4.16.2.13)Six tiles × three states with no agreed copy is a build blocker for FE and untestable for QC. Once agreed, the error toast should be registered in Common_rule/list-toast-popup.md alongside Ref: TE-SYS-01.🟡
9Is Benefits displayed abbreviated (~$13K) or in full? The design frame shows the abbreviated form with a tilde, which Ref: CR-11 does not define.Written as CR-11 formatting with the frame's abbreviation treated as design intent and the exact figure preserved in the hover tooltip (Ref: BR_4.16.2.15)If abbreviation is intended, the rounding rule (~$13K from $13,412) needs stating, and CR-11 needs an abbreviated-display clause so other screens do it identically.🟢
10Exact endpoint paths are not given by any source. The RFQ names the endpoints functionally — HR Integration, Current Level Detail — not as routes.Written as GET /hr-integration and GET /current-level-detail, matching the naming convention used across the dashboard UCs (Ref: BR_4.16.2.2)Trivial to align, but must be pinned before FE integration. Same class of gap as GET /certificate in UC_4.16.1.🟢
11The Career tab design frame is not in References/Wireframe/. It was supplied to BA on 2026-08-26 together with the certificate frames and carries every on-screen string quoted in §9.Cited as "Client design frame — Career tab, 2026-08-26"Every string in §9 currently traces to an artefact the repo does not hold, which fails a source-of-truth audit. Same finding as UC_4.16.1 §10 item 14. Traceability.🟢

11. Build Ownership

ItemSotatek buildsStack Trading Ops configuresThird party runs
The Career tab layout, the six tiles and their loading / empty / error states✅ Frontend
GET /hr-integration — the server-side Rippling read (W-2) and SQL retainer read (contractor)✅ Backend✅ owns the Rippling API credentials and the integration accountRippling
GET /current-level-detailLevel, Title, payout_portal_url and the Payout Routing branch✅ Backend
The W-2 discriminator field of §10 item 1✅ Backend (once the client rules on it)
PTO balance, accrual, request and approvalNot built — explicitly out of scope (Ref: [HR-DEF-01])✅ owns the Rippling PTO policy configurationRippling owns the logic end to end
Benefits enrolment and the benefits estimate❌ read + display only✅ owns the plan configurationRippling
Payroll runs and the pay calendar behind next_pay_date❌ read + display only✅ owns the payroll calendarRippling (W-2, Flow 34) · Dots (contractor retainer, Flow 36)
The static Dots login URL and the static Rippling login URL✅ consumed / configured in the environment✅ supplies both URLsDots · Rippling
Level parameters behind the tiles — Level Title, Base_Income, Base_Income_Flex, Base_Income_Type, DTO_Days✅ via Zapier Tables A / B, no deploymentZapier
Flow 6 / Flow 8 / Flow 13 / Flow 34 / Flow 35 / Flow 36 — the producers of every value on this tab✅ the middleware endpoints those flows call✅ owns the Zap definitionsZapier
The payout mechanics behind [Manage Payouts]Owned by STAGE 5: PAYOUT & WITHDRAWAL, not by this UC
The Latest certificate panel on the same tabOwned by UC_4.16.1

Changelog

DateVersionUpdated itemBeforeAfterNotes
2026-08-26v1Initial documentCreated from RFQ_ Stack Trading Prop Tech V7.pdf (§Endpoint HR Integration, §Endpoint Current Level Detail — Payout Routing), RFQ_ Website and Dashboard Implementation V7.pdf §Part C (Career & HR Widget), Zapier Integration V7.pdf (Flow 6, Flow 8, Flow 13, Flow 34, Flow 35, Flow 36, Table A / Table B), the client-confirmed QnA item [HR-DEF-01] (Adrian Stack, 2026-08-15 — PTO is owned by Rippling, the dashboard is a read-only mirror), the client instruction relayed to BA on 2026-08-26 (hide [Manage Payouts] for W-2 traders; Dots login for everyone else; [View in Rippling] opens the Rippling login page in a new tab) and the client Career tab design frame of 2026-08-26. Scoped per BA instruction to the HR tiles only — the certificate half of the tab is Ref: UC_4.16.1 and the payout mechanics are Ref: STAGE 5: PAYOUT & WITHDRAWAL.

On this page