@@ -6,6 +6,69 @@ All notable changes to `credentials-dotnet` are documented here. The format is b
66
77## [ Unreleased]
88
9+ ### Added — Milestone M8a (Quality & release gates)
10+
11+ The first of three M8 PRs (M8 = conformance + interop + samples + gates). M8a lands the pure-.NET
12+ quality and release gates — no external runtime — closing the package/surface/doc halves of NFR-002,
13+ NFR-005, NFR-009 empirically and wiring CI/CD. Test count ** 318 → 338** ; build stays 0-warning under
14+ ` TreatWarningsAsErrors ` .
15+
16+ - ** ` Credentials.TestSupport ` ** — a shared, non-packable library holding the ` [FrTag] ` requirement-
17+ coverage attribute and ` RequirementIds ` , the single source of truth for the PRD §8 set (34 FR + 9 NFR).
18+ - ** ` Credentials.ArchitectureTests ` ** — invariant gates inspected by metadata only
19+ (` System.Reflection.MetadataLoadContext ` , so the opt-in Credentials.Rdfc is examined without loading
20+ its Newtonsoft into the test host):
21+ - ` PublicSurface_ExposesNoDataProofsType ` (FR-051 / NFR-005, F3) — no ` DataProofsDotnet ` type may
22+ appear in any public/protected signature of the three libraries (return/parameter/field/property/
23+ generic-argument/base/interface vectors all covered).
24+ - ` DefaultLibrary_ReferenceClosure_HasNoNewtonsoft ` (NFR-002, static half) — the compile-time
25+ reference closure of Core + DI is Newtonsoft-free. Documented scope: catches a * used* Newtonsoft
26+ type; the authoritative package-level guarantee is the ConsumerProbe (below).
27+ - ` PublicSurface_EveryDocumentedMember_HasNonEmptySummary ` (NFR-009) — complements CS1591-as-error
28+ (missing docs) by catching * empty* ` <summary> ` on public-surface members.
29+ - ` RoleMethods_NamedAsync_ReturnTaskOrValueTask ` (NFR-004) and ` Library_TargetsNet10 ` (NFR-001).
30+ - ` EveryRequirement_HasAtLeastOneTaggedTest ` (the ** FrCoverage gate** ) — every PRD §8 requirement has
31+ ≥1 ` [FrTag] ` -tagged test (deferring NFR-007 to M8c with a logged reason); a typo'd/unknown id fails.
32+ - ** ` Credentials.RoundTripTests ` ** (FR-003) — byte-fidelity DoD per securing family this engine issues
33+ end-to-end (unsecured received-bytes verbatim; embedded DI in JCS+RDFC byte-stable with exactly one
34+ ` proof ` ; JOSE/SD-JWT verbatim compact + signed-payload == source bytes; COSE verbatim wire bytes;
35+ H1 ` <>& ` /non-BMP-emoji value fidelity).
36+ - ** ` Credentials.ConsumerProbe ` ** + ` tools/check-no-newtonsoft-closure.sh ` (NFR-002, authoritative
37+ package half) — packs Core + DI, restores a real package consumer against a local feed, and asserts
38+ Newtonsoft is absent from the transitive closure (` dotnet list package --include-transitive ` ).
39+ - ** Public-API surface tracking (NFR-005 semver)** — ` Microsoft.CodeAnalysis.PublicApiAnalyzers `
40+ (RS0016/RS0017) wired for the three shippable libraries via ` Directory.Build.targets ` , with the
41+ current surface committed to ` PublicAPI.{Shipped,Unshipped}.txt ` (749 / 26 / 16 entries). Any public-
42+ surface change now fails the build until the API file is updated — a reviewable text diff. RS0026/
43+ RS0027 (the "no overloads with optional parameters" opinion) are disabled for the deliberate, in-place
44+ ergonomic role overloads. ` Microsoft.DotNet.ApiCompat.Tool ` (local tool manifest) +
45+ ` tools/check-api-compat.sh ` add the package-compat check against the last published version (skip-
46+ logged pre-release; honest, never falsely green).
47+ - ** ` [FrTag] ` tagging** — a representative existing test tagged for each of the 42 currently-coverable
48+ requirements, plus two new tests: FR-004 (lazy projections memoized over the frozen document, proven
49+ via ` ReferenceEquals ` ) and FR-021 (` StatusListManager ` set→re-produce→read and clear→re-produce→read).
50+ - ** CI/CD** — ` .github/workflows/ci.yml ` (ubuntu+windows build/test matrix with ` TreatWarningsAsErrors `
51+ as the XML-doc + public-API gate, plus ` no-newtonsoft ` and ` semver ` jobs) and ` release.yml ` (tag-
52+ driven pack + gate + push under a protected ` nuget-release ` environment).
53+
54+ #### Security & hardening (M8a adversarial review)
55+
56+ An adversarial pass attacked each gate to confirm it has teeth (not hollow). The surface, semver
57+ (RS0016), doc (CS1591/empty-summary), and FrCoverage (missing-tag + unknown-id) gates all failed
58+ correctly when defeat was attempted. Two real findings were fixed:
59+
60+ - ** ConsumerProbe was hollow (stale-cache false-pass).** Re-packing the fixed version ` 0.1.0 ` with new
61+ dependencies served * stale* package metadata from nuget's id+version-keyed cache, so a Newtonsoft
62+ dependency added to Core was invisible to the closure check — it always reported the first run's
63+ result. Fixed by packing under a unique per-run version delivered as an environment-variable MSBuild
64+ property (consistent across restore/build/` dotnet list ` , which does not accept ` -p: ` ). Verified: the
65+ fixed gate now reports the violation when Newtonsoft is present and clean otherwise.
66+ - ** The static reference-closure check has an inherent blind spot** — the C# compiler only records
67+ references to * used* assemblies, so an unused-yet-declared ` PackageReference ` carrying Newtonsoft is
68+ invisible to it. Documented honestly; recursion broadened to every non-BCL assembly (so a * used*
69+ Newtonsoft edge hidden behind an intermediate is still caught); the package-level ConsumerProbe is the
70+ authoritative NFR-002 gate. The FrCoverage scan was also hardened to ignore commented-out ` [FrTag] ` s.
71+
972### Added — Milestone M7 (VCDM 1.1 verify)
1073
1174- ** VCDM 1.1 verification (FR-044 / D8):** the verifier now accepts ** VCDM 1.1** credentials and
0 commit comments