Add audited administrator resolution of uncertain email deliveries

This commit is contained in:
2026-09-06 13:06:17 +03:00
parent d956de3014
commit 22e886936e
8 changed files with 118 additions and 3 deletions
+11
View File
@@ -188,3 +188,14 @@ test('durable AI job endpoints enforce account isolation without starting provid
assert.equal((await request('/api/me/ai-jobs?id=missing','DELETE',null,other)).status,404);
assert.equal((await request('/api/me/ai-jobs','PUT',{})).status,405);
});
test('outbox review endpoint requires administrator and rejects unsupported or invalid changes',async()=>{
assert.equal((await request('/api/admin/notify/outbox','GET',null,null)).status,401);
assert.equal((await request('/api/admin/notify/outbox')).status,403);
assert.equal((await request('/api/admin/notify/outbox','POST',{id:'x',action:'skip',note:'Bu kullanıcı yönetici değildir.'})).status,403);
const admin=signToken({email:'outbox-admin@example.test',name:'Admin',isAdmin:true});
assert.equal((await request('/api/admin/notify/outbox','GET',null,admin)).status,200);
assert.equal((await request('/api/admin/notify/outbox','DELETE',null,admin)).status,405);
assert.equal((await request('/api/admin/notify/outbox','POST',{id:'x',action:'skip',note:'short'},admin)).status,400);
assert.equal((await request('/api/admin/notify/outbox','POST',{id:'missing',action:'skip',note:'Sağlayıcı kaydı kontrol edildi ve kapatılıyor.'},admin)).status,409);
});
+16
View File
@@ -69,3 +69,19 @@ test('notifier resumes exact saved email after provider failure even when curren
assert.equal(calls.length,2);assert.deepEqual(calls[0],calls[1]);assert.ok(calls[0].idempotencyKey.startsWith('notify/'));
assert.deepEqual(subscriptions.list('integration')[0].sonGorulenler,['integrated']);
});
for(const action of ['confirmed_sent','skip'])test(`manual outbox ${action} is audited, closes only uncertain work and prevents replay`,()=>{
const email='review-'+action;
const sub=subscriptions.subscribe(email,{konular:['Lab']})[0];subscriptions.markBaseline(sub.id,[]);
const delivery=subscriptions.reserveDelivery(sub.id,{to:email,subject:'Review',html:'A'},['review-tender'],{clock:1});
assert.throws(()=>subscriptions.resolveDelivery(delivery.id,'admin',{action,note:'Kontrol edilen sağlayıcı kaydı açıklaması.',providerId:'provider-proof',confirmed:true}),/inceleme beklemiyor/);
subscriptions.reserveDelivery(sub.id,null,[],{clock:23*3600000+1});
assert.throws(()=>subscriptions.resolveDelivery(delivery.id,'admin',{action,note:'short'}),/20 karakter/);
if(action==='confirmed_sent')assert.throws(()=>subscriptions.resolveDelivery(delivery.id,'admin',{action,note:'Kontrol edilen sağlayıcı kaydı açıklaması.'}),/kontrol onayı/);
subscriptions.resolveDelivery(delivery.id,'admin',{action,note:'Kontrol edilen sağlayıcı kaydı açıklaması.',providerId:'provider-proof',confirmed:true});
const row=subscriptions.list(email)[0];assert.equal(row.deliveryPending,false);assert.deepEqual(row.sonGorulenler,['review-tender']);assert.equal(!!row.sonGonderim,action==='confirmed_sent');
const review=subscriptions.deliveryQueue().find(row=>row.id===delivery.id);assert.equal(review.review.actor,'admin');assert.equal(review.review.action,action);assert.equal(review.state,action==='skip'?'skipped':'sent_manual');
assert.throws(()=>subscriptions.resolveDelivery(delivery.id,'admin',{action,note:'İkinci karar yazılmamalıdır açıklaması.',providerId:'provider-proof',confirmed:true}),/inceleme beklemiyor/);
assert.equal(subscriptions.reserveDelivery(sub.id,{to:email,html:'A'},['review-tender']),null);
assert.equal(subscriptions.remove(sub.id,email),true);assert.equal(subscriptions.deliveryQueue().find(row=>row.id===delivery.id).review.action,action);
});