Releases: necrometer-dev/necrometer
Release list
v0.4.8
v0.4.7
v0.4.7: gauge sits on the top semicircle
v0.4.6
v0.4.6: serve in the image, 3000-repo walk, honest 403/429, org kind Container builds with --features serve. Native pagination matches the site. Rate limits are not "no such user". Org vs user from GET /users. Nameplate is @user, not @@user.
v0.4.5
v0.4.5: rustls 0.23.45 (RUSTSEC-2026-0285), unbreak CI - rustls 0.23.44 → 0.23.45 (TLS 1.3 handshake advisory) - CI wasm smoke was invalid YAML so GitHub never started jobs - cargo-deny actually runs; wasm job no longer depends on a missing PAT
v0.4.4
v0.4.4: kind arg + slim projection for large orgs + Docker rename fix
v0.4.3
v0.4.3: ship wasm-bindgen snippets in pkg/
v0.4.2
Highlights
The engine crate is now named seance. The binary, the GitHub
release asset, the wasm package, and the docker image are all
seance. The product on the website stays Necrometer — the
"seance" is the act of communing with your dead repos.
What's in this release
Renamed:
- Crate
necrometer→seance(Cargo.toml[package].name,
[lib].name,[[bin]].name). - CLI binary
necrometer→seance—./seance card torvalds necrometer.svg. - GitHub release asset
necrometer-x86_64-unknown-linux-musl.tar.gz
→seance-x86_64-unknown-linux-musl.tar.gz. - wasm-pack package name
necrometer→seance(.wasm-pack.toml). - Wasm artifacts
pkg/necrometer.js+pkg/necrometer_bg.wasm+
pkg/necrometer.d.ts+pkg/necrometer_bg.wasm.d.ts→
pkg/seance.js+pkg/seance_bg.wasm+pkg/seance.d.ts+
pkg/seance_bg.wasm.d.ts. - CLI usage strings:
seance serve | seance card <name> [out.svg] | seance hall <names> [out.json].
Kept (intentional):
- The product name on
necrometer.devstaysNecrometer. - The GitHub org/repo names stay
necrometer-dev/...— those are
not renamed. - The action (
necrometer-dev/necrometer-action) keeps its name —
consumers depend onuses: necrometer-dev/necrometer-action@v1. - The card output file stays
necrometer.svg— that's what
README badges link to.
Required consumer changes:
- Workflows calling the action: no change — the action now points
atv0.4.2by default and downloadsseance-*.tar.gz
automatically. - Sites embedding the wasm: update import paths
import init from './pkg/seance.js',
await init('./pkg/seance_bg.wasm'). - Anyone consuming the release artifact directly: switch to
seance-x86_64-unknown-linux-musl.tar.gz.
Internal cleanups
src/time.rs:SystemTimeimport is#[cfg(not(target_arch = "wasm32"))]— wasm builds cleanly without it..wasm-pack.toml: new file documenting the wasm-pack package name
(was previously implicit inwasm-pack builddefaults).
Verification
cargo test --lib → 47 passed
cargo clippy ... -- -D warnings → clean
cargo fmt --all -- --check → clean
cargo build --bin seance → ok
cargo build --bin seance --features serve → ok
cargo build --lib --target wasm32-unknown-unknown → ok
wasm-pack build --release --target web ... → ok
node smoke test → reading=354 svg=44590
v0.4.1
Highlights
A pure quality pass — no behavioural changes. Every module now lints
clean under cargo clippy --all-targets --all-features -- -D warnings,
formats clean under cargo fmt --all -- --check, and the 47-test
suite passes on native + wasm.
What's in this release
style: rustfmt-sweep across all 33 modules, 672 lines rewrappedstyle: drop redundantas i64casts intime.rsstyle: collapse nested-if inweb/mod.rsrate-limit gatestyle: remove unuseddrop(tls)anduse super::*in testsstyle: use range-contains instead of open comparisons intime.rs
Verification
cargo test --lib → 47 passed, 0 failed
cargo clippy ... -D warnings → clean
cargo fmt --all -- --check → clean
wasm-pack build --release → 44801-byte SVG output
v0.4.0
Highlights
The engine now has proper CI: every push runs cargo fmt --check,
cargo clippy -D warnings, the 47-test suite, a musl static build, and
a wasm smoke test. A weekly audit runs cargo audit + cargo deny.
The Docker image is reproducible (cargo-chef cache layer,
SOURCE_DATE_EPOCH honoured, dead chown -R removed) and the repo
has CODEOWNERS + CONTRIBUTING.md + SECURITY.md.
What's in this release
CI (ci.yml): cargo fmt --check, cargo clippy -D warnings,
cargo test --lib, musl build with clux/muslrust:stable, wasm smoke
test that decodes analyze_repos + render_card outputs and asserts
sizes are sane.
Audit (audit.yml): weekly cargo audit + cargo deny check,
fails on unknown registries or yanked crates.
Wasm auto-PR (wasm.yml): when src/** or Cargo.toml change,
rebuild pkg/ and open a PR into necrometer-dev.github.io. Uses
the org-bot push-to-fork so consumers don't need to wire up a PAT.
deny.toml: unknown registries = deny, unknown git = deny,
wildcards = deny. License allowlist covers every transitive dep.
Docker: two-stage clux/muslrust:stable → alpine:3.20 with a
cargo-chef planner+cook+build pipeline (only the cook layer
invalidates when Cargo.lock changes). SOURCE_DATE_EPOCH honoured.
Dead chown -R /app in entrypoint.sh removed (the runtime image
doesn't mount /app as a user-writable volume).
Governance: .github/CODEOWNERS requires @UberMetroid review on
every file. CONTRIBUTING.md documents the project principles (zero
deps, 256-line ceiling, zero-trust), layout, build commands, and the
version-bump procedure. SECURITY.md documents the threat model,
supported versions, mitigations list, and security@necrometer.dev
as the reporting address.
Verification
cargo test --lib → 47 passed, 0 failed
cargo clippy ... -D warnings → clean
cargo fmt --all -- --check → clean
musl build → static binary passes
wasm-pack build --release → 44801-byte SVG output
v0.3.0
Highlights
A from-the-ground-up rewrite. The engine now compiles cleanly to
three targets (native CLI, wasm, HTTP server) from one codebase,
ships with 47 unit tests, and respects the 256-line ceiling —
the largest file is src/time.rs at 241 lines.
The dependency tree went from ~190 transitive crates down to a
handful. Removed: serde, serde_json, chrono, anyhow,
reqwest, axum, maud, tracing, tokio, mimalloc, tower,
http-body, http, hyper, h2, bytes. Kept: rustls,
webpki-roots, wasm-bindgen, js-sys. No new deps.
What's in this release
Hand-rolled from first principles:
src/json/— recursive-descent JSON parser + serializer
(replacesserde_json)src/time.rs— RFC 3339 parser, proleptic Gregorian calendar,
unix epoch math (replaceschrono)src/http.rs+src/http_server.rs— rustls HTTPS client +
blocking HTTP/1.1 server with token-bucket rate limiter and
per-IP state (replacesreqwest+axum)src/escape.rs— SVG / URL / subject validation (replaces
maud)src/error.rs— flatErrorenum withResultalias
(replacesanyhow)src/web/— four files:mod.rs(router),headers.rs
(CSP/security headers),pages.rs(HTML),css.rs(styles)
Module split — every file ≤ 241 lines:
| Module | Largest file | Lines |
|---|---|---|
card/ (11 files) |
graveyard.rs |
121 |
metrics/ (4 files) |
analyze.rs |
153 |
web/ (4 files) |
pages.rs |
132 |
github/ (3 files) |
client.rs |
156 |
json/ (2 files) |
parser.rs |
213 |
Native → wasm portability fix:
Utc::now() previously panicked on wasm32-unknown-unknown because
it goes through SystemTime::now(). The wasm path now uses a
#[wasm_bindgen] extern "C" { fn wasm_clock_secs() -> f64; } import
that JS supplies via Date.now() / 1000.
Security headers (in web/headers.rs):
X-Content-Type-Options: nosniffReferrer-Policy: no-referrerX-Frame-Options: DENYContent-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; connect-src https://api.github.com; img-src 'self' data:; font-src 'self'
Test coverage: 47 unit tests covering JSON parsing, RFC 3339
roundtripping, HSL→hex, fate thresholds, SVG element presence,
easter-egg rendering, XML escaping (XSS guard), and end-to-end
HTTP server loopback.
Verification
cargo test --lib → 47 passed, 0 failed
cargo clippy ... -D warnings → clean
cargo fmt --all -- --check → clean
wasm-pack build --release → 44801-byte SVG output
cargo tree --edges normal → 4 runtime deps (rustls,
webpki-roots, wasm-bindgen, js-sys)