Member Junction
    Preparing search index...

    ============================================================================ SCOPE RESOLUTION SEAM

    An EntityAction may be narrowed to ONE configuration record — this Deal Type, this Contract Type, this Pipeline, this Company — via the ScopeEntityID / ScopeRecordID pair. NULL means "applies to every record of the entity", which is the pre-existing behaviour and by far the common case.

    The framework stores and filters on the pair; it does not interpret it. How a scope record relates to a subject record is an application concern: Sales knows a Deal reaches its Deal Type through Deal.DealTypeID, and core must not. So the question "does this subject record fall under this scope record?" is answered by a @RegisterClass-resolved resolver, keyed by scope entity name, most-specific wins — the same shape as BasePriceResolver in BizApps Orders and GLAccountResolver in Accounting.

    The default implementation below walks the subject entity's foreign keys looking for one that points at the scope entity. That covers the direct case (Sales registers nothing for Deal Types because Deal.DealTypeID is found automatically). An app needing something indirect — scope by Company where the subject reaches Company through a Pipeline — registers its own resolver:

    @RegisterClass(EntityActionScopeResolver, 'Companies')
    export class CompanyScopeResolver extends EntityActionScopeResolver {
    public override async IsInScope(subject: BaseEntity, scopeEntityID: string, scopeRecordID: string): Promise<boolean | null> {
    // return null to decline and fall back to the default FK walk
    }
    }

    Declining returns null, not false. false means "I looked and this record is out of scope"; null means "not my call" and falls back to the default. Conflating them would silently disable every binding a partially applicable resolver didn't recognise.

    Index

    Constructors

    Methods

    • The default answer: look for a foreign key on the subject entity that points at the scope entity, and compare the subject's value for that field against the scope record's ID.

      Returns null when the subject has no foreign key to the scope entity at all — the relationship is indirect and only the owning app knows how to traverse it, so declining is more honest than answering false. Returns null for ambiguity too: when several distinct foreign keys point at the scope entity, picking one arbitrarily would silently bind the workflow to the wrong relationship (a Deal with both OwnerCompanyID and ClientCompanyID has no single defensible "the" Company).

      Parameters

      • subject: BaseEntity
      • scopeEntityID: string
      • scopeRecordID: string

      Returns boolean

    • Answers whether subject falls under the scope record identified by scopeEntityID / scopeRecordID.

      Parameters

      • subject: BaseEntity
      • scopeEntityID: string
      • scopeRecordID: string

      Returns Promise<boolean>

      true / false for a decision, or null to decline and let the caller fall back to the default foreign-key walk.

    • Compares a subject's foreign-key value against a scope record ID. Scope record IDs are stored as text and may be UUIDs (which differ in case between SQL Server and PostgreSQL) or numeric keys, so UUIDsEqual handles the former and a trimmed comparison the latter.

      Parameters

      • subjectValue: string
      • scopeRecordID: string

      Returns boolean