Mabadiliko
Nini kipya.
Kila kuboresha jukwaa, kama ni meli.
· SecurityService
$everything records a disclosure when a recipient is named
The whole chart in one response is the largest single thing this system hands out, and until now it wrote a PHI audit row and nothing else. That was right for the case it was built for — the practice's own screens read a chart through the same endpoint, and an accounting where every internal read appears as a disclosure to the practice itself is one where the real releases are unfindable. It was wrong for the other case. A records officer answering a §164.524 request in FHIR rather than C-CDA was making the same release through a path that did not record it, which is the exact §164.528 hole the ledger exists to close. The recipient is the signal, and it stays OPTIONAL here while remaining required on the C-CDA. The document endpoint exists to produce something that leaves the building, so an unnamed recipient there is always a missing answer; this one has a legitimate internal caller. The description carries the size, and says so explicitly when the cap truncated the record. "Complete record" and "the most recent thousand entries" are different answers to a patient asking what the other practice received, and the difference is what somebody investigating a bad handoff needs.
· kamo-internal
The unread badge goes red, pulses, and sits on the hexagon
Three things, all about a badge nobody notices. It was `--presence-color`, so it was GREEN whenever the member was online — the one state in which it is least likely to be spotted, because a green disc on a green-bordered head reads as part of the head. It is now the same red every other "go and do something" mark in this chrome wears, with a bolder white count. It sat at top:-6px/right:-6px, which is the corner of the SQUARE bounding box. A hexagon leaves those corners empty, so the badge floated a quarter of the width clear of the shape, attached to nothing. The polygon is a 0-100 viewBox stretched over a square, so its top-right vertex is exactly (75%, 6.7%) — the badge is now centred there and overlaps the border. And it wears the nav attention pulse the legal and timecard controls already wear, rather than a second animation three pixels away that a member would have to learn separately. Joining the shared class means the reduced-motion degrade comes with it: the rings stop, the count and its red stay.
· kamo-internal
Bank reconciliation on the healthcare revenue cycle
The last EHR endpoint without a caller, and it belongs beside the other six revenue-cycle queues rather than anywhere new. The gap between posted and banked. A remittance the payer says it sent with no matching deposit is either a posting error or money that never arrived, and only the second has a clock on it: it is recoverable while the payer's own records still show it, and not afterwards. The tab carries no count because the billing summary does not report one — it shows what it loaded rather than a number derived from somewhere else, which is the honest option until the summary carries it.
· kamo-internal
Who asked — unrecognised callers and Part 2 disclosures
Two compliance queues that were recorded server-side and never shown. UNRECOGNISED CALLERS. Every inbound exchange request that could not be attributed to a partner is kept rather than dropped, because a partner whose credential has gone stale and somebody probing the endpoint look identical until a human reads them. Toned critical with zero as the expected value, and the empty state says so — otherwise an empty list reads as a feature that is not working rather than as the answer you want. PART 2 DISCLOSURES, on their own. 42 CFR Part 2 is a separate obligation from HIPAA: its own consent rules, its own three-year accounting, its own penalties. Mixing it into the general disclosure list would make the separate obligation invisible, which is the whole reason the responder tracks it separately in the first place.
· kamo-internal
Resolve duplicate records, and record the ones that are not
Registration prevents duplicates; nothing could fix the ones already there — from an import, a phone booking taken before the record was found, a married name. The merge and not-a-match endpoints had no caller at all. THE DIRECTION IS NAMED IN FULL. Both merges are offered as separate buttons saying who survives and who becomes a pointer, and the confirm repeats it: "merge A into B" is ambiguous on a screen showing both, and merging the wrong way round buries the chart that had the history in it. "DIFFERENT PEOPLE" IS THE HALF THAT GETS SKIPPED. Twins, a parent and child sharing a name, a father and son — these are offered as duplicates on every registration and every review until somebody records otherwise, and a pair re-examined forever is a pair somebody eventually merges by mistake. The prompt says what recording it achieves so it does not read as bookkeeping. Gated on MERGE_PATIENT_RECORDS, which is deliberately not implied by being able to register: merging is the most damaging thing this module does, and the right exists so a practice can hold it to a much shorter list than "the front desk".
· kamo-internal
A conversation switcher beside every maximized chat
ChatSwitcherColumn mounts ConversationsPane beside a maximized chat window's own content, so a member can switch conversations without leaving the window. ToolDock builds one whenever a window's platform entry is flagged chatSwitcher (chat, support, social, sms, ai-chat) AND the window itself is maximized, and hands it to a new switcher slot on ToolWindowShell, which only shows it while the window is actually maximized. Clicking a row calls openConversation(row, { maximized: true }), which the tool-windows store already honours on every path, demoting whichever window was maximized. The column's own collapse preference round-trips through the same **************** shape ConversationsPane already uses for its bucket preference, under its own chatSwitcherCollapsed key, and the pane itself is mounted with **************** so the two simultaneous mounts (this column and the Interaction Center's slide panel) never clobber each other's saved tab.
· kamo-shared-library
The first FulfillmentPolicy implementation
FulfillmentPolicy has declared supports/createFromCommitment since it was written and a repo-wide grep returned exactly one line: the declaration. Its work was inlined unconditionally in processOrderPaid, which builds a shipment-shaped FulfillmentOrder for every line with an offering regardless of what was sold. A Spring @Service with constructor injection — a NEW pattern for this policy family, not a copied one: RetailInventoryPolicy is never instantiated or injected either, so every member of the family was dead code. supports() matches EngagementType.SERVICE directly, never the vocabulary: PROCUREMENT also maps to EngagementVocabulary.SERVICE but is the buyer's side of a vendor order and must never raise a ServiceJob. It is conservative because the order path stops at the first policy that says yes. Commitment cannot navigate to its Order — the FK is on Order.commitment with no inverse — so OrderRepository gains findByCommitmentUid to reach the address snapshot. The returned FulfillmentOrder is left unsaved; the caller already saves it. Also widens the query guard from one package to the whole library. Three per-package guards left ~50 files of @Query covered by nothing, including every commerce repository — which is how the new query above came to be believed validated when it was not. All 746 parse today.
· kamo-internal
Visit preparation, cancellation, and vaccine lot recall
The last endpoints without a screen. CANCEL, beside no-show on the day. They were one action short of each other and they are not the same thing: somebody TOLD us, so the slot is freed, it is not billable, and it does not count against the patient. Three different consequences that a single button would have hidden. The reason is asked rather than assumed. VISIT PREPARATION, beneath the day — the same desk looking a fortnight ahead. Eligibility nobody checked is a visit that gets delivered and not paid for, cheap to fix the day before and impossible afterwards. An authorisation with two visits left is treatment that stops mid-course, and the patient is the one who finds out, at the door. A visit left open holds the chart, keeps the note unsigned and keeps the encounter unbillable — usually somebody was interrupted, and the queue is how it gets noticed the same week rather than at month end. VACCINE LOT RECALL, beneath the safety queues, as a lookup rather than a queue: the question does not exist until a manufacturer or a health department names a lot, and then the practice has hours to find everybody who got it. That is the only reason the lot number is indexed at all.
· kamo-internal
Problems, open orders and results
The clinician's working views. The endpoints existed; the chart showed a summary and nothing you could work from. THE PRESCRIBING BANNER IS THE POINT OF THE PANEL. An allergy list that has never been reviewed and one that is genuinely empty look identical on every screen that simply renders the list — and one of them is a clinical assertion somebody made while the other means nobody has asked. The server already tracks which; this says so, before somebody prescribes. OPEN ORDERS ARE TONED BY expectedBy, NOT BY AGE. The server stores an expected date precisely so "overdue" is a fact rather than a feeling: an order placed three weeks ago and due next month is fine, and one due yesterday is not. An order placed and never resulted is the failure this module has a closure status for — the result goes to a fax machine, or never comes, and nothing on a normal screen counts the days. A result opens its own trend rather than standing alone. One potassium of 5.4 means something different from the fourth in a row. The purpose of use is named by the SCREEN on every read, because only the screen knows why it is open — and a purpose guessed at the server is a guess printed in a legal document handed to a patient.
· kamo-internal
A patient's insurance, claims, and the self-pay restriction
Practice-wide revenue cycle already lives under /commerce; the PER-PATIENT half had no screen — the front desk could not see who pays before a visit, and nothing showed whether the practice was allowed to bill at all. THE RESTRICTION BANNER LEADS THE PANEL. Under §164.522(a)(1)(vi) a patient who pays out of pocket in full can require the service is not disclosed to their health plan. Billing anyway is a disclosure they explicitly forbade — it is a right, not a billing preference, and it has to be visible before somebody submits a claim rather than discoverable afterwards. The banner also says what the restriction does NOT block: a referral, a medication list, or records reaching a clinician treating them. Reading it as "hide this from everyone" withholds a medication list from the person about to prescribe against it, turning a compliance rule into a safety problem. A coverage that has never been verified says so rather than showing a blank — it is a front-desk task, not missing data. An unpaid claim shows its timely filing deadline, which is the number that decides whether the money is recoverable at all.
· kamo-internal
Register a patient, with the duplicate check first
The Register button switched tabs to Find and did nothing else — PatientSearchPanel took an onRegister callback that nothing ever passed, so a practice could not add a patient through the app at all. THE DUPLICATE CHECK RUNS BEFORE THE RECORD IS CREATED, and Register stays disabled until it has run. A duplicate chart splits somebody's history in two and the only repair is a merge — which this module itself calls its most damaging operation, silent and very hard to undo. One round trip beats that. Register is gated on the check having RUN, not on it having come back clean: twins share a surname and a birth date, and the person at the desk is the one who can tell. A warning that treats every match as an error is a warning people learn to click through. Opening an existing candidate is the FIRST action offered, because most of the time that is the right answer — a registration screen that treats "they are already here" as an edge case is one that produces duplicates. Sex is recorded as ADMINISTRATIVE gender, which is the registration question. Clinical sex, birth sex and gender identity are separate fields asked separately by clinicians; flattening them at the desk loses all three. Registration is a mode of Find rather than a tab of its own — the same job, and the form has a way back, which a dead-end form does not.
· kamo-internal
Booking, and the notes-to-sign worklist
The two things a practice does all day that the app could not do. Both APIs have been on the server the whole time; neither had a screen, so the front desk could see the day and check people in without being able to put anybody on it, and a clinician could sign one note at a time from inside a chart they had opened for another reason. BOOKING. Patient first, then visit type, clinician and date, then the times the schedule actually has free. Slots come from the server's availability rather than a grid drawn here — a calendar that renders every fifteen minutes and lets somebody click one will book into a lunch break, a blocked afternoon, or a slot that filled while the page was open. The list refreshes after every booking, because two people booking the same morning is ordinary, and a failure says so rather than inviting a retry into the same conflict. Remaining capacity is shown rather than a bare "available": a slot is not always one person, and a group or double-booked template says so. SIGNING. Three queues, and the middle one is somebody else's problem. "Mine" is what this clinician owes; "awaiting my countersignature" is what a scribe or student wrote and cannot sign themselves, which blocks THEIR day, so it is called out separately and carries the more urgent tone. "The practice" is the manager's view. Countersigning happens in the list; signing does not. Signing your own note means reading it, so that opens the chart. Countersigning is an attestation about work already reviewed — and the queue at least shows a supervisor exactly how many they are attesting to. The masthead badge is what the clinician owes, not the practice's total: a practice-wide backlog on a personal tab reads as a personal one.
· kamo-shared-library
ServiceJob and ServiceVisit
A sibling of FulfillmentOrder, not a widening of it: FulfillmentOrder is a shipment with a tracking number and a carrier, and retail depends on it. Job 1..N visit from the first migration — a single-visit job is N=1, and retrofitting the parent later is a data migration across every tenant's history. The appointment stays a CalendarEvent, referenced by a soft string id exactly as LeadCallback already does; a second appointment table means a second reminder scheduler and a technician whose phone shows half their day. Scheduled and actual timestamps are kept separately because the finished UI can only answer the second, and a dispatch board needs the first. ServiceJobMappingTest also parses the servicework repositories' @Query values. CoreRepositoryQueryParseTest walks donotmodify.dao.repos only, so nothing otherwise validates these three queries, and an unresolvable JPQL path fails at bean creation — a crash-looping SecurityService rather than a bad result.
· kamo-internal
Work the cross-practice match queue
The last exchange surface with no screen, and the one that decides whether the connection produces anything at all. A held match is another practice saying one of their patients is one of ours, with our matcher unwilling to commit — cross-organization matching is materially harder than matching inside one practice, so the conservative threshold leaves real matches waiting. Unworked, every query about that person answers "we do not have them", and a practice concludes the network is broken rather than that nobody has been through the queue. Confirming asks what the reviewer checked, and rejecting asks why. A wrong confirmation discloses one person's record to another, and "confirmed by J. Smith" with no reason is not something a later review can weigh. The evidence the matcher recorded is shown beside the decision, because otherwise a reviewer is being asked to say two records are the same person on the strength of a percentage.
· kamo-internal
The screens the backend was missing
An audit of every EHR endpoint against its frontend callers turned up surfaces that shipped server-side and could not be reached from the app at all. HEALTHCARE NEVER APPEARED AS A MARKET TYPE. CommerceType.HEALTHCARE and its EHR entitlement have been server-side all along, and /commerce-markets/allowed-types reported it — but the picker built its rows by mapping over a hardcoded COMMERCE_TYPE_ORDER, so any vertical the constant did not name was dropped whatever the server said. That is the same class of bug the endpoint was introduced to replace. Rows now come from the server's list, ordered by the constant, so the next vertical works without a frontend change too. RECORDS AND DISCLOSURES, on the chart. The two things a patient can actually demand: a copy of their record under §164.524, and an account of everywhere it has already gone under §164.528. The accounting had no screen at all — a legally required report that could only be produced by curling an endpoint. The recipient field is required and the helper says why: that name goes into the patient's own accounting, so it has to read as they would recognise it. PORTAL INVITATIONS, beside the release, because a records officer asked for a copy is often the moment to offer the patient continuous access. The link is shown once and the panel says so — only a hash is stored. BULK EXPORT KICKOFF AND CANCEL. A jobs list with no way to start a job is decoration. Prefer: respond-async is sent because the specification requires a server to refuse a kickoff without it. Timestamps go through useFormatters throughout, so an export stamped 23:40 UTC reads as the day the practice was working.
· kamo-shared-library
Fill ServiceLineItem and its four classification axes
ServiceLineItem shipped as an empty 18-line subclass whose only reference in the whole corpus was its own declaration, so a service sold through POS persisted as a PURCHASE row. The four classification enums are the axes US states actually differ on, and the part Kamo owns even when an external engine computes the tax. A repair to tangible personal property, a capital improvement to non-residential real property and an MRRA job on a house are three different taxable events, and the difference is not derivable from a price and a description. labourMinutes is what will join the pricebook to the schedule — the same number prices the line and sizes the appointment. OrderLineItem gains **************** and Order gains discountTotal/shippingTotal, because otherwise every one of those is destroyed the moment a quote becomes an order. discountType reuses QuoteDiscountType rather than a String: two vocabularies that must agree is the bug this block exists to prevent.
· kamo-internal
Quality and Records office
Two sections for surfaces that had none. QUALITY. The rate is the headline; the care gap is the product. A practice shown "67% controlled" can do nothing with it — a practice shown the 41 NAMED patients in the denominator and not the numerator has a work list, and closing that list is the only thing that moves the number. So the measure cards open into the gap, each row carries the REASON it is a gap ("no mammogram since 2024-06-01" is a task; "in the gap" is a name), and clicking one opens the chart. Direction is read from the measure and said in words beside every rate. CMS122 counts patients whose diabetes is POORLY controlled and CMS165 counts patients whose blood pressure IS controlled; colouring both the same way would tell a practice its worst diabetic cohort was its best. No rate renders as a dash, not 0% — "no eligible patients" and "no eligible patient received the care" are opposite facts. The tab count is the care gap rather than a percentage: a score is something somebody glances at, a count of patients is work somebody picks up. RECORDS OFFICE. The three questions a records officer is asked together the hour something goes wrong — what has left, who can reach in, and which permissions are about to lapse. The lapsing list earns its place on its own: a parent's access to a child's record ends the day the child reaches majority, and without this nothing tells anybody in advance — the grant simply stops and a parent rings the practice. An issued partner credential is shown once, in a panel that says so, because only its hash is stored. Timestamps go through useFormatters so they render in the MEMBER's zone: an export stamped 23:40 UTC belongs to the day the practice was working, not the one after it. The check-server-timestamps guard caught the first version.
· SecurityService
The patient portal — sign-in, records, and proxy access
The §164.524 right of access, made real: a patient signs in and reads their own problems, medications, allergies, immunisations and appointments, and can download the whole record as a C-CDA. A THIRD PRINCIPAL, and the guards now know all three. EhrEndpointGuardTest grew PORTAL_AUTHENTICATED for the handlers that resolve a patient session and PORTAL_DOORS for the two that cannot — activating an invitation and signing in, because obtaining a session is what they are for. Both lists are policed rather than merely excused: the first checks each handler really resolves a portal session, the second that sign-in verifies a password and that activation looks the invitation up by the hash of the presented token. EVERY SIGN-IN FAILURE ANSWERS THE SAME SENTENCE, and an unknown address still costs the time of a hash. Distinguishing "no such account" from "wrong password" confirms which addresses are patients of this practice — and being a patient of an oncology clinic is a diagnosis. A 404 rather than a 403 on somebody else's record is the same reasoning. FAILURES LOCK THE ACCOUNT, not an IP. A portal login is the one credential a covered entity publishes the address of, and the realistic attack is a slow spray across many accounts rather than a burst against one, which a per-IP rate limit does not see. Withdrawing access revokes every live session, not just the account. Disabling alone leaves whoever is signed in reading the record until their session happens to expire, which is not what anybody means by withdrawing access. The password rule is LENGTH ONLY. Composition rules — a digit, a symbol, a capital — push people towards Password1! and away from the long passphrases that are actually strong. Portal reads are audited as PATIENT_REQUEST with a PATIENT_AUTHORIZED basis, and the record download is also written to the disclosure ledger. §164.528 does not require a patient's own access in their accounting, but 42 CFR §2.25 has no such exclusion and "who opened my record" deserves a complete answer.
· kamo-shared-library
The patient portal's identity model
A patient is NOT a Member, and this is deliberately not the workforce identity. Reusing the staff login would mean a patient held a principal that every internal authorisation check has to remember to exclude, and the first check that forgot would hand a patient a staff screen. A portal principal resolves to one patient plus whatever proxy grants that login holds, and to nothing else. SESSIONS ARE ROWS, not self-contained tokens. A practice withdrawing access, or a patient reporting a lost phone, needs the session to stop working NOW — and a stateless token cannot be revoked before it expires. There is an idle timeout as well as an absolute one, because a portal left open on a family computer is the ordinary case rather than the exotic one. INVITATIONS ARE SINGLE-USE AND TIME-BOXED, and only the token's hash is stored. A link lives in an inbox for years; a reusable one is a permanent credential sitting in whatever mailbox that address later belongs to. The refusal says WHICH problem it is — used, superseded, expired — because "invalid link" sends a patient to the practice with nothing to say and the practice with nothing to look up. PROXY ACCESS CARRIES AN END DATE BY DEFAULT. This is where portals go wrong, and they go wrong in one specific way: a grant is made and never reviewed. A parent's access to a child's record is entirely appropriate at seven and is a disclosure at seventeen, so a minor's grant expires on the day they reach majority, computed from their birth date at grant time. Scope is stored because a carer who manages appointments has no business reading a mental-health note, and a system offering only access/no-access makes a practice choose between too much and nothing. Rows are never deleted. Withdrawing access is a decision somebody made about a person's §164.524 right and has to stay visible as one; a deleted row looks like an account that never existed.
· VOIPService
List text conversations by last message, for the conversation list
· kamo-internal
The record's Communications tab shows communications
It rendered the record's media stream alone — the internal notes people write about a job. Useful, and not what anybody means by "the communications about this order": the customer's calls, texts and e-mails were nowhere, because the communications spine was keyed on leads only. Notes are still there as the first sub-tab, and the customer's traffic is beside them, keyed on the record the same way its documents are. This renders the platform's existing timeline component, not a second one. The contact-point notice is the part people miss. Inbound calls are matched against registered numbers, so a record nobody registered one against has a timeline that is empty for a reason nothing else on screen would explain — and the member concludes the feature is broken rather than unconfigured. It appears only once the count is known, so it never flashes at somebody whose record is correctly set up.
· SecurityService
Commerce records as owners, and one place for the matching rules
The third owner the spine was widened for, and the one that was still defined and unused. A record's documents already hang off it through the document manager's (assocType, assocObjectId) pair; its traffic now does too. ContactPointRegistrar exists because the write rules are MATCHING rules. The canonical form a number is stored in and the minimum length it must reach are what decide which timeline an inbound call lands on, and they were inline in PatientCommsService. A second copy for commerce would eventually normalise differently, and the symptom is a call that matches a patient's number under one code path and nobody's under another, with nothing in either log to say why. Authorisation deliberately stays with the callers. Who may register a patient's number is a clinical question answered by a care relationship; who may register a service job's is the commerce right. Putting either rule in the registrar would have meant the other lived somewhere else. A commerce record does NOT roll up its account. That would put every job a customer ever had on the page for one of them — a different question, which the account page already answers.
· SecurityService
The TEFCA responder — discovery, document query, document retrieve
The three operations a partner actually calls, expressed over FHIR rather than SOAP: IHE's XCPD and XCA shapes, on the QHIN Technical Framework's FHIR path, because that is where new connections are being built and a SOAP stack is a second security surface over the same data. AUTHENTICATION. These have no session, so ExchangePartnerAuthenticator resolves a bearer credential and the tenant comes from the partner row it finds. The X-Exchange-Trust-Id header is compared against the authenticated partner and logged when it disagrees — never used to select one. Two guard tests caught the first version: the endpoint ratchet, because it resolves no session, and EhrEndpointGuardTest's tenant-from-the-caller rule, because it took a tenantId parameter. The second was a real flaw and is gone; the first is answered by a baseline entry that says why, plus a new PARTNER_AUTHENTICATED category whose own test checks the credential path EXISTS rather than merely excusing it. DISCOVERY refuses thin demographics. A family name alone is a way to enumerate a practice's patient list. Candidates carry their match score, because a requester who cannot see it cannot make the judgement the low-confidence band exists for, and finding nobody is an empty bundle rather than an error — "we do not have this person" is a common and legitimate answer. PART 2 DATA IS WITHHELD SILENTLY. A query omits it; a retrieve answers 404 rather than 403. Forbidden would confirm the document exists, and telling a partner "there is data here you cannot have" discloses the existence of substance-use-disorder treatment — which is the exact thing Part 2 protects. A restricted patient answers an empty bundle for the same reason. RETRIEVE IS RE-AUTHORISED IN FULL. The query said the document exists; this is the call that moves a patient's record to another organization, and a partner suspended between the two must not be served by the second. Every request records an ExchangeRequest row before the response is built, including the refusals. An investigation is about the refusals.
· kamo-shared-library
A real credential for exchange partners, and retrieved documents
The responder endpoints have no user session — the caller is another organization's server — so a bearer credential this practice issues at onboarding is the ONLY thing between a stranger and a patient's record. The first version read the partner's identity out of an X-Exchange-Trust-Id header, which would have answered whoever typed the right OID; the OIDs are published in a directory. The HASH is stored, never the token. A leaked database must not yield working credentials for every partner a practice exchanges with. SHA-256 rather than bcrypt because the token is 256 bits this system generated — there is no low-entropy secret to slow an attacker over — and because a fast hash is looked up by index rather than tried row by row, which also leaves no timing signal. The lookup takes NO tenant. The credential identifies one partner row, which carries the practice it belongs to, so the tenant is derived — an endpoint that took one would be asking the caller which practice's records to search, and the tenant is the one part of a request a caller must never choose. ExchangeDocument keeps what crossed the boundary. Retrieved documents are KEPT, not merged: an outside summary is an assertion by another organization, and folding its problems and medications straight into the chart puts a clinician's name against facts they never reviewed. Reconciliation is a separate, deliberate act, and reconciledAt is the queue that makes retrieval useful rather than a folder nobody opens. Metadata is stored apart from the bytes because a clinician picks two documents from a list of forty, and shipping all forty is a disclosure larger than the question needed.
· SecurityService
Five real quality measures, and the engine that runs them
Measures are Java rather than CQL, and the trade is worth stating. The eCQM specifications are published in Clinical Quality Language, and an engine would let a practice load a measure without a deploy — it would also mean shipping an interpreter, a terminology expansion service and a FHIR-shaped data model, and getting any of those subtly wrong produces a rate that is confidently wrong, which is worse than not having the measure. These read the chart directly, are covered by tests naming the patients they include, and can be read by a clinician checking the logic against what they were told. The five, and the detail each one is usually wrong about: CMS122 diabetes A1c poor control — INVERSE: the numerator is poor control and lower is better. A missing A1c counts as poor control, deliberately: a diabetic with no result is unmonitored, not unmeasured, and treating it as neutral would let a practice score better by testing fewer people. CMS165 blood pressure — BOTH halves must be controlled. Reading only the systolic, the tempting simplification, credits a practice for a patient at 130/95. The threshold is below 140, not at or below. CMS125 breast cancer screening — the lookback is 27 months, not 24. Screening is recommended every two years, so a patient screened in month 25 has done exactly what was asked and a 24-month window scores them as a failure. A mastectomy patient on a mammogram work list is how a clinician stops believing the rest of the list. CMS147 influenza — the window is the FLU SEASON that ENDS within the period (October to March), not the calendar year. Anchored on the season that STARTS in the period, every patient not yet vaccinated in December reads as a gap and the score collapses each January. A recorded refusal is an EXCEPTION: counting it as a failure marks a practice down for respecting a decision, and teaches staff not to record refusals. CMS138 tobacco — a non-user is satisfied by screening alone; a user needs an intervention as well. Implemented as "was there a screening" it is trivial to pass and measures nothing; as "was there an intervention" it fails every non-smoker in the practice. Each patient's chart is loaded ONCE and offered to every measure — five measures each loading the same rows is five times the work, and on a ten-thousand-patient practice that is the difference between a report that finishes and one that does not. Gated on VIEW_QUALITY_MEASURES rather than a care relationship: a denominator IS every patient who met the criteria, so there is no one patient to have a relationship with. The per-patient endpoint IS gated on one, because that is an ordinary clinical read about a named person.
· kamo-shared-library
The quality measure model, and the row that makes it useful
MeasurePatientResult is the point of this commit. A practice shown "67% controlled" can do nothing with it; a practice shown the 41 NAMED patients in the denominator and not the numerator has a work list, and closing that list is the only thing that moves the number. Every quality product that gets used is built around that table; every one that gets ignored stops at the percentage. Exclusion and exception are modelled separately because reporting programmes audit one and not the other. An exclusion says the measure never applied — a bilateral mastectomy, so mammogram screening is not care that was missed. An exception says it applied and could not be delivered — the patient decoderd. Recording one as the other is how a practice fails a review. The arithmetic is not the obvious fraction. Exclusions and exceptions both LEAVE the denominator, so numerator/denominator overstates a practice's failure by however many patients it legitimately could not treat — on 100 eligible with 10 excluded and 5 excepted, twelve points of score. effectiveDenominator() is named rather than left implicit for exactly that reason. An empty denominator reports NO rate, never zero. "No eligible patients" and "no eligible patient received the care" are opposite facts, and a dashboard showing 0% for the first tells a practice it is failing at something it was never asked to do. Reports are append-only. A rate submitted to a payer must never move; re-running a period writes a new report, and two reports for one period are the record that the number changed and when — which is what an audit asks about. higherIsBetter lives on the report because the direction is not uniform: CMS122 counts patients whose diabetes is POORLY controlled, CMS165 counts patients whose blood pressure IS controlled. A dashboard colouring every rate the same way tells half of them the opposite of the truth.
· kamo-internal
Mirror the Service Work rights into TypeScript
VIEW_SERVICE_WORK, VIEW_OWN_SERVICE_WORK, MANAGE_SERVICE_WORK, ASSIGN_SERVICE_WORK and COMPLETE_SERVICE_WORK land at ids 268-272, not the 265-269 the plan assumed -- a concurrent session claimed 265-267 for Patient Records while Task 1 was blocked, so kamo-shared-library shipped the real ids at 7125873. Verified by reading the Java enum directly. RIGHT_PARENT gains the five edges (VIEW_SERVICE_WORK and VIEW_OWN_SERVICE_WORK under ACCESS_COMMERCE; MANAGE/ASSIGN/COMPLETE under VIEW_SERVICE_WORK), the parity pin moves 184 -> 189, and RoleRightType.ts gets the five constants plus their _values entries.
· SecurityService
Bulk export, C-CDA, and one accounting that covers every channel
BULK EXPORT. Kickoff answers 202 with a Content-Location and no body; polling answers 202 while running and 200 with the manifest when done. Returning a friendlier 200-with-status from the kickoff — the obvious improvement — makes every conformant client treat the export as finished and fetch a manifest that does not exist yet. Prefer: respond-async is required for the same reason: it is the client asserting it knows this is asynchronous. Gated on EXPORT_PATIENT_DATA and nothing else, deliberately. Every other clinical read is bounded by a care relationship with a named patient; a bulk export names no patient — that is what makes it bulk — so there is no relationship to check and the right IS the gate. ClinicalRightsGuard exists because the EHR rights were declared and nothing enforced them, which is fine where the care-relationship check stands behind them and is nothing at all on the population-level surfaces. The worker's state changes live in their own bean. Written as private methods on the runner they would have looked transactional, been annotated REQUIRES_NEW, and silently run in the caller's context — Spring's proxy does not intercept a call from one method of a bean to another. This platform has shipped that bug before. Each file is written to storage BEFORE its row is saved: a row pointing at a missing object makes a manifest whose links 500, which reads as data loss to the receiving system. C-CDA. What the hospital down the road can import. Recipient is a required parameter because generating a summary is a DISCLOSURE, and the accounting has to answer "who has my record" with a name a patient recognises. THE ACCOUNTING. DisclosureLedger existed and nothing wrote to it, while the §164.528 endpoint read exchange rows only — so a patient asking who has their record was shown the TEFCA responses and nothing else. A bulk export to their health plan, a records release, a portal download: none appeared, and nothing said the list was partial. An accounting that is silently incomplete is worse than one that is missing, because it is believed. Every channel now writes through DisclosureRecorder, and the endpoint reads the ledger. The recorder writes in its OWN transaction. A disclosure that happened and was not recorded is the failure it exists to prevent; the converse over-reports, which is a question somebody answers rather than a regulation somebody breaches.
· kamo-shared-library
Give Service Work its first five rights
ServiceType.SERVICE(28) shipped with zero rights, so its nine endpoints were gated only by whether the caller had a session. Ids start at 268 rather than the planned 265: a concurrent change was claiming 265-267 for Patient Records. Ids are never reused and a duplicate is fatal — RoleRightType builds LOOKUP_BY_ID with Collectors.toMap, which throws on a duplicate key, so two rights sharing an id stop every service that loads this enum from booting. They carry ServiceType.POS, not SERVICE. No RoleRightType uses SERVICE, RETAIL or RENTAL; all 36 commerce rights use the parent app type, and the permission editors filter on exact serviceType equality — so a SERVICE tag would have needed its own editor section and still left the other 36 invisible. VIEW_OWN_SERVICE_WORK is a sibling of VIEW_SERVICE_WORK under ACCESS_COMMERCE, never its child: a customer seeing their own jobs must not inherit staff-wide visibility. Same shape as VIEW_OWN_SUBSCRIPTIONS beside VIEW_SUBSCRIPTIONS. Committed through a private index so a concurrent session's in-flight Patient Records rights, live in the same two files, are not swept in.
· kamo-shared-library
Bulk FHIR export and C-CDA, and the rights that gate them
Two things a practice cannot operate without, and neither is a bigger version of reading a chart. BULK EXPORT (clinical/bulk). The FHIR Bulk Data model: a job, its NDJSON files, and a manifest. Three decisions worth stating. transactionTime is stamped at KICKOFF, not completion. Clients chain incremental exports by feeding it back as _since; stamped at completion, everything charted during an hour-long run falls into a gap between the two exports that the client is never told about. Keyset pagination on uid, never OFFSET — a system export walks whole tables, and with OFFSET page ten thousand costs ten thousand pages of work. The reader is written ONCE and parameterised by entity rather than as a finder on each of eight repositories, because eight identical queries is seven that get a fix and one that does not. Cohorts are explicit membership rows with joined/left dates, not a stored query. A cohort defined by criteria re-evaluates on every read, so two exports of "the same group" a week apart cover different people without saying so — and an accounting asking "was my record in the March extract" cannot be reconstructed from criteria that have since changed. C-CDA (clinical/cda). What the hospital down the road can actually import; FHIR is what a modern integration uses. The narrative block is generated first and the entries reference it, because the narrative is what a human is shown and what the document legally asserts — a section with perfect entries and no narrative renders blank in every viewer a clinician will open. Every section is emitted even when empty, and an empty allergy list carries an explicit negated "no known allergies" entry. An omitted section means UNKNOWN, and the clinician on the other end prescribes as if there are none. An unmappable code system is nullFlavoured rather than guessed at: a receiver told the wrong system looks the code up in the wrong dictionary and either finds nothing or, worse, finds something. RIGHTS 265-267. All three are ROOTS, not children of VIEW_CHART, which is the tempting parent and the wrong one: viewing a chart is bounded by a care relationship with ONE patient, and all three of these read across the whole population by design. BULK_EXPORTS storage domain, on its own line because a weekly full export is a weekly full copy — the fact a bill should make visible before the invoice does.

Ulimwengu wako unasubiri.
Kuanza bure katika dakika. Ongeza bidhaa wakati wowote wewe ni tayari - hakuna uhamiaji, hakuna logins mpya.
Bure milele - hakuna kadi ya mkopo inahitajika