Thnkrr — Where Things Stand, 29 September 2026

What this is: a status report on the four features built in this run of work. Each feature becomes a pair of pull requests (PRs: requests to add finished code to the main version): one for the server code (the API) and one for the web app. Below, "PR 1" means that pair. For each feature it covers what we built, what is still a stand-in, and what ships.

A few words used below:


In one minute


The four PRs at a glance

#FeatureDecisionBranchBuilt onPushed?
1Moderation before the pilot + care referralsD-67 (plus the research in docs/20)feat/moderation-pre-pilotmainMostly. Not yet pushed: the care referrals (both repositories) and today's doc updates (API)
2Photos in postsD-66feat/post-imagesmainYes, fully
3Video in postsD-69feat/post-videosPR 2 (it needs photos)No
4Parental consentD-68feat/parental-consentmainNo
—Everything together, for testing—dev/pilotall fourNo (never becomes a PR)

Suggested merge order: 1 → 2 → 3 → 4.

Two things to do while merging:

  1. Migration numbers. Every branch numbered its database changes from the same starting point, so each PR after the first renumbers its migration to the next free number when it's merged. dev/pilot has already done this (numbers 0016–0019), so we know it works.
  2. Three merge fixes must be re-made. They exist only on dev/pilot today. With the suggested order, PR 2 (photos) carries fix 1, PR 3 (video) carries fixes 2 and 3, and PR 4 (consent) carries none. They are listed in the dev/pilot section below.

PR 1 — Moderation before the pilot, plus care referrals

In one line: everything a student writes or uploads is checked before anyone else sees it; the legal safety duties are built; and a reviewer can refer a student at risk to a named person at their school.

What we built

ModuleWhat it doesWhere the code lives
Tougher text checkCatches disguised writing: numbers for letters, look-alike characters, a phone number with spaces in it. Guards the AI check against "ignore your instructions" tricks.API moderation/normalize.ts, stage1.ts
Nothing shown before it's clearedPosts, comments, messages and profile text wait until they pass. If content is deleted during review, its review closes too. A decision is saved completely or not at all, so nothing is left half-approved.API moderation/service.ts, feed, messaging
Smarter AI checkThe AI sees a short excerpt of the conversation, with names replaced by roles. Every decision records which version of the rules it used.API moderation/service.ts, classifier*.ts
One review list, worst firstFour lanes: at-risk students, child safety, held messages, everything else. A student who keeps trying to sneak past the filter has everything new they post sent to a person for 24 hours.API moderation/routes.ts; web ModerationPage, priority.ts, QueueCard
Report and removeProfile text and school descriptions can be reported. A reviewer can remove a live post, comment, profile photo or banner for breaking the rules, without waiting for a report.API moderation/*; web RemoveDialog, ReportDialog
Vendor test kitRuns the same test set through any AI checker, so suppliers are compared fairly (the "bake-off").API scripts/moderation-eval.ts
The legal safety layerFive parts, listed below the table.API safety/*, lib/phash.ts; web SafetyPages, SafetyPanels
Care referrals (D-67)A reviewer refers a student at risk to a named care contact at their school. The school must reply within 24 hours (1 hour if urgent). An overdue referral tells our team to phone the school. The school gets a Student support page. Thnkrr never contacts parents.API care/*; web ReferDialog, CarePanel, StudentSupport, CareCard
Test stub made safeThe laptop stand-in that approves everything never approves self-harm language.API classifier-dev.ts

The legal safety layer, in five parts:

New database tables: safety cases, removal requests, the media block list, complaints (grievances) and care referrals.

Docs:

Stubs and stand-ins left

SwitchWhat it does todayBefore going live
MODERATION_DEV_AUTOAPPROVEOn a laptop with no AI key, approves everything except self-harm language. Forced off in production.Run the bake-off, then pick the real AI checker. Today our code can only talk to Claude. The two recommended options — OpenAI's free moderation check, and the gpt-oss-safeguard model rented through Amazon (Bedrock) — still need that link written.
SAFETY_HANDLER_IDSEmpty, so any moderator can open a safety case.Set it to the two named people before the first real case.
Reporting to NCMEC (the US National Center for Missing & Exploited Children) and the Indian policeThe case record and the runbook (docs/22) are built. A named person files the report by hand.We aren't registered with NCMEC yet. The founder names the filer.
Block listHolds only images we removed ourselves.Connect the free child-abuse lists after the applications are approved.

Not built (known, planned)

Known issues

Last test run (28 Sept, on this branch): 341 of 341 API tests passed.


PR 2 — Photos in posts (D-66)

In one line: a post can carry photos, and it works like LinkedIn's.

What we built

ModuleWhat it doesWhere
Photo upload and processingUp to 8 photos per post, 8 MB each. Each photo is rebuilt to remove hidden location data, and resized.API media/service.ts, lib/storage.ts
Photos in the feedA grid on the post, and a full-size viewer. Each photo has alt text for screen readers.API feed/service.ts; web PostImages.tsx
Writing a photo postPick photos, add alt text to each, then post.Web PostEditor.tsx
A person checks every photo postThe AI check can only read words, so a post with photos always goes to a person, even if its words pass.API moderation/service.ts; web QueueCard
Removal deletes the filesRemoving or deleting the post deletes the public copies of its photos.API media/service.ts

New database table: post images.

Stubs and stand-ins left

Ships

The whole feature. It is complete and pushed.

Last test run: not re-run on its own since it was built (26 Sept). Its tests ran inside the full dev/pilot run on 28 Sept, and all passed.


PR 3 — Video in posts (D-69)

In one line: a post can carry one video, with LinkedIn's limits (15 minutes, 5 GB). It's captioned automatically, and a person watches every video before it's shown.

What we built

ModuleWhat it doesWhere
Upload in piecesBig files go up in 16 MB pieces, three at a time. If the connection drops, the upload picks up where it stopped.API video-service.ts, lib/storage.ts; web lib/video-upload.ts
Processing on our own serverEvery video is rebuilt, and hidden location and phone details are removed. The server makes a smaller copy for the feed (480p) and a sharper one (720p) for full screen, plus a poster and a 30-frame storyboard. The file is read with strict limits, so a booby-trapped video can't harm the server.API media/video.ts
Automatic captionsSpeech is turned into text on our own server (Whisper), so no student's voice leaves our systems. The student checks the captions line by line, uploads their own caption file, or chooses none.API lib/transcriber.ts; web ComposerVideo.tsx
Checking what a video saysThe spoken words and the captions go through the same text check as a post. A phone number said out loud flags the post.API moderation/service.ts
WatchingIn the feed, a video plays silently as you scroll to it, with captions on. Tap it for full size, with sound and a speed control. Autoplay can be switched off in Settings. No view counts.Web PostVideo.tsx, AppearanceSection.tsx
ReviewingThe reviewer sees the storyboard first. The video stays blurred and silent until they choose to play it. Approve stays locked until the whole video has been played (up to 2× speed; skipping ahead doesn't count).Web ReviewVideo.tsx, QueueCard
Removal deletes the filesRemoving or deleting the post deletes every public copy.API video-service.ts

Database changes: no new table. The existing media and posts tables gain video columns (length, sound, captions, transcript, and a link from each post to its video).

Docs:

Stubs and stand-ins left

Not built (the full list is in docs/23 §7)

Known issues

None open. The walkthrough on 28 September found four bugs in the video players, all fixed and re-checked in the browser:

Last test run (28 Sept, on this branch): 281 of 281 API tests passed, including a real video run through ffmpeg.


PR 4 — Parental consent (D-68)

In one line: a student's account opens only after their school confirms who they are and a parent or guardian deliberately says yes.

What we built

ModuleWhat it doesWhere
School check firstThe student names a guardian. A named person at the school (the "consent verifier", chosen by our team) checks those details before any email goes out.API consent/service.ts; web SchoolStep, GuardianChecks
The guardian's pageNothing happens just by opening the link. To say yes, the guardian ticks a box, answers yes or no on mentors separately, and types their name. A paper form is available as another route.API consent/*; web ConsentPages.tsx
WithdrawalThe confirmation email carries a link that lets the guardian withdraw consent at any time. Withdrawing pauses the account.API consent/*; web ConsentPages.tsx
Clocks and remindersThe guardian's link lasts 7 days. If the school hasn't checked the guardian's details after 2 school days, it gets a reminder; after 5 school days, our team is told. A sign-up nobody said yes to is closed and deleted after 30 days. All of these are settings.API consent/service.ts, hourly job
Waiting screen = profile formWhile they wait, the student fills in their profile, which saves as they type (on the device only). A status panel sits on top. This was the founder's redline.Web ProfileStep, lib/profile-draft.ts
Mentor ruleOnly a guardian's explicit no blocks mentor requests.API mentorship/service.ts
Private by defaultGuardian contact details are encrypted in the database. Every step is recorded as evidence (the consent events table).API lib/crypto.ts, consent_events
India's adult checkA connector for checking that the guardian is an adult (India's rule, from May 2027). Today it only has a test version. DigiLocker (the Indian government's digital documents app) plugs in later.API consent/adult-check.ts

Docs: updated docs/14 and docs/16 (the founder's redline folded in).

Test data: Mr. Okafor is North Shore Academy's consent verifier and care contact. This fixed the "North Shore has no consent verifier" email.

Stubs and stand-ins left

SwitchWhat it does todayBefore going live
CONSENT_DEMO_AUTOCONFIRMOn a laptop, consent confirms itself after 3 seconds. It can never run in production. It is off on dev/pilot, so the real flow can be tested.Nothing; production ignores it
ADULT_CHECK_PROVIDEROnly a test version (dev) exists.DigiLocker, before India's rule starts (May 2027)
DATA_ENCRYPTION_KEYOn a laptop it's derived from another secret.Required in production; the server won't start without it
OPS_EMAILEmpty, so alerts meant for our team are only written to the log.Set it to the team inbox
SUPPORT_EMAILA placeholder address (support@thnkrr.local).The real support address

A choice to confirm

A student whose school isn't on Thnkrr has their sign-up closed. This used to apply only to under-18s; it now applies to every student. We flagged it at the time, and it is easy to reverse.

Last test run: after the final fix, the tests for that fix were re-run (48 of 48 passed). The full dev/pilot run later on 28 Sept included this fix, and all passed.


dev/pilot — all four together

What it is: a local branch that merges all four features, so they can be tested together on localhost. It has its own database and file storage, separate from main's. It never becomes a PR.

Rule: fixes are made on the feature branch, then merged into dev/pilot again. The only changes made directly here are the fixes needed where two features meet.

Migration numbers here: 0016 photos, 0017 care referrals, 0018 consent, 0019 video.

The three fixes that exist only here. Each must be re-made in the PR named in brackets (with the suggested merge order):

  1. Photos + moderation (API) [PR 2]: the "a photo post always goes to a person" rule, moved into moderation's rewritten review code. Plus one line in a test (images: []).
  2. Video + moderation (API) [PR 3]: the same rule for video posts. The AI only reads the words and speech, never the pictures.
  3. Video + care (web) [PR 3]: on a video post flagged for self-harm, the reviewer's Publish button also stays locked until the video has been watched in full.

Last full test run (28 Sept):

How to run it: stop the main stack first, because both use the same ports. Then start the API in thnkrr-api-combined and the web app in thnkrr-web-combined. The .env there has the speech model set and the consent stub off.


Before anything goes live (all four together)

AreaWhat's needed
SettingsReal AI checker chosen and its key set; SAFETY_HANDLER_IDS; DATA_ENCRYPTION_KEY; OPS_EMAIL; SUPPORT_EMAIL; WHISPER_MODEL
ServerInstall ffmpeg, the Whisper speech program and its model file
File storage rulesLet the web app read caption files and see each upload piece's receipt (the ETag header). Delete half-finished uploads after 1 day. Delete original videos after 30 days, except those kept for a safety case.
Amazon accountSwitch on Amazon's opt-out that stops it keeping or using our pictures to improve its AI, before Amazon checks the first student photo or video still
PeopleFour named people: two reviewers, who also handle safety cases (SAFETY_HANDLER_IDS); the person who files NCMEC reports; and the Grievance Officer. Someone to cover about 18–25 minutes of video review a day. A consent verifier and a care contact at each pilot school.
Outside applicationsThe free child-abuse lists: Microsoft's PhotoDNA, the UK's Internet Watch Foundation (IWF), Canada's Project Arachnid and the US NCMEC; for video, also Google's CSAI Match. Plus registering with NCMEC so we can file reports, and a quote from Thorn (a child-safety non-profit) — or Google's free Content Safety API instead.
TestsUpdate the 3 out-of-date browser tests

What we need from the founder

Everything is set out in two one-page briefs:

New or updated today (29 September)

DocBranchWhat changed
docs/23 — Video: storage, checks and costsvideoNew. The full record.
docs/24 — Video: one-page summaryvideoNew. For the founder.
docs/18 — Amazon services and costsvideoVideo storage, delivery, processing and checks added. The Lightsail plan choice.
docs/19 — Why Amazon, and the alternativesvideoWhy video is processed on our own server, not a video service. Speech-to-text on our server vs Amazon Transcribe. What running models on our own server costs.
docs/20 — Moderation researchmoderationNew §11 on video. Computing cost of running a picture model on our own server.
docs/21 — Moderation decision briefmoderationVideo row, video costs, and one more thing we need from the founder.
docs/15 — Text moderationmoderationA note on which models can run on our own server, and what they cost.

●  Have your own?

// Publish your own markdown.

Write your own
Thnkrr — Where Things Stand, 29 September 2026 · DocHouse