Skip to content

refactor!: rename the packages and namespace to Reefact.AspNetCore.* - #80

Merged
Reefact merged 2 commits into
mainfrom
claude/rename-package-ids
Aug 12, 2026
Merged

refactor!: rename the packages and namespace to Reefact.AspNetCore.*#80
Reefact merged 2 commits into
mainfrom
claude/rename-package-ids

Conversation

@Reefact

@Reefact Reefact commented Aug 12, 2026

Copy link
Copy Markdown
Owner

Summary

nuget.org refuses AspNetCore.EnumMemberNameBinding: AspNetCore.* is a reserved prefix, and
a push under it is answered 409 Conflict. That is the entire publication failure this repository
has been chasing since 1.0.0-beta.1 — not the credentials, not trusted publishing, not the
workflow. Nothing about the packages was wrong except their name.

The message, obtained by uploading the same .nupkg through nuget.org's web interface, which
prints what the API returns and the CLI discards:

The package ID is reserved. You can upload your package with a different package ID.

Type of change

  • Bug fix
  • New feature
  • Breaking change to the public API
  • Refactoring
  • Analyzer / diagnostic change
  • Tests
  • Documentation
  • Build / CI / tooling

Changes

before after
package AspNetCore.EnumMemberNameBinding Reefact.AspNetCore.EnumMemberNameBinding
companion AspNetCore.EnumMemberNameBinding.OpenApi Reefact.AspNetCore.EnumMemberNameBinding.OpenApi
namespace AspNetCore.EnumMemberNameBinding Reefact.AspNetCore.EnumMemberNameBinding
version 1.0.0-beta.3

Reefact.* is a prefix this account has reserved, so the packages publish and carry the verified
owner mark — which is the only trust signal a package with no downloads yet has to offer.

The namespace moves too, not only the PackageId, and the refusal is the argument: a
top-level AspNetCore namespace claims a name this library does not own, in the one place where
nobody enforces it. Leaving it would ship a Reefact.* package containing an AspNetCore.*
assembly declaring an AspNetCore.* namespace — three names for one thing. Nothing has ever been
published, so this is the only moment the change costs nothing.

Mechanically it is one prefix added in front of 182 occurrences, applied as a substitution with
a negative lookbehind rather than by hand. Measured before touching anything: no occurrence was
already prefixed, and no line held both Microsoft.AspNetCore and this name — so there was nothing
for it to collide with or apply twice to.

Also here: 1.0.0-beta.2 gains a changelog section of its own, and 1.0.0-beta.1's is corrected.
It recorded the 409 and said the cause was unknown, which was true when written and is not now.

Testing

  • dotnet build -c Release — 0 errors, 0 warnings
  • dotnet test -c Release — 972 tests (109 + 613 + 58 + 192), including the 192 documentation
    tests that recompile every C# sample in the pages
  • tests/PackageSmokeTest/run.shThe published package behaves as documented.
  • tools/packaging/verify-packages.sh on a fresh dotnet pack -p:Version=1.0.0-beta.3, both
    packages accepted
  • verify-published.test.sh, changelog-section.test.sh, lint-layout.test.sh,
    lint-layout.sh

Two things the substitution could not see, and neither was found by reading:

  1. Three identifiers written in lowercase, because the flat container indexes that way.
    verify-published.test.sh failed on the "both packages present" case — precisely the
    half-rename it was written to catch.
  2. build/*.targets, whose file name must equal the package id or NuGet refuses to pack it.
    The smoke test stopped at NU5019.

Both are fixed and both checks pass. They are the reason this PR is worth more than a search and
replace.

Public API

  • No change to the public surface
  • The surface changed and the baseline was updated in the same commit

Every public type changes namespace. PublicAPI.Shipped.txt moved with its project and its
contents were rewritten in the same commit; the build is the proof, since RS0016/RS0017 fail it
on any mismatch and warnings are errors here.

Documentation

  • README / docs/ updated
  • The French counterpart was updated to match
  • CHANGELOG.md and docs/for-users/CHANGELOG.fr.md both updated
  • No documentation change required

Ten headings and sixty-five bullets on each side. The extractor returns 429 lines for
1.0.0-beta.3, 5 for 1.0.0-beta.2, 9 for 1.0.0-beta.1, and still refuses Unreleased.

Migration

None to perform. Neither package has ever been published under the old name, so no consumer can be
holding one. Anyone working from this repository's own history adds Reefact. in front of the
package reference and the using.

After merging

v1.0.0-beta.1 and v1.0.0-beta.2 are spent — tagged, never published, and the v* ruleset
forbids moving or deleting a tag. The next tag is v1.0.0-beta.3, and the release will now fail
loudly rather than silently if the feed still does not have the packages.


Generated by Claude Code

claude added 2 commits August 12, 2026 14:51
nuget.org refuses `AspNetCore.EnumMemberNameBinding`: `AspNetCore.*` is a
reserved prefix, and a push under it is answered 409 Conflict. That is the whole
of the publication failure this repository has been chasing since 1.0.0-beta.1 —
not the credentials, not trusted publishing, not the workflow. Two tags were
spent on it, and no rerun of either could ever have worked, because nothing
about the packages was wrong except their name.

The identifier is now `Reefact.AspNetCore.EnumMemberNameBinding`, under a prefix
this account has reserved — so the packages publish, and carry the verified
owner mark that a package with no downloads yet has nothing else to offer.

The namespace moves with it rather than only the PackageId, and the refusal is
the argument: a top-level `AspNetCore` namespace claims a name this library does
not own, in the one place where nobody enforces it. Leaving it would ship a
`Reefact.*` package containing an `AspNetCore.*` assembly declaring an
`AspNetCore.*` namespace — three names for one thing. Nothing is published, so
this is the only moment the change costs nothing.

Mechanically it is one prefix added in front of 182 occurrences, which is why it
was done as a substitution with a negative lookbehind rather than by hand: no
occurrence was already prefixed, no line held both `Microsoft.AspNetCore` and
this name, so there was nothing for it to collide with or apply twice to.

Two things the substitution could not see, and both were caught by the checks
rather than by reading:

- Three identifiers written in lowercase, because the flat container indexes
  that way. `verify-published.test.sh` failed on the "both packages present"
  case, which is exactly the half-rename it exists to catch.
- `build/*.targets`, whose file name has to equal the package id or NuGet
  refuses to pack it. The smoke test stopped at NU5019.

972 tests, the smoke test, both packaging checks and the layout linter pass. The
API baseline moved in this commit, as the surface did.

BREAKING CHANGE: every public type moves from the AspNetCore.EnumMemberNameBinding
namespace to Reefact.AspNetCore.EnumMemberNameBinding, and both package ids gain
the same prefix. There is no migration to perform: neither package has ever been
published under the old name, so no consumer can be holding one. A reader coming
from the repository's own history updates the package reference and the using
directive, both by adding `Reefact.` in front.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcQ3umdkRNsR7FRB9s2P2w
The section renames rather than being rewritten — nothing about the library
changed between beta.2 and beta.3 — but it gains what a reader installing this
actually needs first: the packages are called something else now, and why.

beta.2 gets a section of its own beside beta.1, because a changelog that skips a
version invites the reader to go looking for it. It says the one thing that
distinguishes the two attempts: beta.1 reported success with nothing on the feed,
beta.2 failed and named what was missing. That is the step added between them
doing its job, and it is what turned an unexplained silence into a question
narrow enough to answer in an hour.

beta.1's entry is corrected rather than left as written. It recorded the 409 and
said the cause was unknown, which was true when it was written and is not now:
the identifier was refused because `AspNetCore.*` is reserved. Leaving a
known-wrong "cause unknown" in the record is worse than not having written it.

Both languages carry the same structure — ten headings, sixty-five bullets — and
the extractor returns 429 lines for beta.3, 5 for beta.2, 9 for beta.1, and still
refuses Unreleased by name.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GcQ3umdkRNsR7FRB9s2P2w
@Reefact
Reefact merged commit abe8961 into main Aug 12, 2026
10 checks passed
@Reefact
Reefact deleted the claude/rename-package-ids branch August 12, 2026 14:55
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