diff --git a/profiles.js b/profiles.js
index abffbbd..93242dd 100644
--- a/profiles.js
+++ b/profiles.js
@@ -159,6 +159,15 @@ function positionsFor(email) {
const e = String(email || '').trim().toLowerCase();
return Object.values(db.byId).filter(p => p.emailVerified && String(p.email || '') === e).map(p => p.id).sort((a, b) => a - b);
}
+// Reach for one leader's org: how many of the positions below them have given a
+// way to be contacted. This is the number that makes coverage a leader's own
+// problem rather than a rule imposed on members.
+function reachFor(ids) {
+ const list = (ids || []).map(Number).filter(Boolean);
+ const reachable = [];
+ for (const id of list) { const p = db.byId[norm(id)]; if (p && p.emailVerified && p.email) reachable.push(id); }
+ return { total: list.length, reachable: reachable.length, ids: reachable.slice(0, 2000) };
+}
function coverage() {
const all = Object.values(db.byId);
return { profiles: all.length, withUsername: all.filter(p => p.username).length,
@@ -171,5 +180,5 @@ function adminList() { return Object.values(db.byId).map(pub).sort((a, b) => a.i
// local testing only: the server exposes this outside production, never on the live site
function peekCode(id) { const st = codes.get(norm(id)); return st ? st.code : null; }
-module.exports = { init, get, pub, status, complete, isComplete, setUsername, byUsername, suggest, peekCode,
+module.exports = { init, get, pub, status, complete, isComplete, setUsername, byUsername, suggest, peekCode, reachFor,
startEmail, verifyEmail, contactFor, setTelegram, positionsFor, coverage, adminList, ensure, USER_RE, EMAIL_RE };
diff --git a/public/my.html b/public/my.html
index 2fd125f..efa3e51 100644
--- a/public/my.html
+++ b/public/my.html
@@ -31,5 +31,5 @@
-
+