# Nutrition dashboard and food-mapping safety

Use this reference when adding nutrition read APIs, SIGHi classifications, food mapping, meal/day views, or nutrition/symptom overlays to a private health dashboard.

## Semantic boundaries

- A SIGHi value 0–3 is a **source classification**, not a measured histamine quantity, medical warning, or personal tolerance result.
- Keep separate fields and storage for source classification and personally documented tolerance. Neutral personal statuses may include `unknown`, `documented_tolerated`, `documented_not_tolerated`, and `unclear`; never label a food simply “safe”.
- Show daily maximum source class, cumulative mapping index, mapping coverage, and unknown-product count separately. A day is complete only when every relevant product is classified.
- Missing nutrients, macros, meals, and mappings remain unknown. Never turn missing values into zero, achieved targets, “normal”, or a complete score.
- Do not invent an inflammation score. A true Dietary Inflammatory Index requires the published normalization method, licensed/versioned reference parameters, units, global means/standard deviations, effect scores, and a declared missing-parameter policy. If those inputs are unavailable, show transparent components and state that the index is not reliably calculable.
- Nutrition/symptom overlays use wording such as “temporal association”, “exploratory observation”, and “hypothesis”; never causal language.

## Read-model boundary

- Build additive, authenticated, bounded endpoints for day ranges, one day, and a mapping queue.
- Expose only allowlisted fields and nutrients with known units. Unknown-unit micronutrients are omitted rather than guessed.
- Never expose raw import JSON, source product IDs, numeric database IDs, file paths, tokens, source URLs, or internal provenance payloads.
- Preserve meal groups explicitly: breakfast, lunch, dinner, snacks, and unassigned.
- Include timezone, coverage, unknown counts, mapping-definition version, and data-completeness metadata in the public contract.

## Mapping action workflow

1. Keep the network server read-only for the health database.
2. Validate an exact single-value form protected by same-origin checks and one-time CSRF.
3. Queue a private `0600` action containing an explicit decision: `assign`, `composite`, or `ignore`.
4. Revalidate the complete payload in the network-isolated worker.
5. Apply the action transactionally and idempotently, audit provenance/version fields, and recompute only deterministically affected days.
6. Preserve imported/raw nutrition tables unchanged.

A mapping decision should carry bounded, allowlisted values for alias, canonical food, source classification, confidence, mapping method, source label/version, note, ingredient-review requirement, and separately documented personal tolerance.

- `assign`: requires a canonical food, a reviewed source classification, and no pending ingredient review.
- `composite`: must remain unclassified and require ingredient review. Never auto-classify sauces, brand products, prepared meals, or composites from product-name punctuation alone.
- `ignore`: must not alter mappings or summaries.

## Deterministic fixture and browser contracts

- Seed products, mapping rules/aliases, scores, confidence, and provenance, then invoke the same production day recompute function used by the worker. Do not write a derived daily index directly merely to satisfy a chart test.
- Include three consecutive fully mapped exposure days; at least one must contain breakfast, lunch, dinner, and snack, with amount/unit, all four macros, one additional known-unit nutrient, mapping provenance, and known confidence for each synthetic product.
- Put one complete seven-dimension symptom check-in with a nonzero Aphthae value exactly two calendar days after the last exposure day. Keep a separate incomplete day containing both mapped and unmapped products, with no numeric daily index.
- Keep two browser contracts: an incomplete-only visible range proves the fail-closed empty state; a mixed range proves an ECharts instance, nonzero geometry, three numeric exposure days, a null incomplete day, an Aphthae marker, and the accessible table fallback.
- Prefer ECharts instance/options, expected series/data, geometry, and table semantics over internal canvas-count assertions. Exercise the chart event path for day bars and symptom markers, browser back/forward restoration, and tooltip wording/coverage/unknown counts.
- Synthetic product labels must also pass the API metadata scrubber. Avoid label tokens that resemble opaque IDs (for example, mixed letters and digits in one token), or the fixture may contain rows while the safe public item list is empty.

## Migration and release gates

- Back up SQLite before additive schema work; run `integrity_check` before and after.
- Prove migration idempotency, preserve raw-table rows byte/field-equivalently, and perform a restore test from the backup.
- Keep committed schema DDL, runtime migration DDL, and schema-manifest table count/digest aligned. If a personal-tolerance check constraint is widened, migrate legacy rows without erasing former statuses, evidence levels, notes, or timestamps.
- Synthetic fixtures should include complete/incomplete days, all meal groups, an unassigned meal, a simple food, a composite brand product, unknown nutrient units, symptom/event timing, mapping actions, and affected-day-only recomputation.
- Test enqueue-before-worker, one-time CSRF, duplicate form keys, invalid scores, manipulated queue filenames/IDs, composite rejection, ignore semantics, idempotency, separate personal-tolerance storage, a private worker receipt, and no leakage of internal identifiers.
- Store processed receipts outside the root `*.json` action glob so a later worker run cannot mistake receipts for new actions. Receipt publication must be private and atomic; the action remains idempotent if receipt writing is retried.
- Keep production inventory evidence to technical counts and coverage only—never food names, nutrient values, or raw payloads.
