fix(frontend): CLI curl-command copy bug, stale/missing content, and Fido attribution cleanup
- CliHandoff: the visible curl install command was a hardcoded truncated
placeholder ("...install.sh"), so the copy button worked but manually
selecting/copying the text gave a broken command. Now shows the real URL
and lets CSS `truncate` handle the visual clipping.
- Dock: adds a full-width backdrop-blur shelf under the floating desktop
dock so it doesn't visually blend into scrolled content (page bg is
near-black, so plain color gradients were invisible -- blur is what
actually reads). Desktop only; the mobile dock is already a flush bar.
- HomePage: hero now mentions "Open source" (linked, dotted underline) --
previously absent anywhere on the landing page.
- StatsBar: "releases available" count now includes eval/enterprise
editions, not just the consumer catalog (17 -> combined total).
- About/Privacy/Disclaimer: these hadn't been updated since the CLI
shipped. Privacy Policy now discloses the CLI's anonymous telemetry and
crowdsourced link-contribution behavior (previously undisclosed). About
page's stale hardcoded product list replaced with a link to the catalog,
plus a new section explaining the CLI. Disclaimer now covers the CLI
binary under the same terms.
- Fido/Rufus attribution was scattered with duplicate linked mentions on
the same pages; consolidated to one canonical linked credit per surface
(About's Credits section, README's intro) instead of repeating it.
- FAQAccordion: fixed a factual error ("ported to Go and Node.js" -- no
Node.js backend exists), and linked the actual repo in the open-source
FAQ answer (previously just asserted it with no link).
- sitemap.xml: removed a dead entry for product 48, which was already
removed from the catalog (Microsoft returns 502 for it).
- README: fixed three inaccuracies in the /contribute API doc (wrong auth
header, wrong body field name, wrong status codes) against the actual
backend/main.go implementation, and added the missing telemetry/sentinel
fields to the /metrics example response.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b516804541
commit
73eee730c9
10 changed files with 109 additions and 37 deletions
23
README.md
23
README.md
|
|
@ -134,8 +134,6 @@ Browser → Backend → (CF Worker) → Microsoft API → Signed CDN URL
|
|||
5. Cache result → return to browser
|
||||
```
|
||||
|
||||
The flow mirrors [Fido.ps1](https://github.com/pbatard/Fido) by Pete Batard — the same script bundled with Rufus.
|
||||
|
||||
Outbound requests to Microsoft are optionally routed through a Cloudflare Worker (`cloudflare-worker/worker.js`). This distributes requests across Cloudflare's global edge IPs instead of a single server IP, preventing Microsoft's rate-limit block (error 715-123130) under high traffic. The Worker is opt-in via environment variables — omit them to go direct to Microsoft.
|
||||
|
||||
### Caching layer
|
||||
|
|
@ -249,17 +247,17 @@ Valid slugs: `server-2025`, `server-2022`, `server-2019`, `server-2016`, `win11-
|
|||
|
||||
### `POST /contribute`
|
||||
|
||||
Accepts a crowdsourced link from the CLI tool to warm the cache. Requires `Authorization: Bearer <CONTRIBUTE_SECRET>` header.
|
||||
Accepts a crowdsourced link from the CLI tool to warm the cache. Requires an `X-Contribute-Secret: <CONTRIBUTE_SECRET>` header.
|
||||
|
||||
```json
|
||||
{
|
||||
"product_id": "3262",
|
||||
"sku_id": "0x0409",
|
||||
"response": { /* raw Microsoft JSON */ }
|
||||
"raw_json": { /* raw Microsoft JSON */ }
|
||||
}
|
||||
```
|
||||
|
||||
Returns `200 OK` on acceptance, `400` on validation failure (expired link, unknown product), `429` on rate limit (~5 req/min per IP).
|
||||
Returns `204 No Content` on acceptance; `422` on validation failure (unknown product, invalid SKU, expiry under 1 hour, disallowed download host); `400` on a malformed request body; `401` if the secret header doesn't match; `429` on rate limit (~5 req/min per IP).
|
||||
|
||||
### `GET /metrics?secret=<secret>`
|
||||
|
||||
|
|
@ -271,10 +269,22 @@ Returns real-time cache statistics for the running instance. Auth via `?secret=`
|
|||
"link": { "requests": 38, "cache_hits": 35, "ms_fetches": 3, "neg_hits": 0, "stale": 0, "hit_rate": "92.1%", "cache_size": 6 },
|
||||
"eval": { "requests": 12, "cache_hits": 12, "stale": 0, "hit_rate": "100.0%", "cache_size": 5 },
|
||||
"neg_cache_size": 0,
|
||||
"total_ms_fetches": 6
|
||||
"total_ms_fetches": 6,
|
||||
"sentinel_errors": 0,
|
||||
"sentinel_distinct_sources_est": 0,
|
||||
"telemetry": {
|
||||
"actions": { "fetch": 364, "eval": 40, "interactive": 14 },
|
||||
"platforms": { "windows": 176, "darwin": 70, "linux": 132 },
|
||||
"products": { "3262": 109, "2618": 95 },
|
||||
"results": { "success": 197, "failed": 221 },
|
||||
"versions": { "0.3.6": 41 },
|
||||
"errors": { "fetching download links: Sentinel marked this request as rejected.": 90 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`sentinel_errors` / `sentinel_distinct_sources_est` track how often Microsoft's Sentinel WAF has blocked the backend's own outbound Microsoft calls. `telemetry` aggregates anonymous CLI usage events (see [Usage telemetry](#usage-telemetry) below) — omitted entirely if no CLI events have been recorded yet.
|
||||
|
||||
---
|
||||
|
||||
## Supported Products
|
||||
|
|
@ -292,7 +302,6 @@ Returns real-time cache statistics for the running instance. Auth via `?secret=`
|
|||
| Windows 10 22H2 | 2618 | x64 / x86 |
|
||||
| Windows 10 22H2 Home China | 2378 | x64 |
|
||||
| Windows 8.1 | 52 | x64 / x86 |
|
||||
| Windows 8.1 Single Language | 48 | x64 / x86 |
|
||||
|
||||
### Evaluation editions (Server & Enterprise)
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,6 @@
|
|||
<url><loc>https://msdl.tech-latest.com/product/win11-ent</loc><lastmod>2026-05-18</lastmod><priority>0.8</priority><changefreq>monthly</changefreq></url>
|
||||
|
||||
<!-- Product Pages -->
|
||||
<url><loc>https://msdl.tech-latest.com/product/48</loc><lastmod>2026-05-12</lastmod><priority>0.8</priority><changefreq>monthly</changefreq></url>
|
||||
<url><loc>https://msdl.tech-latest.com/product/52</loc><lastmod>2026-05-12</lastmod><priority>0.8</priority><changefreq>monthly</changefreq></url>
|
||||
<url><loc>https://msdl.tech-latest.com/product/2378</loc><lastmod>2026-05-12</lastmod><priority>0.8</priority><changefreq>monthly</changefreq></url>
|
||||
<url><loc>https://msdl.tech-latest.com/product/2618</loc><lastmod>2026-05-12</lastmod><priority>0.8</priority><changefreq>monthly</changefreq></url>
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ function InstallSteps() {
|
|||
</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-between gap-2 rounded-lg bg-white/4 border border-white/7 px-3 py-2">
|
||||
<code className="text-[11px] font-mono text-zinc-400 truncate">curl -fsSL .../install.sh | bash</code>
|
||||
<code className="text-[11px] font-mono text-zinc-400 truncate">curl -fsSL https://api.msdl.tech-latest.com/install.sh | bash</code>
|
||||
<button onClick={handleCurlCopy} className="flex-shrink-0 text-zinc-500 hover:text-white transition-colors">
|
||||
{curlCopied ? <Check size={12} className="text-green-400" /> : <Copy size={12} />}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -45,6 +45,11 @@ export default function Dock() {
|
|||
|
||||
return (
|
||||
<>
|
||||
{/* Full-width shelf so the floating desktop dock separates from scrolled content — page bg is
|
||||
near-black (zinc-950), so plain color gradients are invisible; backdrop-blur is what reads.
|
||||
Desktop only: the mobile dock is already a flush full-width bar with no gap to bridge. */}
|
||||
<div className="hidden sm:block fixed inset-x-0 bottom-0 h-24 backdrop-blur-md bg-gradient-to-t from-zinc-950/90 via-zinc-950/60 to-transparent pointer-events-none z-40" />
|
||||
|
||||
{/* ── DESKTOP DOCK (sm+) — centered floating pill ── */}
|
||||
<div className="hidden sm:flex fixed bottom-5 left-0 right-0 justify-center z-50 pointer-events-none">
|
||||
<motion.div
|
||||
|
|
|
|||
|
|
@ -1,12 +1,23 @@
|
|||
import { useState } from 'react'
|
||||
import { useState, type ReactNode } from 'react'
|
||||
import { motion, AnimatePresence } from 'motion/react'
|
||||
import { ChevronRight } from 'lucide-react'
|
||||
|
||||
interface FaqItem {
|
||||
q: string
|
||||
a: string
|
||||
a: ReactNode
|
||||
}
|
||||
|
||||
const repoLink = (
|
||||
<a
|
||||
href="https://github.com/starkSV/windows-iso-downloader"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-400 hover:text-blue-300 transition-colors"
|
||||
>
|
||||
GitHub
|
||||
</a>
|
||||
)
|
||||
|
||||
const faqs: FaqItem[] = [
|
||||
{
|
||||
q: 'Is this legal?',
|
||||
|
|
@ -34,7 +45,13 @@ const faqs: FaqItem[] = [
|
|||
},
|
||||
{
|
||||
q: 'Is MSDL open source?',
|
||||
a: 'Yes. Both the frontend and the backend proxy are fully open source. The backend implements the same session-based flow as the Fido PowerShell script, ported to Go and Node.js. You can self-host the entire stack.',
|
||||
a: (
|
||||
<>
|
||||
Yes. Both the frontend and the backend proxy are fully open source, on {repoLink}. The
|
||||
backend and the standalone CLI both implement the same session-based flow as the Fido
|
||||
PowerShell script, ported to Go. You can self-host the entire stack.
|
||||
</>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { motion } from 'motion/react'
|
||||
import { useState, useEffect } from 'react'
|
||||
import { evalProducts } from '../data/evalProducts'
|
||||
|
||||
interface Stat {
|
||||
value: string
|
||||
|
|
@ -7,14 +8,14 @@ interface Stat {
|
|||
}
|
||||
|
||||
export default function StatsBar() {
|
||||
const [totalReleases, setTotalReleases] = useState('17')
|
||||
const [totalReleases, setTotalReleases] = useState((17 + evalProducts.length).toString())
|
||||
|
||||
useEffect(() => {
|
||||
fetch('/data/products.json')
|
||||
.then(r => r.json())
|
||||
.then((data: Record<string, { active?: boolean }>) => {
|
||||
const activeCount = Object.values(data).filter(p => p.active !== false).length
|
||||
setTotalReleases(activeCount.toString())
|
||||
setTotalReleases((activeCount + evalProducts.length).toString())
|
||||
})
|
||||
.catch(() => {})
|
||||
}, [])
|
||||
|
|
|
|||
|
|
@ -49,16 +49,8 @@ export default function AboutPage() {
|
|||
<Section title="How it works">
|
||||
<p>
|
||||
Our backend replicates the session-based authentication flow that Microsoft uses to
|
||||
serve download links to end users. The same approach is used by{' '}
|
||||
<a
|
||||
href="https://github.com/pbatard/Fido"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-blue-400 hover:text-blue-300 transition-colors"
|
||||
>
|
||||
Fido
|
||||
</a>{' '}
|
||||
(the PowerShell script bundled with Rufus). The flow is:
|
||||
serve download links to end users — the same technique used by Rufus (credited below).
|
||||
The flow is:
|
||||
</p>
|
||||
<ol className="list-decimal list-inside space-y-1 text-zinc-500 text-sm">
|
||||
<li>Register a session with Microsoft's tracking endpoint</li>
|
||||
|
|
@ -87,9 +79,22 @@ export default function AboutPage() {
|
|||
</code>
|
||||
</p>
|
||||
<p>
|
||||
Product IDs are maintained manually based on Microsoft's release cadence.
|
||||
Windows 11 25H2, 24H2, Windows 10 22H2, and Windows 8.1 are currently listed.
|
||||
New releases are added as Microsoft publishes them.
|
||||
Product IDs are maintained manually based on Microsoft's release cadence, covering
|
||||
consumer Windows (11, 10, 8.1) as well as Windows Server (2016–2025) and Windows 11
|
||||
Enterprise evaluation editions. New releases are added as Microsoft publishes them —
|
||||
see the <a href="/products" className="text-blue-400 hover:text-blue-300 transition-colors">full catalog</a>.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
<Section title="CLI tool">
|
||||
<p>
|
||||
MSDL also ships as a standalone command-line tool,{' '}
|
||||
<code className="text-[11px] font-mono bg-white/5 border border-white/7 px-1.5 py-0.5 rounded text-zinc-400">msdl</code>.
|
||||
It runs the same Microsoft session flow directly from your own machine instead of through
|
||||
our backend — useful when Microsoft is rate-limiting our server, since a request from
|
||||
your own connection isn't affected by that. See the{' '}
|
||||
<a href="/cli" className="text-blue-400 hover:text-blue-300 transition-colors">CLI page</a> for
|
||||
install instructions.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ export default function DisclaimerPage() {
|
|||
>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-white mb-1">Disclaimer</h1>
|
||||
<p className="text-xs font-mono text-zinc-600">Last updated: May 18, 2026</p>
|
||||
<p className="text-xs font-mono text-zinc-600">Last updated: July 16, 2026</p>
|
||||
</div>
|
||||
|
||||
<div className="p-4 rounded-xl border border-amber-500/15 bg-amber-500/6 text-amber-400/80 text-[12px] leading-relaxed">
|
||||
|
|
@ -43,7 +43,9 @@ export default function DisclaimerPage() {
|
|||
<p>
|
||||
MSDL is an independent, open-source project. It is not produced, approved, or supported
|
||||
by Microsoft Corporation. The name "Windows" and the Windows logo are registered
|
||||
trademarks of Microsoft Corporation.
|
||||
trademarks of Microsoft Corporation. This applies equally to the website and the{' '}
|
||||
<code className="text-zinc-400 text-[11px] font-mono bg-white/5 px-1 py-0.5 rounded">msdl</code>{' '}
|
||||
command-line tool.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
|
|
@ -76,8 +78,9 @@ export default function DisclaimerPage() {
|
|||
<Section title="Open source">
|
||||
<p>
|
||||
The source code is publicly available. You are free to inspect, fork, and self-host
|
||||
this project under the terms of its open-source license. The project credits the
|
||||
open-source Fido script by Pete Batard for the underlying session flow.
|
||||
this project under the terms of its open-source license. See the{' '}
|
||||
<a href="/about" className="text-blue-400 hover:text-blue-300 transition-colors">About page</a>{' '}
|
||||
for credits.
|
||||
</p>
|
||||
</Section>
|
||||
</motion.div>
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ export default function HomePage() {
|
|||
<p className="text-zinc-400 text-base max-w-sm mx-auto mb-6 leading-relaxed">
|
||||
Direct links from Microsoft's CDN. No ads. No registration.
|
||||
</p>
|
||||
<div className="flex items-center justify-center gap-4 text-[12px] text-zinc-500">
|
||||
<div className="flex items-center justify-center flex-wrap gap-x-4 gap-y-1.5 text-[12px] text-zinc-500">
|
||||
<span className="flex items-center gap-1.5">
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-green-500 inline-block" />
|
||||
Always official
|
||||
|
|
@ -136,6 +136,16 @@ export default function HomePage() {
|
|||
<span className="w-1.5 h-1.5 rounded-full bg-zinc-600 inline-block" />
|
||||
Free forever
|
||||
</span>
|
||||
<span className="text-zinc-700">·</span>
|
||||
<a
|
||||
href="https://github.com/starkSV/windows-iso-downloader"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center gap-1.5 hover:text-zinc-300 transition-colors"
|
||||
>
|
||||
<span className="w-1.5 h-1.5 rounded-full bg-purple-500 inline-block" />
|
||||
<span className="underline decoration-dotted decoration-zinc-600 underline-offset-4">Open source</span>
|
||||
</a>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
|
|
|
|||
|
|
@ -31,14 +31,37 @@ export default function PrivacyPolicyPage() {
|
|||
>
|
||||
<div>
|
||||
<h1 className="text-2xl font-bold text-white mb-1">Privacy Policy</h1>
|
||||
<p className="text-xs font-mono text-zinc-600">Last updated: May 18, 2026</p>
|
||||
<p className="text-xs font-mono text-zinc-600">Last updated: July 16, 2026</p>
|
||||
</div>
|
||||
|
||||
<Section title="No data collected">
|
||||
<Section title="No data collected on the website">
|
||||
<p>
|
||||
MSDL does not collect, store, log, or share any personally identifiable information.
|
||||
There are no user accounts, no cookies, no analytics trackers, and no third-party
|
||||
advertising scripts of any kind.
|
||||
The MSDL website does not collect, store, log, or share any personally identifiable
|
||||
information. There are no user accounts, no cookies, no analytics trackers, and no
|
||||
third-party advertising scripts of any kind.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
<Section title="CLI tool: anonymous telemetry and link sharing">
|
||||
<p>
|
||||
The <code className="text-zinc-400 text-[11px] font-mono bg-white/5 px-1 py-0.5 rounded">msdl</code>{' '}
|
||||
CLI is a separate, optional download and sends two kinds of anonymous data by default,
|
||||
both of which you can disable:
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-zinc-400">Usage telemetry</strong> — action type (fetch, eval, list,
|
||||
interactive), platform (Windows/macOS/Linux), CLI version, and whether the run succeeded
|
||||
or failed. No personal data, IP address, or product-key information is included. Disable
|
||||
with <code className="text-zinc-400 text-[11px] font-mono bg-white/5 px-1 py-0.5 rounded">--no-telemetry</code>{' '}
|
||||
or the <code className="text-zinc-400 text-[11px] font-mono bg-white/5 px-1 py-0.5 rounded">MSDL_NO_TELEMETRY=1</code> environment variable.
|
||||
</p>
|
||||
<p>
|
||||
<strong className="text-zinc-400">Link contribution</strong> — after a successful fetch, the
|
||||
CLI can share the product ID, SKU ID, and Microsoft's raw signed-link response back to our
|
||||
backend, so the next website visitor gets a cached hit instead of a fresh Microsoft request.
|
||||
Only that Microsoft response is shared — nothing about you or your machine. Disable with{' '}
|
||||
<code className="text-zinc-400 text-[11px] font-mono bg-white/5 px-1 py-0.5 rounded">--no-contribute</code>{' '}
|
||||
or <code className="text-zinc-400 text-[11px] font-mono bg-white/5 px-1 py-0.5 rounded">MSDL_NO_CONTRIBUTE=1</code>.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue