Skip to content

Architecture Decision Records

This page documents notable architectural decisions made in this app.

Every query is scoped to the generating user

Data-bearing blocks resolve against the acting user (the request user in a live preview, or the Job's initiating user when published) and query through Nautobot's object permissions. A report is only ever as complete as the permissions of whoever generated it.

Why: reports must never expose objects the requesting user could not otherwise see.

Published reports are immutable snapshots

Publishing renders the template to HTML and freezes it as a PublishedReport record, along with a snapshot of the template's name. Editing or deleting the source template later never touches existing snapshots.

Why: historical reports must remain reproducible and auditable. Each publish creates a new record rather than mutating a previous one.

Row caps are enforced at resolution time

Saved View and Export Template blocks clamp their in-report and attachment row counts to a hard system ceiling (5000).

Why: reports render synchronously in the report builder and live preview tab, so unbounded querysets would make rendering slow and documents unreadable.

Locked weight slots for single-use structural blocks

Title Page and Table of Contents blocks are single-use per template and occupy reserved weight slots (0 and 10); user-managed blocks start at weight 100 and are spaced to leave room for insertions. This is enforced in ReportBlock.clean() and ReportBlock.save(), and honored by the reorder-blocks API action.

Why: these structural blocks have a fixed position in a document, so their ordering should not be user-editable in the same way as content blocks.

Errors are surfaced inline, not fatally

When a single block fails to render, or an attachment cannot be produced (for example, a PDF requested without WeasyPrint installed), the failure is caught, logged, and surfaced as an inline alert (or a skipped attachment) instead of aborting the whole report or email.

Why: one misconfigured block should not prevent an otherwise-valid report from being generated and delivered.