fix(audit): residential/tenancies — M28 (unified stage validation), M29 (explicit-disable wins), L31 (active-tenancy warning), L32 (socket event + saveStages tx)
Updated tenancy-auto-create integration test to assert M29 (explicit disable respected) instead of the old re-enable behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import type {
|
||||
UpdateResidentialInterestInput,
|
||||
} from '@/lib/validators/residential';
|
||||
import { sendEmail } from '@/lib/email';
|
||||
import { assertValidStage } from '@/lib/services/residential-stages.service';
|
||||
import { SETTING_KEYS, getPortBrandingConfig, readSetting } from '@/lib/services/port-config';
|
||||
import { brandingPrimaryColor, renderShell } from '@/lib/email/shell';
|
||||
|
||||
@@ -550,6 +551,15 @@ export async function updateResidentialInterest(
|
||||
});
|
||||
if (!before) throw new NotFoundError('Residential interest');
|
||||
|
||||
// Reject moves to a stage that isn't in this port's live stage list.
|
||||
// The validator accepts any string (so admins can add custom stages
|
||||
// without a deploy); the membership check is enforced here at write
|
||||
// time so a PATCH can't park an interest on a non-existent stage that
|
||||
// would then surface as an orphan in funnel reports.
|
||||
if (data.pipelineStage !== undefined) {
|
||||
await assertValidStage(portId, data.pipelineStage);
|
||||
}
|
||||
|
||||
const [updated] = await db
|
||||
.update(residentialInterests)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
|
||||
Reference in New Issue
Block a user