Publish hygiene + multi-tenancy guard-docs (P3 — Federation/Foundation)
Filing target: github.com/wangkanai/federation and
github.com/wangkanai/foundation, Priority P3
(per research 009 §8
P3 publish-hygiene + P3 multi-tenancy guard-docs rows).
Motivated by: research
agile/research/009-refactoring-shared-federation-domain-from-account/report.md
§8 P3 rows (line 117 + line 118). Drafted from epic
031-oss-contribution-parallel-track/031-05-p2-p3-items-tracker-small-contributions.
Problem statement
Two P3 hygiene gaps on wangkanai/federation and wangkanai/foundation
make consumer adoption harder than the upstream packages intend. Both
gaps are small in scope and small in cost to close; together they
unblock the consumption story that the P0 license and P1 model gaps
in 031-01 / 031-02 / 031-03 / 031-04 are otherwise paving.
Gap A — Stale NuGet publish (009 §8 P3, line 117)
The published NuGet package Wangkanai.Federation 3.0.0 still carries
net8 / Apache-2.0 metadata from a prior monorepo state (per
research 009 §5 F6). The current main branch:
- targets
net9 / net10 (not net8),
- has changed license posture (the F7 raw-
LICENSE-vs-README/nuspec
mismatch — the P0 issue 031-01),
- still has no concrete permission/tenant/etc. POCOs (the F6
"Planned Features" gap that the P1 issues 031-02 / 031-03 / 031-04
are requesting).
The 3.0.0 package is therefore stale on three independent axes: target
framework, license, and feature surface. Consumers who pin 3.0.0 get
the wrong story on all three. Consumers who try to pin main directly
have no published artifact to pin against.
Gap B — No public domain-entity guardrail docs (009 §8 P3, line 118)
wangkanai/federation and wangkanai/foundation ship base entity shapes
(Entity, AuditableEntity) but do not currently publish guidance on
the conventions that make domain-entity types safely composable across
the DDD + permission-matrix boundary. Two patterns are well-proven in
RiverSync's Account IdP but are absent from any public upstream doc:
RolePermission_Has_No_ClaimsCompiler_Logic guard. A
reflection-based test bans the runtime method names Compile /
Evaluate / Build on the link entity so a future contributor
cannot smuggle compiler logic into the schema-only POCO.
- Scalar-FK aggregate convention. FKs are declared as
Guid
scalars (no navigation properties), so consumers with different
ORM conventions (Dapper, EF, raw ADO.NET) can map the entity
without fighting the upstream type.
Both patterns are small, copy-paste-able, and load-bearing: every
permission-style entity in RiverSync's Account.Domain.Authorization
follows them, and the absence of upstream documentation means every
consumer re-discovers the convention (or fails to discover it).
RiverSync usage context
RiverSync is a six-app product platform. Its OIDC identity-provider role
is centralized in a single application (Account); the other five
(Portal, Admin, Partners, Pipeline, Field) participate strictly
as OIDC relying parties. The following four anchors explain why a P3
hygiene ask matters to us — and why we are framing it as a small
publish + docs ask rather than a feature request.
-
Thin Common foundation (epic 029).
Epic 029 — Common OSS Foundation Layer
establishes RiverSync.Common.Domain as a thin shell depending on
Wangkanai.Domain and Wangkanai.System. The Foundation spike that
029 §5 recommended (1-day; migrate timestamps to AuditableEntity)
is the kind of consumption-validation work that benefits from a
current NuGet publish of wangkanai/foundation.
-
Planned thin Common overlays on Foundation (epic 030).
Epic 030 — Extract Federation Domain Models To Common
is the follow-on that would push consumable model shapes
(PermissionInfo, RolePermissionInfo) into Common.Domain. The
P3 publish-hygiene ask is the precondition: without a current
NuGet artifact, 030 cannot pin wangkanai/foundation cleanly.
-
Local DM-33 schema-only guard pattern (proven).
The RolePermission_Has_No_ClaimsCompiler_Logic reflection-based
guard at
Account/test/Unit/Authorization/RolePermissionTests.cs:39-56
bans runtime method names Compile / Evaluate / Build on
RolePermission so a future contributor cannot smuggle compiler
logic into the schema-only POCO. The test itself is the
documentation — it tells the next contributor what the
link-entity shape contract IS. We would like this convention
to ship as a docs / guidance ask on the upstream side so
consumers don't re-invent (or omit) it.
-
Local FK-scalar convention (FR-006).
RiverSync's Account.Domain.Authorization.Permission and
RolePermission are FK-free / FK-scalar respectively
(Account/src/Domain/Authorization/Permission.cs:9-28
and
Account/src/Domain/Authorization/RolePermission.cs:39-70).
The same convention lives on ApplicationUser.TenantId (Account/src/Domain/Identity/ApplicationUser.cs:26-33)
and across the rest of Account.Domain. Again — it is load-bearing
and undocumented upstream.
No timeline promises (explicit)
To be unambiguous about what this issue is not asking:
- No timeline promise. This issue does not commit RiverSync to any
particular release date for adopting any upstream release. Internal
sequencing is governed separately by our own epic planning and may
change without notice to this issue.
- No adoption commitment. RiverSync has not committed to taking a
hard Wangkanai.Federation (or Wangkanai.Foundation) dependency
even after this issue is resolved. The thin Common strategy in
029/030 is OSS-agnostic and is being executed on Wangkanai.Domain
- No licensing-philosophy request. License clarity is a separate
concern, already tracked in the P0 issue (031-01, Filed upstream).
This P3 ask presumes the P0 resolution; we are not asking the
P3 question to be answered in a way that contradicts the P0
resolution.
- No code contribution attached. This is a publish-hygiene +
docs ask, not a roadmap sketch. We are happy to review any
proposed wording and to share a brief non-binding read of how
the resolution would land on our side — none of that is contingent
on the resolution itself.
Request
We respectfully ask the wangkanai/federation and wangkanai/foundation
maintainers to consider two coordinated P3 hygiene changes. They are
small and order-independent.
1. Re-publish Wangkanai.Federation against current main
- Target framework. Publish against
net9 and/or net10 (the
current TFM in main); deprecate or mark the net8 3.0.0 line
as superseded.
- License metadata. Once the P0 issue (031-01) is resolved,
re-publish with the agreed license propagated to:
- the NuGet
.nuspec <license> element,
- the package's
LICENSE embedded resource,
- the package's README fragment.
Coordinate with the P0 ask so the published package's metadata
matches the in-tree LICENSE and README.md.
- Versioning. A minor-version bump (e.g.
4.0.0) signals "this
is the new current line, do not pin 3.0.0." A CHANGELOG / release
note entry should explicitly call out the F6 "Planned Features"
status (the package still ships the planned-features surface — the
bump is for hygiene, not for new models) so consumers can re-pin
deliberately without expecting new features.
2. Publish a domain-entity guardrails note (Foundation or Federation)
A short companion document (call it GUARDRAILS.md or similar) that
documents two conventions currently absent from upstream docs:
The note should be short (one to two pages), live at the repo root
(or under docs/), and ship with the next minor publish. It does
not need to ship a new base type — the guardrails describe the
use of the existing Entity / AuditableEntity bases.
What we are NOT asking for
- No new permission/tenant/etc. POCO types (the P1 issues 031-02 /
031-03 / 031-04 cover those).
- No change to upstream's licensing philosophy (tracked separately in
P0, 031-01).
- No specific ORM shape — the FK-scalar convention is configurable in
the consumer's mapping, not embedded in the upstream type.
- No change to the runtime behavior of any existing
Entity /
AuditableEntity consumer. This is docs + publish hygiene only.
Why now
These are pre-existing gaps, not new regressions — but the timing is
right for three converging reasons that make the publish + docs ask
visible from a multi-app product platform's perspective:
- The P0 license issue (031-01) is already Filed. The
publish-hygiene half of this P3 ask explicitly presumes the P0
resolution (the re-publish needs to propagate the agreed license
metadata). Filing the P3 now lets the maintainer sequence the
publish work alongside P0 rather than after.
- The P1 model asks (031-02 / 031-03 / 031-04) are Filed or in
flight. Once the P1 work lands upstream, consumers will want to
pin the new shapes — and "the new shapes are in the in-tree commit
but not in the published artifact" is exactly the gap the publish
ask closes. Doing the publish-hygiene work now (rather than
waiting for the P1 PRs to land) means the consumer can do a
single coordinated pin later, not three staggered ones.
- The guardrails note is a 1-day copy-paste. The DM-33 schema-only
guard test and the FR-006 scalar-FK convention already exist in
RiverSync's shipping code. A GUARDRAILS.md for upstream is a
paragraph-long restatement of patterns that are already proven in
a shipped project. The cost to upstream is small; the cumulative
cost to every consumer who re-discovers the convention locally is
measurable.
Without the publish-hygiene half, the P0/P1 chain ends in a "the
metadata is right in the tree but wrong on nuget.org" state that
defeats the upstream narrative. Without the guardrails note, every
multi-app consumer re-derives the same two conventions independently.
References
Drafted by RiverSync for upstream filing against wangkanai/federation
(and wangkanai/foundation for the GUARDRAILS.md half). Not yet
filed. Once filed, the upstream URL will replace this header note and
the tracker row in docs/oss-contributions.md
will be updated to Filed.
Publish hygiene + multi-tenancy guard-docs (P3 — Federation/Foundation)
Problem statement
Two P3 hygiene gaps on
wangkanai/federationandwangkanai/foundationmake consumer adoption harder than the upstream packages intend. Both
gaps are small in scope and small in cost to close; together they
unblock the consumption story that the P0 license and P1 model gaps
in 031-01 / 031-02 / 031-03 / 031-04 are otherwise paving.
Gap A — Stale NuGet publish (009 §8 P3, line 117)
The published NuGet package
Wangkanai.Federation3.0.0 still carriesnet8 / Apache-2.0 metadata from a prior monorepo state (per
research 009 §5 F6). The current
mainbranch:net9/net10(notnet8),LICENSE-vs-README/nuspecmismatch — the P0 issue 031-01),
"Planned Features" gap that the P1 issues 031-02 / 031-03 / 031-04
are requesting).
The 3.0.0 package is therefore stale on three independent axes: target
framework, license, and feature surface. Consumers who pin 3.0.0 get
the wrong story on all three. Consumers who try to pin
maindirectlyhave no published artifact to pin against.
Gap B — No public domain-entity guardrail docs (009 §8 P3, line 118)
wangkanai/federationandwangkanai/foundationship base entity shapes(
Entity,AuditableEntity) but do not currently publish guidance onthe conventions that make domain-entity types safely composable across
the DDD + permission-matrix boundary. Two patterns are well-proven in
RiverSync's
AccountIdP but are absent from any public upstream doc:RolePermission_Has_No_ClaimsCompiler_Logicguard. Areflection-based test bans the runtime method names
Compile/Evaluate/Buildon the link entity so a future contributorcannot smuggle compiler logic into the schema-only POCO.
Guidscalars (no navigation properties), so consumers with different
ORM conventions (Dapper, EF, raw ADO.NET) can map the entity
without fighting the upstream type.
Both patterns are small, copy-paste-able, and load-bearing: every
permission-style entity in RiverSync's
Account.Domain.Authorizationfollows them, and the absence of upstream documentation means every
consumer re-discovers the convention (or fails to discover it).
RiverSync usage context
RiverSync is a six-app product platform. Its OIDC identity-provider role
is centralized in a single application (
Account); the other five(
Portal,Admin,Partners,Pipeline,Field) participate strictlyas OIDC relying parties. The following four anchors explain why a P3
hygiene ask matters to us — and why we are framing it as a small
publish + docs ask rather than a feature request.
Thin Common foundation (epic 029).
Epic 029 — Common OSS Foundation Layer
establishes
RiverSync.Common.Domainas a thin shell depending onWangkanai.DomainandWangkanai.System. The Foundation spike that029 §5 recommended (1-day; migrate timestamps to
AuditableEntity)is the kind of consumption-validation work that benefits from a
current NuGet publish of
wangkanai/foundation.Planned thin Common overlays on Foundation (epic 030).
Epic 030 — Extract Federation Domain Models To Common
is the follow-on that would push consumable model shapes
(
PermissionInfo,RolePermissionInfo) intoCommon.Domain. TheP3 publish-hygiene ask is the precondition: without a current
NuGet artifact, 030 cannot pin
wangkanai/foundationcleanly.Local DM-33 schema-only guard pattern (proven).
The
RolePermission_Has_No_ClaimsCompiler_Logicreflection-basedguard at
Account/test/Unit/Authorization/RolePermissionTests.cs:39-56bans runtime method names
Compile/Evaluate/BuildonRolePermissionso a future contributor cannot smuggle compilerlogic into the schema-only POCO. The test itself is the
documentation — it tells the next contributor what the
link-entity shape contract IS. We would like this convention
to ship as a docs / guidance ask on the upstream side so
consumers don't re-invent (or omit) it.
Local FK-scalar convention (FR-006).
RiverSync's
Account.Domain.Authorization.PermissionandRolePermissionare FK-free / FK-scalar respectively(
Account/src/Domain/Authorization/Permission.cs:9-28and
Account/src/Domain/Authorization/RolePermission.cs:39-70).The same convention lives on
ApplicationUser.TenantId(Account/src/Domain/Identity/ApplicationUser.cs:26-33)and across the rest of
Account.Domain. Again — it is load-bearingand undocumented upstream.
No timeline promises (explicit)
To be unambiguous about what this issue is not asking:
particular release date for adopting any upstream release. Internal
sequencing is governed separately by our own epic planning and may
change without notice to this issue.
hard
Wangkanai.Federation(orWangkanai.Foundation) dependencyeven after this issue is resolved. The thin Common strategy in
029/030 is OSS-agnostic and is being executed on
Wangkanai.DomainWangkanai.Systemtoday.concern, already tracked in the P0 issue (031-01, Filed upstream).
This P3 ask presumes the P0 resolution; we are not asking the
P3 question to be answered in a way that contradicts the P0
resolution.
docs ask, not a roadmap sketch. We are happy to review any
proposed wording and to share a brief non-binding read of how
the resolution would land on our side — none of that is contingent
on the resolution itself.
Request
We respectfully ask the
wangkanai/federationandwangkanai/foundationmaintainers to consider two coordinated P3 hygiene changes. They are
small and order-independent.
1. Re-publish
Wangkanai.Federationagainst currentmainnet9and/ornet10(thecurrent TFM in
main); deprecate or mark thenet83.0.0 lineas superseded.
re-publish with the agreed license propagated to:
.nuspec<license>element,LICENSEembedded resource,Coordinate with the P0 ask so the published package's metadata
matches the in-tree
LICENSEandREADME.md.4.0.0) signals "thisis the new current line, do not pin 3.0.0." A
CHANGELOG/ releasenote entry should explicitly call out the F6 "Planned Features"
status (the package still ships the planned-features surface — the
bump is for hygiene, not for new models) so consumers can re-pin
deliberately without expecting new features.
2. Publish a domain-entity guardrails note (Foundation or Federation)
A short companion document (call it
GUARDRAILS.mdor similar) thatdocuments two conventions currently absent from upstream docs:
RolePermission_Has_No_ClaimsCompiler_Logic-style schema-onlyguard. Domain entities that participate in the role/permission
matrix MUST NOT carry runtime methods named
Compile/Evaluate/Build. A reflection-based test (with the banned-member listenumerated explicitly) is the recommended enforcement. The pattern
reference is
Account/test/Unit/Authorization/RolePermissionTests.cs:39-56.FK-scalar aggregate convention. Foreign keys are declared as
Guid(or analogous scalar) properties — NOT navigation properties— so consumers can configure their own ORM mapping (Dapper, EF,
raw ADO.NET, custom repositories) without fighting the upstream
type. The pattern reference is
Account/src/Domain/Authorization/Permission.cs:9-28(FK-free) and
Account/src/Domain/Authorization/RolePermission.cs:22-71(FK-scalar).
The note should be short (one to two pages), live at the repo root
(or under
docs/), and ship with the next minor publish. It doesnot need to ship a new base type — the guardrails describe the
use of the existing
Entity/AuditableEntitybases.What we are NOT asking for
031-03 / 031-04 cover those).
P0, 031-01).
the consumer's mapping, not embedded in the upstream type.
Entity/AuditableEntityconsumer. This is docs + publish hygiene only.Why now
These are pre-existing gaps, not new regressions — but the timing is
right for three converging reasons that make the publish + docs ask
visible from a multi-app product platform's perspective:
publish-hygiene half of this P3 ask explicitly presumes the P0
resolution (the re-publish needs to propagate the agreed license
metadata). Filing the P3 now lets the maintainer sequence the
publish work alongside P0 rather than after.
flight. Once the P1 work lands upstream, consumers will want to
pin the new shapes — and "the new shapes are in the in-tree commit
but not in the published artifact" is exactly the gap the publish
ask closes. Doing the publish-hygiene work now (rather than
waiting for the P1 PRs to land) means the consumer can do a
single coordinated pin later, not three staggered ones.
guard test and the FR-006 scalar-FK convention already exist in
RiverSync's shipping code. A
GUARDRAILS.mdfor upstream is aparagraph-long restatement of patterns that are already proven in
a shipped project. The cost to upstream is small; the cumulative
cost to every consumer who re-discovers the convention locally is
measurable.
Without the publish-hygiene half, the P0/P1 chain ends in a "the
metadata is right in the tree but wrong on nuget.org" state that
defeats the upstream narrative. Without the guardrails note, every
multi-app consumer re-derives the same two conventions independently.
References
multi-tenancy guard-docs row (line 118); §5 F6 (Federation
"Planned Features" + stale 3.0.0 package); F7 (raw-
LICENSE-vs-README/nuspec mismatch, sibling P0 issue) —
agile/research/009-refactoring-shared-federation-domain-from-account/report.mdARCH:VI(Account as sole identity issuer; RP-onlyfederation) —
.claude/rules/architecture/federation-auth.mdagile/epics/029-common-oss-foundation-layer/epic.mdPermissionInfo/RolePermissionInfooverlays) —agile/epics/030-extract-federation-domain-models-to-common/epic.mdterms) —
agile/epics/031-oss-contribution-parallel-track/031-01-p0-license-metadata-issue/Tenant+(email,tenant), 031-04 codec) —
agile/epics/031-oss-contribution-parallel-track/github.com/wangkanai/federation
github.com/wangkanai/foundation
nuget.org/packages/Wangkanai.Federation/3.0.0
RolePermission_Has_No_ClaimsCompiler_Logicschema-only guard pattern (DM-33) —
Account/test/Unit/Authorization/RolePermissionTests.cs:39-56RolePermissionlink entity —Account/src/Domain/Authorization/RolePermission.cs:22-71Permissiongrant-key entity —Account/src/Domain/Authorization/Permission.cs:9-28TenantIdonApplicationUser—Account/src/Domain/Identity/ApplicationUser.cs:26-33Drafted by RiverSync for upstream filing against
wangkanai/federation(and
wangkanai/foundationfor theGUARDRAILS.mdhalf). Not yetfiled. Once filed, the upstream URL will replace this header note and
the tracker row in
docs/oss-contributions.mdwill be updated to
Filed.