@pnx-mixtape/mxds 0.1.0-rc.4 → 0.1.0-rc.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/.claude/skills/create-mxds-component/SKILL.md +77 -0
  2. package/DESIGN.md +595 -0
  3. package/README.md +2 -3
  4. package/dist/build/accordion.entry.js +2 -1
  5. package/dist/build/autocomplete.entry.js +1 -1
  6. package/dist/build/back-to-top.css +1 -0
  7. package/dist/build/back-to-top.entry.js +1 -0
  8. package/dist/build/base.css +1 -1
  9. package/dist/build/button.css +1 -1
  10. package/dist/build/card.css +1 -1
  11. package/dist/build/chunks/Accordion-Bqe8vTNR.js +44 -0
  12. package/dist/build/chunks/AccordionGroup-BYtoAFxg.js +47 -0
  13. package/dist/build/chunks/AccordionMobile-D517oXYZ.js +26 -0
  14. package/dist/build/chunks/Autocomplete-kRo8RNbC.js +135 -0
  15. package/dist/build/chunks/BackToTop-4M-Wl7z3.js +64 -0
  16. package/dist/build/chunks/ClosableAlert-CZ114JsL.js +55 -0
  17. package/dist/build/chunks/CookieConsent-wd8gQ2Oe.js +18 -0
  18. package/dist/build/chunks/Dialog-DoYcGqhW.js +48 -0
  19. package/dist/build/chunks/DropMenu-CSTZq0Zt.js +68 -0
  20. package/dist/build/chunks/FeedbackForm-BsL7fv8s.js +64 -0
  21. package/dist/build/chunks/Gallery-DqJPujX5.js +165 -0
  22. package/dist/build/chunks/GlobalToggle-7H3F1Wvc.js +82 -0
  23. package/dist/build/chunks/InPageNavigation-D7m3IN89.js +86 -0
  24. package/dist/build/chunks/Navigation-CRModT40.js +142 -0
  25. package/dist/build/chunks/Popover-CiTAftNU.js +30 -0
  26. package/dist/build/chunks/Sticky-C1H8MNqK.js +51 -0
  27. package/dist/build/chunks/Tabs-BJD3kABL.js +160 -0
  28. package/dist/build/chunks/Translate-yAgySwet.js +46 -0
  29. package/dist/build/chunks/cookie-compliance-CG6x-TcV.js +119 -0
  30. package/dist/build/chunks/enums-BrHxPZZ_.js +36 -0
  31. package/dist/build/chunks/polyfills-D-qh1a_2.js +33 -0
  32. package/dist/build/chunks/utilities-B9mNRs7V.js +255 -0
  33. package/dist/build/content-block.css +1 -1
  34. package/dist/build/cookie-consent.entry.js +1 -1
  35. package/dist/build/dialog.entry.js +1 -1
  36. package/dist/build/drop-menu.entry.js +1 -1
  37. package/dist/build/elements.js +147 -1
  38. package/dist/build/feedback-form.css +1 -0
  39. package/dist/build/feedback-form.entry.js +1 -0
  40. package/dist/build/filters.entry.js +145 -1
  41. package/dist/build/form.css +1 -1
  42. package/dist/build/gallery.entry.js +1 -1
  43. package/dist/build/global-alert.entry.js +1 -1
  44. package/dist/build/header.css +1 -1
  45. package/dist/build/header.entry.js +1 -1
  46. package/dist/build/icon.css +1 -1
  47. package/dist/build/in-page-navigation.entry.js +1 -1
  48. package/dist/build/navigation.css +1 -1
  49. package/dist/build/navigation.entry.js +1 -1
  50. package/dist/build/pagination.css +1 -1
  51. package/dist/build/popover.entry.js +1 -1
  52. package/dist/build/react.js +2291 -1
  53. package/dist/build/side-navigation.css +1 -1
  54. package/dist/build/sidebar.css +1 -1
  55. package/dist/build/sticky.entry.js +1 -1
  56. package/dist/build/tabs.entry.js +1 -1
  57. package/dist/build/translate.css +1 -0
  58. package/dist/build/translate.entry.js +1 -0
  59. package/dist/build/utility-list.entry.js +53 -1
  60. package/dist/types/Component/BackToTop/BackToTop.d.ts +20 -0
  61. package/dist/types/Component/BackToTop/BackToTop.d.ts.map +1 -0
  62. package/dist/types/Component/BackToTop/Elements/BackToTop.d.ts +27 -0
  63. package/dist/types/Component/BackToTop/Elements/BackToTop.d.ts.map +1 -0
  64. package/dist/types/Component/BackToTop/back-to-top.entry.d.ts +2 -0
  65. package/dist/types/Component/BackToTop/back-to-top.entry.d.ts.map +1 -0
  66. package/dist/types/Component/DropMenu/DropMenu.d.ts +2 -1
  67. package/dist/types/Component/DropMenu/DropMenu.d.ts.map +1 -1
  68. package/dist/types/Component/Navigation/Elements/Navigation.d.ts +2 -3
  69. package/dist/types/Component/Navigation/Elements/Navigation.d.ts.map +1 -1
  70. package/dist/types/Component/SideNavigation/Components/SideNavigationTree.d.ts +3 -3
  71. package/dist/types/Component/SideNavigation/Components/SideNavigationTree.d.ts.map +1 -1
  72. package/dist/types/Component/SideNavigation/SideNavigation.d.ts +3 -1
  73. package/dist/types/Component/SideNavigation/SideNavigation.d.ts.map +1 -1
  74. package/dist/types/Component/Tabs/Components/TabDropMenu.d.ts.map +1 -1
  75. package/dist/types/Component/Tabs/Elements/Tabs.d.ts.map +1 -1
  76. package/dist/types/Component/Translate/Elements/Translate.d.ts +23 -0
  77. package/dist/types/Component/Translate/Elements/Translate.d.ts.map +1 -0
  78. package/dist/types/Component/Translate/Translate.d.ts +37 -0
  79. package/dist/types/Component/Translate/Translate.d.ts.map +1 -0
  80. package/dist/types/Component/Translate/languages.d.ts +11 -0
  81. package/dist/types/Component/Translate/languages.d.ts.map +1 -0
  82. package/dist/types/Component/Translate/translate.entry.d.ts +2 -0
  83. package/dist/types/Component/Translate/translate.entry.d.ts.map +1 -0
  84. package/dist/types/Form/FeedbackForm/Elements/FeedbackForm.d.ts +37 -0
  85. package/dist/types/Form/FeedbackForm/Elements/FeedbackForm.d.ts.map +1 -0
  86. package/dist/types/Form/FeedbackForm/FeedbackForm.d.ts +36 -0
  87. package/dist/types/Form/FeedbackForm/FeedbackForm.d.ts.map +1 -0
  88. package/dist/types/Form/FeedbackForm/feedback-form.entry.d.ts +2 -0
  89. package/dist/types/Form/FeedbackForm/feedback-form.entry.d.ts.map +1 -0
  90. package/dist/types/Utility/Elements/google-translate-widget.d.ts +91 -0
  91. package/dist/types/Utility/Elements/google-translate-widget.d.ts.map +1 -0
  92. package/dist/types/Utility/utilities.d.ts +2 -0
  93. package/dist/types/Utility/utilities.d.ts.map +1 -1
  94. package/dist/types/elements.d.ts +3 -0
  95. package/dist/types/elements.d.ts.map +1 -1
  96. package/dist/types/enums.d.ts +3 -1
  97. package/dist/types/enums.d.ts.map +1 -1
  98. package/dist/types/react.d.ts +3 -0
  99. package/dist/types/react.d.ts.map +1 -1
  100. package/dist/types/tokens.d.ts +1 -0
  101. package/dist/types/tokens.d.ts.map +1 -1
  102. package/docs/API.md +1215 -0
  103. package/docs/CSSGuidelines.md +893 -0
  104. package/docs/CodeQuality.md +940 -0
  105. package/docs/ComponentArchitecture.md +714 -0
  106. package/docs/Contributing.md +626 -0
  107. package/docs/MemoryManagement.md +598 -0
  108. package/docs/Migrations.md +6 -0
  109. package/docs/README.md +100 -0
  110. package/docs/Security.md +444 -0
  111. package/docs/Testing.md +739 -0
  112. package/docs/Troubleshooting.md +674 -0
  113. package/package.json +9 -6
  114. package/src/Atom/Button/Button.tsx +1 -1
  115. package/src/Atom/Button/__snapshots__/Button.stories.tsx.snap +2 -2
  116. package/src/Atom/Button/_buttons.css +1 -0
  117. package/src/Atom/Icon/README.md +1 -1
  118. package/src/Atom/Icon/_icon.css +1 -0
  119. package/src/Atom/Icon/images/thumb.svg +1 -0
  120. package/src/Atom/Link/_links.css +1 -0
  121. package/src/Atom/Media/__snapshots__/Media.stories.ts.snap +4 -9
  122. package/src/Atom/Media/media.twig +4 -5
  123. package/src/Component/BackToTop/BackToTop.stories.ts +127 -0
  124. package/src/Component/BackToTop/BackToTop.stories.tsx +53 -0
  125. package/src/Component/BackToTop/BackToTop.tsx +120 -0
  126. package/src/Component/BackToTop/Elements/BackToTop.ts +119 -0
  127. package/src/Component/BackToTop/README.md +164 -0
  128. package/src/Component/BackToTop/__snapshots__/BackToTop.stories.ts.snap +24 -0
  129. package/src/Component/BackToTop/__snapshots__/BackToTop.stories.tsx.snap +3 -0
  130. package/src/Component/BackToTop/back-to-top.css +70 -0
  131. package/src/Component/BackToTop/back-to-top.entry.js +1 -0
  132. package/src/Component/BackToTop/back-to-top.twig +26 -0
  133. package/src/Component/Card/Components/CardContent.tsx +1 -1
  134. package/src/Component/Card/Components/CardMedia.tsx +1 -1
  135. package/src/Component/Card/__snapshots__/Card.stories.tsx.snap +3 -3
  136. package/src/Component/Card/card.css +1 -1
  137. package/src/Component/Carousel/Carousel.stories.ts +66 -36
  138. package/src/Component/Carousel/__snapshots__/Carousel.stories.tsx.snap +5 -5
  139. package/src/Component/ContentBlock/Components/ContentBlockMedia.tsx +1 -1
  140. package/src/Component/ContentBlock/content-block.css +1 -1
  141. package/src/Component/DropMenu/DropMenu.stories.ts +21 -2
  142. package/src/Component/DropMenu/DropMenu.tsx +14 -4
  143. package/src/Component/DropMenu/__snapshots__/DropMenu.stories.ts.snap +3 -3
  144. package/src/Component/DropMenu/__snapshots__/DropMenu.stories.tsx.snap +2 -2
  145. package/src/Component/DropMenu/drop-menu.twig +7 -1
  146. package/src/Component/HeroBanner/__snapshots__/HeroBanner.stories.tsx.snap +1 -1
  147. package/src/Component/InPageNavigation/__snapshots__/InPageNavigation.stories.ts.snap +48 -13
  148. package/src/Component/InPageNavigation/in-page-navigation.twig +4 -6
  149. package/src/Component/ListItem/Components/ListItemMedia.tsx +1 -1
  150. package/src/Component/Navigation/Elements/Navigation.ts +25 -29
  151. package/src/Component/Navigation/README.md +11 -10
  152. package/src/Component/Navigation/__snapshots__/Navigation.stories.ts.snap +8 -8
  153. package/src/Component/Navigation/_navigation-dropdown.css +9 -11
  154. package/src/Component/Navigation/_navigation-mega.css +5 -11
  155. package/src/Component/Navigation/_navigation.css +5 -3
  156. package/src/Component/Navigation/menu.twig +1 -1
  157. package/src/Component/Navigation/navigation.twig +0 -1
  158. package/src/Component/Pagination/Pagination.stories.ts +57 -27
  159. package/src/Component/Pagination/pagination.css +16 -7
  160. package/src/Component/Popover/__snapshots__/Popover.stories.tsx.snap +3 -3
  161. package/src/Component/SideNavigation/Components/SideNavigationTree.tsx +68 -24
  162. package/src/Component/SideNavigation/README.md +78 -32
  163. package/src/Component/SideNavigation/SideNavigation.stories.ts +41 -2
  164. package/src/Component/SideNavigation/SideNavigation.stories.tsx +31 -0
  165. package/src/Component/SideNavigation/SideNavigation.tsx +13 -3
  166. package/src/Component/SideNavigation/__snapshots__/SideNavigation.stories.ts.snap +87 -3
  167. package/src/Component/SideNavigation/__snapshots__/SideNavigation.stories.tsx.snap +2 -0
  168. package/src/Component/SideNavigation/side-navigation.css +3 -3
  169. package/src/Component/SideNavigation/side-navigation.twig +10 -3
  170. package/src/Component/Tabs/Components/TabDropMenu.tsx +7 -1
  171. package/src/Component/Tabs/Elements/Tabs.ts +13 -3
  172. package/src/Component/Tabs/Tabs.stories.ts +33 -12
  173. package/src/Component/Tabs/Tabs.stories.tsx +28 -14
  174. package/src/Component/Tabs/__snapshots__/Tabs.stories.ts.snap +3 -3
  175. package/src/Component/Tabs/__snapshots__/Tabs.stories.tsx.snap +2 -2
  176. package/src/Component/Translate/Elements/Translate.ts +76 -0
  177. package/src/Component/Translate/README.md +285 -0
  178. package/src/Component/Translate/Translate.stories.ts +87 -0
  179. package/src/Component/Translate/Translate.stories.tsx +77 -0
  180. package/src/Component/Translate/Translate.tsx +213 -0
  181. package/src/Component/Translate/__snapshots__/Translate.stories.ts.snap +18 -0
  182. package/src/Component/Translate/__snapshots__/Translate.stories.tsx.snap +3 -0
  183. package/src/Component/Translate/languages.ts +39 -0
  184. package/src/Component/Translate/translate.css +62 -0
  185. package/src/Component/Translate/translate.entry.js +1 -0
  186. package/src/Component/Translate/translate.twig +44 -0
  187. package/src/Form/Autocomplete/Autocomplete.stories.tsx +2 -1
  188. package/src/Form/FeedbackForm/Elements/FeedbackForm.ts +122 -0
  189. package/src/Form/FeedbackForm/FeedbackForm.stories.ts +99 -0
  190. package/src/Form/FeedbackForm/FeedbackForm.stories.tsx +73 -0
  191. package/src/Form/FeedbackForm/FeedbackForm.tsx +196 -0
  192. package/src/Form/FeedbackForm/README.md +233 -0
  193. package/src/Form/FeedbackForm/__snapshots__/FeedbackForm.stories.ts.snap +125 -0
  194. package/src/Form/FeedbackForm/__snapshots__/FeedbackForm.stories.tsx.snap +5 -0
  195. package/src/Form/FeedbackForm/feedback-form.css +74 -0
  196. package/src/Form/FeedbackForm/feedback-form.entry.js +1 -0
  197. package/src/Form/FeedbackForm/feedback-form.twig +80 -0
  198. package/src/Form/form.css +17 -19
  199. package/src/Introduction.mdx +1 -1
  200. package/src/Layout/Footer/__snapshots__/Footer.stories.ts.snap +3 -3
  201. package/src/Layout/Header/Components/GlobalToggle.tsx +1 -1
  202. package/src/Layout/Header/Header.stories.ts +53 -48
  203. package/src/Layout/Header/Header.stories.tsx +35 -22
  204. package/src/Layout/Header/Header.tsx +2 -2
  205. package/src/Layout/Header/__snapshots__/Header.stories.ts.snap +18 -14
  206. package/src/Layout/Header/__snapshots__/Header.stories.tsx.snap +2 -2
  207. package/src/Layout/Header/_toggles.css +7 -7
  208. package/src/Layout/Page/__snapshots__/Page.stories.tsx.snap +1 -1
  209. package/src/Layout/Sidebar/sidebar.css +10 -3
  210. package/src/Utility/Elements/google-translate-widget.ts +293 -0
  211. package/src/Utility/global.d.ts +4 -0
  212. package/src/Utility/utilities.ts +2 -0
  213. package/src/_custom-media.css +2 -0
  214. package/src/elements.ts +3 -0
  215. package/src/enums.ts +2 -0
  216. package/src/react.ts +3 -0
  217. package/src/tokens.js +1 -0
  218. package/dist/build/chunks/Accordion-GN0sME4W.js +0 -1
  219. package/dist/build/chunks/AccordionGroup-Bzqp5__q.js +0 -1
  220. package/dist/build/chunks/AccordionMobile-DG5jSe8Q.js +0 -1
  221. package/dist/build/chunks/Autocomplete-B4RtkAyh.js +0 -1
  222. package/dist/build/chunks/ClosableAlert-DEhj8Nxm.js +0 -1
  223. package/dist/build/chunks/CookieConsent-BkCMRVST.js +0 -1
  224. package/dist/build/chunks/Dialog-Haahn-Yn.js +0 -1
  225. package/dist/build/chunks/DropMenu-1baQc8Yc.js +0 -1
  226. package/dist/build/chunks/Gallery-D8NGXy2Q.js +0 -1
  227. package/dist/build/chunks/GlobalToggle-B52fdBQu.js +0 -1
  228. package/dist/build/chunks/InPageNavigation-Dyn2TR-N.js +0 -1
  229. package/dist/build/chunks/Navigation-hOrfLq7h.js +0 -1
  230. package/dist/build/chunks/Popover-Cxg-s5Jn.js +0 -1
  231. package/dist/build/chunks/Sticky-BGCuuEJK.js +0 -1
  232. package/dist/build/chunks/Tabs-DYy1YTdU.js +0 -15
  233. package/dist/build/chunks/cookie-compliance-Bbm-0vpj.js +0 -1
  234. package/dist/build/chunks/enums-DLV_1NAf.js +0 -1
  235. package/dist/build/chunks/polyfills-C7pRt54M.js +0 -1
  236. package/dist/build/chunks/utilities-_Bq3TxAQ.js +0 -1
@@ -0,0 +1,444 @@
1
+ # Security Guidelines
2
+
3
+ Security best practices for the Mixtape Design System.
4
+
5
+ ## Table of Contents
6
+
7
+ - [XSS Prevention](#xss-prevention)
8
+ - [Input Validation](#input-validation)
9
+ - [URL Safety](#url-safety)
10
+ - [Data Sanitization](#data-sanitization)
11
+ - [Secure Dependencies](#secure-dependencies)
12
+ - [Information Disclosure](#information-disclosure)
13
+
14
+ ---
15
+
16
+ ## XSS Prevention
17
+
18
+ ### Never Use dangerouslySetInnerHTML
19
+
20
+ ```tsx
21
+ // ❌ BAD - XSS vulnerability
22
+ <div dangerouslySetInnerHTML={{ __html: userContent }} />
23
+
24
+ // User provides: <img src=x onerror='alert(document.cookie)'>
25
+ // Result: JavaScript executes!
26
+
27
+ // ✅ GOOD - Safe rendering
28
+ <div>{userContent}</div>
29
+
30
+ // React automatically escapes content
31
+ // Result: Displays as text, doesn't execute
32
+ ```
33
+
34
+ ### Never Use innerHTML
35
+
36
+ ```typescript
37
+ // ❌ BAD - XSS vulnerability
38
+ element.innerHTML = htmlString
39
+
40
+ // ✅ GOOD - Use DOMParser
41
+ const parser = new DOMParser()
42
+ const doc = parser.parseFromString(htmlString, "text/html")
43
+ const safeElement = doc.body.firstElementChild
44
+
45
+ // Or use the createElement utility
46
+ import { createElement } from "../Utility/utilities"
47
+ const safeElement = createElement(htmlString)
48
+ ```
49
+
50
+ ### The createElement Utility
51
+
52
+ ```typescript
53
+ // Safe HTML parsing without script execution
54
+ export const createElement = (string: string): Element | null => {
55
+ try {
56
+ const parser = new DOMParser()
57
+ const doc = parser.parseFromString(string, "text/html")
58
+ return doc.body.firstElementChild
59
+ } catch (error) {
60
+ if (process.env.NODE_ENV !== "production") console.error(error)
61
+ return null
62
+ }
63
+ }
64
+
65
+ // Usage
66
+ const element = createElement('<div class="safe">Content</div>')
67
+ // Scripts in the string won't execute
68
+ ```
69
+
70
+ ---
71
+
72
+ ## Input Validation
73
+
74
+ ### Use the validators Utility
75
+
76
+ Always validate user input before using it:
77
+
78
+ ```typescript
79
+ import { validators } from "../Utility/utilities"
80
+
81
+ // ✅ GOOD - Validate everything
82
+ function handlePageChange(pageParam: string) {
83
+ // Validate page is an integer within bounds
84
+ if (!validators.integer(pageParam, 1, lastPage)) {
85
+ console.warn("Invalid page parameter")
86
+ return 1 // Safe fallback
87
+ }
88
+
89
+ return parseInt(pageParam, 10)
90
+ }
91
+ ```
92
+
93
+ ### Validate Numbers
94
+
95
+ ```typescript
96
+ import { validators } from "../Utility/utilities"
97
+
98
+ // ❌ BAD - No validation
99
+ const page = parseInt(userInput) // Could be NaN, Infinity, etc.
100
+
101
+ // ✅ GOOD - Validate first
102
+ if (!validators.integer(userInput, 1, 100)) {
103
+ throw new Error("Page must be between 1 and 100")
104
+ }
105
+ const page = parseInt(userInput, 10)
106
+ ```
107
+
108
+ ### Validate JSON
109
+
110
+ ```typescript
111
+ import { validators } from "../Utility/utilities"
112
+
113
+ // ❌ BAD - Uncaught parse error
114
+ const data = JSON.parse(localStorage.getItem("data"))
115
+
116
+ // ✅ GOOD - Validate before parsing
117
+ const stored = localStorage.getItem("data")
118
+ if (!validators.json(stored)) {
119
+ return defaultValue // Safe fallback
120
+ }
121
+
122
+ try {
123
+ const data = JSON.parse(stored)
124
+ return data
125
+ } catch {
126
+ return defaultValue
127
+ }
128
+ ```
129
+
130
+ ---
131
+
132
+ ## URL Safety
133
+
134
+ ### Validate All URLs
135
+
136
+ ```typescript
137
+ import { validators } from "../Utility/utilities"
138
+
139
+ // ❌ BAD - Accepts any URL including javascript:
140
+ window.open(userProvidedUrl)
141
+
142
+ // ✅ GOOD - Validate protocol
143
+ if (!validators.url(userProvidedUrl)) {
144
+ console.error("Invalid URL")
145
+ userProvidedUrl = window.location.href // Safe fallback
146
+ }
147
+ window.open(userProvidedUrl)
148
+ ```
149
+
150
+ ### The validators.url Function
151
+
152
+ ```typescript
153
+ // Only allows http: and https: by default
154
+ validators.url("https://example.com") // true
155
+ validators.url("http://example.com") // true
156
+ validators.url("javascript:alert(1)") // false
157
+ validators.url("data:text/html,...") // false
158
+ validators.url("file:///etc/passwd") // false
159
+
160
+ // Custom protocols if needed
161
+ validators.url("ftp://example.com", ["ftp:", "ftps:"]) // true
162
+ ```
163
+
164
+ ### External Links
165
+
166
+ Always add `rel="noopener noreferrer"` to external links with `target="_blank"`:
167
+
168
+ ```tsx
169
+ // ❌ BAD - Vulnerable to tabnapping
170
+ <a href="https://external.com" target="_blank">
171
+ Link
172
+ </a>
173
+
174
+ // ✅ GOOD - Secure
175
+ <a href="https://external.com" target="_blank" rel="noopener noreferrer">
176
+ Link
177
+ </a>
178
+ ```
179
+
180
+ **Why?** Without `noopener`, the opened page can access `window.opener` and redirect your page to a phishing site.
181
+
182
+ ---
183
+
184
+ ## Data Sanitization
185
+
186
+ ### localStorage Security
187
+
188
+ ```typescript
189
+ // ⚠️ WARNING: localStorage is NOT secure
190
+ // - Data is stored UNENCRYPTED
191
+ // - Accessible to all scripts on same origin
192
+ // - Persists across sessions
193
+
194
+ // ❌ BAD - Sensitive data
195
+ localStorage.setItem("authToken", token)
196
+ localStorage.setItem("password", password)
197
+ localStorage.setItem("creditCard", cc)
198
+
199
+ // ✅ GOOD - Non-sensitive data only
200
+ localStorage.setItem("theme", "dark")
201
+ localStorage.setItem("language", "en")
202
+ localStorage.setItem("preferences", JSON.stringify(prefs))
203
+
204
+ // For sensitive data, use:
205
+ // - httpOnly cookies (server-side only)
206
+ // - sessionStorage (cleared on close)
207
+ // - Memory-only (JavaScript variables)
208
+ ```
209
+
210
+ ### Cookie Security
211
+
212
+ ```typescript
213
+ import Cookies from "js-cookie"
214
+
215
+ // ✅ GOOD - Secure cookie settings
216
+ Cookies.set("session", value, {
217
+ path: "/",
218
+ expires: 7,
219
+ sameSite: "Lax", // CSRF protection
220
+ secure: true, // HTTPS only (production)
221
+ httpOnly: false, // Client-side access needed
222
+ })
223
+
224
+ // For authentication tokens:
225
+ // - Use httpOnly: true (JavaScript can't access)
226
+ // - Set by server, not client-side
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Secure Dependencies
232
+
233
+ ### Regular Audits
234
+
235
+ ```bash
236
+ # Run security audit
237
+ pnpm audit
238
+
239
+ # Fix vulnerabilities
240
+ pnpm audit --fix
241
+
242
+ # Check for outdated packages
243
+ pnpm outdated
244
+ ```
245
+
246
+ ### Monitor CVEs
247
+
248
+ The design system uses:
249
+
250
+ - **Oxlint** instead of ESLint (faster, safer)
251
+ - **DOMParser** instead of innerHTML (safer)
252
+ - **Validators utility** instead of heavy validation libs (smaller attack surface)
253
+ - **AbortController** for cleanup (browser standard, no deps)
254
+
255
+ ### Keep Dependencies Updated
256
+
257
+ ```bash
258
+ # Update dependencies
259
+ pnpm update
260
+
261
+ # Update to latest versions
262
+ pnpm update --latest
263
+
264
+ # Check for security advisories
265
+ pnpm audit
266
+ ```
267
+
268
+ ---
269
+
270
+ ## Information Disclosure
271
+
272
+ ### Environment-Specific Logging
273
+
274
+ ```typescript
275
+ // ❌ BAD - Logs sensitive info in production
276
+ console.error("Failed to authenticate:", email, password)
277
+ console.log("Database query:", query)
278
+ console.warn("API key:", apiKey)
279
+
280
+ // ✅ GOOD - Only log in development
281
+ if (process.env.NODE_ENV !== "production") {
282
+ console.error("Failed to authenticate:", email)
283
+ // Don't log password ever!
284
+ }
285
+
286
+ // For user-facing errors (OK in production)
287
+ console.error("Could not copy URL to clipboard") // Generic message
288
+ console.error("Invalid email address") // No sensitive data
289
+ ```
290
+
291
+ ### Error Messages
292
+
293
+ ```typescript
294
+ // ❌ BAD - Reveals internal structure
295
+ throw new Error(`User ${userId} not found in database table users_auth`)
296
+
297
+ // ✅ GOOD - Generic public message
298
+ throw new Error("User not found")
299
+
300
+ // Log details only in development
301
+ if (process.env.NODE_ENV !== "production") {
302
+ console.error("Database error:", details)
303
+ }
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Security Checklist
309
+
310
+ Before shipping, verify:
311
+
312
+ - [ ] No `dangerouslySetInnerHTML` usage
313
+ - [ ] No `innerHTML` usage
314
+ - [ ] All URLs validated with `validators.url()`
315
+ - [ ] All numbers validated with `validators.integer()` or `validators.number()`
316
+ - [ ] All JSON validated with `validators.json()` before parsing
317
+ - [ ] External links have `rel="noopener noreferrer"`
318
+ - [ ] No sensitive data in localStorage
319
+ - [ ] Environment-specific logging (NODE_ENV checks)
320
+ - [ ] Generic error messages (no internal details)
321
+ - [ ] Dependencies audited (`pnpm audit`)
322
+ - [ ] No hardcoded credentials
323
+ - [ ] HTTPS used in production
324
+ - [ ] CSRF protection (SameSite cookies)
325
+ - [ ] Input sanitization on all user data
326
+ - [ ] XSS testing done (try `<script>alert(1)</script>`)
327
+
328
+ ---
329
+
330
+ ## Testing for Vulnerabilities
331
+
332
+ ### XSS Testing
333
+
334
+ ```javascript
335
+ // Test 1: Try to inject script in all inputs
336
+ const xssPayloads = [
337
+ "<script>alert(1)</script>",
338
+ "<img src=x onerror=alert(1)>",
339
+ "javascript:alert(1)",
340
+ "<svg onload=alert(1)>",
341
+ '"><script>alert(1)</script>',
342
+ ]
343
+
344
+ xssPayloads.forEach(payload => {
345
+ // Try in every input field
346
+ // Expected: Should be escaped/rejected
347
+ })
348
+ ```
349
+
350
+ ### URL Injection Testing
351
+
352
+ ```javascript
353
+ // Test 2: Try malicious URLs
354
+ const maliciousUrls = [
355
+ "javascript:alert(document.cookie)",
356
+ "data:text/html,<script>alert(1)</script>",
357
+ "file:///etc/passwd",
358
+ "vbscript:msgbox(1)",
359
+ ]
360
+
361
+ maliciousUrls.forEach(url => {
362
+ validators.url(url) // Should return false
363
+ })
364
+ ```
365
+
366
+ ### Input Validation Testing
367
+
368
+ ```javascript
369
+ // Test 3: Try to break validation
370
+ validators.integer("999999999999999", 1, 10) // Should reject
371
+ validators.integer("-1", 1, 10) // Should reject
372
+ validators.integer("5.5", 1, 10) // Should reject (not integer)
373
+ validators.integer("abc", 1, 10) // Should reject
374
+ ```
375
+
376
+ ---
377
+
378
+ ## OWASP Top 10 Coverage
379
+
380
+ ### A03:2021 – Injection
381
+
382
+ - ✅ No innerHTML usage (XSS prevention)
383
+ - ✅ No dangerouslySetInnerHTML (XSS prevention)
384
+ - ✅ DOMParser for safe HTML parsing
385
+ - ✅ Input validation with validators utility
386
+
387
+ ### A04:2021 – Insecure Design
388
+
389
+ - ✅ URL protocol validation
390
+ - ✅ Bounds checking on all numbers
391
+ - ✅ Secure-by-default patterns
392
+
393
+ ### A05:2021 – Security Misconfiguration
394
+
395
+ - ✅ Environment-specific logging
396
+ - ✅ Generic error messages
397
+ - ✅ Secure cookie defaults (SameSite, Secure)
398
+
399
+ ### A06:2021 – Vulnerable Components
400
+
401
+ - ✅ Regular `pnpm audit` runs
402
+ - ✅ Dependencies kept updated
403
+ - ✅ Minimal dependencies (smaller attack surface)
404
+
405
+ ### A07:2021 – Identification and Authentication
406
+
407
+ - ✅ No credentials in localStorage
408
+ - ✅ Secure cookie practices
409
+ - ✅ httpOnly recommended for auth tokens
410
+
411
+ ### A08:2021 – Software and Data Integrity
412
+
413
+ - ✅ JSON validation before parsing
414
+ - ✅ Try-catch around all parsing
415
+ - ✅ Graceful fallbacks on bad data
416
+
417
+ ### A09:2021 – Logging Failures
418
+
419
+ - ✅ Environment-specific logging
420
+ - ✅ No sensitive data in logs
421
+ - ✅ User-facing errors are generic
422
+
423
+ ### A10:2021 – Server-Side Request Forgery
424
+
425
+ - ✅ URL validation before requests
426
+ - ✅ Protocol whitelisting
427
+ - ✅ Same-origin checks where applicable
428
+
429
+ ---
430
+
431
+ ## Resources
432
+
433
+ - [OWASP Top 10](https://owasp.org/Top10/)
434
+ - [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
435
+ - [MDN Security](https://developer.mozilla.org/en-US/docs/Web/Security)
436
+ - [Web.dev Security](https://web.dev/secure/)
437
+
438
+ ---
439
+
440
+ ## Related Documentation
441
+
442
+ - [Code Quality Guidelines](./CodeQuality.md)
443
+ - [Input Validation (API.md)](./API.md#validators)
444
+ - [Memory Management](./MemoryManagement.md)