Skip to content

v1.37.8 — the assistant can answer for your visits - #768

Merged
MBombeck merged 5 commits into
mainfrom
release/v1.37.8
Aug 10, 2026
Merged

v1.37.8 — the assistant can answer for your visits#768
MBombeck merged 5 commits into
mainfrom
release/v1.37.8

Conversation

@MBombeck

Copy link
Copy Markdown
Owner

Assembled off origin/main. Two strands, both additive, no schema change and no contract drift.

The visit history over the assistant wire

  • get_visits: a bounded read of past practice visits (default 12 months, optional practitioner name filter), returning date, practitioner, specialty, kind, reason, outcome, status and the linked condition labels. Absence is explicit: an account that never recorded a visit gets { present: false }, never { present: true, visits: [] }.
  • Upcoming appointments fold into get_preventive_care as their own field rather than a second due-list tool, so "what is coming up" has one answer. The Vorsorge due-list still excludes ENCOUNTER-origin reminders.
  • The Coach snapshot carries a small visits block: upcoming appointments within 14 days plus the single most recent past visit, placed explicitly in the degradation ordering so it sheds before the clinical core. Not the full history, which stays a get_visits question.
  • Free-text reason and outcome ride the USER_TEXT fence; short label fields are marker-scrubbed. No sentence produced from this data may state a cause.
  • A structural guard freezes the encounter and vaccination link tables to their one gateway module, so the eventual absorption of those tables is a storage change and not a call-site sweep.

Log hardening

  • WideEventBuilder.addWarning now scrubs through redactSecrets on the way in, the same as setError, setHttp and addExternalCall. A warning routinely carries an outbound error string that for a few integrations is a request URL with a credential in it, so this closes the last builder entry point that could reach the log unredacted.

Watched-red evidence

  • Absence contract: forcing the empty get_visits case to { present: true, visits: [] } turns the honesty test red; reverted, shasum-restored.
  • Link guard: planting a real prisma.encounterConditionLink call in a route turns the guard red naming the offender; reverted, shasum-restored. The guard matches a non-zero set inside the module.

Guardrail audit against the tree

Three encounter link tables and no fourth. No relevanceNote, no per-link discriminator, no edges view. No new module key or nav entry added by this venture (visits live on the existing checkups surface). No new cron, queue, notification event type or preference key. No FHIR resource type added. Eight sharing domains unchanged. The published reminder origin enum unchanged. Nothing became mandatory: an encounter saves with a date alone and every link picker is optional. No new column, so nothing write-only to answer for.

Gate

typecheck, lint, openapi:check (in sync), test (21111 passed / 12 skipped), integration (1837 passed against testcontainers Postgres 16), build: all green. An independent review ran the relevant suites and a watched-red pass on the guard and returned ship.

Add get_visits, a bounded read of past visits (default the last 12
months, optional practitioner-name filter) returning date, status,
kind, practitioner, specialty, the visit's own reason and outcome, and
the linked condition labels, newest first. Absence is explicit: an
account that has never recorded a visit reads { present: false }, never
{ present: true, visits: [] }.

Fold upcoming appointments into get_preventive_care as their own named
field rather than minting a second due-list tool, so a question about
what is coming up gets one answer. The Vorsorge arm stays free of
ENCOUNTER-origin reminders; the appointments are read from Encounter
directly. Reason and outcome ride the USER_TEXT wrapping, and every row
is scoped to the caller by construction.
The Coach can now see that a visit is coming and what the last one was
about, without being handed a visit archive. The block is deliberately
small: the appointments booked within the next 14 days plus the single
most recent visit that happened. A full history is a get_visits
question, not a prompt-budget one.

Built as a peer of the illness and labs blocks and registered for
degradation EXPLICITLY against the lowest-priority cluster, so it is
among the first blocks shed when the character cap binds, before any
clinical cluster. Encrypted reason and outcome decrypt fail-soft and
every free-text string routes through the prompt sanitiser first.
A structural guard asserts that no file outside src/lib/links touches
the five link tables the service owns, with the two backup restore
writers as the only, frozen exemption. The matcher is whitespace
tolerant and proven non-vacuous: it must match every owned table inside
the service, so it can never pass by matching nothing.

This makes provable the property the link module was built for, that the
later absorption of these narrow tables into one join model is a storage
change behind the module rather than a sweep across every call site.
addWarning pushed the raw string while setError, setHttp and
addExternalCall all scrub through redactSecrets. A warning routinely
carries an outbound error string, and for several integrations that
string is the request URL with a credential in it, so a secret could
reach stdout and the log store unredacted. It now scrubs on the way in
like the other entry points, and a test asserts a licence-key-bearing
warning is masked.
@MBombeck
MBombeck merged commit a4bea8b into main Aug 10, 2026
23 checks passed
@MBombeck
MBombeck deleted the release/v1.37.8 branch August 10, 2026 01:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant