@eltonssouza/development-utility-kit 1.0.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 (137) hide show
  1. package/.claude/agents/analyst.md +198 -0
  2. package/.claude/agents/backend-developer.md +126 -0
  3. package/.claude/agents/brain-keeper.md +229 -0
  4. package/.claude/agents/code-reviewer.md +181 -0
  5. package/.claude/agents/database-engineer.md +94 -0
  6. package/.claude/agents/devops-engineer.md +141 -0
  7. package/.claude/agents/frontend-developer.md +97 -0
  8. package/.claude/agents/gate-keeper.md +118 -0
  9. package/.claude/agents/migrator.md +291 -0
  10. package/.claude/agents/mobile-developer.md +80 -0
  11. package/.claude/agents/n8n-specialist.md +94 -0
  12. package/.claude/agents/product-owner.md +115 -0
  13. package/.claude/agents/qa-engineer.md +232 -0
  14. package/.claude/agents/release-engineer.md +204 -0
  15. package/.claude/agents/scaffold.md +87 -0
  16. package/.claude/agents/security-engineer.md +199 -0
  17. package/.claude/agents/sprint-runner.md +44 -0
  18. package/.claude/agents/stack-resolver.md +84 -0
  19. package/.claude/agents/tech-lead.md +182 -0
  20. package/.claude/agents/update-template.md +54 -0
  21. package/.claude/agents/ux-designer.md +118 -0
  22. package/.claude/settings.json +44 -0
  23. package/.claude/skills/README.md +332 -0
  24. package/.claude/skills/active-project/SKILL.md +129 -0
  25. package/.claude/skills/api-integration-test/SKILL.md +64 -0
  26. package/.claude/skills/auto-test-guard/SKILL.md +237 -0
  27. package/.claude/skills/auto-test-guard/resources/backend-tests.md +20 -0
  28. package/.claude/skills/auto-test-guard/resources/e2e-tests.md +24 -0
  29. package/.claude/skills/auto-test-guard/resources/execution-report.md +49 -0
  30. package/.claude/skills/auto-test-guard/resources/frontend-tests.md +18 -0
  31. package/.claude/skills/auto-test-guard/resources/initial-setup.md +108 -0
  32. package/.claude/skills/auto-test-guard/resources/run-suite.md +48 -0
  33. package/.claude/skills/auto-test-guard/resources/senior-gate.md +19 -0
  34. package/.claude/skills/brain-keeper/SKILL.md +60 -0
  35. package/.claude/skills/brain-keeper/obsidian/app.json +9 -0
  36. package/.claude/skills/brain-keeper/obsidian/appearance.json +4 -0
  37. package/.claude/skills/brain-keeper/obsidian/core-plugins.json +20 -0
  38. package/.claude/skills/brain-keeper/obsidian/daily-notes.json +5 -0
  39. package/.claude/skills/brain-keeper/obsidian/graph.json +32 -0
  40. package/.claude/skills/brain-keeper/obsidian/snippets/folder-colors.css +90 -0
  41. package/.claude/skills/brain-keeper/obsidian/templates.json +5 -0
  42. package/.claude/skills/brain-keeper/templates/README.md +51 -0
  43. package/.claude/skills/brain-keeper/templates/adr.md +40 -0
  44. package/.claude/skills/brain-keeper/templates/bug.md +35 -0
  45. package/.claude/skills/brain-keeper/templates/daily.md +38 -0
  46. package/.claude/skills/brain-keeper/templates/feature.md +62 -0
  47. package/.claude/skills/brain-keeper/templates/meeting.md +34 -0
  48. package/.claude/skills/brain-keeper/templates/tech-debt.md +21 -0
  49. package/.claude/skills/caveman/SKILL.md +187 -0
  50. package/.claude/skills/create-stack-pack/SKILL.md +281 -0
  51. package/.claude/skills/grill-me/SKILL.md +79 -0
  52. package/.claude/skills/honcho-memory/SKILL.md +207 -0
  53. package/.claude/skills/honcho-memory/docs/api-endpoints-verified.md +75 -0
  54. package/.claude/skills/honcho-memory/hooks/on-prompt-submit.js +221 -0
  55. package/.claude/skills/honcho-memory/hooks/on-stop.js +193 -0
  56. package/.claude/skills/honcho-memory/lib/honcho-client.js +363 -0
  57. package/.claude/skills/honcho-memory/lib/memory-injector.js +93 -0
  58. package/.claude/skills/honcho-memory/package.json +32 -0
  59. package/.claude/skills/honcho-memory/scripts/cli.js +370 -0
  60. package/.claude/skills/honcho-memory/scripts/setup.js +109 -0
  61. package/.claude/skills/honcho-memory/tests/t001-api-endpoints-verified.test.js +89 -0
  62. package/.claude/skills/honcho-memory/tests/t002-structure.test.js +97 -0
  63. package/.claude/skills/honcho-memory/tests/t003-honcho-client.test.js +162 -0
  64. package/.claude/skills/honcho-memory/tests/t004-soft-delete.test.js +259 -0
  65. package/.claude/skills/honcho-memory/tests/t005-memory-injector.test.js +175 -0
  66. package/.claude/skills/honcho-memory/tests/t006-on-prompt-submit.test.js +215 -0
  67. package/.claude/skills/honcho-memory/tests/t007-on-stop.test.js +165 -0
  68. package/.claude/skills/honcho-memory/tests/t008-cli.test.js +214 -0
  69. package/.claude/skills/honcho-memory/tests/t009-setup.test.js +232 -0
  70. package/.claude/skills/honcho-memory/tests/t010-skill-md.test.js +114 -0
  71. package/.claude/skills/honcho-memory/tests/t011-settings-hooks.test.js +105 -0
  72. package/.claude/skills/honcho-memory/tests/t012-docs-update.test.js +106 -0
  73. package/.claude/skills/honcho-memory/tests/t013-smoke-e2e.test.js +90 -0
  74. package/.claude/skills/pair-debug/SKILL.md +288 -0
  75. package/.claude/skills/prd-ready-check/SKILL.md +58 -0
  76. package/.claude/skills/project-manager/SKILL.md +167 -0
  77. package/.claude/skills/quality-standards/SKILL.md +201 -0
  78. package/.claude/skills/quick-feature/SKILL.md +264 -0
  79. package/.claude/skills/run-sprint/SKILL.md +342 -0
  80. package/.claude/skills/scaffold/SKILL.md +58 -0
  81. package/.claude/skills/stack-discovery/SKILL.md +159 -0
  82. package/.claude/skills/test-coverage-auditor/SKILL.md +59 -0
  83. package/.claude/skills/to-issues/SKILL.md +163 -0
  84. package/.claude/skills/to-prd/SKILL.md +130 -0
  85. package/.claude/skills/update-template/SKILL.md +254 -0
  86. package/.claude/stacks/CODEOWNERS +30 -0
  87. package/.claude/stacks/README.md +88 -0
  88. package/.claude/stacks/_template.md +116 -0
  89. package/.claude/stacks/java/spring-boot-3.md +376 -0
  90. package/.claude/stacks/java/spring-boot-4.md +438 -0
  91. package/.claude/stacks/typescript/angular-18.md +420 -0
  92. package/.claude/stacks/typescript/angular-19.md +397 -0
  93. package/.claude/stacks/typescript/angular-21.md +494 -0
  94. package/CLAUDE.md +453 -0
  95. package/README.md +391 -0
  96. package/bin/cli.js +773 -0
  97. package/bin/lib/backup.js +62 -0
  98. package/bin/lib/detect-stack.js +476 -0
  99. package/bin/lib/help.js +233 -0
  100. package/bin/lib/identity.js +108 -0
  101. package/bin/lib/local-dir.js +69 -0
  102. package/bin/lib/manifest.js +236 -0
  103. package/bin/lib/sync-all.js +394 -0
  104. package/bin/lib/version-check.js +398 -0
  105. package/dashboard/db.js +199 -0
  106. package/dashboard/package.json +22 -0
  107. package/dashboard/public/app.js +709 -0
  108. package/dashboard/public/content/docs/agents-reference.en.md +911 -0
  109. package/dashboard/public/content/docs/architecture-overview.en.md +260 -0
  110. package/dashboard/public/content/docs/autonomy-matrix.en.md +186 -0
  111. package/dashboard/public/content/docs/git-flow.en.md +525 -0
  112. package/dashboard/public/content/docs/honcho-memory.en.md +394 -0
  113. package/dashboard/public/content/docs/hooks-reference.en.md +420 -0
  114. package/dashboard/public/content/docs/pipeline.en.md +400 -0
  115. package/dashboard/public/content/docs/quality-gate.en.md +315 -0
  116. package/dashboard/public/content/docs/skills-reference.en.md +500 -0
  117. package/dashboard/public/content/docs/stack-rules.en.md +362 -0
  118. package/dashboard/public/content/docs/troubleshooting.en.md +637 -0
  119. package/dashboard/public/content/manifest.json +102 -0
  120. package/dashboard/public/content/manual/backend.en.md +1138 -0
  121. package/dashboard/public/content/manual/existing-project.en.md +831 -0
  122. package/dashboard/public/content/manual/frontend.en.md +1065 -0
  123. package/dashboard/public/content/manual/fullstack.en.md +1508 -0
  124. package/dashboard/public/content/manual/mobile.en.md +866 -0
  125. package/dashboard/public/index.html +108 -0
  126. package/dashboard/public/style.css +610 -0
  127. package/dashboard/public/vendor/marked.min.js +69 -0
  128. package/dashboard/rtk.js +143 -0
  129. package/dashboard/server-app.js +403 -0
  130. package/dashboard/server.js +104 -0
  131. package/dashboard/test/sprint1.test.js +406 -0
  132. package/dashboard/test/sprint2.test.js +571 -0
  133. package/dashboard/test/sprint3.test.js +560 -0
  134. package/package.json +33 -0
  135. package/scripts/hooks/subagent-telemetry.sh +14 -0
  136. package/scripts/hooks/telemetry-writer.js +250 -0
  137. package/scripts/latest-versions.json +56 -0
@@ -0,0 +1,397 @@
1
+ ---
2
+ stack: typescript/angular-19
3
+ versions_covered: "19.0.x — 19.2.x"
4
+ last_validated: 2026-05-27
5
+ validated_against: "sandbox — Angular 19.1.3 (mid-cycle maintenance)"
6
+ status: active
7
+ pack_owner: "@elton"
8
+ security_review: 2026-05-27
9
+ next_review_due: 2027-05-27
10
+ ---
11
+
12
+ # Angular 19.x (TypeScript 5.5)
13
+
14
+ Knowledge pack for projects on Angular 19.x (released Nov/2024). Covers projects in **legacy maintenance** mode — new features should target `angular-21.md`. Angular 19 introduced Resource API, Signal Forms (preview), `linkedSignal()`, stable `effect()`, and the `output()` function.
15
+
16
+ ## 1. When to use this pack
17
+
18
+ - Project declares `Frontend stack: Angular 19.x` in `## Project Identity`.
19
+ - `package.json` declares `@angular/core: ^19.0.0` through `^19.2.x`.
20
+ - For Angular 18 projects: use `angular-18.md`.
21
+ - For Angular 21+ greenfield: use `angular-21.md`. This pack is for **maintained legacy** that has not yet jumped to 21.
22
+
23
+ ## 2. Stack baseline (what this pack assumes)
24
+
25
+ | Component | Version range | Notes |
26
+ |---|---|---|
27
+ | Angular | 19.0.x — 19.2.x | Released Nov/2024; LTS through May/2026 |
28
+ | Node.js | 20.x LTS (min) / 22.x LTS preferred | Node 18 dropped in Angular 19 |
29
+ | TypeScript | 5.5.x — 5.6.x | TS 5.7 not yet supported in 19 |
30
+ | RxJS | 7.8.x | RxJS only for HTTP/streams; signals for local state |
31
+ | ng-bootstrap | 18.x | Compatible with Angular 19 |
32
+ | Jest | 29.x + jest-preset-angular 14.x | Karma deprecated; Jest is default |
33
+ | @testing-library/angular | 17.x | Component testing — query by role/text |
34
+ | Playwright | 1.48+ | E2E + browser-based a11y scan |
35
+ | @axe-core/playwright | 4.10+ | E2E a11y per ADR-007 |
36
+ | jest-axe | 9.x | Component-level a11y per ADR-007 |
37
+ | @lhci/cli | 0.14+ | Lighthouse budget per ADR-007 |
38
+ | Zone.js | OPTIONAL (zoneless viable in 19) | Zoneless more stable than 18 — evaluate per project |
39
+
40
+ ## 3. Project structure
41
+
42
+ ```
43
+ frontend/
44
+ ├── src/app/
45
+ │ ├── core/ ← auth, http interceptors, guards (CanMatchFn)
46
+ │ ├── shared/ ← reusable standalone components, pipes, directives
47
+ │ ├── features/ ← lazy-loaded feature folders (each with routes.ts)
48
+ │ └── app.routes.ts
49
+ ├── src/environments/ ← environment.ts, environment.prod.ts
50
+ ├── src/styles/ ← global tokens, theme.scss
51
+ ├── src/assets/
52
+ └── angular.json
53
+ ```
54
+
55
+ **Rules**: 3 physical files per component (TS + HTML + SCSS — see §4). Standalone is default; NgModules forbidden for new code. Lazy load every feature.
56
+
57
+ ## 4. Code patterns
58
+
59
+ ### Component — 3 separate files (HARD RULE, ADR-008+)
60
+
61
+ `product-list.component.ts`:
62
+
63
+ ```typescript
64
+ import { Component, ChangeDetectionStrategy, inject, resource } from '@angular/core';
65
+ import { CommonModule } from '@angular/common';
66
+ import { firstValueFrom } from 'rxjs';
67
+ import { ProductService } from './product.service';
68
+
69
+ @Component({
70
+ selector: 'app-product-list',
71
+ standalone: true,
72
+ imports: [CommonModule],
73
+ changeDetection: ChangeDetectionStrategy.OnPush,
74
+ templateUrl: './product-list.component.html',
75
+ styleUrl: './product-list.component.scss',
76
+ })
77
+ export class ProductListComponent {
78
+ private svc = inject(ProductService);
79
+
80
+ // Resource API (NEW in 19) — automatic loading/error state
81
+ productsResource = resource({
82
+ loader: () => firstValueFrom(this.svc.list()),
83
+ });
84
+ }
85
+ ```
86
+
87
+ `product-list.component.html`:
88
+
89
+ ```html
90
+ @if (productsResource.isLoading()) {
91
+ <p>Loading...</p>
92
+ } @else if (productsResource.error()) {
93
+ <p class="error">{{ productsResource.error()?.message }}</p>
94
+ } @else {
95
+ <ul>
96
+ @for (p of productsResource.value(); track p.id) {
97
+ <li>{{ p.name }}</li>
98
+ } @empty {
99
+ <li>No products.</li>
100
+ }
101
+ </ul>
102
+ }
103
+ ```
104
+
105
+ `product-list.component.scss`:
106
+
107
+ ```scss
108
+ .error { color: var(--color-error); }
109
+ ```
110
+
111
+ **Rule**: NEVER inline `template:` or `styles:` in the `.ts`. No size threshold. No "small component" exception. `code-reviewer` / `tech-lead` blocks the merge on violation.
112
+
113
+ ### Resource API (NEW in 19)
114
+
115
+ ```typescript
116
+ // reactive params + auto reload when params change
117
+ productsResource = resource({
118
+ request: () => ({ category: this.category() }),
119
+ loader: ({ request }) => firstValueFrom(this.svc.list(request.category)),
120
+ });
121
+
122
+ // rxResource for cold observables
123
+ detail = rxResource({
124
+ request: () => this.id(),
125
+ loader: ({ request }) => this.svc.get(request),
126
+ });
127
+ ```
128
+
129
+ **Rule**: prefer `resource()` over manual `signal<{loading,data,error}>` shapes. Replaces ad-hoc loading flags.
130
+
131
+ ### Signal Forms (NEW in 19 — preview)
132
+
133
+ ```typescript
134
+ import { signalForm, control } from '@angular/forms';
135
+ import { required, maxLength, email } from '@angular/forms/validators';
136
+
137
+ form = signalForm({
138
+ name: control('', { validators: [required, maxLength(120)] }),
139
+ email: control('', { validators: [required, email] }),
140
+ });
141
+
142
+ submit() {
143
+ if (this.form.valid()) {
144
+ this.svc.create(this.form.value()).subscribe();
145
+ }
146
+ }
147
+ ```
148
+
149
+ **Note**: Signal Forms API still evolving in 19. Projects may prefer typed Reactive Forms (`FormBuilder.nonNullable.group`) until 21 stabilizes. Document trade-off in the project's `tech-debt.md`.
150
+
151
+ ### Output function (NEW in 19) — replaces `@Output` decorator
152
+
153
+ ```typescript
154
+ // ❌ Legacy
155
+ @Output() saved = new EventEmitter<Product>();
156
+
157
+ // ✅ Angular 19
158
+ saved = output<Product>();
159
+
160
+ // emit:
161
+ this.saved.emit(product);
162
+ ```
163
+
164
+ Migration tool: `ng generate @angular/core:output-migration`.
165
+
166
+ ### linkedSignal — derived but mutable
167
+
168
+ ```typescript
169
+ // derived value that can be overridden by user
170
+ total = linkedSignal(() => this.items().reduce((s, i) => s + i.price, 0));
171
+
172
+ // allow manual override:
173
+ overrideTotal(v: number) { this.total.set(v); }
174
+ ```
175
+
176
+ ### Effect (stable in 19)
177
+
178
+ ```typescript
179
+ constructor() {
180
+ effect(() => {
181
+ console.log('Cart size:', this.items().length);
182
+ });
183
+ }
184
+ ```
185
+
186
+ **Rule**: never trigger HTTP in `effect()` — use Resource API. Effects for logging, persistence, DOM side effects only.
187
+
188
+ ### Service with typed HttpClient + interceptor
189
+
190
+ ```typescript
191
+ @Injectable({ providedIn: 'root' })
192
+ export class ProductService {
193
+ private http = inject(HttpClient);
194
+ private base = '/api/v1/products';
195
+
196
+ list(category?: string): Observable<Product[]> {
197
+ const params = category ? new HttpParams().set('category', category) : undefined;
198
+ return this.http.get<Product[]>(this.base, { params });
199
+ }
200
+
201
+ create(req: CreateProductRequest): Observable<Product> {
202
+ return this.http.post<Product>(this.base, req);
203
+ }
204
+ }
205
+
206
+ // core/auth.interceptor.ts (functional)
207
+ export const authInterceptor: HttpInterceptorFn = (req, next) => {
208
+ const token = inject(AuthStore).token();
209
+ return token ? next(req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })) : next(req);
210
+ };
211
+ ```
212
+
213
+ ### Guards (CanMatchFn — functional)
214
+
215
+ ```typescript
216
+ export const authGuard: CanMatchFn = () => {
217
+ const auth = inject(AuthStore);
218
+ const router = inject(Router);
219
+ return auth.isLoggedIn() || router.createUrlTree(['/login']);
220
+ };
221
+
222
+ // app.routes.ts
223
+ {
224
+ path: 'admin',
225
+ canMatch: [authGuard],
226
+ loadChildren: () => import('./features/admin/admin.routes'),
227
+ }
228
+ ```
229
+
230
+ ## 5. Testing
231
+
232
+ ### Component (Jest + Testing Library)
233
+
234
+ ```typescript
235
+ import { render, screen } from '@testing-library/angular';
236
+ import { of } from 'rxjs';
237
+ import { ProductListComponent } from './product-list.component';
238
+ import { ProductService } from './product.service';
239
+
240
+ test('resource loads and renders products', async () => {
241
+ await render(ProductListComponent, {
242
+ providers: [
243
+ { provide: ProductService, useValue: { list: () => of([{ id: '1', name: 'widget' }]) } },
244
+ ],
245
+ });
246
+ expect(await screen.findByText('widget')).toBeVisible();
247
+ });
248
+ ```
249
+
250
+ ### A11y component (jest-axe — per ADR-007)
251
+
252
+ ```typescript
253
+ import { axe, toHaveNoViolations } from 'jest-axe';
254
+ expect.extend(toHaveNoViolations);
255
+
256
+ test('has no a11y violations', async () => {
257
+ const { container } = await render(ProductListComponent, { providers: [...] });
258
+ expect(await axe(container)).toHaveNoViolations();
259
+ });
260
+ ```
261
+
262
+ Threshold: 0 `serious` / 0 `critical` (ADR-007).
263
+
264
+ ### E2E (Playwright + axe-core)
265
+
266
+ ```typescript
267
+ import { test, expect } from '@playwright/test';
268
+ import AxeBuilder from '@axe-core/playwright';
269
+
270
+ test('product list is accessible', async ({ page }) => {
271
+ await page.goto('/products');
272
+ await expect(page.getByRole('list')).toBeVisible();
273
+ const results = await new AxeBuilder({ page }).analyze();
274
+ expect(results.violations.filter(v => ['serious', 'critical'].includes(v.impact!))).toEqual([]);
275
+ });
276
+ ```
277
+
278
+ ### Pyramid ratio (ADR-007)
279
+
280
+ E2E ≤ 30% of total tests (hard-fail above; ideal ≤ 15%). `auto-test-guard` counts and blocks on violation.
281
+
282
+ ## 6. Build & run commands
283
+
284
+ ```bash
285
+ npm install
286
+ npm start # ng serve, port 4200
287
+ npm run build -- --configuration=production # prod build
288
+ npm test -- --watchAll=false --coverage # Jest + coverage
289
+ npx playwright test # E2E
290
+ npx playwright test --ui # E2E with UI
291
+ npx lhci autorun # Lighthouse budget
292
+ npx ng update @angular/core@19 @angular/cli@19 # safe within-major updates
293
+ npm audit --audit-level=high # CVE scan
294
+ ```
295
+
296
+ ## 7. Security (per ADR-007 + ADR-027)
297
+
298
+ ### 7.1 Authentication & Authorization
299
+
300
+ - **JWT** stored in `httpOnly` cookie (preferred) OR in-memory signal (NEVER `localStorage` for tokens — XSS-vulnerable).
301
+ - **Functional `HttpInterceptorFn`** attaches `Authorization: Bearer <token>` per request.
302
+ - **Route guards**: `CanMatchFn` for lazy-load gates (prevents bundle download for unauthorized users); `CanActivateFn` for runtime checks.
303
+ - **Refresh token flow**: silent renewal via interceptor on 401 + retry.
304
+
305
+ ### 7.2 CORS
306
+
307
+ Backend responsibility — Angular only consumes. NEVER request `*` from backend. Allowed origins must be the production app's origin only.
308
+
309
+ ### 7.3 Validation & XSS
310
+
311
+ - Angular auto-escapes interpolation `{{ value }}` — safe by default.
312
+ - **NEVER** `[innerHTML]="userInput"` without `DomSanitizer.bypassSecurityTrustHtml(...)` (and even then, audit the source).
313
+ - **NEVER** `eval()` or `Function()` with user input.
314
+ - Signal Forms validators are typed natively in 19 — fewer cast errors.
315
+ - Sanitize file uploads on the backend (MIME + extension + content scan).
316
+
317
+ ### 7.4 Secrets management
318
+
319
+ - NEVER commit API keys, OAuth client secrets, or tokens to `src/environments/*.ts`.
320
+ - Use build-time injection via CI env vars: `ng build --define environment.apiKey="$API_KEY"`.
321
+ - For runtime config: `/assets/config.json` fetched on bootstrap (not committed).
322
+ - Local dev: `environment.local.ts` in `.gitignore`.
323
+
324
+ ### 7.5 Rate limiting
325
+
326
+ Backend responsibility. Frontend SHOULD debounce search inputs and disable submit buttons during in-flight requests to avoid spamming:
327
+
328
+ ```typescript
329
+ search = signal('');
330
+ debouncedSearch = toSignal(toObservable(this.search).pipe(debounceTime(300)));
331
+ ```
332
+
333
+ ### 7.6 OWASP Top 10 mapping
334
+
335
+ | OWASP | Mitigation in this stack |
336
+ |---|---|
337
+ | A01 Broken Access Control | Route guards (`CanMatchFn`) + backend re-checks; never trust frontend RBAC |
338
+ | A02 Cryptographic Failures | TLS 1.3; tokens in `httpOnly` cookies or memory; no plaintext in `localStorage` |
339
+ | A03 Injection | Angular auto-escape; `DomSanitizer` for trusted HTML; backend parameterized queries |
340
+ | A04 Insecure Design | ADR for new auth/payment flows; threat-model lazy routes |
341
+ | A05 Security Misconfiguration | CSP header from backend; `ng build --configuration=production` strips dev hooks |
342
+ | A06 Vulnerable Components | `npm audit --audit-level=high` in CI; Renovate/Dependabot; `ng update` per minor |
343
+ | A07 Auth Failures | Generic error messages; rate-limit handled by backend; MFA flow respects standard `oauth2-pkce` |
344
+ | A08 Data Integrity | SRI for CDN scripts; signed build artifacts; verify lockfile in CI |
345
+ | A09 Logging Failures | Browser console scrubbed in prod; never log JWT/PII; structured logs forwarded to backend |
346
+ | A10 SSRF | N/A frontend-direct; ensure backend allowlists outbound URLs |
347
+
348
+ ### 7.7 LGPD specifics
349
+
350
+ - Cookie consent banner before any non-essential cookie/analytics.
351
+ - Right to deletion: UI flow that triggers backend soft-delete + email confirmation.
352
+ - Data subject access: profile page exports user data as JSON via signed link.
353
+ - PII fields tagged in forms (e.g. `data-pii="true"`) so analytics can suppress them.
354
+
355
+ ## 8. Anti-patterns (block in code-review)
356
+
357
+ | ❌ Bad | ✅ Good | Why |
358
+ |---|---|---|
359
+ | `template: '<div>...'` or `styles: [...]` inline in `.ts` | 3 separate files (`.ts` + `.html` + `.scss`) | Hard rule — non-negotiable (ADR-008) |
360
+ | `@Output() x = new EventEmitter()` (new code) | `x = output<T>()` | Function API; decorator deprecated in roadmap |
361
+ | `any` in TypeScript | Explicit type or `unknown` + narrow | TS strict mode |
362
+ | Manual `loading`/`error`/`data` signals | `resource()` / `rxResource()` | Built-in state machine |
363
+ | NgModule for new feature | `standalone: true` component + `loadChildren` route | Standalone is default since 17 |
364
+ | `ChangeDetectionStrategy.Default` | `ChangeDetectionStrategy.OnPush` | Required for signal-based change detection |
365
+ | `signal().push(item)` (mutation) | `signal.update(arr => [...arr, item])` | Signals require new reference |
366
+ | `[innerHTML]="userInput"` raw | `DomSanitizer.sanitize(SecurityContext.HTML, x)` | XSS risk |
367
+ | Token in `localStorage` | `httpOnly` cookie or in-memory signal | XSS-stealable |
368
+ | RxJS for local component state | Signals | RxJS overhead unnecessary for state |
369
+ | `*ngIf` / `*ngFor` (legacy) | `@if` / `@for` (built-in control flow) | Type-safer + tree-shakable |
370
+ | Zone.js for greenfield (in 19) | Evaluate zoneless (`provideExperimentalZonelessChangeDetection`) | Smaller bundle, more stable in 19 |
371
+ | `effect()` triggering HTTP | `resource()` / explicit `subscribe` | Effects are for side effects, not data fetch |
372
+
373
+ ## 9. Migration hints — Angular 19 → 21
374
+
375
+ When migrating a project from this pack to `angular-21.md`:
376
+
377
+ - **Skip Angular 20** (released ~May/2025) if practical — jumping 19 → 21 is supported via two consecutive `ng update` runs. Read each release's breaking changes.
378
+ - **Resource API matures** — `request` / `loader` signatures stabilize; some 19-preview options may rename.
379
+ - **Signal Forms** leave preview — APIs from 19 may need rename (`signalForm` → final shape). Run `ng update` migration schematics.
380
+ - **Server Components** exit experimental — may be adopted for new pages.
381
+ - **esbuild builder** becomes default for all new projects (already opt-in in 19).
382
+ - **Zoneless** likely default in 21 — audit any code relying on `NgZone.run`.
383
+ - **TypeScript** moves to 5.7+ — review `tsconfig.strict` deltas.
384
+ - Use the `migrator` agent — it knows both packs and produces an ADR per major cross.
385
+
386
+ ## 10. References
387
+
388
+ - ADR-007 (Senior+ gate thresholds — a11y, Lighthouse, pyramid)
389
+ - ADR-026 (Generic agents + packs architecture)
390
+ - ADR-027 (This pack's governance — frontmatter, security review cadence)
391
+ - ADR-029 (Canonical pack format)
392
+ - Angular 19 release notes: https://blog.angular.dev/meet-angular-v19-7b29dfd05b84
393
+ - Angular Update Guide: https://update.angular.io/
394
+ - Signal Forms RFC: https://github.com/angular/angular/discussions/53485
395
+ - Resource API docs: https://angular.dev/guide/signals/resource
396
+ - OWASP Top 10 (2021): https://owasp.org/Top10/
397
+ - OWASP Angular Cheat Sheet: https://cheatsheetseries.owasp.org/cheatsheets/AngularJS_Security_Cheat_Sheet.html