Show Google's OAuth callback URL on its registration card
An operator filling in the Google Workspace registration had nothing telling them what to put in the Google Cloud console's Authorized redirect URIs, and the Re...
Accept an explicit org, not only the host
Registration bound the account to whatever organization the host resolved to. On register.kamocrm.com — the signup page for every organization with no register ...
Forward /api/email/oauth/callback to EmailService
Google's OAuth redirect target. Same shape as the email and meet provider callbacks beside it: public and sessionless, because the popup lands on this gateway o...
Serve Google's OAuth callback on /api/email/oauth/callback
The platform console needs an address to show an operator setting up the Google Workspace registration, the way VOIP has /api/voip/oauth/callback. The only emai...
Brand and scope signup with ?org=
register.kamocrm.com is the signup page for every organization that has no register host of its own, so the hostname cannot say which one a visitor is signing u...
The FHIR datatype layer and its discipline harness (SP3)
The foundation every clinical entity reuses, and the build gate that stops it drifting. Both land together on purpose: a harness written before there is anythin...
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 the AI training corpus exports for PHI tenants
ANALYTICS_EXPORT is blocked because exports leave the boundary with no de-identification. Both training exports already had a fail-closed audit — there IS a rec...
Refuse MCP tool execution for a tenant that handles PHI
executeTool forwards operator-supplied arguments to an operator-typed URL and can spawn a stdio process, with no allowlist, no SSRF guard and no destination aud...
Guard social messaging and Canva at their credential chokepoints
SOCIAL_MESSAGING is enforced in SocialCredsResolver.resolve — the narrowest point covering every adapter and both directions. No credentials means no Telegram, ...
Guard the last four unenforced capabilities; the baseline is now empty
SOCIAL_MESSAGING, CANVA, MCP_GATEWAY and ANALYTICS_EXPORT were each declared outside the compliance boundary, bound to no ServiceType, and checked by nothing — ...
Rights, entities, repositories and DTOs
MANAGE_SYSTEM_BUGS is a PlatformRightType and must stay one: the dispatch it a tenant administrator can edit their own organization's security models. Screensh...
Add a global alias-uniqueness check
**************** scopes by provider, and that was right while an alias was only ever resolved as (security_provider_id, alias) — the pair behind a <alias>.<pare...
Dispatch a bug report into sage's open VS Code
URI handler that creates a conversation in a RUNNING window and pre-fills the input, which is the only way to reach the editor sage already has open instead of ...
Create the System Bugs tables
No CHECK constraint on the ordinal columns: support_ticket_status_check is what happens when Hibernate freezes one at an enum's size and the enum then grows, an...
Plan the System Bugs build across six repos
Screenshots turn out to need no table: an Img row already carries an assoc type plus an assoc object id, and imgs has no CHECK constraint on assoc_id, so append...
Manage a custom domain from Company settings
A domain used to be the doorway into an organization: DNS had to be configured before anyone could sign in at all, which is why /setup/dns was reached from the ...
Design the System Bugs tab and its AI dispatch path
vscode:// URI handler opens a conversation in the window sage already has open, and coderProcessWrapper carries model and effort, which the URI cannot. Also rec...
Record SP1 as complete, and the six things the plan got wrong
Keeps the reasoning rather than just ticking boxes — the top-level-org skip and the PLANNING-stage regression are both the kind of mistake that would be made ag...
Send the tree on the app-catalog endpoint too
Branch Types → Allowed Apps builds its editor from /features/app-catalog, not from the tenant features listing, so it was the one surface that could not see whi...
Render the app tree, and confirm what a parent switch-off takes
Children now sit under their parent in the Apps & Features list, each with its own switch. Nesting is expressed by ORDER plus an indent rather than a nested con...
Price the commerce children and the EHR, with a totality guard
Neither pricing map had a totality check, and the two failure modes are different and both silent. Missing from CATALOG, an app lands nowhere on the pricing mat...
Rebuild against the Affiliate Sales Scoreboard rights
No source change here. SecurityService is what enumerates RoleRightType.values() to serve the rights editor (SecurityRoleController) and to populate a grant-all...
Stop counting a member's visits to their own link
A member checking that their own tracking link works is the most common first visit any code ever gets, and it is worse than useless: it inflates the number the...
The Affiliate Sales Scoreboard widget
One grid column wide and two rows tall: the ten people in the organisation bringing in the most through their tracking links, over today, this month, this year ...
The Affiliate Sales Scoreboard endpoint
GET **************** answers this organisation's top ten for one metric over one window, plus the caller's own standing when they are not on it. The counters o...
Add the Affiliate Sales Scoreboard widget rights
Five rights, 234-238, in the MARKETING group and hung off VIEW_REFERRAL_CODES: a leaderboard of referral numbers is tracking-code data, and a member who may not...
Brand and scope the sign-in screen with ?org=
login.kamocrm.com is the sign-in screen for every organization that has no host of its own, so the hostname cannot say which one is signing in. ?org= does: it n...
Serve an org's branding to a screen with no session
Login, registration and the meeting lobby paint an organization's colours before any session exists. They knew which one from the hostname, which is exactly wha...
Restore CRLF on the two theme files
Both files are uniformly CRLF and my previous commit rewrote them through Python in text mode, which reflowed every line: Theme.tsx showed 237 changed lines and...
Paint the branding of the org in the tab, not the host
getThemePath() derived the theme base from window.location.hostname. That answered the right question while every organization had a hostname of its own — and f...
Clear the cloned session in the enter-as tab
Entering an org opens a tab with window.open('', '_blank') and points it at /validate. That was cross-origin until now, so nothing was shared. It is same-origin...
Ratchet that a blocked capability with no app has a call-site guard
Splitting an app from the capability inside it is what lets a clinic hold a phone system and a video room at all, but it moves the enforcement burden. PhiModule...
Refuse meeting recording for a tenant that handles PHI
The capability split made ServiceType.MEET permitted — a live conference on self-hosted Meet never leaves the cluster — while MEETING_RECORDING stayed blocked, ...
The blocked capability now outranks the right, and god mode
PhiPlaybackAuthorizer gated PHI call playback on VIEW_CALL_LOGS. That was the whole check because ServiceType.VOIP mapped to the blocked VOIP_RECORDING module, ...
Regenerate the ServiceType mirrors after the stage correction
The five pre-existing commerce verticals are COMPLETED, EHR is PLANNING.
The five pre-existing verticals must ship available
Shipping all six children PLANNING was wrong for five of them. RETAIL, RENTAL, SERVICE, SUBSCRIPTION and PROCUREMENT are not new functionality — they are what C...
Read the session from the tab, not the shared cookie jar
46 client modules read the *** id out of document.cookie and sent it as X-***-Token. sessionStorage is per-TAB; a cookie is per-ORIGIN. While every organization...
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...
The scheduled-support presenter picker offered nobody
The Presenters tab dropdown was empty for every organization, and always had been. GET **************** answers with { teamMembers, total }; the tab read data.m...
Serve the app tree, and fix the unguarded auto-enable
FeatureController now sends parent/children/isParent on every serialized app so the client can render children nested under their parent. Served rather than mir...
Mirror the six commerce child apps, and stop the mirrors drifting
Both TS mirrors are now GENERATED from ServiceType.java rather than hand-maintained. They had drifted badly from Java and from each other: stale "RAG integratio...
Task 7 needed no new migration, and top-level orgs must be included
The app-tree backfill turned out to already exist as **************** restricted to isGated() verticals. Dropping that restriction is the whole change. Records...
One scrollbar, three times as wide, down every conversation
The bar beside the messages was 8px in the member chat and SMS, 6px in support tickets and social, and in the AI chat it was nothing at all: that list declared ...
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 /api/org/current the domain the client requires
internal.kamocrm.com failed to render with "Invalid organization data: missing 'id' or 'domain'". Organization.fromJSON refuses a record without a domain, and t...
Move jump-to-newest in with the toolbar's other actions
Search now owns the whole left track of the toolbar, because the empty part of that track is exactly the room the field opens into. The scroll-to-bottom control...
Refresh the favicon and drop the unused blueleven logos
public/favicon.ico now carries 48x48 and 32x32 layers instead of 32x32/16x16. The five logo-blu*/logo-blueleven* PNGs are referenced from nowhere in the app, so...
Je, unaona nini kuhusu usafiri?
Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.