@maccesar/titools 2.0.7 → 2.2.0

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 (132) hide show
  1. package/{AGENTS-TEMPLATE.md → AGENTS-VERCEL-RESEARCH.md} +16 -18
  2. package/README.md +250 -168
  3. package/agents/{ti-researcher.md → ti-pro.md} +10 -10
  4. package/bin/titools.js +16 -12
  5. package/lib/cleanup.js +95 -0
  6. package/lib/commands/agents.js +146 -70
  7. package/lib/commands/skills.js +349 -0
  8. package/lib/commands/uninstall.js +189 -154
  9. package/lib/commands/update.js +104 -21
  10. package/lib/config.js +26 -20
  11. package/lib/downloader.js +1 -1
  12. package/lib/installer.js +37 -97
  13. package/lib/platform.js +9 -5
  14. package/lib/prompts/checkboxCancel.js +264 -0
  15. package/lib/prompts/selectCancel.js +204 -0
  16. package/lib/symlink.js +19 -7
  17. package/lib/utils.js +17 -17
  18. package/package.json +10 -10
  19. package/skills/alloy-guides/SKILL.md +8 -30
  20. package/skills/alloy-guides/references/CLI_TASKS.md +14 -24
  21. package/skills/alloy-guides/references/CONCEPTS.md +5 -25
  22. package/skills/alloy-guides/references/CONTROLLERS.md +2 -19
  23. package/skills/alloy-guides/references/MODELS.md +40 -10
  24. package/skills/alloy-guides/references/PURGETSS.md +1 -11
  25. package/skills/alloy-guides/references/VIEWS_DYNAMIC.md +8 -14
  26. package/skills/alloy-guides/references/VIEWS_STYLES.md +14 -25
  27. package/skills/alloy-guides/references/VIEWS_WITHOUT_CONTROLLERS.md +2 -8
  28. package/skills/alloy-guides/references/VIEWS_XML.md +29 -40
  29. package/skills/alloy-guides/references/WIDGETS.md +1 -17
  30. package/skills/alloy-howtos/SKILL.md +1 -22
  31. package/skills/alloy-howtos/references/best_practices.md +0 -17
  32. package/skills/alloy-howtos/references/cli_reference.md +1 -23
  33. package/skills/alloy-howtos/references/config_files.md +86 -15
  34. package/skills/alloy-howtos/references/custom_tags.md +14 -13
  35. package/skills/alloy-howtos/references/debugging_troubleshooting.md +3 -22
  36. package/skills/alloy-howtos/references/samples.md +4 -14
  37. package/skills/purgetss/SKILL.md +11 -37
  38. package/skills/purgetss/references/EXAMPLES.md +106 -17
  39. package/skills/purgetss/references/animation-system.md +0 -67
  40. package/skills/purgetss/references/apply-directive.md +0 -18
  41. package/skills/purgetss/references/arbitrary-values.md +0 -25
  42. package/skills/purgetss/references/class-index.md +0 -46
  43. package/skills/purgetss/references/cli-commands.md +0 -41
  44. package/skills/purgetss/references/configurable-properties.md +0 -55
  45. package/skills/purgetss/references/custom-rules.md +0 -14
  46. package/skills/purgetss/references/customization-deep-dive.md +0 -49
  47. package/skills/purgetss/references/dynamic-component-creation.md +56 -37
  48. package/skills/purgetss/references/grid-layout.md +0 -32
  49. package/skills/purgetss/references/icon-fonts.md +0 -50
  50. package/skills/purgetss/references/installation-setup.md +61 -32
  51. package/skills/purgetss/references/migration-guide.md +127 -0
  52. package/skills/purgetss/references/opacity-modifier.md +0 -34
  53. package/skills/purgetss/references/performance-tips.md +261 -0
  54. package/skills/purgetss/references/platform-modifiers.md +0 -46
  55. package/skills/purgetss/references/smart-mappings.md +0 -12
  56. package/skills/purgetss/references/tikit-components.md +393 -0
  57. package/skills/purgetss/references/titanium-resets.md +1 -27
  58. package/skills/purgetss/references/ui-ux-design.md +467 -117
  59. package/skills/{alloy-expert → ti-expert}/SKILL.md +45 -54
  60. package/skills/ti-expert/references/alloy-builtins.md +387 -0
  61. package/skills/{alloy-expert → ti-expert}/references/alloy-structure.md +147 -40
  62. package/skills/ti-expert/references/anti-patterns.md +90 -0
  63. package/skills/ti-expert/references/cli-expert.md +109 -0
  64. package/skills/{alloy-expert → ti-expert}/references/code-conventions.md +182 -49
  65. package/skills/{alloy-expert → ti-expert}/references/controller-patterns.md +103 -93
  66. package/skills/{alloy-expert → ti-expert}/references/error-handling.md +12 -12
  67. package/skills/{alloy-expert → ti-expert}/references/examples.md +144 -85
  68. package/skills/{alloy-expert → ti-expert}/references/migration-patterns.md +38 -36
  69. package/skills/{alloy-expert → ti-expert}/references/patterns.md +8 -8
  70. package/skills/ti-expert/references/performance-listview.md +251 -0
  71. package/skills/{alloy-expert/references/performance-patterns.md → ti-expert/references/performance-optimization.md} +67 -283
  72. package/skills/{alloy-expert/references/security-patterns.md → ti-expert/references/security-device.md} +12 -295
  73. package/skills/ti-expert/references/security-fundamentals.md +284 -0
  74. package/skills/{alloy-expert → ti-expert}/references/state-management.md +10 -10
  75. package/skills/ti-expert/references/testing-e2e-ci.md +432 -0
  76. package/skills/ti-expert/references/testing-unit.md +433 -0
  77. package/skills/ti-expert/references/theming.md +394 -0
  78. package/skills/ti-guides/SKILL.md +1 -14
  79. package/skills/ti-guides/references/advanced-data-and-images.md +126 -10
  80. package/skills/ti-guides/references/app-distribution.md +48 -10
  81. package/skills/ti-guides/references/application-frameworks.md +9 -2
  82. package/skills/ti-guides/references/cli-reference.md +338 -82
  83. package/skills/ti-guides/references/coding-best-practices.md +14 -4
  84. package/skills/ti-guides/references/commonjs-advanced.md +103 -6
  85. package/skills/ti-guides/references/hello-world.md +5 -2
  86. package/skills/ti-guides/references/hyperloop-native-access.md +439 -46
  87. package/skills/ti-guides/references/javascript-primer.md +4 -3
  88. package/skills/ti-guides/references/resources.md +0 -1
  89. package/skills/ti-guides/references/style-and-conventions.md +57 -9
  90. package/skills/ti-guides/references/tiapp-config.md +48 -6
  91. package/skills/ti-howtos/SKILL.md +2 -27
  92. package/skills/ti-howtos/references/android-platform-deep-dives.md +41 -90
  93. package/skills/ti-howtos/references/automation-fastlane-appium.md +15 -14
  94. package/skills/ti-howtos/references/buffer-codec-streams.md +22 -22
  95. package/skills/ti-howtos/references/cross-platform-development.md +68 -37
  96. package/skills/ti-howtos/references/debugging-profiling.md +8 -53
  97. package/skills/ti-howtos/references/extending-titanium.md +12 -51
  98. package/skills/ti-howtos/references/google-maps-v2.md +30 -29
  99. package/skills/ti-howtos/references/ios-map-kit.md +19 -25
  100. package/skills/ti-howtos/references/ios-platform-deep-dives.md +95 -283
  101. package/skills/ti-howtos/references/local-data-sources.md +45 -37
  102. package/skills/ti-howtos/references/location-and-maps.md +47 -28
  103. package/skills/ti-howtos/references/media-apis.md +84 -27
  104. package/skills/ti-howtos/references/notification-services.md +40 -89
  105. package/skills/ti-howtos/references/remote-data-sources.md +21 -36
  106. package/skills/ti-howtos/references/tutorials.md +79 -39
  107. package/skills/ti-howtos/references/using-modules.md +4 -30
  108. package/skills/ti-howtos/references/web-content-integration.md +28 -45
  109. package/skills/ti-howtos/references/webpack-build-pipeline.md +54 -18
  110. package/skills/ti-ui/SKILL.md +1 -21
  111. package/skills/ti-ui/references/accessibility-deep-dive.md +71 -25
  112. package/skills/ti-ui/references/animation-and-matrices.md +0 -47
  113. package/skills/ti-ui/references/application-structures.md +0 -46
  114. package/skills/ti-ui/references/custom-fonts-styling.md +9 -57
  115. package/skills/ti-ui/references/event-handling.md +32 -40
  116. package/skills/ti-ui/references/gestures.md +0 -40
  117. package/skills/ti-ui/references/icons-and-splash-screens.md +21 -44
  118. package/skills/ti-ui/references/layouts-and-positioning.md +47 -39
  119. package/skills/ti-ui/references/listviews-and-performance.md +187 -73
  120. package/skills/ti-ui/references/orientation.md +57 -71
  121. package/skills/ti-ui/references/platform-ui-android.md +114 -48
  122. package/skills/ti-ui/references/platform-ui-ios.md +63 -38
  123. package/skills/ti-ui/references/scrolling-views.md +14 -23
  124. package/skills/ti-ui/references/tableviews.md +6 -56
  125. package/lib/commands/install.js +0 -188
  126. package/skills/alloy-expert/references/anti-patterns.md +0 -133
  127. package/skills/alloy-expert/references/testing.md +0 -872
  128. package/skills/ti-guides/references/alloy-cli-advanced.md +0 -84
  129. package/skills/ti-guides/references/alloy-data-mastery.md +0 -29
  130. package/skills/ti-guides/references/alloy-widgets-and-themes.md +0 -19
  131. /package/skills/{alloy-expert → ti-expert}/assets/ControllerAutoCleanup.js +0 -0
  132. /package/skills/{alloy-expert → ti-expert}/references/contracts.md +0 -0
@@ -1,287 +1,4 @@
1
- # Security Patterns for Titanium Mobile Apps
2
-
3
- ## Token Storage Strategy
4
-
5
- **NEVER store tokens in:** `Ti.App.Properties` (plaintext), localStorage, or files.
6
-
7
- **USE platform-specific secure storage:**
8
-
9
- ```javascript
10
- // lib/services/tokenStorage.js
11
- exports.TokenStorage = {
12
- save(token) {
13
- if (Ti.Platform.osname === 'android') {
14
- // Use Android KeyStore
15
- const keyStore = Ti.Android.createKeyStore({
16
- name: 'SecureKeyStore'
17
- })
18
- keyStore.addEntry('authToken', token)
19
- } else {
20
- // Use iOS Keychain
21
- Ti.KeychainItem.setItem({
22
- identifier: 'authToken',
23
- value: token,
24
- accessGroup: 'com.yourapp.keychain'
25
- })
26
- }
27
- },
28
-
29
- get() {
30
- if (Ti.Platform.osname === 'android') {
31
- const keyStore = Ti.Android.createKeyStore({
32
- name: 'SecureKeyStore'
33
- })
34
- return keyStore.getEntry('authToken')
35
- } else {
36
- return Ti.KeychainItem.getItem({
37
- identifier: 'authToken',
38
- accessGroup: 'com.yourapp.keychain'
39
- })
40
- }
41
- },
42
-
43
- clear() {
44
- if (Ti.Platform.osname === 'android') {
45
- const keyStore = Ti.Android.createKeyStore({
46
- name: 'SecureKeyStore'
47
- })
48
- keyStore.removeEntry('authToken')
49
- } else {
50
- Ti.KeychainItem.removeItem({
51
- identifier: 'authToken',
52
- accessGroup: 'com.yourapp.keychain'
53
- })
54
- }
55
- }
56
- }
57
- ```
58
-
59
- ## Certificate Pinning
60
-
61
- Prevent man-in-the-middle attacks by pinning SSL certificates:
62
-
63
- ```javascript
64
- // lib/api/pinnedClient.js
65
- exports.createPinnedClient = function() {
66
- const client = Ti.Network.createHTTPClient({
67
- // Security: Enable certificate pinning
68
- certificatePinning: true,
69
-
70
- // Specify allowed certificates
71
- validatesSecureCertificate: true,
72
-
73
- onload: () => {
74
- // Success
75
- },
76
-
77
- onerror: (e) => {
78
- // Certificate validation failed
79
- if (e.error.indexOf('certificate') >= 0) {
80
- Ti.API.error('Certificate pinning failed - possible MITM attack')
81
- }
82
- }
83
- })
84
-
85
- return client
86
- }
87
- ```
88
-
89
- **Add certificates to tiapp.xml:**
90
-
91
- ```xml
92
- <ti:app>
93
- <certificates>
94
- <certificate>
95
- <name>api.example.com</name>
96
- <type>rsa</type>
97
- <file>certificates/api-pin.pem</file>
98
- </certificate>
99
- </certificates>
100
- </ti:app>
101
- ```
102
-
103
- ## Data Encryption at Rest
104
-
105
- ```javascript
106
- // lib/services/encryption.js
107
- // AES-256 encryption for sensitive local data
108
-
109
- const crypto = require('ti.crypto')
110
-
111
- exports.encrypt = function(data, key) {
112
- return crypto.encrypt({
113
- data: data,
114
- key: key,
115
- algorithm: crypto.AES_256_CBC,
116
- options: { mode: crypto.CBC }
117
- })
118
- }
119
-
120
- exports.decrypt = function(encryptedData, key) {
121
- return crypto.decrypt({
122
- data: encryptedData,
123
- key: key,
124
- algorithm: crypto.AES_256_CBC,
125
- options: { mode: crypto.CBC }
126
- })
127
- }
128
-
129
- // Usage: Secure cache of sensitive user data
130
- module.exports = class SecureCache {
131
- constructor(encryptionKey) {
132
- this.key = encryptionKey
133
- this.cache = {}
134
- }
135
-
136
- set(key, value) {
137
- const encrypted = encrypt(JSON.stringify(value), this.key)
138
- this.cache[key] = encrypted
139
- }
140
-
141
- get(key) {
142
- if (!this.cache[key]) return null
143
-
144
- const decrypted = decrypt(this.cache[key], this.key)
145
- return JSON.parse(decrypted)
146
- }
147
-
148
- clear() {
149
- this.cache = {}
150
- }
151
- }
152
- ```
153
-
154
- ## Secure HTTP Communication
155
-
156
- ```javascript
157
- // lib/api/secureClient.js
158
- exports.createSecureClient = function(baseUrl) {
159
- return {
160
- request(method, endpoint, data = null) {
161
- return new Promise((resolve, reject) => {
162
- const client = Ti.Network.createHTTPClient({
163
- timeout: 10000,
164
-
165
- onload: function() {
166
- if (this.status === 200) {
167
- try {
168
- resolve(JSON.parse(this.responseText))
169
- } catch (e) {
170
- reject(new Error('Invalid JSON response'))
171
- }
172
- } else {
173
- reject(new Error(`HTTP ${this.status}`))
174
- }
175
- },
176
-
177
- onerror: function(e) {
178
- // Log security events
179
- if (this.status === 401 || this.status === 403) {
180
- Ti.API.warn(`[SECURITY] Unauthorized: ${endpoint}`)
181
- }
182
- reject(e)
183
- }
184
- })
185
-
186
- client.open(method, `${baseUrl}${endpoint}`)
187
-
188
- // Security headers
189
- client.setRequestHeader('User-Agent', `MyApp/${Ti.App.version}`)
190
- client.setRequestHeader('Accept', 'application/json')
191
- client.setRequestHeader('Content-Type', 'application/json')
192
-
193
- client.send(data ? JSON.stringify(data) : null)
194
- })
195
- },
196
-
197
- get(endpoint) {
198
- return this.request('GET', endpoint)
199
- },
200
-
201
- post(endpoint, data) {
202
- return this.request('POST', endpoint, data)
203
- }
204
- }
205
- }
206
- ```
207
-
208
- ## Authentication Token Refresh Pattern
209
-
210
- ```javascript
211
- // lib/services/authService.js
212
- const { TokenStorage } = require('lib/services/tokenStorage')
213
-
214
- const TOKEN_REFRESH_THRESHOLD = 5 * 60 * 1000 // 5 minutes before expiry
215
-
216
- exports.refreshAuthToken = async function() {
217
- const refreshToken = TokenStorage.get('refreshToken')
218
-
219
- const response = await api.post('/auth/refresh', {
220
- refresh_token: refreshToken
221
- })
222
-
223
- TokenStorage.save(response.access_token)
224
-
225
- // Set up auto-refresh
226
- scheduleTokenRefresh(response.expires_in)
227
- }
228
-
229
- function scheduleTokenRefresh(expiresIn) {
230
- const refreshTime = expiresIn - TOKEN_REFRESH_THRESHOLD
231
-
232
- setTimeout(() => {
233
- refreshAuthToken().catch(() => {
234
- // Refresh failed - redirect to login
235
- Alloy.createController('login').getView().open()
236
- })
237
- }, refreshTime)
238
- }
239
- ```
240
-
241
- ## Input Validation
242
-
243
- ```javascript
244
- // lib/services/validator.js
245
- exports.Validator = {
246
- email(email) {
247
- const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
248
- if (!regex.test(email)) {
249
- throw new ValidationError('Invalid email format')
250
- }
251
- return email.trim().toLowerCase()
252
- },
253
-
254
- password(password) {
255
- if (password.length < 8) {
256
- throw new ValidationError('Password must be at least 8 characters')
257
- }
258
- // Add more rules as needed
259
- return password
260
- },
261
-
262
- sanitizeInput(input) {
263
- // Remove potentially dangerous characters
264
- return input
265
- .replace(/[<>\"']/g, '')
266
- .trim()
267
- }
268
- }
269
- ```
270
-
271
- ## OWASP Mobile Security Checklist
272
-
273
- | Category | Check | Implementation |
274
- | -------------------- | --------------------------- | ---------------------------------- |
275
- | **Data Storage** | Credentials stored securely | Keychain/KeyStore for tokens |
276
- | **Data Storage** | Sensitive data encrypted | AES-256 for cached data |
277
- | **Communication** | HTTPS only | `validatesSecureCertificate: true` |
278
- | **Communication** | Certificate pinning | SSL pinning enabled |
279
- | **Authentication** | Token refresh | Auto-refresh before expiry |
280
- | **Authentication** | Session timeout | Auto-logout after inactivity |
281
- | **Input Validation** | Server-side validation | Never trust client input |
282
- | **Input Validation** | Sanitize user input | Remove XSS patterns |
283
- | **Cryptography** | No hardcoded keys | Keys from secure storage |
284
- | **Cryptography** | Use standard algorithms | AES-256, SHA-256 |
1
+ # Device Security: Biometrics, Deep Links & Integrity
285
2
 
286
3
  ## Biometric Authentication
287
4
 
@@ -366,13 +83,13 @@ exports.BiometricService = {
366
83
  }
367
84
  ```
368
85
 
369
- ### Biometric Login Flow
86
+ ## Biometric Login Flow
370
87
 
371
88
  ```javascript
372
89
  // controllers/auth/login.js
373
- const { BiometricService } = require('lib/services/biometricService')
374
- const { TokenStorage } = require('lib/services/tokenStorage')
375
- const { AuthService } = require('lib/services/authService')
90
+ const { BiometricService } = require('services/biometricService')
91
+ const { TokenStorage } = require('services/tokenStorage')
92
+ const { AuthService } = require('services/authService')
376
93
 
377
94
  function init() {
378
95
  // Check if biometric login is available and enabled
@@ -437,7 +154,7 @@ async function onLoginSuccess(user) {
437
154
 
438
155
  ```javascript
439
156
  // lib/services/deepLinkService.js
440
- const logger = require('lib/services/logger')
157
+ const logger = require('services/logger')
441
158
 
442
159
  // Whitelist of allowed schemes and hosts
443
160
  const ALLOWED_SCHEMES = ['myapp', 'https']
@@ -594,11 +311,11 @@ exports.DeepLinkService = {
594
311
  }
595
312
  ```
596
313
 
597
- ### Registering Deep Link Handler
314
+ ## Registering Deep Link Handler
598
315
 
599
316
  ```javascript
600
317
  // alloy.js
601
- const { DeepLinkService } = require('lib/services/deepLinkService')
318
+ const { DeepLinkService } = require('services/deepLinkService')
602
319
 
603
320
  // iOS: Handle app launch from deep link
604
321
  if (Ti.App.getArguments().url) {
@@ -635,7 +352,7 @@ if (OS_ANDROID) {
635
352
 
636
353
  ```javascript
637
354
  // lib/services/securityService.js
638
- const logger = require('lib/services/logger')
355
+ const logger = require('services/logger')
639
356
 
640
357
  exports.SecurityService = {
641
358
  /**
@@ -811,11 +528,11 @@ exports.SecurityService = {
811
528
  }
812
529
  ```
813
530
 
814
- ### Integrating Security Checks
531
+ ## Integrating Security Checks
815
532
 
816
533
  ```javascript
817
534
  // alloy.js
818
- const { SecurityService } = require('lib/services/securityService')
535
+ const { SecurityService } = require('services/securityService')
819
536
 
820
537
  // Check device integrity at app start
821
538
  const securityCheck = SecurityService.enforceSecurityPolicy()
@@ -831,7 +548,7 @@ setInterval(() => {
831
548
  }, 5 * 60 * 1000) // Every 5 minutes
832
549
  ```
833
550
 
834
- ## Additional Security Checklist
551
+ ## Security Checklist
835
552
 
836
553
  | Category | Check | Implementation |
837
554
  | -------------- | -------------------------- | ------------------------ |
@@ -0,0 +1,284 @@
1
+ # Security Fundamentals for Titanium Mobile Apps
2
+
3
+ ## Token Storage Strategy
4
+
5
+ **NEVER store tokens in:** `Ti.App.Properties` (plaintext), localStorage, or files.
6
+
7
+ **USE platform-specific secure storage:**
8
+
9
+ ```javascript
10
+ // lib/services/tokenStorage.js
11
+ exports.TokenStorage = {
12
+ save(token) {
13
+ if (Ti.Platform.osname === 'android') {
14
+ // Use Android KeyStore
15
+ const keyStore = Ti.Android.createKeyStore({
16
+ name: 'SecureKeyStore'
17
+ })
18
+ keyStore.addEntry('authToken', token)
19
+ } else {
20
+ // Use iOS Keychain
21
+ Ti.KeychainItem.setItem({
22
+ identifier: 'authToken',
23
+ value: token,
24
+ accessGroup: 'com.yourapp.keychain'
25
+ })
26
+ }
27
+ },
28
+
29
+ get() {
30
+ if (Ti.Platform.osname === 'android') {
31
+ const keyStore = Ti.Android.createKeyStore({
32
+ name: 'SecureKeyStore'
33
+ })
34
+ return keyStore.getEntry('authToken')
35
+ } else {
36
+ return Ti.KeychainItem.getItem({
37
+ identifier: 'authToken',
38
+ accessGroup: 'com.yourapp.keychain'
39
+ })
40
+ }
41
+ },
42
+
43
+ clear() {
44
+ if (Ti.Platform.osname === 'android') {
45
+ const keyStore = Ti.Android.createKeyStore({
46
+ name: 'SecureKeyStore'
47
+ })
48
+ keyStore.removeEntry('authToken')
49
+ } else {
50
+ Ti.KeychainItem.removeItem({
51
+ identifier: 'authToken',
52
+ accessGroup: 'com.yourapp.keychain'
53
+ })
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ## Certificate Pinning
60
+
61
+ Prevent man-in-the-middle attacks by pinning SSL certificates:
62
+
63
+ ```javascript
64
+ // lib/api/pinnedClient.js
65
+ exports.createPinnedClient = function() {
66
+ const client = Ti.Network.createHTTPClient({
67
+ // Security: Enable certificate pinning
68
+ certificatePinning: true,
69
+
70
+ // Specify allowed certificates
71
+ validatesSecureCertificate: true,
72
+
73
+ onload: () => {
74
+ // Success
75
+ },
76
+
77
+ onerror: (e) => {
78
+ // Certificate validation failed
79
+ if (e.error.indexOf('certificate') >= 0) {
80
+ Ti.API.error('Certificate pinning failed - possible MITM attack')
81
+ }
82
+ }
83
+ })
84
+
85
+ return client
86
+ }
87
+ ```
88
+
89
+ **Add certificates to tiapp.xml:**
90
+
91
+ ```xml
92
+ <ti:app>
93
+ <certificates>
94
+ <certificate>
95
+ <name>api.example.com</name>
96
+ <type>rsa</type>
97
+ <file>certificates/api-pin.pem</file>
98
+ </certificate>
99
+ </certificates>
100
+ </ti:app>
101
+ ```
102
+
103
+ ## Data Encryption at Rest
104
+
105
+ ```javascript
106
+ // lib/services/encryption.js
107
+ // AES-256 encryption for sensitive local data
108
+
109
+ const crypto = require('ti.crypto')
110
+
111
+ exports.encrypt = function(data, key) {
112
+ return crypto.encrypt({
113
+ data: data,
114
+ key: key,
115
+ algorithm: crypto.AES_256_CBC,
116
+ options: { mode: crypto.CBC }
117
+ })
118
+ }
119
+
120
+ exports.decrypt = function(encryptedData, key) {
121
+ return crypto.decrypt({
122
+ data: encryptedData,
123
+ key: key,
124
+ algorithm: crypto.AES_256_CBC,
125
+ options: { mode: crypto.CBC }
126
+ })
127
+ }
128
+
129
+ // Usage: Secure cache of sensitive user data
130
+ module.exports = class SecureCache {
131
+ constructor(encryptionKey) {
132
+ this.key = encryptionKey
133
+ this.cache = {}
134
+ }
135
+
136
+ set(key, value) {
137
+ const encrypted = encrypt(JSON.stringify(value), this.key)
138
+ this.cache[key] = encrypted
139
+ }
140
+
141
+ get(key) {
142
+ if (!this.cache[key]) return null
143
+
144
+ const decrypted = decrypt(this.cache[key], this.key)
145
+ return JSON.parse(decrypted)
146
+ }
147
+
148
+ clear() {
149
+ this.cache = {}
150
+ }
151
+ }
152
+ ```
153
+
154
+ ## Secure HTTP Communication
155
+
156
+ ```javascript
157
+ // lib/api/secureClient.js
158
+ exports.createSecureClient = function(baseUrl) {
159
+ return {
160
+ request(method, endpoint, data = null) {
161
+ return new Promise((resolve, reject) => {
162
+ const client = Ti.Network.createHTTPClient({
163
+ timeout: 10000,
164
+
165
+ onload: function() {
166
+ if (this.status === 200) {
167
+ try {
168
+ resolve(JSON.parse(this.responseText))
169
+ } catch (e) {
170
+ reject(new Error('Invalid JSON response'))
171
+ }
172
+ } else {
173
+ reject(new Error(`HTTP ${this.status}`))
174
+ }
175
+ },
176
+
177
+ onerror: function(e) {
178
+ // Log security events
179
+ if (this.status === 401 || this.status === 403) {
180
+ Ti.API.warn(`[SECURITY] Unauthorized: ${endpoint}`)
181
+ }
182
+ reject(e)
183
+ }
184
+ })
185
+
186
+ client.open(method, `${baseUrl}${endpoint}`)
187
+
188
+ // Security headers
189
+ client.setRequestHeader('User-Agent', `MyApp/${Ti.App.version}`)
190
+ client.setRequestHeader('Accept', 'application/json')
191
+ client.setRequestHeader('Content-Type', 'application/json')
192
+
193
+ client.send(data ? JSON.stringify(data) : null)
194
+ })
195
+ },
196
+
197
+ get(endpoint) {
198
+ return this.request('GET', endpoint)
199
+ },
200
+
201
+ post(endpoint, data) {
202
+ return this.request('POST', endpoint, data)
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ ## Authentication Token Refresh Pattern
209
+
210
+ ```javascript
211
+ // lib/services/authService.js
212
+ const { TokenStorage } = require('services/tokenStorage')
213
+
214
+ const TOKEN_REFRESH_THRESHOLD = 5 * 60 * 1000 // 5 minutes before expiry
215
+
216
+ exports.refreshAuthToken = async function() {
217
+ const refreshToken = TokenStorage.get('refreshToken')
218
+
219
+ const response = await api.post('/auth/refresh', {
220
+ refresh_token: refreshToken
221
+ })
222
+
223
+ TokenStorage.save(response.access_token)
224
+
225
+ // Set up auto-refresh
226
+ scheduleTokenRefresh(response.expires_in)
227
+ }
228
+
229
+ function scheduleTokenRefresh(expiresIn) {
230
+ const refreshTime = expiresIn - TOKEN_REFRESH_THRESHOLD
231
+
232
+ setTimeout(() => {
233
+ refreshAuthToken().catch(() => {
234
+ // Refresh failed - redirect to login
235
+ Alloy.createController('login').getView().open()
236
+ })
237
+ }, refreshTime)
238
+ }
239
+ ```
240
+
241
+ ## Input Validation
242
+
243
+ ```javascript
244
+ // lib/services/validator.js
245
+ exports.Validator = {
246
+ email(email) {
247
+ const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
248
+ if (!regex.test(email)) {
249
+ throw new ValidationError('Invalid email format')
250
+ }
251
+ return email.trim().toLowerCase()
252
+ },
253
+
254
+ password(password) {
255
+ if (password.length < 8) {
256
+ throw new ValidationError('Password must be at least 8 characters')
257
+ }
258
+ // Add more rules as needed
259
+ return password
260
+ },
261
+
262
+ sanitizeInput(input) {
263
+ // Remove potentially dangerous characters
264
+ return input
265
+ .replace(/[<>\"']/g, '')
266
+ .trim()
267
+ }
268
+ }
269
+ ```
270
+
271
+ ## OWASP Mobile Security Checklist
272
+
273
+ | Category | Check | Implementation |
274
+ | -------------------- | --------------------------- | ---------------------------------- |
275
+ | **Data Storage** | Credentials stored securely | Keychain/KeyStore for tokens |
276
+ | **Data Storage** | Sensitive data encrypted | AES-256 for cached data |
277
+ | **Communication** | HTTPS only | `validatesSecureCertificate: true` |
278
+ | **Communication** | Certificate pinning | SSL pinning enabled |
279
+ | **Authentication** | Token refresh | Auto-refresh before expiry |
280
+ | **Authentication** | Session timeout | Auto-logout after inactivity |
281
+ | **Input Validation** | Server-side validation | Never trust client input |
282
+ | **Input Validation** | Sanitize user input | Remove XSS patterns |
283
+ | **Cryptography** | No hardcoded keys | Keys from secure storage |
284
+ | **Cryptography** | Use standard algorithms | AES-256, SHA-256 |
@@ -82,8 +82,8 @@ exports.appStore = new StateStore()
82
82
 
83
83
  ```javascript
84
84
  // alloy.js
85
- const { appStore } = require('lib/services/stateStore')
86
- const { TokenStorage } = require('lib/services/tokenStorage')
85
+ const { appStore } = require('services/stateStore')
86
+ const { TokenStorage } = require('services/tokenStorage')
87
87
 
88
88
  // Initialize store from persisted data
89
89
  function initAppStore() {
@@ -105,7 +105,7 @@ initAppStore()
105
105
 
106
106
  ```javascript
107
107
  // controllers/home/index.js
108
- const { appStore } = require('lib/services/stateStore')
108
+ const { appStore } = require('services/stateStore')
109
109
 
110
110
  function init() {
111
111
  // Get current state
@@ -143,9 +143,9 @@ function cleanup() {
143
143
 
144
144
  ```javascript
145
145
  // lib/services/authService.js
146
- const { appStore } = require('lib/services/stateStore')
147
- const { TokenStorage } = require('lib/services/tokenStorage')
148
- const api = require('lib/api/authApi')
146
+ const { appStore } = require('services/stateStore')
147
+ const { TokenStorage } = require('services/tokenStorage')
148
+ const api = require('api/authApi')
149
149
 
150
150
  exports.login = async function(email, password) {
151
151
  appStore.setState({
@@ -195,7 +195,7 @@ Services can maintain their own cached state:
195
195
 
196
196
  ```javascript
197
197
  // lib/services/userService.js
198
- const { appStore } = require('lib/services/stateStore')
198
+ const { appStore } = require('services/stateStore')
199
199
 
200
200
  class UserService {
201
201
  constructor() {
@@ -260,7 +260,7 @@ When state needs to sync with server:
260
260
 
261
261
  ```javascript
262
262
  // lib/services/syncService.js
263
- const { appStore } = require('lib/services/stateStore')
263
+ const { appStore } = require('services/stateStore')
264
264
 
265
265
  exports.syncWithServer = function() {
266
266
  const localState = appStore.getState()
@@ -727,8 +727,8 @@ appStore.use(debugMiddleware)
727
727
 
728
728
  ```javascript
729
729
  // controllers/debug/stateViewer.js (Development only)
730
- const { StateDebug } = require('lib/services/stateDebug')
731
- const { appStore } = require('lib/services/stateStore')
730
+ const { StateDebug } = require('services/stateDebug')
731
+ const { appStore } = require('services/stateStore')
732
732
 
733
733
  function init() {
734
734
  if (!Alloy.CFG.debug) {