SRS: UC_4.14.2 — Pod Mentorship Module (LIVE)
UC_4.14.2: Pod Mentorship Module (LIVE)
| Field | Value |
|---|---|
| BA in Charge | Anh Hoang |
| Date Created | 2026-08-26 |
| Version | v1.1 (updated 2026-09-06) |
| Document References | RFQ_ Website and Dashboard Implementation V7.pdf (§Community Page Implementation — Pod Mentorship Module) · RFQ_ Stack Trading Prop Tech V7.pdf (§Community, Trustpilot and Discord Bot Endpoints — Get Pod Data / Create Pod Channel / Archive Pod Channel) · Zapier Integration V7.pdf (§3.2 Table C, §3.3 Table E, §Flow 10 / 11 / 12 / 15A–15C / 17) · Discord Server Details.md (§DYNAMIC PODS, §Compiled Discord Roles and Badges) · CR-20260818-001 (Flow 7 — Pod Impact & Dispersal) |
Document References
| # | Original Document | Key Sections Used |
|---|---|---|
| 1 | RFQ_ Website and Dashboard Implementation V7.pdf | §Community Page Implementation — Pod Mentorship Module: "Call GET /community/my-pod. Render the data card displaying the Pod Leader, the list of active members, and their current levels. The Enter Pod Chat CTA button must link out externally to the discord_channel_url provided in the payload." |
| 2 | RFQ_ Stack Trading Prop Tech V7.pdf | §Community, Trustpilot and Discord Bot Endpoints — Get Pod Data (input user_id; output leader_name, leader_level, discord_channel_url, join_form_url, members[] { name, level, status }; "If unassigned, populates join_form_url… If assigned, returns the leader data, the array of active members, and the direct Discord Channel URL.") · Create Pod Channel (pod-[leader_name], private text + voice) · Archive Pod Channel (archived-pod-[leader_name], clears channel_url) · §pod_role runtime derivation ("If pod_leader_id is populated in the user's record = MEMBER. If the user's ID exists in the Pod_Leader_Registry = LEADER.") |
| 3 | Zapier Integration V7.pdf | §3.2 Table C Global_Variables (Pod_Max_Capacity = 7, Min_Pod_Leader_Level = 7) · §3.3 Table E Pod_Leader_Registry (Max_Capacity, Current_Count, Status, Pending_Carry_Balance) · Flow 10 (matching waterfall, Plan_Due T+72h) · Flow 11 (Waitlist Processor, 48-hour Klaviyo confirm) · Flow 12 (Zombie Protocol → Inactive_Hold) · Flow 15A (re-assignment on leader Terminated/Suspended) · Flow 15B (leader opt-in) · Flow 15C (termination offboarding) · Flow 17 (carry vesting) |
| 4 | Discord Server Details.md | §Channel Specifications — category DYNAMIC PODS, pod-[leader_name] ("Private text and voice channel provisioned for specific pod members"), archived-pod-[leader_name] ("Renamed and locked channel after a pod leader is terminated or suspended") · §Compiled Discord Roles and Badges (Pod Leader = manage Pod Channels; Pod Member = access assigned Pod Channel) |
| 5 | QnA from clients — STAGE 2: Community & Live Broadcast | Client-confirmed answers [POD-DEF-01], [POD-DEF-02], [POD-BIZ-01] → [POD-BIZ-16], [POD-UI-01], [POD-ZAP-01], [PIT-BIZ-01], [PIT-BIZ-09b] (Stage 2 - Dashboard & Fomula (Community).csv, rows Pod Mentorship / *; Adrian Stack / Adam, 2026-08-04 → 2026-08-18) |
| 6 | QnA from clients — STAGE 2: Founding Mentor | FM-09 (Adrian Stack) — "a Founding Mentor is always a pod_leader. The Role_Flag = 'Founding Mentor' simply acts as an architectural shield to bypass the automated digital eviction scripts, preventing the system from deleting their pod if they hit a stop-loss on their trading account." |
| 7 | CR-20260818-001 | Flow 7 — new "Pod Impact & Dispersal" step (2026-08-18, Adrian Stack) — mentee exit frees the capacity seat; leader exit fires POD_LEADER_TERMINATED → Flow 15A. UI consequence named explicitly in the CR: affected mentees fall to Pending Mentor Allocation |
| 8 | Client design pack — My POD card (LIVE) | Four finalized states supplied to BA on 2026-08-26: Matched · Unassigned + Discord linked · Unassigned + Discord not linked · Pending. ⚠️ Not yet checked into References/Wireframe/ — see §10 item 10 |
1. Overview
| Field | Content |
|---|---|
| ID | UC_4.14.2 |
| Use Case | Pod Mentorship Module (LIVE) |
| Description | On the Community page, the My POD card is the Dashboard's window onto the trader's mentorship pod. It consumes a single endpoint, GET /community/my-pod, and renders exactly one of four states derived from that payload plus the account's Discord linking flag (Ref: BR_4.14.2.2). When the trader is matched, the card shows the Pod Leader, the full member list with each member's avatar, title, level and account-status indicator — every avatar read through from that person's own Settings profile photo (Ref: BR_4.14.2.15) — and an [Enter My POD] control that opens the pod's private Discord channel (Ref: BR_4.14.2.6, BR_4.14.2.9). When the trader has no pod, the card carries the [Join a POD] control that routes to the external matching form — unless the account has not linked Discord, in which case the control is rewritten to [Link Discord to Unlock] and points the trader at The PIT card beside it (Ref: BR_4.14.2.3, BR_4.14.2.4). While the matching engine is working — after a form submission, or after a Pod Leader has been terminated — the card renders one shared Pending Mentor Allocation state that never shows a member list and never shows the outgoing leader (Ref: BR_4.14.2.5). This UC owns the Dashboard presentation only. The matching waterfall, the SLA engine, the carry vesting and the Zapier flows that move a trader between states are owned by the UC_8.2.x Pod System documents and are named here only as the events that change what this card renders (Ref: BR_4.14.2.13). |
| Zapier Flow | Not triggered by this card. Context only — the card is a read surface over state written by: Flow 10 (Pod Joining / matching waterfall), Flow 11 (Waitlist Processor), Flow 12 (Zombie Protocol → Inactive_Hold), Flow 4 patch (Alumni Graduation at Level 7), Flow 7 §Pod Impact & Dispersal (Ref: CR-20260818-001), Flow 15A / 15B / 15C (re-assignment, leader opt-in, leader termination), Flow 17 (carry vesting). All are detailed in BR_4.14.2.13 |
| Zapier Table | Table C — Global_Variables: Pod_Max_Capacity = 7, Min_Pod_Leader_Level = 7 — ops-editable, never read by the frontend (Ref: BR_4.14.2.11) · Table E — Pod_Leader_Registry: Leader_Name, Leader_ID, Trading_Style, Asset_Class, Max_Capacity, Current_Count, Status, Pending_Carry_Balance — the source of truth behind the payload, never surfaced field-for-field on the card (Ref: BR_4.14.2.6) |
| 3rd Party | Discord — pod category pod-[leader_name] with one private text and one private voice channel (destination of [Enter My POD]), Pod Member / Pod Leader roles, custom Node.js bot (channel provisioning and role assignment) · Typeform or ActiveCampaign — the external matching form behind join_form_url (Ref: BR_4.14.2.4) · Klaviyo — the 48-hour seat-confirmation email of Flow 11, and the Pod_Reassigned_Notification lifecycle email; not Sotatek's template (Ref: BR_4.14.2.13) |
Design states covered by this UC (client design pack, 2026-08-26):
| # | State | What the card shows | Ref |
|---|---|---|---|
| 1 | Matched | Pod Leader tile (display name + title + level) · POD members list with per-member status indicator · [Enter My POD] | §5 |
| 2 | Unassigned · Discord linked | You're not in a POD + the supporting line + [Join a POD] rendered as the primary control | §6.1 |
| 3 | Unassigned · Discord not linked | Identical title and supporting line + [🔒 Link Discord to Unlock] rendered as a secondary / muted control | §6.2 |
| 4 | Pending Mentor Allocation | Pending status chip beside the card header · Pending Mentor Allocation + queue subtext · no member list, no leader, no CTA | §6.3 |
The SIM counterpart of this card — a permanently locked empty state with a disabled [Join a POD] — is owned by UC_4.9.2 and is not one of the four states above (Ref: BR_4.14.2.1).
2. Trigger
- The trader navigates to the Community page via the Community tab in the persistent sidebar (Ref: UC_4.1.2 §2 Screen Description) → the My POD card mounts and issues its single
GET /community/my-podrequest (Ref: BR_4.14.2.10). - The trader activates the card's call-to-action — [Enter My POD], [Join a POD] or [Link Discord to Unlock], whichever the current state renders (Ref: BR_4.14.2.3, BR_4.14.2.4, BR_4.14.2.9).
There is no third trigger. No server push, no polling interval and no cross-widget event re-renders this card. A pod assignment completed by the backend one second after mount is not reflected until the next mount (Ref: BR_4.14.2.10).
3. Pre-conditions
- The user is authenticated and is on the Community page.
- The account is a LIVE account at Level 1 or above. A SIM / Evaluation account never reaches this UC — the card is owned by UC_4.9.2 for the whole time the account is SIM (Ref: BR_4.14.2.1).
- To render any state:
GET /community/my-podhas returned successfully. There is no client-side default state — a failed request has its own treatment and never falls back to the empty state (Ref: BR_4.14.2.10). - To act on the unassigned-state CTA:
discord_user_idis populated on the user record. If it isnullthe control is rewritten rather than disabled (Ref: BR_4.14.2.3). - The card's rendering is independent of the broadcast session. It renders identically whether
is_liveistrueorfalse, and a session transition does not re-render it (Ref: BR_4.14.2.10).
4. Post-conditions
- The card is rendered in exactly one of the four states listed in §1, and occupies its full slot in the Community page grid in every one of them (Ref: BR_4.14.2.1).
- No state of this card writes anything. The card issues exactly one
GET; it never posts, patches or deletes. Pod membership is created, changed and removed entirely by the backend flows in BR_4.14.2.13. - Activating [Join a POD] hands the trader to an external form. The Dashboard learns nothing about the submission and shows no confirmation — the state change surfaces on the next mount (Ref: BR_4.14.2.4, BR_4.14.2.10).
- Activating [Enter My POD] opens Discord in a new tab. The Dashboard session is untouched (Ref: BR_4.14.2.9).
5. Basic Flow — Matched (trader is in a pod)
- The Community page renders. The My POD card mounts in its grid slot.
- The frontend calls
GET /community/my-podwith the authenticateduser_id. This is the card's only request (Ref: BR_4.14.2.2, BR_4.14.2.10). - The payload identifies the account as assigned to a pod, and carries
leader_name,leader_level,discord_channel_urland themembers[]array (Ref: BR_4.14.2.2). - The card renders the Pod Leader tile: the leader's avatar, their display name, and beneath it the leader's title and level taken from the 24-level career path —
Table Afor Futures,Table Bfor Forex — not from the Discord role map (Ref: BR_4.14.2.8). The avatar is the leader's ownprofile_photo_urlfrom Settings →Profile & Preferences, falling back to their initials (Ref: BR_4.14.2.15). - The card renders the
POD memberslist. Every member of the pod is listed with their avatar, name, title and level, and a status indicator driven by that member'sstatusvalue. Each avatar is resolved per displayed member on the same rule as the leader's (Ref: BR_4.14.2.15). The list is identical for a Pod Leader and for a Pod Member — there is no privacy masking and no management layout (Ref: BR_4.14.2.6, BR_4.14.2.7). - A member currently held by the Zombie Protocol renders with the inactive indicator and the
Inactivelabel beside their name (Ref: BR_4.14.2.7). - The card renders the [Enter My POD] control.
- The trader activates [Enter My POD]. The browser opens
discord_channel_urlin a new tab. The destination is the pod's private Discord category — one text channel and one voice channel, permissioned to that pod only (Ref: BR_4.14.2.9). - The card holds this appearance for the rest of the page view. Nothing on the card is interactive besides that one control — member rows are not clickable, and no counter, capacity bar or SLA countdown is rendered anywhere on it (Ref: BR_4.14.2.10, BR_4.14.2.11, BR_4.14.2.12).
6. Alternative Flows
6.1 — Unassigned, Discord account linked
Applies when the payload reports the account as not assigned to a pod and discord_user_id is populated. This is the state of a trader who has just completed live onboarding and has not yet submitted the matching form.
- Steps 1–2 of §5 run unchanged.
- The payload carries
join_form_urland no leader data (Ref: BR_4.14.2.2). - The card renders the empty state: the title
You're not in a PODand the supporting lineJoin a POD to trade with a team, get feedback, and track performance together. - The card renders [Join a POD] as the primary control, enabled.
- The trader activates it. The browser opens
join_form_urlin a new tab — an external Typeform or ActiveCampaign form, not an in-app screen and not a modal (Ref: BR_4.14.2.4). - The trader completes the form outside the Dashboard. The backend matching waterfall runs asynchronously (Ref: BR_4.14.2.13).
- The card does not change. It shows no confirmation, no spinner and no "submitted" state, because the Dashboard is never told the form was submitted. On the next mount of the Community page the card renders either the matched state of §5 or the pending state of §6.3, depending on what the payload then reports (Ref: BR_4.14.2.10).
6.2 — Unassigned, Discord account not linked
Applies when the payload reports the account as not assigned to a pod and discord_user_id is null. Submitting the matching form in this condition would produce a match the trader cannot use, because a pod lives entirely inside a private Discord channel the bot can only grant to a linked account.
- Steps 1–3 of §6.1 run unchanged. The title and the supporting line are identical — no new screen and no alternative copy is built for this case (Ref: BR_4.14.2.3).
- The call-to-action is rewritten, not disabled: the label becomes
Link Discord to Unlock, it carries a 🔒 icon, and it renders as a secondary / muted control (Ref: BR_4.14.2.3). - The trader activates it. No modal opens and no navigation occurs. Instead, in the same page view, the
Link your Discord account firstblock inside The PIT card is given a short highlight / pulse treatment to draw attention to it, and the toast Ref: TS-POD-01 is displayed (Ref: BR_4.14.2.3). - On a mobile viewport, where The PIT card is stacked below this card, the same activation additionally performs a smooth auto-scroll of the viewport down to The PIT card, and the highlight runs on arrival (Ref: BR_4.14.2.3).
- The instruction block the trader is being pointed at — the heading, the three numbered steps, the token value and [Copy], and [Open Discord] — is owned by BR_4.5.2.7. This card renders no instructions, no token and no Discord link of its own.
- The trader completes
/link [token]in#verifyinside Discord. The bot writesdiscord_user_idto the user record (Ref: BR_4.5.2.6). - The control reverts to the primary [Join a POD] of §6.1 on the next page load or Community-page mount. The card does not poll
discord_user_idand does not subscribe to a linking event, so the change is not live within the current view (Ref: BR_4.14.2.3, BR_4.14.2.10).
6.3 — Pending Mentor Allocation
Applies whenever the trader is between pods. Two distinct causes share one screen, and the card gives the trader no way to tell them apart (Ref: BR_4.14.2.5):
| Cause | How the trader got here |
|---|---|
| A — Awaiting first match | The trader submitted the matching form and the waterfall found no seat, so Flow 10 Step 5 placed them on the pod waitlist; or the matching script has not finished yet |
| B — Leader lost | The trader's Pod Leader was terminated or suspended, pod_leader_id was cleared, and Flow 15A is re-matching the whole cohort (Ref: CR-20260818-001) |
- Steps 1–2 of §5 run unchanged.
- The payload reports the account as pending assignment.
- A
Pendingstatus chip renders beside theMy PODcard header. - The card body renders the title
Pending Mentor Allocationand the supporting lineYou are in the queue for the next available mentor. We will assign you to a POD as soon as a spot opens up. - The member list is not rendered at all — not empty, not collapsed, not zero-state. A trader with no Pod Leader is in no pod, so there are no peers to show (Ref: BR_4.14.2.5).
- No information about the outgoing leader is rendered in any form — no name, no level, no avatar, no
former mentorline, and no status label such asTerminated,SuspendedorUnder Review(Ref: BR_4.14.2.5). - No call-to-action is rendered. The trader is already in the automated queue; there is nothing to submit and no queue position to display (Ref: BR_4.14.2.5).
- The card leaves this state on the next mount after the backend completes the assignment, transitioning directly to the matched state of §5 (Ref: BR_4.14.2.10).
7. Exceptional Flow
- [If
GET /community/my-podfails with a network error, a timeout, or HTTP 5xx] — the card keeps its grid slot and renders the error treatment with Ref: TE-SYS-01. It must not fall back to theYou're not in a PODempty state: telling a matched trader they have no pod would invite them to submit the matching form a second time and create a duplicate record for the matching engine (Ref: BR_4.14.2.10). - [If the payload reports the account as assigned but
discord_channel_urlisnullor empty] — this is the window between Flow 15B inserting a leader intoPod_Leader_RegistryandPOST /create-pod-channelreturning, and it is also the permanent condition of an archived pod, whereArchive Pod Channelclearschannel_urlin the registry. The card renders the leader and the member list normally and renders [Enter My POD] in a Disabled state; no error and no toast is shown (Ref: BR_4.14.2.9). - [If the trader is the Pod Leader and the pod currently has no mentees] — the
members[]array is empty. The leader tile renders, and thePOD memberslist renders its own empty line. The card stays in the matched state; it does not fall back toYou're not in a POD, because the trader is in a pod — their own (Ref: BR_4.14.2.6). - [If a member's
statuscarries a value the frontend does not recognise] — it is treated as not active: the inactive indicator and theInactivelabel are rendered. Only the explicit active value produces the active indicator (Ref: BR_4.14.2.7). - [If the trader's Pod Leader breaches their own trading account] — nothing on this card changes. For an ordinary leader the card only reacts once Flow 15A has actually re-matched the cohort, at which point the trader is already in the pending state of §6.3. For a Founding Mentor the eviction scripts are bypassed entirely, so no transition ever fires (Ref: BR_4.14.2.14).
- [If the trader reaches Level 7 while a mentee] — the Alumni Graduation Sequence removes them from the pod automatically. On the next mount the card renders the unassigned state of §6.1. No notification, no farewell state and no reference to the former pod is rendered (Ref: BR_4.14.2.13).
- [If the trader's Discord roles are revoked by Flow 7 §Digital Eviction] —
discord_user_idis not deleted, so the card still evaluates the account as linked and still renders [Enter My POD]. Activating it opens a Discord URL the trader no longer has permission to view. The Dashboard has no visibility of Discord role state and builds no check for it (Ref: BR_4.5.2.8). - [If the broadcast session starts or ends while the trader is on the page] — the card does not re-render and keeps its state. Only the video component re-renders (Ref: BR_4.5.1.8).
8. Business Rules
BR_4.14.2.1: Eligibility Is LIVE Level 1+, and the Card Is Never Hidden
Pod Mentorship is reserved for traders at Level 1 and above trading live capital. It is not available to SIM or Evaluation accounts in any form, including read-only viewing of pod information (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Definition A1, Adrian Stack).
| Account | Card owner | Appearance |
|---|---|---|
| SIM / Evaluation (Level 0) | UC_4.9.2 | One permanent locked state: You're not in a POD + Pass the Associate Track to Unlock + a Disabled [Join a POD]. No API call is issued |
| LIVE Level 1+ | This UC | One of the four states in §1, derived from GET /community/my-pod |
- The card must not be hidden in any state. Removing the component breaks the Community page CSS grid. The card keeps its slot and its dimensions in all four states, including the pending state, which renders the least content of the four.
- The handover between the two UCs happens on the next mount of the Community page after the account leaves SIM. There is no real-time transition and no animation between the locked card and this one.
BR_4.14.2.2: One Endpoint, One Call — and How the Four States Are Derived
The card is fed entirely by GET /community/my-pod, taking user_id and returning a single payload that carries leader data, the member array and the routing URLs together (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Community Endpoints — Get Pod Data; RFQ_ Website and Dashboard Implementation V7.pdf §Community Page Implementation). One payload serves both the Pod Leader's view and a Pod Member's view — there is no second endpoint and no role-specific variant (Ref: BR_4.14.2.6).
Payload as specified by the source:
| Field | Type | Meaning | Present when |
|---|---|---|---|
leader_name | string | The Pod Leader's display name | Assigned |
leader_level | int | The Pod Leader's career-path level (Ref: BR_4.14.2.8) | Assigned |
discord_channel_url | URL string | Direct URL of the pod's private Discord channel — the target of [Enter My POD] (Ref: BR_4.14.2.9) | Assigned |
join_form_url | URL string | The external ActiveCampaign / Typeform matching form — the target of [Join a POD] (Ref: BR_4.14.2.4) | Unassigned |
members[] | array of { name: string, level: int, status: string } | Every member of the pod, including the trader themselves | Assigned |
Fields the card needs that the specified payload does not carry:
| Field | Needed for | Status |
|---|---|---|
pod_status | Telling the pending state apart from the unassigned state | 🔴 BA proposal — see the blocking note below and §10 item 1 |
leader_profile_photo_url and members[].profile_photo_url | The avatar on the leader tile and on every member row (Ref: BR_4.14.2.15) | 🟡 BA proposal — a join onto Users in the same database; see §10 item 11 |
Where the data actually comes from — this endpoint reads SQL, not Discord. The card looks like a Discord surface, so it is worth stating plainly: Get Pod Data queries the SQL database to find the assigned pod_leader_id (Source: RFQ_ Stack Trading Prop Tech V7.pdf §Community Endpoints). Rendering this card triggers no Discord API call at all.
| Field | Actually sourced from |
|---|---|
leader_name · leader_level · members[] | The SQL database — the Users table plus the pod registry. Names and levels are Dashboard identity, not Discord nicknames |
discord_channel_url | The SQL registry, where it was stored earlier by POST /create-pod-channel and cleared by POST /archive-pod-channel. It is a URL string at rest, not a live Discord read (Ref: BR_4.14.2.9) |
join_form_url | The SQL configuration — an ActiveCampaign / Typeform destination (Ref: BR_4.14.2.4) |
| Avatars | The same SQL database, Users.profile_photo_url — a join away, though not yet in the payload (Ref: BR_4.14.2.15) |
- Consequence. Discord identity governs what the trader sees inside the pod channel — nickname, Discord profile picture, roles. It does not feed this card, in either direction. The one place on the Community page where Discord identity is the source is the chat panel's author name (Ref: BR_4.9.1.6); the two must not be conflated.
- The frontend never queries Zapier Table E directly.
Max_Capacity,Current_Count,StatusandPending_Carry_Balanceare backend-side fields; the endpoint is the only contract the Dashboard knows (Ref: BR_4.14.2.11). pod_roleis derived server-side, not sent as a flag. The backend evaluates it at runtime:pod_leader_idpopulated on the user record = MEMBER; the user's ID present inPod_Leader_Registry= LEADER (Source: RFQ_ Stack Trading Prop Tech V7.pdf). The card does not need it, because both roles render the same layout.
State resolution — evaluated in this fixed order, first match wins:
| Priority | Condition | State |
|---|---|---|
| 1 | The account is SIM / Level 0 | Not this UC — UC_4.9.2 |
| 2 | The request failed | Error treatment, Ref: TE-SYS-01 (Ref: BR_4.14.2.10) |
| 3 | The payload reports assigned | Matched — §5 |
| 4 | The payload reports pending assignment | Pending Mentor Allocation — §6.3 |
| 5 | The payload reports unassigned | Unassigned — §6.1 |
- The Discord linking flag is not part of this ladder. It is a gate on the action, not on the state: it rewrites the CTA of the unassigned state and never changes which state is rendered (Ref: BR_4.14.2.3). Mixing the two would produce impossible combinations such as "assigned but rendered empty".
🔴 The frontend switches on
pod_statusalone, never on which fields are null —unassignedandpendingboth leaveleader_namenull and are otherwise indistinguishable. The field is not yet in the specified payload: §10 item 1, blocking for BE.
⚠️ The WBS row for this UC is bypassed. It names
GET /pod/statusand expects awaitlist_positionand acarry balance; the RFQ and the client answers giveGET /community/my-pod, no queue position (Ref: BR_4.14.2.5) and no carry balance (Ref: BR_4.14.2.6). This document is authoritative and BE builds to it. The WBS row is to be corrected to match; it is not a source for this card.
BR_4.14.2.3: The Discord Gate Rewrites the CTA — No New Screen, No Modal, No Dead Click
Pod mentorship happens inside a private Discord channel, so an account with no linked Discord identity cannot be routed into a pod. No new screen is built for this — the linking guidance is already rendered permanently in The PIT widget beside this card (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A16).
| Aspect | Rule |
|---|---|
| Condition | discord_user_id IS NULL on the user record |
| Scope | The unassigned state only. The title and supporting line are unchanged; only the control changes |
| Label | Join a POD → Link Discord to Unlock, with a 🔒 icon |
| Style | Secondary / muted, not disabled — the control must remain activatable, because activating it is what performs the guidance |
| On activation | No modal. A short highlight / pulse treatment is applied to the Link your Discord account first block inside The PIT card, plus the toast Ref: TS-POD-01 |
| On mobile | Where The PIT card is stacked below, activation additionally performs a smooth auto-scroll to The PIT card, with the highlight running on arrival |
| Unlock | Once the backend has synchronised discord_user_id, the control reverts to the primary [Join a POD] and routes to join_form_url as normal |
- Two constraints the design must hold: the trader never reaches a matching form whose result they cannot use, and no second Discord-linking surface is built anywhere.
- The remedy is owned elsewhere. The instruction block being highlighted — heading, three numbered steps, token value, [Copy], [Open Discord] — belongs to BR_4.5.2.7. This card states the blocker; it does not restate the remedy.
- The gate is evaluated on mount only. The card does not poll
discord_user_idand does not subscribe to a linking event, so a trader who links mid-session must reload to unlock the control (Ref: BR_4.14.2.10).
🔴 Matched + unlinked is not ruled. The gate above covers the unassigned state only; whether it extends to [Enter My POD] is §10 item 2, blocking for BE.
BR_4.14.2.4: [Join a POD] Hands Off to an External Form — the Dashboard Never Sees the Submission
[Join a POD] routes the trader to the join_form_url returned by the endpoint. The destination is an external ActiveCampaign or Typeform page, not an in-app screen and not a modal (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A13, Adrian Stack).
- The URL is always taken from the payload. It is never hard-coded in the frontend, so Operations can change the form destination without a release.
- The link opens in a new tab (
target="_blank",rel="noopener noreferrer"), so the trader keeps their Dashboard session — which matters here, because the state change they are waiting for only appears when they return to it. - The form collects the input for the matching waterfall: Asset Class and Trading Style, the latter as a restricted list of
Scalping,Day Trading,Swing Trading,Algorithmic Trading(Source: Zapier Integration V7.pdf §Flow 10 Step 2). Ref: §10 item 4. - Sotatek does not build this form. It is owned by Stack Trading Operations inside the third-party tool (Ref: §11).
- No confirmation is rendered on return. The Dashboard receives no callback, so the card shows no
Submitted, no spinner and no disabled CTA after the trader comes back. Whether the next mount lands on §5 or §6.3 depends on whether the waterfall found a seat (Ref: BR_4.14.2.10).
BR_4.14.2.5: Pending Mentor Allocation — One Screen for Two Causes, and the Old Leader Is Erased
Both routes into the between-pods condition — the post-submission wait and the Flow 15A re-match — render the same screen. They are never split into two designs (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A15).
| Element | Rule |
|---|---|
| Status chip | Pending, rendered beside the My POD card header |
| Title | Pending Mentor Allocation |
| Supporting line | You are in the queue for the next available mentor. We will assign you to a POD as soon as a spot opens up. — it must convey that the queue is automated and that the wait is for the next free mentor seat |
| Member list | Not rendered. Not an empty list, not a zero-state, not a collapsed section |
| Leader data | Not rendered in any form |
| Call-to-action | None |
- Why no member list. A trader with no Pod Leader is not in a pod, so there are no peers to display. Rendering the previous cohort would imply a pod that no longer exists.
- The outgoing leader must be invisible. Absolute: no name, no level, no avatar, no
former mentorline, and no status label such asTerminated,SuspendedorUnder Review. The Dashboard is not a place where a mentor's dismissal is announced to their mentees. - No queue position is displayed. The supporting line is a qualitative reassurance, not a counter. No
waitlist_positionfield exists (Ref: BR_4.14.2.2). - No estimated wait time is displayed. Flow 11 releases a seat only when one is vacated and then waits up to 48 hours for the next trader in the queue to confirm by email, so no bounded estimate exists to render.
BR_4.14.2.6: One Shared Layout for Leader and Member — No Privacy Masking, No Management Panel
The matched state renders identically whether the viewer is the Pod Leader or a Pod Member (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A9 and A10, Adrian Stack).
| Question the layout answers | Rule |
|---|---|
| Does a Member see the other members? | Yes — the full list. The backend returns the name, level and status of everyone in the pod. There is no privacy restriction hiding teammates' names |
| Does a Member see the Leader? | Yes — the same leader tile that the Leader themselves sees |
| Does the Leader get a different layout? | No. No member-management controls, no mentee statistics table, no capacity widget, no approval queue |
| Where does a Leader track mentee performance? | In the weekly AI brief email (Flow 10.3), not in this component |
| Is a member row clickable? | No. The list is static — no drill-down to a member's profile, PNL or trading plan (Source: same row, answer A12, Adam) |
- The trader themselves appears in the
members[]array. The card does not filter them out and does not style their own row differently. - No financial data is rendered on this card, for either role.
Pending_Carry_Balanceis the Pod Leader's accrued mentorship carry, held in Table E and paid on the 1st of each month by Flow 17. It is not in the endpoint payload, it belongs to one person rather than to the pod, and the client explicitly ruled out any statistics surface here. It is therefore not rendered on this card — the WBS row that asks for it is bypassed (Ref: BR_4.14.2.2).
BR_4.14.2.7: The Member Status Indicator Is Account Status, Not Presence
Each member row carries a small status indicator. It is not an online/offline dot — the backend has no real-time presence engine and opens no WebSocket for this card. The indicator maps directly to the status string returned for that member in the members[] array (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A11, Adrian Stack).
status | Indicator | Label beside the name |
|---|---|---|
| Active | Active indicator | None |
Any other value — including the Inactive_Hold set by the Zombie Protocol | Inactive indicator | Inactive |
- Where the inactive state comes from. Flow 12 (Zombie Protocol) runs daily at 02:00 Central, selects traders whose last trade is more than 30 days old, disables their market data, decrements the Pod Leader's
Current_Countto free the seat, and sets the trader's pod status toInactive_Hold. Such a member must be distinguishable in the list by theInactivelabel beside their name. - Binary rendering, deliberately. The frontend treats only the explicit active value as active and every other value — including one it has never seen — as inactive, so the card stays correct when the backend adds a value. The enum itself is §10 item 6.
- The indicator says nothing about mentorship progress. It is not a "Trading Plan submitted" flag and not an SLA state (Ref: BR_4.14.2.12).
⚠️ Two client answers exist for this field and the conflict is not formally closed: §10 item 3.
BR_4.14.2.8: Title and Level Come from the Career Path, Not from the Discord Role Map
The label under each name — Senior trader - Lvl 12, Associate - Lvl 3 — is the trader's real title and level on the 24-level career path, sourced from Table A (Futures) and Table B (Forex) (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / UI-UX A1, Adam and Adrian).
- It is explicitly not Table G. Table G (
Discord_Role_Map) is a Discord permission grouping only, and its role titles must not be rendered here. - The leader's label is built from
leader_level; each member's label is built from that member'slevel. The mapping from level to title is the same one used by the Levels module, so a level that is renamed there is renamed here without a change to this card. - Futures and Forex traders can sit in the same pod, and the two tracks have different title tables. The label is therefore resolved per person, from the track their account belongs to — never from the viewer's own track.
BR_4.14.2.9: [Enter My POD] Is an External Link into a Private Discord Category
[Enter My POD] opens discord_channel_url directly. It is not an in-app page and there is no in-Dashboard pod chat (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A13, Adam).
- The link opens in a new tab (
target="_blank",rel="noopener noreferrer"), consistent with [Open Discord] on The PIT card beside it (Ref: BR_4.5.2.7). It never navigates the current tab away from the Dashboard. - What it opens. A POD is not a bare voice channel: it is provisioned as a Discord Category named
pod-[leader_name]containing exactly one private text channel and one private voice channel, permissioned to the members of that pod alone (Source: Discord Server Details.md §DYNAMIC PODS;Stage 2 - Dashboard & Fomula (Community).csv— The Pit / Business logic A9b, Adrian Stack, 2026-08-10). The same structure is recorded from the metrics side in BR_4.5.2.11. - Provisioning is backend work, invisible to this card.
POST /create-pod-channelinstructs the bot to create the channels and set permissions and returns the URL;POST /archive-pod-channelstrips access, renames the channel toarchived-pod-[leader_name], and clearschannel_urlin the registry. - Disabled when there is no URL. If the payload reports the account as assigned but
discord_channel_urlisnullor empty — the provisioning window after Flow 15B, or an archived pod — the control renders Disabled and no error or toast is shown. The rest of the matched state renders normally. - The Dashboard does not verify Discord permissions. It knows only the URL. Whether the trader currently holds the
Pod Memberrole is Discord's business (Ref: BR_4.5.2.8).
⚠️ The RFQ and the WBS call this control
Enter Pod Chat; the label divergence is §10 item 5.
BR_4.14.2.10: One Request per Mount — No Polling, No Push, No Optimistic State
The card is a snapshot, not a live feed. Everything it can show is decided by the single response it receives when it mounts.
| Concern | Rule |
|---|---|
| Requests | Exactly one GET /community/my-pod per mount of the Community page |
| Polling | None. No interval refresh at any cadence |
| Server push | None. No WebSocket channel and no notification event feeds this card |
| Refresh after an action | None. Returning from the external form or from Discord does not re-fetch; the trader must re-enter the page |
| Loading treatment | The card has no dedicated skeleton. It follows the Community page's page-level loading treatment, in step with the other widgets |
| Broadcast session changes | No effect. A broadcast going live or ending re-renders the video component only; this card retains its state without interruption (Ref: BR_4.5.1.8) |
| Request failure | Error treatment with Ref: TE-SYS-01. Never a fallback to the empty state |
- Why the empty-state fallback is forbidden. A matched trader shown
You're not in a PODwould reasonably click [Join a POD] and submit the matching form again, producing a duplicate entry for the waterfall and a second SLA record. A silent failure here is more expensive than a visible one. - The consequence for QA. Every backend transition in BR_4.14.2.13 — being matched, being graduated at Level 7, losing a leader, a teammate going inactive — is expected to appear only after a page re-entry. Lag between the backend event and the card is not a defect.
BR_4.14.2.11: Capacity Is an Operations Setting, Never a UI Element
A standard pod is capped at 7 mentees + 1 Pod Leader = 8 people in one Discord Category. The cap is not a constant in code: it is Pod_Max_Capacity in Zapier Table C — Global_Variables, with a per-leader override in Max_Capacity on Table E — Pod_Leader_Registry (Source: Zapier Integration V7.pdf §3.2, §3.3; Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A1, Adrian Stack).
- Ops owns the numbers, not Engineering. Changing the maximum capacity, marking a mentor active or ineligible, and registering a new mentor are all performed by Stack Trading Operations through the Zapier Tables interface, so that global variables change without a code deployment (Ref: §11).
- A Founding Pod Leader may carry a different capacity, configured individually on their registry row. The card must therefore never assume 7, and must never derive anything from a hard-coded number.
- Nothing about capacity is rendered. No
Fullbadge when a pod is at capacity (Source: same row, answer A6). Nox/7counter, no progress bar, no remaining-seats line.Max_CapacityandCurrent_Countare not in the endpoint payload, so the frontend holds no data to render them from (Ref: BR_4.14.2.2). - Minimum leader level is likewise invisible.
Min_Pod_Leader_Level = 7(Table C) gates who may become a Pod Leader in Flow 15B. It has no rendering on this card.
BR_4.14.2.12: SLA Deadlines Are Server-Side and Email-Only — Nothing Counts Down Here
The mentorship programme enforces exactly two onboarding deadlines, and neither appears on this card in any form (Source: Stage 2 - Dashboard & Fomula (Community).csv — Pod Mentorship / Business logic A4 and A7, Adrian Stack).
| SLA | Owner | Duration | On this card |
|---|---|---|---|
| Trading Plan submission | Mentee | Plan_Due = T+72 hours from the Flow 10 trigger | Nothing |
| Induction Sync meeting | Mentor | Induction_Due = T+5 days from pod assignment | Nothing |
- Both are tracked server-side and communicated entirely by automated email: warning and breach notices are dispatched by Flow 10.2, which scans for approaching and breached deadlines and identifies whether the violator is the mentee or the mentor. SLA is never displayed on the UI.
- No countdown, no progress bar, no
Plan pendinglabel and no per-member SLA badge is built. The status indicator beside a member's name is account status and must not be repurposed to carry SLA meaning (Ref: BR_4.14.2.7). - Beyond the two onboarding deadlines there is no meeting cadence to display. Session frequency after induction is arranged between mentor and mentee in Discord, and the mentor's engagement level is audited automatically by the backend (Flow 10.5, Gemini
PASS/FAILwritten to the registry). None of that surfaces on the Dashboard.
BR_4.14.2.13: Every State Change Is a Backend Event — the Card Only Reflects Them
The card writes nothing. Membership is created and destroyed by seven distinct backend paths, and this rule exists so that QA and BE can trace each rendered state back to the event that produced it.
| # | Event | Mechanism | State this card lands on |
|---|---|---|---|
| 1 | Trader completes live onboarding | Flow 3 completion → Flow 10 sends Pod_Mentorship_Invite | Unassigned — §6.1 / §6.2 |
| 2 | Trader submits the matching form and a seat is found | Flow 10 Step 3–4: waterfall Asset match (strict) → Style match → fallback lowest Current_Count; assign in DB, increment Current_Count, POST /manage-discord-role for Pod Member, bot welcome ping, log Plan_Due T+72h | Matched — §5 |
| 3 | Trader submits the form and no seat is found | Flow 10 Step 5: status set to Pod_Waitlist, waitlist count incremented, Pod_Waitlist_Notification sent | Pending — §6.3 |
| 4 | A seat frees up | Flow 11: triggered when Current_Count decreases → Pod_Spot_Available_Confirm sent via Klaviyo → the trader has 48 hours to click through, or they are skipped and the next in the queue is offered the seat → on confirmation, Flow 10 Step 4 assignment runs | Pending → Matched |
| 5 | A teammate stops trading for 30 days | Flow 12 (Zombie Protocol, daily 02:00 Central): market data disabled, Current_Count decremented, trader set to Inactive_Hold | Matched, that member rendered Inactive (Ref: BR_4.14.2.7) |
| 6 | The trader reaches Level 7 | Flow 4 patch — Alumni Graduation Sequence: IF New_Level == 7 AND Pod_Leader_ID exists → decrement Current_Count on Table E, set users.pod_leader_id = NULL, POST /manage-discord-role with remove_role = 'Pod Member', then run Flow 11 to fill the freed seat. Automatic on level-up — independent of whether they accept the Pod Leader invitation | Unassigned — §6.1 |
| 7 | The trader, or their leader, leaves the programme | Flow 7 §Pod Impact & Dispersal (Ref: CR-20260818-001). Condition A — mentee exit: decrement the leader's Current_Count, clear the leaver's pod_leader_id. Condition B — leader exit: set Status = Terminated in Pod_Leader_Registry and fire the POD_LEADER_TERMINATED webhook, which natively triggers Flow 15A — every active mentee of that leader is re-run through the matching script, the leader's Pod Leader role is removed, the channel is archived by POST /archive-pod-channel, and Pod_Reassigned_Notification is dispatched | The affected mentees → Pending — §6.3 |
- Flow 15 has two further branches with the same UI consequence. Trigger B is a BPS admin re-assignment (
POST /admin-pod-reassignment, which syncs Discord roles and updatesCurrent_Counton both the old and the new leader), and Trigger C marks a leaderPermanently_Ineligibleso the Flow 10 waterfall excludes them. Both land the affected trader in the pending state and then in a new pod, with no distinct rendering of their own. Pod_Reassigned_Notificationis not Sotatek's to write. It is classified as a lifecycle marketing event: the backend pushes a webhook payload to Zapier, Zapier forwards it to Klaviyo, and Klaviyo owns the template and the send (Source:Stage 2 - Dashboard & Fomula (Community).csv— Pod Mentorship / Business logic A8).- On a graduation, the mentor's card simply loses a row. The graduating trader disappears from
members[]on the next mount. No notification, noGraduatedlabel and no farewell state is rendered on either side. Three related questions remain unanswered by the client — see §10 item 8. - Whether Flow 11 runs after the Flow 7 decrement is not yet confirmed. Event 6 explicitly chains into Flow 11; event 7 does not say. If it does not, a seat freed by a resignation is never automatically filled, and traders sit in the pending state of §6.3 longer than the design implies — see §10 item 9.
BR_4.14.2.14: Founding Mentor — a Leader's Breach Is Never Surfaced to Their Mentees
A Founding Mentor is an ordinary Pod Leader with one architectural exception: Role_Flag = 'Founding Mentor' acts as a shield that bypasses the automated digital-eviction scripts, so the system does not dissolve their pod if they breach a stop-loss on their own trading account (Source: QnA from clients — STAGE 2: Founding Mentor, FM-09).
What this means for the mentee's card:
- The mentor's trading account is locked by the normal breach treatment, but their
Pod_Leader_Registry.Statusis not moved toTerminated, so Flow 15A never fires. There is no event for this card to react to, and the mentee's card continues to render the matched state of §5 unchanged. - No status of the Leader is rendered at all — not
Under Review, notBreached, notSuspended, not an inactive indicator on the leader tile. The payload carries onlyleader_nameandleader_level; there is no leader status field to render, by design. - The same silence applies to a non-Founding leader during the window between their breach and Flow 15A completing. The card either still shows the old matched state, or has already moved to the pending state of §6.3, which is required to erase the outgoing leader entirely (Ref: BR_4.14.2.5). At no point is a leader's failure narrated to their mentees.
- The
Inactivelabel of BR_4.14.2.7 applies to members, from themembers[]array. It has no equivalent on the leader tile.
BR_4.14.2.15: Avatar Source — the Trader's Dashboard Profile Photo, Read Through Per Displayed User
Every avatar on this card — the Pod Leader tile and each member row — renders the profile_photo_url of the person being displayed, taken from that user's Users record. That column is written in exactly one place, Settings → Profile & Preferences, and BR_4.6.2.13 already names this card as one of its four consumer surfaces. This UC consumes that rule; it does not create a second avatar source.
| Aspect | Rule |
|---|---|
| Source column | profile_photo_url on the Users record of the displayed trader — leader and members alike |
| Owning UC | Settings → Profile & Preferences (BR_4.6.2.6 for the upload flow, BR_4.6.2.13 for propagation). There is no avatar setting anywhere else in the Dashboard |
| Propagation model | Read-through, not push. Settings writes one column; this card reads it on its own next data fetch. No sync job, no fan-out event, no cached copy per surface |
Fallback when profile_photo_url IS NULL | The displayed trader's own initials, derived per BR_4.6.2.7. Never a generic placeholder figure |
| Refresh timing | The trader's own photo change is reflected here on the next mount of the Community page, not immediately. Only the sidebar user chip refreshes on the commit's HTTP 200 (Ref: BR_4.6.2.13) |
-
The fallback is resolved per person, not per card. A pod can therefore show a photo for the leader and initials for three members in the same list — for example
Marcus Chenwith no photo renders asMC. This is expected rendering, not a loading state. -
Name and level are not part of this rule. They come from
leader_name/leader_levelandmembers[].name/members[].level, and the title label is resolved from the career path (Ref: BR_4.14.2.8). This rule contributes the image only. -
The avatar is not a Discord asset. The Discord server nickname and Discord profile picture govern what the trader looks like inside the pod channel; they do not feed this card. Conversely, changing the Dashboard photo does not change anything on the Discord side.
-
profile_photo_urlmust be resolved server-side, returned beside the leader fields and inside eachmembers[]entry. The frontend cannot resolve it itself:members[]carriesname,levelandstatusand nouser_id, so it holds names rather than identities. The field is not yet in the specified payload — §10 item 11.
9. Screen Description
| No. | Field Name | Field Type | Displaying rule / Behaviour rule |
|---|---|---|---|
| 1 | Card header | Label | Displaying rule:- Static header text My POD. Displayed in all four states; the card is never hidden and never changes its grid slot. Ref: BR_4.14.2.1.- Overflow: Wrap text.Behaviour rule:- Read-only. No user interaction. |
| 2 | Pending chip | Label | Displaying rule:- Chip with the text Pending, rendered beside the card header.- Displayed only in the Pending Mentor Allocation state; hidden in the other three. Ref: BR_4.14.2.5.- Overflow: Wrap text.Behaviour rule:- Read-only, not clickable. Carries no tooltip and no queue position. |
| 3 | Empty-state title | Label | Displaying rule:- You're not in a POD in the two unassigned states; Pending Mentor Allocation in the pending state. Not rendered in the matched state. Ref: BR_4.14.2.2.- Overflow: Wrap text.Behaviour rule:- Read-only. No user interaction. |
| 4 | Supporting line | Label | Displaying rule:- Unassigned states (both linked and unlinked — the copy does not change with the Discord gate): Join a POD to trade with a team, get feedback, and track performance together. Ref: BR_4.14.2.3.- Pending state: You are in the queue for the next available mentor. We will assign you to a POD as soon as a spot opens up. Ref: BR_4.14.2.5.- Overflow: Wrap text.Behaviour rule:- Read-only. No user interaction. |
| 5 | Pod Leader tile | Label | Displaying rule:- Displayed only in the matched state. Renders the leader's avatar, the display name from leader_name, and beneath it the title and level resolved from leader_level against the 24-level career path — Table A for Futures, Table B for Forex, never Table G. Ref: BR_4.14.2.8.- Avatar — the leader's own profile_photo_url, written in Settings → Profile & Preferences and read through per displayed user. When it is null, the leader's initials are rendered instead, derived per BR_4.6.2.7 — never a generic placeholder figure. Not sourced from Discord. Ref: BR_4.14.2.15.- Identical for a viewer who is the Pod Leader and one who is a Pod Member. Ref: BR_4.14.2.6.- No leader status is rendered — no Under Review, Breached, Suspended or activity indicator. Ref: BR_4.14.2.14.- Overflow: name Truncate with tooltip; title/level line Wrap text.Behaviour rule:- Read-only, not clickable. No drill-down to the leader's profile. The avatar is not an upload control here — the photo is editable only in Settings. Ref: BR_4.6.2.6. |
| 6 | POD members list | Label | Displaying rule:- Section header POD members. Displayed only in the matched state; not rendered at all in the pending state — not as an empty list and not as a zero-state. Ref: BR_4.14.2.5.- Renders every entry of members[], including the trader's own row, which receives no distinct styling. Ref: BR_4.14.2.6.- If members[] is empty (a Pod Leader with no mentees yet), the section renders its own empty line and the card stays in the matched state. Ref: §7.Behaviour rule:- Scrollable within the card when the list exceeds the visible area. The card keeps its fixed height so that the widget beside it is not displaced. Ref: BR_4.14.2.1.- Static list. Rows are not clickable — no profile, PNL or trading-plan drill-down. Ref: BR_4.14.2.6. |
| 7 | Member row | Label | Displaying rule:- Three elements per row: avatar, display name from name, and beneath it the title and level resolved from level on the same career-path mapping as Row 5. Ref: BR_4.14.2.8.- Avatar — that member's own profile_photo_url, resolved per displayed user, with their own initials as the fallback when it is null. A pod may therefore render a photo for one member and initials for the next in the same list; that is expected, not a loading state. Ref: BR_4.14.2.15, BR_4.6.2.7.- Status indicator — an active indicator when status is the active value; the inactive indicator plus the label Inactive beside the name for every other value, including Inactive_Hold. This reflects account status, never Discord presence and never SLA progress. Ref: BR_4.14.2.7, BR_4.14.2.12.- Overflow: name Truncate with tooltip; title/level line Wrap text.Behaviour rule:- Read-only. No context menu, no hover action, no click target. |
| 8 | Enter My POD | Button (Primary) | Displaying rule:- Label Enter My POD. Displayed only in the matched state. Ref: BR_4.14.2.9.- Disabled when the payload reports the account as assigned but discord_channel_url is null or empty — the Flow 15B provisioning window, or an archived pod. No error and no toast accompanies the disabled state. Ref: BR_4.14.2.9.Behaviour rule:- On activation (enabled): opens discord_channel_url in a new tab (target="_blank", rel="noopener noreferrer"). The destination is the pod's private Discord category — one text and one voice channel. The Dashboard session is unaffected and no request is issued.- On activation (disabled): no action.- The Dashboard does not verify that the trader still holds the Pod Member Discord role. Ref: BR_4.5.2.8. |
| 9 | Join a POD | Button (Primary) | Displaying rule:- Label Join a POD. Displayed in the unassigned state when discord_user_id is populated. Enabled. Ref: BR_4.14.2.4.- Not rendered in the matched or pending states.Behaviour rule:- On activation: opens join_form_url from the payload in a new tab. The URL is always read from the response, never hard-coded.- Impact: the trader is handed to an external ActiveCampaign / Typeform form that collects Asset Class and Trading Style and feeds the backend matching waterfall. The Dashboard receives no callback — no confirmation, no spinner and no disabled state is rendered on return, and the resulting state appears only on the next mount. Ref: BR_4.14.2.10. |
| 10 | Link Discord to Unlock | Button (Secondary) | Displaying rule:- Label Link Discord to Unlock with a 🔒 icon. Replaces Row 9 in the unassigned state when discord_user_id IS NULL. Rendered as a secondary / muted control and remains activatable — it is not disabled. Ref: BR_4.14.2.3.- The title and supporting line above it are unchanged from Row 9's state — no separate screen is built. Ref: BR_4.14.2.3.Behaviour rule:- On activation: no modal opens and no navigation occurs. A short highlight / pulse treatment is applied to the Link your Discord account first block inside The PIT card, and the toast Ref: TS-POD-01 is displayed.- On a mobile viewport, where The PIT card is stacked below, activation additionally performs a smooth auto-scroll to that card, with the highlight running on arrival.- Impact: none server-side. No request is issued and no state is written; the control is purely a wayfinding device.- Reverts to Row 9 on the next page load or Community-page mount once discord_user_id is synchronised. The card does not poll for it. Ref: BR_4.14.2.10. |
Related behaviour owned elsewhere:
- The
Link your Discord account firstinstruction block on The PIT card — heading, three numbered steps, token value, [Copy] and [Open Discord] — is owned by BR_4.5.2.7. This card states the blocker and points at that block; it never restates the remedy.- The SIM variant of this card, with its permanently disabled [Join a POD], is owned by UC_4.9.2.
- When the trader navigates into the Community screen, the Newsquawk audio stream in the persistent header switches to Off automatically. Owned by BR_4.1.4.4.
10. Open Items Pending Client Confirmation
| # | Item | Written in this UC as | Why it needs a ruling | Severity |
|---|---|---|---|---|
| 1 | The payload cannot express the pending state. The RFQ describes two branches only — assigned and unassigned — but the client mandated a third state, Pending Mentor Allocation. Both unassigned and pending leave leader_name null, so the frontend cannot distinguish them from the specified payload. | BA proposal: add a pod_status discriminator with the enum unassigned | pending | matched, and switch on it alone (Ref: BR_4.14.2.2) | Without it the Pending Mentor Allocation state that BR_4.14.2.5 requires cannot be implemented. Blocking for BE. | 🔴 |
| 2 | Matched but not linked. The Discord gate was ruled only for the unassigned state. A matched trader with discord_user_id = null would be given [Enter My POD] to a channel they hold no role for — the dead click the client asked to prevent. | BA proposal: apply the identical gate to [Enter My POD] — same label, same muted style, same pulse-plus-toast (Ref: BR_4.14.2.3) | Either the gate is extended, or BE must guarantee that assignment is impossible while unlinked. One of the two must be true. | 🔴 |
| 3 | Source of the member status indicator — Discord online presence, or account status from members[].status? Two client answers exist. (Open Item #6 in QnA_STAGE2_COMMUNITY_LIVE_BROADCAST.md.) | Account status from members[].status (Ref: BR_4.14.2.7) | The presence reading requires a Discord presence poll the backend does not have — new BE scope. | 🟡 |
| 4 | Fields collected by the matching form — Asset Class and Trading Style, or Trading Style only with Asset_Class derived from the trading account? (Open Item #7.) | Both fields, per Flow 10 Step 2 (Ref: BR_4.14.2.4) | Low FE impact — the form is third-party — but it is the input to the matching waterfall, whose first criterion is a strict asset match. | 🟡 |
| 5 | CTA label: Enter My POD or Enter Pod Chat? The design pack and [POD-BIZ-13] use the former; the RFQ and the WBS use the latter. | Written as Enter My POD (Ref: BR_4.14.2.9) | Copy confirmation only, but it appears in the WBS description and will otherwise be raised at UAT. | 🟡 |
| 6 | members[].status has no defined enum. The RFQ says only "status": "string". The client's answer groups "inactive or suspended" into one visual state; Flow 12 writes Inactive_Hold. | Rendered as binary: the active value → active indicator; everything else → inactive indicator + Inactive label (Ref: BR_4.14.2.7) | QA cannot write test data without the legal values, and a future BE value would silently render as inactive. | 🟡 |
| 7 | Discord Server Details.md restricts the pod channel to "Trader Level 6 and above", contradicting [POD-DEF-01] (Level 1+) and Flow 10, which assigns a pod immediately after live onboarding. | Written to [POD-DEF-01] — Level 1+ (Ref: BR_4.14.2.1) | If the Discord document is authoritative, Level 1–5 traders would be matched into a channel their role cannot open, and the whole card is wrong for them. | 🟡 |
| 8 | Alumni graduation leaves three questions open (Open Item #14): (a) if a trader declines the Pod Leader invitation, do they stay pod-less or re-join as a mentee; (b) is the departing mentee's carry / SLA state cleaned up; (c) what does the mentor's card show when a mentee graduates out. | (c) written as the mechanical consequence — the row disappears on the next mount, with no notification and no Graduated label (Ref: BR_4.14.2.13). (a) and (b) not specified | (a) decides whether the unassigned state of §6.1 is a dead end or a re-entry point for a Level 7+ trader. | 🟡 |
| 9 | Does Flow 7 trigger Flow 11 after freeing the seat? The Flow 4 graduation patch explicitly does; the Flow 7 Pod Impact & Dispersal step does not say. (Open question (c) of CR-20260818-001, Open Item #17.) | Consequence recorded, not resolved (Ref: BR_4.14.2.13) | If it does not, a seat freed by a resignation is never filled automatically and traders sit in §6.3 indefinitely. | 🟡 |
| 10 | Design pack not in the repository. The four states in §1 came to BA as images on 2026-08-26 and are not under References/Wireframe/. The two files that do exist, in Stage 2/Community & Live Broadcast/, cover only states 1 and 2. | Cited as "client design pack, 2026-08-26" | The UC cites a source that cannot be opened from the repo. The files should be committed under References/Wireframe/Stage 2.2/Community & Live Broadcast/. | 🟢 |
| 11 | The payload carries no avatar field, and no user_id to resolve one from. Get Pod Data returns names, levels and statuses only, yet the design renders an avatar on the leader tile and on every member row. The pod query and the Users.profile_photo_url column are in the same SQL database, so this is a join, not an integration (Ref: BR_4.14.2.15). | BA proposal: the endpoint returns profile_photo_url beside the leader fields and inside each members[] entry, resolved server-side | Without it the card renders the trader's own photo at best and initials for everyone else, contradicting the design pack. Fold into the same payload change as item 1. | 🟡 |
11. Build Ownership
Recorded because the pod system spans four parties and the card renders data that none of Sotatek's code writes.
| Item | Sotatek builds | Stack Trading Ops configures | Third party runs |
|---|---|---|---|
| The My POD card and its four states | ✅ Frontend | — | — |
| Trader avatars on the card | ✅ Frontend renders; Settings → Profile & Preferences owns the upload and the column (Ref: BR_4.14.2.15) | — | AWS S3 (image storage behind the signed-URL upload) |
GET /community/my-pod | ✅ Backend | — | — |
POST /create-pod-channel · POST /archive-pod-channel · POST /manage-discord-role and the Node.js Discord bot | ✅ Backend | — | Discord (platform) |
Pod_Max_Capacity, Min_Pod_Leader_Level (Table C) and per-leader Max_Capacity, Status (Table E) | — | ✅ via Zapier Tables, no deployment | Zapier |
| Registering a new mentor · marking a leader eligible or ineligible | — | ✅ | Zapier |
The matching form behind join_form_url (Asset Class, Trading Style) | — | ✅ builds and owns the form | Typeform or ActiveCampaign |
| The matching waterfall, waitlist, SLA cron, AI brief, carry vesting (Flows 10 / 10.x / 11 / 15 / 17) | ✅ Backend endpoints called by the flows | ✅ owns the Zap definitions | Zapier · Gemini · Klaviyo · Dots / Rippling |
Pod_Reassigned_Notification, Pod_Waitlist_Notification, Pod_Spot_Available_Confirm email templates and sends | ❌ — webhook payload only | — | Klaviyo (Ref: BR_4.14.2.13) |
Setting Role_Flag = 'Founding Mentor' | ✅ Backend field | ✅ set manually by Admin | Rippling (agreement signature) |
Changelog
| Date | Version | Updated item | Before | After | Notes |
|---|---|---|---|---|---|
| 2026-09-06 | v1.1 | BR_4.14.2.2 · BR_4.14.2.6 · §10 — WBS contract bypassed | Logged as 🔴 open item 2, blocking for BE: the WBS row names GET /pod/status and expects a waitlist_position and a carry balance, contradicting the RFQ and the client answers. | Not an open item — the WBS row is wrong and is bypassed. This document is authoritative and BE builds to it: GET /community/my-pod, no queue position, no carry balance. 📋 Housekeeping outside this UC: correct WBS row stt 105 (mapping_be, mapping_fe, description) in References/WBS/. Item removed from §10; the remaining items renumbered 1–11 and all cross-references updated. Two 🔴 blocking items remain — pod_status and the matched-but-unlinked gate. | User decision 2026-09-06. |
| 2026-09-06 | v1.1 | §10 item 13 — avatar source vs. Discord | Logged as an open item, closed in place with a ✅ row and a paragraph of rationale, while the two BR_4.14.2.15 blockquotes still described it as an unsettled BA position. | Item removed from the Open Items table — it is not open. The rule stands as written in BR_4.14.2.15: Dashboard profile_photo_url first, the displayed trader's initials as the only fallback, Discord never consulted for an avatar or a name on any surface. [PP-DEF-02] answered 2026-08-27; client rationale was broken images and expired Discord CDN links. BR_4.6.2.13 rules and this UC inherits — adding a second avatar source would be a change request. Twelve open items remain, three of them 🔴 blocking for BE. | Client answer 2026-08-27, [PP-DEF-02]. |
| 2026-09-06 | v1.1 | §5 · §6 · §8 Business Rules — duplicated open-item narrative removed | Each open item was written twice: a multi-paragraph blockquote inside its Business Rule (client quotes, who-said-what history, "BA proposal pending confirmation") and a full row in §10. Verbatim client quotes also sat inside rule descriptions. | Business Rules state the decided rule only, each followed by a one-line pointer to its §10 item. No content is lost — §10 already carried every open item in full. Client quotes removed from rule descriptions; short (Source: …) citations kept for traceability. Affects BR_4.14.2.1 · BR_4.14.2.2 · BR_4.14.2.3 · BR_4.14.2.4 · BR_4.14.2.5 · BR_4.14.2.6 · BR_4.14.2.7 · BR_4.14.2.9 · BR_4.14.2.10 · BR_4.14.2.15. | User request 2026-09-06. Editorial only — no rule, field, endpoint or state behaviour changed. |
| 2026-08-26 | v1 | Initial document | — | — | Created for the LIVE counterpart of UC_4.9.2. Closes every item that BR_4.9.2.3 deferred to this UC. Content sourced from client-confirmed answers [POD-DEF-01], [POD-DEF-02], [POD-BIZ-01] → [POD-BIZ-16], [POD-UI-01], [POD-ZAP-01] in Stage 2 - Dashboard & Fomula (Community).csv; FM-09 in the Founding Mentor QnA; RFQ_ Stack Trading Prop Tech V7.pdf §Community Endpoints; RFQ_ Website and Dashboard Implementation V7.pdf §Community Page Implementation; Zapier Integration V7.pdf Tables C and E and Flows 10 / 11 / 12 / 15A–C / 17; Discord Server Details.md; CR-20260818-001; and the client design pack of 2026-08-26. Scope is the Dashboard presentation only — the matching engine, SLA engine and carry vesting stay with UC_8.2.x and are referenced in BR_4.14.2.13 purely as the events that change this card. New toast Ref: TS-POD-01 added to the master list for BR_4.14.2.3. BR_4.14.2.15 takes up the avatar-source ruling that BR_4.6.2.13 deferred to this UC. Open items logged in §10. |