v0.6.0
Highlights
-
/github/:userand/github/:user/:repo— banner cards for any public GitHub user, organization, or repository. Profile cards render display name, bio,★ followers · ⌥ repos · following · gists, company affiliation, blog homepage URL (scheme stripped), Twitter handle asx.com/<handle>, location · joined-since collapsed onto one row, and anOrganizationbadge for org accounts. Repo cards use the repo NAME alone as headline (owner is implied by the URL — keeps banner width comparable to the user card), full description,★ stars ⎇ forks ⚠ open-issues,language · license · default-branch, andpushed <relative> · release <tag>collapsed onto a single row.GITHUB_TOKENenv var is optional — when set, raises the per-process upstream cap from 60 to 5000 req/hr; token is env-only and redacted from any debug log. Per-IP rate limit (30/min/IP) on the route group;Vary: User-Agenton every response. Private repos return 404 even if the configured token has access — the route never exposes private repo data. -
/dns/:hostname— banner card with all canonical DNS record types in a single lookup: A, AAAA, CNAME, MX, NS, TXT (prefix-classified intospf · dmarc · N verifications), SOA, CAA, SRV, plus aDNSSEC ✓badge when the zone is signed. Hostname-as-banner with labeled tabular caption rows left-aligned viaBannerBoxes, so labels and values align cleanly across rows. RFC 8552 underscored attribute labels supported (_dmarc.example.com,_acme-challenge.foo.com,_sip._tcp.example.com) — these are the route's headline use cases for email-auth and ACME debugging. DoT-by-default to1.1.1.1:853,1.0.0.1:853(cloudflare-dns.com SNI) so viewer queries don't leak in plaintext on the wire;DNS_RESOLVERaccepts a comma-separated fallback list andDNS_RESOLVER_SNIoverrides the TLS hostname for self-signed internal resolvers. -
Hardened operational posture for the new routes — TTL-honoring cache (
clamp(min upstream TTL, [60s, 600s])for/dns, three-state for both routes covering success / transient-fail / NXDOMAIN). Stale-on-transient serves cached records with a( stale data )caption rather than a generic 502. Process-global rate gate (100 q/s sustain / 200 burst viagolang.org/x/time/rate) on/dns/*caps egress to upstream even under botnet-driven 30/min/IP × N IPs fan-out. Self-throttle returns 503 + max-age=60 (semantically distinct from per-IP rate limit's 200 + max-age=60).robots.txtextended toDisallow: /github/andDisallow: /dns/.
Other changes
- Hostname validation on
/dns/*enforces RFC 1035 LDH plus RFC 8552 leading underscore, max 253 chars, IDNA + lowercase + trim-trailing-dot canonicalization. Refused suffixes (.local,.localhost,.internal,.lan,.example,.test,.invalid,.arpa) return 400 before any wire query is issued. IP-literal-as-hostname rejection runs after canonicalize so trailing-dot variants don't evade. - Private-IP filter on
/dns/*strips A/AAAA literals matching RFC1918 / loopback / link-local / unspecified / multicast. AAAA values areUnmap'd so IPv4-mapped IPv6 (::ffff:10.0.0.1) doesn't leak private addresses through the v6 form. CNAME, NS, MX, SRV, and TXT values pass through unchanged — the gap is documented honestly indocs/security.md. - Per-RR TXT classification on
/dns/*: eachdns.TXT.Txtis one RR's chunks; concatenate the chunks within a single RR, classify the joined-per-RR string against the prefix table (v=spf1,v=DMARC1,v=DKIM1,google-site-verification=,apple-domain-verification=,MS=,facebook-domain-verification=,stripe-verification=,_atproto), accumulate flags and counts across RRs. Vary: User-Agentinvariant tightened —/qr,/github/*, and/dns/*all emit it on every response (200/400/404/415/502/503). The latent CDN cache-poisoning bug at/and/stock(no Vary header on UA-class-variant or locale-variant bodies) remains pre-existing follow-up.- Forbidden-banner-glyph sanitizer on
/github/*substitutes:→;,%→pct,,→,▲▼→. Leading_on/dns/*headlines is substituted to a space because pylon parses leading underscore as a directive (same class of issue as leading@). - Per-route Cache-Control:
/github/:user200=600s,/github/:user/:repo200=120s,/dns/*200=300s, all routes 404=3600s, rate-limited=60s, 502/400=no-store. - New deps, all permissive:
github.com/miekg/dns(BSD-3),github.com/foxcpp/go-mockdns(MIT, test only),golang.org/x/net/idna(BSD-3),golang.org/x/time/rate(Apache-2.0).
Container image
ghcr.io/cmj0121/imagelet:0.6.0