RFDs/0020
Organization export and import
Goal
Let an organization take all of its data out of Renga in a documented format, and bring it into another Renga deployment. Today the only way to move data is a PostgreSQL dump, which works for a deployment that serves one organization but not for one that serves many:
-
A dump contains every organization in the database. Cutting one out is fragile: users are shared across organizations, and some sequences, such as resource revisions, are global.
-
A dump restores only into the same schema version, so it cannot move data between deployments running different Renga releases.
-
A dump carries secrets: password hashes, session tokens, and intake key hashes.
An organization export solves all three. It is also how an organization moves between a shared deployment and a deployment of its own, in either direction.
Database backups are a separate concern and stay the operator’s responsibility. An export is not a backup system: see Backups.
The archive
An export is one .tar.zst file containing:
-
manifest.json: the archive format version, the Renga version that wrote it, the organization’s ID, slug, and name, when the snapshot was taken, which optional parts it includes, and a SHA-256 checksum and record count for every other file; -
one newline-delimited JSON file per record type, such as
resources.ndjson,prefixes.ndjson, orcables.ndjson, one record per line.
Record types follow Renga’s domain, not its table layout: a record carries the fields a person or agent can set or observe, with references to other records by ID. Each record type has a documented schema for each archive format version. A migration that changes an exported shape bumps the format version and adds a converter from the previous version, so a release can import archives from older releases. Importing an archive from a newer release than the target is refused.
Organization-owned records keep their UUIDs. References among those records therefore need no translation, and links that people saved to a resource keep working after a move. The target organization and people are different: the importer chooses the target organization, and the source organization ID in the manifest can never select it. References to global users are mapped through the principal model below rather than trusted as destination user IDs.
Contents
The export always includes the organization’s current state:
-
inventory resources with their lifecycle, desired specification, identifiers, identifier claims, overrides, owners, conditions, and relationships;
-
sources and the evidence that current reconciliation relies on, so field ownership and staleness survive the move, including the observation records and payloads that retained claims and evidence require;
-
DCIM, IPAM, and topology records, including cables, plans, and import contracts;
-
the catalog: types, revisions, templates, and expectations;
-
findings, finding workflows, and triage rules;
-
teams, saved views, change requests, custom roles, assignments, and portable organization settings;
-
agents and their installation IDs, without credentials;
-
memberships and every person referenced by current state, as described below.
Two optional parts can be added when exporting:
-
History: Activity (change events), resource revisions, job and job events, and cable and module change events. Imported jobs are historical records, not executable jobs.
-
Additional raw observations: observations still within retention that the current-state evidence does not require. These can be much larger than everything else together.
Members
Users are global in Renga and are not organization-owned records. The archive instead has a source-scoped principal for every person referenced by current state or included history, including former members. A principal carries the source attribution and, where available, the person’s email address and display name. Current memberships, team memberships, and assignments refer to that principal and retain their manual, identity-provider, or directory authority, status, and validity.
A principal records who the source says acted; it does not assert that a destination account is that person. The archive never includes a credential: no password hash, passkey, authenticator secret, recovery code, session, or token.
Excluded
-
Credentials of every kind: user credentials, intake key hashes, directory connection tokens, identity provider client secrets, job lease and report credentials, and pending execution approvals.
-
Deployment configuration: identity providers, local sign-in policy, and anything else read from the environment.
-
Security state that must be re-established by people at the destination: approved installation keys, trusted privileged bindings, and terminal or VM grants (RFDs 13 and 14). The archive lists them for reference, and import creates them as pending or disabled. Accepting an invitation cannot enable these grants.
Exporting
An owner exports from organization settings. Exporting requires the
organization.export permission (RFD 17), which only
the owner role holds
among the built-in roles. An export covers the whole organization regardless
of the exporter’s own read scope, so it is not part of ordinary read access.
The export runs in the background inside one repeatable-read transaction, so
the archive is a consistent snapshot even while agents keep reporting. When it
finishes, Renga notifies the exporter and offers the archive for download from
a link that expires after seven days, after which the archive is deleted. Every
download rechecks the member’s current organization.export permission; an
owner can revoke the download before expiry. Starting an export, downloading
it, revoking it, and its expiry are recorded in Activity.
Operators can export any organization with a release command, renga export
--organization <slug> --output <file>, which writes the same archive. It is
for operators with access to the deployment, not for organization members.
Importing
Import always targets an empty organization: one that has no resources, records, or members other than the person importing. Merging into an organization that already holds data is out of scope, because there is no correct general answer to two records describing the same device.
Renga validates the whole archive before writing anything: checksums, the format version, every record against its schema, and every reference. References must stay within the archive or point to the chosen target where the format explicitly allows it. Validation rejects unsafe archive paths and links and enforces limits on compressed and expanded bytes, files, records, and record size. It reports every problem it can safely collect within those limits.
If the archive is valid, Renga applies it in one transaction. That transaction rechecks the importer’s authorization, target emptiness, ID collisions, and destination constraints while preventing concurrent writes to the target. Notifications, invitation delivery, and other external effects happen only after commit. The whole import lands or the organization stays empty. Allocating a large range of global revision numbers may delay revision-producing writes in other organizations, so the implementation measures and bounds that effect.
-
IDs: if any organization-owned record ID in the archive already exists anywhere in the target deployment, Renga refuses the import unless the importer chooses to import a copy. A copy gives every organization-owned record a new ID and rewrites references; saved links to the original do not carry over. The target organization and destination users are mapped in both modes and never take identity from source UUIDs.
-
Revisions: resources and included historical revisions get new revision numbers from the target deployment, allocated in source revision order. Current resource versions and versions embedded in snapshots are rewritten consistently. Imported Activity keeps source timestamps and principal attribution, is visibly marked as imported, and identifies its source archive; it does not claim the destination authenticated those actors.
-
Members: only active manual memberships, team memberships, and assignments are eligible to return through an invitation. Acceptance proves control of a destination identity before applying them. Identity-provider and directory-managed access remains inactive reference data until a configured destination authority freshly establishes it. Expired, disabled, or revoked access never revives, and Renga never creates or overwrites a global user from an archive assertion.
-
People and actors: source principals remain imported attribution, including where a schema requires an actor, until safely linked to a destination user. Unclaimed personal records, such as private saved views, remain private and unavailable; an unresolved user reference is never changed to organization ownership.
-
Jobs: imported jobs and events preserve the source’s recorded state, including uncertainty, but are historical only. They never enter leasing, retry, approval, or execution queues. Any destination execution is a newly requested and authorized job with a new operation identity.
-
Agents: agent records keep their installation IDs. After the organization creates new intake keys and deploys them, each agent’s reports continue its existing record and history.
-
Security state: installation keys come back pending, privileged bindings unapproved, and terminal and VM grants disabled, so someone at the destination approves each again.
-
Settings: portable organization policy travels with the archive, but values that weaken security require owner confirmation and can never override a destination operator’s locks or deployment policy.
Importing requires an organization’s owner, or an operator through a matching
renga import release command. The import, its source manifest, and its
outcome are recorded in Activity.
Backups
Operators back up the database with ordinary PostgreSQL tools or their
database provider. In a deployment that serves several organizations,
restoring one organization from a backup uses an export: restore the backup
into a separate database, run renga export against it for that organization,
and import the archive into an empty organization in the live deployment.
A deployment that serves a single organization can also hand that organization a full database dump; that is ordinary PostgreSQL administration and not part of this RFD.
Decisions
-
Additional raw observations by default. Left out unless the exporter asks for them. The default archive already includes every observation that current claims and evidence require, so it imports as a complete organization; the remaining retained observations mostly add size.