Claude
Skills
Sign in
Back

forge-app-review

Included with Lifetime
$97 forever

Reviews Forge apps for security vulnerabilities, architecture issues, cost inefficiencies, performance problems, and trigger/scheduling waste before deployment. Use when the user says "review my Forge app", "check my app", "pre-deploy check", "is my app ready to deploy", "audit my Forge app", "check for security issues", "check performance", "review manifest", "check my Forge app for problems", "app review", "optimize my Forge app costs", "reduce invocations", "why is my app expensive", "check my triggers", or any request to evaluate a Forge app's quality, safety, cost efficiency, or readiness. Also triggers when users ask about Forge best practices, permission scopes, resolver optimization, storage efficiency, cold start reduction, frontend offloading, trigger filtering, scheduled trigger frequency, N+1 API calls, bulk API usage, verbose logging, or Forge platform pricing.

Web Dev

What this skill does


# Forge App Review

Deep pre-deploy review of Forge apps across **Security**, **Architecture**, **Cost**, **Performance**, and **Triggers & Scheduling**. Produces a severity-sorted issue list with actionable fixes.

## Forge Pricing Reference

Forge uses a consumption-based pricing model. Charges only apply above free monthly allowances. Use this table to assess cost impact of findings:

| Capability | Billing Unit | Free Monthly Allowance | Overage Price (USD) |
|-----------|-------------|----------------------|-------------------|
| **Functions: Duration** | GB-seconds | 100,000 GB-seconds | $0.000025 / GB-second |
| **KVS: Reads** | GB read | 0.1 GB | $0.055 / GB |
| **KVS: Writes** | GB written | 0.1 GB | $1.090 / GB |
| **Logs: Writes** | GB written | 1 GB | $1.005 / GB |
| **SQL: Compute duration** | Hours | 1 hour | $0.143 / hour |
| **SQL: Compute requests** | Per 1M requests | 100,000 requests | $1.929 / 1M requests |
| **SQL: Data stored** | GB-hours | 730 GB-hours | $0.00076850 / GB-hour |

**Key cost insight:** KVS writes are ~20× more expensive than reads. Logging is ~$1/GB over the free tier. The cost formula for functions is: **GB-seconds = (memoryMiB ÷ 1024) × duration in seconds**.

**Free capabilities** (not billed): UI modules (UI Kit and Custom UI frontends run in the browser), Jira expressions, Forge Remote invocations (though the remote function runtime is billed), entity properties (stored by the product, not by Forge Storage).

---

## Execution Mandate

When triggered, immediately:

1. Read `manifest.yml` — this is the source of truth for permissions, modules, egress, triggers, scheduled triggers, and function memory settings
2. Read `package.json` — check dependencies, versions, scripts
3. Scan all resolver files in `src/` — check patterns, error handling, data flow, API call patterns (N+1, missing fields, sequential calls), logging verbosity
4. Scan UI code (Custom UI or UI Kit) — check component patterns, bridge usage, whether API calls and logic could be moved to the frontend, product context usage, invoke patterns (chatty, per-render)
5. Check for Forge Storage / Entity Store usage patterns — TTL strategy, write frequency, query vs iteration, entity properties vs KVS
6. Check trigger and scheduling configuration — frequency, filtering, ignoreSelf, early exit, polling vs event-driven
7. Check for Forge Remote usage or opportunities — compute offloading, trade-offs
8. Compile all findings into a severity-sorted issue list

Do NOT ask the user what to review. Review everything. Do NOT modify any code unless explicitly asked. Do NOT skip categories — even if the app looks clean, confirm it explicitly.

---

## Review Process

### Step 1: Manifest Analysis (`manifest.yml`)

Read the manifest first. Extract:
- **Permissions/scopes** — list all `scopes` and `permissions` entries
- **Modules** — list all module types and their function key references
- **Egress** — check `app.connect.remotes` or `permissions.external.fetch.backend` URLs
- **Environment variables** — check for `app.storage` or environment variable declarations

Cross-reference every `function` key in modules against actual resolver `resolver.define()` calls.

### Step 2: Dependencies (`package.json`)

Check:
- Node.js engine compatibility (Forge requires Node 18.x+)
- Unnecessary large dependencies (e.g., `lodash` when only one function is used, `moment` instead of native Date or `dayjs`)
- Missing `@forge/api`, `@forge/bridge`, or `@forge/ui` depending on app type
- Dev dependencies leaking into production
- Outdated `@forge/*` packages

### Step 3: Resolver Code

Read all files that contain `resolver.define` or `Resolver` imports. Check for:
- Error handling patterns
- API call patterns (`requestJira`, `requestConfluence`, `api.asUser()`, `api.asApp()`)
- Data validation and sanitization
- Storage operations
- External fetch calls

### Step 4: UI Code

For **UI Kit** apps — scan for `@forge/react` imports, component usage, hooks.
For **Custom UI** apps — scan for `@forge/bridge` usage, `invoke()` calls, CSP compliance.

In both cases, check for:
- **Frontend offloading opportunities**: Are there resolvers that only do read-only `requestJira()`/`requestConfluence()` calls that could instead use `@forge/bridge` directly from the browser?
- **Product context via resolver**: Is the app invoking a resolver just to get issue/project/space key? Use `useProductContext()` (UI Kit) or `view.getContext()` (Custom UI) instead.
- **Invoke on every render**: Is `invoke()` called without proper `useEffect` with empty dependency array, causing re-invocation on every render?
- **Client-side logic**: Is data formatting, sorting, filtering, or validation done in a resolver when it could run in the browser for free?

### Step 5: Storage Analysis

Search for usage of:
- `storage.get`, `storage.set`, `storage.delete` — check for unnecessary writes, short TTLs (KVS writes are ~20× more expensive than reads), and missing caching patterns
- `storage.query` (Entity Store) — check for proper use of indexes, `.where()`, and `.limit()` instead of fetching all items and filtering in code
- Entity properties (`requestJira` to `/properties/`) — note these are **free** and stored by the product (not Forge Storage quota), suitable for small per-entity metadata (max 32 KB per property). Good for flags, markers, timestamps attached to Jira issues or Confluence pages. Queryable via JQL for Jira entity properties. **Not suitable for sensitive data** — visible to other apps and users via REST API.
- Cache patterns — is app-level data that rarely changes (e.g., custom field IDs, project configs, workflow statuses) being fetched from APIs on every invocation? Should be cached in KVS with a TTL (1 hour+ preferred to minimize writes)
- Write amplification — a 1-minute TTL cache with 100 calls/hour causes ~60 writes/hour; a 1-hour TTL causes ~1 write/hour at ~60× less cost

### Step 6: Trigger & Scheduling Analysis

Check the manifest for `scheduledTrigger` and `trigger` modules:
- **Scheduled triggers**: Is the interval appropriate? (`fiveMinutes` is rarely justified — prefer `hour`, `day`, or `week`)
- **Polling vs events**: Is a scheduled trigger polling for changes that could be caught by a product event trigger?
- **Event filtering**: Do product event triggers have `filter.expression` to limit invocations to relevant events?
- **ignoreSelf**: If the app writes to entities and listens to events on those entities, is `filter.ignoreSelf: true` set? (Jira only)
- **Early exit**: Do trigger handler functions check for work to do before running expensive operations?
- **External polling**: Could scheduled triggers polling external services be replaced with web triggers?

### Step 7: Forge Remote Analysis

Check if the app uses Forge Remote (`remotes:` section in manifest):
- If present, note that Forge Remote offloads compute to an external backend — the Forge function is not executed for those calls, saving FaaS invocations. But the app loses "Runs on Atlassian" eligibility.
- If not present, check whether the app would benefit from Forge Remote:
  - Compute-intensive operations (ML inference, image processing, complex report generation)
  - Long-running operations that approach the 25-second function timeout
  - Existing backend services the app duplicates logic from
  - Large-scale storage needs exceeding Forge Storage limits
- Note: For most apps, staying on-platform is simpler. Only recommend Forge Remote when there's a genuine need.

### Step 8: Compile Findings

Produce a single issue list sorted: **Critical → Warning → Info**.

---

## Security Checks

| ID | Check | Severity | What to Look For |
|----|-------|----------|-----------------|
| SEC-01 | Overly broad scopes | Critical | `read:jira-work` when only `read:jira-work:jira` (granular) is needed. Any `write:` scope that isn't actually used in code. Any `manage:` or `admin:` scope. |
| SEC-02 | Missing egress restrictions | Critical | Exte
Files: 3
Size: 30.9 KB
Complexity: 43/100
Category: Web Dev

Related in Web Dev