---
id: WF-PFM-ELG-002
title: Publish or roll back a rule version
trigger: >-
  A publisher releases a draft or republishes an earlier expression, optionally
  supplying simulation evidence, a skip choice, release dates and force.
product_area: platform
module: eligibility
revision: 1
status: draft
design_intent: confirmed
origin: >-
  Eligibility Engine architecture (governance chapter 14 §7, the publish steps),
  approved 2026-10-17 (PLAT-M11 "Decisions"); PLAT-M11 plan D4 "Refuse unless
  forced", 2026-10-21
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-PFM-ELG-004
  - CAP-PFM-ELG-010
  - CAP-PFM-ELG-011
moves:
  - STATE-PFM-ELG-002
  - STATE-PFM-ELG-003
crosses:
  - SVC-PFM-ELG-eligibility
idempotency: >-
  Publication has no request replay key. Repeating after success finds no draft;
  a recent competing publication can yield a stale-publication refusal. Pending
  role rechecks deduplicate.
concurrency: >-
  Validation precedes the transaction. The locked draft fingerprint protects the
  commit, and the same rule lock serializes publication with consumer
  compatibility checks.
hops:
  - 'n': 1
    actor_or_service: Publish dialog (console)
    action: >-
      Collect release choices in the publish dialog and submit the checked
      draft.
    anchor: 'react-console:components/eligibility/governance/publish-dialog.tsx'
    seam: sync
    on_failure: The dialog retains the service error and stays open.
    left_inconsistent: No service publication has committed at this step.
    observer: The publisher sees the refusal.
    provenance: observed
    source: 'react-console:components/eligibility/governance/publish-dialog.tsx'
  - 'n': 2
    actor_or_service: Eligibility publish
    action: >-
      Check validation and licensing through referenced expressions and verify
      any cited simulation belongs to this exact successful draft.
    anchor: >-
      services-platform:modules/eligibility/services/governance/publish.ts:validateForPublish
    seam: sync
    on_failure: 'Reject invalid, foreign, unfinished or stale evidence.'
    left_inconsistent: Validation leaves the draft and consumers intact.
    observer: The publisher receives the validation details.
    provenance: observed
    source: >-
      services-platform:modules/eligibility/services/governance/publish.ts:publishDefinition
  - 'n': 3
    actor_or_service: Eligibility publish (one transaction)
    action: >-
      Lock and recheck the draft, record dependencies, allocate the release
      number, supersede an overlapping latest release, fit followers, refuse
      incompatible uses unless forced, suspend forced incompatibilities, remove
      affected plans, audit and queue role rechecks.
    anchor: >-
      services-platform:modules/eligibility/services/governance/publish.ts:publishDefinition
    seam: sync
    on_failure: >-
      An overlap, race or compatibility failure rolls back the whole
      transaction.
    left_inconsistent: 'Release, suspensions, plan deletion, audit and queued requests are atomic.'
    observer: Publication output and audit explain the result.
    provenance: observed
    source: >-
      services-platform:modules/eligibility/services/invalidation/on-definition-published.ts:onDefinitionPublished
  - 'n': 4
    actor_or_service: Eligibility publish (after commit)
    action: >-
      Remove optional cached plans, advance affected display generations and
      nudge the recheck dispatcher after commit.
    anchor: >-
      services-platform:modules/eligibility/services/compile/plan-cache.ts:forgetPlans
    seam: sync
    on_failure: >-
      Cache errors fall back to misses; failed follow-up does not reverse
      publication.
    left_inconsistent: >-
      Display answers can survive for two minutes; queued work can wait for the
      next dispatcher minute.
    observer: Cache metrics expose misses without a dedicated follow-up alert.
    provenance: observed
    source: >-
      services-platform:modules/eligibility/services/invalidation/on-definition-published.ts:nudgeAfterPublish
  - 'n': 5
    actor_or_service: Security role recheck queue
    action: Have Security process the queued subjects and reconcile derived roles.
    anchor: >-
      services-platform:modules/security/services/persistence/derived-assignment-reconciles.ts:queueDerivedAssignmentReconciles
    seam: queue
    on_failure: Queue retry eventually reaches dead-letter handling and its age alarm.
    left_inconsistent: Old grants remain until successful reconciliation or expiry.
    observer: Security’s queue-age alarm detects delayed work.
    provenance: documented
    source: 'services-platform:docs/eligibility.md#13.6 The triggers'
branches:
  - >-
    Rollback validates old logic against current declarations, publishes it
    under a new number and preserves the current draft.
  - >-
    A nonoverlapping release can be scheduled alongside another published
    interval.
  - 'The API accepts neither simulation nor skip, recording neither choice.'
waits: []
evidence:
  - >-
    services-platform at ad3f6a6: services/governance/publish.ts;
    services/invalidation/on-definition-published.ts;
    services/compile/plan-cache.ts; services/evaluate/decision-cache.ts;
    services/bindings/consumer-bindings.ts (unfitBindingsOf,
    suspendUnfitBinding); docs/eligibility.md §7.3, §8.3, §11, §16.
  - >-
    react-console at baf6dae:
    components/eligibility/governance/publish-dialog.tsx.
controls: [TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-DAT-005, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-MON-003, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Publish or roll back a rule version

## What It Does

A publisher releases a draft or republishes an earlier expression, optionally supplying simulation evidence, a skip choice, release dates and force.

## The Flow

```mermaid
flowchart TD
  H1["Publish dialog (console)" ]
  H2["Eligibility publish" ]
  H1 --> H2
  H3["Eligibility publish (one transaction)" ]
  H2 --> H3
  H4["Eligibility publish (after commit)" ]
  H3 --> H4
  H5["Security role recheck queue" ]
  H4 --> H5
```

Collect release choices in the publish dialog and submit the checked draft. Check validation and licensing through referenced expressions and verify any cited simulation belongs to this exact successful draft. Lock and recheck the draft, record dependencies, allocate the release number, supersede an overlapping latest release, fit followers, refuse incompatible uses unless forced, suspend forced incompatibilities, remove affected plans, audit and queue role rechecks. Remove optional cached plans, advance affected display generations and nudge the recheck dispatcher after commit. Have Security process the queued subjects and reconcile derived roles.

## When Something Fails

The dialog retains the service error and stays open. No service publication has committed at this step. Reject invalid, foreign, unfinished or stale evidence. Validation leaves the draft and consumers intact. An overlap, race or compatibility failure rolls back the whole transaction. Release, suspensions, plan deletion, audit and queued requests are atomic. Cache errors fall back to misses; failed follow-up does not reverse publication. Display answers can survive for two minutes; queued work can wait for the next dispatcher minute. Queue retry eventually reaches dead-letter handling and its age alarm. Old grants remain until successful reconciliation or expiry.

## Open Design Questions

Rollback validates old logic against current declarations, publishes it under a new number and preserves the current draft. A nonoverlapping release can be scheduled alongside another published interval. The API accepts neither simulation nor skip, recording neither choice.
