@rashidee/co2 1.2.5

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 (190) hide show
  1. package/dist/index.js +25449 -0
  2. package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
  3. package/drizzle/0001_wise_wolf_cub.sql +13 -0
  4. package/drizzle/0002_secret_spyke.sql +16 -0
  5. package/drizzle/0003_workspace_config_singleton.sql +16 -0
  6. package/drizzle/0004_terminal_claim_v120.sql +11 -0
  7. package/drizzle/0005_brainstorm_v124.sql +10 -0
  8. package/drizzle/0006_project_v140.sql +6 -0
  9. package/drizzle/0007_prd_wizard_v124.sql +14 -0
  10. package/drizzle/0008_workflow_artifact_v126.sql +24 -0
  11. package/drizzle/0009_project_import_v150.sql +7 -0
  12. package/drizzle/0010_quality_v151.sql +3 -0
  13. package/drizzle/meta/0000_snapshot.json +1335 -0
  14. package/drizzle/meta/0001_snapshot.json +1416 -0
  15. package/drizzle/meta/0002_snapshot.json +1510 -0
  16. package/drizzle/meta/_journal.json +83 -0
  17. package/package.json +41 -0
  18. package/plugin/.claude-plugin/marketplace.json +36 -0
  19. package/plugin/.claude-plugin/plugin.json +22 -0
  20. package/plugin/README.md +625 -0
  21. package/plugin/SKILLS.md +350 -0
  22. package/plugin/co2.svg +5 -0
  23. package/plugin/commands/brainstorm-loop.md +129 -0
  24. package/plugin/skills/conductor-defect/SKILL.md +898 -0
  25. package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
  26. package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
  27. package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
  28. package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
  29. package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
  30. package/plugin/skills/depgen-k8s/SKILL.md +468 -0
  31. package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
  32. package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
  33. package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
  34. package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
  35. package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
  36. package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
  37. package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
  38. package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
  39. package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
  40. package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
  41. package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
  42. package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
  43. package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
  44. package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
  45. package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
  46. package/plugin/skills/modelgen-relational/SKILL.md +707 -0
  47. package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
  48. package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
  49. package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
  50. package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
  51. package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
  52. package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
  53. package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
  54. package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
  55. package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
  56. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
  57. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
  58. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
  59. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
  60. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
  61. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
  62. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
  63. package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
  64. package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
  65. package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
  66. package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
  67. package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
  68. package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
  69. package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
  70. package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
  71. package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
  72. package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
  73. package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
  74. package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
  75. package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
  76. package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
  77. package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
  78. package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
  79. package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
  80. package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
  81. package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
  82. package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
  83. package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
  84. package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
  85. package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
  86. package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
  87. package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
  88. package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
  89. package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
  90. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
  91. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
  92. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
  93. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
  94. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
  95. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
  96. package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
  97. package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
  98. package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
  99. package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
  100. package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
  101. package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
  102. package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
  103. package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
  104. package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
  105. package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
  106. package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
  107. package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
  108. package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
  109. package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
  110. package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
  111. package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
  112. package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
  113. package/plugin/skills/testgen-functional/SKILL.md +1381 -0
  114. package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
  115. package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
  116. package/plugin/skills/util-projectinit/SKILL.md +307 -0
  117. package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
  118. package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
  119. package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
  120. package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
  121. package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
  122. package/plugin/skills/util-projectsync/SKILL.md +501 -0
  123. package/plugin/skills/util-updprd/SKILL.md +324 -0
  124. package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
  125. package/plugin/skills/util-ustagger/SKILL.md +154 -0
  126. package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
  127. package/static/assets/arc-DRKw7sjs.js +1 -0
  128. package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
  129. package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
  130. package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
  131. package/static/assets/channel-C2nVbuwv.js +1 -0
  132. package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
  133. package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
  134. package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
  135. package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
  136. package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
  137. package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
  138. package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
  139. package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
  140. package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
  141. package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
  142. package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
  143. package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
  144. package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
  145. package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
  146. package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
  147. package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
  148. package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
  149. package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
  150. package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
  151. package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
  152. package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
  153. package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
  154. package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
  155. package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
  156. package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
  157. package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
  158. package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
  159. package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
  160. package/static/assets/graph-C9eacEi8.js +1 -0
  161. package/static/assets/index-LZSQkLE2.css +41 -0
  162. package/static/assets/index-y7XDSgMG.js +495 -0
  163. package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
  164. package/static/assets/init-Gi6I4Gst.js +1 -0
  165. package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
  166. package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
  167. package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
  168. package/static/assets/katex-C5jXJg4s.js +257 -0
  169. package/static/assets/layout-DEXfKzaS.js +1 -0
  170. package/static/assets/linear-CLO--ryk.js +1 -0
  171. package/static/assets/map-Czzmt4hB.js +1 -0
  172. package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
  173. package/static/assets/ordinal-Cboi1Yqb.js +1 -0
  174. package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
  175. package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
  176. package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
  177. package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
  178. package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
  179. package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
  180. package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
  181. package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
  182. package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
  183. package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
  184. package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
  185. package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
  186. package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
  187. package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
  188. package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
  189. package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
  190. package/static/index.html +24 -0
@@ -0,0 +1,370 @@
1
+ # Storage Patterns — Hive Local Database + Dio HTTP Client
2
+
3
+ This reference describes how Hive (local NoSQL storage) and Dio (HTTP client) are
4
+ configured and used together in the spec. Include this content in Sections 8 and 9 of
5
+ the generated specification.
6
+
7
+ ---
8
+
9
+ ## Hive Setup
10
+
11
+ ### Initialization
12
+
13
+ ```dart
14
+ // lib/core/local_storage/hive_setup.dart
15
+ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
16
+ import 'package:hive/hive.dart';
17
+ import 'package:hive_flutter/hive_flutter.dart';
18
+
19
+ import '../../features/task/domain/task.dart';
20
+ import '../../features/profile/domain/profile.dart';
21
+
22
+ class HiveSetup {
23
+ HiveSetup._();
24
+
25
+ static const _settingsBox = 'settings';
26
+ static const _userProfileBox = 'user_profile';
27
+ static const _taskCacheBox = 'task_cache';
28
+ static const _encryptionKeyName = 'hive_encryption_key';
29
+
30
+ static Future<void> init() async {
31
+ await Hive.initFlutter();
32
+
33
+ // Register type adapters
34
+ Hive.registerAdapter(TaskAdapter());
35
+ Hive.registerAdapter(TaskStatusAdapter());
36
+ Hive.registerAdapter(ProfileAdapter());
37
+
38
+ // Open plain (non-sensitive) boxes
39
+ await Hive.openBox(_settingsBox);
40
+
41
+ // Open encrypted boxes for sensitive cached data
42
+ final cipher = await _resolveCipher();
43
+ await Hive.openBox<Profile>(_userProfileBox, encryptionCipher: cipher);
44
+ await Hive.openBox<Task>(_taskCacheBox, encryptionCipher: cipher);
45
+ }
46
+
47
+ static Future<HiveAesCipher> _resolveCipher() async {
48
+ const secureStorage = FlutterSecureStorage();
49
+ String? base64Key = await secureStorage.read(key: _encryptionKeyName);
50
+ if (base64Key == null) {
51
+ final key = Hive.generateSecureKey();
52
+ base64Key = base64Encode(key);
53
+ await secureStorage.write(key: _encryptionKeyName, value: base64Key);
54
+ }
55
+ return HiveAesCipher(base64Decode(base64Key));
56
+ }
57
+
58
+ /// Clears all cached boxes (call on logout)
59
+ static Future<void> clearUserData() async {
60
+ await Hive.box<Profile>(_userProfileBox).clear();
61
+ await Hive.box<Task>(_taskCacheBox).clear();
62
+ }
63
+ }
64
+ ```
65
+
66
+ ### Typed Box Providers
67
+
68
+ ```dart
69
+ // lib/core/local_storage/box_provider.dart
70
+ import 'package:hive/hive.dart';
71
+ import 'package:riverpod_annotation/riverpod_annotation.dart';
72
+
73
+ import '../../features/profile/domain/profile.dart';
74
+ import '../../features/task/domain/task.dart';
75
+
76
+ part 'box_provider.g.dart';
77
+
78
+ @Riverpod(keepAlive: true)
79
+ Box settingsBox(SettingsBoxRef ref) => Hive.box('settings');
80
+
81
+ @Riverpod(keepAlive: true)
82
+ Box<Profile> profileBox(ProfileBoxRef ref) => Hive.box<Profile>('user_profile');
83
+
84
+ @Riverpod(keepAlive: true)
85
+ Box<Task> taskCacheBox(TaskCacheBoxRef ref) => Hive.box<Task>('task_cache');
86
+ ```
87
+
88
+ ### Secure Storage Provider
89
+
90
+ ```dart
91
+ // lib/core/local_storage/secure_storage_provider.dart
92
+ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
93
+ import 'package:riverpod_annotation/riverpod_annotation.dart';
94
+
95
+ part 'secure_storage_provider.g.dart';
96
+
97
+ @Riverpod(keepAlive: true)
98
+ FlutterSecureStorage secureStorage(SecureStorageRef ref) {
99
+ return const FlutterSecureStorage(
100
+ aOptions: AndroidOptions(encryptedSharedPreferences: true),
101
+ iOptions: IOSOptions(accessibility: KeychainAccessibility.first_unlock),
102
+ );
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Hive Type Adapter (Co-located With Freezed Model)
109
+
110
+ Annotate freezed model fields with `@HiveField(N)` to generate adapters. The Hive
111
+ generator picks them up via `build_runner`:
112
+
113
+ ```dart
114
+ // lib/features/task/domain/task.dart
115
+ import 'package:freezed_annotation/freezed_annotation.dart';
116
+ import 'package:hive/hive.dart';
117
+
118
+ part 'task.freezed.dart';
119
+ part 'task.g.dart';
120
+
121
+ @HiveType(typeId: 1)
122
+ enum TaskStatus {
123
+ @HiveField(0) @JsonValue('DRAFT') draft,
124
+ @HiveField(1) @JsonValue('IN_PROGRESS') inProgress,
125
+ @HiveField(2) @JsonValue('COMPLETED') completed,
126
+ }
127
+
128
+ @freezed
129
+ class Task with _$Task {
130
+ @HiveType(typeId: 2)
131
+ const factory Task({
132
+ @HiveField(0) required String id,
133
+ @HiveField(1) required String title,
134
+ @HiveField(2) String? description,
135
+ @HiveField(3) required TaskStatus status,
136
+ @HiveField(4) required DateTime dueDate,
137
+ @HiveField(5) required DateTime createdAt,
138
+ @HiveField(6) required DateTime updatedAt,
139
+ }) = _Task;
140
+
141
+ factory Task.fromJson(Map<String, dynamic> json) => _$TaskFromJson(json);
142
+ }
143
+ ```
144
+
145
+ > Each module's `typeId` must be unique across the application — keep a registry in a
146
+ > central `lib/core/local_storage/type_ids.dart` if many modules use Hive.
147
+
148
+ ---
149
+
150
+ ## Cache-Aside Read Pattern
151
+
152
+ ```dart
153
+ // lib/features/task/data/task_repository.dart (excerpt)
154
+ class TaskRepository {
155
+ TaskRepository(this._dio, this._cacheBox);
156
+ final Dio _dio;
157
+ final Box<Task> _cacheBox;
158
+
159
+ Future<List<Task>> listCached() async {
160
+ return _cacheBox.values.toList();
161
+ }
162
+
163
+ Future<List<Task>> refreshList(TaskListParams params) async {
164
+ try {
165
+ final response = await _dio.get<Map<String, dynamic>>(
166
+ '/tasks',
167
+ queryParameters: params.toJson(),
168
+ );
169
+ final page = PaginatedResponse.fromJson(
170
+ response.data!,
171
+ (json) => Task.fromJson(json as Map<String, dynamic>),
172
+ );
173
+ // Replace cache with fresh page
174
+ await _cacheBox.clear();
175
+ await _cacheBox.addAll(page.content);
176
+ return page.content;
177
+ } on DioException catch (e) {
178
+ throw ApiFailure.fromDioException(e);
179
+ }
180
+ }
181
+
182
+ Future<void> upsertCached(Task task) async {
183
+ final key = _cacheBox.values.toList().indexWhere((t) => t.id == task.id);
184
+ if (key >= 0) {
185
+ await _cacheBox.putAt(key, task);
186
+ } else {
187
+ await _cacheBox.add(task);
188
+ }
189
+ }
190
+ }
191
+ ```
192
+
193
+ ---
194
+
195
+ ## Paginated Response Type
196
+
197
+ ```dart
198
+ // lib/core/api/paginated_response.dart
199
+ import 'package:freezed_annotation/freezed_annotation.dart';
200
+
201
+ part 'paginated_response.freezed.dart';
202
+
203
+ @Freezed(genericArgumentFactories: true)
204
+ class PaginatedResponse<T> with _$PaginatedResponse<T> {
205
+ const factory PaginatedResponse({
206
+ required List<T> content,
207
+ required int page,
208
+ required int size,
209
+ required int totalElements,
210
+ required int totalPages,
211
+ }) = _PaginatedResponse<T>;
212
+
213
+ factory PaginatedResponse.fromJson(
214
+ Map<String, dynamic> json,
215
+ T Function(Object?) fromJsonT,
216
+ ) {
217
+ return PaginatedResponse<T>(
218
+ content: (json['content'] as List).map((e) => fromJsonT(e)).toList(),
219
+ page: json['page'] as int,
220
+ size: json['size'] as int,
221
+ totalElements: json['totalElements'] as int,
222
+ totalPages: json['totalPages'] as int,
223
+ );
224
+ }
225
+ }
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Settings & Preferences
231
+
232
+ Use the plain `settings` box for simple key-value preferences:
233
+
234
+ ```dart
235
+ // Theme mode
236
+ ref.read(settingsBoxProvider).put('themeMode', 'dark');
237
+ final mode = ref.read(settingsBoxProvider).get('themeMode') as String?;
238
+
239
+ // Locale
240
+ ref.read(settingsBoxProvider).put('locale', 'ms');
241
+
242
+ // First-launch flag
243
+ final firstLaunch = !(ref.read(settingsBoxProvider).get('hasLaunched') as bool? ?? false);
244
+ await ref.read(settingsBoxProvider).put('hasLaunched', true);
245
+ ```
246
+
247
+ For complex typed preferences, define a small `@freezed` class with a Hive adapter and
248
+ store it in a dedicated box (e.g., `Box<UserPreferences>`).
249
+
250
+ ---
251
+
252
+ ## Dio Configuration (Recap)
253
+
254
+ The Dio instance is constructed once in `dioProvider` and shared via Riverpod. Its
255
+ interceptors are layered in this exact order:
256
+
257
+ 1. **AuthInterceptor** — injects Bearer token (reads via `AuthRepository.getAccessToken`)
258
+ 2. **RetryInterceptor (dio_smart_retry)** — exponential backoff on 5xx and network
259
+ errors; only retries idempotent methods (GET, PUT, DELETE)
260
+ 3. **PrettyDioLogger** — verbose request/response logging in `kDebugMode` only
261
+
262
+ ```dart
263
+ // (Already shown in spec-template Section 8)
264
+ ```
265
+
266
+ ### `pretty_dio_logger` Configuration
267
+
268
+ ```dart
269
+ PrettyDioLogger(
270
+ requestHeader: true, // log headers
271
+ requestBody: true, // log request body
272
+ responseBody: true, // log response body
273
+ responseHeader: false,
274
+ error: true,
275
+ compact: false,
276
+ maxWidth: 90,
277
+ );
278
+ ```
279
+
280
+ ### Retry Interceptor
281
+
282
+ ```dart
283
+ RetryInterceptor(
284
+ dio: dio,
285
+ retries: 3,
286
+ retryDelays: const [
287
+ Duration(seconds: 1),
288
+ Duration(seconds: 2),
289
+ Duration(seconds: 4),
290
+ ],
291
+ retryableExtraStatuses: const {502, 503, 504},
292
+ // By default, dio_smart_retry only retries idempotent methods (GET, HEAD, PUT,
293
+ // DELETE, OPTIONS, TRACE). POST is NOT retried by default — which is correct for
294
+ // most mutations. Override per-request via `RequestOptions.extra['retry'] = true`
295
+ // for explicitly idempotent POSTs.
296
+ );
297
+ ```
298
+
299
+ ### Per-Request Retry Override
300
+
301
+ To enable retries for a single (idempotent-by-design) POST:
302
+
303
+ ```dart
304
+ await dio.post(
305
+ '/audit-logs',
306
+ data: payload,
307
+ options: Options(extra: {RetryInterceptor.kRetryAttemptsKey: 3}),
308
+ );
309
+ ```
310
+
311
+ ---
312
+
313
+ ## Error Mapping at the Boundary
314
+
315
+ Repositories convert `DioException` into the sealed `ApiFailure` type so that screens
316
+ deal with a typed failure rather than transport-level details:
317
+
318
+ ```dart
319
+ try {
320
+ final response = await _dio.get<Map<String, dynamic>>('/tasks/$id');
321
+ return Task.fromJson(response.data!);
322
+ } on DioException catch (e) {
323
+ throw ApiFailure.fromDioException(e);
324
+ }
325
+ ```
326
+
327
+ `ApiFailure.fromDioException` (see `spec-template.md` Section 8) handles:
328
+ - Network timeouts → `ApiFailure.network()`
329
+ - 401 → `ApiFailure.unauthorized()`
330
+ - 403 → `ApiFailure.forbidden()`
331
+ - 404 → `ApiFailure.notFound()`
332
+ - 5xx → `ApiFailure.server(status, message)`
333
+ - Everything else → `ApiFailure.unknown(error)`
334
+
335
+ Screens consume failures via Riverpod `AsyncValue.when(error: ...)` and feed them into
336
+ the `ErrorState` widget for consistent UX.
337
+
338
+ ---
339
+
340
+ ## Migration Strategy
341
+
342
+ When a freezed/Hive model adds a field with a new `@HiveField` index:
343
+ - The new field MUST be nullable or have a default value — Hive treats missing fields
344
+ as `null` for older records.
345
+ - Never reuse a removed `@HiveField` index. Mark the field with `@Deprecated` if you
346
+ need to keep reading it; otherwise remove and never assign that index again.
347
+ - For breaking schema changes (renamed type, restructured fields), bump the box name
348
+ (e.g., `task_cache` → `task_cache_v2`) and run a one-time clear-and-refetch on startup:
349
+
350
+ ```dart
351
+ final box = await Hive.openBox<Task>('task_cache_v2');
352
+ if (Hive.boxExists('task_cache')) {
353
+ await Hive.deleteBoxFromDisk('task_cache');
354
+ }
355
+ ```
356
+
357
+ ---
358
+
359
+ ## Logout Hygiene
360
+
361
+ On user logout, clear all caches and secure-storage keys to avoid leaking data to the
362
+ next user on a shared device:
363
+
364
+ ```dart
365
+ Future<void> performLogout(WidgetRef ref) async {
366
+ await ref.read(authProvider.notifier).signOut();
367
+ await HiveSetup.clearUserData();
368
+ // Secure storage keys cleared inside AuthRepository.signOutLocal()
369
+ }
370
+ ```