Aspect404_
I enjoy pushing the limits of what I can design and finding creative ways to bend video games and software to my will, just living one day at a time!
Explore
- aboutWho I am and what I work on.
- blogPosts about my projects.
- linksWhere to find me elsewhere.
- pgpMy public key, for encrypted mail.
Elsewhere
Legal
About
Who I am and what I work on.
#Now
Hey, I'm Ethan, and I enjoy programming! I'm also known by my internet username of Aspect404_, and I live in central Michigan. I currently work at Vantage Plastics as a thermoforming machine operator. That's just nerd speak, which means I run machines that heat up plastic sheets and mold them into parts such as automotive component trays. Outside of work, I have a lot of random hobbies, mainly programming, which you can read more about below if you're interested. I also love playing games such as Minecraft, Rocket League, Bloons TD 6, and Arma 3. I love computers; Nova, my main build, has a 9950X3D, 192GiB of memory, the ROG Astral LC RTX 5090 OC Edition GPU, and over 20TiB of SSDs... Don't even get me started on Navi or Luna... Also, I use Arch Linux btw. This website isn't done yet, lol. I have other projects to work on; I just figured I should deploy it. Thanks for reading my yapping, and take care! <3
#Background
const experienceLevels = {
"Beginner": 0, "Moderate": 1, "Experienced": 2, "Professional": 3
} as const;
type ExperienceLevel = (keyof typeof experienceLevels);
type ProgrammingLanguage = {
name: string;
experience: ExperienceLevel;
startedAt: number;
endedAt?: number;
};
const programmingLanguages: Array<ProgrammingLanguage> = [
// I loved hacking Flash games.
{ name: "ActionScript", experience: "Moderate", startedAt: 2017, endedAt: 2019 },
// Until the day Minecraft truly dies.
{ name: "Java", experience: "Professional", startedAt: 2019 },
// I don't use Windows anymore.
{ name: "PowerShell", experience: "Beginner", startedAt: 2019, endedAt: 2023 },
// Started during my teenage "I'm a hacker" phase.
{ name: "Python", experience: "Moderate", startedAt: 2020, endedAt: 2023 },
// "having an affair with typescript rn" - 4/4/24, 20:15
{ name: "JavaScript", experience: "Professional", startedAt: 2020, endedAt: 2024 },
// Tried a different language for the JVM.
{ name: "Kotlin", experience: "Beginner", startedAt: 2022, endedAt: 2022 },
// And formerly Zsh as my default shell.
{ name: "Bash", experience: "Experienced", startedAt: 2022 },
// I was trying native languages.
{ name: "C++", experience: "Moderate", startedAt: 2023, endedAt: 2024 },
// Amazing while I was learning.
{ name: "Zig", experience: "Beginner", startedAt: 2024, endedAt: 2024 },
// I don't care for static linking.
{ name: "Rust", experience: "Moderate", startedAt: 2024 },
// The love of my life.
{ name: "TypeScript", experience: "Professional", startedAt: 2024 },
] as const;
#Get in touch
The best ways to reach me are on the links page. For anything sensitive, use my PGP key.
Blog
Posts and updates, newest first.
Links
Where to find me elsewhere.
Licenses
Licenses for this site and the software it runs on.
#This site
- Text & content
All rights reserved- Source code
All rights reserved- Version
aspect404.dev 4.6.5
The page layout, styles, scripts and icons were written for this site. No web fonts, icon packs or front-end libraries are used.
#Third-party software
Three Rust programs run on one server for this site: the application server, aspect.host, and a router that handles HTTPS and certificates. Their source code is not public: all rights reserved, as for this site's text. Below, the crates compiled into each program are listed the way its Cargo.toml names them: what a crate is used for above it, its license (SPDX) after it.
#aspect404.dev
The application server behind this site.
[dependencies]
# HTTP routing and handlers
axum = "0.8" # MIT
# Async runtime, networking, timers
tokio = "1" # MIT
# HTTP/1.1 connection handling and timeouts
hyper = "1" # MIT
# Service glue between hyper and axum
tower-service = "0.3" # MIT
# Own code, shared with the router and aspect.host: Unix socket server and the router's visitor headers
router-ipc = "0.3" # All rights reserved
# Own code, shared with aspect.host: storing the files I share there
aspecthost-store = "0.1" # All rights reserved
# rPGP: OpenPGP encryption of security codes
pgp = "0.20" # MIT OR Apache-2.0
# Serialization framework
serde = "1" # MIT OR Apache-2.0
# JSON API
serde_json = "1" # MIT OR Apache-2.0
# SHA-256 for ETags, CSP hashes, and session and upload tokens
sha2 = "0.10" # MIT OR Apache-2.0
# Base64 and base64url encoding
base64 = "0.22" # MIT OR Apache-2.0
# Constant-time comparison
subtle = "2" # BSD-3-Clause
# Secure random codes and tokens
rand = "0.8" # MIT OR Apache-2.0
# QR codes for pairing the admin phone bridge
qrcodegen = "1.8" # MIT
# Error handling
anyhow = "1" # MIT OR Apache-2.0
# Safe system calls: suspend-aware clock, free disk space, opening files without following links, process limits
rustix = "1" # Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT
# Memory allocator: Microsoft's mimalloc C library, linked statically
mimalloc = "0.1" # MIT
[toolchain]
# The C standard library, linked statically
musl = "1.2.5" # MIT
# The Rust standard library: everything else
rust-std = "1.95" # MIT OR Apache-2.0
Together they pull in 182 third-party crates (cargo tree -e normal in its directory). Most are dual-licensed MIT OR Apache-2.0; the rest use MIT, Apache-2.0 (sync_wrapper), Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT (rustix and linux-raw-sys), BSD-3-Clause, Unlicense OR MIT, Zlib or Unicode-3.0.
#aspect.host
Where I share files: a separate program on the same server.
[dependencies]
# Async runtime, Unix socket, timers
tokio = "1" # MIT
# HTTP/1.1 connection handling and timeouts
hyper = "1" # MIT
# Own code, shared with the router and aspect404.dev: Unix socket server and the router's visitor headers
router-ipc = "0.3" # All rights reserved
# Own code, shared with aspect404.dev: reading the stored files
aspecthost-store = "0.1" # All rights reserved
# Safe system calls: opening stored files without following links, process limits
rustix = "1" # Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT
# SHA-256 for the CSP hashes of its pages
sha2 = "0.10" # MIT OR Apache-2.0
# Base64 encoding of those hashes
base64 = "0.22" # MIT OR Apache-2.0
# Memory allocator: Microsoft's mimalloc C library, linked statically
mimalloc = "0.1" # MIT
[toolchain]
# The C standard library, linked statically
musl = "1.2.5" # MIT
# The Rust standard library: everything else
rust-std = "1.95" # MIT OR Apache-2.0
Together they pull in 33 third-party crates (cargo tree -e normal in its directory). All are licensed MIT, MIT OR Apache-2.0 or, for rustix and linux-raw-sys, Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT.
The files shared there are not covered by this page: unless a file says otherwise, all rights stay with me or with the file's author.
#TLS router
Accepts HTTPS connections to both sites, obtains their certificates from Let's Encrypt and passes each request on. Its direct dependencies are listed, plus the AWS-LC cryptography library and the HTTP/2 implementation they use.
[dependencies]
# TLS 1.2 and 1.3
rustls = "0.23" # Apache-2.0 OR ISC OR MIT
# TLS on async sockets
tokio-rustls = "0.26" # MIT OR Apache-2.0
# Cryptography, including post-quantum key exchange
aws-lc-rs = "1.18" # ISC AND (Apache-2.0 OR ISC)
# The AWS-LC cryptography library (through aws-lc-rs)
aws-lc-sys = "0.45" # ISC AND (Apache-2.0 OR ISC) AND Apache-2.0 AND MIT AND BSD-3-Clause AND (Apache-2.0 OR ISC OR MIT) AND (Apache-2.0 OR ISC OR MIT-0)
# Certificates from Let's Encrypt (ACME)
instant-acme = "0.8" # Apache-2.0
# Certificate keys, signing requests and challenge certificates
rcgen = "0.14" # MIT OR Apache-2.0
# Async runtime, networking, timers
tokio = "1" # MIT
# HTTP/1.1 and HTTP/2 with visitors, requests to the sites, port 80 redirects and the ACME client
hyper = "1" # MIT
# HTTP/2 (through hyper)
h2 = "0.4" # MIT
# Tokio I/O and timer adapters for hyper
hyper-util = "0.1" # MIT
# Size limits on ACME responses
http-body-util = "0.1" # MIT
# Byte buffers
bytes = "1" # MIT
# Brotli compression of pages and of the certificate chain
brotli = "9" # BSD-3-Clause AND MIT
# gzip compression of pages, for browsers without Brotli
flate2 = "1" # MIT OR Apache-2.0
# Own code, shared with the sites: visitor headers, host checks and client limits
router-ipc = "0.3" # All rights reserved
# Serialization framework
serde = "1" # MIT OR Apache-2.0
# Account and state files
serde_json = "1" # MIT OR Apache-2.0
# Certificate dates and renewal times
time = "0.3" # MIT OR Apache-2.0
# Error handling
anyhow = "1" # MIT OR Apache-2.0
# Safe system calls: opening key, state and configuration files, process limits
rustix = "1" # Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT
[toolchain]
# The Rust standard library: everything else
rust-std = "1.95" # MIT OR Apache-2.0
Together they pull in 78 third-party crates (cargo tree -e normal in its directory). Most are dual-licensed MIT OR Apache-2.0; the rest use MIT, Apache-2.0 (instant-acme), ISC, Apache-2.0 OR ISC OR MIT, Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT (rustix and linux-raw-sys), BSD-3-Clause, BSD-3-Clause AND MIT (brotli), BSD-3-Clause OR MIT (brotli-decompressor), Unlicense OR MIT, Zlib (zlib-rs), Unicode-3.0 or the AWS-LC licenses above.
The full list of transitive dependencies and their license texts is available on request at legal@aspect404.dev.
Privacy
This site does not track you.
#In short
- No analytics, trackers, ads, fingerprinting or embeds, and no requests to anyone else.
- No access logs: your IP address, browser and the pages you view are not recorded.
- No browser storage, and no cookies unless you sign in as the admin.
- JavaScript is optional for visitors.
#Hosting
The site runs on a Hetzner server, which may keep connection data to prevent network abuse. HTTPS is handled by the site's own router with Let's Encrypt certificates. While you are connected, your IP address is held in memory to limit connections per address; it is never written to disk. Public pages may be kept compressed in memory to answer faster.
#aspect.host
aspect.host, where I share files, works the same way: no cookies, no browser storage, no analytics and no access logs. Only I upload files there; with each file it keeps its name, size, upload time and media details until I delete it. Chat apps such as Discord fetch a link's preview and may keep a copy under their own privacy policies.
#Cookies
Two strictly necessary cookies are set only when someone uses the admin sign-in:
| Name | Purpose | Lifetime |
|---|---|---|
__Host-challenge | Links a pending security code to your browser during sign-in. | 5 minutes, or until used |
__Host-session | Keeps the site owner signed in. | Until sign-out, 5 minutes of inactivity, or closing the browser |
Both are HttpOnly, SameSite=Strict and Secure, and what they refer to lives only in the server's memory. A sign-in request's IP address is kept in memory for up to 5 minutes to rate-limit attempts.
#Contact
Questions about your data: legal@aspect404.dev (encrypted mail welcome, see PGP).
Last updated: Wednesday, October 7th, 2026
Terms
The short, friendly terms for using this site.
#Using this site
You may read, link to and share pages from this site. Please don't try to disrupt it, overload it, or get into the admin area without permission.
#Content
Unless stated otherwise, the rights to this site's content are described on the licenses page. Third-party names and trademarks belong to their owners.
#No warranty
Everything here is provided "as is", without warranty of any kind. Opinions are my own and may be out of date. To the extent permitted by law, I am not liable for any loss arising from use of this site.
#External links
Links to other sites are provided for convenience; I am not responsible for their content or their privacy practices.
#Changes
These terms may change; the date below shows the latest revision.
#Governing law & contact
These terms are governed by the laws of the State of Michigan, USA. Questions: legal@aspect404.dev.
Last updated: Monday, September 28th, 2026
PGP key
Use this key to send me encrypted mail or to verify things I have signed.
#Import
curl -s https://aspect404.dev/pgp.asc | gpg --importThen compare the output of gpg --fingerprint with the fingerprint listed in the key below.
#Public key
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: User ID: Aspect404_ (25-28) <admin@aspect404.dev>
Comment: Valid from: 1/1/25 12:00AM
Comment: Valid until: 1/1/28 12:00PM
Comment: Type: 255-bit EdDSA (secret key available)
Comment: Usage: Signing, Encryption, Certifying User IDs, SSH Authentication
Comment: Fingerprint: 6431 CB61 EFB5 7AA5 671D F86F FDC7 66C2 0176 D321
mDMEZ3TL0BYJKwYBBAHaRw8BAQdA80Rp/fG6rB+OQnr7OzmjCQOQql8X0/GU4sMF
1+3wl6m0KEFzcGVjdDQwNF8gKDI1LTI4KSA8YWRtaW5AYXNwZWN0NDA0LmRldj6I
lgQTFgoAPhYhBGQxy2HvtXqlZx34b/3HZsIBdtMhBQJndMvQAhsBBQkFpENABQsJ
CAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJEP3HZsIBdtMhMbYA/j5ghdkxgjZ+u7FM
M8XAMr95zs9bQ/rWOiBZ7Z5XPWjKAQCC66scGCTbEOo9RNQqmKnA7TLYc9whnARE
0HRpAJYXCrg4BGd0y9ASCisGAQQBl1UBBQEBB0BG5Ozw6CI20bO2WCZlS8CvFnks
HK9yLeX5R3qZ1px0XQMBCAeIfgQYFgoAJhYhBGQxy2HvtXqlZx34b/3HZsIBdtMh
BQJndMvQAhsMBQkFpENAAAoJEP3HZsIBdtMhHogA/122SD8r4o92WbTUF/gXK5sk
fq6emd2TjtOeYGI5RRs7AP92UT0WPUea3VLliYPkYsU5P2dhVMb8ZD+ZmECs9wRV
BrgzBGd0y9AWCSsGAQQB2kcPAQEHQBkG8WWU6vFdwIAwOpp7dpwQRZVRrwl+IRSp
H9Mfl62piPUEGBYKACYWIQRkMcth77V6pWcd+G/9x2bCAXbTIQUCZ3TL0AIbAgUJ
BaRDQACBCRD9x2bCAXbTIXYgBBkWCgAdFiEEzmMYAKYGkEj+lyTSg4iZFl8GzPcF
Amd0y9AACgkQg4iZFl8GzPdzKQEA4tqZ/IVhhTV6afkytyHbg2n8ZHnfXBqZW/ef
XyCtuXoBAPqO7+JdRPTi1idL61nwKnDuIfKuATXnnNSQwFdYGoYLiT0BAPNxD661
eCnxFLodX/Su/ZSBvPqLX40TxPp6W2xs6b0hAP9y106T+oFczeWhW1R1qj10hXi2
dvKdySqOIVireaN0DbgzBGd0y9AWCSsGAQQB2kcPAQEHQDIMj8bB+JLC6U7bcSvj
1Lv6b2Ga4Dl+L2Y/L12sw2GxiH4EGBYKACYWIQRkMcth77V6pWcd+G/9x2bCAXbT
IQUCZ3TL0AIbIAUJBaRDQAAKCRD9x2bCAXbTIc0tAQDUIXFfk6Kmd8SGX7kYgw1u
9LVlt6hJx+Q96alDTvAf6QD+MERAqzsk+b/MGDR4/9g1e6cKDuiy6abdHocSOS0f
Kgc=
=puok
-----END PGP PUBLIC KEY BLOCK-----
Key not published yet. The public key will appear here once it is ready. Until then, admin sign-in is disabled.
Admin
Sign in to the admin panel
There are no passwords here. The server encrypts a one-time security code to the published PGP key, so only the holder of the matching private key can read it. Sessions end after 5 minutes of inactivity; see cookies.
Admin sign-in is disabled because no PGP key has been published yet.
Admin sign-in requires JavaScript.
-
Request security code
Generate a fresh encrypted security code, valid for 5 minutes.
-
Enter security code
Page not found
There is nothing at this path. It may have been moved, renamed or deleted.
404 Not Found