- Uninstalling the extension deletes everything in its own storage. The four values on
- Toddle's site stay until the browser's data for web.toddleapp.com is
- cleared. Removing a licence key deletes the key; the last check's result and the
- account email stay until the extension is uninstalled.
+ {licenceSync.detail}
+
+
+ Uninstalling the extension deletes everything in its own storage on that computer.
+ The four values on Toddle's site stay until the browser's data for
+ web.toddleapp.com is cleared. Removing a licence key deletes the key (from
+ version {extensionVersions.next}, on every computer signed in to the same Chrome
+ account, so remove it before uninstalling if you want it gone from your Chrome account
+ too); the last check's result and the account email stay until the extension is
+ uninstalled.
A licence key carries the buyer's email address, and may also name who it is for:
the buyer's email, or for an organisation licence the school's email domain. Where it
diff --git a/src/pages/legal/privacy.astro b/src/pages/legal/privacy.astro
index 678b7b8..a3a1b1c 100644
--- a/src/pages/legal/privacy.astro
+++ b/src/pages/legal/privacy.astro
@@ -13,6 +13,7 @@ import {
dataProtection,
extensionDataFacts,
legal,
+ licenceSync,
security,
updatedLabel,
} from "../../data/legal";
@@ -42,7 +43,7 @@ const description =
extension makes only two connections outside Toddle: feedback you write in its menu
and choose to send, and, while a licence is entered, a once-a-day download of a
signed list of cancelled keys that sends nothing about you. Neither ever includes
- anything from Toddle. We do hold your email address if you bought something, the
+ anything from Toddle. {licenceSync.short} We do hold your email address if you bought something, the
way any shop does. This website asks before it measures anything and lets you take
all, some or none of it; the extension measures nothing at all, and never will.
diff --git a/src/pages/legal/security.astro b/src/pages/legal/security.astro
index 6685ce4..e0f8a56 100644
--- a/src/pages/legal/security.astro
+++ b/src/pages/legal/security.astro
@@ -18,6 +18,7 @@ import {
extensionVersions,
flags,
legal,
+ licenceSync,
security,
securityMailto,
updatedLabel,
@@ -51,7 +52,7 @@ const glance = [
{
label: "Stores",
value:
- "Settings, a licence key, the last licence check's result and the email of the Toddle account last seen, on the device. No student data.",
+ `Settings, a licence key, the last licence check's result and the email of the Toddle account last seen, on the device; from ${security.next}, the licence key also in Chrome's sync, never sent to Nyuchi. No student data.`,
},
{
label: "Tested",
@@ -335,14 +336,14 @@ const severityClass: Record = {
school's email domain. Where it does, the extension compares that with the Toddle
account signed in, inside the browser only, and sends it nowhere. A key that names no one
works for any account until it expires. Activating a key contacts nothing, and the
- key is never sent anywhere. It is kept in the extension's own storage, which Toddle's
- page cannot reach.
+ extension never sends the key to Nyuchi or anywhere else. It is kept in the
+ extension's own storage, which Toddle's page cannot reach. {licenceSync.detail}
No student data on the device
In the extension's own storage: the teacher's switches, the licence key if one was
- entered, the result of the last check for cancelled keys, and the email of the
+ entered (from {security.next}, also in Chrome's sync), the result of the last check for cancelled keys, and the email of the
Toddle account last seen signed in, to check who a licence is for. In Toddle's own
site storage, four housekeeping values: a copy of the switches and of which features
the licence allows, whether flags are concealed, the My classes choice, and the
diff --git a/src/pages/legal/terms.astro b/src/pages/legal/terms.astro
index 0e75d82..d9026ab 100644
--- a/src/pages/legal/terms.astro
+++ b/src/pages/legal/terms.astro
@@ -9,6 +9,7 @@
import BaseLayout from "../../layouts/BaseLayout.astro";
import {
legal,
+ licenceSync,
ownership,
pricing,
refunds,
@@ -127,7 +128,7 @@ const description =
address, and may also name who it is for: the buyer's email, for the Toddle account
with that address, or for an organisation licence the school's email domain, for
Toddle accounts on that domain. Where it does, the comparison happens in your browser
- only. While a key is entered, the extension downloads once a day a signed list of
+ only. {licenceSync.short} While a key is entered, the extension downloads once a day a signed list of
cancelled keys, sending nothing about you; a key we have cancelled stops unlocking the
licensed features once the extension has seen that list. If the check cannot be made,
the last result stands, so a network outage never switches a licence off. When a key
diff --git a/src/pages/toddle-enhancement-extension.astro b/src/pages/toddle-enhancement-extension.astro
index 774314b..87ddcce 100644
--- a/src/pages/toddle-enhancement-extension.astro
+++ b/src/pages/toddle-enhancement-extension.astro
@@ -22,6 +22,8 @@ import {
flags,
ownership,
pricing,
+ licenceSync,
+ upgrade,
refunds,
toddleNotice,
} from "../data/legal";
@@ -202,7 +204,7 @@ const facts = [
{
label: "What it stores",
value:
- "On your own machine only: your switch settings, your licence key if you have one, the result of the last check for cancelled keys, and the email of the Toddle account last seen signed in, to check who a licence is for; and, in Toddle's own site storage, a copy of the switches, whether flags are concealed, your My classes choice and the academic year Toddle is showing. No student data: what it reads is held in the tab's memory until the tab is closed or reloaded, and never written to storage.",
+ `On your own machine: your switch settings, your licence key if you have one, the result of the last check for cancelled keys, and the email of the Toddle account last seen signed in, to check who a licence is for; and, in Toddle's own site storage, a copy of the switches, whether flags are concealed, your My classes choice and the academic year Toddle is showing. ${licenceSync.short} No student data: what it reads is held in the tab's memory until the tab is closed or reloaded, and never written to storage.`,
},
];
@@ -590,9 +592,14 @@ const schema = [
Checkout is through Buy Me a Coffee, and your licence key is emailed to you
automatically, usually within a minute of paying. It is checked on your own machine, so activating it contacts
nothing and works offline — and one key covers your laptop and your classroom
- desktop. While a key is entered, the extension checks once a day for cancelled keys,
+ desktop. From version {extensionVersions.next} it follows your Chrome account, so you
+ enter it once; Chrome's sync carries it, and it is never sent to us. While a key is entered, the extension checks once a day for cancelled keys,
sending nothing about you.
+
+ Upgrading.{" "}
+ {upgrade.text}
+
Refunds.{" "}
{`${refunds.rule} ${refunds.how} ${refunds.key}`}
diff --git a/tests/seo.test.ts b/tests/seo.test.ts
index 08555d0..a67fd82 100644
--- a/tests/seo.test.ts
+++ b/tests/seo.test.ts
@@ -253,7 +253,9 @@ describe("the releases page", () => {
describe("prices", () => {
/* The organisation licence is US$149.99 a year, confirmed by the founder.
- Any other figure for it anywhere on the site is a mistake. */
+ Any other figure for it anywhere on the site is a mistake. The one other
+ figure allowed is the upgrade code's discount, "US$7 off" (`upgrade` in
+ src/data/legal.ts). */
it("states the organisation price as US$149.99 everywhere", () => {
for (const file of [
"toddle-enhancement-extension/index.html",
@@ -262,7 +264,13 @@ describe("prices", () => {
]) {
const text = built(file);
expect(text, file).toContain("US$149.99");
- expect(text, file).not.toMatch(/US\$\s?(?!149\.99\b|5\b)\d/);
+ expect(text, file).not.toMatch(/US\$\s?(?!149\.99\b|5\b|7 off\b)\d/);
}
});
+
+ it("shows individual licence holders the upgrade to the school's licence", () => {
+ const page = built("toddle-enhancement-extension/index.html");
+ expect(page).toContain("BXXF20VA");
+ expect(page).toContain("US$7 off the organisation licence");
+ });
});
From 05e0682fab72ccb5d7842ca84c6d6cfe282693bd Mon Sep 17 00:00:00 2001
From: Bryan Fawcett
Date: Wed, 7 Oct 2026 12:05:55 +0800
Subject: [PATCH 09/20] ci: a release to main is tagged as the next minor (#73)
* ci: a release to main is tagged as the next minor
The repo tagged staging merges as patches (staging-version.yml) but had
nothing on main, so a release to main produced no tag. This calls the
org's reusable auto-tag on main with the version computed from the tags
(channel main: the next minor), the RELEASE_BUMP_TOKEN, and a GitHub
release.
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
* ci: the main version workflow runs only on main
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
---------
Co-authored-by: Claude Opus 5.5
---
.github/workflows/main-version.yml | 35 ++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
create mode 100644 .github/workflows/main-version.yml
diff --git a/.github/workflows/main-version.yml b/.github/workflows/main-version.yml
new file mode 100644
index 0000000..68e591a
--- /dev/null
+++ b/.github/workflows/main-version.yml
@@ -0,0 +1,35 @@
+# Versioning policy (nyuchi/.github#80): every release to `main` is the next
+# MINOR, tagged on the merged commit, with a GitHub release. Staging merges are
+# patches (staging-version.yml); a major is only ever by hand.
+name: Main version
+
+on:
+ push:
+ branches: [main]
+ workflow_dispatch:
+ inputs:
+ bump:
+ description: Override the bump (major is only ever manual).
+ type: choice
+ options: [minor, major]
+ default: minor
+
+permissions:
+ contents: read
+
+jobs:
+ version:
+ # Only main: a manual run started from another branch tags nothing.
+ if: github.ref == 'refs/heads/main'
+ uses: nyuchi/.github/.github/workflows/reusable-auto-tag.yml@924e5b4d0983d31379aedbec02b990793f29c792 # main, 2026-10-04
+ with:
+ # Empty: the version is computed from the tags (package.json's version
+ # is not the release version).
+ version-command: ""
+ channel: main
+ bump: ${{ inputs.bump || '' }}
+ create-release: true
+ secrets:
+ token: ${{ secrets.RELEASE_BUMP_TOKEN }}
+ permissions:
+ contents: write
From 4f205d4f8946dbfef7b8f2a502341c87861eb64d Mon Sep 17 00:00:00 2001
From: Bryan Fawcett
Date: Wed, 7 Oct 2026 12:15:04 +0800
Subject: [PATCH 10/20] docs: release review fixes: the licence host per
version, one legal date, the changelog cut to 0.1.0 (#75)
* docs: release review fixes: the licence host per version, one legal date, the changelog cut to 0.1.0
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
* docs: the README's version is the latest tag
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
* docs: the changelog's licence-host entry names the versions
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
* docs: the staging patch tags start at v0.0.1
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
---------
Co-authored-by: Claude Opus 5.5
---
CHANGELOG.md | 38 ++++++++++++++++----
README.md | 2 +-
public/llms.txt | 5 +--
src/data/legal.ts | 5 ++-
src/pages/legal/data.astro | 3 +-
src/pages/legal/privacy.astro | 4 +--
src/pages/legal/security.astro | 3 +-
src/pages/toddle-enhancement-extension.astro | 6 ++--
8 files changed, 47 insertions(+), 19 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 21bf393..ffd59a6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,15 @@
# Changelog
-## Unreleased
+From this release the site's versions are its git tags, under the org's
+versioning policy: each merge into `staging` is a patch tag (from
+v0.0.1, 2026-10-04), each release to `main` the next minor. The 3.x and 2.x
+numbers below were the site's earlier, hand-kept numbering and are retired; the
+`version` in package.json is not the release version.
+
+## 0.1.0 — 2026-10-07
+
+Released with the Toddle Enhancement Extension 0.9.0, which is in Chrome Web
+Store review; the site describes it as the next version until it is live.
### Added
@@ -18,12 +27,26 @@
### Changed
+- **0.9.0's last changes, on the Releases page and the legal pages.** Text
+ and icons at the right size on Toddle, a flag's text drawn from its
+ Markdown, the Excusals tab's Time out column, and a licence key that
+ follows the teacher's own Chrome account (also kept in Chrome's synced
+ storage, never sent to Nyuchi). Every page that said the key stays on the
+ device says so; the wording lives once, in `licenceSync`
+ (`src/data/legal.ts`). The pricing section shows individual licence holders
+ the upgrade: code BXXF20VA, US$7 off the organisation licence only.
+- **One account of 0.9.0 across the site.** The gradebook's toolbar and the
+ Attendance dashboard's details run in closed shadow roots in 0.9.0 on every
+ page; the 6 October review's fixes reach schools in 0.9.0; each version
+ difference says from which version.
+- **A release to `main` is tagged as the next minor** (`main-version.yml`,
+ the org's reusable auto-tag, with a GitHub release).
- **The licence server's address is `licenses.nyuchi.com`.** The privacy
policy, the data and security pages, the vulnerability disclosure scope,
the extension page's allowlist note, llms.txt and SECURITY.md name the new
- host for the daily check for cancelled keys, and say that earlier versions
- of the extension ask `licences.nyuchi.dev`, the same server, which still
- answers. The legal pages' date moves to 7 October 2026.
+ host for the daily check for cancelled keys from version 0.9.0, and say
+ that 0.8.2, on the store today, asks `licences.nyuchi.dev`, the same
+ server, which still answers. The legal pages' date moves to 7 October 2026.
- **@bundu/ui 0.5.0** (was 0.1.1): the kit's updated tokens. The page
background is a cooler, neutral off-white; layout, type, buttons and the
Nyuchi brand colours are unchanged. Every check and test passes as before.
@@ -63,7 +86,8 @@
Toddle's admin portal. My classes switches on and off at once.
- For schools: the Admin console, Group Policy, Intune and macOS steps,
the organisation key pasted in once by each teacher, and allowing
- `licences.nyuchi.dev`, summarised on the extension page; the full guide
+ the licence server (now `licenses.nyuchi.com`, and `licences.nyuchi.dev`
+ for 0.8.2), summarised on the extension page; the full guide
on request. A link to the help centre's "How to use" collection.
- The data schema (the extension's `docs/data-schema.md`) is described on
the data handling page and the extension page, available on request.
@@ -82,7 +106,9 @@
PDPA is no longer named. The facts live once, in `dataProtection`
(`src/data/legal.ts`).
- **The legal pages match the extension's code, for 0.8.2 and 0.8.4**, and
- are dated 6 October 2026. Checked against the extension's data schema
+ were dated 6 October 2026. (Superseded within this release: the pages now
+ describe 0.9.0, say flags are concealed rather than hidden, and are dated
+ 7 October 2026; see the entries above.) Checked against the extension's data schema
(`docs/toddle-data-fields.md`) and its code:
- Student flags: from 0.8.4 they are shown as Toddle shows them, and the
free switch hides them everywhere; versions before 0.8.4 hid them by
diff --git a/README.md b/README.md
index 5251753..7b69a4c 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@


-**Version:** 3.0.0 | **Live:** [learning.nyuchi.com](https://learning.nyuchi.com) | **Default branch:** `main` | **Deploy:** Vercel
+**Version:** the latest git tag (see [CHANGELOG.md](CHANGELOG.md)) | **Live:** [learning.nyuchi.com](https://learning.nyuchi.com) | **Default branch:** `main` | **Deploy:** Vercel
---
diff --git a/public/llms.txt b/public/llms.txt
index 3af4cb3..69b52f1 100644
--- a/public/llms.txt
+++ b/public/llms.txt
@@ -81,7 +81,8 @@ community-based platforms. Nyuchi Web Services is its development division.
processed by Formspree; no student data, no page address, no licence key.
(2) Only while a licence is entered, at most once a day, the background
worker makes one plain request to https://licenses.nyuchi.com/v1/revocations
- (licences.nyuchi.dev, the same server, for earlier versions),
+ (from version 0.9.0; version 0.8.2, on the store today, asks
+ licences.nyuchi.dev, the same server),
sending no licence key, no identifiers, no cookies and no Toddle data; it
downloads a Nyuchi-signed list of SHA-256 fingerprints of cancelled keys
and checks its own key locally. Cloudflare sees the IP address as with any
@@ -135,7 +136,7 @@ community-based platforms. Nyuchi Web Services is its development division.
## Legal
-All dated 6 October 2026. Operated by Nyuchi Web Services, the development
+All dated 7 October 2026. Operated by Nyuchi Web Services, the development
division of Nyuchi Africa (Private) Limited, Harare, Zimbabwe.
- [Privacy policy](https://learning.nyuchi.com/legal/privacy): what the
diff --git a/src/data/legal.ts b/src/data/legal.ts
index bdf278e..33ec47c 100644
--- a/src/data/legal.ts
+++ b/src/data/legal.ts
@@ -61,7 +61,7 @@ export const dataProtection = {
},
} as const;
-/** The date above as people write it: "6 October 2026". */
+/** The date above as people write it: "7 October 2026". */
export const updatedLabel = new Date(
`${legal.updated}T00:00:00Z`,
).toLocaleDateString("en-GB", {
@@ -246,8 +246,7 @@ export const extensionDataFacts = [
{
claim:
"Outside connection two, only while a licence is entered: a daily check for cancelled keys.",
- detail:
- "At most once a day, and only while a licence key is entered, the extension's background worker makes one plain request to https://licenses.nyuchi.com/v1/revocations (earlier versions ask licences.nyuchi.dev, the same server); a key just entered is checked within 5 minutes. It sends no licence key, no identifiers, no cookies and no Toddle data. It downloads a list, signed by Nyuchi, of the fingerprints (SHA-256 hashes) of cancelled keys, checks its own key against that list on your machine, and keeps only the result. Cloudflare, which runs the server, sees your IP address as with any web request; Nyuchi does not log it. If the list cannot be fetched, the last result stands, so a network outage never switches a licence off.",
+ detail: `At most once a day, and only while a licence key is entered, the extension's background worker makes one plain request to https://licenses.nyuchi.com/v1/revocations (from version ${next}; version ${current}, on the Chrome Web Store today, asks licences.nyuchi.dev, the same server); a key just entered is checked within 5 minutes. It sends no licence key, no identifiers, no cookies and no Toddle data. It downloads a list, signed by Nyuchi, of the fingerprints (SHA-256 hashes) of cancelled keys, checks its own key against that list on your machine, and keeps only the result. Cloudflare, which runs the server, sees your IP address as with any web request; Nyuchi does not log it. If the list cannot be fetched, the last result stands, so a network outage never switches a licence off.`,
},
{
claim: "Exports are local.",
diff --git a/src/pages/legal/data.astro b/src/pages/legal/data.astro
index 8c78b7f..238f7db 100644
--- a/src/pages/legal/data.astro
+++ b/src/pages/legal/data.astro
@@ -247,7 +247,8 @@ const subprocessors = [
A daily check for cancelled keys, only while
a licence is entered: one plain request from the extension's background worker to
- https://licenses.nyuchi.com/v1/revocations (earlier versions ask
+ https://licenses.nyuchi.com/v1/revocations (from version
+ {extensionVersions.next}; version {extensionVersions.current}, on the store today, asks
licences.nyuchi.dev, the same server), sending no licence key, no
identifiers, no cookies and no Toddle data. It downloads a list, signed by Nyuchi, of
the SHA-256 fingerprints of cancelled keys and checks its own key locally. Cloudflare
diff --git a/src/pages/legal/privacy.astro b/src/pages/legal/privacy.astro
index a3a1b1c..1dea3a0 100644
--- a/src/pages/legal/privacy.astro
+++ b/src/pages/legal/privacy.astro
@@ -142,8 +142,8 @@ const description =
What is sent. One plain request to
https://licenses.nyuchi.com/v1/revocations, from the extension's
- background worker (earlier versions ask licences.nyuchi.dev, the
- same server). It carries no licence key, no identifiers, no cookies and no
+ background worker (from version {security.next}; version {security.version}, on the
+ store today, asks licences.nyuchi.dev, the same server). It carries no licence key, no identifiers, no cookies and no
Toddle data.
diff --git a/src/pages/legal/security.astro b/src/pages/legal/security.astro
index e0f8a56..be6352d 100644
--- a/src/pages/legal/security.astro
+++ b/src/pages/legal/security.astro
@@ -314,7 +314,8 @@ const severityClass: Record = {
A daily check for cancelled keys. At most
once a day, only while a licence is entered, the background worker makes one plain request
- to https://licenses.nyuchi.com/v1/revocations (earlier versions ask
+ to https://licenses.nyuchi.com/v1/revocations (from version
+ {extensionVersions.next}; version {extensionVersions.current}, on the store today, asks
licences.nyuchi.dev, the same server). It
sends no licence key, no identifiers, no cookies and no Toddle data. It downloads a
list, signed by Nyuchi, of the fingerprints (SHA-256 hashes) of cancelled keys, and
diff --git a/src/pages/toddle-enhancement-extension.astro b/src/pages/toddle-enhancement-extension.astro
index 87ddcce..a6f603e 100644
--- a/src/pages/toddle-enhancement-extension.astro
+++ b/src/pages/toddle-enhancement-extension.astro
@@ -199,7 +199,7 @@ const facts = [
{
label: "Its two outside connections",
value:
- "The Send feedback form, only when you press Send: what you typed and the version number, to our feedback form, processed by Formspree. And, only while a licence is entered, at most one request a day to licenses.nyuchi.com for a signed list of cancelled keys' fingerprints, which sends no key, no identifiers and no Toddle data; if it fails, the last result stands.",
+ `The Send feedback form, only when you press Send: what you typed and the version number, to our feedback form, processed by Formspree. And, only while a licence is entered, at most one request a day to licenses.nyuchi.com (licences.nyuchi.dev, the same server, in version ${extensionVersions.current}, on the store today) for a signed list of cancelled keys' fingerprints, which sends no key, no identifiers and no Toddle data; if it fails, the last result stands.`,
},
{
label: "What it stores",
@@ -513,8 +513,8 @@ const schema = [
it to staff; each teacher pastes it in once, from the welcome page or the
toolbar menu's Enter a licence key. If your network filters outbound
traffic, allow {toddleExtension.licenceHost}
- (and licences.nyuchi.dev, which earlier versions
- ask) so the daily check for cancelled keys can run. If it is blocked, licences keep
+ (and licences.nyuchi.dev, which version
+ {extensionVersions.current}, on the store today, asks) so the daily check for cancelled keys can run. If it is blocked, licences keep
working on the last result.
From edba47964954ea671c26b0e416702abb39d6c7c9 Mon Sep 17 00:00:00 2001
From: Bryan Fawcett
Date: Wed, 7 Oct 2026 12:22:15 +0800
Subject: [PATCH 11/20] docs: second release review fixes: what 0.9.0 reads,
versioned flag claims, fixed review history (#76)
* docs: second release review fixes: what 0.9.0 reads, versioned flag claims, fixed review history
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
* docs: the flags summary keeps its full stop
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
* style: no blank line in flags
Co-Authored-By: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01GHjaH1Vt2dVLWU68iz8tFq
---------
Co-authored-by: Claude Opus 5.5
---
.github/workflows/staging-version.yml | 2 ++
CHANGELOG.md | 7 +++++++
src/data/legal.ts | 8 ++++----
src/data/releases.ts | 2 +-
src/pages/legal/data.astro | 6 ++++--
src/pages/legal/security.astro | 2 +-
src/pages/legal/student-privacy.astro | 4 +++-
src/pages/legal/terms.astro | 2 +-
src/pages/toddle-enhancement-extension.astro | 4 ++--
9 files changed, 25 insertions(+), 12 deletions(-)
diff --git a/.github/workflows/staging-version.yml b/.github/workflows/staging-version.yml
index 4cc02fa..76bfb08 100644
--- a/.github/workflows/staging-version.yml
+++ b/.github/workflows/staging-version.yml
@@ -18,6 +18,8 @@ permissions:
jobs:
version:
+ # Only staging: a manual run started from another branch tags nothing.
+ if: github.ref == 'refs/heads/staging'
uses: nyuchi/.github/.github/workflows/reusable-staging-release.yml@924e5b4d0983d31379aedbec02b990793f29c792 # main, 2026-10-04
with:
bump: ${{ inputs.bump || '' }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ffd59a6..bc1be7b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,13 @@ Store review; the site describes it as the next version until it is live.
Attendance dashboard's details run in closed shadow roots in 0.9.0 on every
page; the 6 October review's fixes reach schools in 0.9.0; each version
difference says from which version.
+- **Second release review.** The 0.9.0 notes no longer say nothing new is
+ read (the data handling page lists each read, now including the teachers'
+ roles and photos the staff view shows); the flags summary, the search data
+ and the student privacy page say from which version flags are never hidden
+ and asked for each time; the first review's version is fixed at 0.8.2; the
+ terms and the product page say the cancelled-keys check is at most once a
+ day; the staging version workflow runs only on `staging`.
- **A release to `main` is tagged as the next minor** (`main-version.yml`,
the org's reusable auto-tag, with a GitHub release).
- **The licence server's address is `licenses.nyuchi.com`.** The privacy
diff --git a/src/data/legal.ts b/src/data/legal.ts
index 33ec47c..0f4e43d 100644
--- a/src/data/legal.ts
+++ b/src/data/legal.ts
@@ -173,8 +173,7 @@ export const upgrade = {
* Checked against the extension's SECURITY.md and docs/data-schema.md.
*/
export const flags = {
- summary:
- "The extension never hides Toddle's own student flags: they show as Toddle shows them. When your screen is shown to a class, a parent or a visitor, one free switch conceals them across Toddle, so what a flag says cannot be read from across the room.",
+ summary: `From version ${next}, the extension never hides Toddle's own student flags: they show as Toddle shows them. When your screen is shown to a class, a parent or a visitor, one free switch conceals them across Toddle, so what a flag says cannot be read from across the room.`,
reveal:
'In the student sidebar, "Show flags" shows one student\'s flags when you need them.',
limit:
@@ -203,7 +202,7 @@ export const extensionDataFacts = [
{
claim: "What it reads, feature by feature.",
detail:
- "Toddle answers with what the signed-in teacher's own account may see, and no more. The gradebook tools, when a teacher expands an assessment: its assessment tools as Toddle defines them (rubric criteria, descriptors and levels, grade scales and their colours, checklist items, scores, standards and learning goals), and each assigned student's name, email, student ID, submission status and results, including written responses and comments. No descriptor or level is written in the extension. The home page: each class's staff, to show its primary teacher and the My classes filter. A student's profile page: the teachers of each of the student's classes. The Attendance dashboard: each student's year group and the names of the periods, from Toddle's own request, and the primary teacher of the class each student is in now, for the “Now: class · teacher” line. The student sidebar, when a teacher opens a student or a class: the student's name, photo, year group and age (the date of birth is used to work out the age and is never shown), email, student ID and enrolment date; their family accounts and contacts, with names, relationships, phone numbers and emails; their homeroom advisor; the school's additional profile fields, of which only Student Group and Room number are ever shown; today's timetable and attendance marks; their active flags (see the next point); and each class's teachers, with their display titles and emails.",
+ "Toddle answers with what the signed-in teacher's own account may see, and no more. The gradebook tools, when a teacher expands an assessment: its assessment tools as Toddle defines them (rubric criteria, descriptors and levels, grade scales and their colours, checklist items, scores, standards and learning goals), and each assigned student's name, email, student ID, submission status and results, including written responses and comments. No descriptor or level is written in the extension. The home page: each class's staff, to show its primary teacher and the My classes filter. A student's profile page: the teachers of each of the student's classes. The Attendance dashboard: each student's year group and the names of the periods, from Toddle's own request, and the primary teacher of the class each student is in now, for the “Now: class · teacher” line. The student sidebar, when a teacher opens a student or a class: the student's name, photo, year group and age (the date of birth is used to work out the age and is never shown), email, student ID and enrolment date; their family accounts and contacts, with names, relationships, phone numbers and emails; their homeroom advisor; the school's additional profile fields, of which only Student Group and Room number are ever shown; today's timetable and attendance marks; their active flags (see the next point); and the teachers of each class, of today's blocks and of the homeroom, with their display titles, roles and emails, and their photos where Toddle gives them, which the sidebar's staff view shows when a teacher's name is clicked (it asks Toddle for nothing more).",
},
{
claim:
@@ -277,7 +276,8 @@ export const security = {
{
date: "2026-10-01",
label: "1 October 2026",
- version: extensionVersions.current,
+ /** Fixed: review history does not move when `current` does. */
+ version: "0.8.2",
findings: "1 to 12",
},
{
diff --git a/src/data/releases.ts b/src/data/releases.ts
index 4c34350..6e3dffb 100644
--- a/src/data/releases.ts
+++ b/src/data/releases.ts
@@ -121,7 +121,7 @@ export const releases: Release[] = [
items: [
"The flags switch, the student sidebar, My classes and teacher names, the gradebook's toolbar and controls, and the Attendance dashboard's details now run in the extension's own part of the browser, inside closed shadow roots that no script on Toddle's page can read or click into. Whether each one runs is decided by your switches and licence, never by Toddle's page.",
"Each rebuilt part was given its own security review on 6 October 2026, as were flag visibility and the sidebar's new staff and class views. Everything they found is fixed, each with a test. The Security page has the details.",
- "Nothing new is read from Toddle, and the extension sends nothing new anywhere. The one change is Chrome's: it now syncs your licence key through your own Chrome account, never to Nyuchi.",
+ "Everything it reads, including what is new in this release, comes from Toddle, as you, and stays in your browser; the data handling page lists each read. The extension sends nothing new anywhere. The one change is Chrome's: it now syncs your licence key through your own Chrome account, never to Nyuchi.",
],
},
],
diff --git a/src/pages/legal/data.astro b/src/pages/legal/data.astro
index 238f7db..5fb9edf 100644
--- a/src/pages/legal/data.astro
+++ b/src/pages/legal/data.astro
@@ -134,8 +134,10 @@ const subprocessors = [
work out the age and is never shown), email, student ID, enrolment date, family
accounts and contacts with relationship, phone numbers and email, homeroom advisor,
the school's additional profile fields (only Student Group and Room number are ever
- shown), today's timetable and attendance marks, and each class's teachers with
- their display titles and emails.
+ shown), today's timetable and attendance marks, and the teachers of each class, of
+ today's blocks and of the homeroom, with their display titles, roles and emails, and
+ their photos where Toddle gives them, which the sidebar's staff view shows when a
+ teacher's name is clicked (it asks Toddle for nothing more).