ChangelogRevision 04

18 Aug 2026

Student workflow, import, archive, and matching polish

This update records the implementation completed over the last two days. It is intentionally text-only: the work is grouped by workflow area so staff can see what changed, what is protected, and which parts remain planned for a later phase.

PART 01

Import & operations

Review portrait imports, replacements, normalization, and long-running work before it changes the archive.

01
improved

Portrait folder import now follows a review-first flow

Verified

Admins can drop a class, year, or parent folder, inspect the parsed students, and confirm the import before anything is saved.

What changed

The portrait import dialog now supports folder drag-and-drop, folder selection, filename parsing, thumbnail detection, invalid-file warnings, duplicate-ID warnings, name-conflict warnings, preview rows, and a clear import progress state. Original files remain unchanged.

Why

The old flow made it difficult to understand what a folder would create and gave staff little feedback during a large import.

02
changed

Year and class are inferred from the folder context

Verified

Entering class C with Year 13 is interpreted as 13C rather than an unrelated class named C.

What changed

Year groups and class names are normalized when they are read from folder paths or entered as defaults. The import preview shows the final Year / class value before confirmation, and the same normalization is used by the student directory to avoid equivalent values appearing as separate filters.

Why

Folder naming is not always consistent, but the resulting student record still needs one stable academic grouping.

03
addedprivacy

Archived student records can be replaced with explicit confirmation

Verified

A reused Student ID can restore/replace an archived test record only after the preview identifies the person and an admin confirms the action.

What changed

The import preview separates new students, archived records ready to replace, and active IDs that remain protected. Replacement names and IDs are shown before import, and the final action stays disabled until the replacement confirmation is checked.

Why

A deleted or archived test record can leave a real Student ID behind; silently blocking the real student or silently replacing the wrong person is unsafe.

04
improvedperformance

Import no longer waits for a full archive match

Verified

Portrait saving and archive matching are separate steps, so staff can finish the import and run matching from the Students page.

What changed

Portrait indexing still reports progress during import, but the expensive archive-wide matching pass is moved to Check ready references. The import status explains this distinction so a long-running match is not mistaken for a stuck upload.

Why

Matching every imported reference during one modal made large imports feel frozen and made failures difficult to recover.

PART 02

Student directory & lifecycle

Manage the active roster, progress cohorts, and preserve former-student records.

05
improved

Students controls are easier to scan and operate

Verified

Search, Filters, Year, and Class now sit in a clearer command row with larger hit areas and more stable responsive layout.

What changed

The student directory keeps the current/former split, search, quick Year/Class controls, advanced filters, sorting, progressive browsing, role-scoped views, and management actions while improving spacing, focus states, and control sizing on desktop and smaller screens.

Why

The previous control row was visually crowded and the native dropdowns were difficult to hit accurately.

06
fixedprivacy

Restricted student filtering now matches the stored privacy state

Verified

Students restricted through photo-use controls now appear when staff filter for Restricted.

What changed

The Restricted filter now checks both the consent restriction field and the separate photosHidden/photo-use restriction flag. The control is labelled Consent / photo use to make the relationship clear without merging the underlying data meanings.

Why

The Restrict photo use action and the consent dropdown previously wrote/read different fields, so the person could be restricted but disappear from the Restricted result.

07
fixed

Equivalent year values no longer create duplicate dropdown options

Verified

Values such as 13 and Year 13 are normalized to one Year 13 option.

What changed

Quick Year options are built from canonical year groups before de-duplication. This keeps the dropdown, year rail, class inference, and filter state aligned even when legacy records contain different spellings.

Why

The same year was previously shown twice because the directory used raw stored values in one place and canonical values in another.

PART 03

Photo archive

Browse academic years and large folder collections without losing the important counts and statuses.

08
improvedperformance

Academic-year folders use a scalable directory layout

Verified

An academic year can show hundreds of folders as a compact, scannable table instead of a wall of oversized cards.

What changed

The year workspace now presents Photos, Folders, Need attention, and Restricted shown at the top, followed by folder search, sorting, table columns, All photos, per-folder photo counts, Ready/Preparing status, updated time, and pagination. The default page size is 15 folders and the directory is designed for 300+ folders.

Why

A school archive will outgrow a card grid quickly; staff need to find a folder by name or sort order without loading every photo.

PART 04

Journey & matching

Build a long-term photo record with age-stage references and controlled archive matching.

09
improvedperformance

Ready-reference matching is durable and cancellable

Verified

Staff can run a class or roster-wide matching pass without keeping a browser loop open, and can cancel it safely.

What changed

The global Check ready references action queues a durable job, processes bounded batches with leases and retry policy, checks the AWS Rekognition budget before provider calls, reports progress, preserves completed results, and exposes cancellation. Individual Find more matches remains available from a student Journey.

Why

Large matching work must survive browser navigation and deployment timeouts while avoiding uncontrolled AWS calls.

10
changedprivacy

Journey exclude is reversible and scoped to one student

Verified

Staff can remove an incidental/edge-of-frame person from one student’s Journey without deleting the original photo or face data.

What changed

The Journey card now uses a compact X action with a hover/focus Exclude label. The decision is stored for the student-photo pair, excluded photos move to an expandable restore section, and Restore returns the photo to that student’s Journey. Other students and the archive remain unchanged.

Why

A student appearing at the edge of a group photo should lower their Journey inclusion without becoming a deletion or publication restriction.

11
improved

Journey photos can be selected individually for export

Verified

Staff can select the useful cards one by one instead of relying on Select all photos.

What changed

Journey photo cards now expose an individual selection control, selected state, selected count, preview-aware selection, Select all, Clear selection, Create collection, and Prepare export. This keeps the common case practical when only a few photos in a long Journey are needed.

Why

Selecting an entire Journey is often too broad for a real export request.

PART 05

Privacy & access

Make photo-use policy visible while keeping every viewer inside their authorised scope.

12
fixedprivacy

Journey rejection is no longer confused with publication restriction

Verified

Excluding a photo from a student Journey does not automatically mark the photo as Do not publish or change its privacy eligibility.

What changed

Journey curation, student photo-use restriction, consent restriction, and export eligibility remain separate concepts. A Journey reject only affects the selected student’s Journey; export and publication decisions continue to use their own server-side privacy checks.

Why

These decisions have different owners, scope, and consequences and should not be represented by one shared status.

PART 06

Release & reliability

Record the checks that separate implemented work from work that has reached production.

13
improvedperformance

Recent changes were typechecked, built, and deployed

Verified

The two-day implementation set is live on the production alias with the expected unauthenticated API behavior.

What changed

The latest source passed TypeScript checking and the Next.js production build, including public-data checks. Vercel production builds completed successfully, the homepage returned 200, and the reviews endpoint returned 401 when called without a session.

Why

The changelog should distinguish implemented work from work that has actually passed the deployment path.