diff --git a/CHANGELOG.md b/CHANGELOG.md index 65830d4..1073ede 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,35 @@ ### Changed +- **The extension page and legal pages describe 0.9.0, the next Chrome Web + Store release**, and say where 0.8.2, on the store today, differs. Patches + (0.8.3 to 0.8.9) are test releases that do not go to the store, so + `extensionVersions.next` is now 0.9.0, not 0.8.4. + - Student flags: the extension no longer hides Toddle's own flags. A + teacher can conceal them for a shared screen with the free switch, and + "Show flags" in the sidebar shows one student's. The wording is + "conceal" and "flag visibility", said once in `flags` + (`src/data/legal.ts`); a test fails on "hide flags" on the extension + page, the home page and in llms.txt. The sidebar asks Toddle for a + student's flags each time it opens. The value on Toddle's site is + `tee-blur-flags` (`gbx-hide-flags` in 0.8.2). + - The rebuild: the flag switch, the student sidebar and the home page's + additions run in the extension's isolated world, in closed shadow roots + (product page, Security page, llms.txt). The Security page adds the home + page channel's limit. + - The student sidebar: today's timetable as its own part, the student's + email, a class's teachers to email at once, and stepping aside in + 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 + 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. + - Data handling: the licence server keeps a SHA-256 of each key, never + the key itself, and the school's email domains for an organisation key. + - The second security review was of 0.8.4, a test release; its fixes are + in 0.9.0. - **The privacy policy rests on two laws: Zimbabwe's Cyber and Data Protection Act [Chapter 12:07] and the EU and UK GDPR**, applied to everyone. A new "The law we follow" section names POTRAZ as Zimbabwe's regulator, says diff --git a/astro.config.mjs b/astro.config.mjs index e90682d..a9b8591 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -35,7 +35,8 @@ export default defineConfig({ */ serialize(item) { item.url = item.url.replace(/(.+)\/$/, "$1"); - item.lastmod = new Date(); + // The sitemap item takes an ISO 8601 string, not a Date. + item.lastmod = new Date().toISOString(); return item; }, }), diff --git a/package-lock.json b/package-lock.json index c71d146..94891ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7313,9 +7313,9 @@ } }, "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.2.tgz", + "integrity": "sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==", "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" diff --git a/public/llms.txt b/public/llms.txt index 6d7b550..334a496 100644 --- a/public/llms.txt +++ b/public/llms.txt @@ -17,25 +17,36 @@ community-based platforms. Nyuchi Web Services is its development division. score-based rubrics, single-point rubrics, checklists, scores, comments, grade scales, learning goals — into one column per standard, criterion or item, so a teacher sees the whole class at once instead of opening a side - panel per student. It also adds a switch that hides Toddle's student flags - across the product, so a gradebook can be projected or screen-shared without - a flag being visible. From version 0.8.4, flags are shown as Toddle shows - them, and a staff member can hide them everywhere with the switch, which is - free; an eye button then shows one student's flags. Versions before 0.8.4 - hid them by default. It hides flags, not names. Free: the flag switch and - a "My classes" filter on the Toddle home page. With a licence: the - per-criterion gradebook columns, CSV export, primary teacher names, the - Attendance dashboard's details, and the student sidebar. The sidebar - (since version 0.8.2) works anywhere a student appears in Toddle (class - pages, the Attendance dashboard's Periods, Students and Excusals tabs, name links, - gradebook student cells) and shows a photo, grade, age and class of, Student - Group, room number, homeroom advisor, contacts with relationship, phone and - email, a "Now" card (current attendance code, block, class, room and - timetabled teacher), today's daily attendance code, and the student's - classes in Today and All tabs. Clicking a class opens a class view with its - current block, primary teacher, parent course, room and every teacher with - their display title and email. Message buttons open Toddle's own chat; the - extension sends no message itself. On the Attendance dashboard's Students + panel per student. It also gives teachers control of flag visibility on a + shared screen. From version 0.9.0 (the next Chrome Web Store release), + the extension no longer hides Toddle's own student flags; a teacher can + conceal them with one free switch, in Toddle's header or the extension's + menu, so a gradebook can be projected or screen-shared without what a flag + says being readable from across the room. In the student sidebar, "Show flags" shows + one student's flags. Concealing is a screen, not a lock: a concealed flag + can still show that a student has a flag. In version 0.8.2, on the store + today, flags are hidden from the start and the switch shows or hides them. + It conceals flags, not names. Free: the flag switch and a "My classes" + filter on the Toddle home page. With a licence (US$5 a year for one + teacher, US$149.99 a year for a school's email domain): the per-criterion + gradebook columns, CSV export, primary teacher names, the Attendance + dashboard's details, and the student sidebar. The sidebar works anywhere a + student appears in Toddle (class pages, the Attendance dashboard's Periods, + Students and Excusals tabs, name links, gradebook student cells), except + in School setup, Toddle's admin portal, where it steps aside. It shows a + photo, grade, age and class of, the student's email (click to copy), + Student Group, room number, homeroom advisor, contacts with relationship, + phone and email, a "Now" card (current attendance code, block, class, room + and timetabled teacher), and today's timetable as its own part, which + shows today's periods, "No classes today", or "Couldn't load timetable" + with a Retry button, without holding up the rest of the panel. Clicking a + class opens a class view with its current block, primary teacher, parent + course, room and every teacher with their display title and email; the + teachers can be emailed together. Message buttons open Toddle's own chat; + the extension sends no message itself. From version 0.9.0 the flag switch, + the student sidebar and the home page's additions run in the extension's + own isolated world, drawn in closed shadow roots that no script on + Toddle's page can read or click into. On the Attendance dashboard's Students tab, each student's year group and current class and teacher appear under their name, and the current block's column is outlined. It reads Toddle in the teacher's own browser, for the teacher at the screen, through an exact @@ -56,8 +67,8 @@ community-based platforms. Nyuchi Web Services is its development division. email domain), which is compared with the signed-in Toddle account inside the browser only. An organisation licence is one key for the school's email domain: anyone signed in to Toddle with an address at that domain is - covered. Unless flags are hidden, the sidebar asks Toddle for a student's - flags each time it opens, and keeps them only while it is open. Apart + covered. The sidebar asks Toddle for a student's flags each time it opens, + and keeps them only while it is open. Apart from Toddle, it has two outside connections, neither carrying Toddle data. (1) Opt-in feedback: the toolbar menu's "Send feedback" form, which, only when the person presses Send, sends what they typed (topic, message, and an email only if they @@ -76,11 +87,21 @@ community-based platforms. Nyuchi Web Services is its development division. licence key if there is 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 hidden, the My classes choice and the academic - year Toddle is showing. No student data is stored: what it reads stays in + switches, whether flags are concealed, the My classes choice and the + academic year Toddle is showing. No student data is stored: what it reads stays in the tab's memory until the tab is closed or reloaded. Rubric levels and descriptors are read from whatever a school has configured in Toddle; none - are defined in the extension. Security: https://learning.nyuchi.com/legal/security + are defined in the extension. Every query, stored value and request is + listed field by field in the extension's data schema, which is checked + against its code on every change; schools can ask privacy@nyuchi.com for + a copy. Schools deploy it from the Chrome Web Store by extension ID, with + a Google Admin console force-install (or Group Policy, Intune or a macOS + profile); an organisation key is pasted in once by each teacher, since it + cannot be pushed by policy. Teachers get each minor release (0.9.0 next) + from the Chrome Web Store; patch releases between them are for testing + and do not go to the store. Help: + https://support.nyuchi.com/en/collections/19764027-how-to-use-the-toddle-enhancement-extension + Security: https://learning.nyuchi.com/legal/security ## Where the learning content went @@ -138,8 +159,8 @@ division of Nyuchi Africa (Private) Limited, Harare, Zimbabwe. end-to-end network recorder that fails on any non-Toddle request, every release gated on them), two adversarial reviews (1 October 2026: two High, one Medium and several Low findings, all fixed in 0.8.2 with tests; - 6 October 2026: two Medium and two Low findings in the code for 0.8.4, all - fixed before it is published), and the residual limits (scripts Toddle + 6 October 2026: two Medium and two Low findings in the code for 0.8.4, a + test release, all fixed there and in 0.9.0), and the residual limits (scripts Toddle itself loads share the page and the teacher's access regardless of any extension; Toddle's pages send no Content-Security-Policy; a script already listening in Toddle's page can replay the extension's per-load diff --git a/src/data/legal.ts b/src/data/legal.ts index 29b02b4..d583e10 100644 --- a/src/data/legal.ts +++ b/src/data/legal.ts @@ -87,8 +87,8 @@ export const pricing = [ includes: [ "Every assessment tool expanded into per-criterion columns", "CSV export", - "The student sidebar, with where they are now and today's classes", - "The class view, and message buttons into Toddle's chat", + "The student sidebar, with where they are now and today's timetable", + "The class view, a class's teachers to email at once, and message buttons into Toddle's chat", "Primary teacher names, and the Attendance dashboard's Now line", ], }, @@ -107,28 +107,57 @@ export const pricing = [ ] as const; /** - * Which versions of the extension the legal pages describe. `current` is what - * teachers have from the Chrome Web Store (the v0.8.3 tag carries the same - * code). `next` is the release under Unreleased in the extension's changelog: - * reviewed, not yet published. Claims that differ between the two say "from - * version 0.8.4", so they stay true on both sides of the release. When `next` - * ships, move it to `current` and drop the "before" wording. + * Which versions of the extension the legal pages describe. + * + * How the extension is released: patches (0.8.3, 0.8.4, …) are GitHub + * releases, for testing, and never go to the Chrome Web Store; each minor + * (0.9.0, …) is released from the extension's `main` branch and published to + * the store. Teachers get minors. + * + * `current` is what teachers have from the Chrome Web Store (the v0.8.3 tag + * carries the same code). `next` is the next minor: everything under + * Unreleased in the extension's changelog, reviewed, already in the patch + * releases up to `latestPatch`, and not yet on the store. Claims that differ + * between the two say "from version 0.9.0" and say what `current` does, so + * they stay true on both sides of the release. When `next` ships, move it to + * `current` and drop the "before" wording. */ export const extensionVersions = { current: "0.8.2", sameCodeAs: "0.8.3", - next: "0.8.4", + next: "0.9.0", + /** The newest patch release (GitHub only, for testing). */ + latestPatch: "0.8.9", /** The oldest version security reports are accepted for. */ supportedFrom: "0.8.2", } as const; -const { next } = extensionVersions; +const { current, next } = extensionVersions; + +/** + * Student flags, said once. From 0.9.0 the extension never hides Toddle's own + * flags: a teacher can conceal them for a shared screen. The wording is + * "conceal" and "flag visibility", never "hide", and it promises no more than + * the extension does: how a concealed flag looks is still being refined, so + * this says only that what a flag says cannot be read from across a room. + * 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.", + reveal: + 'In the student sidebar, "Show flags" shows one student\'s flags when you need them.', + limit: + "Concealing is a screen, not a lock. A concealed flag can still show that a student has a flag. Concealing changes only what is drawn on the screen, never Toddle's data, and does not stop anyone at the computer opening a student's flags in Toddle.", + before: `In version ${current}, on the Chrome Web Store today, the extension hides flags from the start, and the switch shows or hides them.`, +} as const; /** * What the extension does with data. Each of these is a claim that can be - * checked against the source (the extension's docs/toddle-data-fields.md is - * the full schema, checked against its code), and each maps to an answer on - * the Chrome Web Store privacy form. + * checked against the source (the extension's docs/data-schema.md, formerly + * docs/toddle-data-fields.md, is the full schema, checked against its code on + * every change), and each maps to an answer on the Chrome Web Store privacy + * form. */ export const extensionDataFacts = [ { @@ -144,12 +173,12 @@ 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, when flags are shown; 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 each class's teachers, with their display titles and emails.", }, { claim: - "Student flags: shown as Toddle shows them, hidden with one free switch.", - detail: `From version ${next}, flags are shown as Toddle shows them. A staff member can hide them everywhere in Toddle with the switch, in Toddle's top bar or the extension's menu; the eye button then shows one student's flags. Versions before ${next} hid flags by default. Unless flags are hidden, the sidebar asks Toddle for a student's active flags each time it opens; while they are hidden, it asks only when someone presses the eye button. It keeps them only while that student's sidebar is open. Hiding flags changes only what is drawn on the screen, never Toddle's data. The flag switch is free and always will be.`, + "Student flags: Toddle's own are never hidden, and a teacher can conceal them for a shared screen.", + detail: `From version ${next}, the extension no longer hides Toddle's own student flags: they show as Toddle shows them, including in Toddle's student popover, with their links and documents. A teacher can choose to conceal flags, for a screen a class or a visitor can see, with the free flag switch in Toddle's top bar or the extension's menu. It is off until they switch it on; a teacher who had chosen to hide flags in an earlier version keeps that choice, as concealing. What a concealed flag says cannot be read from across a room, though it can still show that a student has a flag. ${flags.reveal} The sidebar asks Toddle for a student's active flags each time it opens, and keeps them only while that student's sidebar is open. Concealing changes only what is drawn on the screen, never Toddle's data. ${flags.before} In that version, while flags are hidden, the sidebar asks for a student's flags only when someone presses its eye button. The flag switch is free and always will be.`, }, { claim: "Your Toddle sign-in stays with Toddle.", @@ -173,7 +202,7 @@ export const extensionDataFacts = [ }, { claim: "What it stores: settings and licence details, and no student data.", - detail: `In Chrome's storage for the extension, on your device: your switches (the extension on or off, student flags, the student sidebar, My classes, primary teacher names, gradebook tools, and student details on the Attendance dashboard); your licence key, if you entered one; the result of the last check for cancelled keys (whether your key is on the list, the list's date and when the check was made, never the list itself); and the email address of the Toddle account last seen signed in, with the time, so the extension can check who a licence is for. That email is read on every Toddle page, with or without a licence key, and stays on the device. In the browser's storage for Toddle's own site: tee-settings, a copy of your switches and of which features the licence allows (no key and no email); gbx-hide-flags, whether flags are hidden, so they are hidden before the page is drawn; tee-course-view, whether you chose My classes in the home page filter; and tee-academic-year, the number of the academic year Toddle last asked for. Nothing it reads about students, classes, results or attendance is ever written to storage. Versions before ${next} have three switches: student flags, the student sidebar and primary teacher names.`, + detail: `In Chrome's storage for the extension, on your device: your switches (the extension on or off, student flags, the student sidebar, My classes, primary teacher names, gradebook tools, and student details on the Attendance dashboard); your licence key, if you entered one; the result of the last check for cancelled keys (whether your key is on the list, the list's date and when the check was made, never the list itself); and the email address of the Toddle account last seen signed in, with the time, so the extension can check who a licence is for. That email is read on every Toddle page, with or without a licence key, and stays on the device. In the browser's storage for Toddle's own site: tee-settings, a copy of your switches and of which features the licence allows (no key and no email); tee-blur-flags (gbx-hide-flags in version ${current}), whether flags are concealed, so they are concealed before the page is drawn; tee-course-view, whether you chose My classes in the home page filter; and tee-academic-year, the number of the academic year Toddle last asked for. Nothing it reads about students, classes, results or attendance is ever written to storage. Version ${current} has three switches: student flags, the student sidebar and primary teacher names.`, }, { claim: "What it holds in memory, and for how long.", @@ -227,7 +256,9 @@ export const security = { { date: "2026-10-06", label: "6 October 2026", - version: extensionVersions.next, + /** The code reviewed: the 0.8.4 patch, the rebuild's first steps. Its + fixes are in every later release, and in `next`. */ + version: "0.8.4", findings: "13 to 16", }, ], diff --git a/src/data/site.ts b/src/data/site.ts index 78c5a9a..ff8ec01 100644 --- a/src/data/site.ts +++ b/src/data/site.ts @@ -169,6 +169,14 @@ export const toddleExtension = { supportEmail: "support@nyuchi.com", /** Mailto used while there is no store listing, and for school enquiries. */ enquiry: "mailto:support@nyuchi.com?subject=Toddle%20Enhancement%20Extension", + /** "How to use the Toddle Enhancement Extension" in Nyuchi's help centre: + the page the extension's own Help button opens. */ + help: "https://support.nyuchi.com/en/collections/19764027-how-to-use-the-toddle-enhancement-extension", + /** The Chrome Web Store's update URL, for force-install policies set + outside the Google Admin console. */ + storeUpdateUrl: "https://clients2.google.com/service/update2/crx", + /** The licence server's host, which a school's network should allow. */ + licenceHost: "licences.nyuchi.dev", } as const; /** diff --git a/src/pages/index.astro b/src/pages/index.astro index aa7ff93..896dbf1 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -79,8 +79,8 @@ const description =
A Chrome extension for the Toddle gradebook. It expands every rubric - into per-criterion columns, exports the lot to CSV, and hides student - flags with one switch so you can share your screen safely. + into per-criterion columns, exports the lot to CSV, and conceals student + flags with one free switch when you share your screen.
tee-settings, a copy of the switches and of which features the
- licence allows (not the key, and no email); gbx-hide-flags, whether
- flags are hidden; tee-course-view, whether you chose My classes in the
+ licence allows (not the key, and no email); tee-blur-flags (gbx-hide-flags in version {extensionVersions.current}), whether flags are concealed;
+ tee-course-view, whether you chose My classes in the
home page filter; and tee-academic-year, the number of the academic year
Toddle is showing. None of it is about a student, and the extension sends none of it
anywhere.
diff --git a/src/pages/legal/data.astro b/src/pages/legal/data.astro
index 9a3bd6c..d9adc27 100644
--- a/src/pages/legal/data.astro
+++ b/src/pages/legal/data.astro
@@ -12,6 +12,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro";
import {
dataProtection,
extensionVersions,
+ flags,
legal,
refunds,
updatedLabel,
@@ -29,7 +30,7 @@ const held = [
what: "Licence purchases",
where: "Nyuchi's licence server and its database, on Cloudflare",
fields:
- "The email address the key was issued to, and the address that paid if different; the plan; how many were bought; for an organisation licence, the seat count and the buyer's answer to the order question (the school and roughly how many teachers); Buy Me a Coffee's purchase and item references; the key itself; when it was issued, emailed and refunded, its expiry, and its status.",
+ "The email address the key was issued to, and the address that paid if different; the plan; how many were bought; for an organisation licence, the school's email domains, the seat count and the buyer's answer to the order question (the school and roughly how many teachers); Buy Me a Coffee's purchase and item references; a fingerprint (SHA-256 hash) of the key, never the key itself; when it was issued, emailed and refunded, its expiry, and its status.",
},
{
what: "The order and payment",
@@ -136,13 +137,12 @@ const subprocessors = [
their display titles and emails.
And four small values in the browser's storage for Toddle's own site: tee-settings,
a copy of the switches and of which features the licence allows (no key and no
- email); gbx-hide-flags, whether flags are hidden; tee-course-view,
+ email); tee-blur-flags (gbx-hide-flags in version {extensionVersions.current}), whether flags are concealed; tee-course-view,
whether the teacher chose My classes in the home page
filter; and tee-academic-year, the number of the academic year Toddle
last asked for. No student data is stored.
@@ -257,6 +257,20 @@ const subprocessors = [
browser only, and sends it nowhere.
+ This page is the summary. The extension's data schema is the detail: every query it + can send to Toddle, with every field it asks for and what each is used for; every + value it stores, with its shape and when it is deleted; and every request that leaves + the device. It is written for a school's data protection lead or IT team, and for + Toddle. It is checked against the code on every change, so a query the code allows + that the schema does not describe fails the build, and where something could not be + confirmed from the code it is listed as an open question rather than guessed. Ask + {legal.privacyEmail} for a copy. +
+None of this comes from Toddle, and none of it is about students. diff --git a/src/pages/legal/privacy.astro b/src/pages/legal/privacy.astro index 98ad55e..aefd5c5 100644 --- a/src/pages/legal/privacy.astro +++ b/src/pages/legal/privacy.astro @@ -168,7 +168,9 @@ const description = meant to, or sends a query that is not on its fixed, read-only list. It has had two adversarial reviews. Every finding of the first, on {security.reviews[0].label}, was fixed in version {security.reviews[0].version}; every finding of the second, on {security.reviews[1].label}, - was fixed in version {security.reviews[1].version} before it is published. + of the code for version {security.reviews[1].version}, a test release, was fixed in + that release, and the fixes are in version {security.next}, the next on the Chrome + Web Store. The Security page sets out the security model, how it is tested, what the reviews found, the limits no extension can remove, and how to report a vulnerability.
diff --git a/src/pages/legal/security.astro b/src/pages/legal/security.astro index 7336728..2150214 100644 --- a/src/pages/legal/security.astro +++ b/src/pages/legal/security.astro @@ -16,6 +16,7 @@ import BaseLayout from "../../layouts/BaseLayout.astro"; import { extensionVersions, + flags, legal, security, securityMailto, @@ -190,8 +191,10 @@ const severityClass: Record- From version {security.next}, student flags are shown as Toddle shows them, and a - staff member can hide them everywhere with the free flag switch; versions - before {security.next} hid them by default. Unless flags are hidden, the sidebar asks Toddle - for a student's flags each time it opens, and keeps them only while it is open. The - CSV export is made in the browser and saved where the teacher's downloads go, by the - teacher's choice. + From version {security.next}, the extension no longer hides Toddle's own student flags; a + staff member can choose to conceal them for a shared screen with the free flag + switch. The sidebar asks Toddle for a student's flags each time it opens, and keeps + them only while it is open. {flags.before} The CSV export is made in the browser and + saved where the teacher's downloads go, by the teacher's choice. +
+ ++ The extension is being rebuilt so that as little of it as possible runs where + Toddle's own scripts run. From version {security.next}, the flag switch, the student + sidebar with a class's teachers, and the home page's My classes option and teacher + names run in the extension's own isolated part of the browser. What they draw on + Toddle's pages sits inside closed shadow roots, which no script on Toddle's page can + read or click into, and whether each one runs is decided by the extension's own + switches and licence, never by Toddle's page. What only Toddle's page holds (who was + clicked, the course list as it loads, Toddle's chat and icons) is read by small parts + with no interface of their own, which talk to the extension on private channels set + up before Toddle's own scripts run. The gradebook and the Attendance dashboard are + moving the same way.
- Part of the extension has to run inside Toddle's page to read the gradebook, which - means it shares that page with Toddle's own scripts. It is protected as far as a page - allows: + Part of the extension still has to run inside Toddle's page, to read the gradebook and + what Toddle draws, which means it shares that page with Toddle's own scripts. It is + protected as far as a page allows:
- The second review covered everything new in version {secondReview.version}: the - extension's own pages, rebuilt; the first rebuilt part that runs on Toddle's pages - (the flags switch, in a closed shadow root that no script on the page can reach); the - build that makes them; and the new switches. It also re-read the code that runs in - Toddle's page against the claims made about it. It found two medium-severity issues - and two low (findings {secondReview.findings}). All were fixed in - version {secondReview.version} before it is published, and none was in - version {security.version}. + The second review covered everything new in version {secondReview.version}, a test + release: the extension's own pages, rebuilt; the first rebuilt part that runs on + Toddle's pages (the flags switch, in a closed shadow root that no script on the page + can reach); the build that makes them; and the new switches. It also re-read the code + that runs in Toddle's page against the claims made about it. It found two + medium-severity issues and two low (findings {secondReview.findings}). All were fixed + in version {secondReview.version}, and the fixes are in every release after it, + including {security.next}. None was in version {security.version}. Each later + step of the rebuild (the student sidebar, the home page) was reviewed the same way as + it was made, and what those reviews found about the page's limits is set out below.
- The flag switch is a privacy aid, not a security control. It hides flags from the + The flag switch is a privacy aid, not a security control. It conceals flags on the screen; it does not hide names, and does not stop anyone deliberately opening a - student's profile. + student's flags or profile. {flags.limit}
diff --git a/src/pages/legal/student-privacy.astro b/src/pages/legal/student-privacy.astro index c12d853..b3dce6b 100644 --- a/src/pages/legal/student-privacy.astro +++ b/src/pages/legal/student-privacy.astro @@ -7,7 +7,13 @@ * enforced by the extension's closed-loop tests. */ import BaseLayout from "../../layouts/BaseLayout.astro"; -import { dataProtection, legal, updatedLabel } from "../../data/legal"; +import { + dataProtection, + extensionVersions, + flags, + legal, + updatedLabel, +} from "../../data/legal"; import { toddleExtension } from "../../data/site"; const title = "Student privacy — Nyuchi Learning"; @@ -70,6 +76,21 @@ const privacyMail = `mailto:${legal.privacyEmail}`; who can see what is still decided by the school's Toddle permissions.
++ Toddle lets a school mark students with flags, and those flags are the most sensitive + thing a teacher's screen can show. From version {extensionVersions.next}, the + extension no longer hides Toddle's own flags, so staff see what the school has recorded. + What it adds is flag visibility for a shared screen: a teacher can conceal flags + with one free switch before the screen is shown to a class, a parent or a visitor, + so what a flag says cannot be read from across the room. {flags.reveal} +
++ The sidebar reads a student's active flags from Toddle each time it opens, shows them + in that teacher's browser only, and forgets them when it closes. They are never + stored and never sent anywhere. {flags.limit} +
+Because no student data is collected, stored or transmitted by Nyuchi, Nyuchi does not diff --git a/src/pages/legal/terms.astro b/src/pages/legal/terms.astro index 3a6aa82..feba7dc 100644 --- a/src/pages/legal/terms.astro +++ b/src/pages/legal/terms.astro @@ -58,8 +58,8 @@ const description =
- Hiding student flags is free and is not licensed. It protects a child, so it is not - something we will ever put behind a payment. The My classes filter on the Toddle + Concealing student flags for a shared screen is free and is not licensed. It + protects a child, so it is not something we will ever put behind a payment. The My classes filter on the Toddle home page is free too. A licence covers the gradebook's per-criterion columns, the CSV export, the student sidebar, primary teacher names and the Attendance dashboard's student details. @@ -156,7 +156,7 @@ const description = works by reading the interface Toddle's own web app uses. Toddle does not publish that interface and is under no obligation to keep it stable. A Toddle release can change it, and when that happens a column may stop appearing or a flag may stop being - hidden. + concealed.
We will fix breakages as quickly as we can, and the extension is built to fail diff --git a/src/pages/toddle-enhancement-extension.astro b/src/pages/toddle-enhancement-extension.astro index bdc30fe..9818b5c 100644 --- a/src/pages/toddle-enhancement-extension.astro +++ b/src/pages/toddle-enhancement-extension.astro @@ -7,12 +7,17 @@ * know what it can see before putting it on a hundred machines. The flag * switch gets the most room because it is the part people will be asked to * justify. + * + * It describes version 0.9.0 (`extensionVersions.next`), the next release on + * the Chrome Web Store, and says where 0.8.2, on the store today, differs. + * Flags are "concealed", never "hidden": the extension no longer hides + * Toddle's own flags (see `flags` in src/data/legal.ts). */ import { Picture } from "astro:assets"; import type { ImageOutputFormat } from "astro"; import BaseLayout from "../layouts/BaseLayout.astro"; import { toddleExtension } from "../data/site"; -import { extensionVersions, pricing, refunds, toddleNotice } from "../data/legal"; +import { extensionVersions, flags, pricing, refunds, toddleNotice } from "../data/legal"; import gradebookShot from "../assets/screenshots/01-gradebook.jpg"; import sidebarShot from "../assets/screenshots/02-student-sidebar.jpg"; import todayShot from "../assets/screenshots/03-today.jpg"; @@ -38,9 +43,10 @@ const primaryCta = live ? { label: "Add to Chrome", href: toddleExtension.webStore! } : { label: "Tell me when it is live", href: toddleExtension.enquiry }; -/* `free` is the split the extension enforces: the flag switch and My classes - for everyone, the rest with a licence. Keep it in step with `pricing` in - src/data/legal.ts and the terms. */ +/* `free` is the split the extension enforces (its docs/licensing.md and + app/features/registry.ts): the flag switch and My classes for everyone, the + rest with a licence. Keep it in step with `pricing` in src/data/legal.ts, + the terms, and the licence email (nyuchi-licence-server, src/email.js). */ const features = [ { mineral: "cobalt", @@ -51,8 +57,8 @@ const features = [ { mineral: "malachite", free: true, - title: "Hide student flags", - body: `One switch in the Toddle header hides flags across Toddle: the gradebook, Attendance, the class portfolio, submissions, search results, profile headers and the student sidebar. An eye button shows one student's flags when you need them. It stays as you left it, so you can arm it before a lesson. From version ${extensionVersions.next}, flags show as Toddle shows them until you switch them off; earlier versions hid them from the start.`, + title: "Conceal student flags", + body: `${flags.summary} The switch sits in Toddle's header and the extension's menu, and stays as you left it, so you can set it before a lesson.`, }, { mineral: "gold", @@ -64,25 +70,25 @@ const features = [ mineral: "tanzanite", free: true, title: "My classes", - body: "The Toddle home page's course filter gains a third option beside All courses and My courses: only the classes you actually teach. It is remembered, and a tag by the heading says when it is on.", + body: "The Toddle home page's course filter gains a third option beside All courses and My courses: only the classes you actually teach. It switches on and off at once, it is remembered, and a tag by the heading says when it is on. It only appears where you are on a class.", }, { mineral: "terracotta", free: false, title: "The student sidebar", - body: "Click a student anywhere they appear in Toddle — class pages, name links, gradebook student cells, every tab of the Attendance dashboard — and they dock to the side until you close it: one larger photo, grade · age · class of, Student Group, room number, homeroom advisor, and contacts with their relationship, tap-to-call phone and email.", + body: "Click a student anywhere they appear in Toddle — class pages, name links, gradebook student cells, every tab of the Attendance dashboard — and they dock to the side until you close it: one larger photo, grade · age · class of, their email (click to copy it, or the envelope to write), Student Group, room number, homeroom advisor, and contacts with their relationship, tap-to-call phone and email. In School setup, Toddle's admin portal, it steps aside, so a click there does what Toddle does.", }, { mineral: "copper", free: false, - title: "Now, and today", - body: "Beside the photo, a Now card: the student's attendance code for the block happening now, the block, class, room and timetabled teacher — or their next class, or that they are finished or have no classes. Below, today's daily attendance code, and their classes in two tabs: Today, in time order with each period's attendance code and the current one first, and All.", + title: "Now, and today's timetable", + body: "Beside the photo, a Now card: the student's attendance code for the block happening now, the block, class, room and timetabled teacher. Today's timetable is its own part: today's periods in time order with each one's attendance code, “No classes today”, or “Couldn't load timetable” with a Retry button. The rest of the panel never waits for it.", }, { mineral: "sodalite", free: false, title: "The class view, and messages", - body: "Click a class for the block it is in now, its primary teacher, parent course and room, and every teacher with their display title and email. Message buttons for staff, the student, the family channel and each family member open Toddle's own chat, under your school's messaging rules.", + body: "Click a class for the block it is in now, its primary teacher, parent course and room, and every teacher with their display title and email. Tick the teachers you want and email them all at once, or copy their addresses. Message buttons for staff, the student, the family and each family member open Toddle's own chat, under your school's messaging rules.", }, { mineral: "cobalt", @@ -135,13 +141,17 @@ const shots = [ caption: "My classes · Free", }, { + /* Taken in version 0.8.2, which hid flags; retake it on 0.9.0. The alt + text describes the picture as it is. */ src: flagsShot, - alt: "A student's profile card in Toddle with a Show flags button where the flags would be, so they stay hidden until pressed; personal details are hidden behind grey bars.", - caption: "Hide student flags · Free", + alt: "A student's profile card in Toddle with a Show flags button where the flags would be, as in version 0.8.2; personal details are covered by grey bars.", + caption: "The flag switch · Free", }, { + /* Taken in version 0.8.2; 0.9.0 has a switch for every feature, grouped + by where it works. Retake it on 0.9.0. */ src: menuShot, - alt: "The extension's toolbar menu: the organisation licence and version, a Show student flags switch under Free, Student sidebar and Primary teacher names switches under With a licence, and Send feedback and Help.", + alt: "The extension's toolbar menu in version 0.8.2: the organisation licence and version, a Show student flags switch under Free, Student sidebar and Primary teacher names switches under With a licence, and Send feedback and Help.", caption: "The toolbar menu", }, { @@ -159,12 +169,13 @@ const shots = [ const facts = [ { label: "Where it runs", - value: "Only on web.toddleapp.com. It has no access to any other site.", + value: + "Only on web.toddleapp.com. It has no access to any other site. From version 0.9.0 the flag switch, the student sidebar and the home page's additions run in the extension's own isolated part of the browser, drawn inside closed shadow roots that no script on Toddle's page can read or click into; the gradebook and the Attendance dashboard are moving the same way.", }, { label: "What it reads", value: - "What Toddle already lets you see — gradebook results, rubric descriptors and levels as your school set them up, class staff, student details, today's timetable and attendance, and a student's flags when they are shown — through an exact list of read-only queries to Toddle's own API, for you at the screen, reusing the session you are already signed in with. It never asks for your password. Toddle's sign-in headers stay in the tab's memory, in one script in Toddle's page, and go nowhere but Toddle.", + "What Toddle already lets you see — gradebook results, rubric descriptors and levels as your school set them up, class staff, student details, today's timetable and attendance, and a student's flags each time the sidebar opens — through an exact list of read-only queries to Toddle's own API, for you at the screen, reusing the session you are already signed in with. It never asks for your password. Toddle's sign-in headers stay in the tab's memory, in one script in Toddle's page, and go nowhere but Toddle.", }, { label: "What it writes", @@ -184,13 +195,13 @@ 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 hidden, 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 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.", }, ]; const title = "Toddle Enhancement Extension — Nyuchi Learning"; const description = - "A Chrome extension for the Toddle gradebook: every rubric expanded into per-criterion columns, CSV export, and a switch that hides student flags so you can share your screen without compromising privacy."; + "A Chrome extension for the Toddle gradebook: every rubric expanded into per-criterion columns, CSV export, a student sidebar, and a free switch that conceals student flags when your screen is shared."; /* The claims here are the ones a search result or an assistant will repeat, so they mirror the privacy policy rather than the marketing copy. */ @@ -213,10 +224,10 @@ const schema = [ publisher: { "@id": "https://learning.nyuchi.com/#organization" }, featureList: [ "Expands every Toddle assessment tool into per-criterion columns", - "Hides student flags across Toddle with one switch", + "Conceals student flags across Toddle with one free switch, for a shared screen; never hides Toddle's own flags", "CSV export of results and submission status", "A My classes filter on the Toddle home page", - "A student sidebar anywhere a student appears in Toddle: photo, grade, contacts, where they are now, today's classes and attendance", + "A student sidebar anywhere a student appears in Toddle: photo, grade, email, contacts, where they are now, today's timetable and attendance", "A class view with every teacher, and message buttons that open Toddle's own chat", "The Attendance dashboard's Students tab with each student's year group, current class and teacher", "Primary teacher names beside each class", @@ -345,26 +356,26 @@ const schema = [
Toddle marks students with flags. They are useful — that is the point of - them — and they are exactly what you do not want on a projector, in a + them — and what they say is exactly what you do not want on a projector, in a screen share with a parent, in a lesson observation, or in a screenshot - pasted into a planning document. One switch takes them off the screen. + pasted into a planning document. One switch conceals them while your screen + is shared.
Students stay identifiable to you — you are still teaching, and a - gradebook of anonymous rows is no use to anyone. It is the flag that - comes off the screen, because that is the piece of information the + gradebook of anonymous rows is no use to anyone. It is what a flag says + that comes off the screen, because that is the piece of information the room should not be reading over your shoulder.
- Toddle draws the gradebook on an HTML canvas, so a flag there cannot - be hidden with styling. The extension empties the flag out of the - cell before the browser paints it, and hides the ones Toddle - renders as ordinary page elements everywhere else. + The extension no longer hides Toddle's own flags: they stay where Toddle puts + them, with their links and documents in Toddle's student popover. Concealing + them is your choice, off until you switch it on. {flags.reveal}
It stays on. The setting persists as you move around Toddle and across browser sessions, so it - is something you arm before a lesson rather than something you have + is something you set before a lesson rather than something you have to remember at the worst possible moment.
The switch shows its state. - It sits in the Toddle header and reads as on or off at a glance — - check it before you share, the same way you check the right window is - selected. + It sits in the Toddle header, the same size as Toddle's own buttons, and + reads as on or off at a glance — check it before you share, the same way + you check the right window is selected.
- It hides flags. It does not hide names, and it does not stop anyone - opening a student's profile deliberately. It works by changing what - Toddle draws, which means it depends on Toddle's own markup and a - Toddle release could change that. Arm it before you share, check the - switch is on, and treat it as a good lid — not as a compliance control - and not as a substitute for your school's safeguarding practice. + It conceals flags. It does not hide names. {flags.limit} It works by + changing what Toddle draws, which means it depends on Toddle's own markup, + and a Toddle release could change that. Switch it on before you share, check + it is on, and treat it as a good screen — not as a compliance control and not + as a substitute for your school's safeguarding practice. +
++ This describes version {extensionVersions.next}, the next release on the + Chrome Web Store. {flags.before}
No files to download, no Developer mode, nothing to unzip. Updates arrive on - their own, the way every other Chrome extension does. + their own, the way every other Chrome extension does. Stuck? + How to use the extension, in our help centre.
{primaryCta.label} @@ -442,16 +464,50 @@ const schema = [For a school
- Because it is on the Chrome Web Store, IT can force-install it to a teaching - organisational unit by its extension ID — the standard route, with no - self-hosted package to maintain and no Developer mode on anyone's machine. - Nothing for staff to click, and updates arrive on their own. + Because it is on the Chrome Web Store, IT can install it for every teacher by its + extension ID, with no self-hosted package to maintain and no Developer mode on + anyone's machine. Chrome keeps it up to date from the store. +
+{toddleExtension.extensionId}, from the Chrome Web Store.
+
+ Without the Admin console, the same force-install policy works through Group
+ Policy or Intune on Windows and a configuration profile on macOS, with the ID and
+ the store's update URL,
+ {toddleExtension.extensionId};{toddleExtension.storeUpdateUrl}.
+
+ The licence. An organisation licence is
+ one key for your school's email domain. A key cannot be pushed by policy, so send
+ 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}
+ so the daily check for cancelled keys can run. If it is blocked, licences keep
+ working on the last result.
- The extension ID is
- {toddleExtension.extensionId}. We will send
- you the console steps and the full answer to "what can this thing see?" — which
- somebody will ask, and should.
+ We will send you the full deployment guide, and the full answer to "what can this
+ thing see?" — which somebody will ask, and should.
Pricing
The flag switch protects a student, so it is not behind a price and never will @@ -555,6 +611,14 @@ const schema = [ }
+ The data schema. Every piece of Toddle + data the extension reads, every value it stores and every request it makes is + listed, field by field, in its data schema, written for a school's data + protection lead or IT team. It is checked against the code on every change: a + query the code allows that the schema does not describe fails the build. Ask us + for a copy. +
+If your IT team would rather verify this than take our word for it, a Chrome extension is a folder of readable JavaScript — they can unpack the installed package and read every line of it. We will also answer @@ -588,7 +652,16 @@ const schema = [ gradebook, and tells you when something could not be expanded rather than quietly showing you less. Report a break and we will chase the rename.
++ How updates reach you. Fixes are made and + tested as small patch releases, which do not go to the Chrome Web Store. When a + batch of them is ready, it is published to the store as the next version ({extensionVersions.next} is + next), and Chrome installs it on its own. +