SmartExchange · .NET 10 · Chapter 04
Generated relationship registry
The registry connects CRM declarations to three consumers: the Context Resolver, scope validation and the SQL mapping factory.
Where the registry is used
| Consumer | Call / responsibility |
|---|---|
SmartExchangeAuthorizationContextResolver.ResolveAsync() | GetRelationships(resource) → select grant resource kinds: root plus direct declaration targets. |
SmartExchangeAuthorizationScopeValidator | Generate(diagram) → allow named scope pairs only when that resource declares the target. |
Application mapping, through AuthorizationSqlMappingFactory.Create() | Convert the same relationship steps into correlated SQL subqueries. |
SmartExchangeAuthorizationRelationshipRegistry.Generate(DiagramCrm) produces AuthorizationRelationship records: resource kind, attribute alias, target kind/key and join steps. GetRelationships(string) returns definitions for one resource; ScopeValidator exposes cached metadata validation.
Registry use in both examples
| Registry output / use | Person export | InterestedParty export |
|---|---|---|
| Attribute | resource.attr.companyIds | resource.attr.projectIds |
| TargetResourceKind | Company | Project |
| Generated path | Person → PersonInCompany → Company | InterestedParty → Project |
| Resolver selection | Person + Company | InterestedParty + Project + Investor |
| Scope validation | Company/read/Resource is a direct Company fact. | InterestedParty/read/Project requires the declared pair. |
| SQL enforcement | EXISTS PersonInCompany JOIN Company | EXISTS Project |
Both relationships supply trusted SQL structure; the policy chooses why a grant qualifies. The resolver retains all actions/scopes for selected kinds and does not recursively traverse their other relations. Investor is selected for InterestedParty because it is also directly annotated; this demo policy does not consume Investor grants.
Person relationship JSON · InterestedParty relationship JSON
Scope normalization and validation
| Method | Implemented behavior |
|---|---|
LegacySqlAuthorizationGrantAdapter.Normalize() | Instance assignment → Instance scope; same entity → Resource scope; different declared target → named scope. Cross-entity conversion also requires unique canonical permission ownership. |
ValidateResource(resource) | Require a known CRM entity name, with exact casing. |
SupportsScope(resource, scope) | Accept Resource, Instance or a declared resource→target pair. |
Validate(grant) | Validate resource/scope, nonblank action and a nonempty record ID except for Instance scope. |
InterestedParty / read / Project. Project/read does not turn into InterestedParty/read. Validation checks metadata and contract consistency; the policy still decides access.Registry generation also rejects ambiguous paths, duplicate aliases and unsupported key/deletion metadata. SQL adds Deleted = 0 at every relationship step; the application retains the root query’s deletion filter.