biome-plugin-suitescript 0.3.0 → 0.4.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 (2) hide show
  1. package/README.md +30 -25
  2. package/package.json +8 -1
package/README.md CHANGED
@@ -1,10 +1,15 @@
1
1
  # biome-plugin-suitescript
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/biome-plugin-suitescript)](https://www.npmjs.com/package/biome-plugin-suitescript)
4
+ [![CI](https://img.shields.io/github/actions/workflow/status/nemchik/biome-plugin-suitescript/ci.yml?branch=main&label=CI)](https://github.com/nemchik/biome-plugin-suitescript/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/npm/l/biome-plugin-suitescript)](LICENSE)
6
+
3
7
  [Biome](https://biomejs.dev) lint plugins and a tag checker for NetSuite **SuiteScript 2.1**, ported from
4
8
  [acdvs/eslint-plugin-suitescript](https://github.com/acdvs/eslint-plugin-suitescript) and
5
9
  [btonasse/eslint-plugin-suitescript](https://github.com/btonasse/eslint-plugin-suitescript).
6
10
 
7
- Requires Biome **>= 2.6.4** (npm-distributed plugins use `biome-manifest.json`) and Node >= 22 for the CLI.
11
+ Requires Biome **>= 2.6.4** (npm-distributed plugins use `biome-manifest.json`) and Node >= 24 for the CLI. Node 24 LTS is also what Oracle's
12
+ [SuiteCloud CLI for Node.js requires](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_1558708810.html).
8
13
  Rules work on both AMD `define()` and ES `import`/`export` source, in `.js` and `.ts`.
9
14
 
10
15
  ## Install
@@ -59,30 +64,30 @@ decided is in [docs/rule-priority.md](docs/rule-priority.md).
59
64
 
60
65
  | Rule | Severity | Presets | Description | Rule source |
61
66
  | ---------------------------------------- | -------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
62
- | `noBrowserGlobals` | error | :green_circle::large_blue_circle: | No `document`, `window`, `localStorage`, `XMLHttpRequest`, `alert`, `navigator`, `URLSearchParams` or `fetch` in server scripts | Tier 1: [SAFE guide](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/SKILL.md) · Tier 3: [Oracle help: FAQ](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_N3917921.html) |
63
- | `noGlobalShadowing` | error | :green_circle::large_blue_circle: | No variable named `log` or `util` other than the N/log, N/util module itself | Tier 1: [upgrade skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-upgrade/SKILL.md) |
64
- | `noMissingModules` | error | :green_circle::large_blue_circle: | A module used (`record.load()`) must be loaded in `define`/`import` (`log` and `util` are globals) | Tier 0: [ADR 0006](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0006-log-is-a-global-with-two-opposite-styles.md) · Tier 1: [upgrade skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-upgrade/SKILL.md), [learning skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-learning/SKILL.md) |
65
- | `noModuleScopeApiCalls` | error | :green_circle::large_blue_circle: | No `N/` API calls while the `define` callback runs; initialize from entry points (calls that only build an object, `createColumn`, `createFilter`, `createSort` and `createSetting`, are skipped) | Tier 1: [SAFE guide](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/SKILL.md) |
66
- | `noNativeIterators` | error | :green_circle::large_blue_circle: | No generator functions or `Symbol.iterator` (GraalJS) | Tier 1: [SAFE guide](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/SKILL.md) |
67
- | `noSuiteQLTypeInSearch` | error | :green_circle::large_blue_circle: | No SuiteQL abbreviation (`PurchOrd`) as the `type` of `search.create` | Tier 1: [SAFE guide](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/SKILL.md) |
68
- | `noSuiteScript1Api` | error | :green_circle::large_blue_circle: | No `nlapi*`/`nlobj*` or 1.0-only methods (`getFieldValue`, `getLineItemValue`, `e.getCode()`) | Tier 1: [upgrade skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-upgrade/SKILL.md) |
69
- | `noHardcodedSecrets` | error | :key: | No string literal assigned to `password`, `secret`, `apiKey`, .... **Opt-in, in no preset: it guesses from names, so it can misfire on look-alike names** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) · Tier 3: [Oracle help: security considerations](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_159804448843.html) |
70
- | `noDynamicRequire` | warn | :green_circle::large_blue_circle: | `require()` takes string literal module names, not expressions | Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) · Tier 4: [acdvs `no-dynamic-require`](https://github.com/acdvs/eslint-plugin-amd/blob/main/lib/rules/no-dynamic-require.ts) |
71
- | `noDynamicSuiteQL` | warn | :green_circle::large_blue_circle: | `runSuiteQL` queries use `?` placeholders, not concatenation or template literals (calls that pass `params` are skipped) | Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
72
- | `noInnerHtml` | warn | :green_circle::large_blue_circle: | No non-static value assigned to `innerHTML`/`outerHTML` or passed to `insertAdjacentHTML`/`document.write` (client scripts) | Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
73
- | `noPostMessageWildcard` | warn | :green_circle::large_blue_circle: | No `'*'` target origin in `postMessage` | Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
74
- | `noWildcardCors` | warn | :green_circle::large_blue_circle: | No `Access-Control-Allow-Origin: *` response header | Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
75
- | `requireEachReturn` | warn | :green_circle::large_blue_circle: | A `.run().each` or `.iterator().each` callback returns a value (`true` to continue) | Tier 1: [upgrade skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-upgrade/SKILL.md), [learning skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-learning/SKILL.md) |
76
- | `noRecordInLoop` | warn | :large_blue_circle: | No `record.load`, `query.runSuiteQL` or `search.create` inside loops or `forEach`/`each`/`map` callbacks | Tier 1: [SAFE guide](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/SKILL.md) |
77
- | `requireLogModule` | warn | :large_blue_circle: | A used `log.*` needs `N/log` loaded (the upgrade skill recommends it; the global needs no loading) | Tier 0: [ADR 0006](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0006-log-is-a-global-with-two-opposite-styles.md) · Tier 1: [upgrade skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-upgrade/SKILL.md), [learning skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-suitescript-learning/SKILL.md) |
78
- | `noInsecureCookie` | warn | :key: | A literal `Set-Cookie` value has `HttpOnly`, `Secure` and `SameSite`. **Opt-in, in no preset: only literal values are checked, and we have not confirmed a Suitelet may set `Set-Cookie`** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
79
- | `noLocationHeader` | warn | :key: | No `Location` header built from a variable; use `N/redirect`. **Opt-in, in no preset: the value may already be validated, and the skill's references still set `Location` after sanitising it** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
80
- | `noPublicFileUpload` | warn | :key: | No `isOnline: true` (public file). **Opt-in, in no preset: public assets legitimately set `isOnline`** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill: file upload](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/references/07-file-upload-download.md) |
81
- | `noSensitiveBrowserStorage` | warn | :key: | No token- or password-named key in `localStorage`/`sessionStorage.setItem`. **Opt-in, in no preset: it guesses from the key name** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
82
- | `noStackInResponse` | warn | :key: | No `.stack` inside `response.write`/`writeLine` arguments. **Opt-in, in no preset: a stack returned from a RESTlet is not detected, and the skill's own logging example includes `e.stack`** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
83
- | `noSuiteQLSelectStar` | warn | :key: | No `SELECT *` in a literal SuiteQL query. **Opt-in, in no preset: the guide itself recommends a `SELECT * ... ROWNUM <= 1` probe, and only literal queries are seen** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [SAFE guide: performance](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/references/03-performance-optimization.md) |
84
- | `noSuiteQLSystemNoteJoin` | warn | :key: | No `JOIN SystemNote` in a literal SuiteQL query. **Opt-in, in no preset: a tightly filtered join is fine, and only literal queries are seen** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [SAFE guide](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-sdf-safe-guide/SKILL.md) |
85
- | `noWeakHash` | warn | :key: | No `HashAlg.MD5` or `HashAlg.SHA1`. **Opt-in, in no preset: it cannot tell a security use from a vendor integration that requires MD5 or SHA-1, and the type definitions list only `SHA256` and `SHA512` for `crypto.HashAlg`, so the member names come from the skill alone** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/oracle/netsuite-suitecloud-sdk/blob/master/packages/agent-skills/netsuite-owasp-secure-coding/SKILL.md) |
67
+ | `noBrowserGlobals` | error | :green_circle::large_blue_circle: | No `document`, `window`, `localStorage`, `XMLHttpRequest`, `alert`, `navigator`, `URLSearchParams` or `fetch` in server scripts | Tier 1: [SAFE guide](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/SKILL.md) · Tier 3: [Oracle help: FAQ](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_N3917921.html) |
68
+ | `noGlobalShadowing` | error | :green_circle::large_blue_circle: | No variable named `log` or `util` other than the N/log, N/util module itself | Tier 1: [upgrade skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-upgrade/SKILL.md) |
69
+ | `noMissingModules` | error | :green_circle::large_blue_circle: | A module used (`record.load()`) must be loaded in `define`/`import` (`log` and `util` are globals) | Tier 0: [ADR 0006](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0006-log-is-a-global-with-two-opposite-styles.md) · Tier 1: [upgrade skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-upgrade/SKILL.md), [learning skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-learning/SKILL.md) |
70
+ | `noModuleScopeApiCalls` | error | :green_circle::large_blue_circle: | No `N/` API calls while the `define` callback runs; initialize from entry points (calls that only build an object, `createColumn`, `createFilter`, `createSort` and `createSetting`, are skipped) | Tier 1: [SAFE guide](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/SKILL.md) |
71
+ | `noNativeIterators` | error | :green_circle::large_blue_circle: | No generator functions or `Symbol.iterator` (GraalJS) | Tier 1: [SAFE guide](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/SKILL.md) |
72
+ | `noSuiteQLTypeInSearch` | error | :green_circle::large_blue_circle: | No SuiteQL abbreviation (`PurchOrd`) as the `type` of `search.create` | Tier 1: [SAFE guide](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/SKILL.md) |
73
+ | `noSuiteScript1Api` | error | :green_circle::large_blue_circle: | No `nlapi*`/`nlobj*` or 1.0-only methods (`getFieldValue`, `getLineItemValue`, `e.getCode()`) | Tier 1: [upgrade skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-upgrade/SKILL.md) |
74
+ | `noHardcodedSecrets` | error | :key: | No string literal assigned to `password`, `secret`, `apiKey`, .... **Opt-in, in no preset: it guesses from names, so it can misfire on look-alike names** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) · Tier 3: [Oracle help: security considerations](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/chapter_159804448843.html) |
75
+ | `noDynamicRequire` | warn | :green_circle::large_blue_circle: | `require()` takes string literal module names, not expressions | Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) · Tier 4: [acdvs `no-dynamic-require`](https://github.com/acdvs/eslint-plugin-amd/blob/main/lib/rules/no-dynamic-require.ts) |
76
+ | `noDynamicSuiteQL` | warn | :green_circle::large_blue_circle: | `runSuiteQL` queries use `?` placeholders, not concatenation or template literals (calls that pass `params` are skipped) | Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
77
+ | `noInnerHtml` | warn | :green_circle::large_blue_circle: | No non-static value assigned to `innerHTML`/`outerHTML` or passed to `insertAdjacentHTML`/`document.write` (client scripts) | Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
78
+ | `noPostMessageWildcard` | warn | :green_circle::large_blue_circle: | No `'*'` target origin in `postMessage` | Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
79
+ | `noWildcardCors` | warn | :green_circle::large_blue_circle: | No `Access-Control-Allow-Origin: *` response header | Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
80
+ | `requireEachReturn` | warn | :green_circle::large_blue_circle: | A `.run().each` or `.iterator().each` callback returns a value (`true` to continue) | Tier 1: [upgrade skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-upgrade/SKILL.md), [learning skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-learning/SKILL.md) |
81
+ | `noRecordInLoop` | warn | :large_blue_circle: | No `record.load`, `query.runSuiteQL` or `search.create` inside loops or `forEach`/`each`/`map` callbacks | Tier 1: [SAFE guide](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/SKILL.md) |
82
+ | `requireLogModule` | warn | :large_blue_circle: | A used `log.*` needs `N/log` loaded (the upgrade skill recommends it; the global needs no loading) | Tier 0: [ADR 0006](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0006-log-is-a-global-with-two-opposite-styles.md) · Tier 1: [upgrade skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-upgrade/SKILL.md), [learning skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-suitescript-learning/SKILL.md) |
83
+ | `noInsecureCookie` | warn | :key: | A literal `Set-Cookie` value has `HttpOnly`, `Secure` and `SameSite`. **Opt-in, in no preset: only literal values are checked, and we have not confirmed a Suitelet may set `Set-Cookie`** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
84
+ | `noLocationHeader` | warn | :key: | No `Location` header built from a variable; use `N/redirect`. **Opt-in, in no preset: the value may already be validated, and the skill's references still set `Location` after sanitising it** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
85
+ | `noPublicFileUpload` | warn | :key: | No `isOnline: true` (public file). **Opt-in, in no preset: public assets legitimately set `isOnline`** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill: file upload](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/references/07-file-upload-download.md) |
86
+ | `noSensitiveBrowserStorage` | warn | :key: | No token- or password-named key in `localStorage`/`sessionStorage.setItem`. **Opt-in, in no preset: it guesses from the key name** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
87
+ | `noStackInResponse` | warn | :key: | No `.stack` inside `response.write`/`writeLine` arguments. **Opt-in, in no preset: a stack returned from a RESTlet is not detected, and the skill's own logging example includes `e.stack`** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
88
+ | `noSuiteQLSelectStar` | warn | :key: | No `SELECT *` in a literal SuiteQL query. **Opt-in, in no preset: the guide itself recommends a `SELECT * ... ROWNUM <= 1` probe, and only literal queries are seen** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [SAFE guide: performance](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/references/03-performance-optimization.md) |
89
+ | `noSuiteQLSystemNoteJoin` | warn | :key: | No `JOIN SystemNote` in a literal SuiteQL query. **Opt-in, in no preset: a tightly filtered join is fine, and only literal queries are seen** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [SAFE guide](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-sdf-safe-guide/SKILL.md) |
90
+ | `noWeakHash` | warn | :key: | No `HashAlg.MD5` or `HashAlg.SHA1`. **Opt-in, in no preset: it cannot tell a security use from a vendor integration that requires MD5 or SHA-1, and the type definitions list only `SHA256` and `SHA512` for `crypto.HashAlg`, so the member names come from the skill alone** | Tier 0: [ADR 0005](https://github.com/nemchik/biome-plugin-suitescript/blob/main/docs/adr/0005-guessing-rules-are-in-no-preset.md) · Tier 1: [OWASP skill](https://github.com/nemchik/biome-plugin-suitescript/blob/main/.agents/skills/netsuite-owasp-secure-coding/SKILL.md) |
86
91
  | `noAuthorizationHeaderInInternalRequest` | error | :green_circle::large_blue_circle: | No `Authorization` header in `https.requestRestlet`/`requestSuitelet`/`requestSuiteTalkRest` | Tier 2: [headintheclouddev `N/https`](https://github.com/headintheclouddev/typings-suitescript-2.0/blob/master/N/https.d.ts) · Tier 3: [Oracle help: https.requestRestlet](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_159139340774.html) |
87
92
  | `noPositionalOptions` | error | :green_circle::large_blue_circle: | No literal passed where a module function takes an options object (`record.load('customer', 1)`) | Tier 2: [headintheclouddev `N/*`](https://github.com/headintheclouddev/typings-suitescript-2.0/tree/master/N) |
88
93
  | `noSecretKeyGuidAndSecret` | error | :green_circle::large_blue_circle: | `https.createSecretKey` takes `guid` or `secret`, not both | Tier 2: [headintheclouddev `N/https`](https://github.com/headintheclouddev/typings-suitescript-2.0/blob/master/N/https.d.ts) · Tier 3: [Oracle help: https.createSecretKey](https://docs.oracle.com/en/cloud/saas/netsuite/ns-online-help/section_4418247967.html) |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "biome-plugin-suitescript",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Biome lint plugins and a tag checker for NetSuite SuiteScript 2.1, ported from eslint-plugin-suitescript.",
5
5
  "keywords": [
6
6
  "biome-plugin",
@@ -42,6 +42,12 @@
42
42
  "lint": "biome lint",
43
43
  "prepack": "npm run build",
44
44
  "readme": "node scripts/rules-table.ts",
45
+ "skills": "skills",
46
+ "skills:add": "skills add --skill \"*\" --agent universal --agent claude-code --yes",
47
+ "skills:check": "skills check",
48
+ "skills:install": "skills experimental_install && node scripts/link-claude-skills.ts",
49
+ "skills:list": "skills list",
50
+ "skills:update": "skills update --project --yes && node scripts/link-claude-skills.ts",
45
51
  "sync-modules": "node scripts/sync-modules.ts",
46
52
  "sync-typings": "node scripts/sync-typings.ts",
47
53
  "pretest": "npm run build",
@@ -59,6 +65,7 @@
59
65
  "@types/node": "24.19.2",
60
66
  "git-pull-run": "2.1.0",
61
67
  "lefthook": "2.2.2",
68
+ "skills": "1.7.6",
62
69
  "typescript": "7.0.2"
63
70
  },
64
71
  "peerDependencies": {