{
    "ready": true,
    "site": {
        "id": 0,
        "domain": "hur.st",
        "display_name": "hur.st's bl.aagh",
        "primary_country_code": "",
        "category_name": "Personal: Portfolios & CVs"
    },
    "metrics": {
        "global_rank": 19828,
        "country_rank": 10427,
        "category_rank": 25,
        "daily_pageviews_per_visitor": 3.91,
        "daily_time_on_site_seconds": 327,
        "bounce_rate": 31.64,
        "search_visits_percent": 40.67,
        "total_sites_linking_in": 1,
        "monthly_unique_visitors": 131,
        "recorded_at": "2026-03-20 20:18:57"
    },
    "audit": {
        "score": 92
    },
    "traffic_sources": {
        "direct_percent": 28.51,
        "search_percent": 36.57,
        "social_percent": 6.85,
        "referral_percent": 12.7,
        "email_percent": 6.29,
        "paid_percent": 9.08
    },
    "seo_profile": {
        "backlinks_total": 1,
        "referring_domains": 1,
        "dofollow_backlinks_percent": 100,
        "organic_keywords": 56,
        "indexed_pages": 66,
        "page_speed_score": 100,
        "mobile_friendliness_score": 89,
        "authority_score": 28,
        "spam_risk_score": 2
    },
    "crawl_report": {
        "robots_status": 200,
        "sitemap_status": 200,
        "sitemap_total_urls": 66,
        "crawl_blocked": false,
        "crawl_blocked_by": "",
        "crawl_blocked_reason": "",
        "notes": [],
        "created_at": "2026-03-20 20:18:57"
    },
    "keywords": [
        {
            "keyword": "hur.st's bl.aagh",
            "position": 24,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "hur.st's bl.aagh personal: portfolios & cvs",
            "position": 26,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "hur.st's bl.aagh reviews",
            "position": 28,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "hur",
            "position": 30,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "aagh",
            "position": 32,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "about",
            "position": 34,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "about me",
            "position": 36,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        },
        {
            "keyword": "help",
            "position": 38,
            "search_engine": "Estimated",
            "checked_at": "2026-04-19 11:50:04",
            "is_estimated": true
        }
    ],
    "rating": {
        "overall": 64,
        "label": "Healthy",
        "breakdown": [
            {
                "label": "Technical foundation",
                "score": 17,
                "max": 18
            },
            {
                "label": "Authority & trust",
                "score": 8,
                "max": 30
            },
            {
                "label": "Reach & market presence",
                "score": 3,
                "max": 18
            },
            {
                "label": "Search visibility",
                "score": 3,
                "max": 12
            },
            {
                "label": "Engagement & retention",
                "score": 9,
                "max": 10
            },
            {
                "label": "Channels & diversification",
                "score": 4,
                "max": 6
            },
            {
                "label": "Registry stability",
                "score": 3,
                "max": 6
            },
            {
                "label": "Quality system",
                "score": 94,
                "max": 100
            },
            {
                "label": "Reputation system",
                "score": 37,
                "max": 100
            },
            {
                "label": "Safety system",
                "score": 100,
                "max": 100
            },
            {
                "label": "Evidence confidence",
                "score": 100,
                "max": 100
            }
        ],
        "authority_score": 28,
        "quality_score": 94,
        "reputation_score": 37,
        "safety_score": 100,
        "confidence_score": 100,
        "fraud_score": 0,
        "authority_signals": {
            "backlinks": 1,
            "referring_domains": 1,
            "organic_keywords": 56,
            "indexed_pages": 66,
            "monthly_visitors": 131,
            "global_rank": 19828,
            "engagement_score": 80,
            "crawl_quality_score": 100,
            "brand_completeness_score": 63,
            "link_diversity_score": 92,
            "technical_reliability_score": 96,
            "whois_score": 45,
            "whois_age_years": 0,
            "whois_stability_score": 100,
            "spam_penalty": 0
        },
        "whois_signals": {
            "age_years": 0,
            "days_to_expiry": null,
            "days_since_last_registry_update": null,
            "stability_score": 100,
            "registrar_changes": 0,
            "ownership_changes": 0,
            "nameserver_changes": 0,
            "status_changes": 0,
            "history_entries": 1,
            "privacy_protected": false,
            "dnssec_enabled": false,
            "has_registrant_country": false,
            "registrant_country": "",
            "nameserver_count": 0,
            "status_count": 0
        }
    },
    "authority_score": 28,
    "trust_score": 75,
    "domain_tags": {
        "primary_tag": "T",
        "primary_tag_score": 80,
        "primary_candidate": "T",
        "primary_candidate_score": 80,
        "tag_codes": "T",
        "tags": [
            {
                "code": "T",
                "label": "Trusted",
                "tone": "good",
                "description": "Strong trust, stability, and low-risk signals were detected.",
                "reason": "Low spam indicators plus strong trust, quality, registry, and stability signals were detected.",
                "message": "The site shows a reasonably trustworthy and stable profile.",
                "priority": 80,
                "score": 80,
                "match_percent": 80,
                "threshold_band": "strong"
            }
        ],
        "tag_breakdown": [
            {
                "code": "T",
                "label": "Trusted",
                "tone": "good",
                "description": "Strong trust, stability, and low-risk signals were detected.",
                "reason": "Low spam indicators plus strong trust, quality, registry, and stability signals were detected.",
                "message": "The site shows a reasonably trustworthy and stable profile.",
                "priority": 80,
                "score": 80,
                "match_percent": 80,
                "threshold_band": "strong"
            },
            {
                "code": "Uncertain",
                "label": "Uncertain",
                "tone": "unknown",
                "description": "External checks stayed inconclusive, so the model avoided a harder verdict.",
                "reason": "",
                "message": "The evidence does not currently look notably uncertain.",
                "priority": 18,
                "score": 18,
                "match_percent": 18,
                "threshold_band": "none"
            },
            {
                "code": "C",
                "label": "Caution",
                "tone": "caution",
                "description": "Signals are mixed or weak, so this domain should be treated carefully.",
                "reason": "Review carefully: mixed trust signals.",
                "message": "The current crawl does not show a meaningful caution match.",
                "priority": 0,
                "score": 0,
                "match_percent": 0,
                "threshold_band": "none"
            },
            {
                "code": "Crypto",
                "label": "Crypto drainer risk",
                "tone": "toxic",
                "description": "Wallet-connect or seed-phrase theft patterns were detected.",
                "reason": "Wallet-connect or seed-phrase theft patterns were detected.",
                "message": "No meaningful crypto-drainer signals were detected.",
                "priority": 0,
                "score": 0,
                "match_percent": 0,
                "threshold_band": "none"
            },
            {
                "code": "D",
                "label": "Dangerous",
                "tone": "toxic",
                "description": "Strong signs of phishing, malware, or other harmful behaviour were detected.",
                "reason": "Multiple high-risk signals pushed this domain into the dangerous range.",
                "message": "No meaningful dangerous-signal match was detected.",
                "priority": 0,
                "score": 0,
                "match_percent": 0,
                "threshold_band": "none"
            }
        ],
        "nsfw_score": 0,
        "trust_score": 76,
        "manual": {
            "has_changes": false,
            "verified_status": "",
            "tag_codes": "",
            "rating_delta": 0,
            "authority_delta": 0,
            "trust_delta": 0,
            "note": "",
            "adjusted_by": 0,
            "adjusted_at": "",
            "lock_scores": false,
            "lock_flags": false
        },
        "summary": "Trusted (80% match) because low spam indicators plus strong trust, quality, registry, and stability signals were detected.",
        "external_intel": [],
        "external_decision": [],
        "signal_scores": [
            {
                "label": "Strongest tag heuristic",
                "value": "T · 80%",
                "tone": "good",
                "detail": "The highest raw tag match from the heuristic engine before visibility thresholds and manual overrides."
            },
            {
                "label": "Trust score",
                "value": "76/100",
                "tone": "good",
                "detail": "Confidence derived from authority, crawl quality, stability, and risk signals."
            },
            {
                "label": "Authority score",
                "value": "28/100",
                "tone": "spam",
                "detail": "A higher authority score usually means broader reputation and backlink confidence."
            },
            {
                "label": "Spam risk",
                "value": "0/100",
                "tone": "good",
                "detail": "Lower is better. This blends spam indicators with false-positive protections for legitimate sites."
            },
            {
                "label": "Quality score",
                "value": "89/100",
                "tone": "good",
                "detail": "Based on crawl quality, content completeness, and technical evidence."
            },
            {
                "label": "Safety score",
                "value": "100/100",
                "tone": "good",
                "detail": "Higher is safer. Direct fraud signals can heavily cap this even when SEO signals look strong."
            },
            {
                "label": "Fraud score",
                "value": "0/100",
                "tone": "good",
                "detail": "Lower is better. This reflects phishing, drainer, fake-support, fake-shop, and malware signals."
            },
            {
                "label": "Infrastructure risk",
                "value": "0/100",
                "tone": "good",
                "detail": "Lower is better. This reflects the IP, registrar, and nameserver neighbourhood seen by the crawler."
            },
            {
                "label": "Evidence confidence",
                "value": "100/100",
                "tone": "good",
                "detail": "Higher means the crawler had enough pages and registry evidence to make a stronger call."
            },
            {
                "label": "External evidence",
                "value": "Low",
                "tone": "unknown",
                "detail": "Quality of the structured search and review evidence cluster."
            },
            {
                "label": "External decision",
                "value": "Inconclusive",
                "tone": "unknown",
                "detail": "How third-party evidence compares with the current candidate tag."
            },
            {
                "label": "NSFW score",
                "value": "0/100",
                "tone": "good",
                "detail": "Context-aware adult-content detection with medical / educational false-positive reduction."
            },
            {
                "label": "Registry stability",
                "value": "100/100",
                "tone": "good",
                "detail": "Based on age, expiry runway, and the amount of ownership / registrar churn."
            }
        ],
        "signal_sections": [
            {
                "title": "Registry & ownership",
                "items": [
                    {
                        "label": "Domain age",
                        "value": "—",
                        "tone": "unknown",
                        "detail": "Older domains generally carry more historical trust than very new ones."
                    },
                    {
                        "label": "Stability score",
                        "value": "100/100",
                        "tone": "good",
                        "detail": "Penalised by registrar, ownership, and nameserver churn."
                    },
                    {
                        "label": "Days to expiry",
                        "value": "—",
                        "tone": "unknown",
                        "detail": "Very short renewal windows can be a weak trust signal."
                    },
                    {
                        "label": "Registrar / ownership changes",
                        "value": "0 / 0",
                        "tone": "good",
                        "detail": "Frequent ownership churn can weaken trust."
                    },
                    {
                        "label": "Nameserver changes",
                        "value": "0",
                        "tone": "good",
                        "detail": "Repeated infrastructure changes can indicate instability."
                    },
                    {
                        "label": "DNSSEC / privacy",
                        "value": "DNSSEC off · privacy off",
                        "tone": "caution",
                        "detail": "DNSSEC strengthens DNS trust; privacy is neutral on its own."
                    }
                ]
            },
            {
                "title": "Reputation & search evidence",
                "items": [
                    {
                        "label": "Backlinks",
                        "value": "1",
                        "tone": "unknown",
                        "detail": "Broader backlink evidence usually improves confidence."
                    },
                    {
                        "label": "Referring domains",
                        "value": "1",
                        "tone": "unknown",
                        "detail": "Unique linking domains are more useful than raw link volume."
                    },
                    {
                        "label": "Organic keywords",
                        "value": "56",
                        "tone": "caution",
                        "detail": "Search footprint helps distinguish real sites from thin shells."
                    },
                    {
                        "label": "Indexed pages",
                        "value": "66",
                        "tone": "caution",
                        "detail": "Larger index coverage usually means more evidence to classify from."
                    },
                    {
                        "label": "Brand strength",
                        "value": "63/100",
                        "tone": "good",
                        "detail": "Stronger brand signals reduce false positives for legitimate sites."
                    },
                    {
                        "label": "Risk label",
                        "value": "GOOD",
                        "tone": "unknown",
                        "detail": "This is the raw crawl / heuristic risk label feeding the tag model."
                    }
                ]
            },
            {
                "title": "Crawl, content & technicals",
                "items": [
                    {
                        "label": "HTTP status",
                        "value": "200",
                        "tone": "good",
                        "detail": "Healthy responses make classification more reliable."
                    },
                    {
                        "label": "HTTPS / speed",
                        "value": "HTTPS OK · 75 ms",
                        "tone": "good",
                        "detail": "Slow or broken technical signals weaken confidence."
                    },
                    {
                        "label": "Content words",
                        "value": "451",
                        "tone": "caution",
                        "detail": "Thin pages are harder to trust and easier to manipulate."
                    },
                    {
                        "label": "Schema / structure",
                        "value": "0 schema · meta · H1",
                        "tone": "caution",
                        "detail": "Structured markup and basic on-page hygiene improve quality confidence."
                    },
                    {
                        "label": "Links on page",
                        "value": "63 internal · 3 external",
                        "tone": "good",
                        "detail": "Link patterns help detect thin directories and promo pages."
                    },
                    {
                        "label": "Page speed / mobile",
                        "value": "100/100 · 89/100",
                        "tone": "good",
                        "detail": "Better technical quality generally reduces low-effort site patterns."
                    },
                    {
                        "label": "Crawl access",
                        "value": "Open",
                        "tone": "good",
                        "detail": "The crawler reached the site without an anti-bot challenge."
                    }
                ]
            },
            {
                "title": "External evidence & explainability",
                "items": [
                    {
                        "label": "Decision state",
                        "value": "Inconclusive",
                        "tone": "unknown",
                        "detail": "Structured third-party evidence is still too thin, mixed, or unqualified to force a harder verdict."
                    },
                    {
                        "label": "Evidence quality",
                        "value": "Low",
                        "tone": "unknown",
                        "detail": "Blends source trust, domain matching, evidence diversity, and freshness."
                    },
                    {
                        "label": "Support vs contradiction",
                        "value": "0 / 0",
                        "tone": "unknown",
                        "detail": "Compares how much structured external evidence supports the candidate tag against evidence that contradicts it."
                    },
                    {
                        "label": "Qualified risk sources",
                        "value": "No",
                        "tone": "good",
                        "detail": "Risk tags only promote from external evidence when source diversity or source trust thresholds are met."
                    },
                    {
                        "label": "Uncertainty buffer",
                        "value": "Clear",
                        "tone": "good",
                        "detail": "Prevents thin or mixed external evidence from forcing a stronger tag than the evidence can justify."
                    }
                ]
            }
        ],
        "positives": [
            "Low registrar / ownership churn with solid registry stability.",
            "Healthy crawl quality and on-page completeness."
        ],
        "risks": []
    },
    "traffic_confidence": 52,
    "whois": {
        "current": {
            "id": 51887,
            "domain": "hur.st",
            "source_type": "whois_text",
            "rdap_url": "",
            "registrar_name": "",
            "registrar_handle": "",
            "registrant_name": "",
            "registrant_org": "",
            "registrant_country": "",
            "registrant_email": "",
            "abuse_email": "",
            "created_date": null,
            "updated_date": null,
            "expires_date": null,
            "nameservers_json": "[]",
            "status_json": "[]",
            "dnssec": "unknown",
            "privacy_protected": 0,
            "content_hash": "f7e17c57c5fdd24df1793ece6bff99716369356b90b29c4725ac3ba12a76b72c",
            "history_count": 1,
            "last_checked_at": "2026-03-20 20:18:55",
            "last_changed_at": "2026-03-20 20:18:55",
            "created_at": "2026-03-20 20:18:56",
            "updated_at": "2026-03-20 20:18:56"
        },
        "history": [
            {
                "id": 52961,
                "domain": "hur.st",
                "source_type": "whois_text",
                "registrar_name": "",
                "registrar_handle": "",
                "registrant_name": "",
                "registrant_org": "",
                "registrant_country": "",
                "registrant_email": "",
                "abuse_email": "",
                "created_date": null,
                "updated_date": null,
                "expires_date": null,
                "nameservers_json": "[]",
                "status_json": "[]",
                "dnssec": "unknown",
                "privacy_protected": 0,
                "content_hash": "f7e17c57c5fdd24df1793ece6bff99716369356b90b29c4725ac3ba12a76b72c",
                "checked_at": "2026-03-20 20:18:55",
                "change_summary": "Initial WHOIS snapshot captured.",
                "created_at": "2026-03-20 20:18:55"
            }
        ],
        "signals": {
            "age_years": 0,
            "days_to_expiry": null,
            "days_since_last_registry_update": null,
            "stability_score": 100,
            "registrar_changes": 0,
            "ownership_changes": 0,
            "nameserver_changes": 0,
            "status_changes": 0,
            "history_entries": 1,
            "privacy_protected": false,
            "dnssec_enabled": false,
            "has_registrant_country": false,
            "registrant_country": "",
            "nameserver_count": 0,
            "status_count": 0
        }
    },
    "discovered_domain": {
        "id": 146272,
        "domain": "hur.st",
        "first_seen_at": "2026-03-16 06:42:57",
        "last_crawled_at": "2026-03-20 20:18:57",
        "last_title": "hur.st's bl.aagh",
        "last_http_status": 200,
        "discovered_from_domain": "namehack.club",
        "depth": 0,
        "backlinks_count": 1,
        "rating_cache": 61,
        "spam_score": 24,
        "risk_label": "good",
        "category_name": "Personal: Portfolios & CVs",
        "primary_country_code": "",
        "internal_links_count": 63,
        "external_links_count": 3,
        "social_profiles_count": 1,
        "content_word_count": 451,
        "title_quality_score": 79,
        "has_meta_description": 1,
        "has_h1": 1,
        "language_code": "en",
        "response_time_ms": 75,
        "robots_status": 200,
        "sitemap_status": 200,
        "sitemap_total_urls": 66,
        "quality_score": 89,
        "site_name": "",
        "canonical_domain": "",
        "favicon_present": 1,
        "schema_org_count": 0,
        "noindex_detected": 0,
        "feed_links_count": 0,
        "https_working": 1,
        "estimated_authority_score": 24,
        "trust_score": 90,
        "nsfw_score": 0,
        "overall_rank_estimate": 18820,
        "primary_tag": "T",
        "tag_codes": "T",
        "manual_verified_status": "",
        "manual_tag_codes": "",
        "manual_rating_delta": 0,
        "manual_authority_delta": 0,
        "manual_trust_delta": 0,
        "manual_note": null,
        "manual_adjusted_by": null,
        "manual_adjusted_at": null,
        "manual_lock_scores": 0,
        "manual_lock_flags": 0,
        "crawl_blocked": 0,
        "crawl_blocked_by": "",
        "crawl_blocked_reason": null,
        "safety_score": 100,
        "fraud_score": 0,
        "legitimacy_score": 51,
        "infrastructure_risk_score": 0,
        "score_confidence": 100,
        "tag_confidence": 72,
        "category_confidence": 88,
        "deep_crawl_pages": 50,
        "resolved_ip": "158.220.85.230",
        "category_candidates_json": "[{\"category\":\"Personal: Portfolios & CVs\",\"score\":88}]",
        "page_signals_json": "[{\"path\":\"/about\",\"status\":200,\"title\":\"About — hur.st's bl.aagh\",\"word_count\":308,\"summary_text\":\"About — hur.st's bl.aagh About &mdash; hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Thomas Hurst That is, indeed, my name 2023-09-16 I’m a computer programmer from North East England. I started out with ARexx in the mid 1990’s, and it’s been mostly downhill from there via, amongst other things, Perl, PHP, Ruby, Python, C, and most recently, Rust. My biggest claim to fame is co-developing the NZB specification, the de- facto standard for distributing binary data on the Usenet distributed discussions system. If you’ve downloaded a Linux ISO from Usenet in the past 15 years, I probably helped make it happen. I primarily use FreeBSD, and run a small search engine to help the community keep track of what’s going on there and in related projects. Beyond\",\"classification_terms\":[\"about\",\"about me\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":3,\"depth\":1},{\"path\":\"/blog\",\"status\":200,\"title\":\"Blog — hur.st's bl.aagh\",\"word_count\":444,\"summary_text\":\"Blog — hur.st's bl.aagh Blog &mdash; hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Excessive Swapping with FreeBSD NUMA Poor VM behaviour with ZFS ARC and unbalanced NUMA domains [freebsd] 2023-09-24 &nbsp; Freaky/numastat on Github Early last year I finally diagnosed a long-standing issue with my FreeBSD machine, which always had gobs of memory for things but which frequently encountered swap pressure for no discenerable reason. This is a slightly edited copy of an unpublushed report I wrote back then, prior to the hardware being retired. Maybe it’ll be useful to someone. Continue Reading Micro-Optimising in JRuby Calling Java from JRuby for fun and profit [ruby] [jruby] [java] 2018-08-26 One of the neatest bits of JRuby is the simple way you can\",\"classification_terms\":[\"blog\",\"about\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":4,\"depth\":1},{\"path\":\"/projects\",\"status\":200,\"title\":\"Projects — hur.st's bl.aagh\",\"word_count\":2090,\"summary_text\":\"Projects — hur.st's bl.aagh Projects &mdash; hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon portacl-rc FreeBSD mac_portacl(4) rc script [shell] [bsd] 2023-09-12 &nbsp; Freaky/portacl-rc on Github &nbsp;security&#x2F;portacl-rc mac_portacl(4) is a FreeBSD kernel security module providing an access control policy for permitting specific users and groups to bind to ports that would otherwise be restricted to the super-user. portacl-rc is an rc script that makes configuring it easier and safer. Continue Reading IMSErious Execute commands in response to Internet Message Store Events [rust] [dovecot] [email] 2022-04-24 &nbsp; Freaky/IMSErious on Github &nbsp; imserious on Crates.io IMSErious is a tiny Rust web service that makes up part of my email infrastru\",\"classification_terms\":[\"projects\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":31,\"depth\":1},{\"path\":\"/welcome/\",\"status\":200,\"title\":\"Welcome\",\"word_count\":76,\"summary_text\":\"Welcome Welcome hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Welcome Greetings, giant bag of mostly water. This is the personal website of Thomas Hurst, a computer programmer from North East England. You might take a look at my rather stale blog, admire the non-exhaustive list of low-quality junk I’ve made, or if you really want, you might look at how to get in touch so you can complain about it. Thomas Hurst\",\"classification_terms\":[\"welcome\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":0,\"depth\":1},{\"path\":\"/about/\",\"status\":200,\"title\":\"About — hur.st's bl.aagh\",\"word_count\":308,\"summary_text\":\"About — hur.st's bl.aagh About &mdash; hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Thomas Hurst That is, indeed, my name 2023-09-16 I’m a computer programmer from North East England. I started out with ARexx in the mid 1990’s, and it’s been mostly downhill from there via, amongst other things, Perl, PHP, Ruby, Python, C, and most recently, Rust. My biggest claim to fame is co-developing the NZB specification, the de- facto standard for distributing binary data on the Usenet distributed discussions system. If you’ve downloaded a Linux ISO from Usenet in the past 15 years, I probably helped make it happen. I primarily use FreeBSD, and run a small search engine to help the community keep track of what’s going on there and in related projects. Beyond\",\"classification_terms\":[\"about\",\"about me\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":3,\"depth\":1},{\"path\":\"/blog/\",\"status\":200,\"title\":\"Blog — hur.st's bl.aagh\",\"word_count\":444,\"summary_text\":\"Blog — hur.st's bl.aagh Blog &mdash; hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Excessive Swapping with FreeBSD NUMA Poor VM behaviour with ZFS ARC and unbalanced NUMA domains [freebsd] 2023-09-24 &nbsp; Freaky/numastat on Github Early last year I finally diagnosed a long-standing issue with my FreeBSD machine, which always had gobs of memory for things but which frequently encountered swap pressure for no discenerable reason. This is a slightly edited copy of an unpublushed report I wrote back then, prior to the hardware being retired. Maybe it’ll be useful to someone. Continue Reading Micro-Optimising in JRuby Calling Java from JRuby for fun and profit [ruby] [jruby] [java] 2018-08-26 One of the neatest bits of JRuby is the simple way you can\",\"classification_terms\":[\"blog\",\"about\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":4,\"depth\":1},{\"path\":\"/projects/\",\"status\":200,\"title\":\"Projects — hur.st's bl.aagh\",\"word_count\":2090,\"summary_text\":\"Projects — hur.st's bl.aagh Projects &mdash; hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon portacl-rc FreeBSD mac_portacl(4) rc script [shell] [bsd] 2023-09-12 &nbsp; Freaky/portacl-rc on Github &nbsp;security&#x2F;portacl-rc mac_portacl(4) is a FreeBSD kernel security module providing an access control policy for permitting specific users and groups to bind to ports that would otherwise be restricted to the super-user. portacl-rc is an rc script that makes configuring it easier and safer. Continue Reading IMSErious Execute commands in response to Internet Message Store Events [rust] [dovecot] [email] 2022-04-24 &nbsp; Freaky/IMSErious on Github &nbsp; imserious on Crates.io IMSErious is a tiny Rust web service that makes up part of my email infrastru\",\"classification_terms\":[\"projects\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":31,\"depth\":1},{\"path\":\"/about/contact/\",\"status\":200,\"title\":\"Contact\",\"word_count\":45,\"summary_text\":\"Contact Contact hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Contact If you have a problem, if no one else can help... 2022-11-12 MethodLocationReply ProbabilityReply Latency IRC Freaky @ libera.chat0.930 seconds–12 hours Fediverse @Freaky@hachyderm.io0.82 hours—2 days Email tom@hur.st0.68 hours–7 days Thomas Hurst\",\"classification_terms\":[\"about/contact\",\"about\",\"contact\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/blog/2023/09-24-excessive-swapping-with-freebsd-numa/\",\"status\":200,\"title\":\"Excessive Swapping with FreeBSD NUMA\",\"word_count\":519,\"summary_text\":\"Excessive Swapping with FreeBSD NUMA Excessive Swapping with FreeBSD NUMA hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Excessive Swapping with FreeBSD NUMA Poor VM behaviour with ZFS ARC and unbalanced NUMA domains [freebsd] 2023-09-24 &nbsp; Freaky/numastat on Github Early last year I finally diagnosed a long-standing issue with my FreeBSD machine, which always had gobs of memory for things but which frequently encountered swap pressure for no discenerable reason. This is a slightly edited copy of an unpublushed report I wrote back then, prior to the hardware being retired. Maybe it’ll be useful to someone. When migrating data from one large ZFS pool to another, I found my swap device filling up completely, despite enormous amounts of free memory (&gt;50GB) and a relatively sever\",\"classification_terms\":[\"blog/2023/09-24-excessive-swapping-with-freebsd-numa\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/freebsd/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":96,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Excessive Swapping with FreeBSD NUMA Poor VM behaviour with ZFS ARC and unbalanced NUMA domains [freebsd] 2023-09-24 &nbsp; Freaky/numastat on Github Early last year I finally diagnosed a long-standing issue with my FreeBSD machine, which always had gobs of memory for things but which frequently encountered swap pressure for no discenerable reason. This is a slightly edited copy of an unpublushed report I wrote back then, prior to the hardware being retired. Maybe it’ll be useful to someone. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/freebsd\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/blog/2018/08-26-micro-optimising-jruby/\",\"status\":200,\"title\":\"Micro-Optimising in JRuby\",\"word_count\":635,\"summary_text\":\"Micro-Optimising in JRuby Micro-Optimising in JRuby hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Micro-Optimising in JRuby Calling Java from JRuby for fun and profit [ruby] [jruby] [java] 2018-08-26 One of the neatest bits of JRuby is the simple way you can call out to Java. There’s a lot of Java out there, and you can wrap it up in nice little Ruby interfaces with just a few lines of code. Let’s illustrate with some trivial examples, hooking up bits of Java to Ruby and seeing how well they perform compared to the equivalent pure Ruby. Current time in ISO format🔗 We rarely think about the cost of generating a timestamp, and that’s probably quite fair given I can make nearly 130,000 of them every second: Time.now.utc.iso8601 128.908k (± 3.9%) i/s - 644.166k in 5.006521s\",\"classification_terms\":[\"blog/2018/08-26-micro-optimising-jruby\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":10,\"depth\":1},{\"path\":\"/tags/ruby/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":979,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon monotime Rust-style monotonic clocks in Ruby [ruby] [rust] 2018-09-05 &nbsp; Freaky/monotime on Github Monotime offers an alternative to the typical method of monotonic timekeeping in Ruby: # Bog standard Ruby start = Process.clock_gettime(Process::CLOCK_MONOTONIC) do_something elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # With monotime require &#39;monotime&#39; include Monotime start = Instant.now do_something elapsed = start.elapsed # or elapsed = Duration.measure { do_something } It’s less fiddly, and uses proper types wrapping elapsed times in nanoseconds, which is about as close to the native representations as Ruby gets. Continue Reading Micro-Optimi\",\"classification_terms\":[\"tags/ruby\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":14,\"depth\":1},{\"path\":\"/tags/jruby/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":100,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Micro-Optimising in JRuby Calling Java from JRuby for fun and profit [ruby] [jruby] [java] 2018-08-26 One of the neatest bits of JRuby is the simple way you can call out to Java. There’s a lot of Java out there, and you can wrap it up in nice little Ruby interfaces with just a few lines of code. Let’s illustrate with some trivial examples, hooking up bits of Java to Ruby and seeing how well they perform compared to the equivalent pure Ruby. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/jruby\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/java/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":100,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Micro-Optimising in JRuby Calling Java from JRuby for fun and profit [ruby] [jruby] [java] 2018-08-26 One of the neatest bits of JRuby is the simple way you can call out to Java. There’s a lot of Java out there, and you can wrap it up in nice little Ruby interfaces with just a few lines of code. Let’s illustrate with some trivial examples, hooking up bits of Java to Ruby and seeing how well they perform compared to the equivalent pure Ruby. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/java\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/blog/2018/08-25-password-generation-in-ruby-and-rust/\",\"status\":200,\"title\":\"Password Generation in Ruby and Rust\",\"word_count\":3352,\"summary_text\":\"Password Generation in Ruby and Rust Password Generation in Ruby and Rust hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Password Generation in Ruby and Rust Writing the same small program in two different languages. [ruby] [rust] 2018-08-25 &nbsp; Freaky/simplepass on Github I’ve been doing a fair bit of Rust lately. Honestly, I haven’t been so smitten with a language since I started writing Ruby back in 1999. Rust is many of the things Ruby isn’t—precompiled, screaming fast, meticulously efficient, static, explicit, type-safe. But it’s also expressive and, above all, fun. I think this rare mix makes it a good companion language for Ruby developers, particularly with things like Helix and rutie making it easy to bridge the two. The best way of learning is by doing, so why not avoid\",\"classification_terms\":[\"blog/2018/08-25-password-generation-in-ruby-and-rust\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":2,\"depth\":1},{\"path\":\"/tags/rust/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":1076,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon IMSErious Execute commands in response to Internet Message Store Events [rust] [dovecot] [email] 2022-04-24 &nbsp; Freaky/IMSErious on Github &nbsp; imserious on Crates.io IMSErious is a tiny Rust web service that makes up part of my email infrastructure. It responds to Open-Exchange IMSE messages from the Dovecot email server by executing commands. In my case, I use it to trigger fdm – a mail retrieval agent. Continue Reading annoirc An IRC bot for annotating channels [rust] [irc] 2020-11-13 &nbsp; Freaky/annoirc on Github annoirc is an Internet Relay Chat bot, make to provide page titles and descriptions when people enter a URL on a channel. Continue Reading faccess Basic cros\",\"classification_terms\":[\"tags/rust\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":15,\"depth\":1},{\"path\":\"/blog/2018/08-08-first/\",\"status\":200,\"title\":\"First Post\",\"word_count\":156,\"summary_text\":\"First Post First Post hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon First Post Someone... pays me for this, right? Guys? [meta] [web] 2018-08-09 Hmm, I’m doing this again, am I? Last time was a custom PHP CMS with enough fancy features it even had dual-mode HTML/XHTML rendering based on the Accept-Content header. Look. It made sense at the time. Sort of. Shut up. 16(!) years later… it still mostly works, and it’s certainly not the worst thing I’ve ever written, but I haven’t been a PHP guy in a long time, and it’s time for a change. So here I am with Gutenberg, a static site generator written in my new favourite language, Rust. Whether or not I actually do anything with it, I helped fix bugs in four different projects in the process of setting it up, and m\",\"classification_terms\":[\"blog/2018/08-08-first\",\"about\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/meta/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":156,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon First Post Someone... pays me for this, right? Guys? [meta] [web] 2018-08-09 Hmm, I’m doing this again, am I? Last time was a custom PHP CMS with enough fancy features it even had dual-mode HTML/XHTML rendering based on the Accept-Content header. Look. It made sense at the time. Sort of. Shut up. 16(!) years later… it still mostly works, and it’s certainly not the worst thing I’ve ever written, but I haven’t been a PHP guy in a long time, and it’s time for a change. So here I am with Gutenberg, a static site generator written in my new favourite language, Rust. Whether or not I actually do anything with it, I helped fix bugs in four different projects in the process of setting i\",\"classification_terms\":[\"tags/meta\",\"about\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/web/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":433,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon First Post Someone... pays me for this, right? Guys? [meta] [web] 2018-08-09 Hmm, I’m doing this again, am I? Last time was a custom PHP CMS with enough fancy features it even had dual-mode HTML/XHTML rendering based on the Accept-Content header. Look. It made sense at the time. Sort of. Shut up. 16(!) years later… it still mostly works, and it’s certainly not the worst thing I’ve ever written, but I haven’t been a PHP guy in a long time, and it’s time for a change. So here I am with Gutenberg, a static site generator written in my new favourite language, Rust. Whether or not I actually do anything with it, I helped fix bugs in four different projects in the process of setting i\",\"classification_terms\":[\"tags/web\",\"about\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":4,\"depth\":1},{\"path\":\"/projects/portacl/\",\"status\":200,\"title\":\"portacl-rc\",\"word_count\":192,\"summary_text\":\"portacl-rc portacl-rc hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon portacl-rc FreeBSD mac_portacl(4) rc script [shell] [bsd] 2023-09-12 &nbsp; Freaky/portacl-rc on Github &nbsp;security&#x2F;portacl-rc mac_portacl(4) is a FreeBSD kernel security module providing an access control policy for permitting specific users and groups to bind to ports that would otherwise be restricted to the super-user. portacl-rc is an rc script that makes configuring it easier and safer. Traditional mac_portacl(4) configuration looks something like this: # sysrc kld_list+=mac_portacl # echo &gt;&gt;/etc/sysctl.conf security.mac.portacl.rules=&quot;uid:80:tcp:80,uid:80:tcp:443,uid:80:udp:443&quot; net.inet.ip.portrange.reservedhigh=0 ^D # kldload mac_portacl # service sysctl re\",\"classification_terms\":[\"projects/portacl\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/shell/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":157,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon portacl-rc FreeBSD mac_portacl(4) rc script [shell] [bsd] 2023-09-12 &nbsp; Freaky/portacl-rc on Github &nbsp;security&#x2F;portacl-rc mac_portacl(4) is a FreeBSD kernel security module providing an access control policy for permitting specific users and groups to bind to ports that would otherwise be restricted to the super-user. portacl-rc is an rc script that makes configuring it easier and safer. Continue Reading run-one Friendly wrapper around lockf&#x2F;flock, unofficial clone of an Ubuntu package [shell] 2017-04-21 &nbsp; Freaky/run-one on Github &nbsp;original on Launchpad Wanting to hone my shell scripting skills a bit, I ended up reimplementing a cute script by Dustin\",\"classification_terms\":[\"tags/shell\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":2,\"depth\":1},{\"path\":\"/tags/bsd/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":330,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon portacl-rc FreeBSD mac_portacl(4) rc script [shell] [bsd] 2023-09-12 &nbsp; Freaky/portacl-rc on Github &nbsp;security&#x2F;portacl-rc mac_portacl(4) is a FreeBSD kernel security module providing an access control policy for permitting specific users and groups to bind to ports that would otherwise be restricted to the super-user. portacl-rc is an rc script that makes configuring it easier and safer. Continue Reading checkrestart Find processes that need restarting after an upgrade [c] [bsd] 2020-02-26 &nbsp; Freaky/checkrestart on Github &nbsp;sysutils&#x2F;checkrestart checkrestart is a FreeBSD semi-workalike of the old checkrestart program from debian-goodies — it looks for r\",\"classification_terms\":[\"tags/bsd\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":5,\"depth\":1},{\"path\":\"/projects/imserious/\",\"status\":200,\"title\":\"IMSErious\",\"word_count\":357,\"summary_text\":\"IMSErious IMSErious hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon IMSErious Execute commands in response to Internet Message Store Events [rust] [dovecot] [email] 2022-04-24 &nbsp; Freaky/IMSErious on Github &nbsp; imserious on Crates.io IMSErious is a tiny Rust web service that makes up part of my email infrastructure. It responds to Open-Exchange IMSE messages from the Dovecot email server by executing commands. In my case, I use it to trigger fdm – a mail retrieval agent. This is one of those things that would have been about ten times smaller if I’d written it in Ruby or Python, but I wanted an excuse to play with axum, Tokio’s new web framework, and also as a production service for my internal network I wanted it to be as lightweight and as reasonabl\",\"classification_terms\":[\"projects/imserious\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/dovecot/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":83,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon IMSErious Execute commands in response to Internet Message Store Events [rust] [dovecot] [email] 2022-04-24 &nbsp; Freaky/IMSErious on Github &nbsp; imserious on Crates.io IMSErious is a tiny Rust web service that makes up part of my email infrastructure. It responds to Open-Exchange IMSE messages from the Dovecot email server by executing commands. In my case, I use it to trigger fdm – a mail retrieval agent. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/dovecot\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/email/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":83,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon IMSErious Execute commands in response to Internet Message Store Events [rust] [dovecot] [email] 2022-04-24 &nbsp; Freaky/IMSErious on Github &nbsp; imserious on Crates.io IMSErious is a tiny Rust web service that makes up part of my email infrastructure. It responds to Open-Exchange IMSE messages from the Dovecot email server by executing commands. In my case, I use it to trigger fdm – a mail retrieval agent. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/email\",\"about\",\"blog\",\"store\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/ioztat/\",\"status\":200,\"title\":\"ioztat\",\"word_count\":485,\"summary_text\":\"ioztat ioztat hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon ioztat ZFS dataset IO statistics [python] [zfs] 2022-01-25 &nbsp; jimsalterjrs/ioztat on Github &nbsp; Freaky/ioztat-packages on Github &nbsp;sysutils&#x2F;py-ioztat ioztat is to OpenZFS datasets what zpool-iostat(8) is to ZFS pools and vdevs. Where zpool-iostat provides IO statistics for accesses to the lower level components that make up a ZFS filesystem — the devices that underpin it and the mirrored, striped, and parity-combined virtual devices these are part of — ioztat does so for the filesystems and virtual block devices layered on top. ioztat grew from a relatively modest Python script written by a few Reddit users, with a few sorting options and not much else. I added FreeBSD support\",\"classification_terms\":[\"projects/ioztat\",\"about\",\"support\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":8,\"depth\":1},{\"path\":\"/tags/python/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":98,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon ioztat ZFS dataset IO statistics [python] [zfs] 2022-01-25 &nbsp; jimsalterjrs/ioztat on Github &nbsp; Freaky/ioztat-packages on Github &nbsp;sysutils&#x2F;py-ioztat ioztat is to OpenZFS datasets what zpool-iostat(8) is to ZFS pools and vdevs. Where zpool-iostat provides IO statistics for accesses to the lower level components that make up a ZFS filesystem — the devices that underpin it and the mirrored, striped, and parity-combined virtual devices these are part of — ioztat does so for the filesystems and virtual block devices layered on top. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/python\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/zfs/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":98,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon ioztat ZFS dataset IO statistics [python] [zfs] 2022-01-25 &nbsp; jimsalterjrs/ioztat on Github &nbsp; Freaky/ioztat-packages on Github &nbsp;sysutils&#x2F;py-ioztat ioztat is to OpenZFS datasets what zpool-iostat(8) is to ZFS pools and vdevs. Where zpool-iostat provides IO statistics for accesses to the lower level components that make up a ZFS filesystem — the devices that underpin it and the mirrored, striped, and parity-combined virtual devices these are part of — ioztat does so for the filesystems and virtual block devices layered on top. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/zfs\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/annoirc/\",\"status\":200,\"title\":\"annoirc\",\"word_count\":148,\"summary_text\":\"annoirc annoirc hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon annoirc An IRC bot for annotating channels [rust] [irc] 2020-11-13 &nbsp; Freaky/annoirc on Github annoirc is an Internet Relay Chat bot, make to provide page titles and descriptions when people enter a URL on a channel. It’s written in fully async Rust, and has served a few small channels successfully for several years (as of late 2022). It supports connections to multiple IRC servers, making multiple HTTP requests concurrently, deduplicating and rate-limiting those requests, caching results, and reconfiguring itself on SIGHUP. It’s a bit messy internally, but I learned a lot about working with Tokio in making it, which was the primary goal. It speaks to Rust’s strengths that I was able to i\",\"classification_terms\":[\"projects/annoirc\",\"about\",\"support\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/irc/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":54,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon annoirc An IRC bot for annotating channels [rust] [irc] 2020-11-13 &nbsp; Freaky/annoirc on Github annoirc is an Internet Relay Chat bot, make to provide page titles and descriptions when people enter a URL on a channel. Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/irc\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/faccess/\",\"status\":200,\"title\":\"faccess\",\"word_count\":487,\"summary_text\":\"faccess faccess hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon faccess Basic cross-platform file accessibility checks for Rust [rust] 2020-03-16 &nbsp; Freaky/faccess on Github &nbsp; faccess on Crates.io faccess adds file accessbility checks for file paths to Rust: pub trait PathExt { fn access(&amp;self, mode: AccessMode) -&gt; std::io::Result&lt;()&gt;; fn readable(&amp;self) -&gt; bool; fn writable(&amp;self) -&gt; bool; fn executable(&amp;self) -&gt; bool; } impl PathExt for std::path::Path; Usage For the simple case: use std::path::PathBuf; use faccess::PathExt; let path = PathBuf::from(&quot;/path/to/file&quot;); if path.readable() { println!(&quot;{} was probably readable!&quot;, path.display()); } More complex needs, such as reporting precisely\",\"classification_terms\":[\"projects/faccess\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/checkrestart/\",\"status\":200,\"title\":\"checkrestart\",\"word_count\":287,\"summary_text\":\"checkrestart checkrestart hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon checkrestart Find processes that need restarting after an upgrade [c] [bsd] 2020-02-26 &nbsp; Freaky/checkrestart on Github &nbsp;sysutils&#x2F;checkrestart checkrestart is a FreeBSD semi-workalike of the old checkrestart program from debian-goodies — it looks for running processes with open files to replaced binaries and libraries, indicating they’ve not been restarted since a software update. It is a C program using the libprocstat(3) and sysctl(3) interfaces, with output handled using libxo(3), providing both traditional text-based output, and structured JSON and XML for consumption by other programs: -# checkrestart PID JID NAME UPDATED COMMAND 44960 0 weechat Binary weechat 84169 0\",\"classification_terms\":[\"projects/checkrestart\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/c/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":198,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon checkrestart Find processes that need restarting after an upgrade [c] [bsd] 2020-02-26 &nbsp; Freaky/checkrestart on Github &nbsp;sysutils&#x2F;checkrestart checkrestart is a FreeBSD semi-workalike of the old checkrestart program from debian-goodies — it looks for running processes with open files to replaced binaries and libraries, indicating they’ve not been restarted since a software update. Continue Reading pqsort Fast partial quicksort [c] 2009-01-01 &nbsp; Freaky/pqsort on Github pqsort is the sorting library I wrote for Newzbin’s custom search engine - it’s a lightly modified quicksort capable of partitioning and sorting only part of a list. Quicksort lends itself very we\",\"classification_terms\":[\"tags/c\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":3,\"depth\":1},{\"path\":\"/projects/elite-shield-tester/\",\"status\":200,\"title\":\"Elite Shield Tester\",\"word_count\":233,\"summary_text\":\"Elite Shield Tester Elite Shield Tester hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Elite Shield Tester Find the best-possible Elite Dangerous Shields [rust] [javascript] [elite] [gaming] 2019-12-02 &nbsp; Freaky/elite_shield_tester on Github &nbsp;Web Version In the popular space simulation game, Elite Dangerous, one of the challenges is determining how best to outfit your ship — if you’re going into combat, choosing the right shield, with the right boosters and the right engineering can be the difference between life or death. So why not sap the fun out of it by using a computer to work out the best configuration for us? Fundamentally, this is a problem of combinatorics — there are a set of X shield configurations, and Y×Z shield booster configurations, which c\",\"classification_terms\":[\"projects/elite-shield-tester\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/javascript/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":271,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Elite Shield Tester Find the best-possible Elite Dangerous Shields [rust] [javascript] [elite] [gaming] 2019-12-02 &nbsp; Freaky/elite_shield_tester on Github &nbsp;Web Version In the popular space simulation game, Elite Dangerous, one of the challenges is determining how best to outfit your ship — if you’re going into combat, choosing the right shield, with the right boosters and the right engineering can be the difference between life or death. So why not sap the fun out of it by using a computer to work out the best configuration for us? Continue Reading 🖩 Bloom Filter Calculator 🖩 It has, like, graphs, and stuff. [php] [javascript] [web] 2009-01-11 &nbsp;Bloom Filter Calcula\",\"classification_terms\":[\"tags/javascript\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":2,\"depth\":1},{\"path\":\"/tags/elite/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":105,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Elite Shield Tester Find the best-possible Elite Dangerous Shields [rust] [javascript] [elite] [gaming] 2019-12-02 &nbsp; Freaky/elite_shield_tester on Github &nbsp;Web Version In the popular space simulation game, Elite Dangerous, one of the challenges is determining how best to outfit your ship — if you’re going into combat, choosing the right shield, with the right boosters and the right engineering can be the difference between life or death. So why not sap the fun out of it by using a computer to work out the best configuration for us? Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/elite\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/gaming/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":105,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Elite Shield Tester Find the best-possible Elite Dangerous Shields [rust] [javascript] [elite] [gaming] 2019-12-02 &nbsp; Freaky/elite_shield_tester on Github &nbsp;Web Version In the popular space simulation game, Elite Dangerous, one of the challenges is determining how best to outfit your ship — if you’re going into combat, choosing the right shield, with the right boosters and the right engineering can be the difference between life or death. So why not sap the fun out of it by using a computer to work out the best configuration for us? Continue Reading Thomas Hurst\",\"classification_terms\":[\"tags/gaming\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/compactor/\",\"status\":200,\"title\":\"Compactor\",\"word_count\":279,\"summary_text\":\"Compactor Compactor hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Compactor A friendly user interface to Windows 10 filesystem compression [rust] [windows] 2019-06-18 &nbsp; Freaky/Compactor on Github &nbsp; Freaky/compresstimator on Github One of the more notable features that shipped with Windows 10 is a new filesystem compression system based on the Windows Overlay Filesystem architecture, originally developed for transparent handling of disk images. It’s intended for use in applications, in particular the base OS (in a feature referred to as CompactOS), but sadly this is only exposed to users via a command line program — compact.exe — and most users fail to take advantage of it. Compactor offers this as an alternative: Compactor makes it easy for user\",\"classification_terms\":[\"projects/compactor\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/tags/windows/\",\"status\":200,\"title\":\"hur.st's bl.aagh\",\"word_count\":120,\"summary_text\":\"hur.st's bl.aagh hur.st&#x27;s bl.aagh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Compactor A friendly user interface to Windows 10 filesystem compression [rust] [windows] 2019-06-18 &nbsp; Freaky/Compactor on Github &nbsp; Freaky/compresstimator on Github One of the more notable features that shipped with Windows 10 is a new filesystem compression system based on the Windows Overlay Filesystem architecture, originally developed for transparent handling of disk images. It’s intended for use in applications, in particular the base OS (in a feature referred to as CompactOS), but sadly this is only exposed to users via a command line program — compact.exe — and most users fail to take advantage of it. Compactor offers this as an alternative: Continue Reading Tho\",\"classification_terms\":[\"tags/windows\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/tarssh/\",\"status\":200,\"title\":\"tarssh\",\"word_count\":476,\"summary_text\":\"tarssh tarssh hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon tarssh An async Rust SSH tarpit [rust] 2019-03-25 &nbsp; Freaky/tarssh on Github &nbsp; tarssh on Crates.io tarssh is an SSH tarpit – a server that trickles an endlessly repeating introductory banner to clients for as long as it remains connected, in order to expend the resources of attackers. It’s based on the same concept as Chris Wellons’ Endlessh, a similar service written in C. Tarssh is my first Rust program using Tokio, an asynchronous runtime that allows for the construction of highly scalable event-driven programs using kqueue, epoll and similar APIs, using Rust’s Futures API. The first release of tarssh predates Rust’s async/await syntax, and so the result was a quite unwieldy tree o\",\"classification_terms\":[\"projects/tarssh\",\"about\",\"api\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":3,\"depth\":1},{\"path\":\"/projects/cw/\",\"status\":200,\"title\":\"cw\",\"word_count\":404,\"summary_text\":\"cw cw hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon cw Count Words - a Rust wc implementation [rust] 2019-01-07 &nbsp; Freaky/cw on Github &nbsp; cw on Crates.io cw is a fast Rust reimplementation of the classic Unix wc command, featuring fast paths for most common modes of operation, including SIMD-accelerated line and UTF-8 codepoint counting via the bytecount crate (closing issue #41 there in the process). It also supports multithreading, because of course it does. Even in single-threaded mode it is almost always much faster than either FreeBSD or GNU wc implementations. -% wc * 33 182 1378 README 133 133 620 eign 281 287 1984 freebsd 1308 1308 8546 propernames 235970 235970 2493838 web2 76205 121847 1012731 web2a 235970 235970 2493838 words 549\",\"classification_terms\":[\"projects/cw\",\"about\",\"support\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":21,\"depth\":1},{\"path\":\"/projects/esc/\",\"status\":200,\"title\":\"Email Search Command\",\"word_count\":71,\"summary_text\":\"Email Search Command Email Search Command hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Email Search Command Email Sucks Completely [rust] 2018-09-05 &nbsp; Freaky/esc on Github esc is an embryonic email search tool, in the spirit of notmuch, built on top of Tantivy and mailparse. It can index my 2 million emails in about 3 minutes flat. Which is good, because it doesn’t have any efficient re-indexing support. Thomas Hurst\",\"classification_terms\":[\"projects/esc\",\"about\",\"support\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/monotime/\",\"status\":200,\"title\":\"monotime\",\"word_count\":181,\"summary_text\":\"monotime monotime hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon monotime Rust-style monotonic clocks in Ruby [ruby] [rust] 2018-09-05 &nbsp; Freaky/monotime on Github Monotime offers an alternative to the typical method of monotonic timekeeping in Ruby: # Bog standard Ruby start = Process.clock_gettime(Process::CLOCK_MONOTONIC) do_something elapsed = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start # With monotime require &#39;monotime&#39; include Monotime start = Instant.now do_something elapsed = start.elapsed # or elapsed = Duration.measure { do_something } It’s less fiddly, and uses proper types wrapping elapsed times in nanoseconds, which is about as close to the native representations as Ruby gets. You can do maths on them, sleep using them\",\"classification_terms\":[\"projects/monotime\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":2,\"depth\":1},{\"path\":\"/projects/comlim/\",\"status\":200,\"title\":\"Comlim\",\"word_count\":134,\"summary_text\":\"Comlim Comlim hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Comlim Ruby command runner with resource limits [ruby] 2018-08-23 &nbsp; Freaky/comlim on Github Comlim is a command builder for Ruby focusing on an easy interface to restricted execution—limiting memory, runtime, and command output. Runner = Comlim.memory(32.megabytes) .cputime(30.seconds) .runtime(60.seconds) .output(4.kilobytes) RubyRunner = Runner.command(&#39;ruby&#39;).arg(&#39;-e&#39;) RubyRunner.arg(&#39;loop { }&#39;).execute # killed after 30 seconds Notes CPU and memory limits are enforced by the OS via spawn’s rlimit_cpu and rlimit_memory options. Output and runtime limits are enforced by the library, with output collected via non-blocking reads. Unfortunately, there’s no time-limi\",\"classification_terms\":[\"projects/comlim\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/blooming-ruby/\",\"status\":200,\"title\":\"Blooming Ruby\",\"word_count\":251,\"summary_text\":\"Blooming Ruby Blooming Ruby hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Blooming Ruby Prototypical BitArray and BloomFilter library [ruby] 2018-08-10 &nbsp; Freaky/blooming-ruby on Github Yet another Ruby bloom filter, and a new bit array implementation, including a speedy JRuby-specific version. This was extracted from an experiment in leaked password list processing, before I moved on to Golomb Compressed Sets, and might be worth extracting into a proper gem at some point. Synopsis BitArray There’s also a bit_array_jruby which uses java.util.BitSet under the hood. require &#39;blooming/bit_array&#39; # Array of 128 bits ba = Blooming::BitArray.new(128) ba.set!(1).set!(2).flip!(1).flip!(2).none? # true ba.set!(1).set!(2).cardinality # =&gt; 2 ba.set?(1) #\",\"classification_terms\":[\"projects/blooming-ruby\",\"about\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/pkg-cruft/\",\"status\":200,\"title\":\"pkg-cruft\",\"word_count\":179,\"summary_text\":\"pkg-cruft pkg-cruft hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon pkg-cruft Help keep FreeBSD tidy [ruby] [bsd] 2018-08-10 &nbsp; Freaky/pkg-cruft on Github A small Ruby script for helping deal with cruft on pkgng-based systems like FreeBSD. Perhaps most interesting is the implementation of checkrestart, a feature similar to the Debian-goodies program of the same name, which can find running processes which may need restarting following an upgrade. # pkg-cruft checkrestart [MISSING EXECUTABLE] (tmux-2.7)? running as 17319 (tmux) [MISSING EXECUTABLE] (zsh-5.5.1)? running as 20115 (zsh) [MISSING EXECUTABLE] (weechat-2.2)? running as 36747 (weechat) /usr/local/bin/mosh-server (mosh-1.3.2_4) running as 53815 (mosh-server) This is done by parsing procstat -va,\",\"classification_terms\":[\"projects/pkg-cruft\",\"about\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1},{\"path\":\"/projects/reattempt/\",\"status\":200,\"title\":\"Reattempt\",\"word_count\":190,\"summary_text\":\"Reattempt Reattempt hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon Reattempt A jittery Enumerable retry and backoff library [ruby] 2018-07-13 &nbsp; Freaky/ruby-reattempt on Github Reattempt is a simple application of Ruby’s Enumerators to provide a nice idiomatic interface to retries. At its most basic: begin Reattempt::Retry.new.each do poke_remote_api end rescue Reattempt::RetriesExceeded =&gt; e handle_repeated_failure(e.cause) end It’s split into two Enumerables - Retry implements the retrying Exception-catching iterator, while Backoff implements the configurable jittered exponential backoff, allowing the API user to implement sleeping as they see fit: # Start delay 0.075-0.125 seconds, increasing to 0.75-1.25 seconds bo = Reattempt::Backoff.new(min_d\",\"classification_terms\":[\"projects/reattempt\",\"about\",\"api\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":5,\"depth\":1},{\"path\":\"/projects/mkpass/\",\"status\":200,\"title\":\"mkpass\",\"word_count\":180,\"summary_text\":\"mkpass mkpass hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon mkpass Command-line password generation [rust] 2018-05-07 &nbsp; Freaky/mkpass on Github mkpass is a simple command-line random password generator written in Rust, with built-in dictionaries to keep run-time dependencies to an absolute minimum. -% mkpass help mkpass 0.1.0 Thomas Hurst &lt;tom@hur.st&gt; Generate reasonably secure passwords USAGE: mkpass [FLAGS] [OPTIONS] FLAGS: -h, --help Prints help information -V, --version Prints version information -v, --verbose Activate verbose mode OPTIONS: -b, --bits &lt;bits&gt; Password strength target, 2^n [default: 72] -d, --dictionary &lt;dict&gt; Built-in dictionary [default: eff] [possible values: eff, diceware, beale, alpha, mixedalpha, mixedalp\",\"classification_terms\":[\"projects/mkpass\",\"about\",\"help\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":2,\"depth\":1},{\"path\":\"/projects/rtss/\",\"status\":200,\"title\":\"rtss\",\"word_count\":386,\"summary_text\":\"rtss rtss hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon rtss Relative Timestamps for Stuff [rust] 2018-04-27 &nbsp; Freaky/rtss on Github rtss annotates its output with relative durations between consecutive lines and since program start. Inspired by Kevin Burke’s Golang tss, I thought it would be a fun exercise and a nice bit of Rust practice to implement something similar. I’m fairly pleased with the result - it’s considerably faster, running at hundreds of MB per second in my tests - and somewhat more featureful, including pty support, allowing it to work similarly to expect’s unbuffer command. rtss on its own build -% cargo build --release 2&gt;&amp;1 | rtss 274.1ms 274.1ms | Compiling libc v0.2.40 1.50s 1.22s | Compiling memchr v2.0.1 2.28s 780.\",\"classification_terms\":[\"projects/rtss\",\"about\",\"support\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":12,\"depth\":1},{\"path\":\"/projects/bitrw/\",\"status\":200,\"title\":\"bitrw\",\"word_count\":137,\"summary_text\":\"bitrw bitrw hur.st&#x27;s bl.aagh BSD, Ruby, Rust, Rambling About Blog Projects &nbsp; Github Mastodon bitrw Bit-level Rust IO [rust] 2018-04-17 &nbsp; Freaky/rust-bitrw on Github bitrw offers bit-level reading and writing for Rust Read and Write types. It was extracted from my gcstool project. Synopsis extern crate bitrw; use bitrw::{BitReader, BitWriter}; // Something implementing io::Write let buf: Vec&lt;u8&gt; = Vec::new(); let mut writer = BitWriter::new(BufWriter::new(buf)); let mut bits_written = writer.write_bit(0)?; bits_written += writer.write_bits(7, 0b100_0001)?; bits_written += writer.write_bits(2, 0b01)?; bits_written += writer.flush()?; // returns u64 indicating the number of bits of padding. assert_eq!(buf, [0b0100_0001, 0b0100_0000]); // Or io::Read, and optionally io::Seek for\",\"classification_terms\":[\"projects/bitrw\",\"about\",\"returns\",\"blog\"],\"external_refs\":[],\"password_input_count\":0,\"email_input_count\":0,\"tel_input_count\":0,\"otp_term_count\":0,\"login_form_count\":0,\"checkout_form_count\":0,\"wallet_prompt_count\":0,\"offdomain_form_actions\":0,\"suspicious_script_refs_count\":0,\"external_script_hosts\":[],\"executable_download_count\":0,\"archive_download_count\":0,\"apk_download_count\":0,\"phone_number_count\":1,\"depth\":1}]",
        "score_reasons_json": "[]",
        "route_domain": "hur.st",
        "display_domain": "hur.st"
    },
    "explainability": {
        "summary": "hur.st currently scores 64/100. The score is being shaped by a mixed signal profile rather than one dominant factor. Evidence confidence is strong enough for a relatively stable read. This is an estimated profile rather than a manually tracked one. Crawler access looks clean.",
        "badges": [
            {
                "label": "Profile",
                "value": "Estimated profile",
                "tone": "unknown",
                "detail": null
            },
            {
                "label": "Evidence confidence",
                "value": "High confidence",
                "tone": "good",
                "detail": "100/100"
            },
            {
                "label": "Traffic confidence",
                "value": "Moderate confidence",
                "tone": "caution",
                "detail": "52/100"
            },
            {
                "label": "Crawler access",
                "value": "Clean visibility",
                "tone": "good",
                "detail": null
            }
        ],
        "weighted_contributions": [
            {
                "label": "Quality system",
                "points": "+32.0",
                "tone": "good",
                "detail": "Technical quality, crawl depth, page structure, and implementation hygiene. Current subsystem score: 94/100."
            },
            {
                "label": "Reputation system",
                "points": "+12.6",
                "tone": "risk",
                "detail": "Authority, search visibility, reach, engagement, and registry stability. Current subsystem score: 37/100."
            },
            {
                "label": "Safety system",
                "points": "+32.0",
                "tone": "good",
                "detail": "Fraud, spam, and trust signals from infrastructure, crawl, and registry evidence. Current subsystem score: 100/100."
            },
            {
                "label": "Risk clamp",
                "points": "-13.0",
                "tone": "risk",
                "detail": "Safety thresholds capped the final score until the risk profile improves."
            }
        ],
        "evidence_cards": [
            {
                "label": "Authority and trust",
                "value": "28/100 · trust 75/100",
                "tone": "caution",
                "detail": "131 monthly visitors, 56 organic keywords, brand completeness 63/100, engagement 80/100."
            },
            {
                "label": "Backlink and search evidence",
                "value": "1 referring domains",
                "tone": "good",
                "detail": "1 backlinks across 1 referring domains. Diversity 92/100; spam penalty 0."
            },
            {
                "label": "Registry and domain stability",
                "value": "0.0 years old",
                "tone": "good",
                "detail": "Stability 100/100 · age 0.0 years."
            },
            {
                "label": "Safety and fraud posture",
                "value": "Safety 100/100 · fraud 0/100",
                "tone": "good",
                "detail": "Primary tag T · safety 100/100 · fraud 0/100."
            }
        ],
        "positives": [
            "Low registrar / ownership churn with solid registry stability.",
            "Healthy crawl quality and on-page completeness.",
            "Registry history looks stable, which supports legitimacy and trust.",
            "HTTPS is working, so the site clears a basic transport-security check.",
            "Backlink diversity looks broad enough to strengthen authority confidence."
        ],
        "risks": [],
        "freshness": [
            {
                "label": "Crawl evidence",
                "value": "2026-03-20 20:18:57",
                "tone": "risk",
                "detail": "Crawl and page content sample. Age: 29d ago."
            },
            {
                "label": "WHOIS snapshot",
                "value": "2026-03-20 20:18:55",
                "tone": "risk",
                "detail": "Registry profile and stability signals. Age: 29d ago."
            },
            {
                "label": "Keyword view",
                "value": "2026-04-19 11:50:04",
                "tone": "good",
                "detail": "Estimated visibility until tracked keyword snapshots exist. Age: 0s ago."
            },
            {
                "label": "Rank history",
                "value": "2026-04-19 11:50:04",
                "tone": "good",
                "detail": "Estimated trend derived from current profile and crawl signals. Age: 0s ago."
            },
            {
                "label": "Audience geography",
                "value": "Not captured yet",
                "tone": "unknown",
                "detail": "Audience mix is estimated from available signals rather than first-party audience logs."
            }
        ],
        "section_notes": {
            "audience": "Audience geography is estimated from category, country, traffic mix, and brand signals until first-party audience data is collected.",
            "keywords": "Top keywords are estimated from crawl language, brand, category, and visibility signals until tracked keyword snapshots are stored.",
            "history": "Rank history is estimated from the current profile because no stored history exists for this domain yet."
        },
        "base_weighted_score": 77,
        "fraud_clamp_penalty": 13,
        "final_score": 64
    },
    "insight_snapshot": {
        "version": 1,
        "generated_at": "2026-04-19T11:50:04+00:00",
        "domain": "hur.st",
        "display_name": "hur.st's bl.aagh",
        "is_tracked": false,
        "is_estimated": true,
        "overall_score": 64,
        "authority_score": 28,
        "trust_score": 75,
        "safety_score": 100,
        "fraud_score": 0,
        "confidence_score": 100,
        "traffic_confidence": 52,
        "last_crawled_at": "2026-03-20 20:18:57",
        "crawl_blocked": false,
        "summary": "hur.st currently scores 64/100. The score is being shaped by a mixed signal profile rather than one dominant factor. Evidence confidence is strong enough for a relatively stable read. This is an estimated profile rather than a manually tracked one. Crawler access looks clean.",
        "badges": [
            {
                "label": "Profile",
                "value": "Estimated profile",
                "tone": "unknown",
                "detail": null
            },
            {
                "label": "Evidence confidence",
                "value": "High confidence",
                "tone": "good",
                "detail": "100/100"
            },
            {
                "label": "Traffic confidence",
                "value": "Moderate confidence",
                "tone": "caution",
                "detail": "52/100"
            },
            {
                "label": "Crawler access",
                "value": "Clean visibility",
                "tone": "good",
                "detail": null
            }
        ],
        "top_positive_signals": [
            "Low registrar / ownership churn with solid registry stability.",
            "Healthy crawl quality and on-page completeness.",
            "Registry history looks stable, which supports legitimacy and trust.",
            "HTTPS is working, so the site clears a basic transport-security check.",
            "Backlink diversity looks broad enough to strengthen authority confidence."
        ],
        "top_risk_signals": [],
        "freshness": [
            {
                "label": "Crawl evidence",
                "value": "2026-03-20 20:18:57",
                "tone": "risk",
                "detail": "Crawl and page content sample. Age: 29d ago."
            },
            {
                "label": "WHOIS snapshot",
                "value": "2026-03-20 20:18:55",
                "tone": "risk",
                "detail": "Registry profile and stability signals. Age: 29d ago."
            },
            {
                "label": "Keyword view",
                "value": "2026-04-19 11:50:04",
                "tone": "good",
                "detail": "Estimated visibility until tracked keyword snapshots exist. Age: 0s ago."
            },
            {
                "label": "Rank history",
                "value": "2026-04-19 11:50:04",
                "tone": "good",
                "detail": "Estimated trend derived from current profile and crawl signals. Age: 0s ago."
            },
            {
                "label": "Audience geography",
                "value": "Not captured yet",
                "tone": "unknown",
                "detail": "Audience mix is estimated from available signals rather than first-party audience logs."
            }
        ],
        "top_tags": [
            {
                "code": "T",
                "label": "Trusted",
                "tone": "good"
            }
        ]
    },
    "is_tracked": false,
    "is_estimated": true,
    "live_state": {
        "status": "processing",
        "status_label": "Cache build running",
        "message": "The refreshed page cache is still being built for this domain.",
        "updated_at": "2026-04-19T14:41:54+00:00"
    },
    "refresh_state": {
        "canRequest": false,
        "queued": true,
        "processing": true,
        "stageKey": "cache-queued",
        "stageLabel": "Cache build running",
        "cooldownUntil": null,
        "message": "The refreshed page cache is still being built for this domain.",
        "action": "/domain/hur.st/refresh",
        "isGuestCooldown": false,
        "cooldownSeconds": 0
    },
    "urlscan_report": {
        "domain": "hur.st",
        "status": "idle",
        "submitted_at": null,
        "completed_at": null,
        "last_checked_at": null,
        "last_error": "",
        "submitted_url": "https://hur.st/",
        "uuid": "",
        "result_url": "",
        "api_result_url": "",
        "visibility": "public",
        "summary": "No urlscan.io report has been requested for this domain yet.",
        "report": [],
        "report_summary": [],
        "is_fresh": false,
        "can_retry": true,
        "poll_after_seconds": 20
    }
}