the metadata engine, six languages in one day
XIFtySense org created April 16. Day one: a Rust core plus Node, C++, Rust, Go, Python, and Swift bindings — all at v0.1.x, all shipping the same metadata model.
XIFty launched April 17 with seven repos under a fresh GitHub org — and six language bindings all shipping the same metadata model on day one. The shape of the launch tells you what the project is for: a single Rust core that downstream consumers can reach from Node, C++, Rust, Go, Python, or Swift without picking a side.
Why the wide bindings on launch day
The conventional wisdom is start with one language, prove the API, then port. XIFty inverted that because the wedge isn’t “developers who want metadata in Rust.” The wedge is creators and storage providers whose stacks are already polyglot — a Node API, a Swift macOS client, a Python upload pipeline, a Go CDN edge worker all touching the same media file and all needing to agree on what’s inside it. Day one needed parity across the surfaces those consumers actually live in.
The architecture made it cheap. The Rust core (XIFty) is the only place that knows how to parse anything; every binding is a thin FFI wrapper around the same xifty_extract_json C ABI. Adding a binding is hours, not weeks. Shipping six on the same day stops the “is this a real project or a hobby?” question before it gets asked.
What v0.1.x meant on day one
The day-one releases (XIFty core v0.1.2 → v0.1.5, XIFtyNode v0.1.0 → v0.1.7, bindings at v0.1.2 → v0.1.3) weren’t a single big-bang push — they were rapid iteration on the contract during the same afternoon. Each patch tightened the FFI shape so the bindings could pin against a stable API. By end-of-day every binding was building against the same minor version.
The schema-policy bet
docs/SCHEMA_POLICY.md declares an additive-only policy at schema_version: 0.1.0: new containers, new namespaces, new fields are fine; renaming or deleting is not. This is what lets the bindings stay in sync without coordination drama — a downstream Swift consumer doesn’t need to know that the Rust core gained a new container last week, as long as the fields they already read are untouched. Every release for the next three weeks held the line.
What’s actually parsed on day one
Day-one format coverage: JPEG, PNG, HEIF, MP4, MOV — the formats most consumer-facing image and video pipelines actually touch. Surfaces EXIF, XMP, ICC, IPTC, and container-level metadata in a normalized field model alongside raw vendor namespaces. The normalized fields (captured_at, dimensions, gps.*, etc.) let downstream consumers ignore container-specific quirks; the namespaces let advanced consumers read the original vendor data when they need it.
Why this matters for log readers
XIFty is a foundational primitive for the rest of the work that’s coming through this log. Khaos storage uses it to inspect uploads. The downstream provenance and AI-disclosure features (May 3 release wave) build on this core. Every time you see a media file with an ai_generated, c2pa, or sidecar field surfaced anywhere in the stack, that path eventually lands at xifty_extract_json in this core.
The wedge: a stable, polyglot, additive-only metadata contract for media that the rest of the agency can build on without forking. Three weeks of further work would show what that wedge unlocks.