dumbtv
dumbtv가 ADB로 Fire TV에서 광고·추적·업데이트 알림을 제거, 루트·앱 변경 없이, 무료 오픈소스
코드는 500개 인증서를 검사하고, Jev는 핵심 티켓만 판단, 정책이 결정하며 모든 입출력·비용을 표시한다
Code checks 500 certificates exactly, Jev reads the ticket and judges only the few that matter, and a fixed policy decides. Every input, output and cent is shown.
보안TypeScript · CSSGitHub @mervin008온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기Certificate ticket triage with Jev: finds the cert, reads the ticket, routes or asks the reporter
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Certificate incident triage that knows which parts need judgment and which need exact code. Built with TypeSafe Jev.
Support tickets about certificates are rarely precise. "We renewed it but it's still broken" could be a stale load balancer node, a missing intermediate, or nothing to do with TLS. CertRadar splits the work the way a PKI team would: code does everything that has an exact answer, Jev reads the human prose and returns calibrated probabilities, and code turns those probabilities into an action through an explicit, inspectable policy.README 전문 보기 ↗Certificate incident triage that knows which parts need judgment and which need exact code. Built with TypeSafe Jev.
Live demo · Write-up · Jev docs
Support tickets about certificates are rarely precise. "We renewed it but it's still broken" could be a stale load balancer node, a missing intermediate, or nothing to do with TLS. CertRadar splits the work the way a PKI team would: code does everything that has an exact answer, Jev reads the human prose and returns calibrated probabilities, and code turns those probabilities into an action through an explicit, inspectable policy.
| Code does (exact) | Jev does (judgment) |
|---|---|
| Expiry maths against a fixed clock | Reads the ticket and picks the likely cause |
| Chain building per client, including AIA fetching and cross-signs | Rates urgency and whether the ticket is too vague to act on |
| SAN and wildcard coverage | Links the ticket to the findings that would explain it |
| CAA checks for failing ACME renewals | |
| Detecting nodes still serving a superseded serial | |
| The routing policy: run a runbook, ask a human, or hand off |
Requires Node.js 22+.
git clone https://github.com/mervin008/certradar.git
cd certradar
npm install
npm run dev # http://localhost:5174
Without an API key the app replays the recorded Jev answers in data/recorded.json. To call Jev live, copy .env.example to .env, set TYPESAFE_API_KEY, restart, and choose Live Jev. Live mode also lets you write your own tickets. The key stays on the server.
New to Node.js, on Windows, or prefer Docker? Follow the step-by-step guide: Running CertRadar locally. It covers installing Node.js, live mode, tests, production builds, Docker, and troubleshooting.
flowchart TD
T["Support ticket<br/>(subject, body, optional CN form)"]
E[("Synthetic estate<br/>500 certificates")]
E --> C["<b>Code</b> · runChecks()<br/>expiry, chains, SANs, CAA, stale serials"]
T --> L["<b>Code</b> · find the certificates<br/>CN from form, else known hostnames"]
T --> J1["<b>Jev request 1</b> · ticket only<br/>cause (Choice) · urgency (Score) · service (Choice)"]
L -- "host matched" --> J2
J1 -- "no host: use service pick" --> J2
C --> J2["<b>Jev request 2</b> · ticket + ≤12 candidate certs<br/>one yes/no (Noul) per finding"]
J1 --> P{"<b>Code</b> · routing policy"}
J2 --> P
P --> A["Suggest a runbook"]
P --> Q["Ask the reporter"]
P --> R["PKI engineer review"]
P --> O["Hand to the app team"]
The estate has 500 synthetic certificates (a seeded generator adds regional storefronts, internal tools, Kafka and Postgres nodes, and hundreds of short-lived mTLS pod certificates around the hand-written scenarios). Jev never sees that inventory.
runChecks() in src/pki.ts finds expired and expiring certificates, nodes serving a superseded serial, missing intermediates, untrusted roots, SAN mismatches, and CAA-blocked renewals. It finds 11 problems in the 500 certificates.Because Jev only ever sees a handful of certificates, the cost per ticket does not grow with the inventory: about $0.0001 whether the estate has 500 certificates or 10 million. Sample tickets are triaged with their evaluation labels stripped; a test guards this.
route() in src/pki.ts checks these rules in order and stops at the first failure:
| Rule | Default threshold | If it fails |
|---|---|---|
| Is it a certificate problem? | Cause not_certificate at ≥ 60% and no finding linked at ≥ 50% | Hand to the owning application team |
| Do we know which certificate it is about? | Host matched, or service pick ≥ 60%, and ≤ 12 candidates | Ask the reporter |
| Is Jev confident about the cause? | Cause confidence ≥ 60% | PKI engineer review |
| Does a finding explain the ticket? | Strongest finding link ≥ 50% | PKI engineer review |
| Do the ticket reading and the evidence agree? | Finding type compatible with the cause | PKI engineer review |
| All pass | Suggest the matching runbook step |
The thresholds live in defaultPolicy and can be moved with sliders in the evaluation panel, which recomputes accuracy and wrong automatic actions instantly.
Each ticket is explained in four numbered steps: finding the certificates (code), Jev reading the ticket, Jev matching the evidence, and the routing policy (code), with every rule shown as passed or failed. When CertRadar asks the reporter, live mode shows the questions as a form; the recorded run links to the follow-up.
POST /v1/systemone and the JSON that came back, as recorded. The API key stays on the server.jev-1.13.0 (published pricing); the table lives in src/pki.ts and an unknown model shows "price not listed" rather than a guess. The two requests run in parallel, and a small timing chart shows the overlap.Recorded with jev-1.13.0 on 19 September 2026 (data/recorded.json), 14 labelled tickets including two follow-ups where the reporter answered CertRadar's questions:
orders-17.orders.svc.internal.test from the reporter, it found the pod still serving a certificate that expired 3 hours earlier, while the renewed one sat undeployed.This is a small, hand-written sample, so treat it as a demo rather than a benchmark.
server/baseline.ts runs the identical pipeline on a normal LLM: same code lookup, same candidate certificates, same two stages, same question wording, same routing policy, with structured JSON output. Only the decision engine differs.
Measured on the 9 tickets that fit the baseline's free-tier quota (npm run baseline -- gemini-3.5-flash-lite, then npx tsx scripts/compare.ts):
Jev (jev-1.13.0) | Ordinary LLM (gemini-3.5-flash-lite) | |
|---|---|---|
| Routed without a human | 7 of 9 | 7 of 9 |
| Wrong automatic actions | 0 | 0 |
| Cause read correctly | 8 of 9 | 8 of 9 |
| Median time per ticket | 596 ms | 1,420 ms |
| Cost per 1,000 tickets | $0.09 | $0.94 |
Accuracy ties, and the two miss different tickets. The difference is in the probabilities: the baseline answered 1.00 to every evidence question, including "would this stale certificate cause a payments timeout?", where Jev answered 0.29. Only the baseline's own low cause confidence stopped that from becoming an action. Thresholds are only meaningful on calibrated numbers.
Caveats: 9 tickets, one run each; the baseline is a straightforward implementation with no prompt tuning; Jev used more tokens (19,981 vs 12,668 input) and is still 10x cheaper because output is free and input is ~18x cheaper. Prices in src/pki.ts come from the providers' published pages.
All settings are environment variables, read from .env if present. Start from .env.example. Never commit .env; it is ignored by Git and by Vercel.
| Variable | Default | Purpose |
|---|---|---|
TYPESAFE_API_KEY | (empty) | Enables live Jev. Without it the app runs in recorded mode only. |
TYPESAFE_MODEL | jev-latest | Model alias or pinned version, for example jev-1.13.0. |
PORT | 5174 | Server port. |
HOST | 127.0.0.1 | Bind address. Set 0.0.0.0 to expose the server beyond localhost. |
GEMINI_API_KEY | (empty) | Only for npm run baseline, the ordinary-LLM comparison. |
npm run dev # dev server with hot reload, http://localhost:5174
npm test # PKI checks, routing policy, API boundary (mocked TypeSafe transport)
npm run build # strict type check + production build into dist/
npm start # serve the build and API
npm run record # re-run all sample tickets against live Jev and update data/recorded.json
npm run baseline -- gemini-3.5-flash-lite [--only T-101,T-102] # same pipeline on an LLM, needs GEMINI_API_KEY
npx tsx scripts/compare.ts # Jev vs baseline table from the two data files
The Node server exposes two endpoints. Both reject cross-origin requests and are never cached.
| Endpoint | Description |
|---|---|
GET /api/config | { "live": boolean, "model": string }: whether live Jev is configured, and which model. |
POST /api/triage | Triages one ticket against live Jev. Returns 503 when no API key is set. |
{
"ticket": {
"subject": "Android app can't connect since this morning",
"body": "Users on Android get a certificate error, iOS is fine.",
"reporter": "Mobile team",
"details": { "cn": "api.acme-retail.test", "client": "Android 7", "since": "08:00" }
}
}
subject (≤ 160 chars) and body (≤ 2,000 chars) are required; reporter and the details fields (cn, error, client, since) are optional. The server copies only these fields before anything reaches the model, caps request bodies at 8 KB, and allows 30 triages per minute with at most 3 in flight. It is a demo server, not a multi-tenant service.
src/
pki.ts synthetic estate, runChecks(), certificate lookup, route() policy, grading, prices
App.tsx the UI: tickets, four-step explanation, evaluation panel
server/
triage.ts the two Jev requests (symptoms, evidence) and answer validation
baseline.ts the same pipeline on an ordinary LLM, for comparison
app.ts Express API: /api/config, /api/triage, origin check, rate limit
index.ts dev (Vite middleware) and production server entry
scripts/ record.ts, baseline.ts, compare.ts (re-record and compare runs)
data/
recorded.json recorded Jev run that the demo replays
baseline.json recorded ordinary-LLM run
tests/ vitest: PKI checks and policy, API boundary
The hosted demo is a static Vite build on Vercel (vercel.json): it serves the recorded run only, and live mode never appears there. .vercelignore keeps .env files, node_modules, dist, and drafts out of the upload. To offer live triage, run the Node server (npm run build && npm start) somewhere the API key can stay server-side.