Skip to content
Merged
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,12 @@ yarn.lock

.claude

CLAUDE.md
.omc

test-results
playwright-report

# 一次性功能验证脚本(见 docs/VERIFICATION.md),不提交、不进 CI
e2e/scratch/

superpowers
89 changes: 89 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Repository Guidelines

This file provides guidance to AI coding agents (Claude Code, etc.) when working with code in this repository.

> **Note:** This is the single source of truth. `CLAUDE.md` only contains `@AGENTS.md` and re-imports this file — do not add content to `CLAUDE.md`; put all guidance here in `AGENTS.md`.

> **Before writing any code, read [`docs/DEVELOP.md`](docs/DEVELOP.md)** — the development spec (commands,
> project structure, coding style, UI & theme rules, testing mechanics, i18n, and the commit/PR workflow). This
> file keeps only the non-negotiable engineering principles and the architecture map; the concrete "how" lives
> in `DEVELOP.md`, and deep internals in [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md).

> **To manually verify a feature actually works, read [`docs/VERIFICATION.md`](docs/VERIFICATION.md)** — drive
> the real built extension end-to-end with one-shot throwaway scratch scripts (not the committed test suite).

> **Before any translation/localization work, read [`docs/translation/README.md`](docs/translation/README.md)** —
> the single source of truth for translation. Whenever you add or change localized content
> (`src/locales/<locale>/translation.json`, per-language docs, UI copy, or test snapshots), you must first read
> that guide and follow the matching `docs/translation/terminology-<locale>.md` if it exists.

> **Before adding, editing, reorganizing, or reviewing any contributor doc (this file or `docs/*`), read
> [`docs/DOC-MAINTENANCE.md`](docs/DOC-MAINTENANCE.md)** — keep the doc set organized (links resolve, index
> current, no duplication) and every claim factually true against the current branch (*if you can't grep it on
> this branch, don't claim it*).

> **Doc map:** [`docs/README.md`](docs/README.md) indexes every contributor doc (development, architecture,
> translation, contributing, localized READMEs).

## Project Overview

ScriptCat — Manifest V3 browser extension that runs Tampermonkey-compatible user scripts. TypeScript + React 18 + Rspack. Package manager is **pnpm** (preinstall enforces).

## Engineering Principles

These are non-negotiable and apply to every change, regardless of what `docs/DEVELOP.md` says about mechanics.

- **Fix root causes, not symptoms — refactor over patch.** No `as any` / `// @ts-ignore` / try-catch swallow / defensive skips to make errors disappear. When the clean fix needs restructuring, refactor rather than bolt on a patch (宁愿重构也不要打补丁). If a test fails, fix the code, not the test.
- **Confirm before you fix.** Before touching a reported bug, reproduce it and confirm it actually exists — never fix from assumption. Then capture it in a failing test, then fix, **in that order** (确定 bug 存在 → 写测试 → 修复).
- **TDD/BDD first.** Write failing tests **before** implementation, using BDD-style Chinese `describe`/`it` titles. (Runner, mocks, and how to run tests are in `docs/DEVELOP.md`.)
- **SOLID, high cohesion & low coupling — applied to the existing extension points.** `Repo<T>` for new entities, `Group.on(...)` for new messages. Inject `Group` / `IMessageQueue` / DAOs via constructor; don't `new` them inside methods. Depend on narrow interfaces (`IMessageQueue`, not `MessageQueue`).
- **Direct replacement over adapter sandwiches.** When swapping a backend/library, replace in place — no `interface Foo + LegacyImpl + NewImpl` unless both must coexist at runtime.
- **Scope discipline — stay in your lane.** Bug fix ≠ cleanup PR. Touch only the files the task requires; leave unrelated files untouched (不要动和任务不相干的文件). Don't add helpers, abstractions, validation, or backwards-compat shims you don't need today. Three similar lines beats a premature abstraction.
- **No dead code or `// removed` markers** — git remembers. Delete unused code outright.

## Architecture

> **Deep dive:** [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) — the human-facing internals guide for
> contributors working on ScriptCat core: process model, message passing, service/data layers, GM API system,
> script execution, and the build pipeline, with "how to extend" recipes. The section below is the quick map.

### Multi-Process Model

5 isolated contexts communicating via message passing:

```
Service Worker (src/service_worker.ts)
├── ExtensionMessage ──────────────→ Content Script (src/content.ts)
│ └── CustomEventMessage ──→ Inject Script (src/inject.ts)
└── ServiceWorkerMessageSend ──────→ Offscreen (src/offscreen.ts) (Chrome; Firefox uses EventPageOffscreenManager)
└── WindowMessage ──→ Sandbox (src/sandbox.ts)
```

> SW → Offscreen uses `ServiceWorkerMessageSend` (`clients.matchAll()` + `postMessage`) on Chrome and
> `EventPageOffscreenManager` on Firefox MV3; Offscreen replies to SW over `ExtensionMessage`. `WindowMessage`
> is the Offscreen ↔ Sandbox channel.

- **Service Worker** — central hub: script CRUD, chrome APIs, permission verification, resource caching, message routing
- **Content** — bridges SW and inject script
- **Inject** — runs in page context with `unsafeWindow`
- **Offscreen** — DOM-capable background environment for background/scheduled scripts
- **Sandbox** — isolated execution via `with(arguments[0])`; cron scheduling

Execution paths: page scripts → `chrome.userScripts`; background → SW → Offscreen → Sandbox; scheduled → cron in Sandbox.

### Message Passing (`packages/message/`)
`ExtensionMessage` (chrome.runtime — SW ↔ Content / Inject / Offscreen), `WindowMessage` (postMessage — Offscreen ↔ Sandbox), `ServiceWorkerMessageSend` (`clients.matchAll()` + `postMessage` — SW → Offscreen on Chrome), `CustomEventMessage` (CustomEvent — Content ↔ Inject), `MessageQueue` (cross-context broadcast).

### Service & Data Layers
- Services in `src/app/service/<context>/` — split by execution context. Constructor-injected `Group`, `IMessageQueue`, DAOs.
- DAOs in `src/app/repo/` extend `Repo<T>` (chrome.storage + cache): `ScriptDAO`, `ValueDAO`, `ResourceDAO`, `PermissionDAO`, `SubscribeDAO`.
- **GM API** split across content / SW / offscreen, each a `GMApi` (content built on `GM_Base`; SW — permission verify, cross-origin; offscreen — DOM-dependent background-script APIs); values via `ValueService`.

### Browser Extension APIs (MV3)
`chrome.userScripts` (page injection), Offscreen API (DOM in background), Declarative Net Request (intercepts `.user.js` URLs to trigger install flow).

### Key Packages

`message/` (with mocks), `filesystem/` (WebDAV + local), `cloudscript/`, `eslint/` (userscript lint config — `eslint-plugin-userscripts`-based `defaultConfig` for the in-app editor), `chrome-extension-mock/`.

> The project's own custom ESLint rule `require-last-error-check` (enforces `chrome.runtime.lastError` handling) lives in `eslint-rules/` at the repo root and is wired in `eslint.config.mjs` — not in `packages/eslint/`.
1 change: 1 addition & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
2 changes: 2 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Before submitting an issue, we recommend that you first check the [existing Issu

ScriptCat is an evolving project. If you encounter problems during use and are confident that these issues are caused by ScriptCat, we welcome you to submit an Issue. When submitting, please include detailed reproduction steps and runtime environment information.

**Security vulnerabilities are an exception — do not open a public Issue.** Report them privately following our [Security Policy](SECURITY.md), so a fix can be prepared before the issue is disclosed.

### Proposing New Features

We welcome you to propose new feature suggestions in Issues. To help us better understand your needs, we recommend that you describe the feature in as much detail as possible and provide what you think might be a possible solution.
Expand Down
59 changes: 47 additions & 12 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,56 @@
# Security Policy

ScriptCat is a Manifest V3 browser extension that runs user-provided scripts with broad
privileges, so we take security reports seriously. Thank you for helping keep users safe.

## Supported Versions

Use this section to tell people about which versions of your project are
currently being supported with security updates.
ScriptCat is distributed through the Chrome Web Store, Firefox Add-ons, and Edge Add-ons and
auto-updates to the latest release. Security fixes ship in **new releases only**:

| Version | Supported |
| --- | --- |
| Latest stable release | :white_check_mark: |
| Current beta channel | :white_check_mark: |
| Any older / superseded version | :x: — update to the latest |

| Version | Supported |
| ------- | ------------------ |
| 5.1.x | :white_check_mark: |
| 5.0.x | :x: |
| 4.0.x | :white_check_mark: |
| < 4.0 | :x: |
Because the stores auto-update, staying on the latest version is the most reliable mitigation.

## Reporting a Vulnerability

Use this section to tell people how to report a vulnerability.
**Please do not report security vulnerabilities through public GitHub Issues, Discord, the
Telegram group, or any other public channel** — doing so discloses the issue to attackers
before a fix is available.

Instead, report it privately:

1. **Preferred — GitHub private vulnerability reporting.** Open a private advisory at
<https://github.com/scriptscat/scriptcat/security/advisories/new> (repo **Security** tab →
*Report a vulnerability*). The report is visible only to you and the maintainers.
2. **Fallback.** If you cannot use that, send a **private** direct message to a maintainer via
[Telegram](https://t.me/scriptscat) or [Discord](https://discord.gg/JF76nHCCM7) asking for a
private channel — do not post details in the public chat.

Please include, as far as you can:

- affected version(s), browser, and OS;
- the impact — what an attacker can actually do;
- step-by-step reproduction, plus a proof-of-concept userscript or page if applicable;
- any suggested fix or mitigation.

### What to expect

- We aim to acknowledge your report within a few days and to keep you updated as we investigate.
- We follow **coordinated disclosure**: we prepare a fix and agree a disclosure timeline with you
before any public write-up, and we credit you unless you ask to stay anonymous.

## 中文上报指引

请**不要**通过公开的 GitHub Issue、Discord、Telegram 群或任何公开渠道提交安全漏洞——那会在修复发布前把问题暴露给攻击者。

请改用私密渠道:

- **首选**:GitHub 私密漏洞上报——在 <https://github.com/scriptscat/scriptcat/security/advisories/new> 提交私密 advisory(仓库 **Security** 标签页 → *Report a vulnerability*),仅你与维护者可见。
- **备选**:通过 [Telegram](https://t.me/scriptscat) 或 [Discord](https://discord.gg/JF76nHCCM7) **私信**维护者索取私密渠道,不要在公开群里贴细节。

Tell them where to go, how often they can expect to get an update on a
reported vulnerability, what to expect if the vulnerability is accepted or
declined, etc.
请尽量附上:受影响版本 / 浏览器 / 操作系统、影响说明(攻击者能做什么)、复现步骤与 PoC、以及可能的修复建议。我们会尽快确认并与你协调披露时间,默认在公开前先修复,并为你署名(除非你希望匿名)。
51 changes: 0 additions & 51 deletions docs/AI prompt.md

This file was deleted.

Loading
Loading