---
id: STATE-CRM-ENT-003
title: Organization role compliance status
object: DOM-CRM-ENT-002
product_area: crm
module: entities
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
  - name: ungoverned
    meaning: >-
      No enabled type policy applies, and recalculation leaves compliance fields
      absent.
    entry_conditions: No enabled type policy applies when recalculation runs.
    allowed_actions:
      - Read the absence of assessment
      - >-
        configure policy and request a later evaluation with the applicable
        grants.
    terminal: false
    reversible: true
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
    experience: Status and violations are absent rather than a reassuring compliant label.
  - name: in compliance
    meaning: >-
      Every configured bound is met by distinct eligible role holders on
      effective affiliations.
    entry_conditions: All applicable role-count bounds pass at evaluation.
    allowed_actions:
      - Read the assessment
      - edit underlying ties
      - request reprocessing.
    terminal: false
    reversible: true
    provenance: observed
    source: >-
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance
    experience: Staff see an assessment with no failed bounds.
  - name: not in compliance
    meaning: >-
      One or more counts fail their bounds; violations retain the configured
      rule order.
    entry_conditions: At least one applicable bound fails when evaluated.
    allowed_actions:
      - Read ordered violations
      - correct underlying coverage
      - request reprocessing.
    terminal: false
    reversible: true
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet)
    experience: >-
      The profile explains the missing or excess holder count; notice delivery
      remains separate.
transitions:
  - from: ungoverned
    to: not in compliance
    trigger: Create under policy or recalculate after policy becomes applicable.
    guard: Enabled type policy has at least one failed rule.
    side_effects:
      - write status and violations in the owning transaction
      - publish enabled attention
      - suppress notices on creation
      - allow notices on subsequent eligible transitions
    who: The compliance evaluator
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet)
    audit_event: >-
      Changed status or violations advance the organization version and capture
      an organization revision. Notice request pointers commit with that
      assessment; unchanged evaluation produces no new assessment revision.
  - from: in compliance
    to: not in compliance
    trigger: 'Recalculate after relationship work, a date boundary or a reprocess.'
    guard: Violations differ and at least one rule fails.
    side_effects:
      - persist status and violations
      - advance owner version
      - capture revision
      - submit deduplicated recipient batches when allowed
      - publish enabled attention
    who: The system under the triggering change context
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify
    audit_event: >-
      Changed status or violations advance the organization version and capture
      an organization revision. Notice request pointers commit with that
      assessment; unchanged evaluation produces no new assessment revision.
  - from: not in compliance
    to: in compliance
    trigger: Recalculate and find no remaining violation.
    guard: The newly empty violation list differs from stored violations.
    side_effects:
      - set compliant status and clear violations
      - resolve enabled attention
      - submit no notice
    who: The compliance evaluator
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary
    audit_event: >-
      Changed status or violations advance the organization version and capture
      an organization revision. Notice request pointers commit with that
      assessment; unchanged evaluation produces no new assessment revision.
  - from: not in compliance
    to: not in compliance
    trigger: Recalculate an already noncompliant organization with changed violations.
    guard: The computed violations differ from storage.
    side_effects:
      - replace violations
      - advance version
      - omit another transition notice
    who: The compliance evaluator
    provenance: observed
    source: >-
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance
    audit_event: >-
      Changed status or violations advance the organization version and capture
      an organization revision. Notice request pointers commit with that
      assessment; unchanged evaluation produces no new assessment revision.
  - from: in compliance
    to: ungoverned
    trigger: Recalculate after removal or disabling of the governing policy.
    guard: Stored compliance data still needs clearing.
    side_effects:
      - clear status and violations
      - resolve enabled attention
    who: The compliance evaluator
    provenance: unknown
    source: FND-CRM-ENT-084
    audit_event: >-
      Changed status or violations advance the organization version and capture
      an organization revision. Notice request pointers commit with that
      assessment; unchanged evaluation produces no new assessment revision.
  - from: not in compliance
    to: ungoverned
    trigger: Recalculate a previously noncompliant record after policy removal.
    guard: Existing compliance fields remain despite absent governing policy.
    side_effects:
      - remove compliance fields
      - resolve enabled attention
    who: The compliance evaluator
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#clears
      the status of an organization whose type no longer holds it to rules
    audit_event: >-
      Changed status or violations advance the organization version and capture
      an organization revision. Notice request pointers commit with that
      assessment; unchanged evaluation produces no new assessment revision.
invalid:
  - from: in compliance
    to: not in compliance
    why: >-
      Ordinary organization payloads cannot control compliance status or
      violations.
    response: >-
      Ordinary organization writes cannot assign the computed assessment. Echoed
      read-only compliance values are ignored; they do not change the
      evaluator’s result.
  - from: ungoverned
    to: in compliance
    why: >-
      Saving policy or changing organization type does not itself recalculate
      existing organizations; a later trigger must do so.
    response: >-
      Changing a type or policy is not an immediate evaluation of every existing
      organization. Existing saved status can remain until another valid trigger
      or reprocess reaches it.
concurrency: >-
  A transaction advisory lock and the organization row lock serialize
  recalculation. Evaluation uses committed relationships and skips writing when
  its compared violations are unchanged. Submission keys identify organization
  version and recipient batch, so retries deduplicate submissions without
  assuring email delivery.
invariants:
  - INV-DOM-CRM-ENT-002-06
  - INV-DOM-CRM-ENT-002-07
  - INV-DOM-CRM-ENT-002-08
evidence:
  - >-
    services-crm at 7ea48a41:
    modules/entities/services/organizations/compliance/organization-compliance.ts,
    compliance-change-events.ts, compliance-email.ts,
    contact-role-compliance.ts;
    services/persistence/organization-attention-items.ts;
    db/organizations.table.ts (CONTACT_ROLE_COMPLIANCE_STATUSES).
automatic:
  - from: in compliance
    to: not in compliance
    when: >-
      A committed role or affiliation change, contact deletion, applicable date
      boundary or reprocess yields a failed bound.
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify
  - from: not in compliance
    to: in compliance
    when: A subsequent evaluation finds all configured bounds satisfied.
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary
ai_may_recommend: false
ai_may_execute: false
permissions_by_state:
  - state: ungoverned
    action: read
    permission: crm.organizations.read
  - state: ungoverned
    action: update
    permission: crm.organizations.update
  - state: in compliance
    action: read
    permission: crm.organizations.read
  - state: in compliance
    action: update
    permission: crm.organizations.update
  - state: not in compliance
    action: read
    permission: crm.organizations.read
  - state: not in compliance
    action: update
    permission: crm.organizations.update
narrative:
  status: verified
  review: NARRATIVE-REVIEW-2026-10-23
narrative_sources:
  - section: The Lifecycle
    provenance: unknown
    source: FND-CRM-ENT-084
    note: A previously compliant assessment clearing after policy removal lacks direct saved-state and version assertions; the corresponding formal row is unknown.
  - section: Transitions Explained
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#an
      organization no type holds that still carries a status, so the recalculation clears it
    note: The fixture starts with a compliant label, but the assertion checks which organization is selected for recalculation, not the saved assessment or version.
  - section: Transitions Explained
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#clears
      the status of an organization whose type no longer holds it to rules
    note: The existing-record case checks clearing a prior failing assessment; it does not assert the passing-policy starting state or its version change.
  - section: Transitions Explained
    provenance: unknown
    source: FND-CRM-ENT-084
    note: The unsupported compliant-to-ungoverned row is unknown. Direct saved-state and version assertions also remain missing for enabling an already-satisfied policy; code contradicts a guaranteed stored passing transition.
  - section: Transitions Explained
    provenance: observed
    source: >-
      services-crm:modules/entities/services/organizations/compliance/contact-role-compliance.ts:checkForContactRoleComplianceViolations;
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculate;
      services-crm:modules/entities/services/persistence/organizations.ts:loadComplianceViolations;
      services-crm:modules/entities/services/persistence/organizations.ts:setOrganizationComplianceStatus
    note: Enabled-policy evaluation compares violations; removing policy separately reports changes when existing assessment fields are cleared.
  - section: Purpose
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: Ownership and Authority
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: The Lifecycle
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: States
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: Transitions Explained
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: What Cannot Happen
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: Concurrency and Timing
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
  - section: Permissions by State
    provenance: documented
    source: 'rhythm-v2-docs:specs/crm/AUTHORIZATION.md#Role Entitlement Matrix'
  - section: Purpose
    provenance: inferred
    source: >-
      services-crm at 7ea48a41:
      modules/entities/services/organizations/compliance/organization-compliance.ts,
      compliance-change-events.ts, compliance-email.ts,
      contact-role-compliance.ts;
      services/persistence/organization-attention-items.ts;
      db/organizations.table.ts (CONTACT_ROLE_COMPLIANCE_STATUSES).
    note: >-
      The explicitly labeled rationale interprets the separation of state
      dimensions and the existing trigger and guard rows.
  - section: Invariants
    provenance: inferred
    source: INV-DOM-CRM-ENT-002-06; INV-DOM-CRM-ENT-002-07; INV-DOM-CRM-ENT-002-08
    note: >-
      Protection explanations interpret the unchanged domain-object invariants;
      no lifecycle policy is added.
  - section: Invariants
    provenance: inferred
    source: "services-crm:modules/entities/services/persistence/contacts.ts; services-crm:modules/entities/services/persistence/organizations.ts; services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts; services-crm:modules/entities/services/persistence/record-locks.ts"
    note: "The rationale interprets this artifact’s sourced invariants and linked capability rules; it does not claim a recorded product decision."
---

# Organization role compliance status

## Purpose

Role compliance describes whether effective representatives satisfy the expectations configured for an organization’s type. Harbor West Chapter may require one billing contact and a bounded number of officers. A stored violation explains the unmet responsibility and count, while an organization with no applicable policy has no such assessment.

Our reading is that explicit assessment states make gaps understandable without implying that compliance is an editable certification. They also determine when a notice may be submitted. An unchanged calculation, continuing noncompliance with different violations, and a new transition into noncompliance are distinct situations for persistence and communication.

## Ownership and Authority

The evaluator owns the stored assessment. Contact relationship work, deletion, date settlement and a requested reprocess provide its triggers; staff do not directly select the desired outcome on the organization. Ordinary organization payloads cannot make the assessment authoritative by echoing a preferred status or violation list.

Organization updaters can request reprocessing, and editors change the underlying people and dated responsibilities under their own permissions. The deterministic role-count calculation uses no inference operation. Platform owns notice delivery after submission and does not decide the CRM compliance state from mail success or failure.

## The Lifecycle

The diagram distinguishes observed assessment changes from one clearing sequence whose saved-state proof remains unknown. Enabling a policy that already passes can calculate compliance without storing it, so the diagram contains no guaranteed transition from an absent assessment to a saved passing label. The compliance-transition finding records the missing assertions for that boundary and for clearing a previously compliant assessment.

```mermaid
stateDiagram-v2
  state "In compliance" as compliant
  state "Not in compliance" as noncompliant
  ungoverned --> noncompliant: evaluate failing policy
  compliant --> noncompliant: recalculation finds violations
  noncompliant --> compliant: recalculation clears violations
  noncompliant --> noncompliant: changed violations, no new transition notice
  compliant --> ungoverned: policy removal, saved-state proof unknown
  noncompliant --> ungoverned: recalculation after policy removal
```

## States

### ungoverned

No enabled type policy applies, and recalculation leaves compliance fields absent. Entry requires this condition: No enabled type policy applies when recalculation runs. Available behavior is Read the absence of assessment; configure policy and request a later evaluation with the applicable grants.. Status and violations are absent rather than a reassuring compliant label.

### in compliance

Every configured bound is met by distinct eligible role holders on effective affiliations. Entry requires this condition: All applicable role-count bounds pass at evaluation. Available behavior is Read the assessment; edit underlying ties; request reprocessing.. Staff see an assessment with no failed bounds.

### not in compliance

One or more counts fail their bounds; violations retain the configured rule order. Entry requires this condition: At least one applicable bound fails when evaluated. Available behavior is Read ordered violations; correct underlying coverage; request reprocessing.. The profile explains the missing or excess holder count; notice delivery remains separate.

## Transitions Explained

### ungoverned → not in compliance

The compliance evaluator starts this change when the following occurs: Create under policy or recalculate after policy becomes applicable. The transition checks this boundary: Enabled type policy has at least one failed rule. The accompanying work is write status and violations in the owning transaction; publish enabled attention; suppress notices on creation; allow notices on subsequent eligible transitions. A changed evaluator result can advance the organization version and capture a revision. The implementation compares violations when deciding to persist; a status-only difference with the same violations does not establish a stored transition. Notice request pointers commit with that assessment; unchanged evaluation produces no new assessment revision.

### Passing calculation without a stored transition

A newly applicable policy can pass because the organization already has the required role holders. That computed result and a stored transition are different outcomes. During enabled-policy evaluation, the implementation compares the previous violations with the new ones before reporting a change to persistence. With no previous violations and none now, the calculated compliant status alone does not cause an organization write.

For example, Harbor West Chapter has effective officers before an administrator enables a policy that those officers already satisfy. Reprocessing can calculate a passing result without recording that label or a new organization version. The absence of a guaranteed saved transition follows from this guard; a calculated passing label does not establish stored compliance. Direct before-and-after saved-state and version assertions for this starting condition are missing. The [compliance-transition finding](../../FINDINGS.md#findings) records that test gap. The formal inventory excludes the unconditional persistence claim because the implementation contradicts it.

The recalculation result also carries the calculated status when it reports that nothing was written. A caller inspecting only that returned status can therefore mistake the calculation for the stored assessment. In this example, the meaningful verification is a subsequent organization read and comparison with its earlier version, alongside the recalculation outcome. The open finding requires those separate assertions; a returned passing label alone cannot settle the transition.

### in compliance → not in compliance

The system under the triggering change context starts this change when the following occurs: Recalculate after relationship work, a date boundary or a reprocess. The transition checks this boundary: Violations differ and at least one rule fails. The accompanying work is persist status and violations; advance owner version; capture revision; submit deduplicated recipient batches when allowed; publish enabled attention. A changed evaluator result can advance the organization version and capture a revision. The implementation compares violations when deciding to persist; a status-only difference with the same violations does not establish a stored transition. Notice request pointers commit with that assessment; unchanged evaluation produces no new assessment revision.

### not in compliance → in compliance

The compliance evaluator starts this change when the following occurs: Recalculate and find no remaining violation. The transition checks this boundary: The newly empty violation list differs from stored violations. The accompanying work is set compliant status and clear violations; resolve enabled attention; submit no notice. A changed evaluator result can advance the organization version and capture a revision. The implementation compares violations when deciding to persist; a status-only difference with the same violations does not establish a stored transition. Notice request pointers commit with that assessment; unchanged evaluation produces no new assessment revision.

### not in compliance → not in compliance

The compliance evaluator starts this change when the following occurs: Recalculate an already noncompliant organization with changed violations. The transition checks this boundary: The computed violations differ from storage. The accompanying work is replace violations; advance version; omit another transition notice. A changed evaluator result can advance the organization version and capture a revision. The implementation compares violations when deciding to persist; a status-only difference with the same violations does not establish a stored transition. Notice request pointers commit with that assessment; unchanged evaluation produces no new assessment revision.

### in compliance → ungoverned

After the policy is removed or disabled, the next recalculation takes the evaluator's separate clearing branch. An existing status or violations makes that branch report a change, allowing persistence to clear the assessment and advance the organization version. The enabled-policy comparison that can suppress a new passing label does not suppress clearing an existing compliant label.

This distinction matters when an administrator retires Harbor West Chapter's role policy. A policy edit alone does not immediately refresh all organizations, but a later valid evaluation can remove the saved assessment. It is not established by direct saved-state and version assertions that this previously compliant starting state completes the clearing sequence. The formal transition is therefore labeled unknown and cites the compliance-transition finding. The evaluator and persistence code support the described mechanism, but the no-policy creation test does not demonstrate this existing-record sequence.

A separate change-event test seeds an organization with a compliant label and no governing policy. It checks that a contact change selects that organization for recalculation. This is useful evidence that the reaction reaches the clearing path, but its assertion stops at selection: it does not read the resulting stored status, violations or version. That narrower test does not close the persistence gap.

### not in compliance → ungoverned

When a previously noncompliant organization loses its policy, recalculation clears the existing status and violations through the same clearing branch. Enabled attention is resolved with the assessment write. No transition into noncompliance occurs, so removing the policy does not itself require another violation notice.

The integration suite includes an existing organization whose type is changed to one without rules, followed by a contact reaction; it checks absent status and violations afterwards. That case supports clearing a prior failing assessment. It does not settle the separately missing passing-policy case or prove every starting state's version effects. The formal trigger names the prior failing assessment, and its source is the existing-record clearing case. The missing version assertion remains a coverage limitation rather than a claim that clearing failed.

## What Cannot Happen

Ordinary organization writes cannot assign the computed assessment. Echoed read-only compliance values are ignored; they do not change the evaluator’s result.

Changing a type or policy is not an immediate evaluation of every existing organization. Existing saved status can remain until another valid trigger or reprocess reaches it.

## Permissions by State

The state rows reference grants from the CRM authorization model. Read access is distinct from mutation, and history requires the corresponding history and read checks. Administrator and Power User hold administrative record actions; ordinary Standard User grants include applicable read and update operations, while Read Only grants do not authorize edits.

Assessment itself is evaluator-owned. Organization update allows requesting reevaluation, while contact authority controls the underlying responsibility corrections; it does not make the computed status writable.

## Concurrency and Timing

The evaluator serializes on a transaction advisory lock and the organization row. It counts distinct effective people from committed relationship data. Under an enabled policy, a changed violation result allows an assessment write; without an applicable policy, clearing existing assessment fields also reports a change. Later contact commits provide later reactions; this is not a single snapshot of all policy and people changes across the workspace.

A transition notice can have multiple recipient batches, each with a deduplication key based on organization, resulting version and batch position. Accepted submission is not guaranteed delivery. Initial creation suppresses its notice, and continuing noncompliance does not by itself imply another transition notice.

## Invariants

Our reading is that separating ungoverned from compliant prevents staff from interpreting absence of a policy as a completed policy check. Violations reflect the most recent evaluation of eligible role holders and periods; a later date boundary or policy edit can require another evaluation. Notice submission follows a relevant changed assessment and keeps its own retry identity. Neither a compliant label nor the end of a reprocess scan demonstrates that a communication reached its recipients.
