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
109 changes: 109 additions & 0 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Bug report
description: Something in IPATool GUI does not work as expected
title: "[Bug] "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to report this. A screenshot helps, but a screenshot
alone usually cannot be acted on: the same dialog can come from the app, from
macOS, or from the `ipatool` CLI running underneath. The fields below are what
makes a report actionable.

- type: checkboxes
id: preflight
attributes:
label: Before you file
options:
- label: I searched existing issues and this is not a duplicate.
required: true
- label: This is not a security vulnerability (those go through the Security tab, see below).
required: true

- type: input
id: app-version
attributes:
label: App version
description: Settings → About in the app, or the installer filename.
placeholder: "0.1.1"
validations:
required: true

- type: dropdown
id: os
attributes:
label: Operating system
options:
- Windows
- macOS (Apple Silicon)
- macOS (Intel)
- Linux (AppImage)
- Linux (deb)
- Other / building from source
validations:
required: true

- type: input
id: os-version
attributes:
label: OS version
description: e.g. "Windows 11 23H2", "macOS 14.5", "Ubuntu 22.04".
placeholder: "macOS 14.5"
validations:
required: true

- type: input
id: ipatool-version
attributes:
label: ipatool engine version
description: |
Shown in Settings → Engine, or from `ipatool --version`. The engine is downloaded
separately from the app, so this is often where a problem lives.
placeholder: "2.6.0"
validations:
required: false

- type: textarea
id: what-happened
attributes:
label: What happened
description: What you did, what you expected, what you got instead. Exact error text is more useful than a description of it.
placeholder: |
1. Opened the app, clicked "Sign in"
2. Typed my Apple ID and password, clicked "Sign in"
3. A macOS "Keychain Not Found" alert appeared: A keychain cannot be found to store "account".
4. Expected: sign-in completes and the app shows my account.
validations:
required: true

- type: dropdown
id: reproducibility
attributes:
label: Does it happen every time?
options:
- Every time
- Only the first time after launching
- Intermittently
- Only happened once
validations:
required: true

- type: textarea
id: logs
attributes:
label: Logs
description: |
Activity → **Export logs** in the app, then attach the file (drag it into this box).
Credentials and tokens are redacted automatically, but give it a quick skim before posting.
render: text
validations:
required: false

- type: textarea
id: extra
attributes:
label: Anything else
description: Proxy/VPN, a recently migrated or reset keychain, antivirus, unusual locale — anything that might be relevant.
validations:
required: false
11 changes: 11 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
url: https://github.com/a23bc/ipatool-gui/security
about: Please report vulnerabilities privately through the Security tab, not as a public issue.
- name: Build, test and release details
url: https://github.com/a23bc/ipatool-gui/blob/main/docs/architecture.md
about: Architecture, the security model, packaging and CI are documented here.
- name: Install / Gatekeeper / SmartScreen problems
url: https://github.com/a23bc/ipatool-gui#install
about: The README covers the "damaged" Gatekeeper warning and the SmartScreen prompt.
27 changes: 27 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
## What changed

<!-- One or two sentences. If it needs more than that, it may be two PRs. -->

## Why

<!-- The problem this solves. Link the issue if there is one: Fixes #… -->

## How it was verified

<!-- Commands you ran, and what you observed. "npm test passes" is not enough on its
own — say which behaviour the new test would catch if it regressed. -->

## Not verified

<!-- Anything you could not check locally: no macOS machine, no real Apple ID, no
packaging toolchain, ... An honest gap is fine; a silent one is not. -->

## Checklist

- [ ] One concern only — unrelated changes are in another PR
- [ ] `npm run typecheck` passes
- [ ] `npm test` passes (coverage gate included)
- [ ] `npm run lint` passes
- [ ] New logic in `src/shared/` has tests
- [ ] No credential, token or local-only file is included
- [ ] User-visible behaviour changes are described above
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ coverage/
*.tsbuildinfo
.vitest-cache/

# Local assistant workspace (never part of a build)
.workbuddy/

# Local environment
.env
.env.*
Expand Down
92 changes: 92 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Contributor Covenant Code of Conduct

## Our Pledge

We as members, contributors, and maintainers pledge to make participation in this
project a harassment-free experience for everyone, regardless of age, body size,
visible or invisible disability, ethnicity, sex characteristics, gender identity and
expression, level of experience, education, socio-economic status, nationality,
personal appearance, race, religion, or sexual identity and orientation.

We pledge to act and interact in ways that contribute to an open, welcoming, diverse,
inclusive, and healthy community.

## Our Standards

Examples of behaviour that contributes to a positive environment:

- Demonstrating empathy and kindness toward other people
- Being respectful of differing opinions, viewpoints, and experiences
- Giving and gracefully accepting constructive feedback
- Accepting responsibility and apologising to those affected by our mistakes, and
learning from the experience
- Focusing on what is best not just for us as individuals, but for the overall
community

Examples of unacceptable behaviour:

- The use of sexualised language or imagery, and sexual attention or advances of any kind
- Trolling, insulting or derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information, such as a physical or email address, without
their explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional
setting

## Enforcement Responsibilities

Maintainers are responsible for clarifying and enforcing these standards and will take
appropriate and fair corrective action in response to any behaviour they deem
inappropriate, threatening, offensive, or harmful.

Maintainers may remove, edit, or reject comments, commits, code, issues and other
contributions that are not aligned with this Code of Conduct, and will communicate the
reasons for moderation decisions when appropriate.

## Scope

This Code of Conduct applies within all project spaces — issues, pull requests,
discussions, commit messages — and also when an individual is officially representing
the project in public spaces.

## Enforcement

Instances of abusive, harassing, or otherwise unacceptable behaviour may be reported to
the maintainer privately, by contacting [@a23bc](https://github.com/a23bc) on GitHub.
Reports are reviewed promptly and handled confidentially; the reporter's identity is
kept private. Please do not use the Security tab for this — it is for vulnerabilities.

All maintainers are obligated to respect the privacy and security of the reporter of any
incident.

## Enforcement Guidelines

Maintainers will follow these Community Impact Guidelines in determining the
consequences for any action they deem in violation of this Code of Conduct.

**1. Correction.** *Community impact:* use of inappropriate language or other behaviour
deemed unprofessional or unwelcome. *Consequence:* a private, written warning, with
clarity around the nature of the violation and an explanation of why the behaviour was
inappropriate.

**2. Warning.** *Community impact:* a violation through a single incident or series of
actions. *Consequence:* a warning with consequences for continued behaviour. No
interaction with the people involved for a specified period. Violating these terms may
lead to a temporary or permanent ban.

**3. Temporary ban.** *Community impact:* a serious violation of community standards,
including sustained inappropriate behaviour. *Consequence:* a temporary ban from any
sort of interaction or public communication with the project for a specified period.

**4. Permanent ban.** *Community impact:* demonstrating a pattern of violation of
community standards, including sustained inappropriate behaviour, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
*Consequence:* a permanent ban from any sort of public interaction within the project.

## Attribution

This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.1,
available at
<https://www.contributor-covenant.org/version/2/1/code_of_conduct.html>.

[homepage]: https://www.contributor-covenant.org
96 changes: 96 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# Contributing

Thanks for helping. This is a small project, so the fastest way to get a change
merged is to keep it small and to show how you verified it.

## Before you start

- **Bugs vs. security.** Bugs go in the issue tracker (use the bug report form — it
asks for the app version, OS, engine version and logs). Anything that looks like a
vulnerability goes through the **Security** tab, not a public issue.
- **Open an issue first for anything larger than a typo.** A new feature, a new
dependency, or a change to the IPC surface is worth a sentence of agreement before
you write the code.
- **This repository ships no `ipatool` binary.** The app downloads it at runtime and
verifies the published SHA-256. Please do not add a bundled copy.

## Development

Requirements: Node 20.19+ and npm.

```bash
npm install
npm run dev # Electron + Vite with HMR
```

Before opening a pull request, run the same checks CI runs:

```bash
npm run typecheck
npm test # vitest, coverage gate enabled
npm run lint
npm run build
```

Packaging (rarely needed for a normal change):

```bash
npm run dist:win # NSIS installer + portable exe
npm run dist:mac # .app (ad-hoc signed)
npm run dist:linux # AppImage + deb
```

## Where code goes

The layering matters more than the file count — put logic in the lowest layer that
can hold it:

| Path | What belongs there |
| --- | --- |
| `src/shared/` | Pure logic with no Electron or Node I/O: parsing, formatting, error classification, validation. **Fully unit-testable, and expected to be tested.** |
| `src/main/` | Electron main process: IPC handlers, queue, engine, settings, subprocess runner. |
| `src/preload/` | The frozen `window.api` bridge. Keep it a thin, explicit allow-list. |
| `src/renderer/` | React UI and zustand stores. Renderer state lives in stores, not components. |

Two rules that come up in review:

- **Everything crossing the IPC boundary is untrusted.** A renderer-supplied string
that becomes a path component or a URL segment must be validated in `src/main`
(see `src/shared/validate.ts`). Types do not survive the boundary.
- **User-visible behaviour changes need a sentence in the PR.** A different default,
a different error message, a new prompt — say so explicitly.

## Tests

- New logic in `src/shared/` needs tests. There is a per-area coverage gate, so an
untested module in the security-relevant paths will fail CI.
- `tests/` runs in the Node environment; `tests/dom/` covers renderer stores with a
stubbed `window.api`.
- A test that only proves "the code runs" is not worth much. Prefer one that fails
against the old behaviour — say in the PR what it catches.
- Signal/timing tests that cannot work on Windows should be scoped with
`describe.skipIf(process.platform === 'win32')` rather than deleted.

## Style

- Match the surrounding code. No reformatting of untouched lines, no "while I'm
here" refactors — they make a review impossible to follow.
- Comments explain **why**, not what. If a line looks odd, the reason it must be that
way belongs next to it.
- Commits: English, imperative mood, one logical change each (`fix(queue): ...`).
- No new runtime dependencies without discussing it first.
- Never commit credentials, tokens, or local-only files (editor config, scratch
scripts, exported logs). Keep those in `.git/info/exclude`, which is per-clone and
never pushed.

## Pull requests

- One concern per PR. If a change needs two independent explanations, it is two PRs.
- Describe: what was wrong, what you changed, how you verified it, and what you did
**not** verify. An honest "untested on macOS" is fine; a silent gap is not.
- CI must be green. `typecheck`, `test` and `build` all run on every PR.

## Licence

By contributing you agree that your work is licensed under the MIT licence, the same
as this project.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,9 @@ More build, test, and release detail: [docs/architecture.md](docs/architecture.m
| Doc | Contents |
| --- | --- |
| [docs/architecture.md](docs/architecture.md) | Multi-account model, pause/resume, progress parsing, security model, packaging & CI, code map |
| [Security](docs/architecture.md#安全披露) | Report vulnerabilities via Private vulnerability reporting — do not open a public issue |
| [docs/troubleshooting.md](docs/troubleshooting.md) | Engine not found, macOS keychain and Gatekeeper problems, proxy/network errors |
| [SECURITY.md](SECURITY.md) | What is in scope, and how to report a vulnerability privately — do not open a public issue |
| [CONTRIBUTING.md](CONTRIBUTING.md) | Development setup, the checks CI runs, where code belongs, what a useful test looks like |

Worth knowing (details in the docs):

Expand Down
4 changes: 3 additions & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ npm run dist:linux # AppImage + deb
| 文档 | 内容 |
| --- | --- |
| [docs/architecture.md](docs/architecture.md) | 多账户模型、暂停续传原理、进度解析、安全模型、打包与 CI、代码地图 |
| [安全披露](docs/architecture.md#安全披露) | 漏洞请走 Private vulnerability reporting,勿开公开 issue |
| [docs/troubleshooting.md](docs/troubleshooting.md) | 引擎装不上、macOS 钥匙串与 Gatekeeper 问题、代理/网络报错对照表 |
| [SECURITY.md](SECURITY.md) | 安全边界与私密报告渠道,勿开公开 issue |
| [CONTRIBUTING.md](CONTRIBUTING.md) | 开发环境、CI 检查项、代码该放哪一层、什么算有用的测试 |

几个值得知道的设计点(细节在文档里):

Expand Down
Loading
Loading