A quote's letterhead falls back to the primary platform apex
QuoteMapper kept its own "kamocrm.com" literal as the theme host of last resort, so a quote for an organization with no live domain still named the old brand's ...
A lead that was ever assigned or opened can be deleted
LeadService.deleteLead cleared only lead_custom_form_data before deleting the row, and six other tables carry a foreign key onto leads(uid). Every assignment wr...
A team member is equal to another only when their ids are (SP10)
SP10 T47, live: MediaService answered "one or more memberIds not found" to a group chat of the owner and two AI members. Lombok's @EqualsAndHashCode(callSuper =...
Publish routes another stream's subject instead of pinning ours; lead notes reach the feed after commit
**************** asserted expectedStream(<own stream>) on every subject, so a subject another stream captures was refused with "expected stream does not match [...
Keep the meeting transcript's ciphertext columns out of JSON
**************** has failed on main since f92765b1 added MeetingTranscript: transcriptTextCipher, transcriptVttCipher and summaryCipher had neither @JsonIgnore ...
An AI workstation's take-over and MCP token are written only by their own UPDATEs
control_member_id/_started_at and **************** are now updatable = false, and HostedComputerRepository gains the only writes they get: recordControl, clearC...
Send Arive the language CODE, not its name — every Create Loan was refused
Arive's Zapier field shows language names but its API takes ISO 639-2 codes (chi, eng, kor, spa, tgl, vie; zxx for Other). Kamo sent "English", so Arive answere...
An AI member is never promoted to organization owner
**************** refuses isOrganizationOwner=true for an ARTIFICIAL target. The owner flag grants every platform right in the top-level organization and opens o...
Keep kamo-shared-library at 1.6.1, the one version every consumer can resolve
db737a54 moved the library to 1.6.2, and only emailservice and initializerservice moved with it. About thirty other services pin 1.6.1. Their CI clones this rep...
An org domain's DKIM private key never serializes
5de57705 added OrgDomain.dkimPrivateKey — the key that signs a domain's transactional mail — with a comment saying it is never sent to the browser, but nothing ...
History records what happens after a lead exists, not its starting form
recordCreated wrote the CREATED row and then diffed the new lead against an empty snapshot, so every non-null starting field became a FIELD_CHANGED row — and th...
A gift card's balance is editable again, by whoever may manage pricing
19505faf stopped updateGiftCard from reading currentBalance so a member of one org could not rewrite another org's card by uid. The org-scoped lookup already cl...
Org-scope RetailService and ****************
Every get/update/delete-by-uid handler under CommerceMarketController's retail sub-resources (categories, brands, attributes/values, images, variants, tags, rev...
UpdateMemberAccess rejects an editor and target in different orgs
**************** compared only security levels and the editor's owner flag, never the two members' organizations. Its one caller today (SecurityService's Member...
RegisterExistingDocument checks the dat's org, and a template can be found by imgId within one
Two org-scoping gaps the esig/imaging audit found, both in shared entry points other services build on: - **************** (the conversion service's dedup-skip...
Count an org's unconfirmed talent-alert rows for the anonymous form's cap
DocsService's public talent-alert subscribe endpoint sends a confirmation email on every accepted call, with no limit on how many not-yet-confirmed rows one org...
UpdateDocType now requires the doc type to belong to the document's own org
ImageService.updateDocType loaded the target ImgDocType by UUID alone; requireEditableAndOwned proves the caller may edit the Img, but says nothing about whose ...
Org-scoped counterparts for the thumbnail-backfill candidate queries
DocsService's /backfill-thumbnails admin endpoint selected candidates from **************** (platform-wide, no organization predicate) or, as a last resort, a r...
UpdateDocType now requires the doc type to belong to the document's own org
ImageService.updateDocType loaded the target ImgDocType by UUID alone; requireEditableAndOwned proves the caller may edit the Img, but says nothing about whose ...
Org-scoped counterparts for the thumbnail-backfill candidate queries
DocsService's /backfill-thumbnails admin endpoint selected candidates from **************** (platform-wide, no organization predicate) or, as a last resort, a r...
Count an org's unconfirmed talent-alert rows for the anonymous form's cap
DocsService's public talent-alert subscribe endpoint sends a confirmation email on every accepted call, with no limit on how many not-yet-confirmed rows one org...
A Hosted Computer is never provisioned automatically
Hosted Computers was reachable by both automatic provisioning paths, and either one would have put it in front of every organization on the platform at once. F...
Intake endpoint counters come from a ledger and stop losing updates
**************** / total_processed / last_received_at were bumped on the endpoint row itself: once per inbound payload (~5/s during a farm import) and once per ...
Keep every credential field out of JSON, and guard the rule library-wide
Follow-up to 034378d2, which covered the columns NAMED as ciphertext. Read-only audits of origin/main in every repository found 61 more fields holding credentia...
A lead search matches the lead's email too
The /leads grid's boxes and the drip enroll dialog send what was typed as search terms, OR-ed across the lead's names, company, vendor lead id and number. The e...
Keep every ciphertext column out of JSON, and guard the rule library-wide
Follow-up to 096feaa1 (Organization's GoDaddy credentials were being served by an endpoint that needs no session). A scan of every **************** found fourte...
Never serialize the GoDaddy key and secret ciphertext
GET /api/security/org/{id} (and /org/domain/{host}) returns the Organization entity itself and answers without a session, and that body carried godaddyApiKey an...
People in a paused drip still leave it when their lead moves on
A paused drip's exit rules (status change, reassignment, goal click) are now listened for, so resuming it never sends to someone who should have left while it w...
Chained drips hear when someone finishes a drip
A drip that starts when someone finishes another drip listens for the engine's own DRIP_COMPLETED events, but the recorder's trigger map left that kind out, so ...
Reconcile durable consumers on the stream that owns the subject
The filter and deliver-group reconciles looked consumers up on the service's configured stream only. Subscriptions to subjects captured by another stream (socia...
Coalesce pool-availability recounts instead of recounting per lead
countAssignablePool scans every lead in the org+market and ran synchronously after every createLead commit. At ~14k leads it already cost ~165 ms, more than the...
Accept the demo page's extra fields on public schedule/join requests
MediaService reads PublicScheduleWebinarRequest with a bare ObjectMapper, where FAIL_ON_UNKNOWN_PROPERTIES is true. The demo page also sends ***Payload, so ever...
Saving a campaign never writes back its counts
The five counters are running totals now, moved only by EmailService with relative updates ("sent_count = sent_count + 1"). Mapped updatable = false, so a campa...
Read the platform's hex secret as hex, and stretch a short key instead of refusing it
JWTUtils decoded security-service.*** as Base64 only. The platform's secret is 64 hex digits (32 bytes), which Base64 turns into 48 meaningless bytes; those wer...
Count the files a document keeps only as old versions
A category that keeps versions holds every earlier file of a document in img_versions, each on its own content-addressed file. The storage meter, the quota and ...
An organization's own domain is named in a link only once it is live
OrgLinkHosts is the one rule for the host a link to an organization may name: its own root domain once it is active, ownership-verified and SSL-confirmed ******...
Rank only members whose security type includes achievements
The leaderboard grouped every member holding an achievement row, so a member whose role denies VIEW_ACHIEVEMENTS — who cannot open the page, the trophy or the w...
An app id an older build cannot name must not fail every feature read
ServiceType ships inside each service's jar while ORG_FEATURES is shared, so a newly added app is ALWAYS in the database before the older readers have been rebu...
Cover the three shared reads a catalog bump still reached users through
Same defect as the sign-in fix, found by reading the fleet's logs rather than one report: eight hours of pod logs across email, media, docs, daemon and security...
Retry the two rights reads that stand between a password and a session
MemberRightsAppliedService carried @RetryOnDbConflict on its WRITE entry points only. The class therefore read as covered while the two methods the authenticate...
The update DTO needs the first-time-buyer field too
68ce0e0f added `isFirstTimeBuyer` to the CREATE request and wired both call sites in LeadService — but the second one reads UpdateLeadRequest's own nested Mortg...
Put back the CRLF a Python edit stripped from two files
Both files are CRLF in this repo, and rewriting them through Python's text mode converted every line — turning a fifteen-line addition into a 771-line diff in 6...
Bring the organization inside the retried read instead of leaving it to fire later
Member.organization is LAZY, so findById left a proxy behind and the real SELECT happened whenever something first dereferenced it. Under open-in-view that is t...
Share the delivery consumer, so a second pod is not refused
Caught in production the moment services went to two replicas on 2026-09-04. Every pod carrying this class logged, once, at boot: [Webhook] Failed to subscri...
System_bug.published needs a column DEFAULT, or it is never created
The field was declared `@Column(nullable = false)` with no columnDefinition, so ddl-auto emitted `ADD COLUMN published boolean not null` — which Postgres REFUSE...
An empty platform registration is not "connect with Kamo's app"
isPlatformEnabled now also requires a client id, matching what OrgOAuthClientController reports as platformEnabled. Without that the meetings screen and the bri...
Comping an account now drops its cached entitlements
SecurityService answers /api/security/entitlements/me out of Redis with a 15-minute TTL, invalidated by messages on kamo.entitlements.invalidate. Every self-ser...
Editing a draft order's seats or cycle now reprices it
updateDraftOrder set seatCount and billingCycle and saved. Both are price drivers, and neither the order's money fields nor its line items were touched, so the ...
A comped order now grants the add-ons it sold
Comping an account granted the plan and nothing else. provisionCompSubscription copied plan, seats, cycle, source and status onto the AccountSubscription and ne...
Bind content_json as JSON, or every insert fails
REPORTED: "Failed to create sales script". The server said exactly why: column "content_json" is of type jsonb but expression is of type character varying ...
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.
