Common Business Rules
Project: Stack Trading Date Created: 2026-07-22 Version: v1.7 Last Updated: 2026-08-31
This document defines common business rules that repeat across multiple screens or UCs. Rules that appear only in a single flow/UC belong in that UC's SRS doc, not here.
CR-01: Numeric Fields
Applies to all numeric input fields (integer only). Does NOT apply to phone numbers, zip/postal codes, or identification numbers — those follow their own format rules specified in the UC.
1.1 Character Validation — Real-Time Block
| Criterion | Rule | Error Message |
|---|---|---|
| Valid chars | Allowed: digits0–9. On invalid keystroke → Block — character does not appear in the field, no message shown | — |
| Paste — invalid format | Reject entire string — nothing is inserted. Show red inline error below field immediately | "Invalid number format" |
1.2 Length Limit
| Criterion | Rule | Error Message |
|---|---|---|
| Max length | Max15 digits. Typing the 16th digit → Block, no message | — |
| Paste exceeding limit | Reject entire string, no auto-truncate. Show red inline error immediately | "[Field name] must not exceed [max] characters" |
1.3 Auto-format (no error shown)
| Criterion | Rule |
|---|---|
| Leading zero | Auto-remove when user types a second digit. E.g.09 → 9 |
| Leading/trailing spaces | Keep while typing; auto-trim on out-click |
1.4 Placeholder & Required
| Criterion | Rule | Error Message |
|---|---|---|
| Placeholder | Display*"Enter [field's label]"* when field is empty | — |
| Required field — empty | On out-click → show red inline error below field + red border. Error auto-clears when user types a valid character | "Please enter [field's label]" |
CR-02: Text / Textarea / Search Fields
Applies to all Textbox, Textarea, and Search inputs.
2.1 Whitespace Auto-Trim
| Criterion | Rule |
|---|---|
| Leading/trailing spaces | Keep while typing (no UX disruption). Auto-trim on out-click |
| Spaces-only input | Treated as empty — applies required-field rule if applicable |
2.2 Default Length Limits
| Field Type | Limit | On Limit Reached |
|---|---|---|
| Textbox | 255 chars | Do NOT block while typing. On out-click → red inline error below field + red border |
| Textarea | 500 chars | Do NOT block while typing. On out-click → red inline error below field + red border |
| Search box | 255 chars | Block — character 256 cannot be entered, no message shown |
| Promo code input | 100 chars | Block — character 101 cannot be entered, no message shown |
2.3 Placeholder
| Field Type | Placeholder |
|---|---|
| Textbox / Textarea | "Enter [field's label]" — specify exact label, e.g. "Enter email" |
| Search box | "Search" |
2.4 Required Field & Errors
Required timing is IDENTICAL for all field types: "On out-click"
| Criterion | Rule | Error Message |
|---|---|---|
| Required — empty | On out-click → red inline error below field + red border. Error auto-clears when user types valid input | "Please enter [field's label]" |
| Over max — Textbox/Textarea | On out-click → red inline error below field + red border. Error auto-clears when input is trimmed to valid length | "[Field name] must not exceed [max] characters" |
| Under min | On out-click → red inline error below field + red border. Error auto-clears when input meets minimum length | "[Field name] must be at least [min] characters" |
2.5 Search Behavior
| Criterion | Rule |
|---|---|
| Real-time search | Filter and display results as user types each character — no Enter required |
| Case sensitivity | Case-insensitive |
CR-03: Dropdown
Applies to all Dropdown / Combobox components.
| Criterion | Rule | Error Message |
|---|---|---|
| Default state | Show*"Select [field's label]"* placeholder. No option pre-selected unless UC specifies a default | — |
| Long option text | Truncate with... in the field. Hover → tooltip shows full text | — |
| After selection | Close dropdown; display selected value in field. No✕ clear icon | — |
| Re-open dropdown | Currently selected option is highlighted (checked/bold) in the list | — |
| Required — empty | On out-click → red inline error below field + red border. Error auto-clears when user selects a valid option | "Please select [field's label]" |
CR-04: Filter Dropdown — Default "All"
Applies to filter controls on list screens. Does NOT apply to form dropdowns.
| Criterion | Rule |
|---|---|
| "All" option | Every filter dropdown MUST have an"All" option at the top of the list |
| Default value | On first load →"All" is selected; all records are displayed |
| Results | Update immediately on filter change — no confirmation needed |
| Distinction | Form dropdown: placeholder"Select [field's label]", no "All" option — see CR-03 |
CR-05: Unsaved Data Navigation Warning
Applies to screens with data-entry forms.
5.1 Trigger Conditions
| Condition | Description |
|---|---|
| Form is dirty | User has changed at least one field since the form loaded |
| Navigation away | User clicks [Cancel], switches tab, uses breadcrumb, or any method to leave the current screen |
| No trigger | Form has not changed → navigate normally, no popup |
5.2 Warning Popup Content
Ref: CF-01
CR-06: List Pagination
| Criterion | Rule |
|---|---|
| Default page size | 10 records per page |
| Page size options | 10, 20, 50, 100. Change → reload list, return to page 1 |
| [Previous] button | Disabled on page 1 |
| [Next] button | Disabled on the last page |
| Info display | "Showing [start]–[end] of [total] records" |
CR-07: File Upload
Applies to screens with upload features. Screen applicability defined in the UC. File count, size limit, and format MUST be taken from UC. Do NOT hardcode defaults.
7.1 Upload Limits
| Criterion | Value | Source |
|---|---|---|
| Maximum file count | [From UC] | UC must specify |
| Allowed formats | [From UC] | UC must list exact extensions |
| Max size per file | [From UC] | UC must specify (e.g., 5 MB, 10 MB) |
7.2 Error Messages
| Violation | Error Message |
|---|---|
| Wrong format | "File [filename] is not an accepted format. Accepted formats: [list from UC]" |
| Exceeds file count limit | "Maximum [N] files allowed" |
| File exceeds size limit | "Please select a file smaller than [N] MB" |
| Server error during upload | Error toast : "Failed to upload file. Please try again later" |
7.3 Upload Area States
| Screen Mode | State |
|---|---|
| Create / Edit | Enabled — user can add or remove files |
| View Detail | Disabled (read-only) — show file list only |
CR-08: Timestamp Standard — UTC / ISO 8601 / Millisecond Precision
Applies to all date/time values across the entire stack: API request and response payloads, database columns, log entries, and webhook parameters.
8.1 Required Standard
| Attribute | Specification |
|---|---|
| Timezone | UTC only. Local timezones must never be stored or returned. |
| Format | ISO 8601 —YYYY-MM-DDTHH:mm:ss.sssZ |
| Precision | Milliseconds (.sss) — required so logs can measure sub-50ms operations |
| DB column type | TIMESTAMP WITH TIME ZONE storing UTC |
| Scope | API request payloads, API responses, database columns, log entries, Zapier webhook parameters |
8.2 Exception
Issuing platforms and brokers (e.g. CME exchange session rollover) manage localized market session schedules independently. Stack Trading's timestamp standard applies only to Stack Trading's own stack and does not override exchange-side time configurations.
8.3 Affected Fields (Non-Exhaustive)
Fields confirmed in source documents that must conform to this rule:
| Field / Column | Location |
|---|---|
timestamp_utc | API:POST /execute-checkout input payload |
expiration_date | Evaluation lifecycle (DB + API response) |
created_at, updated_at | All DB tables (audit metadata) |
start_date timestamp_utc | Evaluation start tracking |
Session_Open_UTC, Official_Close_UTC | Market session DB columns (Zapier tables) |
Halt_Start_UTC, Halt_End_UTC | Market session halt window columns |
Last_Ingested_UTC | Data ingestion audit checkpoint |
next_state_timestamp | /system/market-status response — "ISO8601" format |
CR-09: Special Field Types
Applies to Email and Phone Number input fields across the system. Rules here override CR-02 defaults where specified.
Note: No phone number field has been identified in customer supplies to date. This rule is defined preemptively for future UCs. If a UC introduces a phone field, reference §9.2 and specify any UC-specific constraints inline.
9.1 Email Field
| Criterion | Rule |
|---|---|
| Placeholder | "Enter email" |
| Max length | 100 characters (overrides CR-02 default of 255) |
| Required characters | Must contain@ and at least one . in the domain part |
| Allowed characters | Letters (a–z, A–Z), digits (0–9),. (dot), _ (underscore), - (hyphen) |
| Prohibited characters | Spaces, accented characters, and special characters (e.g.!, #, $, ,) — blocked on paste; flagged on out-click |
| Format | [local-part]@[domain].[tld] — e.g. user@gmail.com |
| Auto-trim | Leading and trailing spaces automatically removed on out-click |
| Validation timing | On out-click (not real-time) |
Validation errors:
| Situation | Timing | Error Message |
|---|---|---|
| Required field — empty | Out-click | "Please enter email" |
| Invalid format | Out-click | "Please enter a valid email address" |
| Exceeds 100 characters | Out-click | "Email must not exceed 100 characters" |
9.2 Phone Number Field
| Criterion | Rule |
|---|---|
| Placeholder | "Enter phone number" |
| Input structure | Two-part field:[Dial code selector] (prefix, left) and [Number input] (right) |
| Dial code default | +1 (United States) on first load |
| Dial code selector | Scroll-only — no search input; user browses the country list by scrolling |
| Valid characters | Digits (0–9) only. Letters and special characters are blocked in real-time |
| Auto-trim | Leading zeros in the number input are automatically removed on out-click |
| Length | FollowsE.164 international standard: 6–15 digits (excluding dial code) |
| Submitted / stored format | The dial code and number are concatenated into a single E.164 string (e.g. +14155552671) — no separator, no spaces. This combined value is what's sent in the API payload (phone_number) and stored in the DB. The UI keeps the two-part input for entry, but the value leaving the form must always carry the country code. |
| Validation timing | On out-click and on submit |
Validation errors:
| Situation | Timing | Error Message |
|---|---|---|
| Required field — empty | Out-click / Submit | "Please enter phone number" |
| Invalid length / format | Out-click / Submit | "Please enter a valid phone number" |
CR-10: Tooltip Interaction
| Environment | Trigger | Dismiss |
|---|---|---|
| Desktop | Hover over tooltip icon | Auto-dismiss on cursor leave |
| Mobile | Tap tooltip icon | Tap anywhere outside the tooltip |
- Tooltip content is static text only — no interactive elements (links, buttons) inside.
- Tooltip does NOT block the flow or require user acknowledgement.
CR-11: Numeric / Monetary Value Display
Applies to all numeric and monetary fields displayed across the app — price, fee, discount, tax, total, balance, equity, PnL, and any other financial or numeric value shown on a screen.
| Criterion | Rule |
|---|---|
| Format | Display with max 2 decimal places. Example:499.00, 11.94, 510.94. |
| Discount display | Discount line items are displayed as a negative dollar amount:−$XX.XX (en-dash + dollar sign + value to 2 decimal places). Example: −$25.00. The value is the absolute discount_amount float returned by the server — never a negative float. |
| Hover | Every value always shows a tooltip on hover with thefull value. Ref: CR-10 for tooltip interaction behavior |
| Thousands separator | Use comma, for thousands grouping (e.g. 1,250.00). |
CR-12: UTM Attribution Capture — Global, Root Layout
Source: Adrian Stack (client, Slack, 2026-07-30). Supersedes any UC-local UTM capture rule that scopes parsing to a single page/step — see CR-20260730-002.
Applies site-wide — every public page of the Marketing website, the Checkout App, and the Partner Application page. This is a cross-cutting rule, not specific to any single UC; individual UCs reference this rule instead of re-defining UTM capture logic.
12.1 Rationale
Users enter the site from unpredictable URLs (an ad may link to a blog post, an affiliate may link to the homepage, organic search may land anywhere). Because users navigate across multiple pages before converting, the system cannot rely on UTM parameters remaining in the active URL bar at the moment of conversion. Two attribution-critical paid-ad flows depend on this rule:
- Associate Track landing page(s) → Checkout.
- Partner landing page → Partner Application webform.
12.2 Global Root Execution
| Criterion | Rule |
|---|---|
| Where | The UTM parsing script sits in theroot layout component — fires on every single page load and every route change, across the entire frontend (Marketing website + Checkout App). Not isolated to specific pages. |
| When | On page initialization (mount) and on every client-side route change. |
12.3 Persistent Storage — localStorage
| Criterion | Rule |
|---|---|
| Storage mechanism | localStorage (not sessionStorage, not in-memory state only) — so attribution survives a closed browser and a returning user on a later visit. |
| UTM parameters present in URL | Writeutm_source, utm_medium, utm_campaign, utm_term, utm_content to localStorage. If old UTM values already exist in storage, overwrite them — this is deliberate last-touch attribution, not first-seen-wins. |
| No UTM parameters in URL | Donothing. Do NOT clear localStorage. Do NOT overwrite existing values with null. Leave existing localStorage UTM values intact. |
12.4 Payload Injection
At the moment of submission for any of the three conversion points below, the frontend component reads the current UTM values from localStorage and injects them into the outbound API payload:
| Conversion point | UC reference |
|---|---|
| Partner Application submit | Partner Application form (CR-20260726-005) |
| Join Waitlist | UC_2.1.3 — direct ActiveCampaign + Klaviyo calls |
| Step 5 of Checkout | UC_2.6.1 / UC_2.6.2 POST /capture-lead, and POST /execute-checkout at Step 6 |
This guarantees acquisition source data is preserved and transmitted to Stack Trading's database, Klaviyo, and ActiveCampaign, even if the user clicks around the site, leaves, and returns later via a clean URL (no UTM params).
CR-13: Rounding to 2 Decimal Places
Applies to all backend-calculated numeric/monetary values that feed into threshold comparisons or are displayed — e.g. Daily_Loss_Limit, Net_P&L, and similar computed values.
| Criterion | Rule |
|---|---|
| Algorithm | Round to nearest hundredth (2 decimal places), round-half-up. Use the code language's native rounding function (e.g.Math.round, toFixed) — no need to hand-code a carry-chain. |
| Examples | 624.99375 → 624.99. 624.99875 → 625.00. |
| Ref | Display formatting once rounded →CR-11. |
CR-14: WebSocket Reconnection & Snapshot Resiliency (Shared)
Applies to every Dashboard widget/table fed by a WebSocket event (e.g. POSITION_METRICS, PERFORMANCE_UPDATE, and equivalent event channels across other Dashboard UCs).
| Criterion | Rule |
|---|---|
| Trigger | Cloudflare edge routing can drop idle or long-running WebSocket connections; separately, the underlying market/exchange can go into an off-hours/closed state where no new events are emitted at all. |
| Backend snapshot persistence | The Backend maintains and holds the latest data snapshot for each real-time widget/table (not merely re-broadcasting on push), so that on a fresh page load or a page reload (F5), the Frontend can restore the widget/table from that snapshot immediately — instead of rendering it empty while waiting for the next WebSocket event. |
| Reconnection behavior | Frontend implements exponential backoff and automatic reconnection to prevent UI freezing or silent data failures. |
| Data retention while reconnecting | Widgets/tables retain their last-known snapshot values rather than clearing to empty while the WebSocket connection is temporarily unavailable or disconnected. |
| Market-closed behavior | If the market is closed (no new events being emitted because there is no trading activity), the widget/table continues displaying the latest available snapshot data until new data becomes available — it does not reset to empty or zero merely because no real-time events are currently arriving. |
| Page reload (F5) behavior | On page load/reload, the Frontend renders from the Backend's latest snapshot first, then applies subsequent WebSocket events on top of it. The widget/table is never shown empty purely because no new WebSocket event has arrived yet since load. |
| Ref | Source: RFQ_ Website and Dashboard Implementation V7.pdf (original reconnection-resiliency rule); Source: User instruction (BA session), 2026-08-31 (extends the rule to backend snapshot persistence, market-closed behavior, and page-reload/F5 behavior). |
(Moved here from UC_4.2.1 §BR_4.2.1.4, which was scoped to a single widget but referenced by multiple sibling and external UCs — see Changelog. Extended 2026-08-31 to cover snapshot persistence, market-closed, and F5/reload behavior, per the same rationale — this is a shared cross-cutting concern, not specific to any one widget.)
CR-15: Reference
CR-15.1: Email
Support@stacktrading.com Marketing@stacktrading.com Compliance@stacktrading.com Sales@stacktrading.com no-reply@stacktrading.com
CR-15.2: Slack
Production Channels
#ops-treasury ID: C0BRCCMN1MG Receives Hourly Solvency Reports, Automated Treasury Sweep confirmations, and the Daily EOD Firm Health Report.
#ops-risk ID: C0BREC78LGH (Replacing #risk-ops): Receives High-Impact News Event summaries, Overnight Margin and Swap Monitor alerts, and TRIM_TO_COMPLIANCE gateway rejection Severity 1 alerts.
#ops-dev ID: C0BRCDB8U3U (Replacing #dev_ops): Receives the Configuration Database Backup success or failure notifications.
#ops-marketing ID: C0BQX3AV679 (Replacing #marketing): Receives fulfillment notifications, such as a Level 10 trader claiming a Tom James Suit or Goodwill Merch inventory depletion alerts.
#ops-onboarding ID: C0BRC4UE15F Receives Background Check flags from Checkr and E-Verify failures.
#ops-general ID: C0BR8LRC5MK (The Catch-All): Designated for Veriff manual resets, FCM institution denial alerts, Dispute/Chargeback handlers, Pay raise logic confirmations, Pod Vesting completions, MID capacity warnings, and Aggregate Exhaustion Severity 1 alerts.
#ops-security ID: C0BQX3L74B1 (The Restricted Channel): A designated secure channel for receiving "High Volume Pod Reassignment" alerts to monitor internal administrators for abuse.
Development/Test Channels
#test-ops-onboarding ID: C0BQX1MDX47 Receives Background Check flags from E-Verify failures.
#test-ops-treasury ID: C0BRCBMGTC2 Receives Hourly Solvency Reports, Automated Treasury Sweep confirmations, and the Daily EOD Firm Health Report.
#test-ops-risk ID: C0BRAMTDYMQ Receives High-Impact News Event summaries, Overnight Margin and Swap Monitor alerts, and TRIM_TO_COMPLIANCE gateway rejection Severity 1 alerts.
#test-ops-general ID: C0BR6UXRR8D Designated for Veriff manual resets, FCM institution denial alerts, Dispute/Chargeback handlers, Pay raise logic confirmations, Pod Vesting completions, MID capacity warnings, and Aggregate Exhaustion Severity 1 alerts.
Glossary
| Term | Definition |
|---|---|
| Trader | Participant in the evaluation program; if targets are met, receives real capital allocation |
| PnL (Profit and Loss) | Trader's profit or loss metric |
| Equity | Current net worth = Starting Balance + Floating P&L. Distinct from Balance (settled) |
| Drawdown | Capital decline — % loss from the highest point ever reached. Primary risk metric |
| Daily Loss Limit | Maximum permitted loss in one trading day. Breach → Soft_Breach (trading suspended until day reset) |
| Max Drawdown / Level Stop | Maximum cumulative loss limit. Breach → account permanently closed (Hard Breach) |
| Profit Target | Required profit level for a trader to pass the evaluation |
| Soft Breach | Minor violation (Daily Loss Limit hit). Trading temporarily suspended; account remains open |
| Hard Breach | Severe violation (Max Drawdown hit). All positions liquidated; account permanently locked |
| Flatten / Liquidate | Close all open positions, returning account to a "flat" (no open orders) state |
| Trim (Partial Position Reduction) | Close a portion of a position (not all) to reduce risk |
| TRIM_TO_COMPLIANCE | Automated algorithm: when risk threshold is exceeded, iteratively close largest positions until portfolio is within safe limits |
| Atomic Kill Switch | Emergency shutdown — 4 sequential steps: (1) lock new orders, (2) close all positions, (3) cancel pending orders, (4) update DB → status "Failed" |
| Margin | Minimum capital required to hold positions overnight |
| DMA (Direct Market Access) | Order routing mechanism that sends orders directly to the real exchange without intermediaries |
| FCM (Futures Commission Merchant) | CFTC-licensed broker for Futures contracts. Ironbeam is Stack Trading's FCM |
| Omnibus Account | Master account held under the company name at the exchange, containing individual trader sub-accounts |
| KYC (Know Your Customer) | Mandatory identity verification process before live capital allocation, for AML/fraud prevention |
| W-8BEN / W-9 | US tax forms: W-9 for US citizens, W-8BEN for non-US persons |
| Carry | Commission earned by a Pod Leader from the profits of their Pod members |
| Pod | Trading group — one leader plus multiple members sharing a trading style |
| WORM (Write Once, Read Many) | Immutable storage mechanism: once written, data cannot be modified or deleted |
| Immutable Ledger | Immutable on-chain record — data written to Polygon PoS blockchain; no one can alter payment history |
| W-2 Employee | Official US employee with a fixed-term contract, salary, benefits, and paid time off |
| International Contractor | Non-US collaborator; receives compensation via Dots (not US payroll) |
| Rippling | HR and payroll management software — automates employee onboarding, tax calculation, and salary disbursement |
| DTO (Days Time Off) | Paid Time Off |
| Evaluation Package | Trader evaluation tier — 3 options: Associate Track (EVAL_L1 / $650 / $25k notional), Accelerated Associate Track (EVAL_L2 / $1,250 / $50k notional), Advanced Associate Track (EVAL_L5 / $4,500 / $150k notional) |
| Founder Cohort | "Founding 500" program — first 500 registrants purchase at a permanently locked price (no market increases) |
| Reset Token | Token allowing a failed trader to reset their Sim account to Day 1, keeping their tier. Cheaper than a new purchase |
| Re-Buy | When a trader fails on a Live account (Level 1+), they must purchase a new Challenge to restart from Level 0. Price = Challenge Price × (1 − Retry_Discount) |
| Defense Protocol | Protection for Level 9+ traders who hit Level Stop — instead of immediate termination, they enter a 48-hour cooling-off period, then trade again with reduced parameters (capital ×0.25, target 6%, stop 5%) |
| Flow A–J | Checkout geo-routing system by country: A=USA/default, B=UK/AU, C=EU/EEA, D=Quebec (French UI), E=UAE, F=Sanctioned (block 403), G=India, H=Philippines, I=Brazil, J=South Africa |
| NMI | Primary payment gateway — processes Credit Card, Apple Pay, Google Pay via Collect.js iframe (PCI compliant) |
| Rithmic | Futures gateway — Level 0 uses Paper Trading Gateway (sim); Level 1+ uses Live FCM Gateway (Ironbeam) |
| TraderEvolution | Primary Forex platform — provides Admin API for account management and equity monitoring |
| YourBourse Bridge | FIX routing bridge — routes orders from TraderEvolution/MT5 to Forex.com and Interactive Brokers |
| Zapier | Automation bus — orchestrates 40+ operational flows (provisioning, promotion, termination, billing, payout, etc.) |
| The Desk Manager / GEKKO | AI commentary engine (Gemini 1.5 Flash 8B) — plays the role of Gordon Gekko, auto-commenting on trader actions across 15 event types. Rate limit: 10 critiques/hour/user |
| Zapier Tables A–J | Global configuration variables stored in Zapier: Table C (global vars), Table D (email templates), Table E (Pod Leader Registry), Table F (Defense Matrix), Table G (Discord roles), Table H (Perks Registry), Table I (Platform Registry), Table J (Pricing) |
| UTC | Coordinated Universal Time — standard for all system timestamps, expiration metrics, and database entries. See CR-08 |
| Nuvei | Payment gateway for LatAm (Brazil, Colombia, Mexico) — replaces EBANX per CR-20260720-002 |
| Everflow | Affiliate/velocity tracking platform — replaces Impact.com per CR-20260720-003 |
| TradeSea | Trading platform — replaces NinjaTrader per CR-20260720-001 |
| Freshdesk | Support ticketing system — replaces Zendesk per CR-20260720-004 |
Changelog
| Date | Version | Updated item | Before | After | Notes |
|---|---|---|---|---|---|
| 2026-07-26 | v1.1 | Initial document | — | CR-01–CR-11 + Glossary | Init version. |
| 2026-07-30 | v1.2 | New CR-12 — UTM Attribution Capture | No global cross-cutting UTM rule existed; UTM capture logic was defined locally inside UC_2.1.1 (BR_2.1.1.4) as session-state + first-seen-wins, scoped to the checkout page only | Added CR-12: global root-layout execution (site-wide, not checkout-only) +localStorage persistence + last-touch (overwrite-on-presence) attribution + payload injection at Partner Application / Waitlist / Checkout Step 5. Supersedes BR_2.1.1.4's storage/attribution mechanism. | CR-20260730-002; Adrian Stack (Slack, 2026-07-30) |
| 2026-08-06 | v1.3 | CR-09 §9.2 — Phone Number Field: Input structure | Two-part field: [Country flag + Dial code] (prefix, left) and [Number input] (right) | Two-part field: [Dial code selector] (prefix, left) and [Number input] (right) — Removed unsourced "Country flag" component; no source confirms flag UI element. |
| 2026-08-08 | v1.4 | New CR-13 — Rounding to 2 Decimal Places | No shared rounding rule existed; UC_4.10.1 referenced CR-11 (display format) for its rounding logic | Added CR-13: round-half-up to nearest hundredth using the code language's native rounding function, applies to computed values likeDaily_Loss_Limit/Net_P&L. UC_4.10.1's BR_4.10.1.1 now cites CR-13 for the rounding algorithm (CR-11 remains for display formatting only) | STAGE2-031; QN-4.10.1-02/04 |
| 2026-08-10 | v1.5 | New CR-14 — WebSocket Reconnection Resiliency (Shared) | Rule lived only as UC_4.2.1 §BR_4.2.1.4, a single-widget BR referenced by 4 sibling UCs (4.2.2/4.2.3/4.2.4/4.2.5) and 4 external UCs (4.3/4.4/4.8.1/4.8.2) | Moved to CR-14 (generalized to any WS-fed Dashboard widget); UC_4.2.1's BR_4.2.1.4 removed, all 8 cross-reference points repointed to common_rules.md#cr-14-websocket-reconnection-resiliency-shared | User request — UC_4.2.1-4.2.5 batch edit |
| 2026-08-20 | v1.6 | CR-02 §2.2 — Default Length Limits: added Promo code input row | Table only listed Textbox (255), Textarea (500), Search box (255) — Promo code input's 100-char block limit existed only locally in UC_2.7-2.8 §5 Screen Description Row 1, not in the shared table | Added row: Promo code input — 100 chars, Block (character 101 cannot be entered, no message shown), matching UC_2.7-2.8's existing field-level spec | User request |
| 2026-08-31 | v1.7 | CR-14 renamed "WebSocket Reconnection Resiliency" → "WebSocket Reconnection & Snapshot Resiliency"; added Backend snapshot persistence / Market-closed behavior / Page reload (F5) behavior rows | CR-14 only covered mid-session reconnection (widget retains last-known values while reconnecting) — did not cover backend snapshot persistence for reload, market-closed state, or F5 behavior | Extended to: (1) Backend maintains latest snapshot per widget so reload restores immediately instead of rendering empty; (2) market-closed → keep showing latest snapshot until new data arrives; (3) F5/reload → render from snapshot first, then apply subsequent WS events on top | User instruction (BA session) — applies to all UCs referencing CR-14 (UC_4.2.1-4.2.5, UC_4.3, UC_4.4, UC_4.5.1, UC_4.5.2, UC_4.6.1-4.6.4, UC_4.8.1, UC_4.8.2, UC_4.12.1, UC_4.12.2, UC_4.12.4, UC_4.12.6, UC_4.13) |
| 2026-08-25 | v1.7 | New CR-15 — Reference (Email & Slack) | Did not exist | Added CR-15 with two sub-sections: CR-15.1 (5 operational email addresses) and CR-15.2 (Slack channel registry — 7 production channels + 4 development/test channels, each with channel ID and description) | User request |
| 2026-08-26 | v1.8 | CR-09 §9.2 — Phone Number Field: added "Submitted / stored format" row | Table only specified the two-part UI input (dial code selector + number input) and E.164 length (6–15 digits excluding dial code); no rule stated whether the dial code must be included in the value sent to the API / stored in DB — downstream UCs (e.g. UC_4.6.2_v1.md, IN-10) already assumed a combined E.164 string but CR-09 itself never said so | Added row: dial code + number are concatenated into a single E.164 string (e.g. +14155552671, no separator) before being sent in the phone_number payload / stored in DB | User request |