Spec for HTTP/Minimal
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Inital commit

Steve Layton 22c76778

+548
+11
README.md
··· 1 + # HTTP/Minimal 2 + 3 + A constrained version of HTTP designed for serving human-readable documents without tracking, scripting, or behavioral manipulation. 4 + 5 + ## Specification 6 + 7 + See [spec.md](spec.md) for the full specification. 8 + 9 + ## License 10 + 11 + Released under [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) - no rights reserved.
+537
spec.md
··· 1 + # HTTP/Minimal 2 + 3 + **Version:** 0.1.0-draft 4 + **Status:** Proposal 5 + 6 + ## Abstract 7 + 8 + HTTP/Minimal is a constrained version of HTTP designed for serving human-readable documents without tracking, scripting, or behavioral manipulation. It is not a new protocol - it is a voluntary restriction on how HTTP is used, enforceable by clients and verifiable by automated tools. 9 + 10 + ## Goals 11 + 12 + 1. **Radical simplicity.** A document is text and links. Maybe images. 13 + 2. **Privacy by architecture.** No cookies, no auth headers, no state. 14 + 3. **Zero JavaScript.** Not "minimal scripts" - none. 15 + 4. **Works today.** Any static file server can serve compliant content. 16 + 5. **Human-writable source.** Content is authored in Markdown, not markup soup. 17 + 18 + ## Non-Goals 19 + 20 + - Replacing HTTP for applications, APIs, or dynamic content 21 + - Defining a new transport protocol 22 + - Competing with Gemini (this is HTTP; use Gemini if you want Gemini) 23 + 24 + --- 25 + 26 + ## 1. Transport Requirements 27 + 28 + ### 1.1 TLS Required 29 + 30 + All HTTP/Minimal content MUST be served over HTTPS (TLS 1.2+, TLS 1.3 RECOMMENDED). 31 + 32 + Plain HTTP requests SHOULD receive a 301 redirect to the HTTPS equivalent and nothing else. 33 + 34 + ### 1.2 HTTP Version 35 + 36 + HTTP/1.1, HTTP/2, and HTTP/3 are all acceptable. Servers SHOULD support HTTP/2 at minimum. 37 + 38 + --- 39 + 40 + ## 2. Request Constraints 41 + 42 + Compliant clients MUST NOT send the following headers: 43 + 44 + | Header | Reason | 45 + |--------|--------| 46 + | `Cookie` | State tracking | 47 + | `Authorization` | Implies authenticated content | 48 + | `DNT` | Unnecessary - tracking is minimized by design | 49 + | `X-Requested-With` | AJAX patterns not applicable | 50 + | Any `X-` header | Custom headers are a slippery slope | 51 + 52 + Compliant clients MUST use only these methods: 53 + 54 + - `GET` - Retrieve a document 55 + - `HEAD` - Check if a document exists or has changed 56 + 57 + All other methods (`POST`, `PUT`, `DELETE`, etc.) are non-compliant. 58 + 59 + ### 2.1 Query Strings 60 + 61 + Query strings are PERMITTED but SHOULD be limited to: 62 + 63 + - Pagination (`?page=2`) 64 + 65 + Query strings MUST NOT be used for: 66 + 67 + - Session tracking 68 + - User identification 69 + - Analytics parameters (utm_*, fbclid, etc.) 70 + 71 + Compliant servers SHOULD ignore or strip unrecognized query parameters. 72 + 73 + --- 74 + 75 + ## 3. Response Constraints 76 + 77 + ### 3.1 Forbidden Response Headers 78 + 79 + Compliant servers MUST NOT send: 80 + 81 + | Header | Reason | 82 + |--------|--------| 83 + | `Set-Cookie` | State tracking | 84 + | `WWW-Authenticate` | Implies auth-gated content | 85 + | `Content-Security-Policy` | Implies executable content to policy | 86 + | `X-Frame-Options` | Embedding restrictions suggest app behavior | 87 + | `Refresh` | Client-side redirects enable tracking | 88 + 89 + ### 3.2 Permitted Response Headers 90 + 91 + Servers SHOULD send: 92 + 93 + | Header | Purpose | 94 + |--------|---------| 95 + | `Content-Type` | Required (`text/markdown; charset=utf-8`) | 96 + | `Content-Length` | Required for HTTP/1.1 | 97 + | `Last-Modified` | Caching | 98 + | `ETag` | Caching | 99 + | `Cache-Control` | Caching (SHOULD be generous; `max-age=3600` or higher) | 100 + | `Link` | Discovery (see Section 6) | 101 + 102 + ### 3.3 Status Codes 103 + 104 + Compliant servers SHOULD limit responses to: 105 + 106 + | Code | Meaning | 107 + |------|---------| 108 + | `200` | OK | 109 + | `301` | Moved Permanently | 110 + | `304` | Not Modified | 111 + | `400` | Bad Request | 112 + | `404` | Not Found | 113 + | `410` | Gone (content deliberately removed) | 114 + | `500` | Server Error | 115 + 116 + Codes `302`, `303`, and `307` are NOT RECOMMENDED as they enable tracking redirects. 117 + 118 + --- 119 + 120 + ## 4. Content Format 121 + 122 + HTTP/Minimal uses **Markdown** as its content format, served with Content-Type `text/markdown; charset=utf-8`. 123 + 124 + ### 4.1 Markdown Variant 125 + 126 + HTTP/Minimal uses [CommonMark](https://commonmark.org/) as the base specification, with the following extensions PERMITTED: 127 + 128 + - **Tables** - GitHub Flavored Markdown (GFM) pipe tables 129 + - **Strikethrough** - `~~text~~` 130 + - **Autolinks** - GFM automatic URL linking 131 + - **Footnotes** - `[^1]` reference-style footnotes 132 + 133 + ### 4.2 Permitted Syntax 134 + 135 + All standard CommonMark elements: 136 + 137 + - Headings (`#`, `##`, etc.) 138 + - Paragraphs 139 + - Emphasis (`*italic*`, `**bold**`) 140 + - Links (`[text](url)` or `[text][ref]`) 141 + - Images (`![alt](url)`) 142 + - Blockquotes (`>`) 143 + - Code spans (`` `code` ``) 144 + - Code blocks (fenced or indented) 145 + - Lists (ordered and unordered) 146 + - Horizontal rules (`---`) 147 + - Hard line breaks 148 + 149 + ### 4.3 Forbidden Syntax 150 + 151 + The following MUST NOT appear in HTTP/Minimal documents: 152 + 153 + | Syntax | Reason | 154 + |--------|--------| 155 + | Raw HTML blocks | Enables script injection, tracking pixels, forms | 156 + | Raw HTML inline | Same | 157 + | `<script>` | No JavaScript | 158 + | `<iframe>` | Embedded third-party content | 159 + | `<form>` | Data collection | 160 + | `<img>` with tracking URLs | Use Markdown image syntax with compliant URLs | 161 + 162 + Clients MUST strip or ignore any raw HTML encountered in Markdown source. 163 + 164 + ### 4.4 Image Requirements 165 + 166 + Images referenced via `![alt](url)` syntax: 167 + 168 + - MUST include alt text (the `[alt]` portion MUST NOT be empty) 169 + - SHOULD be same-origin or from trusted, non-tracking sources 170 + - MUST NOT be 1x1 tracking pixels 171 + 172 + ### 4.5 Link Requirements 173 + 174 + Links are unrestricted in destination -HTTP/Minimal documents MAY link to any URL. 175 + 176 + Clients MAY warn users when following links to non-compliant origins. 177 + 178 + #### 4.5.1 URL Fragments 179 + 180 + URL fragments (`#section-name`) are supported and SHOULD work as follows: 181 + 182 + - When rendering Markdown to HTML, headings SHOULD receive auto-generated `id` attributes based on their text (lowercase, spaces replaced with hyphens) 183 + - Clients receiving `text/markdown` SHOULD scroll to the heading matching the fragment 184 + - Fragment matching SHOULD be case-insensitive 185 + 186 + For example, `## My Section` would be reachable via `#my-section`. 187 + 188 + ### 4.6 Metadata 189 + 190 + Document metadata SHOULD be provided via a YAML front matter block: 191 + 192 + ```markdown 193 + --- 194 + title: My Document 195 + author: Jane Doe 196 + date: 2025-12-27 197 + lang: en 198 + --- 199 + 200 + # My Document 201 + 202 + Content begins here. 203 + ``` 204 + 205 + Recognized front matter fields: 206 + 207 + | Field | Required | Description | 208 + |-------|----------|-------------| 209 + | `title` | RECOMMENDED | Document title | 210 + | `author` | No | Author name or identifier | 211 + | `date` | No | Publication date (ISO 8601) | 212 + | `lang` | No | Language code (BCP 47) | 213 + | `license` | No | Content license (SPDX identifier or URL) | 214 + 215 + Clients SHOULD use `title` for window/tab titles and `lang` for text rendering. 216 + 217 + --- 218 + 219 + ## 5. Client Rendering 220 + 221 + ### 5.1 Dedicated Clients 222 + 223 + HTTP/Minimal clients SHOULD: 224 + 225 + 1. Parse Markdown and render to styled, readable output 226 + 2. Apply a legible default stylesheet (user-configurable) 227 + 3. Strip any raw HTML before rendering 228 + 4. Display images inline with alt text fallback 229 + 5. Make links clearly navigable 230 + 231 + ### 5.2 Browser Rendering 232 + 233 + Standard browsers receiving `text/markdown` will typically display raw source. Options for browser compatibility: 234 + 235 + **Option A: Server-side rendering** 236 + 237 + Servers MAY content-negotiate and serve pre-rendered HTML to browsers: 238 + 239 + - Request with `Accept: text/markdown` → serve Markdown 240 + - Request with `Accept: text/html` → serve HTML rendering 241 + 242 + The HTML rendering MUST be a direct transformation of the Markdown source with no additions (no scripts, no tracking, no analytics). 243 + 244 + **Option B: Client-side rendering via browser extension** 245 + 246 + Browser extensions may render `text/markdown` responses directly. 247 + 248 + **Option C: Raw display** 249 + 250 + Markdown is human-readable as source. No rendering required. 251 + 252 + ### 5.3 Suggested Default Styles 253 + 254 + Clients SHOULD apply sensible typographic defaults: 255 + 256 + - Readable font (system serif or sans-serif) 257 + - Comfortable line length (45-75 characters) 258 + - Adequate line height (1.4-1.6) 259 + - Responsive viewport handling 260 + - Respect user preferences (dark mode, font size) 261 + 262 + --- 263 + 264 + ## 6. Discovery and Verification 265 + 266 + ### 6.1 Well-Known Endpoint 267 + 268 + Compliant servers SHOULD serve a policy document at: 269 + 270 + ``` 271 + /.well-known/http-minimal 272 + ``` 273 + 274 + This document is a JSON object: 275 + 276 + ```json 277 + { 278 + "http_minimal": "0.1", 279 + "compliant": true, 280 + "scope": "/", 281 + "contact": "mailto:admin@example.com", 282 + "validator": "https://example.com/validation-report.json" 283 + } 284 + ``` 285 + 286 + | Field | Required | Description | 287 + |-------|----------|-------------| 288 + | `http_minimal` | Yes | Spec version | 289 + | `compliant` | Yes | Self-attestation | 290 + | `scope` | No | Path prefix this policy applies to (default: entire origin) | 291 + | `contact` | No | Maintainer contact | 292 + | `validator` | No | URL to a third-party validation report | 293 + 294 + ### 6.2 Link Header 295 + 296 + Responses MAY include: 297 + 298 + ``` 299 + Link: </.well-known/http-minimal>; rel="profile" 300 + ``` 301 + 302 + ### 6.3 Compliance Badge (Optional) 303 + 304 + Documents MAY include a compliance indicator: 305 + 306 + ```markdown 307 + --- 308 + [HTTP/Minimal Compliant](/.well-known/http-minimal) 309 + ``` 310 + 311 + --- 312 + 313 + ## 7. Example Document 314 + 315 + ```markdown 316 + --- 317 + title: Welcome to HTTP/Minimal 318 + author: Jane Doe 319 + date: 2025-12-27 320 + lang: en 321 + --- 322 + 323 + # Welcome to HTTP/Minimal 324 + 325 + This is a document served over **HTTP/Minimal** - a constrained version of 326 + HTTPS for human-readable content without tracking, scripts, or manipulation. 327 + 328 + ## What is this? 329 + 330 + HTTP/Minimal is not a new protocol. It's a voluntary restriction on how 331 + HTTP is used: 332 + 333 + - HTTPS only, no exceptions 334 + - No cookies or authentication headers 335 + - No JavaScript, ever 336 + - Content is Markdown, not HTML 337 + 338 + ## Why Markdown? 339 + 340 + Markdown is: 341 + 342 + 1. Human-readable as source 343 + 2. Human-writable without tooling 344 + 3. Transparent - tracking pixels are visible in source and enforceable by clients 345 + 4. Universally supported 346 + 347 + ## Learn More 348 + 349 + Read the full [specification](/spec) or view the 350 + [source for this page](/source/index.md). 351 + 352 + --- 353 + 354 + *[HTTP/Minimal Compliant](/.well-known/http-minimal)* 355 + ``` 356 + 357 + --- 358 + 359 + ## 8. Relationship to Other Specifications 360 + 361 + ### Gemini Protocol 362 + 363 + HTTP/Minimal shares philosophical goals with Gemini (simplicity, anti-tracking, anti-JavaScript) but differs in approach: 364 + 365 + | Aspect | Gemini | HTTP/Minimal | 366 + |--------|--------|--------------| 367 + | Transport | New protocol (gemini://) | HTTPS | 368 + | Content format | text/gemini | text/markdown | 369 + | Browser support | Requires dedicated client | Works with extensions or server-side rendering | 370 + | Port | 1965 | 443 | 371 + 372 + ### Gemtext vs Markdown 373 + 374 + Gemini's text/gemini format is simpler than Markdown (one link per line, no inline formatting). HTTP/Minimal accepts the tradeoff of a slightly more complex format for broader tooling support. 375 + 376 + ### Semantic Web / Microformats 377 + 378 + HTTP/Minimal Markdown documents can include semantic meaning via: 379 + 380 + - Structured YAML front matter 381 + - Consistent heading hierarchies 382 + - Machine-parseable date/author metadata 383 + 384 + --- 385 + 386 + ## 9. Security Considerations 387 + 388 + - **No cookies** eliminates CSRF and session hijacking vectors 389 + - **No JavaScript** eliminates XSS entirely 390 + - **No forms** eliminates CSRF for data submission 391 + - **No raw HTML** prevents injection attacks 392 + - **HTTPS required** ensures transport security 393 + 394 + Remaining vectors: 395 + 396 + - **Malicious links** - users may still be linked to harmful external sites 397 + - **Image-based tracking** - external images can still leak requests; clients MAY block third-party images 398 + - **Cache timing** - sophisticated attackers may infer browsing history via cache timing; out of scope 399 + 400 + --- 401 + 402 + ## 10. Future Considerations 403 + 404 + Items explicitly deferred for future versions: 405 + 406 + - **Signed content** - integration with Signed HTTP Exchanges or content-addressed storage 407 + - **Content addressing** - integration with IPFS, AT Protocol, or content-hash URLs 408 + - **Client certificates** - Gemini-style TOFU identity without cookies 409 + - **Extended metadata** - richer front matter schemas (JSON-LD, etc.) 410 + - **Media embedding** - whether/how to handle audio and video 411 + 412 + --- 413 + 414 + ## Appendix A: Validator Pseudocode 415 + 416 + ```python 417 + def validate_response(response): 418 + errors = [] 419 + 420 + # Check forbidden response headers 421 + forbidden = ['set-cookie', 'www-authenticate', 'refresh'] 422 + for header in forbidden: 423 + if header in response.headers: 424 + errors.append(f"Forbidden header: {header}") 425 + 426 + # Check content type 427 + content_type = response.headers.get('content-type', '') 428 + if not content_type.startswith('text/markdown'): 429 + errors.append("Content-Type must be text/markdown") 430 + 431 + # Parse Markdown 432 + doc = parse_markdown(response.body) 433 + 434 + # Check for raw HTML 435 + if contains_raw_html(doc): 436 + errors.append("Raw HTML is forbidden") 437 + 438 + # Check images have alt text 439 + for image in doc.images: 440 + if not image.alt: 441 + errors.append(f"Image missing alt text: {image.url}") 442 + 443 + return errors 444 + ``` 445 + 446 + --- 447 + 448 + ## Appendix B: Content-Type Registration 449 + 450 + This specification uses `text/markdown` as defined in [RFC 7763](https://datatracker.ietf.org/doc/html/rfc7763). 451 + 452 + Recommended Content-Type header: 453 + 454 + ``` 455 + Content-Type: text/markdown; charset=utf-8; variant=CommonMark 456 + ``` 457 + 458 + --- 459 + 460 + ## Appendix C: Migration Checklist 461 + 462 + For existing sites adopting HTTP/Minimal: 463 + 464 + - [ ] Enable HTTPS if not already 465 + - [ ] Convert content to Markdown (or add Markdown alongside HTML) 466 + - [ ] Configure server to serve `.md` files as `text/markdown` 467 + - [ ] Remove all analytics (Google Analytics, Plausible, etc.) 468 + - [ ] Remove comment systems or link to external discussion 469 + - [ ] Ensure all images have alt text 470 + - [ ] Ensure no raw HTML in Markdown source 471 + - [ ] Add `/.well-known/http-minimal` endpoint 472 + - [ ] Run validator against all documents 473 + - [ ] Optional: implement content negotiation for HTML clients 474 + 475 + --- 476 + 477 + ## Appendix D: Server Configuration Examples 478 + 479 + ### Nginx 480 + 481 + ```nginx 482 + location ~ \.md$ { 483 + types { text/markdown md; } 484 + charset utf-8; 485 + add_header Link '</.well-known/http-minimal>; rel="profile"'; 486 + 487 + # Remove forbidden headers (shouldn't exist, but defensive) 488 + proxy_hide_header Set-Cookie; 489 + proxy_hide_header WWW-Authenticate; 490 + } 491 + ``` 492 + 493 + ### Caddy 494 + 495 + ```caddyfile 496 + @markdown path *.md 497 + header @markdown Content-Type "text/markdown; charset=utf-8" 498 + header @markdown Link "</.well-known/http-minimal>; rel=\"profile\"" 499 + header @markdown -Set-Cookie 500 + ``` 501 + 502 + ### Static file server (Go) 503 + 504 + ```go 505 + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 506 + if r.Method != "GET" && r.Method != "HEAD" { 507 + http.Error(w, "Method not allowed", 405) 508 + return 509 + } 510 + 511 + if strings.HasSuffix(r.URL.Path, ".md") { 512 + w.Header().Set("Content-Type", "text/markdown; charset=utf-8") 513 + w.Header().Set("Link", "</.well-known/http-minimal>; rel=\"profile\"") 514 + } 515 + 516 + http.FileServer(http.Dir("./public")).ServeHTTP(w, r) 517 + }) 518 + ``` 519 + 520 + --- 521 + 522 + ## Acknowledgments 523 + 524 + This specification draws inspiration from: 525 + 526 + - **[Gemini Protocol](https://geminiprotocol.net/)** - for proving that radical simplicity has an audience 527 + - **["Gemini is Solutionism at its Worst"](https://xn--gckvb8fzb.com/gemini-is-solutionism-at-its-worst/)** - マリウス's critique arguing Gemini's goals could be achieved via HTTP with constraints, not a new protocol 528 + - **[CommonMark](https://commonmark.org/)** - for standardizing Markdown 529 + - **[The Web We Lost](https://www.anildash.com/2012/12/13/the-web-we-lost/)** - Anil Dash's 2012 essay on web degradation 530 + - **[Motherfucking Website](https://motherfuckingwebsite.com/)** - satirical proof that content needs nothing else 531 + - **[IndieWeb](https://indieweb.org/)** - for keeping personal publishing alive 532 + 533 + --- 534 + 535 + ## License 536 + 537 + This specification is released under [CC0 1.0 Universal](https://creativecommons.org/publicdomain/zero/1.0/) - no rights reserved. Use it, fork it, improve it.