Invoice links keep working after a resend or reminder; a late-sent invoice is not chased the same hour
Every send and reminder minted a new view-online token and replaced the old one, so the link in the first email Harmony received read "no longer available" once...
Approving a card order grants paid access too
AUTO_BILL orders waited for a Stripe checkout that subscription invoicing no longer uses; the ledger charges the saved card on each billing day instead.
Subscription events store JSON states; billing steps run one row per transaction
**************** are jsonb, and every caller wrote a bare status like ACTIVE - an invalid JSON insert that rolled back whatever it was auditing (order activatio...
Name the organization that owns a subscription catalog row
The catalog update/delete methods take a uid alone, so a caller holding the catalog right in any organization could edit another organization's plans, prices, a...
A dat's object key also asks the inbound MMS parts that hold it (SITP MMS)
VOIPService now keeps the pictures and files people text in (VOIP_MESSAGE_ATTACHMENT) through storeContentAddressed, with no Img row. storageExtension found a d...
A god-mode window is open only until its stamped end (SessionPlatformFacts)
godModeActive() now also needs godModeExpiresAt (epoch millis, number or string) to be after now. SecurityService masks an elapsed window only for its own gates...
Clinical audit rows keep purpose/basis/patient; updated_at stamped on every save (SITP TP23FU)
PhiAccessRecorder stamped occurredAt by rebuilding each event from a field list written before the clinical columns existed, and no caller sets occurredAt, so e...
Deleting a mortgage application no longer 500s, and a received one is kept (SITP TP21FU)
DELETE **************** failed for every application: AppMortgageService.delete removed the borrowers through the JPA cascade while borrower_declarations / borr...
IotConnectionCheck is append-only without @Immutable (every link failed with a 500)
Hibernate 6.5 reads the database-generated checked_at back after the INSERT and then sets a lock mode on the entry; an immutable entry refuses it **************...
Keep hook-token and share-token hashes out of JSON; the OAuth secret prefix is a label
**************** was red on main: **************** and previousHookTokenHash, **************** and previousHookTokenHash, and IotShare.tokenHash had no @JsonIgn...
Seat an organization's existing staff when its subscription is set up
A comp, like a first purchase, created its seats UNASSIGNED and seated the owner alone. Everyone else waited for the owner to hand seats out in Billing, which n...
The default Live Support welcome no longer promises someone 'shortly'
Nobody on the team is notified until the visitor sends their first message, so the default now says that: send a message to reach the team, they're notified whe...
SubscribeQueueBatch binds a WorkQueue stream with DeliverPolicy.All
IOT_EVENTS is a WorkQueue stream (IoT SP00-D6) and NATS refuses any other deliver policy there (10101), so iot-service crashlooped at boot. The policy is read f...
An Img keeps the extension its content is stored under β on dedup and on rename
fileExt is part of the storage key (<imgDatId>.<ext>) every reader builds, but dedup matches on the BYTES. Content already held arriving under another name (a ....
Vet and pin every webhook target, return only failure categories, encrypt signing secrets
The outbound webhook worker POSTed to whatever URL a subscriber stored, from inside the cluster, with no egress control - a subscription aimed at **************...
Read the bulk-export and exchange-document sweeps instead of reporting 0
OrgObjectStorageSweep writes BULK_EXPORTS and EXCHANGE_DOCUMENTS rows into object_storage_days, but OrgStorageAggregator only read that table for BRANDING and D...
A market save rejects a missing or unknown custom form
Both association loops skipped a null form id, or one the organization does not own, and the save still returned success. That is how every market lost its form...
Saving a form no longer rejects its own field IDs
updateForm replaces every stack and field, but the field-ID check compared the request against the rows already stored. The editor sends no field id, so each ke...
RemoteWorkLinkResolver posts through a LabelTransport, so a Spring Boot 3.1 service can declare it β no signature names RestClient (master CP-D97); defaultTransport() keeps the 2 s connect and 5 s read timeouts; a guard test keeps RestClient out (KamoCollab CP05 Task 28)
Resolve releases the record and its inherited sources together β a group pair withheld for mixed reasons (some members INHERITED, some NO_BASIS), or a NO_BASIS pair on a record learned from others, names a releaser only if their one release clears it on re-decision (KamoCollab CP07 Task 3, fix round 1)
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...
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.
