The E-Mail app's description is the shared library's current one, not "Host your email with KamoCRM directly."
These TypeScript enums mirror kamo-shared-library's AppType and ServiceType. The Java source's EMAIL description was reworded ('Read, send and manage your organ...
The sign-in screen credits KamoUniverse and falls back to its apex
kamouniverse.com is now the platform's primary apex (kamocrm.com stays a fully served legacy apex): - Theme.tsx: PLATFORM_APEX, the theme host used before the ...
Send a universe sign-up to its checkout, or to create its organization
kamo-register parks a paid sign-up's plan in sp_checkout_plan, and the KamoUniverse site's plans are the universes' own (family_premium, community_starter, pers...
Login.kamouniverse.com wears the KamoUniverse brand
login.kamouniverse.com is the platform's KamoUniverse sign-in door. Its host resolves to the platform organization, so the by-host lookup would answer "crm" and...
No anonymous write to the session Redis, and no session id in the sign-out log
POST /api/session stored any JSON under any KS= key, with a caller-chosen TTL and no authentication, through a Redis client pair of its own. The session Redis r...
Sign-in logos load a pre-sized copy, and the original when it is missing
Each theme folder now carries img/sized/<stem>/h<rung>.webp beside every logo. A PNG org's logo.svg / logo-full.svg is its whole upload wrapped in base64 (sever...
The *** cookie on login.* is HttpOnly, and no log line carries half a session id
/api/login, /api/login/mfa and /api/session/select planted *** with httpOnly:false ("client- accessible for session checks") — but no browser code on login.* or...
Call it the email on their account, not their personal one
The address a work email is pointed at is whatever the user account holds. That can be a work address an administrator set, not only a personal one. The panel n...
Point a member who typed their work email at their personal one
Forgot-password resets go to the address on the user account, usually a personal one, but members type the work address their organization gave them. SecuritySe...
Send the typed address with the reset code, and forward the caller's address
The reset page sent the 8-character code from the letter on its own, and SecurityService checked it against every account's outstanding reset at once, with no c...
Show the organization's own backgrounds, as many as it has
The sign-out screen asked for img/bg/1-3.webp whatever config.json's backgroundImageCount said, so an organization with no backgrounds of its own was shown what...
Let the organization word the ribbon, and own the tab icon
"Welcome Back!" moves out of the root layout into PaneRibbon, a client component, because the wording is now the organization's to choose and this site learns i...
Carry a referral code through to the register link
The referral code normally travels in the apex cookie the marketing site sets (kdsc_src on .<apex>), which register.<apex> reads for itself, so this link does n...
Carry the job advert through a sign-in, and land on the Careers tab
Somebody who presses Apply on the public careers board and already has an account reaches the register page, follows the sign-in link, and used to arrive on a d...
Drop the animated glimmer
Removes the corner-fading sheen added in 70d068c and 6810799 in full: both spinning layers, the conic gradients, the ring and envelope masks, and the extra z-in...
Fade the glimmer out at two corners, and cap it at half
The sheen now dies completely at the top-right and bottom-left corners and peaks, at half opacity, over the top-left and bottom-right. Each revolution reads as ...
Run a glimmer round the pane's gap every five seconds
A conic gradient centred on the pane, spun once per --glimmer-period, painted twice: a sweep filling the 15px gap, and a 2px rim on the pane's own border. The r...
Seat every screen in a rounded pane under a corner ribbon
Every route now renders inside .kamo-pane: a card inset 15px from the browser edge with a 14px radius, a soft shadow, and overflow:hidden, so a page's own conte...
Prove the deploy by digest, not by tag
The preceding commit stops `set image` being a silent no-op. This asserts the outcome: after the rollout, the tag is resolved to a digest at the registry and th...
A rebuild of the same commit deployed nothing and reported success
The image is tagged with the commit SHA, so rebuilding the same commit produces an identical image reference. `kubectl set image` then changes nothing, the Depl...
Make the strike meter agree with its own caption, and read aloud
Three things the screen was getting wrong, all found by looking at it rather than by running it. The bar was a TALLY of failures, wrapping every five segments....
Show the progressive lockout, so a held sign-in explains itself
The server now refuses sign-ins on a ladder — five free attempts, then five seconds, then locks of five, fifteen and thirty minutes, then a permanent block. Wit...
Drain on SIGTERM, answer a readiness probe, and run two pods
Next handles SIGTERM with a bare process.exit(143), so every deploy severed whatever this pod had in flight — a form post, a server action, a streamed RSC paylo...
Paint every logo on the sign-in site in the org's overlay colour
The org chooses "Login Site Logo Overlay" in kamo-internal beside the home page and loading screen overlays. One setting for the whole site: the sign-in form, t...
Never show a status phrase to somebody who clicked a link
Rendering the page against an unreachable backend put "Internal Server Error" on screen as the explanation. That is a status phrase written for an operator read...
Answer the link in an address-change letter
/verify-email-change spends the token in a change-of-address letter and says what happened. It lives here rather than in the workspace because the letter goes t...
Give the rollout room for the 15s minReadySeconds now costs
progressDeadlineSeconds was 60. That is the window a rollout has to show progress before Kubernetes gives up and marks it failed, and the previous commit added ...
Let a rollout finish what the old pod was doing
Deploys replaced the only pod of each service with nothing to catch the requests in flight. Three settings, applied across the fleet: - preStop sleeps 10s befo...
Paint a white-label sign-in screen from the host's organization
Every image and colour was missing on login.<customer domain> for any organization created after the 2026-08-26 alias migration. getThemePath() resolves an exp...
Delete /api/auto-login, which no longer has a caller
The endpoint existed to turn an existing *** cookie into an OTK and a redirect so the login page could forward a signed-in member straight into their workspace....
Let a signed-in member reach the sign-in form, and back out of the workspace picker
Two halves of the same problem: the login page was a one-way street. It validated any existing *** cookie on load and, when the session was still good, redirec...
The FreeSWITCH crash was mod_kazoo's default config, not the event profile
The stub kazoo.conf.xml 2600Hz ship has no definitions, event-handlers or fetch-handlers sections. mod_kazoo says as much and then faults in its own config thre...
Record four more KamoPBX bring-up traps
- Community mod_kazoo (FreeSWITCH v1.10.11) connects to ecallmgr, reports "Connected", and then never answers a gen_server:call. Resolved by taking 2600Hz's...
Resolve the Kamailio question — SIP registration works end to end
Section 16 recommended a purpose-built config on stock Kamailio and recorded that "2600hz/kamailio does not exist". Both are corrected by evidence. Two further...
Record what is running and the traps that cost a build each
Nine failure modes discovered the hard way, each of which would otherwise be rediscovered: the gitignored vendor tree, make re-fetching over it, ripgrep honouri...
2600Hz ships a patched Kamailio (spec 16)
kazoo-configs-kamailio does not run on stock Kamailio. bflags and import_files are both absent from kamailio/kamailio's own src/core/cfg.lex, and both are rejec...
Reveal the preselected workspace, and give the list the org's scrollbar
Two things about the workspace picker, both about the same list. The workspace a member used last is preselected and named on the button, because this screen i...
FreePBX is deprecated (Decision 4 revised)
No migration and no permanent coexistence. KamoPBX stays on k3m1 whose host netns is empty, so it needs none of FreePBX's ports and no shutdown is required. Des...
KamoPBX implementation plans (programme + 9 phases)
Decomposed into one plan per phase; a single plan would not produce working software until the end. Full bite-sized TDD detail: Phase 0 infrastructure gate ...
Record KamoPBX decisions — KAZOO confirmed, k3m1 placement, ACDc, Tier 3 rebrand
Six open questions answered: 1. KAZOO is the route; hardware owned, so cost framing removed entirely. 2. One node/cluster now, three later — CouchDB q=8 from da...
Record the enum-ordering trap the PBX rollout hit
Seeding a catalog row whose pricing_model is a new enum value makes that row unreadable to any service still on an older shared-lib, and getCatalog loads every ...
Plan per-mailbox billing and the personal-mailbox backend
Plans B and C of 3. Self-review closed five gaps: nothing set mail_cost_mode, nothing server-side stopped a billing group buying mail add-ons, the invoice mailb...
Correct the spec — StorageAutoExpandSweep already exists
The spec claimed no server-driven-quantity reconciler existed to reuse and listed the storage auto-expand columns as dead. Both false: the sweep reads them nigh...
Design per-mailbox e-mail billing and add-on gating
Bills e-mail by the mailbox rather than the seat, gates provider choice on the add-on that covers it, and attributes each mailbox to the billing group that shou...
Brand the sign-in screen from the org's alias, not the host
login.kamocrm.com is the sign-in screen for every organization that has no host of its own. The theme base was derived from that hostname, so all of them were p...
Theme assets come from a host that resolves
The sign-in screen paints an organization's branding from theme.<its own domain>. That domain may not resolve: an org can exist and be signed into before its DN...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
