Files
JRay-public-server/docs/traceability.md
T
dtourolleandClaude Opus 5 a1e789a6fe
CI / fmt, clippy, test (push) Failing after 1m21s
CI / static musl binary (push) Has been skipped
CI / advisories and licences (push) Successful in 24s
Traceability: vendor the shared gate, annotate the source
Adds jray-project as a submodule at scripts/vendor/jray-project, so this repo
runs the same extractor as every other component rather than its own copy, and
gains the system spec that defines the PR/SR requirements its register traces
up to.

scripts/traceability-gate.sh is a thin wrapper holding only what is specific to
this repo: UR/DR prefixes, .rs sources, and REPO_ROOT — which the shared gate
cannot infer once vendored, since its default resolves to the submodule itself.
Each override fails silently in a way that looks like "no work done" rather
than "misconfigured", so the wrapper documents why each is needed.

Annotates 35 units with TRACES tags, on the code that decides rather than every
helper it calls. Coverage is 23/32 (71.9%) with no orphan tags. The nine
untraced are genuinely unimplemented: UR-007 is plugin-side, UR-008 is
federation, and UR-015..018 are the pending SR-003 schema bump.

The gate caught a real error in the first pass: several tags separated IDs of
different types with commas. A comma joins IDs within one type; a pipe
separates types. Fixed, and the diagnostics are now clean.

MIN_COVERAGE stays 0 deliberately. The gate still fails on orphan tags, a >100%
ratio, a register parsing to nothing, or an empty source scan — raise the
threshold as a ratchet once the remaining work lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-30 18:27:16 +02:00

17 KiB

Requirements traceability matrix

Generated: 2026-07-30T16:25:39+00:00

Denominators are read from requirements.md at run time, never hardcoded. Coverage counts a requirement only when it is tagged in source and has a verification tier this CI host can execute — CI is an Intel N100 with no discrete GPU.

Summary

Metric Value
Source files scanned 26
TRACES tags found 35
EXCEPTION tags found 0
Requirements defined 32
Requirements covered 23
Coverage 71.9% (23/32)
Coverage of CI-executable scope 71.9% (23/32)
Tagged but unexecuted in CI (T4/GPU) 0
Orphan tags 0

By type

Type Covered Tagged but unexecuted Defined
UR 13 0 18
DR 10 0 14
  • PR tags present (separate taxonomy, not counted in coverage): PR-004, PR-005, PR-006
  • SR tags present (separate taxonomy, not counted in coverage): SR-001, SR-002, SR-003, SR-004, SR-005

Not executable in CI

CI runs on an Intel N100 with no discrete GPU. These requirements have no verification tier that can run here, so a tag on them is evidence of intent, not of verification. They are never counted as covered.

None.

Orphan tags

A tag naming an ID requirements.md does not define. This is what renumbering produces, and what a typo produces.

None.

Requirements tracing up to nothing

A register row whose Traces to cell names no parent. Work serving no stated goal is how scope creeps in, and it is invisible unless something looks.

None.

Recorded exceptions

Deliberate, documented departures from an invariant (EXCEPTION: AR-nnn <reason>). Reported separately and never counted as coverage — an exception is a decision to be reviewed, not evidence a requirement is met.

None.

Register

ID Status Tier Traces to Trace state Tagged in Requirement
UR-001 Done T2 SR-001 covered src/api/exists.rs, src/matching.rs Cheap existence probe, separate from the fetch, returning availabilit…
UR-002 Done T2 PR-006 covered src/api/upload.rs, src/ingest.rs Accept a contributed manifest for a media item
UR-003 Done T1, T2 SR-004 covered src/api/upload.rs, src/castcheck.rs, src/model.rs, src/validate.rs, src/worker.rs Content verification: strict schema, size caps, approximate TMDB cast…
UR-004 Done T1, T2 SR-004 covered src/auth.rs, src/ratelimit.rs Rate limiting, per token where present and per source IP otherwise
UR-005 Done T1, T2 SR-004 covered src/api/report.rs, src/api/upload.rs, src/auth.rs, src/castcheck.rs, src/worker.rs Trust without accounts: not usable as a content store, nor for prank …
UR-006 Done T2 PR-006 covered src/api/fetch.rs, src/api/upload.rs, src/validate.rs Serve and accept a whole series in one operation
UR-007 In Progress unset PR-005 covered src/api/exists.rs Plugin queries an ordered, configurable list of servers
UR-008 Planned unset PR-006 untagged - Servers replicate manifests between each other
UR-009 In Progress T1 SR-003 covered src/validate.rs Store an audio spectral-peak signature for content-based identificati…
UR-010 Done T1, T2 SR-001 covered src/api/fetch.rs, src/castcheck.rs, src/db/repo.rs, src/model.rs Identity crossing the API boundary is TMDB/IMDB ids, never a name alo…
UR-011 Done T2 SR-004 covered src/model.rs, src/validate.rs Reject any field capable of carrying binary or attacker-chosen content
UR-012 Done T2 SR-005 covered src/db/repo.rs, src/ingest.rs Never accept, store, or serve gallery data — reference faces or embed…
UR-013 Done T1 SR-002 covered src/api/fetch.rs, src/model.rs, src/validate.rs Windows are scene-scoped claims; never reinterpret their boundaries
UR-014 Done T1 SR-003 covered src/model.rs, src/validate.rs Reject an unknown jmanifest_version outright, never guess
UR-015 Planned unset SR-003 untagged - Accept extraction.extinction_sec in place of anneal_sec
UR-016 Planned unset SR-003 untagged - Accept and store extraction.gallery_scope; rank on it (§7)
UR-017 Planned unset SR-003 untagged - Accept per-window belief and identification route; scenes becomes o…
UR-018 Planned unset SR-003 untagged - Exclude belief from content_id, replicating it as an attribute
DR-001 Done T1 SR-004 untagged - Strict parse boundary: unknown fields rejected structurally, not by v…
DR-002 Done unset SR-004 covered src/api/fetch.rs, src/db/repo.rs Fully relational storage — no JSON blob on the write path
DR-003 Done T1 PR-004 covered src/db/mod.rs Single serialized writer connection, with a read pool alongside
DR-004 Done unset PR-004 covered src/db/repo.rs All database access behind a repository layer, not scattered through …
DR-005 Done T1 PR-004 covered src/db/repo.rs Background work in-process, with the job queue as a table so it survi…
DR-006 Done unset PR-004 covered src/ratelimit.rs Rate-limit counters in process memory; no external counter store
DR-007 Done unset PR-004 untagged - Ship a single static binary plus one database file; container optional
DR-008 Done T2 SR-004 covered src/auth.rs, src/config.rs X-Forwarded-For honoured only from explicitly configured proxies
DR-009 Done T2 SR-004 covered src/app.rs Body caps enforced while streaming, before parsing, per route
DR-010 Done T1 SR-003 covered src/api/json.rs Request bodies are UTF-8 only, rejected with a diagnosable error othe…
DR-011 Done T1 SR-003 covered src/content_id.rs, src/validate.rs content_id canonical form is byte-stable and cross-implementation t…
DR-012 Done unset PR-004 untagged - Dependency audit: advisories, licence policy, source policy
DR-013 Done T1 SR-003 covered src/api/json.rs, src/app.rs, src/error.rs API errors use the status codes the spec names, not the framework's d…
DR-014 Done unset PR-004 untagged - Portable SQL — no SQLite-specific form where a standard one exists

Detailed mapping

DR-002

Locations: 3

DR-003

Locations: 1

DR-004

Locations: 1

  • src/db/repo.rs:337 — pub fn insert_manifest(tx: &Transaction<'_>, m: &NewManifest<'_>) -> anyhow::Result<()>

DR-005

Locations: 1

  • src/db/repo.rs:691 — pub fn lease_jobs(tx: &Transaction<'_>, now: &str, limit: usize) -> anyhow::Result<Vec<Jo…

DR-006

Locations: 1

DR-008

Locations: 2

DR-009

Locations: 1

DR-010

Locations: 1

DR-011

Locations: 3

DR-013

Locations: 3

PR-004

Locations: 3

PR-005

Locations: 1

PR-006

Locations: 5

SR-001

Locations: 7

SR-002

Locations: 3

SR-003

Locations: 8

SR-004

Locations: 16

SR-005

Locations: 2

UR-001

Locations: 3

UR-002

Locations: 2

UR-003

Locations: 6

UR-004

Locations: 2

UR-005

Locations: 6

UR-006

Locations: 3

UR-007

Locations: 1

UR-009

Locations: 1

  • src/validate.rs:354 — pub fn validate_audio_signature(sig: &str, runtime_sec: f64) -> VResult<()>

UR-010

Locations: 4

UR-011

Locations: 4

UR-012

Locations: 2

UR-013

Locations: 3

UR-014

Locations: 2