Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Prefer **small, focused diffs**. Match existing markdown and plugin patterns.
| Path | Purpose |
|------|---------|
| **`skills/{fw-setup,fw-app-dev,fw-ai-actions-app,fw-review,fw-publish}/`** | Skill packages (`SKILL.md`, `rules/`, `commands/`, `references/`, `assets/`) |
| **`skills/fw-review/scripts/*.js`** | Deterministic rule checks (mapped in `rules/script-check-rules.md`) |
| **`skills/fw-review/checks/*.js`** | Deterministic rule checks, one per script-backed rule ID (mapped in `rules/script-check-rules.md`); shared CLI/result plumbing in **`skills/fw-review/runners/common.js`** |
| **`skills/shared/`** | `.meta.template.json`, `scripts/meta-*.sh`, `check-update.sh` |
| **`installer/`** | `npx @freshworks/fw-dev-tools` CLI (install, update, status, uninstall) |
| **`installer/src/specs/fw-dev-tools-spec.md`** | **Shipped** routing spec (~28 lines) → Cursor rule / Codex `AGENTS.md` block |
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ fw-dev-tools/
│ │ ├── references/ # Documentation loaded on-demand
│ │ └── assets/ # Templates and resources
│ ├── fw-ai-actions-app/ # AI Actions + third-party integrations (skill id: fw-ai-actions-app; actions.json, SMI)
│ ├── fw-review/ # Automated app review (rules + scripts, structured report)
│ ├── fw-review/ # Automated app review (rules + checks/ + runners/, structured report)
│ ├── fw-setup/ # FDK + Node install / lifecycle (nvm)
│ └── fw-publish/ # Marketplace publish (MCP) guidance
├── scripts/ # Build and utility scripts
Expand Down
47 changes: 24 additions & 23 deletions skills/fw-review/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# fw-review

Automated **Freshworks Platform 3.0** marketplace app audit: manifest and iparams review, frontend rules, deterministic `scripts/*.js` checks, and a fixed **App Review Result** report format.
Automated **Freshworks Platform 3.0** marketplace app audit: manifest and iparams review, frontend rules, deterministic `checks/*.js` rule checks (with shared CLI/result plumbing in `runners/common.js`), and a fixed **App Review Result** report format.

## Overview

**fw-review** is a silent, pipeline-style skill. Agents follow `SKILL.md`, evaluate the rule IDs listed here, run mapped scripts from `scripts/` where specified, and emit output per `rules/report.md`. It does not install FDK; use **fw-setup** (`/fw-setup-status`) when the CLI may be absent. To fix findings, use **fw-app-dev** (full Platform 3.0 apps) or **fw-ai-actions-app** (AI Actions) per **[AGENTS.md](../../AGENTS.md)**.
**fw-review** is a silent, pipeline-style skill. Agents follow `SKILL.md`, evaluate the rule IDs listed here, run mapped rule scripts from `checks/` (each importing shared plumbing from `runners/common.js`) where specified, and emit output per `rules/report.md`. It does not install FDK; use **fw-setup** (`/fw-setup-status`) when the CLI may be absent. To fix findings, use **fw-app-dev** (full Platform 3.0 apps) or **fw-ai-actions-app** (AI Actions) per **[AGENTS.md](../../AGENTS.md)**.

## Install

Expand Down Expand Up @@ -41,27 +41,27 @@ claude plugin install fw-review@freshworks-developers
| IP-04A | Installation parameters | `rules/iparam-rules.md` | Protocol must not be accepted in domain or host fields. |
| IP-05A | Installation parameters | `rules/iparam-rules.md` | Installation inputs must have thorough validation. |
| IP-06A | Installation parameters | `rules/iparam-rules.md` | Validation failures must show helpful, specific messages. |
| FFS-02L | File and folder structure | `rules/script-check-rules.md`, `scripts/external-import-sources.js` | External imports must use allowlisted hosts. |
| FFS-04L | File and folder structure | `rules/script-check-rules.md`, `scripts/https-imports.js` | External imports must use HTTPS. |
| FFS-05L | File and folder structure | `rules/script-check-rules.md`, `scripts/image-resolution.js` | Image assets must meet baseline resolution expectations. |
| FFS-02L | File and folder structure | `rules/script-check-rules.md`, `checks/external-import-sources.js` | External imports must use allowlisted hosts. |
| FFS-04L | File and folder structure | `rules/script-check-rules.md`, `checks/https-imports.js` | External imports must use HTTPS. |
| FFS-05L | File and folder structure | `rules/script-check-rules.md`, `checks/image-resolution.js` | Image assets must meet baseline resolution expectations. |
| FF-01L | Frontend | `rules/frontend-files-rules.md` | Client API calls must use request templates instead of raw Ajax/fetch/HTTP clients. |
| FF-07L | Frontend | `rules/frontend-files-rules.md`, `rules/script-check-rules.md`, `scripts/oauth-config-usage.js` | OAuth client IDs, secrets, and tokens must stay in secure configuration. |
| FF-07L | Frontend | `rules/frontend-files-rules.md`, `rules/script-check-rules.md`, `checks/oauth-config-usage.js` | OAuth client IDs, secrets, and tokens must stay in secure configuration. |
| FF-02M | Frontend | `rules/frontend-files-rules.md` | SMI must not be used when request templates are sufficient. |
| FF-03A | Frontend | `rules/frontend-files-rules.md` | API secrets must appear in request headers, not URLs. |
| FF-04A | Frontend | `rules/frontend-files-rules.md` | API errors must be handled and reported to users. |
| FF-05A | Frontend | `rules/frontend-files-rules.md` | List API calls must use pagination when supported. |
| FF-06A | Frontend | `rules/frontend-files-rules.md` | Source code must not hardcode credentials or secrets. |
| CR-05L | Code readability | `rules/script-check-rules.md`, `scripts/unused-library-imports.js` | Imported third-party libraries must be used. |
| GN-02L | Miscellaneous | `rules/script-check-rules.md`, `scripts/fdk-errors-warnings.js` | FDK validation must not report errors or warnings. |
| GN-08L | Miscellaneous | `rules/script-check-rules.md`, `scripts/freshworks-css-only.js` | Only Freshworks CSS should be referenced. |
| GN-12L | Miscellaneous | `rules/script-check-rules.md`, `scripts/platform-version-upgrade.js` | App must target the expected platform version. |
| CR-05L | Code readability | `rules/script-check-rules.md`, `checks/unused-library-imports.js` | Imported third-party libraries must be used. |
| GN-02L | Miscellaneous | `rules/script-check-rules.md`, `checks/fdk-errors-warnings.js` | FDK validation must not report errors or warnings. |
| GN-08L | Miscellaneous | `rules/script-check-rules.md`, `checks/freshworks-css-only.js` | Only Freshworks CSS should be referenced. |
| GN-12L | Miscellaneous | `rules/script-check-rules.md`, `checks/platform-version-upgrade.js` | App must target the expected platform version. |

## Script Output Contract

Script-backed checks are deterministic Node CLIs. Each script takes an app root path and prints JSON:
Script-backed checks are deterministic Node CLIs. Each rule check lives in `checks/` and uses the shared CLI/result plumbing in `runners/common.js`. Each script takes an app root path and prints JSON:

```bash
node scripts/<script-name>.js /path/to/app
node checks/<script-name>.js /path/to/app
```

Each script returns a JSON object with this shape:
Expand All @@ -84,7 +84,7 @@ Important:
- The user-facing review output must not show `internal.rule_id`.
- `passed`, `summary`, and `details` are intended for downstream evaluation and report generation.

Shared helper in `scripts/common.js`:
Shared helper in `runners/common.js` (imported by every file in `checks/` as `require('../runners/common')`):

- `createRuleResult(ruleId, passed, summary, details)` wraps the script result and stores the rule ID under `internal.rule_id`.
- `runCli(run)` resolves the target directory from `process.argv[2] || process.cwd()`, runs the checker, prints formatted JSON, and sets the process exit code to `0` for pass and `1` for fail.
Expand Down Expand Up @@ -154,7 +154,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### FFS-02L - Dependencies From External Sources Must Use Allowlisted Hosts

**Implemented by:** `scripts/external-import-sources.js`
**Implemented by:** `checks/external-import-sources.js`

**File types scanned:** `.css`, `.html`, `.js`, `.json`, `.jsx`, `.ts`, `.tsx`

Expand Down Expand Up @@ -206,7 +206,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### FFS-04L - Imports Must Use HTTPS

**Implemented by:** `scripts/https-imports.js`
**Implemented by:** `checks/https-imports.js`

**Implementation details:**

Expand All @@ -231,7 +231,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### FFS-05L - Images Must Meet Baseline Resolution Expectations

**Implemented by:** `scripts/image-resolution.js`
**Implemented by:** `checks/image-resolution.js`

**Implementation details:**

Expand Down Expand Up @@ -273,7 +273,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### FF-07L - OAuth Client ID And Secrets Only In OAuth / Secure Config

**Implemented by:** `scripts/oauth-config-usage.js` plus frontend review criteria.
**Implemented by:** `checks/oauth-config-usage.js` plus frontend review criteria.

**Implementation details:**

Expand Down Expand Up @@ -379,7 +379,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### CR-05L - Imported Third-Party Libraries Must Be Used

**Implemented by:** `scripts/unused-library-imports.js`
**Implemented by:** `checks/unused-library-imports.js`

**Implementation details:**

Expand Down Expand Up @@ -410,7 +410,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### GN-02L - FDK Validation Must Not Report Errors Or Warnings

**Implemented by:** `scripts/fdk-errors-warnings.js`
**Implemented by:** `checks/fdk-errors-warnings.js`

**Implementation details:**

Expand All @@ -436,7 +436,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### GN-08L - Only Freshworks CSS Should Be Referenced

**Implemented by:** `scripts/freshworks-css-only.js`
**Implemented by:** `checks/freshworks-css-only.js`

**Implementation details:**

Expand Down Expand Up @@ -464,7 +464,7 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa

#### GN-12L - App Must Target The Expected Platform Version

**Implemented by:** `scripts/platform-version-upgrade.js`
**Implemented by:** `checks/platform-version-upgrade.js`

**Implementation details:**

Expand All @@ -491,14 +491,15 @@ Installation-time configuration review is scoped to `manifest.json`, default ipa
|------|---------|
| `SKILL.md` | Workflow, authoritative rule ID summary, prerequisites |
| `rules/` | Detailed criteria for iparam, frontend, script-backed checks, and report output |
| `scripts/` | Node CLIs for script-backed checks listed in the rule inventory |
| `checks/` | One Node CLI per script-backed rule ID listed in the rule inventory |
| `runners/` | Shared CLI/result plumbing (`runners/common.js` exporting `createRuleResult` and `runCli`) imported by every check |
| `.claude-plugin/` / `.cursor-plugin/` | Plugin metadata for marketplace installs |

## Requirements

- Target app: Platform 3.0 marketplace layout (`manifest.json`, `config/`, `app/`, etc.)
- **FDK** on `PATH` when phases require `fdk` (otherwise install via **fw-setup**)
- **Node.js** to run `scripts/*.js` (same machine as the audit)
- **Node.js** to run `checks/*.js` (same machine as the audit)

## Support

Expand Down
8 changes: 4 additions & 4 deletions skills/fw-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This is an automated pipeline. **After the app directory is determined (Q1 pre-f
3. If **one folder**: Use that directory.
4. If **none**: Inform the user and stop.

All app files in the workflow below are relative to that directory (the folder containing `manifest.json`). Run deterministic check scripts from this skill’s **`scripts/`** against `<app-directory>` (see [README.md](README.md)).
All app files in the workflow below are relative to that directory (the folder containing `manifest.json`). Run deterministic rule checks from this skill’s **`checks/`** against `<app-directory>`; shared CLI/result plumbing lives in **`runners/common.js`** (see [README.md](README.md)).

## Workflow

Expand All @@ -42,15 +42,15 @@ The **Freshworks FDK CLI** (`fdk`) is **not** bundled with this repository and i

1. **Structure** — Read `manifest.json` in the app directory first for platform version, modules, requests, events, and install flow.
2. **Installation parameters** — In the app directory, review `config/iparams.json` or custom `config/iparams.html` / `config/assets/iparams.js` using [rules/iparam-rules.md](rules/iparam-rules.md). Follow the discovery order in that file.
3. **Deterministic script checks** — For each script-backed rule ID in [rules/script-check-rules.md](rules/script-check-rules.md), run the mapped JS file from this skill’s `scripts/` against `<app-directory>`. Treat any returned internal metadata such as `internal.rule_id` as internal only.
3. **Deterministic script checks** — For each script-backed rule ID in [rules/script-check-rules.md](rules/script-check-rules.md), run the mapped JS file from this skill’s `checks/` against `<app-directory>`. Treat any returned internal metadata such as `internal.rule_id` as internal only.
4. **Frontend logical checks** — Review [rules/frontend-files-rules.md](rules/frontend-files-rules.md) for FF-* rules that do not have a one-to-one script.

## Rules

- Do **not** invent rule IDs or Pass/Fail criteria beyond the **Rule ID summary** in this file and the criteria defined in the linked `rules/*.md` files for those IDs.
- Every rule ID **in the Rule ID summary** below must be evaluated to Pass, Fail, or Not Applicable.
- Emit the **App Review Result** block exactly as specified in [rules/report.md](rules/report.md):
- **Exclusive deliverable:** The user-facing reply for the review **must contain only** that block—begin with `## App Review Result`; do **not** add lines above it or below it (aside from what `report.md` defines inside the block: heading, then `successful` or the numbered list). No rule IDs (`GN-*`, `IP-*`, `FF-*`, `FFS-*`, `CR-*`), no internal filenames (`script-check-rules.md`, other `rules/*.md`, `scripts/*.js`), and no citations to skill paths.
- **Exclusive deliverable:** The user-facing reply for the review **must contain only** that block—begin with `## App Review Result`; do **not** add lines above it or below it (aside from what `report.md` defines inside the block: heading, then `successful` or the numbered list). No rule IDs (`GN-*`, `IP-*`, `FF-*`, `FFS-*`, `CR-*`), no internal filenames (`script-check-rules.md`, other `rules/*.md`, `checks/*.js`, `runners/*.js`), and no citations to skill paths.
- The output is **rendered Markdown**. Do **not** wrap the final report in a code fence (no `\`\`\`text` around the whole block); emit the Markdown directly so headings, lists, and links render in the chat client.
- Heading is always the level-2 Markdown heading `## App Review Result` with no suffix. Below it: the word `successful` alone on its own line when there are zero failures; when there are failures, omit `successful` and emit the numbered list per [rules/report.md](rules/report.md).
- Each failure is one numbered list entry with two paragraphs:
Expand Down Expand Up @@ -89,7 +89,7 @@ Then emit the `## App Review Result` block.
- [rules/report.md](rules/report.md) — Output format for the final **App Review Result** block only.
- [rules/iparam-rules.md](rules/iparam-rules.md) — IP-04A, IP-05A, IP-06A.
- [rules/frontend-files-rules.md](rules/frontend-files-rules.md) — All FF-* rules.
- [rules/script-check-rules.md](rules/script-check-rules.md) — Script-backed rule IDs mapped to `scripts/*.js`.
- [rules/script-check-rules.md](rules/script-check-rules.md) — Script-backed rule IDs mapped to `checks/*.js` (with shared CLI/result plumbing in `runners/common.js`).

## Rule ID summary (authoritative list of evaluated rule IDs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'FFS-02L';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

const { spawn } = require('child_process');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'GN-02L';
const MAX_REPORTED_ISSUES = 10;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'GN-08L';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'FFS-04L';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'FFS-05L';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'FF-07L';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'GN-12L';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

const fs = require('fs/promises');
const path = require('path');
const { createRuleResult, runCli } = require('./common');
const { createRuleResult, runCli } = require('../runners/common');

const RULE_ID = 'CR-05L';

Expand Down
4 changes: 2 additions & 2 deletions skills/fw-review/rules/report.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ Rules:
- Each failure is a single numbered list entry. The first paragraph is the issue line ending with the bracketed location link. The second paragraph (indented 3 spaces) starts with `**Fix:**`.
- Separate the issue paragraph and the Fix paragraph with one blank line. Separate consecutive numbered entries with one blank line.
- Do **not** include internal **rule IDs** (e.g. `GN-02L`, `IP-04A`, `FFS-04L`, `FF-07L`, `CR-05L`), **area labels** shown to the user (`Iparams`, `Miscellaneous`), severity labels, or internal JSON metadata such as `internal.rule_id` anywhere in emitted output—including any line intended for the developer reading the chat.
- Do **not** cite this skill’s **markdown or script paths** in emitted output (`script-check-rules.md`, `iparam-rules.md`, other `rules/*.md`, `scripts/*.js`).
- Do **not** cite this skill’s **markdown or script paths** in emitted output (`script-check-rules.md`, `iparam-rules.md`, other `rules/*.md`, `checks/*.js`, `runners/*.js`).
- Do **not** wrap the final report in triple backticks.

## Writing style
Expand Down Expand Up @@ -168,7 +168,7 @@ successful

### Preamble or footnote exposing rule IDs or skill files

Invalid (anything before `## App Review Result` that names a rule ID, cites `rules/*.md` / `scripts/*.js`, or explains Pass/N/A omissions):
Invalid (anything before `## App Review Result` that names a rule ID, cites `rules/*.md` / `checks/*.js` / `runners/*.js`, or explains Pass/N/A omissions):

```markdown
GN-02L is Not applicable when FDK is missing on PATH (per `script-check-rules.md`); …
Expand Down
Loading
Loading