@starci/eslint-canon-be 3.0.7 → 3.0.9
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.
- package/CHANGELOG.md +13 -1
- package/README.md +13 -7
- package/ambient-id.mjs +90 -0
- package/cli.mjs +181 -0
- package/comments.mjs +18 -21
- package/config-owner.mjs +20 -4
- package/connections.mjs +12 -12
- package/cookies.mjs +106 -0
- package/cqrs.mjs +22 -26
- package/data-access.mjs +9 -28
- package/default-deny.mjs +2 -1
- package/e2e-flow.mjs +4 -4
- package/event-bus.mjs +237 -0
- package/feature-thin.mjs +237 -0
- package/idempotency.mjs +3 -1
- package/index.mjs +22 -1
- package/infra-owner.mjs +1 -1
- package/injection.mjs +67 -22
- package/input-bounds.mjs +2 -1
- package/jobs.mjs +214 -0
- package/lib/ast.mjs +7 -0
- package/lib/config.mjs +1 -1
- package/lib/db-writes.mjs +1 -1
- package/lib/doors.mjs +81 -0
- package/lib/edition.mjs +45 -0
- package/lib/entity-writes.mjs +35 -0
- package/lib/hfs.mjs +3 -3
- package/lib/path.mjs +0 -6
- package/lib/persistence.mjs +11 -18
- package/lib/ports.mjs +5 -2
- package/lib/specifier.mjs +27 -0
- package/lib/transactions.mjs +37 -0
- package/lib/transport-slots.mjs +8 -3
- package/lib/unit-spec.mjs +63 -2
- package/module-layering.mjs +3 -24
- package/module-shape.mjs +2 -2
- package/naming.mjs +2 -2
- package/package.json +5 -3
- package/project-graph.mjs +8 -5
- package/projections.mjs +117 -0
- package/query-safety.mjs +1 -1
- package/realtime.mjs +181 -0
- package/runtime/engine/config.mjs +494 -0
- package/runtime/engine/invalid-config.mjs +15 -0
- package/runtime/engine/orca-config.mjs +27 -0
- package/runtime/engine/runtime-root.mjs +5 -0
- package/runtime/engine/yaml.mjs +3 -3
- package/runtime/knowledge/hfs/canon-pins.yaml +163 -32
- package/runtime/knowledge/hfs/rules.yaml +2059 -0
- package/runtime/knowledge/hfs/slots.yaml +915 -123
- package/runtime/knowledge/patterns/fe/folder.yaml +133 -27
- package/runtime/knowledge/sonar-gate.yaml +53 -19
- package/runtime/modules/models/registry.yaml +591 -0
- package/runtime/modules/models/runtimes.yaml +701 -0
- package/runtime/packages/hfs/templates/app/package-scripts/package.json +3 -10
- package/runtime/scripts/api/git/config-get.mjs +10 -0
- package/runtime/scripts/api/git/lib.mjs +17 -27
- package/runtime/scripts/api/git/ls-files.mjs +6 -0
- package/runtime/scripts/api/git/recorded-lines.mjs +19 -0
- package/runtime/scripts/api/git/remote.mjs +5 -0
- package/runtime/scripts/api/git/rev-parse-query.mjs +5 -0
- package/runtime/scripts/{lib/hfs-allows.mjs → hfs/allows.mjs} +3 -3
- package/runtime/scripts/hfs/architecture/ast-walks.mjs +220 -0
- package/runtime/scripts/{checks → hfs}/architecture/backend.mjs +17 -24
- package/runtime/scripts/{checks → hfs}/architecture/background-unowned.mjs +16 -34
- package/runtime/scripts/{checks → hfs}/architecture/client-reaches-server.mjs +3 -1
- package/runtime/scripts/{checks → hfs}/architecture/clones.mjs +4 -4
- package/runtime/scripts/{checks → hfs}/architecture/config.mjs +11 -8
- package/runtime/scripts/{checks → hfs}/architecture/connection-map.mjs +21 -9
- package/runtime/scripts/hfs/architecture/context-coupling.mjs +88 -0
- package/runtime/scripts/hfs/architecture/context-map.mjs +237 -0
- package/runtime/scripts/hfs/architecture/context-owner.mjs +82 -0
- package/runtime/scripts/hfs/architecture/context-platform-tables.mjs +47 -0
- package/runtime/scripts/hfs/architecture/context-transaction.mjs +60 -0
- package/runtime/scripts/{checks → hfs}/architecture/contract-fixture-guard.mjs +5 -11
- package/runtime/scripts/{checks → hfs}/architecture/contracts.mjs +33 -162
- package/runtime/scripts/{checks → hfs}/architecture/dead-exports.mjs +58 -29
- package/runtime/scripts/{checks → hfs}/architecture/doc-language.mjs +1 -1
- package/runtime/scripts/{checks → hfs}/architecture/entrypoint.mjs +2 -1
- package/runtime/scripts/{checks → hfs}/architecture/fe-slot-allows.mjs +4 -4
- package/runtime/scripts/{checks → hfs}/architecture/feature-shape.mjs +6 -3
- package/runtime/scripts/{checks → hfs}/architecture/framework-pinned.mjs +1 -1
- package/runtime/scripts/{checks → hfs}/architecture/frontend.mjs +17 -43
- package/runtime/scripts/{checks → hfs}/architecture/hfs-graph.mjs +1 -1
- package/runtime/scripts/{checks → hfs}/architecture/hfs.mjs +27 -42
- package/runtime/scripts/{checks → hfs}/architecture/i18n-keys.mjs +1 -1
- package/runtime/scripts/{checks → hfs}/architecture/index.mjs +17 -4
- package/runtime/scripts/{checks → hfs}/architecture/machine-ast.mjs +44 -11
- package/runtime/scripts/hfs/architecture/managed-scripts.mjs +27 -0
- package/runtime/scripts/{checks → hfs}/architecture/module-per-transport.mjs +30 -6
- package/runtime/scripts/hfs/architecture/next-data-contract.mjs +96 -0
- package/runtime/scripts/{checks → hfs}/architecture/next-data.mjs +40 -168
- package/runtime/scripts/{checks → hfs}/architecture/owners.mjs +35 -15
- package/runtime/scripts/{checks → hfs}/architecture/register-once.mjs +2 -1
- package/runtime/scripts/{checks → hfs}/architecture/registration.mjs +23 -81
- package/runtime/scripts/{checks → hfs}/architecture/required-files.mjs +21 -13
- package/runtime/scripts/{checks → hfs}/architecture/schema-owner.mjs +17 -114
- package/runtime/scripts/hfs/architecture/server-action.mjs +24 -0
- package/runtime/scripts/hfs/architecture/side-boundary.mjs +16 -0
- package/runtime/scripts/{checks → hfs}/architecture/source-names.mjs +27 -147
- package/runtime/scripts/{checks → hfs}/architecture/sql-owner.mjs +59 -18
- package/runtime/scripts/hfs/architecture/sql-returning.mjs +64 -0
- package/runtime/scripts/hfs/architecture/supabase-ast.mjs +111 -0
- package/runtime/scripts/hfs/architecture/supabase-be.mjs +131 -0
- package/runtime/scripts/hfs/architecture/supabase-tables.mjs +42 -0
- package/runtime/scripts/hfs/architecture/supabase.mjs +434 -0
- package/runtime/scripts/{checks → hfs}/architecture/surface.mjs +10 -4
- package/runtime/scripts/{checks → hfs}/architecture/test-world-files.mjs +11 -21
- package/runtime/scripts/{checks → hfs}/architecture/tiers.mjs +47 -5
- package/runtime/scripts/{checks → hfs}/architecture/transport-owner.mjs +3 -3
- package/runtime/scripts/{checks → hfs}/architecture/typescript.mjs +13 -27
- package/runtime/scripts/hfs/declaration-shape.mjs +62 -0
- package/runtime/scripts/hfs/declaration-slots.mjs +75 -0
- package/runtime/scripts/hfs/edition-slots.mjs +66 -0
- package/runtime/scripts/hfs/manifest-shape.mjs +247 -0
- package/runtime/scripts/hfs/param-names.mjs +18 -0
- package/runtime/scripts/{lib/hfs-path-findings.mjs → hfs/path-findings.mjs} +7 -7
- package/runtime/scripts/{lib → hfs}/project-graph.mjs +0 -0
- package/runtime/scripts/{lib → hfs}/project-rule.mjs +3 -3
- package/runtime/scripts/{lib → hfs}/repo-identity.mjs +9 -6
- package/runtime/scripts/hfs/rule-params-shape.mjs +50 -0
- package/runtime/scripts/{lib/hfs-rules → hfs/rules}/fe-no-tests.mjs +6 -5
- package/runtime/scripts/{lib/hfs-rules → hfs/rules}/read.mjs +1 -1
- package/runtime/scripts/{lib/hfs-rules → hfs/rules}/secrets.mjs +4 -4
- package/runtime/scripts/{lib/hfs-rules → hfs/rules}/spec-placement.mjs +1 -1
- package/runtime/scripts/{lib/hfs-slots.mjs → hfs/slots.mjs} +114 -150
- package/runtime/scripts/hfs/test-world-slot.mjs +6 -0
- package/runtime/scripts/{checks → hfs}/typescript-programs.mjs +0 -5
- package/runtime/scripts/{lib/hfs-view.mjs → hfs/view.mjs} +6 -5
- package/runtime/scripts/lib/dockerfile.mjs +124 -0
- package/runtime/scripts/lib/git.mjs +36 -0
- package/runtime/scripts/lib/i18n.mjs +86 -0
- package/runtime/scripts/lib/json.mjs +13 -3
- package/runtime/scripts/lib/language.mjs +26 -7
- package/runtime/scripts/lib/line-count.mjs +9 -0
- package/runtime/scripts/lib/list.mjs +20 -0
- package/runtime/scripts/lib/path-key.mjs +59 -2
- package/runtime/scripts/lib/read-text.mjs +34 -0
- package/runtime/scripts/lib/regex.mjs +4 -0
- package/runtime/scripts/lib/secret-patterns.mjs +4 -3
- package/runtime/scripts/lib/sops-envelope.mjs +58 -0
- package/runtime/scripts/lib/stack-services.mjs +7 -31
- package/runtime/scripts/lib/ts-ast.mjs +35 -0
- package/runtime/scripts/{checks/common.mjs → lib/walk.mjs} +5 -15
- package/schema-authority.mjs +14 -12
- package/service-deps.mjs +7 -13
- package/service-isolation.mjs +72 -0
- package/size-budget.mjs +3 -2
- package/test-world.mjs +5 -4
- package/testing.mjs +27 -24
- package/transport.mjs +12 -9
- package/unit-spec.mjs +1 -1
- package/user-copy.mjs +5 -4
- package/webhooks.mjs +173 -0
- package/runtime/scripts/api/sops/decrypt.mjs +0 -16
- package/runtime/scripts/lib/recorded-lines.mjs +0 -27
- package/runtime/scripts/lib/test-secrets.mjs +0 -116
- /package/runtime/scripts/{checks → hfs}/architecture/config-unread.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/constructor-deps.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/cross-app-duplicate.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/default-deny.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/error-codes.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/error-masked.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/hooks-are-hooks.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/injection-token-exported.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/package-shape.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/reachability.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/route-files-thin.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/sql-tokens.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/symbols.mjs +0 -0
- /package/runtime/scripts/{checks → hfs}/architecture/unit-spec-providers.mjs +0 -0
|
@@ -23,14 +23,16 @@ rules:
|
|
|
23
23
|
- id: FE-FOLDER-1
|
|
24
24
|
title: Responsibility directories
|
|
25
25
|
kind: mandatory
|
|
26
|
-
hfsRules: [R01, R02, R59, R64]
|
|
26
|
+
hfsRules: [R01, R02, R59, R64, R26, R54, R56, R91, R94]
|
|
27
27
|
requirement: |
|
|
28
|
-
The front end of every app (`fe/`) is an fe/apps/<app>/ monorepo even with one app
|
|
29
|
-
|
|
28
|
+
The front end of every app (`fe/`) is an fe/apps/<app>/ monorepo even with one app — each app declared in
|
|
29
|
+
`hfs.json` `sides.fe.apps` with kind `next` (slot `fe.app.next`; the scaffold writes `landing` and `app`) — and all
|
|
30
|
+
product source lives under fe/apps/<app>/src. An fe/src/ does not exist. Each Next source root
|
|
30
31
|
(fe/apps/<app>/src) uses app/ for framework adapters; features/{pages,layouts,overlays} for route-facing product
|
|
31
32
|
composition; components/{blocks,composites,branches,leaves} for product visuals; hooks/<domain> for React hooks;
|
|
32
|
-
and modules/<capability> for cohesive reusable technical and domain capabilities. Every app
|
|
33
|
-
|
|
33
|
+
and modules/<capability> for cohesive reusable technical and domain capabilities. Every app carries the required
|
|
34
|
+
module instances of slot `fe.modules` and one brand.css under modules/brand when it sets brand tokens
|
|
35
|
+
(`fe.modules.brand`). No other empty role
|
|
34
36
|
folder is required. Grammar remains a separate product-agnostic package. The only files that may sit directly in the
|
|
35
37
|
source root (the directory holding app/) are the framework-pinned root files listed in frameworkPinnedRootFiles
|
|
36
38
|
below: Next.js loads them from that exact place. Each is a thin framework adapter whose internal imports enter
|
|
@@ -40,15 +42,14 @@ rules:
|
|
|
40
42
|
fe.source-root-pinned, even though the machine list names it as a file Next loads. Any other file at the source
|
|
41
43
|
root, including a helper folder beside a pinned file, has no owner and is refused.
|
|
42
44
|
frameworkPinnedRootFiles:
|
|
43
|
-
# Machine list read by scripts/
|
|
45
|
+
# Machine list read by scripts/hfs/architecture/framework-pinned.mjs (FE_SOURCE_LAYOUT_INVALID accepts exactly
|
|
44
46
|
# these basenames directly in a Next source root; FE_TIER_DIRECTION keeps them thin). Exact names,
|
|
45
47
|
# case-sensitive, no globs. It lists what the framework loads from the source root. Which of them a repository may
|
|
46
48
|
# keep is decided by the slot fe.source-root-pinned and FE_NEXT_CONVENTIONS, not by this list.
|
|
47
|
-
# Machine list read by scripts/
|
|
49
|
+
# Machine list read by scripts/hfs/architecture/framework-pinned.mjs (FE_SOURCE_LAYOUT_INVALID
|
|
48
50
|
# accepts exactly these basenames directly in a Next source root;
|
|
49
|
-
# their imports follow the FE_TIER_DIRECTION matrix). Exact names, case-sensitive, no globs. Supervisor rulings
|
|
50
|
-
#
|
|
51
|
-
# middleware, listed so the list survives the upgrade).
|
|
51
|
+
# their imports follow the FE_TIER_DIRECTION matrix). Exact names, case-sensitive, no globs. Supervisor rulings
|
|
52
|
+
# (proxy is the Next 16 name of middleware, listed so the list survives the upgrade).
|
|
52
53
|
- middleware.ts
|
|
53
54
|
- middleware.js
|
|
54
55
|
- middleware.mjs
|
|
@@ -82,7 +83,7 @@ rules:
|
|
|
82
83
|
fe/apps/<app>/src/modules/api/ or fe/apps/<app>/src/modules/session/ with one explicit public index.ts entry
|
|
83
84
|
- id: case-3
|
|
84
85
|
when: "A reusable product visual without scenario ownership"
|
|
85
|
-
write: "fe/apps/<app>/src/components/
|
|
86
|
+
write: "an owner folder of slot `fe.components` under the layer it belongs to — for example fe/apps/<app>/src/components/leaves/<Name>/index.tsx"
|
|
86
87
|
- id: case-4
|
|
87
88
|
when: "A React hook"
|
|
88
89
|
write: "fe/apps/<app>/src/hooks/<domain>/useAutoScroll.ts; built-in React hook calls may remain in visuals"
|
|
@@ -94,7 +95,7 @@ rules:
|
|
|
94
95
|
fe/apps/<app>/src/modules/i18n/ and the adapter imports it; the names the framework mandates there
|
|
95
96
|
(frameworkPinnedRootExports, for example export const config = { matcher }) keep their framework spelling
|
|
96
97
|
- id: case-6
|
|
97
|
-
when: "Any other file or folder directly under the source root (
|
|
98
|
+
when: "Any other file or folder directly under the source root (an `i18n/request.ts` or a `config.ts` there), and an fe/src/"
|
|
98
99
|
write: >
|
|
99
100
|
Move it to its owner, for example fe/apps/<app>/src/modules/i18n/request.ts, and point framework configuration
|
|
100
101
|
(fe/apps/<app>/next.config.ts) at the new path
|
|
@@ -106,13 +107,53 @@ rules:
|
|
|
106
107
|
verification:
|
|
107
108
|
automated:
|
|
108
109
|
- HFS_SLOT_UNDECLARED
|
|
110
|
+
- HFS_SLOT_AMBIGUOUS
|
|
111
|
+
- HFS_SLOT_NOT_ENABLED
|
|
112
|
+
- HFS_FORBIDDEN_PRESENT
|
|
113
|
+
- HFS_TRACKED_MUST_BE_IGNORED
|
|
114
|
+
- HFS_ROOT_ENTRY_FORBIDDEN
|
|
115
|
+
- HFS_ROOT_MARKDOWN_FORBIDDEN
|
|
116
|
+
- HFS_ROOT_SRC_FORBIDDEN_FE
|
|
117
|
+
- HFS_SRC_LAYOUT_INVALID
|
|
118
|
+
- HFS_MODULE_TIER_INVALID
|
|
119
|
+
- HFS_WORK_IN_FE
|
|
120
|
+
- HFS_STACKS_IN_SIDE
|
|
109
121
|
- HFS_SLOT_REQUIRED_MISSING
|
|
110
|
-
-
|
|
111
|
-
-
|
|
122
|
+
- HFS_MIN_INSTANCES
|
|
123
|
+
- HFS_REQUIRED_FILE_MISSING
|
|
124
|
+
- HFS_ROOT_ENTRY_MISSING
|
|
125
|
+
- HFS_APPS_REQUIRED
|
|
126
|
+
- HFS_APP_LAYOUT_INVALID
|
|
127
|
+
- HFS_README_TITLE_INVALID
|
|
128
|
+
- HFS_README_DESCRIPTION_INVALID
|
|
129
|
+
- HFS_README_SECTION_MISSING
|
|
130
|
+
- HFS_README_SECTION_ORDER
|
|
131
|
+
- HFS_README_DEVELOPMENT_INCOMPLETE
|
|
132
|
+
- HFS_README_WORK_POINTER_MISSING
|
|
133
|
+
- HFS_README_PRIVATE_URL
|
|
134
|
+
- HFS_README_BADGE_NOT_LIVE
|
|
135
|
+
- FE_I18N_PLACEMENT
|
|
136
|
+
- FE_I18N_NAVIGATION
|
|
137
|
+
- FE_I18N_FORMATTER
|
|
138
|
+
- FE_APP_ISOLATION
|
|
139
|
+
- BE_TIER_DIRECTION
|
|
112
140
|
- FE_TIER_DIRECTION
|
|
141
|
+
- ARCH_PACKAGE_IMPORTS_APP
|
|
142
|
+
- FE_ROUTE_FILES_THIN
|
|
143
|
+
- FE_NEXT_CONVENTIONS
|
|
144
|
+
- FE_PAGE_METADATA_MISSING
|
|
145
|
+
- FE_ROUTE_ONE_PAGE
|
|
146
|
+
- FE_ROUTE_DRAWING_DECISION
|
|
147
|
+
- FE_ROUTE_CLIENT_BOUNDARY
|
|
148
|
+
- FE_ROUTE_CLIENT_HOOK
|
|
149
|
+
- FE_ROUTE_DEFAULT_EXPORT
|
|
150
|
+
- FE_HOOKS_ARE_HOOKS
|
|
113
151
|
- FE_CUSTOM_HOOK_LOCATION
|
|
114
|
-
-
|
|
115
|
-
-
|
|
152
|
+
- FE_BLOCK_PRODUCT_HOOK_DEFINITION
|
|
153
|
+
- FE_COMPONENT_DEEP_HOOK_IMPORT
|
|
154
|
+
- FE_SOURCE_FORM
|
|
155
|
+
- FE_SOURCE_LAYOUT_INVALID
|
|
156
|
+
- FE_SLOT_FILE_ROLE
|
|
116
157
|
manual:
|
|
117
158
|
- Confirm the unit's responsibility and public entry, rather than assigning it by consumer count.
|
|
118
159
|
relatedExamples:
|
|
@@ -121,7 +162,7 @@ rules:
|
|
|
121
162
|
- id: FE-FOLDER-2
|
|
122
163
|
title: Discoverable files for one unit
|
|
123
164
|
kind: mandatory
|
|
124
|
-
hfsRules: [R02, R55, R65]
|
|
165
|
+
hfsRules: [R02, R55, R65, R20, R92]
|
|
125
166
|
requirement: |
|
|
126
167
|
A split unit (a connected block, and a feature page, layout or overlay) uses index.tsx for the connected X and
|
|
127
168
|
sibling component.tsx for the pure XBase, its XBaseProps and xDefaultState, plus XState when the shape is its own union
|
|
@@ -149,12 +190,40 @@ rules:
|
|
|
149
190
|
write: "hooks/<domain>/useX.ts or modules/<capability>/...; do not create visual twins"
|
|
150
191
|
verification:
|
|
151
192
|
automated:
|
|
152
|
-
-
|
|
153
|
-
-
|
|
154
|
-
-
|
|
193
|
+
- HFS_SLOT_REQUIRED_MISSING
|
|
194
|
+
- HFS_MIN_INSTANCES
|
|
195
|
+
- HFS_REQUIRED_FILE_MISSING
|
|
196
|
+
- HFS_ROOT_ENTRY_MISSING
|
|
197
|
+
- HFS_APPS_REQUIRED
|
|
198
|
+
- HFS_APP_LAYOUT_INVALID
|
|
199
|
+
- HFS_README_TITLE_INVALID
|
|
200
|
+
- HFS_README_DESCRIPTION_INVALID
|
|
201
|
+
- HFS_README_SECTION_MISSING
|
|
202
|
+
- HFS_README_SECTION_ORDER
|
|
203
|
+
- HFS_README_DEVELOPMENT_INCOMPLETE
|
|
204
|
+
- HFS_README_WORK_POINTER_MISSING
|
|
205
|
+
- HFS_README_PRIVATE_URL
|
|
206
|
+
- HFS_README_BADGE_NOT_LIVE
|
|
207
|
+
- FE_CLIENT_BOUNDARY
|
|
208
|
+
- FE_CLIENT_SERVER_IMPORT
|
|
209
|
+
- FE_CLIENT_REACHES_SERVER
|
|
210
|
+
- FE_SERVER_ONLY_MARK
|
|
211
|
+
- FE_STORAGE_OUTSIDE_MODULES
|
|
212
|
+
- FE_DANGEROUS_HTML
|
|
155
213
|
- FE_SIZE_AND_STATE_BUDGET
|
|
214
|
+
- FE_LIST_KEY
|
|
215
|
+
- FE_EFFECT_CLEANUP
|
|
216
|
+
- FE_SWALLOWED_ERROR
|
|
217
|
+
- FE_CONSOLE_CALL
|
|
156
218
|
- HFS_SIZE_GROWTH
|
|
157
|
-
-
|
|
219
|
+
- HFS_SIZE_SOFT_BACKLOG
|
|
220
|
+
- FE_COMPONENT_API
|
|
221
|
+
- FE_COMPONENT_WORLD_OWNERSHIP
|
|
222
|
+
- FE_WORLD_OWNER_RENDER_BOUNDARY
|
|
223
|
+
- FE_CONNECTED_BLOCK_RENDER_PAIR
|
|
224
|
+
- FE_PURE_REACHES_DATA
|
|
225
|
+
- FE_PURE_WORLD_HOOK
|
|
226
|
+
- FE_PURE_WORLD_IMPORT
|
|
158
227
|
manual:
|
|
159
228
|
- Confirm each file owns a real responsibility; do not add a component.tsx twin by habit.
|
|
160
229
|
relatedExamples:
|
|
@@ -163,7 +232,7 @@ rules:
|
|
|
163
232
|
- id: FE-FOLDER-3
|
|
164
233
|
title: Route files adapt to one visual owner and every app has its boundaries
|
|
165
234
|
kind: mandatory
|
|
166
|
-
hfsRules: [R53, R54, R55, R57]
|
|
235
|
+
hfsRules: [R53, R54, R55, R57, R26]
|
|
167
236
|
requirement: |
|
|
168
237
|
Route files under app/[locale]/ (page, layout, template, loading, not-found) are server components. A route may
|
|
169
238
|
resolve framework server inputs (params, searchParams, headers, cookies), then mounts one page-level visual owner.
|
|
@@ -192,10 +261,27 @@ rules:
|
|
|
192
261
|
verification:
|
|
193
262
|
automated:
|
|
194
263
|
- FE_ERROR_BOUNDARY_MISSING
|
|
264
|
+
- FE_SUSPENSE_NULL_FALLBACK
|
|
195
265
|
- FE_ROUTE_FILES_THIN
|
|
266
|
+
- FE_NEXT_CONVENTIONS
|
|
267
|
+
- FE_PAGE_METADATA_MISSING
|
|
268
|
+
- FE_ROUTE_ONE_PAGE
|
|
269
|
+
- FE_ROUTE_DRAWING_DECISION
|
|
270
|
+
- FE_ROUTE_CLIENT_BOUNDARY
|
|
271
|
+
- FE_ROUTE_CLIENT_HOOK
|
|
272
|
+
- FE_ROUTE_DEFAULT_EXPORT
|
|
196
273
|
- FE_CLIENT_BOUNDARY
|
|
274
|
+
- FE_CLIENT_SERVER_IMPORT
|
|
275
|
+
- FE_CLIENT_REACHES_SERVER
|
|
276
|
+
- FE_SERVER_ONLY_MARK
|
|
277
|
+
- FE_STORAGE_OUTSIDE_MODULES
|
|
278
|
+
- FE_DANGEROUS_HTML
|
|
197
279
|
- FE_OWNER_REACHABLE
|
|
280
|
+
- FE_ROUTE_HARDCODED
|
|
281
|
+
- FE_HREF_RESOLVES
|
|
282
|
+
- BE_TIER_DIRECTION
|
|
198
283
|
- FE_TIER_DIRECTION
|
|
284
|
+
- ARCH_PACKAGE_IMPORTS_APP
|
|
199
285
|
manual:
|
|
200
286
|
- Confirm visual routes have one page owner and redirect-only routes have no visual tree.
|
|
201
287
|
relatedExamples: []
|
|
@@ -203,7 +289,7 @@ rules:
|
|
|
203
289
|
- id: FE-FOLDER-4
|
|
204
290
|
title: Hooks are hooks; readers and transport live in modules
|
|
205
291
|
kind: mandatory
|
|
206
|
-
hfsRules: [R56, R50, R49]
|
|
292
|
+
hfsRules: [R56, R50, R49, R21, R26]
|
|
207
293
|
requirement: |
|
|
208
294
|
hooks/<domain>/ holds React hooks (use*.ts, one hook per file) and exactly one <domain>.shared.ts for shared
|
|
209
295
|
non-hook helpers of that domain (key builders, token readers). A file in hooks/ that is not a hook and is not the shared
|
|
@@ -235,8 +321,19 @@ rules:
|
|
|
235
321
|
automated:
|
|
236
322
|
- FE_HOOKS_ARE_HOOKS
|
|
237
323
|
- FE_CUSTOM_HOOK_LOCATION
|
|
324
|
+
- FE_BLOCK_PRODUCT_HOOK_DEFINITION
|
|
325
|
+
- FE_COMPONENT_DEEP_HOOK_IMPORT
|
|
326
|
+
- FE_TRANSPORT_OWNER
|
|
327
|
+
- FE_EFFECT_FETCH
|
|
328
|
+
- FE_SWR_KEY_IDENTITY
|
|
329
|
+
- FE_SWR_MUTATION_RESOURCE_IDENTITY
|
|
330
|
+
- FE_ENV_OWNER
|
|
238
331
|
- HFS_DUPLICATE_CODE
|
|
332
|
+
- HFS_DUPLICATE_SYMBOL
|
|
333
|
+
- FE_CROSS_APP_DUPLICATE
|
|
334
|
+
- BE_TIER_DIRECTION
|
|
239
335
|
- FE_TIER_DIRECTION
|
|
336
|
+
- ARCH_PACKAGE_IMPORTS_APP
|
|
240
337
|
manual:
|
|
241
338
|
- Confirm each lifecycle has one feature owner and transport mechanics have one module owner.
|
|
242
339
|
relatedExamples:
|
|
@@ -274,7 +371,7 @@ rules:
|
|
|
274
371
|
- id: FE-FOLDER-6
|
|
275
372
|
title: Keep units cohesive
|
|
276
373
|
kind: mandatory
|
|
277
|
-
hfsRules: [R49, R21]
|
|
374
|
+
hfsRules: [R49, R21, R91, R92]
|
|
278
375
|
requirement: |
|
|
279
376
|
A unit folder contains files that change for the same responsibility. Do not create generic helpers/ or utils/
|
|
280
377
|
buckets inside components, read deployment configuration in presentation, or split files solely to meet a count.
|
|
@@ -301,9 +398,18 @@ rules:
|
|
|
301
398
|
verification:
|
|
302
399
|
automated:
|
|
303
400
|
- FE_ENV_OWNER
|
|
304
|
-
-
|
|
305
|
-
-
|
|
306
|
-
-
|
|
401
|
+
- HFS_DUPLICATE_CODE
|
|
402
|
+
- HFS_DUPLICATE_SYMBOL
|
|
403
|
+
- FE_CROSS_APP_DUPLICATE
|
|
404
|
+
- FE_SOURCE_FORM
|
|
405
|
+
- FE_SOURCE_LAYOUT_INVALID
|
|
406
|
+
- FE_COMPONENT_API
|
|
407
|
+
- FE_COMPONENT_WORLD_OWNERSHIP
|
|
408
|
+
- FE_WORLD_OWNER_RENDER_BOUNDARY
|
|
409
|
+
- FE_CONNECTED_BLOCK_RENDER_PAIR
|
|
410
|
+
- FE_PURE_REACHES_DATA
|
|
411
|
+
- FE_PURE_WORLD_HOOK
|
|
412
|
+
- FE_PURE_WORLD_IMPORT
|
|
307
413
|
manual:
|
|
308
414
|
- Confirm extraction is justified by ownership or lifecycle rather than file length or count.
|
|
309
415
|
relatedExamples: []
|
|
@@ -4,7 +4,7 @@ title: The Sonar quality gate every product is held to
|
|
|
4
4
|
purpose: |
|
|
5
5
|
The one place the Sonar thresholds live. A product repository never restates them: its
|
|
6
6
|
.starcistacks/application-stacks.yaml `services.sonar.qualityGate` names the gate below, and
|
|
7
|
-
scripts/
|
|
7
|
+
scripts/gates/sonar-local.mjs (1) makes the local SonarQube's gate of that name carry exactly these
|
|
8
8
|
conditions and selects it for the project, and (2) judges an op's slice - the lines it changed - against
|
|
9
9
|
the same numbers. Code-writing ops cannot settle done while the slice is red
|
|
10
10
|
(scripts/kernel/sonar-settle.mjs). Changing a number here changes every repository on the next scan.
|
|
@@ -13,16 +13,16 @@ purpose: |
|
|
|
13
13
|
vulnerability, every hotspot reviewed, no duplicated-lines excess, no cognitive-complexity issue). The one Sonar
|
|
14
14
|
mechanism of the HFS canon is packages/hfs/README.md section "Sonar".
|
|
15
15
|
gate:
|
|
16
|
-
name: starci-
|
|
17
|
-
# A project with no new-code baseline judges the whole project as new code
|
|
16
|
+
name: starci-quality
|
|
17
|
+
# A project with no new-code baseline judges the whole project as new code; a fixed
|
|
18
18
|
# window keeps "new code" the recent work on main, so the server gate is passable on a healthy main.
|
|
19
19
|
newCodePeriod: {type: NUMBER_OF_DAYS, value: 30}
|
|
20
20
|
newCode:
|
|
21
|
-
# Coverage of the
|
|
21
|
+
# Coverage of the measured logic files only (the `ruleParams.be.logicRoles` roles of the `coverage: required` slots). The be unit run writes coverage/lcov.info (@starci/jest-preset coverageReporters lcov) and the
|
|
22
22
|
# managed sonar-project.properties imports it (sonar.javascript.lcov.reportPaths=be/coverage/lcov.info) with
|
|
23
|
-
# sonar.coverage.
|
|
24
|
-
#
|
|
25
|
-
# fe/
|
|
23
|
+
# sonar.coverage.exclusions = the complement of the measured files (SonarQube has no coverage inclusions), rendered by starci app sync from the one derivation scripts/hfs/coverage-scope.mjs (be/jest.config.js and codecov.yml
|
|
24
|
+
# are rendered from it too; a hand edit of any of them is R204 HFS_COVERAGE_SCOPE_DRIFT). The feature tier, declaration files, tests and
|
|
25
|
+
# fe/ are never coverage targets, so coverage on these conditions is the coverage of the modules' logic alone.
|
|
26
26
|
coverage:
|
|
27
27
|
metric: new_coverage
|
|
28
28
|
minPercent: 100
|
|
@@ -40,11 +40,11 @@ newCode:
|
|
|
40
40
|
metric: new_security_hotspots_reviewed
|
|
41
41
|
minReviewedPercent: 100
|
|
42
42
|
unreviewedMax: 0
|
|
43
|
-
# The whole code, not only the new code. Every finding of the HFS canon reaches Sonar through ONE entry, `
|
|
43
|
+
# The whole code, not only the new code. Every finding of the HFS canon reaches Sonar through ONE entry, `starci app lint`
|
|
44
44
|
# (packages/hfs, contract changes hfs-sonar-import and hfs-lint-entry), which writes ONE file, reports/lint.sonar.json
|
|
45
|
-
# (`
|
|
45
|
+
# (`starci app lint --sonar reports/lint.sonar.json`), named by sonar.externalIssuesReportPaths; the gate holds the open-issue count of
|
|
46
46
|
# the whole project at zero. The file carries three engines:
|
|
47
|
-
# starci-hfs the repository findings of `
|
|
47
|
+
# starci-hfs the repository findings of `starci app check` (managed files, tree, pins, CI, contracts; the rule id is the finding code)
|
|
48
48
|
# eslint ESLint's json over the repository (the BE and FE canon plugins alike, per-file and project-graph rules)
|
|
49
49
|
# stylelint stylelint's json over the style glob (front ends)
|
|
50
50
|
# The engines share ONE placement rule (a finding on a file Sonar does not index is filed on the first source file); Sonar's own
|
|
@@ -63,9 +63,9 @@ overall:
|
|
|
63
63
|
hotspots:
|
|
64
64
|
metric: security_hotspots_reviewed
|
|
65
65
|
minReviewedPercent: 100
|
|
66
|
-
# The
|
|
67
|
-
# own measure, so one
|
|
68
|
-
# (sonar-local dashboard) although the project average may round to 100. A file outside the
|
|
66
|
+
# The measured files' coverage (see newCode.coverage), overall and per file: with the exclusions in place each measured file is its
|
|
67
|
+
# own measure, so one measured file below 100 fails the slice verdict (sonar-local evaluateSlice) and the dashboard verdict
|
|
68
|
+
# (sonar-local dashboard) although the project average may round to 100. A file outside the scope is never read.
|
|
69
69
|
coverage:
|
|
70
70
|
metric: coverage
|
|
71
71
|
minPercent: 100
|
|
@@ -81,6 +81,40 @@ overall:
|
|
|
81
81
|
cognitiveComplexity:
|
|
82
82
|
rule: typescript:S3776
|
|
83
83
|
via: overall.issues
|
|
84
|
+
# Lite is the same quality policy without a test or coverage world. Readers select this block from hfs.json edition;
|
|
85
|
+
# keeping both gates in this document makes every threshold data, never a branch-local restatement.
|
|
86
|
+
lite:
|
|
87
|
+
gate:
|
|
88
|
+
name: starci-quality-lite
|
|
89
|
+
newCodePeriod: {type: NUMBER_OF_DAYS, value: 30}
|
|
90
|
+
newCode:
|
|
91
|
+
ignoreBelowChangedLines: 20
|
|
92
|
+
duplication:
|
|
93
|
+
metric: new_duplicated_lines_density
|
|
94
|
+
maxPercent: 3
|
|
95
|
+
issues:
|
|
96
|
+
blockingSeverities: [BLOCKER, CRITICAL]
|
|
97
|
+
metrics: {BLOCKER: new_blocker_violations, CRITICAL: new_critical_violations}
|
|
98
|
+
max: 0
|
|
99
|
+
hotspots:
|
|
100
|
+
metric: new_security_hotspots_reviewed
|
|
101
|
+
minReviewedPercent: 100
|
|
102
|
+
unreviewedMax: 0
|
|
103
|
+
overall:
|
|
104
|
+
issues:
|
|
105
|
+
metric: violations
|
|
106
|
+
max: 0
|
|
107
|
+
engines: [starci-hfs, eslint, stylelint]
|
|
108
|
+
types: {bugs: BUG, code_smells: CODE_SMELL, vulnerabilities: VULNERABILITY}
|
|
109
|
+
hotspots:
|
|
110
|
+
metric: security_hotspots_reviewed
|
|
111
|
+
minReviewedPercent: 100
|
|
112
|
+
duplication:
|
|
113
|
+
metric: duplicated_lines_density
|
|
114
|
+
maxPercent: 3
|
|
115
|
+
cognitiveComplexity:
|
|
116
|
+
rule: typescript:S3776
|
|
117
|
+
via: overall.issues
|
|
84
118
|
# The Sonar enforcers of the rule catalog (knowledge/hfs/rules.yaml): the failure code each condition above is the gate of.
|
|
85
119
|
enforces:
|
|
86
120
|
- {rule: R20, code: HFS_SIZE_GROWTH, enforcer: cognitive-complexity, condition: cognitiveComplexity}
|
|
@@ -91,19 +125,19 @@ enforcedOps: [backend.implement, interface.implement, code.refactor]
|
|
|
91
125
|
reasoning: |
|
|
92
126
|
Chosen against the four projects the local server holds on 2026-09-29 (whole-project duplicated lines
|
|
93
127
|
1.6 / 2.1 / 1.7 / 0.0 percent), so new code that meets them is at or below what main already carries.
|
|
94
|
-
coverage 100 on
|
|
95
|
-
100 threshold on
|
|
96
|
-
verdict and the server gate show the number the runner enforces, file by file. Only
|
|
97
|
-
lives there, the thin
|
|
128
|
+
coverage 100 on the measured logic files, overall and new code (owner 2026-10-01): the unit project already fails below its per-file
|
|
129
|
+
100 threshold on the `ruleParams.be.logicRoles` files of the `coverage: required` slots; Sonar imports the same run's lcov with the same scope, so the dashboard, the slice
|
|
130
|
+
verdict and the server gate show the number the runner enforces, file by file. Only the modules' logic counts: business logic
|
|
131
|
+
lives there, the feature tier is thin (R203) and proven by integration and e2e, and the front end has no unit tests.
|
|
98
132
|
duplication 3: the Sonar way value; the worst project today is 2.1, so 3 rejects a real copy-paste block and
|
|
99
133
|
passes ordinary work.
|
|
100
134
|
blocker/critical 0: the two severities that are defects, not style. main carries old debt of both kinds
|
|
101
|
-
(
|
|
135
|
+
(one product repository carries 3 blocker and 137 critical), so the SLICE verdict reads only changed lines and never main's backlog;
|
|
102
136
|
major and lower are reported on the summary and never fail a slice.
|
|
103
137
|
overall issues 0 and overall duplication 3: the server gate is also the owner's definition of done for the HFS canon:
|
|
104
138
|
a repository that carries any open ESLint, stylelint or HFS finding is not green, whatever the age of the line. The
|
|
105
139
|
op slice keeps judging changed lines (an op cannot fix a repository's whole backlog); the dashboard and CI show the
|
|
106
|
-
whole-project condition. Adopting a repository therefore means clearing its imported findings, which `
|
|
140
|
+
whole-project condition. Adopting a repository therefore means clearing its imported findings, which `starci app check`,
|
|
107
141
|
eslint and stylelint already demand at land.
|
|
108
142
|
hotspots 0 unreviewed: a hotspot is a question the author must answer; on changed lines it is answered in the
|
|
109
143
|
same slice.
|