Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 15 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,20 @@ merge commit and tagged `slice/NNN` (`git tag -l 'slice/*' | wc -l` → 25, on 2
that means in practice:

**Assessed against a recognised baseline.** Trinity holds the
[OpenSSF Best Practices passing badge](https://www.bestpractices.dev/projects/14772), the Open
Source Security Foundation's published bar for basics, change control, reporting, quality,
security and analysis, and the prerequisite the Linux Foundation names for a project entering
Incubation. Every required criterion is met; three *suggested* ones are recorded as unmet rather
than stretched, because a sheet with nothing on it survives a spot check less well than one that
says where the gaps are. The [assurance posture](#assurance-posture) below states what the build
enforces and what enforces it.
[OpenSSF Best Practices **silver** badge](https://www.bestpractices.dev/projects/14772), awarded
2026-09-23. Silver is the Open Source Security Foundation's second tier: it takes the passing bar
for basics, change control, reporting, quality, security and analysis, which is the prerequisite
the Linux Foundation names for a project entering Incubation, and adds documented governance and
roles, continuity of access, a published roadmap, a written test policy, 80% statement coverage,
and an assurance case carrying a threat model, its trust boundaries, an argument that secure design
principles were applied and an argument that common implementation weaknesses were countered.

Every required criterion at both levels is met. What is *not* met is recorded rather than
stretched, because a sheet with nothing on it survives a spot check less well than one that says
where the gaps are: at silver, two suggested-tier criteria (a bus factor of two, and an
accessibility assessment) and one suggestion about signed version tags are marked unmet with the
reason. The [assurance posture](#assurance-posture) below states what the build enforces and what
enforces it.

- **Talks.** Streaming chat with any provider behind one behaviour (`Trinity.LLM`), switched by
configuration; the assistant's text is persisted as a draft every 500 ms or 2 KB while it
Expand Down Expand Up @@ -188,7 +195,7 @@ rather than described by it.
| Approved cryptography | A dedicated CI leg builds from source and runs the cryptographic properties inside a FIPS-mode container, so statements about approved algorithms are measured on that leg rather than asserted. |
| Supply chain | Dependency and licence audits run on every commit; dependency versions are pinned in `VERSIONS.md` and verified against the lock file by the gate. A CycloneDX bill of materials is generated by the gate on every commit and ships beside every packaged binary, so whoever holds the artifact holds the list of what is in it; the bill states its own coverage inside the document, including what it does not cover. |
| Provenance | Every commit carries a Developer Certificate of Origin sign-off, enforced by a hook and independently by CI. Every packaged binary carries build provenance attested through the workflow's own identity and recorded in a public transparency log, verified in the same run that produced it, so a holder can check where the bytes were built without trusting this page. |
| Independent self-certification | The project holds the [OpenSSF Best Practices passing badge](https://www.bestpractices.dev/projects/14772), assessed against the Open Source Security Foundation's published criteria for basics, change control, reporting, quality, security and analysis. Three suggested criteria are recorded as unmet rather than stretched: semantic versioning, which begins at the first supported release, and two concerning dynamic analysis tooling, which the project does not yet run. |
| Independent self-certification | The project holds the [OpenSSF Best Practices **silver** badge](https://www.bestpractices.dev/projects/14772) (awarded 2026-09-23), assessed against the Open Source Security Foundation's published criteria at two tiers. Every required criterion at both is met. What is not met is stated rather than stretched: at passing, three suggested criteria (semantic versioning, which begins at the first supported release, and two concerning dynamic analysis tooling the project does not run); at silver, a bus factor of two and an accessibility assessment, both suggested-tier, and signed version tags. |
| Argued, not asserted | `docs/10-assurance-case.md` decomposes the top-level security claim into ten claims, each with its argument, the evidence a reader can check, and the limit on what it covers; the assumptions the case rests on are named rather than implied. |
| Claim discipline | `docs/09-standards-register.md` records one row per control a regulated deployment might ask about, each with an evidence path and a status. No public claim about a regulation or requirement is made without a row there saying it is true. |

Expand Down
2 changes: 2 additions & 0 deletions docs/09-standards-register.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ document, a PROOF.md line) or `none`; the status; who decides the status. Status
| Control | Where Trinity satisfies it | Evidence path | Status | Decider |
|---|---|---|---|---|
| Recognised open-source security baseline | The OpenSSF Best Practices criteria at the passing level: basics, change control, reporting, quality, security and analysis | https://www.bestpractices.dev/projects/14772 | **passing, self-certified 2026-09-23.** Three suggested criteria are recorded unmet rather than stretched: `version_semver`, `dynamic_analysis`, `dynamic_analysis_enable_assertions` | maintainer |
| Recognised open-source security baseline, second tier | The same criteria at the **silver** level: documented governance and roles, continuity of access, a published roadmap, a written test policy, 80% statement coverage, and an assurance case carrying a threat model, trust boundaries, a secure-design argument and an implementation-weakness argument | https://www.bestpractices.dev/projects/14772 | **silver, self-certified 2026-09-23** (all 44 MUST criteria met or not applicable; `signed_releases` is not applicable only while no release is published, and becomes required at the first one). Recorded unmet with reasons: `bus_factor` and `accessibility_best_practices` (both SHOULD), `version_tags_signed` (SUGGESTED) | maintainer |
| Recognised open-source security baseline, third tier | The same criteria at the **gold** level | https://www.bestpractices.dev/projects/14772 | **30% as of 2026-09-23, not held.** Met so far: `require_2FA` (the organisation enforces two-factor authentication for write access), and the gold-level criteria inherited from the tiers below. `copyright_per_file` and `license_per_file` are met in the tree as of this row and held by `test/spdx_headers_test.exs`. Outstanding and not glossed: `bus_factor` and `contributors_unassociated` and `two_person_review` all need people other than the author in the history; `test_statement_coverage90` needs 90% against the current 80.31%; `build_reproducible` is measured and not met (docs/packaging.md); `security_review`, `code_review_standards`, `small_tasks` and `dynamic_analysis` are open work | maintainer |
| Linux Foundation Incubation prerequisite | The same badge; LF Incubation requires it at passing, alongside documented technical governance and a README per repository | https://www.bestpractices.dev/projects/14772, `GOVERNANCE.md`, `MAINTAINERS.md` | badge held; neutral asset hosting is not yet in place and is a foundation-side step | owner |

**Time-bound answers in that self-certification.** Three of the answers were true on the date given
Expand Down
3 changes: 2 additions & 1 deletion lib/trinity_web/components/layouts/root.html.heex
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<!DOCTYPE html>
<%!-- SPDX-FileCopyrightText: Sudo Apt Holdings LLC --%>
<%!-- SPDX-License-Identifier: Apache-2.0 --%> <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
Expand Down
2 changes: 2 additions & 0 deletions lib/trinity_web/controllers/oauth_html/consent.html.heex
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
<%!-- SPDX-FileCopyrightText: Sudo Apt Holdings LLC --%>
<%!-- SPDX-License-Identifier: Apache-2.0 --%>
<Layouts.app flash={@flash}>
<:bar>
<span class="opacity-70">{gettext("Authorize a client")}</span>
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/build.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// SPDX-FileCopyrightText: Sudo Apt Holdings LLC
// SPDX-License-Identifier: Apache-2.0
fn main() {
tauri_build::build()
}
2 changes: 2 additions & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// SPDX-FileCopyrightText: Sudo Apt Holdings LLC
// SPDX-License-Identifier: Apache-2.0
#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
tauri::Builder::default()
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// SPDX-FileCopyrightText: Sudo Apt Holdings LLC
// SPDX-License-Identifier: Apache-2.0
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
use tauri_plugin_shell::process::CommandEvent;
Expand Down
58 changes: 58 additions & 0 deletions test/spdx_headers_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# SPDX-FileCopyrightText: Sudo Apt Holdings LLC
# SPDX-License-Identifier: Apache-2.0
defmodule SpdxHeadersTest do
@moduledoc """
Every source file this project wrote carries a copyright line and a licence line.

These are the OpenSSF Best Practices criteria `copyright_per_file` and `license_per_file`, both
MUST at the gold level. They are held here rather than checked by hand for the reason every
population rule in this tree is held by a test: the count only stays right if adding a file that
breaks it fails something. When this test was written the tree was five files short of both
criteria, and none of the five was noticed by anyone reading the tree.

The population is `git ls-files`, so a new source file is in scope by existing. The comment
syntax differs by language and the marker does not: SPDX defines the tag, not the comment it
sits in, which is why this checks for the tag rather than for a particular line.
"""
use ExUnit.Case, async: true

@copyright "SPDX-FileCopyrightText"
@license "SPDX-License-Identifier"

# How many lines from the top the tags must appear within. HEEx templates and Rust files both
# carry them first; an Elixir file may sit below a shebang or a moduledoc-free comment.
@window 6

defp sources do
{out, 0} = System.cmd("git", ["ls-files", "*.ex", "*.exs", "*.heex", "*.rs"])
String.split(out, "\n", trim: true)
end

defp head(file), do: file |> File.read!() |> String.split("\n") |> Enum.take(@window)

test "the population is the tree's own source files, and it is not small" do
files = sources()
assert length(files) > 400, "expected the whole tree, got #{length(files)} files"
end

test "every source file carries a copyright statement" do
missing = for f <- sources(), not Enum.any?(head(f), &String.contains?(&1, @copyright)), do: f

assert missing == [],
"these files carry no #{@copyright} line in their first #{@window} lines"
end

test "every source file carries a licence statement" do
missing = for f <- sources(), not Enum.any?(head(f), &String.contains?(&1, @license)), do: f

assert missing == [],
"these files carry no #{@license} line in their first #{@window} lines"
end

test "the licence named in each file is the one the project is under" do
for f <- sources(), line <- head(f), String.contains?(line, @license) do
assert line =~ "Apache-2.0",
"#{f} names a licence that is not the project's: #{String.trim(line)}"
end
end
end
Loading