Record the OpenSSF Best Practices passing badge - #70
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Trinity was assessed against the OpenSSF Best Practices criteria at the passing level and earned the badge on 2026-09-23.
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:
docs/09-standards-register.mdwith its evidence path, per that file's rule that no public claim about an external requirement is made without a row and a statusversion_semver(semantic versioning begins at the first supported release),dynamic_analysisanddynamic_analysis_enable_assertions(no fuzzing or scanner yet)glibadvisory recorded as R25The audit earned its keep on the first pass. Checking the tree against
crypto_randomfound that gateway pairing codes - the credential that pairs an outside identity to Trinity - were drawn fromEnum.random/1, which is not cryptographically secure. Fixed in 4a0b9c3, with a census test preventing recurrence.Gate green: 566 tests.