Thanks for your interest. This project is small and evolving quickly, so contribution guidelines are intentionally light — but a few practices keep the repo healthy.
Before opening a pull request, run:
tools/quality.shThe script runs fmt, clippy, rustdoc, tests, and any installed supply-chain
tools. cargo-audit and cargo-deny are optional locally but enforced in CI;
set RVT_REQUIRE_AUDIT=1 or RVT_REQUIRE_DENY=1 when you want missing tools to
fail locally too.
Supply-chain rules for Rust crates, viewer npm dependencies, advisory ignores,
and GitHub Actions pinning are documented in
docs/supply-chain-policy.md.
- Bug reports with a minimal reproducer (the smallest
.rfaor.rvtthat triggers the issue). Security-sensitive reports go throughSECURITY.md, not public issues. - Performance regressions caught by the benchmark harness in
tools/bench.sh— open an issue with a before/after table. - New FACTs about the file format. The reconnaissance report in
docs/rvt-moat-break-reconnaissance.mdis the canonical place for dated findings. Please mirror any new finding there AND as a reproducible probe underexamples/. - Documentation improvements. The README and inline doc comments are fair game.
- Tests. More coverage is always welcome, especially for edge-case file layouts.
Current shipped surface (as of April 2026 / post-Phase-5a):
- 395 classes · 13,570 fields · 100% type classification
- 80 typed element decoders (every major element class:
walls, floors, roofs, ceilings, doors, windows, columns, beams,
stairs, railings, rooms, furniture, 11 MEP classes, annotations,
parameters — see
src/elements/mod.rs'sall_decoders()for the full list). - Schema-directed ADocument walker across all 11 releases
(fully on 2024-2026; graceful
Decoded::partialon 2016-2023). - Full IFC4 STEP export (
rvt-ifc input.rfa input.ifc): spatial hierarchy + per-element entities + 8 IfcProfileDef subclasses (IFC-24) + extruded / revolved / boolean / faceted-brep / swept- path solids (IFC-16/17/18/19/20) + material layer sets + material profile sets + property sets + opening/fill rels + IfcMember secondary-member routing + IfcRepresentationMap shared geometry (IFC-21) + ForgeUnit → IfcSIUnit/IfcConversionBasedUnit (IFC-39/40). - Three-layer validation CI on every commit: ifc-smoke
(substring counts) + IfcOpenShell (spec-level parse) + 382+
lib tests (per-feature coverage). See
docs/validation-evidence.md. - Python bindings:
pip install rvt(pyo3 + maturin wheel, abi3-py38, one per OS/arch). - Parameter system:
ParameterElement+SharedParameterdefinitions, AProperty* value-carrier decoders (L5B-54), typedParameterValueenum, type-instance inheritance resolution (L5B-55), calculated/reporting flag detection (L5B-56).
Most wanted right now:
-
§L5B-11 — extend walker to Revit 2016–2023. Walker finds entry points across all 11 releases but fully decodes ADocument fields only on 2024–2026. Older releases need per-band heuristics (see recon report §Q6.5). Needs corpus byte-inspection.
-
§L5B-09 — generalize Container 2-column decoder. Current implementation handles
kind: 0x0ewith 6-byte records; other container kinds need reverse-engineering against live instance data. -
§GEO — geometry extraction from the object graph. Writer
- bridge can already emit per-element geometry when the caller supplies dimensions; the extraction side (reading location curves / profile shapes / arbitrary brep from the Revit element bytes) is the open research frontier. GEO-27..35 tasks are the breakdown.
-
§WRT — write path. Byte-preserving stream-level patching round-trips (
write_with_patches), but field-level semantic writes (edit a Wall's height and round-trip to a Revit-openable .rvt) are the big next subsystem. WRT-01..14. -
§VW1 — web viewer (WASM + Three.js). VW1-01..24.
-
Corpus expansion. We only have the
rac_basic_sample_family11-release corpus. Donations of real-world project RVTs (with redistribution rights) would dramatically widen validation — tracked as Q-01.Seven permissive-licensed upstream repos contain usable corpus material — see
docs/corpus-hunt-2026-04-21.mdfor the full list. Highest-leverage single targets:DynamoDS/DynamoRevit—test/System/*.rfa(MIT, © 2014 Autodesk)DynamoDS/DynamoWorkshops— 10.rvtproject files from Autodesk University (MIT)DynamoDS/RefineryToolkits—dt_GenerativeToolkit_TestRVT.rvt(MIT)
Every committed fixture ships with a sibling
.license.jsonfile carrying source repo + license SPDX identifier + SHA256- original path. This preserves attribution and makes re-check trivial.
Outreach targets for AEC educational content (not Sourcegraph- indexable): Autodesk University session library, NIBS / GSA BIM sample models, Penn State / Georgia Tech / TU Delft / ETH Zürich AEC curricula. Email participation requests rather than scraping.
Each layer has a clear validation oracle: rvt-info extracts document title + GUID via metadata; rvt-history gives the upgrade timeline via Phase D string scanning; IfcOpenShell validates IFC output against the full IFC4 schema (enforced in CI per IFC-41).
See docs/rvt-moat-break-reconnaissance.md §Q6 for Layer 5a's
research trail, including the documented refutation of the Q6.2
hypothesis. See TODO.md and the GitHub milestones for
the full per-task decomposition.
Open an issue (or a draft PR) before starting work on any of:
- Layer 5 itself — the questions above are open research; a one-paragraph sketch of your approach in an issue saves everyone time before you spend days on a probe.
- IFC exporter emission (
src/ifc/). Mapping decisions have to align with buildingSMART IFC schema conventions. - The modifying writer (
src/writer::write_with_patches). Any change to Revit's truncated-gzip framing must be verified against a round-trip test. - Layer 4c field-type decoder changes. Coverage is at 100% and CI-gated. If you think a pattern is misclassified, file an issue with byte evidence from the corpus — do not silently change the decoder.
- Rust 2024 edition.
cargo fmtbefore every commit.cargo test --releasemust pass. The CI in.github/workflows/enforces this.- No
unsafein the library crate. If you genuinely need it, open an issue first to discuss. - No panics in parsing paths. Malformed input must return an
Error, neverpanic!. - No PII in tests. Use synthetic fixtures —
testuser,111111,FY-20XX, etc. The redaction tests insrc/redact.rsare the canonical examples. - Keep public status honest. If a change affects user-visible
capability, update
docs/status.md,ROADMAP.md, ordocs/compatibility.mdin the same PR. - Every probe under
examples/gets a module-level doc comment explaining what FACT it proves and how to verify the result against the 11-version corpus.
rvt-rs parses untrusted on-disk byte streams, so coverage-guided
fuzzing is part of the safety story. A cargo-fuzz workspace
lives at fuzz/ — see fuzz/README.md for the
full reference.
cargo-fuzz drives libFuzzer against a single entry-point per
target: you write a small fuzz_target! that takes a &[u8] and
feeds it into one parser surface, and libFuzzer mutates a corpus
looking for any input that makes the target panic, abort, time
out, or OOM. The fuzz crate is a standalone workspace so that the
main cargo build does not need nightly Rust.
To add a new fuzz target:
- Pick the parser surface you want to harden and check whether
it already has a tracked task in the
SEC-14..SEC-23series (listed infuzz/README.md). If it does, claim that task. - Create
fuzz/fuzz_targets/<name>.rsusing the libfuzzer-sys template and register it as a[[bin]]entry infuzz/Cargo.toml. - Run the target locally (
cargo +nightly fuzz run <name>) for long enough to exercise mutation — a few minutes at minimum, longer for anything that touches decompression or XML. - Commit any reproducible crashes to
fuzz/corpus/<name>/as regression inputs (tracked separately under Q-04).
The scaffold itself is tracked as SEC-14; the individual targets are SEC-15 through SEC-23, and a nightly CI runner is SEC-25.
We use Conventional Commits:
feat(<scope>): ...for new featuresfix(<scope>): ...for bug fixesdocs(<scope>): ...for documentationtest(<scope>): ...for test-only changesrefactor(<scope>): ...for behavior-preserving internal changesperf(<scope>): ...for performancechore(<scope>): ...for infra / CI / build
Scopes that appear frequently: formats, object_graph,
elem_table, partitions, writer, ifc, readme, cli.
When you discover something new about the file format:
- Write a short probe under
examples/<name>.rsthat reproduces the finding from bytes. One self-contained file, runs against the phi-ag/rvt sample corpus. - Add a dated addendum to
docs/rvt-moat-break-reconnaissance.mdwith an evidence table and a confidence value. - If the finding is a decoding rule, also add a unit test that
pins the byte pattern (see
FieldType::decodetests insrc/formats.rsfor the pattern).
This keeps every claim independently verifiable, which is the whole point of open reverse-engineering work.
Tests, benchmarks, and probes that need real Revit files resolve
their paths from environment variables so no contributor's home
directory leaks into the repo (the CI PII guard job enforces
this). Three variables are recognised, in decreasing specificity:
RVT_FAMILY_2024— full path to a single.rfasample (family-file probes).RVT_SAMPLES_DIR— directory holding the 11-releasephi-ag/rvtcorpus. Defaults to../../samplesrelative to the crate root.RVT_PROJECT_CORPUS_DIR— directory holding.rvtproject files. Defaults to/private/tmp/rvt-corpus-probe/magnetar/Revit(the path the main contributor uses locally for themagnetar-io/revit-test-datasetsMIT-licensed corpus).
Tests and benches that need these files skip gracefully if the path doesn't exist, so a fresh clone runs all non-corpus-dependent suites green without any env setup. To enable the corpus suites:
# Family corpus (LFS-tracked, 11 releases 2016-2026)
git clone https://github.com/phi-ag/rvt /tmp/phiag
export RVT_SAMPLES_DIR=/tmp/phiag/examples/Autodesk
# Project corpus (LFS-tracked, 2023 and 2024 real .rvt files)
git clone https://github.com/magnetar-io/revit-test-datasets /tmp/magnetar
export RVT_PROJECT_CORPUS_DIR=/tmp/magnetar/Revit
cargo test # full suite
cargo bench --bench project_file # Q-07 multi-MB
cargo run --release --example probe_latest_framing # any probeNever hardcode absolute paths in test or probe code — the PII
guard job scans for /Users/<name>/ and /home/<name>/
patterns on every push.
rvt-rs is Apache-2.0 licensed. By submitting a contribution, you agree that your work is licensable under Apache-2.0 and that you have the right to grant that license.
Please do not submit any code, comments, tests, or documentation
that contains information derived from Autodesk proprietary
sources (NDA'd SDKs, decompiled binaries beyond what the public
RevitAPI.dll symbol export trivially exposes, leaked internal
documents, etc.). This project operates strictly from public
on-disk byte observations.
Questions: open an issue or email 151978260+DrunkOnJava@users.noreply.github.com.