Skip to content

Record the OpenSSF Best Practices passing badge - #70

Merged
HackTuah merged 6 commits into
mainfrom
docs/openssf-badge
Sep 23, 2026
Merged

HackTuah merged 6 commits into
mainfrom
docs/openssf-badge

Conversation

@HackTuah

Copy link
Copy Markdown
Member

Trinity was assessed against the OpenSSF Best Practices criteria at the passing level and earned the badge on 2026-09-23.

Section Result
Basics 13/13
Change Control 9/9
Reporting 8/8
Quality 13/13
Security 16/16
Analysis 7/8

This is the prerequisite the Linux Foundation names for a project entering Incubation, alongside documented technical governance and a README per repository, both of which the project already has.

What this change records:

  • the badge in the README, and a row in the assurance posture table naming what backs it
  • a row in docs/09-standards-register.md with its evidence path, per that file's rule that no public claim about an external requirement is made without a row and a status
  • the three suggested criteria recorded unmet rather than stretched: version_semver (semantic versioning begins at the first supported release), dynamic_analysis and dynamic_analysis_enable_assertions (no fuzzing or scanner yet)
  • a note naming the answers that were true on the date given and are not permanent: the two about received reports, the vulnerability response window, and the 60-day clock on the open glib advisory recorded as R25

The audit earned its keep on the first pass. Checking the tree against crypto_random found that gateway pairing codes - the credential that pairs an outside identity to Trinity - were drawn from Enum.random/1, which is not cryptographically secure. Fixed in 4a0b9c3, with a census test preventing recurrence.

Gate green: 566 tests.

The project was assessed against the OpenSSF Best Practices criteria at the
passing level and earned the badge on 2026-09-23: basics 13/13, change control
9/9, reporting 8/8, quality 13/13, security 16/16, analysis 7/8. It is the
prerequisite the Linux Foundation names for a project entering Incubation.

The badge is in the README and, as a row in the assurance posture table, names
what backs it. docs/09-standards-register.md carries the row with its evidence
path, the three suggested criteria recorded unmet rather than stretched
(version_semver, dynamic_analysis, dynamic_analysis_enable_assertions), and a
note naming the answers that were true on the date given and are not permanent:
the two about received reports, the vulnerability response window, and the
60-day clock on the open glib advisory recorded as R25. Those are re-checked
when the badge is revisited rather than assumed to still hold.

The audit behind the self-certification found and fixed a real weakness on its
first pass: gateway pairing codes were drawn from a non-cryptographic generator
(fixed in 4a0b9c3).

Signed-off-by: Ayla Croft <aylacroft@proton.me>
The badge image alone says little to a reader who does not recognise it. The
status section now states what was assessed, by whom, that it is the Linux
Foundation's named prerequisite for Incubation, and that three suggested
criteria are recorded unmet rather than stretched, with a pointer to the
assurance posture table that says what the build enforces.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
An assurance case is a structured argument that a system's security claims hold,
with the evidence for each named so a reader can check it rather than take it on
trust. It is the artefact a software assurance reviewer is trained to read, and
the material for one already existed here in pieces: the security model, the
standards register, the risk register and the tests.

docs/10-assurance-case.md states one top-level claim - an action with an effect
outside the conversation cannot happen unless a decision allowed it, and what
happened can be reconstructed from records that cannot be silently altered - and
decomposes it into ten claims. Each carries its argument, the files, tests or
commands that evidence it, and the limit on what it covers.

The limits and gaps are part of the document rather than omitted from it: the
gate decides but does not sandbox; a chain signed by a key in a file proves
integrity and not custody; memory safety is claimed for this project's code and
not for the runtime beneath it; and the project does not yet publish a signed
SBOM, which is named as weaker than current federal guidance asks.

The assumptions are named too, because an assurance case that hides them is an
advertisement: the machine is trusted, the BEAM is not an OS sandbox, key
custody is the operator's, the model provider is not trusted for safety, and an
external authority layer is outside the case.

Cross-referenced from the README's assurance posture and repository table and
from docs/07, so it is findable by the reader it is written for.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
The suite deliberately runs fifty concurrent conversations (slice 070 AC7) and
twenty concurrent writers (slice 010 AC2), on a sandbox where every process a
test starts shares its owner's connection. That contention is the point of those
tests. SQLite governs it with busy_timeout, which was left at the driver's
default of two seconds, while the Postgres branch of the same configuration had
already raised queue_target for the same reason: a writer queued on purpose
should wait, not fail.

The result was an intermittent Exqlite 'Database busy' on loaded CI runners and
never locally, in a different test each time - the signature of contention
rather than of a defect in whichever test lost. It failed the gate on pull
requests 67 and 70; on 67 it was re-run and passed, which is the wrong response
and is why it came back.

busy_timeout is now 30 seconds on both SQLite test repositories, matching the
intent already written into the Postgres branch.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…properly

Correction, and it matters because the record should not carry a false reason.
The previous commit said busy_timeout had been 'left at the driver's default of
two seconds'. That is wrong: config/config.exs has shipped busy_timeout: 5_000
for both repositories since slice 010. The change it made was to raise the value
in the test environment from 5 s to 30 s, not to set one that was absent. The
reason for raising it stands - a suite that queues fifty writers on one
connection on purpose should wait rather than fail on a loaded shared runner -
but the stated reason was untrue and is corrected here rather than rewritten.

It also broke test/trinity/repo_config_test.exs, which asserted the live value
was 5000 and so was reading the suite's own configuration while describing
itself as guarding what ships. That test now reads the shipped value from
config/config.exs under the production environment, exactly as the pool-size
test beside it already does and for the same reason, and separately asserts the
suite's value is never below it. The shipped configuration is unchanged and is
now genuinely guarded.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
…eout fix achieved

The busy_timeout raise in the previous commit did not stop the intermittent
failure. Run 35889922107 failed on the very commit that raised it, while the
pull-request run on the same commit passed, so it is seed- and load-dependent
and the raise treated the wrong mechanism.

Why no timeout can fix it: SQLite returns SQLITE_BUSY immediately, without
consulting the busy handler, when a connection holding a read transaction tries
to upgrade to a write while another connection holds the write lock, because
waiting there could deadlock.

R26 records it with what provokes it (two connections, and fifty concurrent
writers queued on purpose at slice 070 AC7), what has been ruled out, three
candidate fixes not yet taken, an owner, and a lift condition a stranger can
check: ten consecutive green runs of the full suite with the stress test still
in the default run. The raise is kept because it helps ordinary lock waiting,
and is no longer described as the fix for this.

Signed-off-by: Ayla Croft <aylacroft@proton.me>
@HackTuah
HackTuah merged commit bf2b52e into main Sep 23, 2026
11 checks passed
@HackTuah
HackTuah deleted the docs/openssf-badge branch September 23, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant