@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,362 @@
1
+ # Routing Patterns — go_router 14 + Feature-Based Architecture
2
+
3
+ This reference describes the go_router conventions and feature-based directory
4
+ structure used in the spec. Include this content in Sections 4 and 7 of the generated
5
+ specification.
6
+
7
+ ---
8
+
9
+ ## Feature-Based Directory Structure
10
+
11
+ Each PRD module maps to a `lib/features/<module>/` folder. This co-locates everything
12
+ related to a feature (model, data, application, presentation) so the coding agent can
13
+ implement one feature folder at a time.
14
+
15
+ ```
16
+ lib/
17
+ ├── main.dart # App entry — Firebase, Hive, Riverpod scope
18
+ ├── app.dart # MaterialApp.router + theme + locale
19
+ ├── firebase_options.dart # Generated by `flutterfire configure`
20
+ ├── router/
21
+ │ └── app_router.dart # go_router configuration + guards
22
+ ├── core/
23
+ │ ├── api/
24
+ │ │ ├── dio_provider.dart # Dio + interceptors
25
+ │ │ ├── api_failure.dart # Sealed failure type
26
+ │ │ ├── auth_interceptor.dart # Bearer token injector
27
+ │ │ └── paginated_response.dart # Generic page envelope
28
+ │ ├── auth/
29
+ │ │ ├── auth_repository.dart # signIn/signOut/refresh
30
+ │ │ ├── auth_provider.dart # Riverpod auth state
31
+ │ │ ├── auth_state.dart # @freezed AuthState
32
+ │ │ └── roles.dart # Role constants
33
+ │ ├── local_storage/
34
+ │ │ ├── hive_setup.dart # Hive.initFlutter + adapters
35
+ │ │ ├── secure_storage_provider.dart # flutter_secure_storage
36
+ │ │ └── box_provider.dart # Typed Box providers
37
+ │ ├── notification/
38
+ │ │ ├── notification_service.dart # FCM + flutter_local_notifications
39
+ │ │ ├── notification_handler.dart # Foreground/background/tap
40
+ │ │ └── notification_navigation.dart # Deep-link routing
41
+ │ ├── theme/
42
+ │ │ ├── app_theme.dart
43
+ │ │ ├── app_colors.dart
44
+ │ │ └── app_typography.dart
45
+ │ ├── env/
46
+ │ │ └── env_config.dart
47
+ │ └── utils/
48
+ │ ├── validators.dart
49
+ │ ├── formatters.dart
50
+ │ └── url_helper.dart
51
+ ├── shared/
52
+ │ ├── widgets/
53
+ │ │ ├── app_scaffold.dart
54
+ │ │ ├── loading_indicator.dart
55
+ │ │ ├── empty_state.dart
56
+ │ │ ├── error_state.dart
57
+ │ │ ├── confirm_dialog.dart
58
+ │ │ ├── status_chip.dart
59
+ │ │ ├── search_bar_field.dart
60
+ │ │ ├── pull_to_refresh_list.dart
61
+ │ │ ├── infinite_scroll_list.dart
62
+ │ │ ├── app_network_image.dart
63
+ │ │ ├── cached_svg_icon.dart
64
+ │ │ └── shell_screen.dart # Bottom-nav shell
65
+ │ ├── form/
66
+ │ │ ├── form_text_field.dart
67
+ │ │ ├── form_dropdown_field.dart
68
+ │ │ ├── form_date_picker_field.dart
69
+ │ │ ├── form_switch_field.dart
70
+ │ │ └── form_image_picker_field.dart # [If ImagePicker = yes]
71
+ │ ├── navigation/
72
+ │ │ └── nav_config.dart # NavItem list
73
+ │ └── providers/
74
+ │ └── theme_mode_provider.dart # ThemeMode controller (Hive-backed)
75
+ ├── features/
76
+ │ ├── auth/ # [If Auth != none]
77
+ │ │ ├── presentation/
78
+ │ │ │ ├── login_screen.dart # [If Auth = Local]
79
+ │ │ │ └── auth_callback_screen.dart # [If Auth = Keycloak]
80
+ │ │ └── auth.dart # Barrel
81
+ │ ├── dashboard/
82
+ │ │ ├── presentation/
83
+ │ │ │ └── dashboard_screen.dart
84
+ │ │ └── dashboard.dart
85
+ │ ├── {{module1}}/ # PRD module 1 (e.g., task)
86
+ │ │ ├── data/
87
+ │ │ │ └── {{module1}}_repository.dart
88
+ │ │ ├── domain/
89
+ │ │ │ └── {{module1}}.dart # @freezed + Hive adapter
90
+ │ │ ├── application/
91
+ │ │ │ └── {{module1}}_providers.dart # Generated providers
92
+ │ │ ├── presentation/
93
+ │ │ │ ├── {{module1}}_list_screen.dart
94
+ │ │ │ ├── {{module1}}_detail_screen.dart
95
+ │ │ │ ├── {{module1}}_form_screen.dart
96
+ │ │ │ └── widgets/
97
+ │ │ │ └── {{module1}}_card.dart
98
+ │ │ └── {{module1}}.dart # Barrel
99
+ │ └── {{module2}}/
100
+ │ └── (same structure)
101
+ └── l10n/ # [If i18n = yes]
102
+ ├── app_en.arb
103
+ └── app_ms.arb
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Route Tree Definition
109
+
110
+ ```dart
111
+ // lib/router/app_router.dart
112
+ import 'package:flutter/material.dart';
113
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
114
+ import 'package:go_router/go_router.dart';
115
+ import 'package:riverpod_annotation/riverpod_annotation.dart';
116
+
117
+ import '../core/auth/auth_provider.dart';
118
+ import '../core/auth/auth_state.dart';
119
+ import '../core/auth/roles.dart';
120
+ import '../features/auth/presentation/auth_callback_screen.dart';
121
+ import '../features/auth/presentation/login_screen.dart';
122
+ import '../features/dashboard/presentation/dashboard_screen.dart';
123
+ import '../features/profile/presentation/profile_screen.dart';
124
+ import '../features/task/presentation/task_form_screen.dart';
125
+ import '../features/task/presentation/task_list_screen.dart';
126
+ import '../shared/widgets/shell_screen.dart';
127
+
128
+ part 'app_router.g.dart';
129
+
130
+ @Riverpod(keepAlive: true)
131
+ GoRouter appRouter(AppRouterRef ref) {
132
+ final authState = ref.watch(authProvider);
133
+
134
+ return GoRouter(
135
+ initialLocation: '/dashboard',
136
+ debugLogDiagnostics: true,
137
+ redirect: (context, state) {
138
+ final isAuthed = authState.valueOrNull is _Authenticated;
139
+ final atLogin = state.matchedLocation == '/login' ||
140
+ state.matchedLocation.startsWith('/auth/');
141
+
142
+ // [If Auth = Local]
143
+ if (!isAuthed && !atLogin) return '/login';
144
+ if (isAuthed && atLogin) return '/dashboard';
145
+ return null;
146
+ },
147
+ routes: [
148
+ // ── Auth routes (public) ───────────────────────────────────────────
149
+ // [If Auth = Local]
150
+ GoRoute(
151
+ path: '/login',
152
+ name: 'login',
153
+ builder: (context, state) => const LoginScreen(),
154
+ ),
155
+ // [If Auth = Keycloak]
156
+ GoRoute(
157
+ path: '/auth/callback',
158
+ name: 'auth-callback',
159
+ builder: (context, state) => const AuthCallbackScreen(),
160
+ ),
161
+
162
+ // ── Authenticated shell (bottom navigation) ────────────────────────
163
+ ShellRoute(
164
+ builder: (context, state, child) => ShellScreen(child: child),
165
+ routes: [
166
+ GoRoute(
167
+ path: '/dashboard',
168
+ name: 'dashboard',
169
+ builder: (context, state) => const DashboardScreen(),
170
+ ),
171
+
172
+ // Task — accessible by WORKER and ADMIN
173
+ GoRoute(
174
+ path: '/task',
175
+ name: 'task-list',
176
+ redirect: (context, state) =>
177
+ _requireRoles(authState, [Roles.worker, Roles.admin]),
178
+ builder: (context, state) => const TaskListScreen(),
179
+ routes: [
180
+ GoRoute(
181
+ path: 'create',
182
+ name: 'task-create',
183
+ builder: (context, state) => const TaskFormScreen(),
184
+ ),
185
+ GoRoute(
186
+ path: ':id',
187
+ name: 'task-detail',
188
+ builder: (context, state) =>
189
+ TaskFormScreen(taskId: state.pathParameters['id']),
190
+ routes: [
191
+ GoRoute(
192
+ path: 'edit',
193
+ name: 'task-edit',
194
+ builder: (context, state) =>
195
+ TaskFormScreen(taskId: state.pathParameters['id']),
196
+ ),
197
+ ],
198
+ ),
199
+ ],
200
+ ),
201
+
202
+ GoRoute(
203
+ path: '/profile',
204
+ name: 'profile',
205
+ builder: (context, state) => const ProfileScreen(),
206
+ ),
207
+
208
+ // Add additional module routes following the same pattern...
209
+ ],
210
+ ),
211
+
212
+ // ── Error routes ───────────────────────────────────────────────────
213
+ GoRoute(
214
+ path: '/unauthorized',
215
+ builder: (context, state) => Scaffold(
216
+ appBar: AppBar(title: const Text('Unauthorized')),
217
+ body: const Center(
218
+ child: Text('You do not have permission to access this page.'),
219
+ ),
220
+ ),
221
+ ),
222
+ ],
223
+ errorBuilder: (context, state) => Scaffold(
224
+ appBar: AppBar(title: const Text('Not Found')),
225
+ body: const Center(child: Text('404 — Page not found.')),
226
+ ),
227
+ );
228
+ }
229
+
230
+ String? _requireRoles(AsyncValue<AuthState> authState, List<String> requiredRoles) {
231
+ final state = authState.valueOrNull;
232
+ if (state is! _Authenticated) return null; // top-level redirect handles auth
233
+ final hasAny = requiredRoles.any((r) => state.user.roles.contains(r));
234
+ return hasAny ? null : '/unauthorized';
235
+ }
236
+ ```
237
+
238
+ ---
239
+
240
+ ## ShellScreen (Bottom Navigation Shell)
241
+
242
+ ```dart
243
+ // lib/shared/widgets/shell_screen.dart
244
+ import 'package:flutter/material.dart';
245
+ import 'package:flutter_riverpod/flutter_riverpod.dart';
246
+ import 'package:go_router/go_router.dart';
247
+
248
+ import '../../core/auth/auth_provider.dart';
249
+ import '../../core/auth/auth_state.dart';
250
+ import '../navigation/nav_config.dart';
251
+
252
+ class ShellScreen extends ConsumerWidget {
253
+ const ShellScreen({super.key, required this.child});
254
+ final Widget child;
255
+
256
+ @override
257
+ Widget build(BuildContext context, WidgetRef ref) {
258
+ final authState = ref.watch(authProvider);
259
+ final user = authState.valueOrNull is _Authenticated
260
+ ? (authState.value! as _Authenticated).user
261
+ : null;
262
+
263
+ final visibleItems = navigationItems.where((item) {
264
+ if (item.requiredRoles == null) return true;
265
+ if (user == null) return false;
266
+ return item.requiredRoles!.any(user.roles.contains);
267
+ }).toList();
268
+
269
+ final location = GoRouterState.of(context).matchedLocation;
270
+ final currentIndex = visibleItems.indexWhere(
271
+ (item) => location.startsWith(item.path),
272
+ );
273
+
274
+ return Scaffold(
275
+ body: child,
276
+ bottomNavigationBar: NavigationBar(
277
+ selectedIndex: currentIndex < 0 ? 0 : currentIndex,
278
+ onDestinationSelected: (index) => context.go(visibleItems[index].path),
279
+ destinations: [
280
+ for (final item in visibleItems)
281
+ NavigationDestination(
282
+ icon: Icon(item.icon),
283
+ selectedIcon: Icon(item.activeIcon),
284
+ label: item.label,
285
+ ),
286
+ ],
287
+ ),
288
+ );
289
+ }
290
+ }
291
+ ```
292
+
293
+ ---
294
+
295
+ ## Deep Link Configuration
296
+
297
+ go_router automatically handles deep links registered in the Android manifest and iOS
298
+ `Info.plist`. For FCM notification payloads, use the same path structure.
299
+
300
+ **Notification payload example:**
301
+ ```json
302
+ {
303
+ "notification": {
304
+ "title": "New task assigned",
305
+ "body": "Inspect site #42"
306
+ },
307
+ "data": {
308
+ "deeplink": "/task/abc-123"
309
+ }
310
+ }
311
+ ```
312
+
313
+ **Handler (in `NotificationService`):**
314
+ ```dart
315
+ FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
316
+ final deeplink = message.data['deeplink'] as String?;
317
+ if (deeplink != null) {
318
+ // Read router from ProviderContainer at app root (set up in app.dart)
319
+ rootContainer.read(appRouterProvider).go(deeplink);
320
+ }
321
+ });
322
+ ```
323
+
324
+ ---
325
+
326
+ ## Typed Route Helpers (Optional via go_router_builder)
327
+
328
+ If `go_router_builder` is added, define typed route classes for compile-time safety:
329
+
330
+ ```dart
331
+ @TypedGoRoute<TaskDetailRoute>(path: '/task/:id')
332
+ class TaskDetailRoute extends GoRouteData {
333
+ const TaskDetailRoute({required this.id});
334
+ final String id;
335
+
336
+ @override
337
+ Widget build(BuildContext context, GoRouterState state) =>
338
+ TaskFormScreen(taskId: id);
339
+ }
340
+
341
+ // Navigate:
342
+ // TaskDetailRoute(id: 'abc-123').push(context);
343
+ ```
344
+
345
+ ---
346
+
347
+ ## AppBar Back Behaviour
348
+
349
+ go_router handles back gestures and the AppBar back arrow automatically via
350
+ `canPop()`. Inside a `ShellRoute`, prefer `context.go(<parent>)` over `context.pop()`
351
+ when navigating between top-level tabs.
352
+
353
+ ---
354
+
355
+ ## Route Guards Summary
356
+
357
+ | Guard | Location | Behaviour |
358
+ |---|---|---|
359
+ | Auth required | Top-level `GoRouter.redirect` | Push `/login` when unauthenticated |
360
+ | Role required | Per-route `redirect` callback | Push `/unauthorized` when role missing |
361
+ | Onboarding | Top-level `GoRouter.redirect` | Push `/onboarding` on first launch (Hive flag) |
362
+ | Deep link from FCM | `NotificationService.onMessageOpenedApp` | Push payload `deeplink` via router instance |