Skip to content

Commit e8a8ef7

Browse files
authored
Add copilot-instructions and fix-audit-vulnerabilities skill (#181)
1 parent aa9bab6 commit e8a8ef7

5 files changed

Lines changed: 465 additions & 0 deletions

File tree

.changeset/nine-falcons-fix.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
---
3+
4+
Add copilot instructions and fix-audit skill

.github/copilot-instructions.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# GitHub Copilot Instructions — iTwin Saved Views
2+
3+
## Project Overview
4+
5+
This repository publishes two iTwin Platform npm packages — [`@itwin/saved-views-client`](https://www.npmjs.com/package/@itwin/saved-views-client) and [`@itwin/saved-views-react`](https://www.npmjs.com/package/@itwin/saved-views-react) — along with private test applications used for local development. See the [README](../README.md) for a full project overview.
6+
7+
## Development Setup
8+
9+
```shell
10+
# Install all workspace dependencies (pnpm required; npm is blocked)
11+
npx pnpm install
12+
13+
# Start the test app (frontend on http://localhost:7948 + backend, with hot reload)
14+
pnpm start
15+
```
16+
17+
To enable iTwin Platform features in the test app, configure [`packages/test-app-frontend/.env`](../packages/test-app-frontend/.env).
18+
19+
> **Running commands on Windows**: The default PowerShell execution policy blocks npm scripts. Use either `cmd /c "cd /d <repo-root> && <command>"` or `powershell -ExecutionPolicy Bypass -Command "<command>"`. The `cmd /c` form is preferred — it requires no policy flag and stdout/stderr are both captured cleanly when you append `2>&1`.
20+
21+
## Available Commands
22+
23+
All commands run from the **repository root** unless otherwise noted.
24+
25+
| Command | Description |
26+
|---|---|
27+
| `pnpm start` | Start both test apps concurrently with hot reload |
28+
| `pnpm run build` | Build all published packages and test app frontend (parallel) |
29+
| `pnpm test` | Run all tests (Vitest) |
30+
| `pnpm run cover` | Run tests and generate a coverage report |
31+
| `pnpm run lint` | Run ESLint on all `src/` and `test/` TypeScript files (CI enforces `--max-warnings 0`) |
32+
| `pnpm run typecheck` | Type-check all packages (parallel) |
33+
| `pnpm audit` | Check all dependencies for known vulnerabilities |
34+
| `pnpm changeset` | Add a changeset for a public API or behavior change |
35+
| `pnpm changeset --empty` | Add an empty changeset for docs or internal-only changes |
36+
37+
## Package Architecture
38+
39+
| Package | Published | Purpose |
40+
|---|---|---|
41+
| [`saved-views-client`](../packages/saved-views-client/) |`@itwin/saved-views-client` | TypeScript client for the iTwin Platform Saved Views REST API. Dual ESM + CJS output. |
42+
| [`saved-views-react`](../packages/saved-views-react/) |`@itwin/saved-views-react` | React 18 components and utilities (`SavedViewTile`, `TileGrid`, `captureSavedViewData`, `applySavedView`). ESM only. |
43+
| [`test-app-frontend`](../packages/test-app-frontend/) | ❌ private | Vite + React dev/demo app. Runs on `http://localhost:7948`. |
44+
| [`test-app-backend`](../packages/test-app-backend/) | ❌ private | Express + iTwin iModels backend supporting the test app. |
45+
46+
## Code Style & Conventions
47+
48+
### Copyright Header
49+
50+
Every source file must begin with this header:
51+
52+
```ts
53+
/*---------------------------------------------------------------------------------------------
54+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
55+
* See LICENSE.md in the project root for license terms and full copyright notice.
56+
*--------------------------------------------------------------------------------------------*/
57+
```
58+
59+
### File Naming
60+
61+
- **React component files**: PascalCase — `SavedViewTile.tsx`, `SavedViewTileContext.tsx`
62+
- **Utility, hook, and function files**: camelCase — `applySavedView.ts`, `useSavedViews.tsx`, `utils.ts`
63+
- **Class files**: PascalCase — `ITwinSavedViewsClient.ts`
64+
- **Model and type files**: PascalCase — `SavedView.ts`
65+
- **Folders containing a component**: PascalCase — `SavedViewTile/`, `TileGrid/`
66+
- **Folders for utilities or groupings**: camelCase — `translation/`
67+
- **Barrel files**: always `index.ts`
68+
69+
### Naming Conventions
70+
71+
- **Components, classes, types, interfaces, enums**: PascalCase
72+
- **Interface names do NOT use an `I` prefix** — use `SavedViewTileProps`, not `ISavedViewTileProps`
73+
- **Functions, variables, React hooks**: camelCase
74+
- **Module-level constants**: camelCase — `modelClipGroupMappings`, not `MODEL_CLIP_GROUP_MAPPINGS`
75+
- **Enum members**: PascalCase — `RenderMode.SmoothShade`
76+
- **Unused parameters**: prefix with `_``_unused`
77+
78+
### Import Conventions
79+
80+
- Use `import type { ... }` for all type-only imports:
81+
```ts
82+
import type { SavedView, SavedViewTag } from "../SavedView.js";
83+
```
84+
- All internal imports use the **`.js` extension** even though source files are `.ts`/`.tsx`:
85+
```ts
86+
import { SavedViewTile } from "./SavedViewTile.js";
87+
```
88+
- Use `export type { ... }` when re-exporting types from barrel files.
89+
90+
### React Component Style
91+
92+
- Exported components use **named function declarations**, not arrow functions:
93+
```ts
94+
export function SavedViewTile(props: SavedViewTileProps): ReactElement { ... }
95+
```
96+
- Always specify **explicit return types** on exported functions.
97+
- Define the props interface directly above the component it belongs to.
98+
- Document public exported APIs and component props with JSDoc `/** */` comments.
99+
100+
### ESLint Rules Agents Must Not Violate
101+
102+
The following are the most common rules that can produce lint failures. CI enforces **zero warnings**:
103+
104+
- Prefix unused variables and parameters with `_`
105+
- Always use `===` / `!==`
106+
- Trailing commas required on multiline expressions and parameter lists
107+
- Single quotes for strings
108+
- Never use `eval()` — it is an error
109+
- Avoid non-null assertions (`!`) — they are a warning; only freely allowed in test files
110+
- Handle all members in `switch` statements over enums and union types (`switch-exhaustiveness-check`)
111+
112+
## Testing
113+
114+
Tests use [Vitest](https://vitest.dev/) with the `happy-dom` environment for DOM simulation. Each package has its own `vitest.config.ts`.
115+
116+
- **Test files**: co-located with source or in a `test/` directory, named `*.test.ts` / `*.test.tsx`
117+
- **Run all tests**: `pnpm test` (from repo root)
118+
- **Run tests for one package**: `cd packages/saved-views-react && pnpm run test:cover`
119+
- **Coverage**: `pnpm run cover` (uses `@vitest/coverage-v8`)
120+
- Test files relax `any` and non-null assertion lint rules — these relaxations must not be used in production code
121+
122+
## Versioning with Changesets
123+
124+
This repository uses [Changesets](https://github.com/changesets/changesets) to manage versioning and changelogs. See the [README](../README.md#versioning-with-changesets) for the full workflow.
125+
126+
- **Public API or behavior change**`pnpm changeset` (select semver bump and describe the change)
127+
- **Docs-only or internal-only change**`pnpm changeset --empty`
128+
- Every PR to main must include a changeset; CI will fail without one
129+
130+
---
131+
132+
## MANDATORY: Pre-commit Checklist
133+
134+
**CRITICAL**: Before finishing any task, you MUST run all four commands below in order and fix every error and warning before considering the work done. Do not skip steps.
135+
136+
```shell
137+
pnpm run build # Must produce zero compiler errors
138+
pnpm test # Must produce zero failing tests
139+
pnpm run lint # Must produce zero errors AND zero warnings
140+
pnpm run typecheck # Must produce zero type errors
141+
pnpm audit # Must produce zero high/critical vulnerabilities
142+
```
143+
144+
**NO EXCEPTIONS**: Code that does not build, has failing tests, or produces lint/type errors must never be committed.
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
name: fix-audit-vulnerabilities
3+
description: 'Identify and fix high-severity npm/pnpm security vulnerabilities in the saved-views monorepo. Use when asked to "fix audit vulnerabilities", "run pnpm audit", "update audit", "fix security issues", "address CVEs", or when security advisories need to be resolved. Runs pnpm audit --audit-level high, diagnoses affected packages, applies dependency overrides or upgrades, then verifies fixes with build and tests.'
4+
---
5+
6+
# Fix Audit Vulnerabilities
7+
8+
Workflow for identifying, fixing, and verifying high-severity security vulnerabilities in the saved-views pnpm monorepo.
9+
10+
## When to Use This Skill
11+
12+
- User asks to "fix audit vulnerabilities" or "run pnpm audit"
13+
- User mentions "security issues", "CVEs", or "dependency vulnerabilities"
14+
- CI audit check is failing
15+
- User wants to "update audit" or "resolve security advisories"
16+
17+
## Prerequisites
18+
19+
- pnpm >= 10 installed
20+
- Node >= 20
21+
- Run commands from the **repository root** (`e:\saved-views_1\saved-views\`)
22+
- On Windows, prefix commands with `cmd /c "cd /d <repo-root> && <command> 2>&1"`
23+
24+
## Step-by-Step Workflow
25+
26+
### Step 1: Run the Audit
27+
28+
Run [run-audit.ps1](./scripts/run-audit.ps1) or execute directly:
29+
30+
```powershell
31+
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process
32+
cd e:\saved-views_1\saved-views
33+
pnpm audit 2>&1
34+
```
35+
36+
> Note: Run without `--audit-level high` so that moderate vulnerabilities are also visible — they may be fixed just as easily.
37+
38+
Read the output carefully. Note:
39+
- **Package name** with the vulnerability
40+
- **Severity** (high or critical)
41+
- **Via** chain (which of your direct deps pulled it in)
42+
- **Fix available** — whether a non-breaking fix exists
43+
44+
### Step 2: Diagnose the Affected Packages
45+
46+
For each vulnerable package, determine which workspace package(s) depend on it:
47+
48+
```powershell
49+
pnpm why <vulnerable-package>
50+
```
51+
52+
> **Caveat:** `pnpm why` only searches the current workspace root, not sub-packages. If it returns nothing, the package is still likely installed as a transitive dep — confirm by checking `pnpm-lock.yaml` directly:
53+
> ```powershell
54+
> Select-String -Path pnpm-lock.yaml -Pattern "^ <vulnerable-package>@"
55+
> ```
56+
57+
Check the sub-package `package.json` files in:
58+
- `packages/saved-views-client/package.json`
59+
- `packages/saved-views-react/package.json`
60+
- `packages/test-app-frontend/package.json`
61+
- `packages/test-app-backend/package.json`
62+
- Root `package.json`
63+
64+
### Step 3: Choose a Fix Strategy
65+
66+
Consult [audit-fix-guide.md](./references/audit-fix-guide.md) for strategy details.
67+
68+
| Situation | Strategy |
69+
|-----------|----------|
70+
| Direct dependency, non-breaking update available | Bump version in the relevant `package.json` |
71+
| Transitive dependency, fix available | Add `pnpm.overrides` in root `package.json` |
72+
| No fix available yet | Add `pnpm.overrides` to pin to the least-vulnerable version |
73+
| Breaking major version bump needed | Update code for compatibility before bumping |
74+
75+
### Step 4: Apply the Fix
76+
77+
**Option A — Bump a direct dependency:**
78+
Edit the relevant `package.json` and update the version range, then:
79+
```powershell
80+
cmd /c "cd /d e:\saved-views_1\saved-views && pnpm install 2>&1"
81+
```
82+
83+
**Option B — Add/update a pnpm override** (root `package.json`):
84+
```json
85+
{
86+
"pnpm": {
87+
"overrides": {
88+
"vulnerable-package@<fixed-version": ">=fixed-version"
89+
}
90+
}
91+
}
92+
```
93+
Then run `pnpm install`.
94+
95+
> **Override key syntax:** Always use comparison-operator ranges on the key (e.g. `"pkg@<1.2.3"`, `"pkg@>=4.0.0 <5.0.5"`) rather than caret/tilde ranges (e.g. `"pkg@^4"`). Caret/tilde ranges in keys may not match correctly.
96+
>
97+
> **Override value syntax:** Use `">=fixed-version"` (not a pinned exact version) so future patches are still resolved. For the value, `>=` works correctly even though it looks unbounded — pnpm resolves the minimum satisfying version.
98+
>
99+
> **Scope overrides precisely:** If a vulnerability only affects one major version range, restrict the key accordingly (e.g. `"picomatch@>=4.0.0 <4.0.4": "4.0.4"`) rather than a bare `"picomatch"` which would force all consumers, including those on a safe `^2.x` range, to use the overridden version.
100+
101+
### Step 5: Consider Deleting the Lockfile for a Fresh Resolve
102+
103+
If some overrides don't seem to take effect, delete `pnpm-lock.yaml` and re-install to force a full dependency re-resolution:
104+
```powershell
105+
Remove-Item pnpm-lock.yaml
106+
pnpm install
107+
```
108+
This ensures all overrides are applied from scratch rather than reusing cached resolutions.
109+
110+
### Step 6: Verify the Fix
111+
112+
Re-run the audit to confirm vulnerabilities are resolved:
113+
```powershell
114+
pnpm audit 2>&1
115+
```
116+
117+
### Step 7: Try to Reduce Overrides
118+
119+
Before finishing, check whether any override can be eliminated by bumping a direct dependency instead. For each override, trace the chain with `pnpm why` and check if the direct dep that pulls it in has a newer version with the vulnerability fixed:
120+
121+
```powershell
122+
pnpm view <direct-dep>@latest dependencies --json
123+
```
124+
125+
Removing an override is always preferable to keeping one — it means the fix is self-maintaining.
126+
127+
### Step 8: Confirm Nothing is Broken
128+
129+
Run build, tests, and lint to make sure the fix didn't break anything:
130+
```powershell
131+
pnpm run build 2>&1
132+
pnpm test 2>&1
133+
pnpm run lint -- --max-warnings 0 2>&1
134+
```
135+
136+
> **Warning — ESLint plugin upgrades:** If you upgraded `@typescript-eslint/eslint-plugin` or `@typescript-eslint/parser` as part of the fix, major version bumps (e.g. v7 → v8) can remove or rename rules, causing lint to break even if audit passes. Common v8 breakages:
137+
> - Formatting rules removed: `@typescript-eslint/comma-dangle`, `@typescript-eslint/quotes`, `@typescript-eslint/member-delimiter-style` → replace with base eslint equivalents (`comma-dangle`, `quotes`) and drop `member-delimiter-style`
138+
> - `@typescript-eslint/ban-types` removed → use `@typescript-eslint/no-empty-object-type` or disable it
139+
> - `no-unused-expressions` default changed → add `["error", { "allowShortCircuit": true, "allowTernary": true }]` to restore previous behavior
140+
> - New rules added to `recommended-type-checked` may flag existing code (e.g. `no-duplicate-type-constituents`, `only-throw-error`)
141+
>
142+
> Always run lint immediately after any `@typescript-eslint` upgrade and before considering the fix complete.
143+
144+
If type errors appear, run typecheck for details:
145+
```powershell
146+
pnpm run typecheck 2>&1
147+
```
148+
149+
## Important Notes
150+
151+
- **Never use `npm`** — this project blocks npm (`"npm": "<0"` in engines). Always use `pnpm`.
152+
- **pnpm overrides** live under the `"pnpm"` key in the root `package.json`, not `"resolutions"`.
153+
- After editing any `package.json`, always run `pnpm install` to regenerate `pnpm-lock.yaml`.
154+
- If a fix requires a major version bump of a published package (`saved-views-client` or `saved-views-react`), check for API breaking changes before applying.
155+
156+
## References
157+
158+
- [Audit Fix Strategy Guide](./references/audit-fix-guide.md)
159+
- [Run Audit Script](./scripts/run-audit.ps1)
160+
- [pnpm audit docs](https://pnpm.io/cli/audit)
161+
- [pnpm overrides docs](https://pnpm.io/package_json#pnpmoverrides)

0 commit comments

Comments
 (0)