JESS MOVEAssurance

Assurance and clinical safety

What this platform refuses to do, and how you would know.

Everything below is generated from the code rather than written about it. Where a control is enforced by a test, the build fails when it stops being true. Where something is not done, it is listed here rather than left for you to discover.

32controls published
21fail the build if broken
4honest gaps
14clinical hazards logged

This is not a DTAC submission, a clinical safety case or a conformity assessment — those are documents a named accountable person signs. It is the evidence they would be assembled from, published so that a buyer can check rather than take on trust. Controls marked enforced fail the build if they stop being true. Controls marked as a gap are things this platform does not do, listed here rather than left for somebody to discover.

What we do not do

4 things this platform has not done.

Listed before the 21 things it enforces, because that is the order a buyer would want them in.

A Clinical Safety Officer whose appointment satisfies DCB0129.

An officer has been appointed and is named in the hazard log. The appointment record is incomplete: DCB0129 requires the officer to be a suitably qualified and experienced clinician holding current professional registration with training in clinical risk management, and the registration body, registration number, training evidence and date of appointment have not been recorded. The log reports itself as not yet valid for submission until they are, and this platform will not assert a clinical registration on anybody’s behalf.

A member can take their record with them.

The food ledger, conditions, strength checks and growth results are all readable through the member’s own endpoints. There is no single one-click export archive yet.

A formal WCAG 2.2 AA audit against the live product.

Not done. Accessibility is designed for and tested in places, but there is no external audit and no VPAT.

Age is self-declared at registration.

Honest gap. Ofcom’s 2026 position is that self-declaration is not highly effective age assurance. The platform’s protections are strongest exactly where a wrong age would matter, but the declaration itself is unverified and a buyer should be told so plainly.

The controls

Every claim, and the mechanism behind it.

Clinical safety

3 enforced · 2 implemented · 1 gap

Enforced by a test

No AI-written health copy reaches the public without a named human reviewer.

The editorial status machine has no draft-to-published transition, publishing requires a named reviewer, and a test asserts the autopilot only ever transitions to in_review and never passes a reviewer argument.

Enforced by a test

Guidance for a declared condition never comments on medication.

Every condition card carries a clinicianOnly section, and a test scans all cards for dose, timing and escalation language and fails on any match.

Enforced by a test

General guidance is suppressed where a declared condition makes it wrong, rather than shown alongside it.

The insight engine applies condition effects before building any card, and the suppressed reading is stated on the page rather than silently removed. Tested against pancreatic insufficiency, kidney disease and appetite-suppressing medication.

True of the code

Strength and balance checks produce a starting level, never a falls risk score.

The falls module returns a level and a prompt to seek assessment. There is no risk field to return, and the reasoning is documented in the module and the migration.

True of the code

A DCB0129 hazard log covering the clinical risks this system introduces.

Fourteen hazards with causes, effects, initial and residual ratings on the DCB0129 matrix, and controls that each name the mechanism enforcing them. Held as data rather than as a document so it cannot drift from the software, and published in full.

Gap

A Clinical Safety Officer whose appointment satisfies DCB0129.

An officer has been appointed and is named in the hazard log. The appointment record is incomplete: DCB0129 requires the officer to be a suitably qualified and experienced clinician holding current professional registration with training in clinical risk management, and the registration body, registration number, training evidence and date of appointment have not been recorded. The log reports itself as not yet valid for submission until they are, and this platform will not assert a clinical registration on anybody’s behalf.

Data protection

4 enforced · 1 implemented · 0 gaps

Enforced by a test

Special-category data is opt-in, minimal, and deletable in one action.

Declared conditions are stored as catalogue identifiers only — no severity, dates, medication or free text — with free text dropped rather than stored. One call deletes the row.

Enforced by a test

Deleting an account deletes everything derived from it.

Foreign keys with ON DELETE CASCADE from app_users cover conditions, the food ledger, growth results and strength checks, so deletion is a database guarantee rather than a callback somebody has to remember.

Enforced by a test

Health data never reaches a household or organisation view, at any group size.

Group reporting enforces a k-anonymity floor of 8, and a test asserts that no module outside the conditions service references the conditions table at all.

True of the code

Analytics identifiers are not reversible and do not persist across days.

Blog view tracking hashes the address and user agent on arrival with a salt regenerated daily; the raw values are never held in a variable that outlives the request.

Enforced by a test

Nothing clinical is written by the ordinary draft autosave.

The autosave document check refuses any key or value containing clinical, diagnosis or consent, and conditions save only through their own endpoint.

Technical assurance

5 enforced · 1 implemented · 0 gaps

Enforced by a test

The schema is versioned and applied automatically, and drift fails the build.

Numbered migrations apply on start against a schema_migrations table, and a test fails if the embedded SQL differs from the files by a byte.

Enforced by a test

Payment events are processed exactly once under concurrent delivery.

Webhooks are claimed before processing with an insert-on-conflict, released on failure, and verified against eight simultaneous deliveries of one event.

Enforced by a test

Every AI action is gated against an available allowance before any provider is called.

The gateway holds the agent ceiling before the provider chain, settles to actual afterwards, and releases in full when nothing was delivered. A test walks every call site for an unbilled one.

True of the code

The running deployment can be identified from a request.

The health endpoint reports the commit the build was stamped from.

Enforced by a test

Every door that can act without a session is bounded, and the limits are published.

Registration, login, password reset, account deletion and guardian confirmation each carry a signed form token that must be old enough to have been read, a field only a script fills in, and a sliding attempt window sized to the door. The numbers and the reason for each are published rather than described. This is not proof that anybody is human, and the platform says so in those words rather than implying otherwise.

Enforced by a test

Text arriving from outside cannot instruct the platform.

Member and partner text is fenced as data before any model call, with a boundary marker generated per call that the text cannot have contained, and text shaped like a command to the system is refused before a provider is reached or an allowance is touched. Nine detectors, six of which refuse on their own; the rest need corroboration because a single ambiguous match is more often a person than an attack. A test corpus of ordinary questions asserts that none of them is refused or even logged.

Interoperability

1 enforced · 1 implemented · 1 gap

True of the code

Contracts are published and machine-readable rather than described.

Policy endpoints publish the editorial rules, the metering rule, the condition catalogue, the falls thresholds and this assurance summary as JSON.

Gap

A member can take their record with them.

The food ledger, conditions, strength checks and growth results are all readable through the member’s own endpoints. There is no single one-click export archive yet.

Enforced by a test

Structured data and a sitemap are served for the public estate.

Article and breadcrumb JSON-LD, a generated sitemap and robots file from one registry, and an RSS feed with autodiscovery.

Usability and accessibility

2 enforced · 0 implemented · 1 gap

Enforced by a test

The interface is six age-calibrated modes, not one interface with a font-size control.

Explorer, Teen, Momentum, Balance, Independence and Vitality, spanning 10 to 100, each with its own register, density and permitted content.

Enforced by a test

Every movement ships with variants, including seated and supported.

Publishing a movement requires five variants; the falls programme starts from the seated level when nothing has been recorded.

Gap

A formal WCAG 2.2 AA audit against the live product.

Not done. Accessibility is designed for and tested in places, but there is no external audit and no VPAT.

Safeguarding and age assurance

3 enforced · 0 implemented · 1 gap

Enforced by a test

No weight, BMI or energy figure can be rendered for an account under 18.

Charter rule C6. The insight engine returns unavailable for any age under 18 before computing anything, conditions cannot be declared, the falls module refuses, and each is covered by a test.

Enforced by a test

A minor account cannot be created without a guardian.

Registration under 18 requires a guardian email and the account activates on confirmation.

Enforced by a test

Copy aimed at a minor uses a stricter lexicon than the general one.

The strict list adds body, shape, size, compete, beat and rank, and applies to editorial and to partner marketing alike.

Gap

Age is self-declared at registration.

Honest gap. Ofcom’s 2026 position is that self-declaration is not highly effective age assurance. The platform’s protections are strongest exactly where a wrong age would matter, but the declaration itself is unverified and a buyer should be told so plainly.

AI transparency

3 enforced · 2 implemented · 0 gaps

True of the code

AI involvement is disclosed wherever it produced something a person reads.

Agent-drafted articles are marked, partner marketing carries a disclosure naming the partner as the publisher, and the coach states when it is answering live.

True of the code

What the AI will not do is published rather than implied.

Every AI surface publishes its own refusals — the coach, FoodLens, the editorial autopilot, the growth engine and the metering rule all expose a neverDoes list.

Enforced by a test

No AI decides who gets access to anything.

Every block on this platform comes from a deterministic rule a person can read, and every limit is a window that expires on its own. The security agent reads the queue of things already blocked and writes an explanation for a reviewer; it has no power to block, ban or unblock, it is metered against the platform’s own allowance, and a test walks its source for any call that would change access.

Enforced by a test

Model decisions are logged with input hashes rather than inputs.

The gateway redacts named field classes before any external call and logs a trace identifier, provider, model and cost — never the prompt.

Enforced by a test

Generated figures state their basis, and unmeasured values are never shown as zero.

FoodLens returns energy as a range and marks each nutrient label, calculated, estimate, reference or unmeasured. Independent testing published in 2026 found leading photo apps underestimate meal energy substantially; this is the control that addresses it.

Safeguarding

The answer a school needs, in one sentence.

No weight, no body-mass index and no energy figure can be rendered for an account under 18 — not hidden by a setting, not available behind a toggle, but absent from what the platform will produce for that account at all.

How you would know

It is charter rule C6, and it is asserted in the test suite rather than described in a policy. A build where a minor could be shown a weight does not pass.

What a child does get

Movement, growth in their own terms, and a coach calibrated to their age. No calorie figure, no target, no comparison to anybody else, and no condition guidance of any kind.

Guardians

An account under 18 cannot be created without a guardian email, and it activates only when that guardian confirms.

What we do not do

Age is self-declared at registration. Ofcom’s 2026 position is that self-declaration is not highly effective age assurance. Our protections are strongest exactly where a wrong age would matter most, but the declaration itself is unverified and you should weigh that.

Clinical risk management

The DCB0129 hazard log, in full.

Clinical risk management under DCB0129, held as data rather than as a document so that it cannot drift from the software it describes. Every control names the mechanism that enforces it; the ones marked tested fail the build if they stop being true. Severity is never reduced between the initial and residual columns — a control changes how likely something is, not how bad it is when it happens anyway.

Appointment incomplete

Mr Justin NseyaClinical Safety Officer

Mr Justin Nseya has been appointed as Clinical Safety Officer. The appointment is not yet complete for a DCB0129 submission: professional registration body, registration number, clinical risk management training, date of appointment are still to be recorded. DCB0129 requires the officer to be a suitably qualified and experienced clinician holding current professional registration, and this platform cannot assert that on anybody's behalf.

A hazard log with an incomplete officer appointment. It is usable evidence and it is not yet a DCB0129 submission, and this platform will not describe it as one until the appointment record is complete.

7acceptable after controls
7undesirable, each with a note
0unacceptable — none ships
36/42controls enforced by a test
H02

A person with exocrine pancreatic insufficiency restricts fat because the platform flagged it.

Cause
General saturated-fat guidance applied to somebody whose current clinical guidance is not to restrict fat.
Effect on the person
Weight loss and fat-soluble vitamin deficiency — the exact harm the out-of-date low-fat advice causes, delivered by us.
Before controlshigh · considerable4 · Unacceptable
After controlslow · considerable3 · Undesirable
  • Tested
    The saturated-fat finding is suppressed entirely where the declared condition makes it wrong, and the suppression is stated on the page rather than silent.risk.logic.ts — risksFor, doNotFlagFat
  • Untested
    The condition card states that the guidance has changed and that older leaflets say the opposite.conditions.ts — pancreatic_insufficiency.careful

Still owed. Depends on the member declaring the condition. Nothing infers it, by design.

H04

Unintended weight loss is treated as progress rather than as a symptom.

Cause
A weight-reduction narrative running for somebody whose falling weight is the presenting sign of an undiagnosed illness.
Effect on the person
Delayed presentation of a serious underlying condition — malignancy, inflammatory bowel disease, malabsorption — because the platform reinforced it as success.
Before controlsmedium · major4 · Unacceptable
After controlslow · major3 · Undesirable
  • Tested
    Where a declared condition makes weight loss a warning, the reduction plan does not run, the BMI target is withheld and a falling weight is raised as high with the action "tell the team treating you".risk.logic.ts — weightLossIsAWarning
  • Tested
    The threshold for saying so is 0.2kg a week rather than the general 1kg.risk.logic.ts — risksFor, weight going down

Still owed. Only fires where a relevant condition has been declared. Somebody with an undiagnosed illness has, by definition, declared nothing — the general "rate of loss" finding is the only net under them.

H06

Somebody falls while attempting a balance or chair-stand self-check.

Cause
A functional measure performed alone, without support in reach, on an unsuitable surface or chair.
Effect on the person
A fall, with fracture the common outcome in the age group this is aimed at.
Before controlsmedium · considerable3 · Undesirable
After controlslow · considerable3 · Undesirable
  • Tested
    Every check carries safety instructions before the method: something solid within arm’s reach, a chair that cannot slide, a clear floor, somebody in the house.falls.ts — FUNCTIONAL_CHECKS[].safety
  • Untested
    Each check tells the person to stop at the first position they cannot hold, and that stopping is the honest number.falls.ts — FUNCTIONAL_CHECKS[].how
  • Untested
    Every measure is optional; a check not attempted is a valid record rather than an incomplete one.falls_checks migration — nullable measures

Still owed. Undesirable rather than acceptable, and deliberately left there. This is a physical test performed unsupervised in somebody’s home, and no instruction reduces that to negligible — the only controls that would are supervision, which we cannot provide, or removing the checks, which would remove the thing that gets people to the right starting level. The judgement is that an unsupervised check with explicit safety instructions is safer than the alternative actually taken, which is starting a programme at a level nobody measured. That judgement belongs to the Clinical Safety Officer to accept or reject.

H07

A good result on the strength and balance checks is read as evidence of being at low risk of falling.

Cause
A functional measure presented as, or mistaken for, a falls risk assessment.
Effect on the person
A person declines or does not seek a real assessment — which covers medication, lying and standing blood pressure, vision, feet and the home — and falls.
Before controlshigh · major4 · Unacceptable
After controlslow · major3 · Undesirable
  • Tested
    No risk score is produced. There is no field to return one in, and the module returns a starting level for exercise instead.falls.ts — StartingPoint has no risk or score member
  • Tested
    Every response carries the statement that this is not an assessment of falls risk, naming the four things it cannot see, and saying that a good result does not mean safe.falls.ts — NOT_A_RISK_SCORE
  • Tested
    A fall in the last twelve months routes to a falls assessment regardless of how well the checks went.falls.ts — startingPoint, referFirst

Still owed. The statement is on every response, and nobody can be made to read it. The platform also has no way of knowing whether an assessment was offered and declined — it can prompt, and it cannot follow up. Reducing this further needs something outside the software: a route by which a poor result reaches a clinician, which is what the NHS procurement route would provide and what nothing here currently does.

H08

A declared allergen present in a product is not surfaced to the person scanning it.

Cause
Incomplete or stale label data, or a photograph analysed as though it were a label.
Effect on the person
Allergic reaction, up to anaphylaxis, or gluten exposure in coeliac disease.
Before controlsmedium · major4 · Unacceptable
After controlslow · major3 · Undesirable
  • Tested
    The fourteen UK declared allergens are reported from the label when a barcode is read, and the source of every figure is stated.barcode.service.ts, @jessmove/foodlens — UK_ALLERGENS
  • Tested
    A photograph never produces an allergen claim; the analysis states what a photograph cannot tell you.foodlens.logic.ts — NEVER_CLAIM
  • Untested
    The coeliac and lactose cards say plainly that the packet is scanned rather than trusted, and name cross-contamination as the usual cause of a reaction despite doing everything right.conditions.ts — coeliac.careful

Still owed. Label data comes from an open catalogue that can be out of date. The platform states its source but cannot guarantee the manufacturer has not changed the recipe.

H09

The coach states something clinical, or invents context about the person.

Cause
A language model answering outside the boundaries set for it.
Effect on the person
A person acts on advice that was not clinically grounded, or loses trust after being told things about their day that were never true.
Before controlshigh · considerable4 · Unacceptable
After controlslow · considerable3 · Undesirable
  • Tested
    The coach publishes what it refuses to do, and the refusals are enforced rather than requested.mova — MOVA_REFUSES
  • Tested
    An answer that repeats context from the tone sample is detected and the model is asked again with the mistake named.mova.service.ts — repeatsSampleContext
  • Tested
    Under-18 answers are checked against the minor rules by the platform after the model returns, not by the model.mova.service.ts — violatesMinorRules

Still owed. The controls detect known failure modes after the model has answered — invented context, a breach of the under-18 rules, a banned phrase. A novel failure that resembles none of them passes. This is the irreducible residual risk of putting a language model in front of a person, and the mitigations are bounded scope, published refusals and the fact that the coach answers in one line rather than at length.

H12

A person on appetite-suppressing medication under-eats to a harmful degree without noticing.

Cause
Appetite pharmacologically suppressed, intake falling well below need, and a platform whose every other rule watches for excess.
Effect on the person
Loss of lean mass, micronutrient shortfall, and fatigue attributed to the medication rather than to intake.
Before controlshigh · considerable4 · Unacceptable
After controlslow · considerable3 · Undesirable
  • Tested
    Below half a reference intake is raised as a high finding, with protein-first named as the action.risk.logic.ts — proteinMattersMore
  • Tested
    Loss faster than roughly one per cent of body weight a week is raised, with resistance work as the lever.risk.logic.ts — muscleLossRisk
  • Tested
    Fewer than two movement days a week is raised as a muscle finding while this is happening.risk.logic.ts — muscleLossRisk, activity

Still owed. Depends on the person recording what they ate. Somebody who stops recording because they ate almost nothing is invisible to this, and that is the failure mode most likely to occur.

H01

A person under 18 is shown a weight, a body-mass index or an energy figure.

Cause
An age check omitted on a surface that renders any of those figures, or an adult surface reachable by a minor account.
Effect on the person
Body-image harm and a recognised pathway into disordered eating, in a group where that pathway is well documented and the platform would have opened it.
Before controlsmedium · considerable3 · Undesirable
After controlsvery low · considerable2 · Acceptable
  • Tested
    The insight engine returns unavailable for any age under 18 before it computes anything at all.risk.logic.ts — insightFor, first branch
  • Tested
    Conditions cannot be declared under 18, at the endpoint as well as in the render.health-insight.controller.ts — setConditions
  • Tested
    The strength and balance module refuses under 18.falls.controller.ts — record
  • Tested
    Energy is withheld from a minor in FoodLens, and the surface policy is a shared gate rather than a per-screen decision.@jessmove/shared — bodySurfacePolicy, charter rule C6

Still owed. Age is self-declared. A minor who registers as an adult defeats every control above. Ofcom’s 2026 position is that self-declaration is not highly effective age assurance, and this is the largest single residual risk in this log.

H03

A person with reduced kidney function is pushed towards protein, or towards a potassium-based salt substitute.

Cause
General guidance — eat more protein, swap to a low-sodium salt — applied without regard to renal function.
Effect on the person
Hyperkalaemia, which can be fatal, or accelerated decline in kidney function.
Before controlsmedium · major4 · Unacceptable
After controlsvery low · major2 · Acceptable
  • Tested
    No surface suggests a salt substitute where the declared condition forbids it, and the salt finding names the substitute as the one swap to avoid.risk.logic.ts — noSaltSubstitute
  • Tested
    Protein is never pushed where a declared condition sets the target from bloods, including against an opposing declared context.risk.logic.ts — doNotPushProtein, and the conflict statement
  • Tested
    Where two declared contexts disagree, the cautious side wins and the member is told who settles it.risk.logic.ts — suppressionsFor, protein conflict
H05

A figure estimated from a photograph is acted on as though it were measured.

Cause
A single confident number returned for a plate whose contents were inferred rather than read.
Effect on the person
Sustained under- or over-eating built on an error. Independent testing published in 2026 found leading photo apps underestimate meal energy by roughly 250 to 345 calories with macronutrient error rates of 48 to 66 per cent.
Before controlsvery high · significant4 · Unacceptable
After controlslow · significant2 · Acceptable
  • Tested
    Energy is returned as a range, never as a single figure.foodlens.logic.ts — energy
  • Tested
    Every nutrient states its basis: label, calculated, estimate, reference or unmeasured.foodlens.logic.ts — frontOfPackFrom
  • Tested
    A nutrient nothing established is shown as not measured, never as zero.foodlens.logic.ts and the ledger entry mapping
  • Tested
    An intelligence score states how much of the plate was actually known.foodlens.service.ts — intelligence
H10

The platform comments on a prescribed medication.

Cause
Condition guidance drifting into dose, timing, escalation, or whether to continue.
Effect on the person
A person alters a prescription on the basis of software that has never seen their results.
Before controlsmedium · major4 · Unacceptable
After controlsvery low · major2 · Acceptable
  • Tested
    Every condition card carries a clinicianOnly section naming the medication as the prescriber’s, and a test scans all cards for dose, timing and escalation language.conditions.ts — clinicianOnly; conditions.test.ts
  • Tested
    The appetite-suppressing medication card is additionally scanned for injection, titration and missed-dose language.gaps.test.ts
  • Tested
    A declared medication carries its own notice stating that nothing here comments on it.conditions.ts — MEDICATION_NOT_ADVICE
H13

A person acts on figures that failed to save, believing them recorded.

Cause
A write that failed silently, or a stale read presented as current.
Effect on the person
Decisions taken on an incomplete record — a week that looks lighter than it was, a condition believed declared that is not.
Before controlsmedium · significant3 · Undesirable
After controlslow · significant2 · Acceptable
  • Tested
    A failed conditions write is surfaced rather than swallowed; the picker says so and does not claim to have saved.conditions.service.ts and conditions.tsx — save state
  • Untested
    A failed conditions read throws rather than returning an empty list, so nobody is handed general advice their condition exists to override.conditions.service.ts — forUser
  • Untested
    A failed strength-check read throws rather than restarting somebody at a level they have outgrown.falls.controller.ts — history

Still owed. Food ledger writes remain best-effort by design: a ledger that cannot be written must not take down the analysis somebody is waiting for. A missing row is a gap in a total rather than a failed scan, and that trade is deliberate.

H11

A declared condition reaches an employer, a household member or a report.

Cause
Group aggregation including special-category data, or a small group size.
Effect on the person
Identification of a person’s health status by somebody with power over them, with the discrimination that follows.
Before controlsmedium · significant3 · Undesirable
After controlsvery low · significant1 · Acceptable
  • Tested
    Group reporting enforces a k-anonymity floor of 8.groups.logic.ts — K_ANONYMITY_FLOOR
  • Tested
    No module outside the conditions service references the conditions table at all, asserted by scanning the source.conditions.test.ts
  • Tested
    Conditions never enter the ordinary draft autosave, which refuses anything clinical.state.logic.ts — FORBIDDEN
H14

AI analysis stops mid-use and the person believes the picture is complete.

Cause
An allowance exhausted between one action and the next.
Effect on the person
A decision taken on a partial reading, believing it whole.
Before controlshigh · minor2 · Acceptable
After controlsvery low · minor1 · Acceptable
  • Tested
    The allowance is checked and held before any provider is called, so an action either runs completely or does not begin.ai-gateway.service.ts — hold, before the provider chain
  • Tested
    Exhaustion returns 402 with the wallet’s own explanation of what is paused and what still works, never a generic failure.allowance.filter.ts
  • Tested
    No caller dresses an empty allowance as an outage.mova, foodlens, blog and growth services — AllowanceExhaustedError rethrow

How the ratings are read

Severity

  • minor Minor injury not requiring professional intervention, or non-serious inconvenience.
  • significant Minor injury requiring professional intervention, or significant psychological trauma.
  • considerable Serious injury or incapacity requiring professional intervention.
  • major Severe or life-threatening injury, or the death of one patient.
  • catastrophic Death of multiple patients.

Likelihood

  • very low Negligible or nearly negligible possibility of occurring.
  • low Could occur but in the great majority of occasions will not.
  • medium Possible.
  • high Not certain but very possible; would be expected to occur.
  • very high Certain or almost certain; highly likely to occur.

A hazard log is not a safety case. The safety case is the argument that these residual risks are acceptable, made and signed by the Clinical Safety Officer. This is the evidence that argument would be built from.

The same content is served as JSON at /assurance, /assurance/safeguarding, /assurance/hazards and /assurance/conditions — see Developers. The published policies sit at All policies.