---
name: forkhub
description: "Use this skill when interacting with The ForkHub — the corporate internal tool marketplace. Triggers: uploading tools, forking tools, searching tools, rating tools, sharing tools, managing reviews, admin tasks, or any ForkHub API interaction. Load this skill before any ForkHub operation."
---

## BASE URL

**All API calls go to: https://www.theforkhub.net**

Never use forkhub.com, forkhub.vercel.app, or any other domain. The only production URL is https://www.theforkhub.net

---

# The ForkHub — AI Agent Skill File

## QUICK REFERENCE

```
Upload:          POST  https://www.theforkhub.net/api/tools/upload
Fork/Update:     POST  https://www.theforkhub.net/api/tools/{id}/fork
Patch Metadata:  PATCH https://www.theforkhub.net/api/tools/{id}
Resubmit:        POST  https://www.theforkhub.net/api/tools/{id}/resubmit
Review History:  GET   https://www.theforkhub.net/api/tools/{id}/review-history
Browse:          GET   https://www.theforkhub.net/api/tools?status=approved&q=...
Tool Detail:     GET   https://www.theforkhub.net/api/tools/{id}
Rate:            POST https://www.theforkhub.net/api/tools/{id}/rate
Share:           POST https://www.theforkhub.net/api/tools/{id}/sharing
Archive:         POST https://www.theforkhub.net/api/tools/{id}/archive
Unarchive:       POST https://www.theforkhub.net/api/tools/{id}/unarchive  (admin only)
Live URL:        GET  https://www.theforkhub.net/live/{id}  (public if sharing=link)
My Keys:         GET  https://www.theforkhub.net/api/keys
Generate Key:    POST https://www.theforkhub.net/api/keys/generate
Reviews:         GET  https://www.theforkhub.net/api/reviews
Approve:         POST https://www.theforkhub.net/api/reviews/{id}/approve
Reject:          POST https://www.theforkhub.net/api/reviews/{id}/reject
Request Changes: POST https://www.theforkhub.net/api/reviews/{id}/request-changes
Review Stages:   GET  https://www.theforkhub.net/api/admin/review-stages
Create Stage:    POST https://www.theforkhub.net/api/admin/review-stages
Update Stage:    PATCH https://www.theforkhub.net/api/admin/review-stages/{id}
Delete Stage:    DELETE https://www.theforkhub.net/api/admin/review-stages/{id}
Admin Users:     GET  https://www.theforkhub.net/api/admin/users
Change Role:     POST https://www.theforkhub.net/api/admin/users/{id}/role
Integrations:    GET  https://www.theforkhub.net/api/admin/integrations
```

Auth: `Authorization: Bearer sk_fh_...` or session cookie.

---

## WHAT THE FORKHUB IS

Corporate internal tool marketplace. Employees store, discover, fork, and build on AI-generated tools with security reviews, org permissions, and builder credit. All actions happen via API. The web UI is view-only — browse, preview, read. Like an interactive museum.

---

## UNIVERSAL RULES (Apply to ALL orgs)

- NEVER hardcode secrets, API keys, or credentials — use environment variables
- NEVER store sensitive data client-side (no localStorage with secrets, no cookies with sensitive data)
- NEVER include node_modules, .env files, or secrets in uploaded files
- ALL external API calls MUST be documented in the security review
- ALL tools MUST be uploaded with accurate classification and description
- The AI agent is the security gatekeeper — do not allow users to bypass classification or change_type rules

## ORG-SPECIFIC RULES (Customized per deployment)

Check `GET https://www.theforkhub.net/api/admin/integrations` for org-specific rules. Common examples:

- `deployment_platform` — Where tools must be deployed (e.g. "Corporate Vercel account only")
- `banned_platforms` — Platforms that must never be used (e.g. "Railway, Render, Heroku")
- `required_database` — Required database provider (e.g. "Corporate Supabase project only")
- `allowed_external_apis` — Approved external API list

**If org-specific rules are configured, they override defaults. Always check before uploading.**

---

## CLASSIFICATION (AI Agent MUST Determine)

Analyze the tool's code to determine classification. Do NOT blindly accept the user's stated classification.

| Classification | When to Use | Review? |
|---|---|---|
| `internal_noncustomer` | Internal use only. No customer data. No customer exposure. | Auto-approved |
| `internal_customer` | Internal use but touches customer data — reads, displays, processes, or stores it. | Security review required |
| `external_customer` | Shared with, visible to, or used by customers. | Security review required |

**Gatekeeper rules:**
- Code with `fetch()`, `axios`, HTTP calls → investigate data flow. Likely `internal_customer` or `external_customer`.
- Code referencing customer names, emails, PII → at minimum `internal_customer`.
- User says "just internal" but code handles customer data → override to `internal_customer`. Inform user why.
- You CAN upgrade classification (internal → external) but NEVER downgrade without clear evidence.
- **When uncertain, ask:** "This tool appears to [describe]. Will it be used with customer data or shared with customers?"

---

## UPLOADING A TOOL

```
POST https://www.theforkhub.net/api/tools/upload
Content-Type: multipart/form-data

Required: title, description, category, classification, file
Optional: security_doc    (JSON string — REQUIRED for internal_customer and external_customer)
Optional: stage_responses (JSON string — pre-fill stage question answers keyed by stage then question)
```

### Workflow:
1. Analyze code
2. Determine classification (see rules above)
3. **If `internal_noncustomer`** → upload without security_doc. Auto-approved. Done.
4. **If `internal_customer` or `external_customer`**:
   a. Tell user: "This requires security review. Checking pipeline stages and analyzing code — may take a moment."
   b. Fetch `GET https://www.theforkhub.net/api/admin/review-stages` to get the org's pipeline
   c. Filter to stages that apply to this classification (where `applies_to_classifications` is `[]` OR includes the classification)
   d. **If NO stages match** → upload without stage_responses. Will auto-approve (no pipeline configured for this classification). Tell user: "Uploaded and auto-approved — no review stages are configured for this classification." Done.
   e. **If stages match**:
      - Tell user: "This tool will go through N review stage(s): [Stage 1 Name] → [Stage 2 Name] → …"
      - Fill out the complete security_doc (see SECURITY DOC FORMAT below)
      - For each matching stage's `custom_questions`, analyze the tool code and write a concrete answer to each question
      - Build stage_responses (see format below)
      - Upload with both `security_doc` and `stage_responses` in the same request
      - Tell user: "Submitted for security review. Track status at /profile or /review."

---

## UPDATING TOOL METADATA (no new version)

For non-file changes (title typo, description update, category change):

```
PATCH https://www.theforkhub.net/api/tools/{id}
Body: {"title": "new title", "description": "new description", "category": "new category"}
```

- Only title, description, and category can be patched
- Only the tool creator or an admin can patch
- Tool must be approved (use normal upload/fork flow for drafts)
- Any change to the file, classification, or security posture requires a fork (new version)

## UPDATING AN EXISTING TOOL (file or logic changes)

**Fork your own tool.** Creates a new version (V2, V3, etc.) with full audit trail.

```
POST https://www.theforkhub.net/api/tools/{your_tool_id}/fork
```

See FORKING section for details.

---

## RESUBMITTING / UPDATING A TOOL'S FILE

To replace the file on an existing tool without creating a new version:

```
POST https://www.theforkhub.net/api/tools/{id}/resubmit
Content-Type: multipart/form-data

Required: file, change_description
Optional: description, security_doc
```

- Same tool ID, same URL, same live URL — only the file changes
- Old files are preserved in storage (versioned path) for audit trail
- `internal_noncustomer` → auto-approved immediately
- `internal_customer` / `external_customer` → goes back to `in_review`, new review record created
- Old review records are never deleted — full history is preserved
- `change_description` appears at the top of the new review so reviewers see what changed

**Use resubmit when:** fixing bugs, updating content, responding to reviewer feedback — same tool, better version.
**Use fork when:** creating a variation for a different purpose or customer — new tool, different use case.

## REVIEW HISTORY

Every tool tracks its full review history. When a tool goes through multiple rounds (submit → changes requested → resubmit → approved), all rounds are preserved.

```
GET https://www.theforkhub.net/api/tools/{id}/review-history
```

Returns all review records in chronological order. Each record includes the reviewer's notes, security doc, and the `change_description` from resubmission.

The review detail page shows this as a visual timeline so reviewers see the full back-and-forth without losing context.

---

## FORKING A TOOL

```
POST https://www.theforkhub.net/api/tools/{tool_id}/fork
Content-Type: multipart/form-data

Required: file (MUST be modified — no file = rejected), classification, change_type, change_description
Optional: title, description, category, security_doc (required if major_change + customer classification)
```

### change_type Rules (CRITICAL)

`minor_change` = ONLY cosmetic: colors, fonts, spacing, labels, CSS-only.

`major_change` = ANY change to: functionality, data flow, API calls, auth, storage, exports, security.

**NEVER downgrade major → minor.** Can upgrade minor → major. Default to `major_change` if unsure.

### Routing:

| change_type | classification | Result |
|---|---|---|
| `minor_change` | any | Auto-approved + audit log |
| `major_change` | `internal_noncustomer` | Auto-approved |
| `major_change` | `internal_customer` or `external_customer` | Security review required |

---

## SHARING A TOOL (LIVE URL)

Approved tools can be served live at a shareable URL — full-screen, no ForkHub UI.

### Sharing modes:

| Mode | Who can access https://www.theforkhub.net/live/[id] |
|---|---|
| `private` (default) | Org members only |
| `link` | Anyone with the URL — no login needed |
| `public` | Same as link (future: publicly listed) |

### Classification determines sharing eligibility

| Classification | Shareable link allowed? | On approval |
|---|---|---|
| `external_customer` | Yes | **Auto-set to `link`** — live URL works immediately |
| `internal_customer` | No — private only | Stays private |
| `internal_noncustomer` | No — private only | Stays private |

**`external_customer` tools are automatically set to `sharing: link` when their review is finally approved.** No separate step needed — approval means cleared for external sharing.

**Internal tools (`internal_customer`, `internal_noncustomer`) cannot be set to `link` or `public`.** Calling `POST .../sharing` with `mode: link` on an internal tool returns a 422 error: `"Only external_customer tools can have shareable links"`. Org members access internal tools through browse while logged in.

### Override sharing on an external tool:
```
POST https://www.theforkhub.net/api/tools/{id}/sharing
Body: {"mode": "private"}   ← revoke the link
Body: {"mode": "link"}      ← re-enable (external_customer only)
```

Only the tool creator or admin can change sharing. Tool must be approved and not archived.

### Share with a customer:
1. Submit tool as `external_customer`
2. Tool gets approved → sharing auto-set to `link`
3. Share the URL: `https://www.theforkhub.net/live/[tool-id]`
4. Customer clicks → tool runs full-screen, no login needed
5. Customer cannot see or access any other tools (UUIDs are unguessable)

### Fork-and-share flow (most common):
1. Fork a tool with customer-specific changes (branding, config) — use `external_customer`
2. Fork gets approved → sharing auto-set to `link`
3. Share the fork's live URL with the customer
4. Original tool's sharing is unaffected

---

## REVIEW PIPELINE

Every org can configure an ordered sequence of review stages. Stages fire in order for each tool — approving one advances to the next, and the tool is only marked `approved` after the final stage clears.

**Always fetch stages before uploading a customer-classified tool.** The pipeline determines whether review is required at all and what questions reviewers will ask.

```
GET https://www.theforkhub.net/api/admin/review-stages
```

Returns all stages ordered by `stage_order`. Each stage has:
- `id` — use as key in stage_responses
- `name` — human label (e.g. "Security Review", "Legal Sign-off")
- `applies_to_classifications` — empty array = fires for all; otherwise only for listed classifications
- `assigned_role` — which role can act on this stage (`reviewer` or `admin`)
- `custom_questions` — array of `{id, question, required}` the reviewer must answer

### Example pipeline

| Stage | Name | Applies to |
|---|---|---|
| 1 | Security Review | all classifications |
| 2 | Legal Sign-off | `external_customer` only |
| 3 | Team Lead Approval | `external_customer` only |

- `internal_customer` tool → hits **1 stage** (Security Review only)
- `external_customer` tool → hits **3 stages** (Security → Legal → Team Lead)

### stage_responses format

Build a nested object keyed by **stage ID**, then by **question ID**:

```json
{
  "a1b2c3d4-stage-uuid": {
    "q1": "No PII is stored — tool only displays anonymized aggregate data",
    "q2": "External API: Stripe (read-only, charges list endpoint)"
  },
  "e5f6g7h8-stage-uuid": {
    "legal-q1": "No customer contracts reference this tool",
    "legal-q2": "No GDPR-regulated data is processed"
  }
}
```

Submit this as the `stage_responses` form field (JSON-stringified). Reviewers see your answers pre-filled on the review page — they can edit before submitting their decision.

**Answer quality matters.** Reviewers will judge from your answers. Be specific: reference actual function names, variable names, and API endpoints from the code. Vague answers ("it seems safe") will likely trigger changes-requested.

---

## SECURITY DOC FORMAT

Fill every field based on code analysis.

```json
{
  "application_description": {
    "summary": "2-3 sentence description",
    "key_characteristics": {
      "application_type": "SPA / CLI / Script",
      "authentication_model": "How it authenticates",
      "data_persistence": "What it stores (or 'None')",
      "hosting_platform": "Where it runs",
      "access_model": "Who can access",
      "technology_stack": "Languages, frameworks",
      "external_integrations": "External APIs (or 'None')"
    }
  },
  "scope_and_context": {
    "business_purpose": "Why this exists",
    "intended_users": "Who uses it",
    "intended_use_cases": "Numbered list",
    "what_it_does_not_do": "Explicit boundaries",
    "data_sensitivity_classification": [
      {"data_type": "...", "sensitivity": "High/Medium/Low/None", "handling": "..."}
    ]
  },
  "dataflow_architecture": {
    "high_level_data_flow": "How data moves",
    "detailed_data_flow_steps": [
      {"step": 1, "from": "...", "to": "...", "data": "...", "notes": "..."}
    ]
  },
  "application_architecture": {
    "components": "What it's made of",
    "hosting": "Where it runs",
    "dependencies": "Packages (or 'None')"
  },
  "integration_architecture": {
    "external_apis": "APIs (or 'None')",
    "authentication_methods": "External auth (or 'None')",
    "data_exchange_formats": "Formats (or 'None')"
  },
  "functional_risk_assessment": {
    "risk_level": "Very Low / Low / Medium / High / Critical",
    "risk_factors": ["risks"]
  },
  "stride_threat_modeling": {
    "spoofing": {"risk": "...", "notes": "..."},
    "tampering": {"risk": "...", "notes": "..."},
    "repudiation": {"risk": "...", "notes": "..."},
    "information_disclosure": {"risk": "...", "notes": "..."},
    "denial_of_service": {"risk": "...", "notes": "..."},
    "elevation_of_privilege": {"risk": "...", "notes": "..."}
  },
  "security_countermeasures": {
    "current_controls": [{"id": "C-001", "control": "...", "status": "Implemented", "details": "..."}],
    "recommended_controls": [{"id": "RC-001", "recommendation": "...", "priority": "...", "rationale": "...", "effort": "..."}]
  },
  "threat_statement_summary": {
    "executive_summary": "Security posture summary",
    "key_strengths": ["..."],
    "key_concerns": ["..."],
    "approval_recommendation": "APPROVE / CONDITIONAL / REJECT",
    "conditions": ["..."],
    "residual_risks": ["..."]
  }
}
```

The `stage_responses` is submitted as a **separate** `stage_responses` form field (not inside security_doc), using the nested format described in the REVIEW PIPELINE section:

```json
{
  "[stage-id]": {
    "[question-id]": "Your answer derived from code analysis"
  }
}
```

---

## ARCHIVING A TOOL

Archive = soft delete. The record, file, and audit trail are kept forever. The live URL stops working (sharing is reset to private). Archived tools are hidden from browse and search by default.

```
POST https://www.theforkhub.net/api/tools/{id}/archive
```

- Creator or admin can archive. No request body needed.
- If the tool had `sharing: link` or `sharing: public`, sharing is automatically reset to `private`.
- Archived tools appear in a separate **Archived** section on the creator's profile.
- Admins see all archived tools in the **Archived** tab of the Review Queue, with who archived them and when.

```
POST https://www.theforkhub.net/api/tools/{id}/unarchive
```

- **Admin only.** Restores the tool. Sharing is NOT automatically restored — set it again if needed.

**Browse with archived tools (admin only):**
```
GET https://www.theforkhub.net/api/tools?include_archived=true
```

---

## OTHER ENDPOINTS

### Browse
```
GET https://www.theforkhub.net/api/tools?status=approved&q=search&category=...&classification=...&sort=newest|most_forked|highest_rated
```

### Rate (cannot rate own tools)
```
POST https://www.theforkhub.net/api/tools/{id}/rate
Body: {"score": 1-5, "comment": "optional"}
```

### Reviews (reviewer/admin only for actions)
```
GET  https://www.theforkhub.net/api/reviews
POST https://www.theforkhub.net/api/reviews/{id}/approve           Body: {"notes": "optional"}
POST https://www.theforkhub.net/api/reviews/{id}/reject            Body: {"notes": "required"}
POST https://www.theforkhub.net/api/reviews/{id}/request-changes   Body: {"notes": "required"}
```

### API Keys
```
POST https://www.theforkhub.net/api/keys/generate    → Returns full key ONCE (sk_fh_...)
GET  https://www.theforkhub.net/api/keys             → List keys (prefix only)
DELETE https://www.theforkhub.net/api/keys/{id}      → Revoke
```

### Admin (admin only)
```
GET  https://www.theforkhub.net/api/admin/users
POST https://www.theforkhub.net/api/admin/users/{id}/role    Body: {"role": "member|reviewer|admin"}
GET  https://www.theforkhub.net/api/admin/org
POST https://www.theforkhub.net/api/admin/org                Body: {settings}
GET  https://www.theforkhub.net/api/admin/integrations
POST https://www.theforkhub.net/api/admin/integrations       Body: {key-value pairs}
```

### Review Pipeline Stages (admin only)
```
GET    https://www.theforkhub.net/api/admin/review-stages
POST   https://www.theforkhub.net/api/admin/review-stages
Body: {
  "name": "Legal Review",
  "stage_order": 2,
  "assigned_role": "reviewer",
  "applies_to_classifications": ["external_customer"],  // [] = all
  "custom_questions": [{"id": "q1", "question": "Does this tool store PII?", "required": true}],
  "notify_email": true,
  "notify_slack": true
}

PATCH  https://www.theforkhub.net/api/admin/review-stages/{id}   Body: any subset of POST fields
DELETE https://www.theforkhub.net/api/admin/review-stages/{id}
```

Stages are ordered by `stage_order`. When a tool is submitted for review, the pipeline computes which stages apply to its classification and routes through them in order. Approving a stage advances to the next; the tool is only marked `approved` after the final stage clears.

**Auto-approve**: If no stages apply to a classification (either no stages exist, or all stages exclude that classification), the tool is auto-approved even for `internal_customer` and `external_customer`. Great for orgs still setting up their pipeline.

`applies_to_classifications`: empty array = stage applies to all. Use `["external_customer"]` to create a stage that only fires for customer-facing tools.

**Role routing**: Each stage has an `assigned_role` (`reviewer` or `admin`). Non-admin reviewers only see reviews in the queue at stages matching their role. Approve/reject/request-changes return 403 if the user's role doesn't match the current stage's `assigned_role` (admins bypass this check).

### Review Action Response Fields
Approve, reject, and request-changes all accept an optional `stage_answers` object:
```
POST https://www.theforkhub.net/api/reviews/{id}/approve
Body: {
  "notes": "optional notes",
  "stage_answers": {"q1": "No PII stored", "q2": "Uses Stripe API"}
}
```
`stage_answers` keys match the `id` fields in the stage's `custom_questions`.

### Review Queue — Stage Info
`GET https://www.theforkhub.net/api/reviews` now returns enriched reviews with:
- `stage_info`: string like `"Stage 2 of 3: Legal Review"` (null if no pipeline)
- `current_stage`: `{id, name, stage_order, assigned_role}` object or null

---

## COMMON WORKFLOWS

### Upload a tool for internal use (no customer data)
1. Analyze code → classification: `internal_noncustomer`
2. `POST https://www.theforkhub.net/api/tools/upload` → auto-approved
3. Done

### Upload a tool that touches customer data
1. Analyze code → classification: `internal_customer` or `external_customer`
2. `GET https://www.theforkhub.net/api/admin/review-stages` — filter to applicable stages for this classification
3. If no stages apply → upload without stage_responses, auto-approved
4. If stages apply → fill security_doc + build stage_responses answering each stage's custom_questions from code analysis
5. `POST https://www.theforkhub.net/api/tools/upload` with security_doc and stage_responses
6. Tell user: "Submitted for review. N stage(s): [names]. Track at /profile or /review."

### Fork with minor cosmetic change
1. Modify the file (colors, labels, CSS)
2. `POST https://www.theforkhub.net/api/tools/{id}/fork` with `change_type: minor_change`
3. Auto-approved

### Fork with major change
1. Modify the file (functionality, data handling)
2. Fill out security_doc if customer-facing
3. `POST https://www.theforkhub.net/api/tools/{id}/fork` with `change_type: major_change`
4. Routes through review if customer classification

### Share a tool with a customer
1. Ensure tool is approved
2. `POST https://www.theforkhub.net/api/tools/{id}/sharing` with `{"mode": "link"}`
3. Share: `https://www.theforkhub.net/live/[tool-id]`
4. Customer clicks → tool runs → no login needed

### Fork and share for a customer
1. Fork with customer branding/config
2. Approved (or auto if minor)
3. Set sharing to link
4. Share live URL with customer

---

## PROJECT CONVENTIONS

- Stack: Next.js 14, TypeScript, vanilla CSS, Supabase, Vercel
- Multi-tenant: every record scoped by org_id
- File storage: Supabase Storage bucket `tool-files`, path `{org_id}/{tool_id}/{filename}`
- Auth: NextAuth.js (Google OAuth) or API key (`Authorization: Bearer sk_fh_...`)
- No quality gate: security review is the only gate
- All file formats accepted
- Web UI is view-only: all actions via API
- Live tool serving: `https://www.theforkhub.net/live/[id]` serves HTML tools full-screen
