Skip to main content
Ctrl+K
fairdm 0.3.1 documentation - Home fairdm 0.3.1 documentation - Home
    • Developers
    • Administrators
    • Users
    • What FairDM is for
    • FAIR data and research data infrastructure
    • The technology stack
    • The core data model
    • How sample and measurement types are stored
    • Controlled vocabularies
    • Configuration over code
    • Why complete metadata matters
    • How access to a record is decided
    • Why FairDM records contributors
    • How contributor accounts and credits work
    • How a profile is claimed
    • How FairDM configures a portal
    • Who is asked to agree to a legal document
    • How locations are stored and protected
    • Dataset publication, DOIs and DataCite metadata
    • Glossary
    • Framework Contributors
    • Architecture Decision Records
    • Roadmap — FairDM
    • Changelog
  • GitHub
  • GitHub
  • Developers
  • Administrators
  • Users
  • What FairDM is for
  • FAIR data and research data infrastructure
  • The technology stack
  • The core data model
  • How sample and measurement types are stored
  • Controlled vocabularies
  • Configuration over code
  • Why complete metadata matters
  • How access to a record is decided
  • Why FairDM records contributors
  • How contributor accounts and credits work
  • How a profile is claimed
  • How FairDM configures a portal
  • Who is asked to agree to a legal document
  • How locations are stored and protected
  • Dataset publication, DOIs and DataCite metadata
  • Glossary
  • Framework Contributors
  • Architecture Decision Records
  • Roadmap — FairDM
  • Changelog
  • GitHub
  • GitHub

Section Navigation

  • ADR 0001 — Environment overrides are found by existence, beside a known anchor
  • ADR 0002 — Configuration checks run automatically in production, and nowhere else
  • ADR 0003 — The baseline ships no working default for a security-critical value
  • ADR 0004 — A portal’s apps are registered ahead of FairDM’s
  • ADR 0005 — A measurement type nominates its value; the base reports and formats it
  • ADR 0006 — What the registry generates carries the framework’s mixins
  • ADR 0007 — Every record has a page of its own
  • ADR 0008 — One editing page per record, with its related rows inline
  • ADR 0009 — A form’s default and a model’s default may legitimately differ
  • ADR 0010 — Record addresses name the record type in the plural
  • ADR 0011 — One navigation entry per collection of pages
  • ADR 0012 — Every page states its own access rules
  • ADR 0013 — A listing shows published records only, for everyone
  • ADR 0014 — Publication is a separate flag from visibility
  • ADR 0015 — A record’s own dataset decides, and a row never links past it
  • ADR 0016 — The framework indexes the fields it searches by default
  • ADR 0017 — Listings are addressed and named apart from records
  • ADR 0018 — Publication is a queryset method, not a default manager
  • ADR 0019 — A portal role is the unit of portal-wide rights
  • ADR 0020 — A missing role is answered four ways, and never by blocking repair
  • ADR 0021 — Profile claims and merges belong to a named role, not to superusers
  • ADR 0022 — Development accounts are a command that refuses, not a fixture that loads
  • ADR 0023 — An overview page is extended through blocks, plugin methods and type templates
  • ADR 0024 — The right to edit a profile is asked of the record
  • ADR 0025 — A level on the contribution decides rights over a core record
  • ADR 0026: A record’s editing pages are six shared pages
  • ADR 0027 — Records refer to each other by short identifier, never by database number
  • ADR 0028 — API tokens are created on the account pages, never exchanged for a password
  • ADR 0029 — People and organizations have their own API endpoints
  • ADR 0030 — A credit on a record carries what DataCite asks of a creator
  • ADR 0031 — Portals run on PostgreSQL with PostGIS
  • ADR 0032 — A location is a value on each record, not a shared row
  • ADR 0033 — A measurement borrows its sample’s location only for a viewer who may open the sample
  • ADR 0034 — Portals build on the base images FairDM publishes
  • ADR 0035 — FairDM does not compress static files
  • ADR 0036 — FairDM declares the image and database a portal runs on
  • ADR 0037 — Autocomplete fields are built on django-tomselect
  • ADR 0038 — Each autocomplete scope is its own view
  • ADR 0039 — Autocomplete addresses are limited per caller
  • ADR 0040 — Backup schedules are periodic tasks
  • ADR 0041 — Backups are encrypted to a public key
  • Architecture Decision Records
  • ADR 0015 — A record’s own dataset decides, and a row never links past it

ADR 0015 — A record’s own dataset decides, and a row never links past it#

Status: accepted

Decision#

A record appears in a listing if and only if the dataset it belongs to is published. No rule reaches through a relation to decide presence.

Separately, where a row would name or link a record the visitor cannot read, it shows neither the name nor the link. The cell keeps its place and carries a placeholder that names nothing: the sample column reads Unpublished, and the dataset column keeps its icon without the anchor around it. What must not survive is the record’s own name and its address.

The same test governs every choice list a filter offers. A filter is a second way to read a listing, so a name withheld from a cell must not be available from a dropdown beside it.

Why#

Deciding by the record’s own dataset is the only rule that stays true as the graph grows. A measurement may belong to a different dataset than the sample it was made on: provenance crossing dataset boundaries is a principle here, not an accident. Any rule that reaches through a relation has to be re-derived for every relation added afterwards, and the version that was not re-derived is the one that leaks.

The link half is the part that is easy to miss. Without it, a listing that correctly excludes an unpublished sample from the sample listing hands out that sample’s name and address from the measurement listing instead. Membership of a listing must never become a route to a record that is not itself readable.

“Cannot read” is wider than “not published”. Since publication is independent of visibility (ADR 0014), the common shape is a published but private dataset. Its records belong in every listing, and the dataset column on those rows would otherwise link to a page the same visitor is refused. The rows stay, because publication alone decides presence. The link does not.

Consequences#

Every column that renders a related record applies the same test the sample and dataset columns apply. A new linked column added later without it is a leak, not a cosmetic omission.

A placeholder in a listing is a meaningful state, not missing data, and is worth reading as “there is a record here you may not read”.

Filter choice lists are scoped where the listing resolves its filter set, not where the framework generates one. A registration may supply its own filter set or build it in a method of its own, and a rule enforced only inside the generator does not reach either.

previous

ADR 0014 — Publication is a separate flag from visibility

next

ADR 0016 — The framework indexes the fields it searches by default

On this page
  • Decision
  • Why
  • Consequences

© Copyright 2026, Samuel Jennings.

Built with the PyData Sphinx Theme 0.21.0.