Skip to content

ci(security): add CodeQL, OpenSSF Scorecard, a security policy and README badges - #29

Merged
AdCodicem merged 10 commits into
mainfrom
claude/dotnet-repo-upgrade-xefbjy
Sep 15, 2026
Merged

AdCodicem merged 10 commits into
mainfrom
claude/dotnet-repo-upgrade-xefbjy

Conversation

@AdCodicem

Copy link
Copy Markdown
Owner

CodeQL runs in manual build mode: autobuild picks the wrong entry point in a
solution whose generator targets netstandard2.0 alongside the net10.0
libraries. Scorecard publishes its results so the README badge can read them.

SECURITY.md points at private vulnerability reporting and says what a finding
in this repository usually looks like, since these packages carry no boundary
of their own -- the interesting reports are about generated parsing, a
bypassable rule, or an integration that lets a value cross without its rules.

The codecov badge stays dark until the coverage upload lands.

Co-Authored-By: Claude Opus 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J

…ADME badges

CodeQL runs in manual build mode: autobuild picks the wrong entry point in a
solution whose generator targets netstandard2.0 alongside the net10.0
libraries. Scorecard publishes its results so the README badge can read them.

SECURITY.md points at private vulnerability reporting and says what a finding
in this repository usually looks like, since these packages carry no boundary
of their own -- the interesting reports are about generated parsing, a
bypassable rule, or an integration that lets a value cross without its rules.

The codecov badge stays dark until the coverage upload lands.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
CONTRIBUTING.md stays short and defers the long-form layout and debugging
guidance to website/docs/contributing.md rather than becoming a second copy of
it. What it does carry is the thing a first contributor cannot guess: a change
to the consumer-facing surface is rarely a one-file change, because the README,
the site and skills/value-objects/ are all held to it by tests.

Issue templates are YAML forms rather than markdown: a generator bug is
diagnosable from the declaration, the call path that reached it and the emitted
source, and a form is what actually gets those three filled in.

The discussion template is scaffolded ready for Discussions being enabled.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
… benchmark run

Auto-merge covers minor and patch bumps only; a major bump gets a comment
saying it was deliberately left for a human, rather than sitting silently in
the PR list. Both depend on repository settings this file cannot set -- "Allow
auto-merge" and CI as a required check -- which is the difference between the
job succeeding and anything actually merging.

Benchmarks stay on workflow_dispatch. A shared runner is contended enough that
absolute timings are not comparable between runs, so a gate on every push would
report noise; the filter is a choice list of the four suites that exist.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
ARCHITECTURE.md is the "where do I start reading" map and deliberately does not
re-explain the reasoning -- the site already does that well. It does carry the
typed-path/boxed-path split, because that is where defects hide and it is not
obvious from the layout.

The ADRs record what the site does not: what was rejected, and what would have
to change to revisit it. 0002 is retroactive and covers the representation
choice; 0003 records the release model, and is written before the commit that
implements it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
dotnet format --verify-no-changes did not pass on this tree. Two separate
causes, only one of which was drift:

LiteralFactory's escape switch kept its statements on the case labels, which
reads well as a table but contradicts csharp_preserve_single_line_statements =
false in this repository's own .editorconfig. Reformatted to match the declared
style. Flipping that setting to true instead would be the other honest fix.

ASP0020 on the sample's minimal API endpoint is a false positive: dotnet format
builds a workspace without running source generators, so it cannot see the
IParsable<Iban> the generator emits, and reports the endpoint as unbindable.
The real build sees it and is clean. CI therefore runs whitespace and style and
deliberately skips analyzers, which EnforceCodeStyleInBuild already covers where
the generator actually runs.

Coverage now comes from all three suites. The unit suite alone exercises the
typed path, which is precisely how a descriptor defect stayed invisible once.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
…merge

Merging to main now publishes a preview and nothing else; a stable release is a
workflow_dispatch on release.yml. The version and CHANGELOG.md come from the
Conventional Commits this repository already enforces, so they cannot drift from
the history, while the step that cannot be undone -- pushing to nuget.org, which
allows delisting but never unpublishing -- still waits for a person.

MinVer is kept rather than replaced. It already produces preview versions with
no decision from anyone, and MINVERVERSIONOVERRIDE is its documented hook for an
external tool that has already chosen the version, so semantic-release hands it
the stable number and MinVer steps aside. Both read the same v* tags. Verified
by packing: all twelve packages stamp the overridden version.

The tag trigger and the publish job leave ci.yml, or the tag semantic-release
creates would publish the release a second time. The preview job refuses
outright to push a non-preview version rather than relying on --skip-duplicate,
since publishing a stable nobody cut is the failure this split exists to avoid.

Package validation now has a real baseline, which EnablePackageValidation has
been missing: semantic-release knows the last released version. The baseline is
skipped where a break is intended -- a major, or a minor while still pre-1.0.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
DocFX extracts the public surface of every package except the generator into
markdown under website/docs/api/, which sidebars.ts picks up as an autogenerated
category. The output is not committed -- deploy-docs.yml regenerates it, and
`npm run docs:api` does the same locally.

Three things this needed beyond running the tool, each found by building the
site rather than assuming:

- markdown.format is now 'detect', so .md is CommonMark. The generated pages are
  full of bare generic signatures like ValueObjectContract<TValueObject, TValue>
  which MDX parses as JSX and rejects outright. No hand-written page uses MDX.
- docfx-postprocess.py rewrites DocFX's raw <a id> heading anchors into
  Docusaurus heading ids, preserving the id so cross-references still resolve.
  Docusaurus otherwise nests its own anchor inside DocFX's, which is invalid
  HTML and produced 323 minifier diagnostics.
- DocumentationSnippetTests now excludes docs/api/. It compiles every published
  csharp block through the real generator, and generated member signatures are
  not declarations anyone wrote.

CLAUDE.md's per-suite test commands were also wrong: given a bare directory
dotnet test prints a hint and exits 0 without running anything, which reads
exactly like a pass. They now pass --project.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
A dry run against main showed semantic-release computing 1.0.0, not 0.1.0: it
ignores prerelease tags when the branch is not a prerelease channel, so
v0.1.0-preview.1 and .2 are invisible to it and it reads the repository as never
released. Three dry runs are tabulated in ADR-0003; a v0.0.0 tag at the initial
commit yields 0.1.0, continuing the preview line instead of skipping the whole
0.x range.

The tag could not be pushed from this session -- git-receive-pack returns 403
for refs/tags while branch pushes succeed -- so it is documented as a command to
run rather than silently left undone.

docs/maintaining.md collects the rest of the settings that live outside this
repository and that let a workflow succeed while doing nothing: auto-merge,
required checks, Pages source, Discussions, CODECOV_TOKEN, and the NuGet trusted
publisher, which has to name both ci.yml and release.yml now that previews and
stable releases are published by different workflows.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
The script skips a bare '<a id="x"></a>' with no heading text on purpose --
rewriting it would emit '## {#id}', an empty heading. The verification that
follows then counted that same heading as unconverted and returned 1, so the
one case the rewrite deliberately declines to touch was also the one case that
failed the docs build.

Not reachable with DocFX's current output, which always emits a title, so this
never fired here; found by running the script against a fixture while extracting
it as a reusable template. Verified against the real output: 323 anchors
rewritten, exit 0, and idempotent on a second run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
The workflow failed on every run with "CodeQL analyses from advanced
configurations cannot be processed when the default setup is enabled". The
analysis itself was fine -- the build succeeded and every query ran -- but
GitHub refuses the SARIF upload, so the job could never go green.

Default setup was already enabled on this repository and already passing, which
an audit that reads the file tree cannot see: it is a repository setting, not a
file. Adding codeql.yml duplicated coverage that existed rather than adding any.

Deleting the workflow rather than disabling default setup: the advanced
configuration's only advantage here was a manual build step for the mixed
netstandard2.0/net10.0 solution, and default setup builds it without help.

The README badge pointed at the deleted workflow, so it goes too; default setup
has no workflow to badge. docs/maintaining.md records the decision and what
would justify revisiting it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CmFH2YU1sNDRtgWStye15J
@AdCodicem
AdCodicem merged commit 7cbf554 into main Sep 15, 2026
9 checks passed
@AdCodicem
AdCodicem deleted the claude/dotnet-repo-upgrade-xefbjy branch September 15, 2026 20:04
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.

2 participants