@mneme-ai/xray 2.175.0 → 2.176.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/public/index.html +26 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mneme-ai/xray",
3
- "version": "2.175.0",
3
+ "version": "2.176.0",
4
4
  "description": "Mneme Repo X-Ray — a signed, raw-free, deterministic X-Ray of any repo. Every number is reproducible from git/AST/metadata and sealed with an offline-verifiable NOTARY receipt. No source code ever leaves the machine; no LLM guesses anything.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/public/index.html CHANGED
@@ -206,23 +206,25 @@
206
206
  .lscard .pill{display:inline-block;font-size:11px;background:var(--soft);border:1px solid var(--line);border-radius:20px;padding:1px 8px;color:var(--ink2)}
207
207
  .lscard .lsnote{margin-top:10px;font-size:11.5px;color:var(--sub);line-height:1.5;border-top:1px solid var(--line2);padding-top:9px}
208
208
  /* SHOWCASE — selling points; the graphic sits to the SIDE (grid areas, no markup move) */
209
- .showcase{max-width:1060px;margin:64px auto 0;padding:0 20px;text-align:left;
210
- display:grid;column-gap:36px;row-gap:10px;align-items:start;align-content:start;
211
- grid-template-columns:1fr 380px;grid-template-areas:"title art" "sub art" "cards cards"}
212
- .showcase .sctitle{grid-area:title;font-size:30px;font-weight:700;letter-spacing:-.02em;color:var(--ink);margin:0;line-height:1.2}
209
+ .showcase{max-width:1080px;margin:60px auto 0;padding:0 20px;
210
+ display:grid;column-gap:32px;row-gap:8px;align-items:center;
211
+ grid-template-columns:1fr 300px;grid-template-areas:"title title" "sub sub" "cards art"}
212
+ .showcase .sctitle{grid-area:title;text-align:center;font-size:29px;font-weight:700;letter-spacing:-.02em;color:var(--ink);margin:0;line-height:1.25}
213
213
  .showcase .sctitle .hl{color:var(--a)}
214
- .showcase .scsub{grid-area:sub;font-size:15px;color:var(--sub);margin:0;line-height:1.6}
215
- .showcase .bigart{grid-area:art;display:flex;justify-content:center;align-self:center;opacity:.95}
216
- .showcase .sc3{grid-area:cards;display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:14px}
217
- .showcase .sccard{background:var(--soft);border:1px solid var(--line);border-radius:16px;padding:20px}
218
- .showcase .scico{font-size:26px;margin-bottom:8px}
219
- .showcase .sccard b{display:block;font-size:15px;color:var(--ink);margin-bottom:6px}
220
- .showcase .sccard span{font-size:13px;color:var(--sub);line-height:1.55}
221
- @media(max-width:820px){
222
- .showcase{grid-template-columns:1fr;grid-template-areas:"title" "sub" "art" "cards"}
223
- .showcase .sc3{grid-template-columns:1fr}
224
- .showcase .bigart svg{width:300px;height:auto}
214
+ .showcase .scsub{grid-area:sub;text-align:center;font-size:15px;color:var(--sub);max-width:680px;margin:6px auto 22px;line-height:1.6}
215
+ .showcase .bigart{grid-area:art;display:flex;justify-content:center;align-self:center;opacity:.92}
216
+ .showcase .bigart svg{width:100%;height:auto;max-width:300px}
217
+ .showcase .sc3{grid-area:cards;display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
218
+ .showcase .sccard{background:var(--soft);border:1px solid var(--line);border-radius:16px;padding:18px}
219
+ .showcase .scico{font-size:24px;margin-bottom:8px}
220
+ .showcase .sccard b{display:block;font-size:14.5px;color:var(--ink);margin-bottom:6px}
221
+ .showcase .sccard span{font-size:12.5px;color:var(--sub);line-height:1.5}
222
+ @media(max-width:880px){
223
+ .showcase{grid-template-columns:1fr;grid-template-areas:"title" "sub" "cards" "art"}
224
+ .showcase .sc3{grid-template-columns:1fr 1fr}
225
+ .showcase .bigart{margin-top:18px}
225
226
  }
227
+ @media(max-width:560px){ .showcase .sc3{grid-template-columns:1fr} }
226
228
  .picker{display:none;margin-top:12px;border:1px solid var(--line);border-radius:10px;background:#fff;overflow:hidden}
227
229
  .picker.on{display:block}
228
230
  .pkbar{display:flex;align-items:center;gap:8px;padding:10px 12px;border-bottom:1px solid var(--line2);font-size:12.5px}
@@ -667,6 +669,14 @@ function renderLocalScan(r){
667
669
  const sec=s.secrets, secCls=sec.totalFindings>0?"bad":"ok";
668
670
  const langs=s.langs.map(([e,n])=>`<span class="pill">${esc(e)} ${n}</span>`).join(" ");
669
671
  const g=s.git, vit = !g.has ? "" : (s.dormantDays>365?"dormant":s.dormantDays>120?"slowing":"active");
672
+ // VERDICT — turn the local numbers into a decision + what-to-do (same idea as the URL report)
673
+ const lt=[]; let ltone="ok", lhead="✅ Quick scan looks clean — see details below";
674
+ if(sec.totalFindings>0){ ltone="bad"; lhead="⚠️ Secret(s) in this folder — fix before sharing"; lt.push(`🔴 ${sec.totalFindings} credential${sec.totalFindings>1?"s":""} in production code — rotate + add a pre-commit secret scan.`); }
675
+ if(g.has && g.authors<=1){ if(ltone==="ok"){ltone="warn"; lhead="✅ Scanned — ⚠️ solo-owned (key-person risk)";} lt.push(`🟠 Bus factor 1 — one author made all ${g.commits} commits. If they leave, this stalls; add reviewers + docs.`); }
676
+ if(g.has && s.dormantDays>365){ if(ltone==="ok"){ltone="warn"; lhead="🪦 Looks unmaintained — last commit over a year ago";} lt.push(`🟠 No activity for ${s.dormantDays} days — may be stale; confirm it is still maintained.`); }
677
+ if(sec.totalFindings===0 && (!g.has || (g.authors>1 && s.dormantDays<=365))) lt.push(`✅ No leaked secrets${g.has?`, actively worked (${g.commits} commits, ${g.authors} authors)`:""} — clean for a quick local check.`);
678
+ if(s.deps.total>0) lt.push(`ℹ️ ${s.deps.total} dependencies declared — run the full report (public URL / bridge) to check which are dying or risky-licensed.`);
679
+ const lverdict = `<div class="verdict v-${ltone}" style="margin:0 -16px 12px;border-radius:0;border-bottom:1px solid #eef0f2"><div class="vhead" style="font-size:15px">${esc(lhead)}</div><ul class="vlist" style="margin-top:8px">${lt.slice(0,4).map(t=>`<li>${t}</li>`).join("")}</ul></div>`;
670
680
  const gitRows = g.has ? `
671
681
  <div class="lsrow"><span class="lsk">Bus factor</span><span class="lsv ${g.authors===1?"bad":""}"><b>${g.authors}</b> author${g.authors===1?" — single point of failure":"s"} · top author ${Math.round(g.topShare*100)}% of ${g.commits} commits</span></div>
672
682
  <div class="lsrow"><span class="lsk">Vitality</span><span class="lsv ${vit==="dormant"?"bad":""}"><b>${vit}</b> · ${s.ageDays}d span · last activity ${s.dormantDays}d ago</span></div>`
@@ -674,6 +684,7 @@ function renderLocalScan(r){
674
684
  out.innerHTML=`<div class="lscard">
675
685
  <div class="lstop"><div class="lsgrade g-${("ABCDEF".includes(s.grade)?s.grade:"C")}">${esc(s.grade)}</div>
676
686
  <div><div class="lsh"><b>📂 ${esc(r.folder)}</b></div><div class="muted" style="font-size:12px">scanned in your browser · ${r.files} files · nothing uploaded</div></div></div>
687
+ ${lverdict}
677
688
  <div class="lsrow"><span class="lsk">Secrets</span><span class="lsv ${secCls}"><b>${sec.totalFindings}</b> in production code${sec.excludedTestHits?` · ${sec.excludedTestHits} in tests (excluded)`:""}</span></div>
678
689
  ${sec.hits.length?`<div class="lshits">${sec.hits.slice(0,6).map(h=>`<div>🔴 ${esc(h.kind)} — ${esc(h.file)}:${h.line}</div>`).join("")}</div>`:`<div class="lsok">✓ no leaked credentials in production code</div>`}
679
690
  ${gitRows}