Required member profile: username + verified email per position, gated at proof of ownership
Marty, 2026-09-16: leaders can write but 94% of positions cannot receive (47 of 771 have ever signed in to messaging, 482 messages sit 85% unread). profiles.js stores username + verified email per POSITION (one wallet holds one position, so a Triple Play holder has three; the person is the email and one email may hold several positions). Seeds the 40 emails already on file from member-alerts.json, pre-filled but unverified so confirming costs one tap. Writes are only ever accepted from a session that PROVED ownership: wallet personal_sign (messages.verifyChallenge) or the Telegram Mini App bridge. The public /my/<id> page is untouched and cannot write a profile, verified by test: all four endpoints 401 unauthenticated while /my/21 stays 200. Endpoints GET /api/public/profile, POST .../username, .../email-start, .../email-verify, plus GET /api/admin/profiles for coverage. Email codes: 6 digits, 15 min, 60s cooldown, 5/day, 6 tries. profile-gate.js is a two-step modal that cannot be dismissed, fired on dashboard boot (covers the Mini App landing) and right after a wallet sign-in. Chatbot canned answer + AI prompt updated. 28 unit tests pass. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -419,6 +419,7 @@
|
||||
const sig=await eth.request({method:'personal_sign',params:[hex,account]});
|
||||
const v=await(await fetch('/api/public/msg-verify',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({address:account,signature:sig})})).json();
|
||||
if(!v.ok)throw new Error(v.error||'Verification failed.');
|
||||
try{ if(window.RMCProfile)await window.RMCProfile.require(); }catch(ge){}
|
||||
loadMsgUI(d);
|
||||
}catch(e){if(err)err.textContent=e.message||String(e);}
|
||||
}
|
||||
@@ -756,4 +757,7 @@
|
||||
const id=pathId();
|
||||
if(id&&!pathHasId)openDashTab=true; // bare /my resolved from storage = returning to your own page
|
||||
if(id)load(id);
|
||||
// Required member profile (username + verified email). No-ops for a visitor who
|
||||
// has not proved they own a position: the API 401s and the gate never shows.
|
||||
try{ if(window.RMCProfile)window.RMCProfile.require(); }catch(e){}
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user