Skip to main content

See every page side by side: jandira-tech.github.io/neurotic_docx_bench
jubarte vs Microsoft Word, docxide-pdf, LibreOffice, PyMuPDF Pro, MiniPdf, rdocx and office2pdf on 808 documents, DOCX to PDF, scored per page.

jubarte-redlines (Python)

PyPI CI license

Word-faithful DOCX redline engine: compare two Word documents into a tracked-changes document that opens cleanly in Microsoft Word; list, accept, or reject revisions; render DOCX to PDF.

Python bindings (PyO3 + maturin) for the Rust jubarte-redlines engine. Pure compute, no Word/LibreOffice dependency, no network, no temp files — documents go in and come out as bytes (whole DOCX/PDF packages), revision metadata comes back as parsed records (get_revisions → list[dict], get_revisions_json → JSON string), and the GIL is released while the engine runs.

Install

pip install jubarte-redlines
# or: uv add jubarte-redlines

Prebuilt wheels are abi3 (one wheel per platform, CPython ≥ 3.10).

Command line

The native jubarte binary offers --keep-nested-comment on accept, reject and convert --track-changes accept|reject. These bindings do not yet dispatch that option or return its kept-thread receipts; use the native binary when retention is needed.

The wheel installs a jubarte-redlines command; uvx runs it without installing anything:

uvx jubarte-redlines redline original.docx modified.docx -o redline.docx --author Legal
uvx jubarte-redlines changes redline.docx
uvx jubarte-redlines accept redline.docx -o clean.docx --kind formatting
uvx jubarte-redlines reject redline.docx -o original-again.docx --id r12
uvx jubarte-redlines convert redline.docx --revisions word
uvx jubarte-redlines read contract.docx
uvx jubarte-redlines read contract.docx --json
uvx jubarte-redlines edit contract.docx -p p12 --anchor "thirty" --content "sixty"
uvx jubarte-redlines edit contract.docx --plan plan.json --out-dir review --pdf
uvx jubarte-redlines capabilities
uvx jubarte-redlines --help

redline is an alias of compare; python -m jubarte_redlines runs the same commands. changes lists what a document tracks, one change per line with its short id (r12; --json for one object per line); accept and reject take repeatable --id (r12, r1+2, header1.r1), --author and --kind to resolve a selection and keep the rest tracked, or everything when none is given; read prints the agent view with the <!-- p12 --> ids edits use (--json the snapshot); edit and add write FILE_modified.docx, or with --out-dir the bundle (clean copy, redline, patch.diff, report.jsonl, optional PDF/PNG pages); capabilities reports what the build can do (--json the manifest). Exit codes: 0 success, 1 error, 2 usage, 3 edit plan refused. Inputs are .docx: save a Word 97-2003 .doc as .docx first.

Library

from pathlib import Path
from jubarte_redlines import (
    compare_documents,
    get_revisions,
    accept_revisions,
    reject_revisions,
    docx_to_pdf,
)

original = Path("original.docx").read_bytes()
modified = Path("modified.docx").read_bytes()

# Word-mode compare → tracked-changes DOCX (w:ins / w:del)
redline = compare_documents(original, modified, author="Reviewer")
Path("redline.docx").write_bytes(redline)

# List revisions (the library's own records; `jubarte changes --json` is the CLI's listing)
for rev in get_revisions(redline):
    print(rev["type"], rev["author"], repr(rev.get("text")))

# Accept / reject every tracked revision, package-wide
clean = accept_revisions(redline)   # ≙ modified content
base = reject_revisions(redline)    # ≙ original content

# Render to PDF (Word-style layout)
Path("redline.pdf").write_bytes(docx_to_pdf(redline))

compare_documents(original, modified, author="Redline", date=None) stamps revisions with a fixed epoch date by default so output is deterministic; pass an ISO-8601 date to override. Errors raise jubarte_redlines.JubarteError.

Both inputs are admitted under a size budget before anything is inflated (512 MiB per file and per part, 2 GiB inflated, 10,000 entries, XML depth 256). input_limits overrides it key by key, for example compare_documents(a, b, input_limits={"max_uncompressed_bytes": 256 << 20}); the keys are max_compressed_bytes, max_entries, max_part_bytes, max_uncompressed_bytes and max_xml_depth. A package past the budget raises JubarteError with INPUT_LIMIT, and an unknown key raises invalid input limits. get_revisions_json and CompareOptions(input_limits=...) take the same mapping.

read() returns a Document — an immutable snapshot, path I/O done once, no operation mutating it or writing files:

from jubarte_redlines import read, EditPlan, diff

doc = read("contract.docx")
doc.markdown()    # body and every header/footer/notes story, <!-- pN --> id lines
doc.inspect()     # Snapshot: summary + paragraphs (ids, style, spans, limitations) + tables
doc.sha256()      # the source_sha256 guard an edit plan carries
doc.changes()     # each tracked change, with the id accept/reject and plans take
doc.accept(ids=["r12"])           # or reject(...): resolve a selection,
                                  # keep the rest tracked (no selection = all)
result = doc.render(pdf=True, png_dpi=144)  # Rendered: pdf, pngs, page report

The snapshot uses schema_version: 3. changes lists logical changes: a change Word wrote as several marks is one entry with its members, and a deletion and an insertion by one author that touch, in either order, are one replacement. summary.tables and tables[] count top-level body tables only; each index is the view's tN. Every table has a nested array (empty for a leaf), containing its cell tables. A nested entry has parent (for example t0.row2.cell0) and no index. A deeper parent includes the cell-local table ordinal, for example t0.row2.cell0.t0.row0.cell1. Paragraph ids and edit-plan schemas are unchanged.

Python nested grids are Table(index=None, parent=CELL_PATH, nested=(...)); top-level grids retain integer indices.

doc.compare(other, author=...) is compare_documents; doc.to_pdf() and doc.to_png(dpi=...) are the one-shot renderers.

An EditPlan builds the tracked-changes transaction doc.edit(plan) applies — all-or-nothing: a refused plan raises EditPlanError (stable code, the failed operation, every operation's outcome) and produces nothing. doc.preview(plan) resolves and reports without applying:

plan = (
    EditPlan(author="Reviewer")
    .for_document(doc)             # bind to this snapshot; STALE_SOURCE if it changed
    .replace("p3", find="30 days", replacement="45 days", format={"bold": True})
    .comment("p3", text="Check with the client", find="45 days")
    .insert_paragraph("p3", runs=["New sentence."], like="p3")
)
out = doc.edit(plan)               # EditResult: clean, redline, report, diff

replace, insert, delete, comment and format_run edit run text; insert_paragraph, delete_paragraph, format_paragraph, merge_paragraphs and rewrite work on whole paragraphs; insert_table(paragraph, rows=[[...], ...]) adds a table and list_paragraphs([...], kind_of_list="decimal") (wire kind list) numbers paragraphs; insert_footnote adds a footnote after an anchor; insert_image adds a picture paragraph; page_setup changes the page size, orientation and margins; resolving(accept={...}, reject={...}) settles existing tracked changes first. plan.to_json() is exactly what edit --plan reads.

diff(old, new) shows the changed paragraphs between two documents — or a document and Markdown text — as [-old-]{+new+} marks (format="critic" for CriticMarkup). When a side is a Word document, the comparer writes the changes, and a replacement inside a paragraph keeps Word Compare's order, the insertion first: {+new+}[-old-].

print(diff(read("v1.docx"), read("v2.docx")))

doc.append(other) puts other after doc on a new page and returns Appended(document, warnings): images, links, headers, styles, lists and notes come along. Comments are dropped (COMMENTS_DROPPED in warnings) unless comments="carry", which brings the comments other's body anchors with their threads and resolution. section_break="continuous" joins on the same page and keep_sections=True keeps other's page setup, headers and footers.

Before a document goes out, or after an agent edited it:

doc.validate()        # Word-validity findings beyond the schema; () is a pass
fixed = doc.repair()  # Repaired: document, repaired, remaining
doc.audit_tracked(read("original.docx"), author="Reviewer")  # untracked or foreign edits
doc.audit("a11y,structure")  # accessibility, style and structure findings by paragraph id
out = doc.scrub()     # authors as "Author", no rsids, document properties or comments
doc.update_fields()   # PAGEREF, REF, NUMPAGES, SEQ and TOC results from jubarte's layout

from_markdown(text, author=..., track_changes="all") writes Markdown as a Word document, CriticMarkup becoming tracked changes and comments, as jubarte convert draft.md does; reference= lends a document's styles and page setup. A change or comment that names no author or date takes author and date when you pass them, else the front matter's author: and last_modified:/modified:/date:/created:, else Redline and the fixed epoch, so the same Markdown writes the same bytes (the CLI falls back to --reference-doc's creator and creation time, then Redline and now). diff_render(a, b, dpi=100) says which pages of two documents look different, pixel for pixel, with magenta overlays on the changed pages.

Document.from_bytes(data) holds bytes you already have and to_bytes() returns them; inspect_json() is the engine's inspect snapshot as JSON text, unchanged (inspect() decodes it). scrub takes author_alias, rsids, docprops and comments to choose what goes.

Also available as

Text comparisons

jubarte-redlines diff a.docx b.docx --format github
jubarte-redlines diff a.docx b.docx --format github -U0 --accept-changes
jubarte-redlines diff a.docx b.docx --format word

Line views (github, normal, context, side-by-side) retain each input’s tracked marks. Word comparison accepts all changes in both inputs first, then creates fresh CriticMarkup; earlier revision provenance disappears. critic remains a representation of document content with its marks. Long lines use a 70-character review window; --full-lines shows all text. Text views support DOCX and Markdown and write stdout or an explicit -o text file. CLI help and usage errors come from the shared clap-derived grammar.

Rendering and fonts

The PDF engine reconstructs Word-oriented layout directly; it does not call Microsoft Word or LibreOffice.

The documented rendering surface includes:

  • tracked changes, and comments as Word's balloons in the markup pane (a resolved comment faded, a reply numbered under its thread);
  • paragraph/run formatting and advanced line layout;
  • CJK and RTL/complex-script text;
  • installed and embedded fonts;
  • merged, vertically merged, autofit and floating tables;
  • DrawingML/VML graphics, text boxes, charts and SmartArt;
  • raster and EMF/WMF images;
  • headers, footers and floating frames;
  • sections, columns, backgrounds and page borders;
  • footnotes and selected fields.

Rendering fidelity still depends on fonts and on document features. WebAssembly has no installed fonts: docxToPdf paints with the fonts a document embeds and the bundled Carlito and Liberation faces, so Chinese, Japanese or Korean text without an embedded font is not painted (see KNOWN_ISSUES.md, item 9).

Supplemental font lookup can be configured with:

export JUBARTE_FONT_DIR=/path/to/jubarte/fonts
export JUBARTE_FONT_INDEX=/path/to/font-index.tsv

Set:

export JUBARTE_FONT_INDEX=off

to disable the persistent font index.

Default per-user font directories are documented in the installation section of this repository.

For known Word-layout differences, see:

Comparison modes

The default comparison mode is:

--mode word

It targets Word-like comparison behavior.

Classic PowerTools behavior is available with:

--mode powertools

Choose explicitly if exact comparison semantics matter to a regression test or downstream workflow.

Supported environments

Surface Supported/tested target
Rust / CLI CI tests Linux, macOS and Windows
Rust toolchain Rust 1.94+
Python CPython 3.10+
Python release wheels macOS x86_64/arm64, manylinux_2_28 x86_64/arm64, musllinux_1_2 x86_64/arm64, Windows x86_64 (abi3, CPython 3.10+)
Node Node 18+
Browser WebAssembly builds
CLI release workflow Linux x86_64/arm64, macOS x86_64/arm64, Windows x86_64 targets

Release assets can vary by tag. Check the release page before scripting a binary download.

A Word 97-2003 .doc converts to .docx with the native binary's jubarte convert old.doc (or jubarte::legacy_doc::doc_to_docx in Rust): text, headings, lists, bold, italic and tables. Every other command, and the Python and JavaScript packages (the npm command line too), refuse a .doc (or an encrypted document of any Word version) with LEGACY_DOC and the hint to save it as .docx without a password, and RTF with UNSUPPORTED_PACKAGE. Convert them to .docx first.

Troubleshooting

Problem What to check
PDF layout differs from Word Verify required fonts; inspect --font-report; read docs/WORD_DIFFERENCES.md
Text is missing or wraps differently Check font resolution and embedded/system font availability
Edit exits with a refusal Read report.jsonl / stdout for STALE_SOURCE, ANCHOR_NOT_FOUND, AMBIGUOUS_ANCHOR, OVERLAPPING_EDITS, UNSUPPORTED_STRUCTURE, etc.
STALE_SOURCE Re-run jubarte read and regenerate the plan from its new sha256: line
AMBIGUOUS_ANCHOR Use a paragraph ID or a more specific exact anchor
Document already contains revisions List them with jubarte changes; explicitly accept/reject them or set an edit-plan revision policy
Comment is present in DOCX but missing from rendered markup Check the documented comment-balloon limitations and docs/WORD_COMMENT_BALLOONS.md
Output page count is not exactly Word's The renderer targets Word behavior but is independent; inspect known differences before treating page count as an invariant
Prebuilt archive is absent for a platform Install with Cargo or build from source; then check the release assets for a later tag
Need exact package differences Use jubarte debug diff and the text, runs, xml or render debug catalogs

License

jubarte-redlines is licensed under GNU Affero General Public License v3.0 only (AGPL-3.0-only).

Review the license requirements before embedding or deploying the software in a product or network service.

Engine comparison site · jandira.tech · arthur.law · Cicero · LinkedIn · contact@arthur.law

Metadata

Release files for jubarte-redlines 0.13.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for jubarte-redlines 0.13.0
File Size Uploaded Provenance Actions
jubarte_redlines-0.13.0.tar.gz 7.8 MB Without provenance Details for jubarte_redlines-0.13.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for jubarte-redlines 0.13.0
File Actions
jubarte_redlines-0.13.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for jubarte_redlines-0.13.0-cp310-abi3-win_amd64.whl
jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details for jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_x86_64.whl
jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details for jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_aarch64.whl
jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_x86_64.whl CPython 3.10 abi3 Linux glibc 2.28+ x86-64 Details for jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_x86_64.whl
jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.28+ ARM64 Details for jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_aarch64.whl
jubarte_redlines-0.13.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for jubarte_redlines-0.13.0-cp310-abi3-macosx_11_0_arm64.whl
jubarte_redlines-0.13.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for jubarte_redlines-0.13.0-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 106.6 MB

Release files / jubarte_redlines-0.13.0.tar.gz

Download URL jubarte_redlines-0.13.0.tar.gz
Size 7.8 MB
Tags Source
SHA-256 checksum
How to use checksums
9d40725670370b73344c71b00e8c0fff20deaf06c221bdc79b69e58b3fc555da
BLAKE2b-256 checksum
How to use checksums
1b634a1b63c42efa895b617367885095a1b6c095dd521eaf85a3fd339979e79c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-win_amd64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-win_amd64.whl
Size 14.2 MB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
8121b82bfc2c3ec27da11eeb78dcf68ca2c96ad29ec40cbc814bd2e119b4116a
BLAKE2b-256 checksum
How to use checksums
626875088fefe93fae60f2e58711dfe2716912be7be9754eb926752ccc91a461
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_x86_64.whl
Size 14.8 MB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
132ddb1f4165c4dcf7ad05e0b3a181a1b27dc4c2eaa6054d498d00a2e62a738e
BLAKE2b-256 checksum
How to use checksums
2e629d031ff5b53d8b7b096a77a829a4847777bb990066828f3bb517569f4ed8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-musllinux_1_2_aarch64.whl
Size 14.1 MB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
a54a41ae16d6a9b522d7a977fbf2b0b2eb94ce4b4a834cd1bda87b8d37fdb185
BLAKE2b-256 checksum
How to use checksums
13bf9ecbda2fffb8c506a6cb06f23b675eb6f955f5211da88143a6ca6e696433
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_x86_64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_x86_64.whl
Size 14.6 MB
Tags CPython 3.10 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
f0430e69e949782f65731e7032bc0fa7bc7a61f23c0eb0d6b808c2bcd11b87a3
BLAKE2b-256 checksum
How to use checksums
ae63937a0da605f9cabce9cad914c578b8f9a087ce59957767033fd957d1e410
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_aarch64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-manylinux_2_28_aarch64.whl
Size 14.0 MB
Tags CPython 3.10 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
5be68dc4d1b7c495e2f9006b1a63d6e225ae29fae9d7e4878881d42ccadf01e1
BLAKE2b-256 checksum
How to use checksums
82c0c1399bf00ad9ee363c2c1efd7405a064863237bc0bec9c41846e1205e5b2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-macosx_11_0_arm64.whl
Size 13.3 MB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
af8cdf836ca74192224d2ef3985371f2edad77891af85c5e56b61fdc63586fac
BLAKE2b-256 checksum
How to use checksums
ef853b24737203e40a251dc55e7e176b64c73e5a4d5728ee9fb72bbac5883c14
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / jubarte_redlines-0.13.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL jubarte_redlines-0.13.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 13.8 MB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
875f207a6f09d0d978b075a5447b69a7daa88a6374d5030e5bc1a095959b08a9
BLAKE2b-256 checksum
How to use checksums
da56b4082329f421eeb2088586afffec7f844fce06eff31520190b0f470b9071
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via uv/0.13.5 {"installer":{"name":"uv","version":"0.13.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"20.04","id":"focal","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for jubarte-redlines 0.13.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page