KamoCRM

Close the AI identity edge cases the SP02 review left open

FixSecurityService
Shipped
September 28, 2026 at 10:11 AM UTC
Author
Kamo
Commit
103e99f

- A never-hired AI relabelled a person no longer keeps ai_state and the pause columns (master 6.1: NULL for a person). They are written only by SQL, so the profile save clears them after the member save whenever a person still carries them (SP98-C-1). - intelligenceType is read in any case, trimmed, by creation, the bulk import's duplicate check and the profile save alike (IntelligenceWire), so a lower-case "artificial" row is an AI to all three (SP98-C-2). - The credential exchange reads the stops again once the session exists (credential, kill switch, org pause, member state). A pause, retire, pause-all or kill switch that committed while it was minting now takes the session back and refuses, instead of leaving it alive until its TTL (SP98-C-3). - Two concurrent credential issues, or a retire, pause or resume that lost a race, answer 503 RETRY rather than 500; a duplicate key on the live credential index counts as a race. Retire's UPDATE is guarded like pause's, so a retire another one beat does nothing more and audits nothing (SP98-C-4). - PUT /members/{id} refuses any status other than ACTIVE on an AI that is not retired: 409 {reason: USE_RETIRE, field: teamMembershipStatus}. It used to stop the AI's sign-in and nothing else, leaving the seat held, the credential live and the hire steps running. An unchanged status still saves, and a never-hired AI relabelled a person in the same save may leave like any person (SP98-C-5).

All changes

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.

Start Free ForeverView Pricing