You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Filing target: github.com/wangkanai/federation (with fallback to a shared claims package, same target as the P1 codec filing at #42) — Feature request, Priority P2 (per research 009 §8
P2 row, line 115).
Status of siblings: P0 (license consistency, 031-01) is Filed upstream per the tracker. P1 (031-02 scoped Permission / RolePermission,
031-03 multi-tenant Tenant, 031-04 codec + value-type primitives) are all Filed
in this series. This issue is the P2 enhancement half — the resolved
entitlement shape + per-app AppKey matrix beyond the codec/value-type primitives.
Defer note — already filed in P1: the deterministic v1: / v1z: packed perm
codec + the PermScope / PermScopeMap value-type primitives (the per-permission
scope half of the AccessScope model) are out of scope for this P2 ask and
already filed at #42 — WASM-safe PermScope + AccessScope value types and deterministic v1:/v1z: packed perm codec.
This P2 issue deliberately asks for the consumption-side shape (the resolved
entitlement + per-app AppKey matrix) on top of those primitives, NOT for a
separate scope-discriminated value type.
Problem statement
A consumer of wangkanai/federation who needs the resolved-access
entitlement shape (the per-app AppKey matrix plus the (App, Perm) → Scope
map) currently has to re-implement that shape from scratch. The codec
primitives and the per-permission PermScope value type are covered by the
P1 filing at #42; what is missing is the higher-level consumption shape
that the resolver produces and that the Seq 3 claims compiler consumes:
The discriminated AccessScope value type with an only-narrowing Intersect truth table — three cases (OrgWide, Region(Id), Site(Id))
with the closed-set-by-construction pattern.
The resolved-access record (ResolvedAccess) carrying the four
components every later pipeline stage reads:
EntitledAppKeys (the apps after the layer-1 entitlement gate),
AppToRoleId (exactly one role per entitled app, the UNIQUE(UserId, AppKey) invariant),
Permissions (the resolved (app, perm) → scope map),
TenantId (the resolution's tenant).
The Application (AppKey) entity carrying the per-app discriminator
that scopes a role to one application — the AppKey string that keys ApplicationUserRole and makes the unique-role rule (RoleName, AppKey) rather than (RoleName, ApplicationId).
These three shapes together are what every federated consumer actually
consumes; without them, every consumer re-derives the truth table
(AccessScope.Intersect), the four-component record layout, and the AppKey string contract. The P1 codec filing covers the per-permission
half; this P2 filing covers the resolved-entitlement + per-app matrix half.
RiverSync ships a production implementation of all three primitives in Account/src/Application/Authorization/AccessScope.cs, Account/src/Application/Authorization/ResolvedAccess.cs, and Account/src/Domain/Authorization/Application.cs. We are asking upstream to
expose consumption-side shapes (a reusable AccessScope value type, a ResolvedAccess record, an Application (AppKey) entity) with the
contracts the next section pins, so that:
A consumer integrating with wangkanai/federation can resolve a
federated principal into a typed (entitled apps, role per app, per-permission scope, tenant) record instead of re-deriving it.
The AccessScope.Intersect truth table — the only-narrowing
invariant that FED-10 (the one-way denial rule) leans on — becomes
reusable across consumers instead of every consumer re-deriving the
truth table from a written spec.
The AppKey string contract (the per-app discriminator that scopes a
role to one application) is owned upstream so cross-consumer
entitlement checks can compare (app, perm) keys on equal terms.
internal generalization of AccessScope to Common.Domain (Status IMPLEMENTED) — the local mirror of this upstream ask
RiverSync context
This P2 ask is grounded in four local anchors — without them, the
upstream framing reads as a request for new shapes. With them, it
reads as a request to publish shapes RiverSync has already validated
in production.
Epic 029-03 — generalized scope/claim primitives — the same
029 spike is the foundation. The AccessScope value type
(Account/src/Application/Authorization/AccessScope.cs) was
generalized into Common.Domain as part of the 029-03 track
(Status IMPLEMENTED). The upstream ask is for the same shape
to live in wangkanai/federation (or a sibling package) so the
Federation consumers get it without the 029-03 spike.
Epic 030 — thin shapes — these entitlement types would live in Common.Domain (per the 030 thin-extraction plan). The 030 epic is
the in-tree surface for the shapes this issue asks upstream to
publish. RiverSync does not duplicate them: 030 is the consumer,
not the source, of any upstream shape.
ARCH:VI — AccessScope is the consumption shape; Account is the
only writer — per .claude/rules/architecture/federation-auth.md,
Account is the sole platform OIDC/OAuth2 identity provider AND the
sole writer of the persisted role↔permission matrix. AccessScope
is the consumption shape the resolver produces; it is not an
issuer shape. The five non-Account product apps (Portal, Admin,
Partners, Pipeline, Field) participate strictly as OIDC relying
parties; none of them persists a role↔permission matrix. This P2
ask is for the consumption shape on top of the codec primitives,
not for a new IdP library.
No timeline promises (explicit)
No commitment to a specific RiverSync release date for adopting any
upstream release.
No commitment that this draft binds RiverSync to take a hard Wangkanai.Federation dependency even after resolution.
No request that upstream change their licensing philosophy.
Internal sequencing of RiverSync's adoption is governed separately
and may change without notice.
Request
We respectfully ask the wangkanai/federation maintainers to ship the
following three coordinated consumption-side shapes so the resolved-access
per-app AppKey matrix is consumable from upstream packages, not just
from RiverSync's Account.Application:
1. A reusable AccessScope value type with only-narrowing Intersect
Shape: abstract record AccessScope with a private constructor
forcing the closed set; three sealed nested records:
OrgWide (no Id, no inline suffix on the wire),
Region(Guid Id) (narrowed to a single Region.Id),
Site(Guid Id) (narrowed further to a single OrganizationSite.Id).
Type system enforces the closed set — analogous to AccessScope.cs:28-30 (abstract record + private ctor + sealed nested
records). The resolver never constructs a custom scope type;
narrowing is the only operation that produces new values.
Factories for resolver-only construction:
OrgWideInstance (shared singleton for the common case),
Region ∩ Site (in either order) is the resolver's call — pure
method returns null; the caller looks up site.RegionId.
Pure on the discriminated values — Intersect MUST NOT take a
dependency on the entity store; putting the Region ∩ Site branch
in the resolver (not here) keeps AccessScope free of any reference
to the 013 store, mirrors AccessScope.cs:109-117.
2. A ResolvedAccess consumption record
Shape: public sealed record ResolvedAccess(...) with the
four-component signature RiverSync uses today
(ResolvedAccess.cs:53-57):
IReadOnlyList<string> EntitledAppKeys — the apps the user is
entitled to after the layer-1 entitlement gate.
IReadOnlyDictionary<string, Guid> AppToRoleId — exactly one role
per entitled app (the UNIQUE(UserId, AppKey) invariant; no
role-union). Carries the role FK scalar only.
IReadOnlyDictionary<(string AppKey, string PermKey), AccessScope> Permissions —
the resolved (app, perm) → scope map. Denied rows are absent
(FED-10: they can never reappear).
Guid TenantId — the tenant the resolution is scoped to; always
set; Guid.Empty for the Empty sentinel.
Closed by construction — primary constructor is the only public
surface; the resolver builds one per sign-in and hands it to
callers; nothing outside the resolver package is expected to mutate
it.
OIDC-agnostic — the record MUST NOT reference any token-issuance
SDK type. The Seq 3 claims compiler in 015-02 maps ResolvedAccess
onto a federated principal; that mapping is the seam that joins the
resolver to the rest of the platform. Mirrors ResolvedAccess.cs:35-40.
Equality is structural — sealed record makes equality
value-based on all four components. Empty therefore compares equal
to any other ResolvedAccess built from the four empty singletons
(the desired behaviour for error paths and "no access" results).
A typed Empty sentinel — ResolvedAccess.Empty for the
"no access" case without per-call allocation
(ResolvedAccess.cs:65-69).
3. An Application (AppKey) entity
Shape: public class Application carrying:
Guid Id (stable key),
string AppKey (per-app discriminator, the human-readable string
e.g. "portal"),
The AppKey-not-Id contract — the unique-role rule is (RoleName, AppKey), NOT (RoleName, ApplicationId). Mirrors Application.cs:9 ("(RoleName, AppKey) rather than (RoleName, ApplicationId)"). This is the most often-missed contract
on the per-app matrix; making it explicit upstream prevents consumers
from accidentally keying on the surrogate Id and producing roles
that don't compose across apps.
AppKey is the wire-level cross-consumer contract — when a
federated token carries an (App, Perm) key, the App half is the AppKey string. Consumers comparing entitlement keys compare AppKey strings, not Id GUIDs.
Why now
The P1 codec filing at #42 covers the per-permission half (the PermScope / PermScopeMap value types and the deterministic v1: / v1z: packed perm codec). The P1 scopes-Permission / RolePermission
filing at #43 covers the role↔permission matrix with Allowed + ScopeRegionId / ScopeSiteId + one-way narrowing. The P1
multi-tenant Tenant / (email, tenant) filing at #41 covers the tenant identity invariant.
What is not yet covered is the consumption-side shape: the
resolved-access record the resolver produces, the AppKey matrix that
scopes roles to one application, and the discriminated AccessScope
value type that ties it all together. These are the primitives every
later pipeline stage reads; without them, every consumer re-derives the
truth table, the four-component record layout, and the AppKey string
contract from a written spec.
The P2 framing is the right altitude for this ask: the codec
primitives are P1 because the wire contract stabilizes immediately on
issue, but the consumption-side shapes are P2 because they are
designed-for-reuse rather than wire-critical — a consumer can survive
without them, just with more boilerplate.
Scope — what this issue is and is not
This issue IS asking for
A reusable AccessScope value type with the only-narrowing Intersect
contract (three cases, abstract record + private ctor + sealed nested
records, factories, pure Intersect).
A ResolvedAccess consumption record (four components, structural
equality, Empty sentinel, OIDC-agnostic).
An Application (AppKey) entity carrying the per-app discriminator
string and the AppKey-not-Id unique-role contract.
This issue is NOT asking for
A second PermScope value type — the per-permission PermScope
A new authorization-server / IdP library — the per-app matrix
and the AppKey contract are consumption shapes, not issuer
shapes. The ResolvedAccess record is OIDC-agnostic by design (per ResolvedAccess.cs:35-40); the per-app matrix is not an OpenIddict / OpenIdConnect artifact.
A new Wangkanai.Federation.Claims package — target the existing wangkanai/federation repo unless upstream indicates a split.
A timeline commitment from RiverSync — RiverSync plans to adopt
these shapes in Common.Domain once published, on its own internal
sequencing (governed separately, without notice).
References
RiverSync artifacts (cited verbatim above)
Account/src/Application/Authorization/AccessScope.cs:28-30 — abstract record + private ctor (closed set by design).
agile/research/009-refactoring-shared-federation-domain-from-account/report.md §7 Option A, line 65 — the recommended layering (extract reusable value types in Common; keep full persisted entities in Account).
agile/research/009-refactoring-shared-federation-domain-from-account/report.md §6 — analysis of the current OSS state vs. RiverSync usage.
No request that RiverSync's Account is to be replaced — Account
remains the sole persisted role↔permission matrix per ARCH:VI; this
ask is for the consumption shape, not the persisted matrix.
Internal sequencing of RiverSync's adoption is governed separately
and may change without notice.
P2:
AccessScope/PermScopediscriminated + only-narrowingIntersect+ AppKey entitlement shapesProblem statement
A consumer of
wangkanai/federationwho needs the resolved-accessentitlement shape (the per-app AppKey matrix plus the
(App, Perm) → Scopemap) currently has to re-implement that shape from scratch. The codec
primitives and the per-permission
PermScopevalue type are covered by theP1 filing at #42; what is missing is the higher-level consumption shape
that the resolver produces and that the Seq 3 claims compiler consumes:
AccessScopevalue type with an only-narrowingIntersecttruth table — three cases (OrgWide,Region(Id),Site(Id))with the closed-set-by-construction pattern.
ResolvedAccess) carrying the fourcomponents every later pipeline stage reads:
EntitledAppKeys(the apps after the layer-1 entitlement gate),AppToRoleId(exactly one role per entitled app, theUNIQUE(UserId, AppKey)invariant),Permissions(the resolved(app, perm) → scopemap),TenantId(the resolution's tenant).Application(AppKey) entity carrying the per-app discriminatorthat scopes a role to one application — the
AppKeystring that keysApplicationUserRoleand makes the unique-role rule(RoleName, AppKey)rather than(RoleName, ApplicationId).These three shapes together are what every federated consumer actually
consumes; without them, every consumer re-derives the truth table
(
AccessScope.Intersect), the four-component record layout, and theAppKeystring contract. The P1 codec filing covers the per-permissionhalf; this P2 filing covers the resolved-entitlement + per-app matrix half.
RiverSync ships a production implementation of all three primitives in
Account/src/Application/Authorization/AccessScope.cs,Account/src/Application/Authorization/ResolvedAccess.cs, andAccount/src/Domain/Authorization/Application.cs. We are asking upstream toexpose consumption-side shapes (a reusable
AccessScopevalue type, aResolvedAccessrecord, anApplication(AppKey) entity) with thecontracts the next section pins, so that:
wangkanai/federationcan resolve afederated principal into a typed
(entitled apps, role per app, per-permission scope, tenant)record instead of re-deriving it.AccessScope.Intersecttruth table — the only-narrowinginvariant that FED-10 (the one-way denial rule) leans on — becomes
reusable across consumers instead of every consumer re-deriving the
truth table from a written spec.
AppKeystring contract (the per-app discriminator that scopes arole to one application) is owned upstream so cross-consumer
entitlement checks can compare
(app, perm)keys on equal terms.Concrete evidence — what RiverSync ships today
Account/src/Application/Authorization/AccessScope.csAccount/src/Application/Authorization/AccessScope.csOrgWide/Region(Id)/Site(Id)sealed nested recordsAccount/src/Application/Authorization/AccessScope.csAccount/src/Application/Authorization/AccessScope.csIntersecttruth table (only-narrowing, null on incompatible)Account/src/Application/Authorization/AccessScope.csAccount/src/Application/Authorization/AccessScope.cssite.RegionIdlookup)Account/src/Application/Authorization/ResolvedAccess.csEntitledAppKeys/AppToRoleId/Permissions/TenantIdAccount/src/Application/Authorization/ResolvedAccess.csEmptysentinel (typed "no access" without per-call alloc)Account/src/Application/Authorization/ResolvedAccess.csAccount/src/Domain/Authorization/Application.csApplicationentity:Id(Guid) +AppKey(per-app discriminator string)Account/src/Domain/Authorization/Application.csAccount/src/Domain/Authorization/Application.csAccount/src/Application/Authorization/CompiledClaimTypes.csResolvedAccess; proves the four-component record is the substrate every later stage readsAccount/src/Application/Authorization/AccessResolver.csResolvedAccess; single per-sign-in instance, hands it to callersAccount/src/Application/Authorization/ClaimsCompiler.csResolvedAccessand projects onto a federated principalagile/research/009-refactoring-shared-federation-domain-from-account/report.md§8 P2 rowagile/research/009-refactoring-shared-federation-domain-from-account/report.md§7 Option A031-oss-contribution-parallel-track/031-04-p1-scope-primitives-deterministic-codec029-common-oss-foundation-layer/029-03-generalized-scope-claim-primitivesAccessScopetoCommon.Domain(Status IMPLEMENTED) — the local mirror of this upstream askRiverSync context
This P2 ask is grounded in four local anchors — without them, the
upstream framing reads as a request for new shapes. With them, it
reads as a request to publish shapes RiverSync has already validated
in production.
029 spike is the foundation. The
AccessScopevalue type(
Account/src/Application/Authorization/AccessScope.cs) wasgeneralized into
Common.Domainas part of the 029-03 track(Status IMPLEMENTED). The upstream ask is for the same shape
to live in
wangkanai/federation(or a sibling package) so theFederation consumers get it without the 029-03 spike.
Common.Domain(per the 030 thin-extraction plan). The 030 epic isthe in-tree surface for the shapes this issue asks upstream to
publish. RiverSync does not duplicate them: 030 is the consumer,
not the source, of any upstream shape.
PermScope+AccessScopevalue types and deterministicv1:/v1z:packedpermcodec #42) — natural extension; defer note referenced —the P1 codec ask at WASM-safe
PermScope+AccessScopevalue types and deterministicv1:/v1z:packedpermcodec #42 covers the per-permission codec half(
PermScope/PermScopeMap+ the deterministicv1:/v1z:packed
permcodec). The 031-04 spec explicitly defers theconsumption-side shape (the resolved-access record + per-app AppKey
matrix) to the 031-05 P2 track. This P2 ask is the deferred half.
only writer — per
.claude/rules/architecture/federation-auth.md,Account is the sole platform OIDC/OAuth2 identity provider AND the
sole writer of the persisted role↔permission matrix.
AccessScopeis the consumption shape the resolver produces; it is not an
issuer shape. The five non-Account product apps (Portal, Admin,
Partners, Pipeline, Field) participate strictly as OIDC relying
parties; none of them persists a role↔permission matrix. This P2
ask is for the consumption shape on top of the codec primitives,
not for a new IdP library.
No timeline promises (explicit)
upstream release.
Wangkanai.Federationdependency even after resolution.and may change without notice.
Request
We respectfully ask the
wangkanai/federationmaintainers to ship thefollowing three coordinated consumption-side shapes so the resolved-access
from RiverSync's
Account.Application:1. A reusable
AccessScopevalue type with only-narrowingIntersectabstract record AccessScopewith a private constructorforcing the closed set; three sealed nested records:
OrgWide(noId, no inline suffix on the wire),Region(Guid Id)(narrowed to a singleRegion.Id),Site(Guid Id)(narrowed further to a singleOrganizationSite.Id).AccessScope.cs:28-30(abstract record + private ctor + sealed nestedrecords). The resolver never constructs a custom scope type;
narrowing is the only operation that produces new values.
OrgWideInstance(shared singleton for the common case),OrgWideScoped()/RegionScoped(Guid id)/SiteScoped(Guid id).Intersect(AccessScope, AccessScope) → AccessScope?— theonly-narrowing truth table:
OrgWide ∩ x = x(identity element),Region(r) ∩ Region(r') = Region(r)iffr == r', elsenull,Site(s) ∩ Site(s') = Site(s)iffs == s', elsenull,Region ∩ Site(in either order) is the resolver's call — puremethod returns
null; the caller looks upsite.RegionId.IntersectMUST NOT take adependency on the entity store; putting the
Region ∩ Sitebranchin the resolver (not here) keeps
AccessScopefree of any referenceto the 013 store, mirrors
AccessScope.cs:109-117.2. A
ResolvedAccessconsumption recordpublic sealed record ResolvedAccess(...)with thefour-component signature RiverSync uses today
(
ResolvedAccess.cs:53-57):IReadOnlyList<string> EntitledAppKeys— the apps the user isentitled to after the layer-1 entitlement gate.
IReadOnlyDictionary<string, Guid> AppToRoleId— exactly one roleper entitled app (the
UNIQUE(UserId, AppKey)invariant; norole-union). Carries the role FK scalar only.
IReadOnlyDictionary<(string AppKey, string PermKey), AccessScope> Permissions—the resolved
(app, perm) → scopemap. Denied rows are absent(FED-10: they can never reappear).
Guid TenantId— the tenant the resolution is scoped to; alwaysset;
Guid.Emptyfor theEmptysentinel.surface; the resolver builds one per sign-in and hands it to
callers; nothing outside the resolver package is expected to mutate
it.
SDK type. The Seq 3 claims compiler in 015-02 maps
ResolvedAccessonto a federated principal; that mapping is the seam that joins the
resolver to the rest of the platform. Mirrors
ResolvedAccess.cs:35-40.sealed recordmakes equalityvalue-based on all four components.
Emptytherefore compares equalto any other
ResolvedAccessbuilt from the four empty singletons(the desired behaviour for error paths and "no access" results).
Emptysentinel —ResolvedAccess.Emptyfor the"no access" case without per-call allocation
(
ResolvedAccess.cs:65-69).3. An
Application(AppKey) entitypublic class Applicationcarrying:Guid Id(stable key),string AppKey(per-app discriminator, the human-readable stringe.g.
"portal"),string Name(display name),ApplicationGating ApplicationGating(additional login gateenum:
None,RequireMfa,RequireApproval),DateTimeOffset CreatedAt/UpdatedAt(audit timestamps).(RoleName, AppKey), NOT(RoleName, ApplicationId). MirrorsApplication.cs:9("(RoleName, AppKey)rather than(RoleName, ApplicationId)"). This is the most often-missed contracton the per-app matrix; making it explicit upstream prevents consumers
from accidentally keying on the surrogate
Idand producing rolesthat don't compose across apps.
federated token carries an
(App, Perm)key, theApphalf is theAppKeystring. Consumers comparing entitlement keys compareAppKeystrings, notIdGUIDs.Why now
The P1 codec filing at #42 covers the per-permission half (the
PermScope/PermScopeMapvalue types and the deterministicv1:/v1z:packedpermcodec). The P1 scopes-Permission / RolePermissionfiling at #43 covers the role↔permission matrix with
Allowed+ScopeRegionId/ScopeSiteId+ one-way narrowing. The P1multi-tenant Tenant /
(email, tenant)filing at #41 covers thetenant identity invariant.
What is not yet covered is the consumption-side shape: the
resolved-access record the resolver produces, the AppKey matrix that
scopes roles to one application, and the discriminated
AccessScopevalue type that ties it all together. These are the primitives every
later pipeline stage reads; without them, every consumer re-derives the
truth table, the four-component record layout, and the
AppKeystringcontract from a written spec.
The P2 framing is the right altitude for this ask: the codec
primitives are P1 because the wire contract stabilizes immediately on
issue, but the consumption-side shapes are P2 because they are
designed-for-reuse rather than wire-critical — a consumer can survive
without them, just with more boilerplate.
Scope — what this issue is and is not
This issue IS asking for
AccessScopevalue type with the only-narrowingIntersectcontract (three cases, abstract record + private ctor + sealed nested
records, factories, pure
Intersect).ResolvedAccessconsumption record (four components, structuralequality,
Emptysentinel, OIDC-agnostic).Application(AppKey) entity carrying the per-app discriminatorstring and the
AppKey-not-Idunique-role contract.This issue is NOT asking for
PermScopevalue type — the per-permissionPermScopePermScopeMapis the P1 codec filing at WASM-safePermScope+AccessScopevalue types and deterministicv1:/v1z:packedpermcodec #42. Do not duplicate here.v1:/v1z:packedpermcodec — already inWASM-safe
PermScope+AccessScopevalue types and deterministicv1:/v1z:packedpermcodec #42. The codec is the per-permission half;AccessScopeis theresolved-access half. Same target, complementary scope.
and the AppKey contract are consumption shapes, not issuer
shapes. The
ResolvedAccessrecord is OIDC-agnostic by design (perResolvedAccess.cs:35-40); the per-app matrix is not anOpenIddict/OpenIdConnectartifact.RolePermissionwithAllowed+ scope fields + one-way narrowing is the P1 filing atScoped Permission + RolePermission base shapes for Foundation overlays #43. The matrix is the input to the resolver;
ResolvedAccessis the output. Different ask.
(email, tenant)invariant — P1filing at Multi-tenant Tenant shape + scalar TenantId + (email, tenant) composite identity #41.
wangkanai/federationrepo unless upstream indicates a split.these shapes in
Common.Domainonce published, on its own internalsequencing (governed separately, without notice).
References
RiverSync artifacts (cited verbatim above)
Account/src/Application/Authorization/AccessScope.cs:28-30— abstract record + private ctor (closed set by design).Account/src/Application/Authorization/AccessScope.cs:38, 48, 58—OrgWide/Region(Id)/Site(Id)sealed nested records.Account/src/Application/Authorization/AccessScope.cs:64-81— resolver-only construction (factories).Account/src/Application/Authorization/AccessScope.cs:83-125—Intersecttruth table.Account/src/Application/Authorization/AccessScope.cs:109-117— Region ∩ Site purity note.Account/src/Application/Authorization/ResolvedAccess.cs:53-57— four-component record signature.Account/src/Application/Authorization/ResolvedAccess.cs:65-69—Emptysentinel.Account/src/Domain/Authorization/Application.cs:9—(RoleName, AppKey)unique-rule.Account/src/Domain/Authorization/Application.cs:21-22— AppKey string contract (per-app discriminator).Research anchors
agile/research/009-refactoring-shared-federation-domain-from-account/report.md§8 P2 row, line 115 — the framing for this P2 ask.agile/research/009-refactoring-shared-federation-domain-from-account/report.md§7 Option A, line 65 — the recommended layering (extract reusable value types in Common; keep full persisted entities in Account).agile/research/009-refactoring-shared-federation-domain-from-account/report.md§6 — analysis of the current OSS state vs. RiverSync usage.Sister filings (this epic)
PermScope+AccessScopevalue types and deterministicv1:/v1z:packedpermcodec (031-04, filed at #42) — the per-permission codec half. Explicitly out of scope for this P2 ask.(email, tenant)(031-03, filed at #41) — the tenant identity invariant. Explicitly out of scope for this P2 ask.Local context
031-oss-contribution-parallel-track/031-05-p2-p3-items-tracker-small-contributions— the P2/P3 items tracker.029-common-oss-foundation-layer/029-03-generalized-scope-claim-primitives— internal generalization ofAccessScopetoCommon.Domain(Status IMPLEMENTED); the local mirror of this upstream ask.030-extract-federation-domain-models-to-common— the follow-on extraction that will surface theResolvedAccessrecord and theApplication(AppKey) entity inCommon.Domain..claude/rules/architecture/federation-auth.md— ARCH:VI (Account as sole platform IdP; other apps participate strictly as OIDC relying parties).What this issue is NOT promising
upstream release.
Wangkanai.Federationdependency even after resolution.PermScope+AccessScopevalue types and deterministicv1:/v1z:packedpermcodec #42) orthe role↔permission matrix (already in Scoped Permission + RolePermission base shapes for Foundation overlays #43) or the tenant identity
(already in Multi-tenant Tenant shape + scalar TenantId + (email, tenant) composite identity #41).
Accountis to be replaced — Accountremains the sole persisted role↔permission matrix per ARCH:VI; this
ask is for the consumption shape, not the persisted matrix.
and may change without notice.