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
13 changes: 11 additions & 2 deletions .github/workflows/release-assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
tag:
description: Existing draft release tag
required: true
default: v0.1.0-demo.20
default: v0.1.0-demo.21
type: string
include_macos:
description: Include macOS (requires Developer ID signing and Apple notarization secrets)
Expand Down Expand Up @@ -168,7 +168,7 @@ jobs:
if [[ "$INCLUDE_MACOS" = "true" ]]; then
bun run release:build
else
bun run release:build --platforms=windows-x64,linux-x64
bun run release:build --platforms=macos-source,windows-x64,linux-x64
fi

- name: Verify built bundles
Expand All @@ -178,6 +178,7 @@ jobs:
run: |
set -euo pipefail
files=(
"release/PacePaper-${VERSION}-macos-source.zip"
"release/PacePaper-${VERSION}-windows-x64.zip"
"release/PacePaper-${VERSION}-linux-x64.tar.gz"
"release/PacePaper-${VERSION}-User-Guide.html"
Expand All @@ -197,6 +198,11 @@ jobs:
(cd release && shasum -a 256 -c SHA256SUMS.txt)
unzip -tq "release/PacePaper-${VERSION}-windows-x64.zip"
tar -tzf "release/PacePaper-${VERSION}-linux-x64.tar.gz" >/dev/null
unzip -tq "release/PacePaper-${VERSION}-macos-source.zip"
source_package="PacePaper-${VERSION}-macos-source"
unzip -p "release/PacePaper-${VERSION}-macos-source.zip" "${source_package}/Start PacePaper.command" > "$RUNNER_TEMP/Start PacePaper.command"
bash -n "$RUNNER_TEMP/Start PacePaper.command"
unzip -p "release/PacePaper-${VERSION}-macos-source.zip" "${source_package}/package.json" | cmp package.json -
if [[ "$INCLUDE_MACOS" = "true" ]]; then
unzip -tq "release/PacePaper-${VERSION}-macos-universal.zip"
extracted_mac="$RUNNER_TEMP/digitaldp-mac-verification"
Expand Down Expand Up @@ -231,6 +237,7 @@ jobs:
release/PacePaper-${{ steps.meta.outputs.version }}-macos-universal.zip
release/PacePaper-${{ steps.meta.outputs.version }}-windows-x64.zip
release/PacePaper-${{ steps.meta.outputs.version }}-linux-x64.tar.gz
release/PacePaper-${{ steps.meta.outputs.version }}-macos-source.zip
release/PacePaper-${{ steps.meta.outputs.version }}-User-Guide.html
release/PacePaper-${{ steps.meta.outputs.version }}-User-Guide.txt
release/PacePaper-${{ steps.meta.outputs.version }}-Release-Notes.txt
Expand All @@ -243,6 +250,7 @@ jobs:
run: |
set -euo pipefail
files=(
"release/PacePaper-${VERSION}-macos-source.zip"
"release/PacePaper-${VERSION}-windows-x64.zip"
"release/PacePaper-${VERSION}-linux-x64.tar.gz"
"release/PacePaper-${VERSION}-User-Guide.html"
Expand Down Expand Up @@ -286,6 +294,7 @@ jobs:
`PacePaper-${version}-User-Guide.txt`,
`PacePaper-${version}-Release-Notes.txt`,
"SHA256SUMS.txt",
`PacePaper-${version}-macos-source.zip`,
];
if (process.env.INCLUDE_MACOS === "true") expected.push(`PacePaper-${version}-macos-universal.zip`);

Expand Down
6 changes: 0 additions & 6 deletions LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

---

Project-name notice: the name "PacePaper" and the project's icon artwork are
not granted by this license. You may use them to refer to this project and its
derivatives, but not as the name or icon of an unrelated product.
38 changes: 28 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,27 @@ PacePaper is a local-network workspace for supervised examination practice and c

PacePaper is an independent school-practice tool. It is not an official examination-delivery system, is not affiliated with or endorsed by the International Baccalaureate, Cambridge University Press & Assessment, Pearson, College Board, ACT, or any other awarding body, and should not be used to deliver live high-stakes examinations.

![WeChat contact QR code for PacePaper](docs/wechat-qr.png)

## Download and run

| Your computer | What to do |
| --- | --- |
| **Windows 10/11 (x64)** | Download `PacePaper-0.1.0-demo.21-windows-x64.zip`, extract it, and run `PacePaper.exe`. Nothing to install; works offline. |
| **Linux (x64)** | Download `PacePaper-0.1.0-demo.21-linux-x64.tar.gz`, extract it, and run `PacePaper`. Nothing to install; works offline. |
| **macOS (Apple silicon or Intel)** | Download `PacePaper-0.1.0-demo.21-macos-source.zip`, extract it, and double-click `Start PacePaper.command`. The launcher offers to install Bun and installs dependencies; first launch needs internet. |

**These downloads are unsigned, so your computer may warn you the first time.**

- **Windows:** SmartScreen may show “Windows protected your PC”. Choose **More info → Run anyway**.
- **macOS:** If the launcher cannot be opened, right-click it and choose **Open**, or run once in Terminal:
`xattr -d com.apple.quarantine "$HOME/Downloads/PacePaper-0.1.0-demo.21-macos-source/Start PacePaper.command"`

PacePaper needs no account or licence key. The bundled sample and ordinary classroom use work offline apart from local-network sharing; optional YouTube or externally hosted HTTPS video needs internet unless hosted on the school network.

## Try PacePaper in two minutes

**Download the latest demo** for Windows or Linux from the [releases page](https://github.com/GowangInc/PacePaper/releases). Extract the archive, open `PacePaper.exe` (Windows) or `PacePaper` (Linux), and your browser opens the teacher dashboard automatically. There is nothing to install — no Bun, no server setup, no internet connection required. Mac users can run the current source with `Start PacePaper.command` after installing [Bun](https://bun.sh/).
Use the **Download and run** table above to choose the Windows, Linux, or macOS download.

On first launch you sign in with the default teacher login **`admin` / `admin`** (change it any time from the **Settings** section), and the Paper library already contains one preloaded **Sample paper** with no subject or IB branding. Open it, start a session, and you can try the whole workflow immediately — classes, timed phases, the candidate view, autosave, focus alerts, and printing — without creating anything first.

Expand Down Expand Up @@ -142,13 +160,13 @@ The development server listens on `127.0.0.1:9148` by default. `public/index.htm

## For developers — build the desktop releases

The release builder produces shareable, self-contained macOS, Windows, and Linux bundles. They use the normal browser for the existing teacher dashboard and printing workflow; Bun, Node.js, the source checkout, and `public/` folder are not required on the recipient computer.
The release builder creates self-contained Windows and Linux bundles plus a macOS source archive. With Apple signing and notarization credentials, it can also create a signed universal macOS application. Packaged applications use the normal browser for the teacher dashboard and printing; the source archive contains the project files needed by its launcher.

The Mac bundle must be signed with a Developer ID Application certificate and notarized by Apple. The release builder deliberately refuses to create an ad-hoc-signed Mac download, because Gatekeeper can report that download as damaged without offering **Open Anyway**.
The compiled Mac application bundle must be signed with a Developer ID Application certificate and notarized by Apple. The release builder refuses to create an ad-hoc-signed app because Gatekeeper can report it as damaged without offering **Open Anyway**. The source archive does not require Apple signing.

**Version 0.1.0-demo.20 is prepared for Windows x64 and Linux x64.** Student sign-in is intentionally low-friction for a trusted school network: students choose their class and name from the active roster, with no PINs or direct links. Candidate saves use revision checks, and safe exam ending waits for each active candidate's latest save unless the teacher records an override reason. Startup database checks and verified pre-migration snapshots protect existing work. The release retains teacher-only marking controls and is not an official examination-delivery system.
**Version 0.1.0-demo.21 ships Windows x64 and Linux x64 applications plus a macOS source archive for Apple-silicon and Intel Macs.** Student sign-in is intentionally low-friction for a trusted school network: students choose their class and name from the active roster, with no PINs or direct links. Candidate saves use revision checks, and safe exam ending waits for each active candidate's latest save unless the teacher records an override reason. Startup database checks and verified pre-migration snapshots protect existing work. The release retains teacher-only marking controls and is not an official examination-delivery system.

Once the signing and notarization credentials described below are available, run `bun run release:build`. The generated archives, standalone user guides, and checksums are placed in `release/`. On macOS, use the notarized `macos-universal` archive for both Apple-silicon and Intel Macs; extract the correct platform archive and start its PacePaper app or executable. The macOS bundle and Windows executable carry the PacePaper icon; the Linux archive includes the matching PNG for desktop integration. A packaged release automatically opens the teacher dashboard on the first available local port from `9148` through `9158`, so the address may be different from `9148` when another local instance is running. The initial release is intentionally offline: it makes no licence, activation, telemetry, or other network call. See the illustrated teacher-facing [`USER_GUIDE.html`](USER_GUIDE.html), its editable [`USER_GUIDE.md`](USER_GUIDE.md) source, and [`release/README.md`](release/README.md) for concise install, storage, signing, and classroom-sharing notes.
Run `bun run release:build` to generate selected archives, standalone user guides, release notes, and checksums in `release/`. Without Apple release credentials, build the unsigned macOS source archive and the Windows/Linux applications with `bun run release:build --platforms=macos-source,windows-x64,linux-x64`; the source ZIP is built from the committed tree. With Developer ID and notarization credentials, the default build also produces a signed universal macOS app. Packaged applications open the teacher dashboard on the first available local port from `9148` through `9158`. See the illustrated [`USER_GUIDE.html`](USER_GUIDE.html), its editable [`USER_GUIDE.md`](USER_GUIDE.md) source, and [`release/README.md`](release/README.md) for install, storage, signing, and classroom-sharing details.

### macOS release credentials

Expand All @@ -164,13 +182,13 @@ Set `DIGITALDP_MAC_NOTARY_KEYCHAIN` as well when the notary profile is stored in

The GitHub release workflow performs the same process using these repository secrets: `APPLE_DEVELOPER_ID_P12_BASE64`, `APPLE_DEVELOPER_ID_P12_PASSWORD`, `APPLE_NOTARY_KEY_BASE64`, `APPLE_NOTARY_KEY_ID`, and `APPLE_NOTARY_ISSUER_ID`. Do not put certificate passwords or private keys in this repository.

To build only Windows and Linux without Apple credentials, explicitly select them:
To build the Windows/Linux applications and macOS source archive without Apple credentials:

```sh
bun run release:build --platforms=windows-x64,linux-x64
bun run release:build --platforms=macos-source,windows-x64,linux-x64
```

For the GitHub workflow, set `include_macos` to `false` for that same platform set. The default still includes macOS and requires successful signing and notarization. Keep the release as a draft until the build and native Windows/Linux startup checks pass; publish only the files listed in that build's `SHA256SUMS.txt` plus the checksum file itself.
The source ZIP is built from the committed Git tree. The GitHub workflow builds this platform set when `include_macos` is `false`; its default also builds the signed and notarized `macos-universal` app. Keep the release as a draft until the build and native Windows/Linux startup checks pass; publish only the files listed in `SHA256SUMS.txt` plus the checksum file itself.

The current release builder keeps data outside the replaceable executable, in the per-user application-data location for the platform. It does not package a live database, teacher paper, student response, or protected reference material. A fresh release seeds one generic **Sample paper** with no subject, level, or IB branding, so new users can try the exam workflow immediately; teacher-created and imported papers remain in the local library. Previously downloaded apps retain the code and examples from their own release; source edits do not update those downloads. The teacher login remains `admin` / `admin` and is reset on every app launch; it is not suitable for real student data.

Expand Down Expand Up @@ -203,7 +221,7 @@ Open the room clock from the specific session for a projector or second screen.

Linked clocks follow authoritative timing across windows, independently of decorative titles and names. Timing saves reject stale edits from another window. For a simple paper, reading and writing minutes can be corrected from the clock while the exam is ready or live: a live save moves candidate phase boundaries and deadlines immediately, which is the fastest recovery when a sitting must be extended. Ended exams and fixed timed sections remain read-only. Mounted student views refresh their server timeline without replacing editors. Check the student view before a classroom trial.

Each published build is summarized in its release notes. See the [current release notes](release/RELEASE_NOTES-0.1.0-demo.20.md) for what ships and the verification limits.
Each published build is summarized in its release notes. See the [current release notes](release/RELEASE_NOTES-0.1.0-demo.21.md) for what ships and the verification limits.

Teacher-facing **Remove** actions archive records instead of permanently deleting them. Removed students cannot sign in, removed classes are unavailable for new sittings, and removed sittings disappear from the active exam list; all remain available under the corresponding **Removed** disclosure for restoration. Existing submissions stay retained and printable. Live sittings cannot be removed, classes with a live sitting must be ended first, and a student with unfinished live work cannot be removed until that response is submitted or the sitting ends.

Expand Down Expand Up @@ -255,4 +273,4 @@ Before a classroom pilot, also test the complete teacher and student journey on

## License and support

PacePaper is open source under the [MIT License](LICENSE). The PacePaper name and icon artwork are not part of the MIT grant (see the notice in the LICENSE file). This is an independent project with no affiliation to any awarding body; it is provided for school practice and familiarisation.
PacePaper is open source under the [MIT License](LICENSE). The PacePaper name and icon artwork are not part of the MIT grant (see [TRADEMARK.md](TRADEMARK.md)). This is an independent project with no affiliation to any awarding body; it is provided for school practice and familiarisation.
84 changes: 73 additions & 11 deletions Start PacePaper.command
Original file line number Diff line number Diff line change
@@ -1,20 +1,82 @@
#!/bin/zsh
#!/bin/bash
# PacePaper — macOS double-click launcher (runs from source).
#
# Double-click this file in Finder. It checks for Bun, offers to install it if missing,
# installs npm dependencies on first run, then starts PacePaper and opens your browser.
# Keep the Terminal window open while PacePaper is in use; Control-C stops it.
#
# This file needs the project folder beside it (package.json, server.ts, src/, public/).

set -u
cd "$(dirname "$0")" || exit 1
export PATH="$HOME/.bun/bin:/opt/homebrew/bin:/usr/local/bin:$PATH"

cd -- "${0:A:h}" || exit 1
export PATH="${HOME}/.bun/bin:/opt/homebrew/bin:/usr/local/bin:${PATH}"
pause_then_exit() {
[ -t 0 ] && { echo; read -r -p "Press Return to close this window. " _; }
exit "${1:-1}"
}

say() { printf '%s\n' "$1"; }

# --- 1. Bun -----------------------------------------------------------------
if ! command -v bun >/dev/null 2>&1; then
echo "PacePaper needs Bun to run from source. Install Bun, then open this file again."
echo "https://bun.sh/"
echo
read -r "?Press Return to close this window."
exit 1
say ""
say "PacePaper runs from source with Bun (https://bun.sh), which isn't installed yet."
say ""
say "Install it, then double-click this file again:"
say " curl -fsSL https://bun.sh/install | bash"
if [ -t 0 ]; then
echo
read -r -p "Install Bun now? [y/N] " answer
case "$answer" in
[yY]*)
say ""
say "Installing Bun..."
if ! curl -fsSL https://bun.sh/install | bash; then
say ""
say "Bun's installer failed. Check your internet connection, then try again."
pause_then_exit 1
fi
export PATH="$HOME/.bun/bin:$PATH"
if ! command -v bun >/dev/null 2>&1; then
say ""
say "Bun was installed but isn't on the PATH yet. Close this window, open it again, and retry."
pause_then_exit 1
fi
;;
*)
say ""
say "Nothing was installed. PacePaper needs Bun to start."
pause_then_exit 1
;;
esac
else
pause_then_exit 1
fi
fi

# --- 2. Gatekeeper quarantine ----------------------------------------------
if command -v xattr >/dev/null 2>&1 && xattr -p com.apple.quarantine "$0" >/dev/null 2>&1; then
say ""
say "Note: macOS quarantined this download. If double-clicking does nothing, run this once in Terminal:"
say " xattr -d com.apple.quarantine \"$0\""
fi

# --- 3. Dependencies (first run, or after package.json changes) -------------
if [ ! -d node_modules ] || [ package.json -nt node_modules ]; then
say ""
say "Installing dependencies (this happens once)..."
if ! bun install; then
say ""
say "Dependency install failed. PacePaper needs an internet connection for this first step."
pause_then_exit 1
fi
fi

echo "Starting PacePaper from source. Keep this window open while the app is in use."
echo "Press Control-C here when you want to stop PacePaper."
echo
# --- 4. Start ---------------------------------------------------------------
say ""
say "Starting PacePaper. Keep this window open while the app is in use."
say "Press Control-C here when you want to stop PacePaper."
say ""

exec bun run start:app
5 changes: 5 additions & 0 deletions TRADEMARK.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Trademark Notice

Project-name notice: the name "PacePaper" and the project's icon artwork are
not granted by this license. You may use them to refer to this project and its
derivatives, but not as the name or icon of an unrelated product.
Loading
Loading