Require an open god-mode window, not eligibility alone, for CONFIGURE_SYSTEM
hasRight was granting the bypass on the raw GD session flag, which SessionPlatformFacts's own javadoc names as the exact anti-pattern it exists to prevent: GD i...
Make seeded and uploaded branding revalidate, so an org stops being served the base theme it was seeded with
A new organization is seeded with the base theme — the platform's own logo and backgrounds copied to the new org's keys — and those keys never change when the o...
A video on a report never reaches an AI dispatch
file and cannot watch one. The desktop agent already magic-byte-checks every attachment, but it refuses the DISPATCH rather than the one file — so a single vide...
Gate the order and pricing surfaces on a right
Thirty-nine endpoints were protected only by "are you signed in". Every order handler on POSController and every pricing and tax handler on CommerceMarketContro...
The outbound audit row was written by an inert REQUIRES_NEW
It was a method on ExchangeQueryService annotated @Transactional(REQUIRES_NEW), called from two private helpers on the same class. Spring's transaction advice l...
Main did not test-compile — PhiExportAuditTest missed a constructor arg
SystemConfigurationController gained a twelfth parameter, PlatformSecretCipher, when platform secrets began being encrypted at rest. This test still passed elev...
A picture-frame image whose bytes are gone answers 410, not 500
The frame stream caught everything as stream_failed and returned 500, so a photo whose object is not in storage rendered as a broken image with no explanation -...
A CCD preview is not a disclosure
Previewing a summary recorded a disclosure naming the recipient — so a patient asking who has their record under §164.528 would be told it went to somebody who ...
Nothing returned an account id, so nothing could be withdrawn
Withdrawing portal access and granting a proxy both take an account id, and no endpoint ever returned one. A practice could invite a patient to the portal and t...
22 of the 26 clinical rights were never enforced
Only the four population-level rights — bulk export, quality measures, portal administration and EHR settings — were ever checked. Prescribe, sign, cosign, plac...
An organization can be looked up by the reference ?org= carries
GET /org/ref/{ref} — the same projected record as /org/domain/{host}, for an organization named by its id or its web alias. Nothing could answer for one. The s...
Actually measure the bulk-export bucket
StorageDomain.BULK_EXPORTS shipped declared, documented as "measured by scanning the object store", and referenced by nothing. It reported zero for every practi...
Create returns the domain its theme is provisioned under
The caller cannot work this out and must stop trying. GET /org/{id} answers with the entity, whose `domains` is LAZY and serializes as null outside a transactio...
A push token may be claimed by one device row, not every past sign-in
Companion to MediaService 8a809b3, which stopped members getting the same chat message three-plus times on their phone. That change made dispatch collapse dupli...
Recover a lost background count from the images themselves
commitBackgroundOrder writes the images to STAGING, and imageBgCount is only a record of how many it wrote — which made that one column a single point of failur...
Gate the nine Service Work endpoints on a right
They shipped checking only that the caller had a session, so any member of an org could read and mutate every work order in it regardless of role. ASSIGN_SERVI...
Drop the nine Service Work endpoints from the unguarded baseline
They are gated as of e6e1d02, so their baseline entries no longer match an unguarded endpoint and **************** fails on the stale lines. Requiring the remov...
Stop the customer **************** rights reading every tenant's rows
Every endpoint that accepted a VIEW_OWN_* right as an OR-alternative loaded its record by primary key alone, never checking who it belonged to: getSubscription,...
Serve a tenant's assets from a host that resolves, and stop deleting its backgrounds
Two faults found while working out why a new org opened with no logo and no colours. THEME DELIVERY. Assets were requested from theme.<the org's own domain>. A...
Show one call once in a rollup, and stop 500ing on unworked leads
Two fixes the account rollup made visible. A phone number can be a contact point on more than one owner at the same time, and two leads on one account sharing ...
Make the KamoDesktop SSO link redeemable exactly once
The link is delivered as a URL, so it lands in browser history and in the reopen-closed-tab list, where it long outlives the session it was minted for. Until no...
The account rollup must not widen what a reader may see
The account timeline I added last commit was a way around the per-lead read gate. A member refused a lead's messages on the page that names the lead could open ...
/org/current stops depending on a live Hibernate session
This endpoint is what the workspace shell loads before it renders, and the client refuses a record it cannot read — Organization.fromJSON throws without a domai...
A failed workspace selection no longer destroys the sign-in
Reported as being thrown back to the email field with "Your sign-in timed out. Please sign in again." after clicking Continue. The timeout had not happened — th...
Stop the logo pass starving backgrounds, and read <picture>
Diagnosed against a real site that returned six logos, brand colours and zero background images. Three separate causes, all ours. The logo pass could eat the e...
An unfinished domain picks a different host, not a refusal
Entering an org was refused outright unless its own custom domain had finished DNS and SSL. That was right while entering meant navigating to https://internal.<...
Stop the SSO token expiry from emptying a live desktop session
"The requested connection does not exist. Please check the connection name and try again." on a KamoDesktop reconnect was not a missing connection. It was the S...
Send the member to the workspace host, not a relative path
SignInCompletionService returned a relative /validate?otk=. That resolves against the host that served the SIGN-IN — login.<apex> — and kamo-login has a /valida...
Delete the "first organization in the database" fallbacks
Seven blocks across five controllers ended their org-resolution with, in effect: if the server name is localhost or a bare IP, return whichever organization the...
Keep an alias unique platform-wide, on both write paths
Creation checked the alias only within one security provider, and PUT /org/{id} checked nothing at all — it applied whatever it was given. Both were reasonable ...
Refuse an alias that names more than one organization
byAlias took LIMIT 1 over orgs.alias, which has no uniqueness constraint: the create path checks it per security provider and PUT /org/{id} does not check it at...
Resolve the domain on /org/current server-side
internal.kamocrm.com failed to render with "Invalid organization data: missing 'id' or 'domain'". Organization has no `domain` field -- it has a `domains` colle...
Give the workspace path the same post-login work as the host path
Two gaps found by re-reading the original login tail against the new one, before enabling the picker. The form-encoded /login endpoint built its LoginRequest w...
Stop requiring DNS verification to sign in
OrgHostResolver.resolveByDomain filtered on od.is_dns_verified = TRUE, so a domain row that existed but had not finished verifying resolved to nothing and login...
Verify-dns answers for the present, not for a stored flag
The endpoint skipped probing entirely when ssl_confirmed was already true, on the reasoning that under the all-hosts rule it could only have been set when every...
Re-verify domains already marked SSL-confirmed, and heal them
findAwaitingVerification filters confirmed domains out by design, so once ssl_confirmed was set nothing ever looked at that domain again. That was fine while th...
Make post-commit org setup actually write, and heal the orgs it missed
A @Transactional method called from **************** does not open a transaction of its own. Spring fires those callbacks from processCommit BEFORE cleanupAfter...
Confirm SSL only when every org host has its own certificate
Certificates are minted one per FQDN -- a single dnsName each, so the leaf CN matches the hostname the browser connected to -- and auto-cert works through an or...
Serve frame media ourselves, with Range
Every photo rendered as a broken image. The URL pointed at MediaService's **************** which I took for a general imaging proxy because it spoke HTTP Range....
Stamp last_login so "Last Login" stops reading Never
Nothing in SecurityService has ever written users.last_login. The write lived in the retired AuthenticationService and was not carried over when authentication ...
Restore the status endpoint the frontend has been polling
kamo-internal polls GET /api/security/session/god-mode once on mount and every 60s thereafter. That endpoint was removed in 9c70cb7 along with the rest of the t...
Drop the universal seed; the timecard widget follows MANAGE_TIMECARDS
UNIVERSALLY_SEEDED_RIGHTS is removed entirely. It existed only because the timecard widget had no parent right to inherit from, and now it has one — so the widg...
Stop cutting note bodies off at 500 characters in the timeline
The All tab of a lead's communications rendered a note through LeadCommunicationMapper, which capped the body at 500 characters — with no ellipsis and no flag, ...
Report leads available for products with no allotment
/manage built its whole response by looping over allotments, calling countAssignablePool once per row. But the Manage-Credits grid lists products from the vendo...
Settle each backlog payload as it is processed
processBacklog mirrored the scheduled job's two defects: it mutated payload statuses in memory and saved them in one batch at the end, and it saved the whole en...
Never fail a submission because its counter update lost a race
storePayload no longer bumps the endpoint's received counter; the receive controller now calls recordReceipt separately, in its own transaction, and swallows th...
Make the verification sweep's DNS upgrade reachable
DomainVerificationWatcher gated on **************** but **************** only ever answers ok/pending/error/na — it has never returned "verified". allVerified w...
Restore media as a required DNS alias so its card can verify
media.<domain> backs MediaService realtime websockets and is live in Traefik, auto-cert and the /setup/dns studio catalog, but it was dropped from KnownAliases ...
Stop reporting a missing column as a missing table
Four controllers each rewrote ANY message containing "does not exist" into "Database table X does not exist. Please run KamoInitializerApp to create the schema....
Close two unauthenticated endpoints reachable from the internet
SecurityService is anyRequest().permitAll() with @EnableMethodSecurity absent, so every @PreAuthorize is inert and public is the default; APIService relays /api...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.