---
id: CAP-PFM-ELG-004
title: 'Release, schedule and restore rule versions'
feature: FEAT-PFM-ELG-01
product_area: platform
module: eligibility
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes:
  - CAP-ELIG-GOV-001
  - CAP-ELIG-GOV-002
  - CAP-ELIG-GOV-003
  - CAP-ELIG-GOV-009
  - CAP-ELIG-GOV-012
  - CAP-ELIG-GOV-013
  - CAP-ELIG-DEF-007
  - CAP-ELIG-ADV-001
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-platform:docs/milestones/plans/PLAT-M11-plan.md#1. Objective'
  - 'services-platform:docs/milestones/plans/PLAT-M11-plan.md#D4'
  - 'services-platform:docs/milestones/plans/PLAT-M11-plan.md#A3'
  - 'services-platform:docs/proposals/eligibility/17-decision-register.md#D-14'
purpose: >-
  A release makes a reviewed expression available to consumers. Version history
  lets staff explain and reverse that choice.
outcomes:
  - Following consumers select the effective published expression.
  - Restoration releases an earlier expression as a new version.
  - Release history attributes changes to their authors.
concepts:
  - CON-PFM-ELG-001
  - CON-PFM-ELG-002
actors:
  - ACT-PFM-023
surfaces:
  - console
  - api
preconditions: []
postconditions: []
permissions:
  - key: platform.eligibility.publish
    where_checked: api
    scope: tenant
  - key: platform.eligibility.read
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-PFM-ELG-004-01
    proved_by: [ATS-PFM-ELG-004-01, TST-PFM-ELG-185, TST-PFM-ELG-411]
    statement: >-
      Publishing and restoring earlier expressions require the sensitive publish
      permission; lacking it rejects the request without a change.
    kind: permission
    enforced_at:
      - api
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/e2e/eligibility-definitions.e2e.spec.js#refuses
      the publish to a writer without the publish permission, 403
    origin: none
  - id: BR-CAP-PFM-ELG-004-02
    proved_by: [ATS-PFM-ELG-001-18, ATS-PFM-ELG-004-02, ATS-PFM-ELG-004-13, TST-PFM-ELG-166, TST-PFM-ELG-188, TST-PFM-ELG-435]
    statement: >-
      Publication rejects validation errors and unlicensed application
      conditions, including those reached through references, while warnings
      remain nonblocking.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish.integration.spec.js#refuses
      a condition type of an application the tenant is not licensed for
    origin: 'services-platform:docs/proposals/eligibility/17-decision-register.md#D-07'
  - id: BR-CAP-PFM-ELG-004-03
    proved_by: [ATS-PFM-ELG-004-03, ATS-PFM-ELG-004-14, ATS-PFM-ELG-005-10, TST-PFM-ELG-435]
    statement: >-
      Publication assigns the draft its next permanent version number and
      supersedes the previous publication when their effective periods overlap.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish.integration.spec.js#publishes
      the next draft as version 2 and supersedes version 1
    origin: none
  - id: BR-CAP-PFM-ELG-004-04
    proved_by: [ATS-PFM-ELG-004-04, TST-PFM-ELG-163, TST-PFM-ELG-165, TST-PFM-ELG-462]
    statement: >-
      Effective periods include their starting day and exclude their ending day;
      overlap with an older publication is rejected, while a disjoint latest
      publication remains effective for its own period.
    kind: validation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/persistence/versions.integration.spec.js#refuses
      a publish whose range overlaps a published version other than the last
      one, naming it, and leaves the draft
    origin: none
  - id: BR-CAP-PFM-ELG-004-05
    proved_by: [ATS-PFM-ELG-004-05, TST-PFM-ELG-413]
    statement: >-
      Effective dates must exist in the calendar, and an impossible date is
      rejected with its field identified.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/e2e/eligibility-governance-repairs.e2e.spec.js#refuses
      a draft with effective_from 2027-02-31, 400, naming the field
    origin: none
  - id: BR-CAP-PFM-ELG-004-06
    proved_by: [ATS-PFM-ELG-004-06, ATS-PFM-ELG-004-15, ATS-PFM-ELG-007-17, TST-PFM-ELG-089, TST-PFM-ELG-434]
    statement: >-
      Publication rejects a version that no longer fits an active following use
      unless explicitly forced, in which case incompatible followers are
      suspended.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish-followers.integration.spec.js#refuses
      the publish as unfit_followers, naming the binding and what its kind does
      not supply
    origin: 'services-platform:docs/milestones/plans/PLAT-M11-plan.md#D4'
  - id: BR-CAP-PFM-ELG-004-07
    proved_by: [ATS-PFM-ELG-004-07, ATS-PFM-ELG-004-16, ATS-PFM-ELG-010-07, TST-PFM-ELG-178, TST-PFM-ELG-434]
    statement: >-
      Publication removes plans for the changed rule and every expression that
      follows it through references; a direct pin to the unchanged earlier
      version retains its plan.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish-followers.integration.spec.js#finds
      every rule that inlines C at any depth, and none that pins a version of C
    origin: none
  - id: BR-CAP-PFM-ELG-004-08
    proved_by: [ATS-PFM-ELG-004-08, TST-PFM-ELG-169, TST-PFM-ELG-435, TST-PFM-ELG-462]
    statement: >-
      Rollback revalidates an earlier expression and copies its dependencies
      into the next publication with a rollback note, preserving any current
      draft.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish.integration.spec.js#publishes
      version 1’s rule as version 3 with the rollback note, superseding version
      2
    origin: none
  - id: BR-CAP-PFM-ELG-004-09
    proved_by: [ATS-PFM-ELG-004-09, TST-PFM-ELG-003, TST-PFM-ELG-180, TST-PFM-ELG-435]
    statement: >-
      Only one concurrent attempt publishes a draft; the losing attempt receives
      the winning version and publication time in a stale-change refusal without
      the publisher’s identity.
    kind: invariant
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish.integration.spec.js#refuses
      the loser with StaleObject naming the winner’s version and when it was
      published, not IllegalOperation
    origin: none
  - id: BR-CAP-PFM-ELG-004-10
    proved_by: [ATS-PFM-ELG-004-10, TST-PFM-ELG-004, TST-PFM-ELG-181]
    statement: >-
      The published expression is the expression validated for that request; a
      racing save can land beforehand, remain as a later draft or produce a
      stale-change or retryable-conflict refusal.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      react-console:acceptance/eligibility/playwright/journeys/governance/ELIG-ACC-0149.spec.ts#ELIG-ACC-0149
    origin: none
  - id: BR-CAP-PFM-ELG-004-11
    proved_by: [ATS-PFM-ELG-004-11, TST-PFM-ELG-170, TST-PFM-ELG-411, TST-PFM-ELG-432]
    statement: >-
      History presents versions newest first, includes the draft and compares
      any pair through readable additions, removals and changes.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/diff.integration.spec.js#answers
      every change from version 1 to the draft, version 2, with its sentence and
      the counts
    origin: none
  - id: BR-CAP-PFM-ELG-004-12
    proved_by: [ATS-PFM-ELG-004-12, ATS-PFM-ELG-004-17, ATS-PFM-ELG-011-09, TST-PFM-ELG-189, TST-PFM-ELG-435]
    statement: >-
      Rule and binding writes create attributable change events, with
      publication versions, change counts and the simulation choice; refused
      writes create none.
    kind: invariant
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/governance/publish.integration.spec.js#records
      the publish with its versions and the size of its diff
    origin: none
  - id: BR-CAP-PFM-ELG-004-13
    proved_by: []
    statement: >-
      Publication has no second-approver requirement because the console’s
      conditional approval stage has no setting that activates it.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: 'react-console:lib/eligibility/status.ts:requiresApproval'
    origin: 'services-platform:docs/milestones/plans/PLAT-M11-plan.md#A3'
scenarios:
  - id: SC-CAP-PFM-ELG-004-01
    given: A member price follows the first release while an audit use pins it.
    when: A publisher releases a second expression admitting inactive members.
    then: >-
      The price follows the new effective release and the auditor retains the
      pin.
    provenance: test
    source: >-
      react-console:acceptance/eligibility/playwright/journeys/governance/ELIG-ACC-0130.spec.ts#ELIG-ACC-0130
  - id: SC-CAP-PFM-ELG-004-02
    given: Two releases have disjoint periods before and after the year boundary.
    when: Evaluation is requested on either side of that boundary.
    then: The expression effective for the selected day answers.
    provenance: test
    source: >-
      react-console:acceptance/eligibility/playwright/journeys/governance/ELIG-ACC-0131.spec.ts#ELIG-ACC-0131
edge_cases:
  - id: SC-CAP-PFM-ELG-004-03
    given: A future release follows an open-ended current expression.
    when: The publisher attempts a correction for the earlier period.
    then: >-
      Overlapping earlier periods fail, and a rollback with an appropriate end
      restores the present expression.
    provenance: test
    source: >-
      react-console:acceptance/eligibility/playwright/journeys/governance/ELIG-ACC-0133.spec.ts#ELIG-ACC-0133
constraints: []
depends_on:
  - CAP-PFM-ELG-001
related:
  - CAP-PFM-ELG-005
  - CAP-PFM-ELG-007
  - CAP-PFM-ELG-010
  - CAP-PFM-ELG-011
journeys:
  - JNY-PFM-ELG-001
  - JNY-PFM-ELG-003
open_questions: []
evidence:
  - >-
    services-platform: docs/eligibility.md;
    docs/milestones/PLAT-M11-eligibility-rules.md and plans/PLAT-M11-plan.md;
    docs/proposals/eligibility/17-decision-register.md; aws/platform.service.ts
    (ELIGIBILITY_PERMISSIONS); modules/eligibility/lifecycle.ts,
    services/governance/publish.ts, diff.ts, change-trail.ts,
    services/persistence/versions.ts (requireDraftStillOpen),
    services/compile/plan-cache.ts,
    services/invalidation/on-definition-published.ts,
    db/eligibility-versions.table.ts, eligibility-plans.table.ts;
    docs/debt/eligibility-published-range-exclusion.md; rule-level source and
    test references
  - >-
    react-console: components/eligibility/governance/publish-dialog.tsx,
    version-history.tsx, version-diff.tsx, lib/eligibility/status.ts;
    acceptance/eligibility/journeys/governance/*.json and
    adversarial/ELIG-ACC-0690, 0691.
controls: [TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, 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-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
exercised_by: [FAS-PFM-ELG-01-02, FAS-PFM-ELG-01-03, FAS-PFM-ELG-01-04, FAS-PFM-ELG-03-02, FAS-PFM-ELG-03-05]
suites: [TST-PFM-ELG-003, TST-PFM-ELG-004, TST-PFM-ELG-089, TST-PFM-ELG-163, TST-PFM-ELG-165, TST-PFM-ELG-166, TST-PFM-ELG-169, TST-PFM-ELG-170, TST-PFM-ELG-178, TST-PFM-ELG-180, TST-PFM-ELG-181, TST-PFM-ELG-185, TST-PFM-ELG-188, TST-PFM-ELG-189, TST-PFM-ELG-411, TST-PFM-ELG-413, TST-PFM-ELG-432, TST-PFM-ELG-434, TST-PFM-ELG-435, TST-PFM-ELG-462]
---
# Release, schedule and restore rule versions

## Purpose

A release makes a reviewed expression available to consumers. Version history lets staff explain and reverse that choice.

## How It Works

A publisher reviews the draft, its validation and comparison with the earlier release. Effective dates support planned changes. An optional simulation adds a view of the likely impact. The publisher commits the release and receives its numbered version. Following consumers can then use the effective expression. Compatibility checks expose followers that cannot support the change. A forced release suspends those incompatible uses for repair. The publisher can inspect older versions and restore an earlier expression through a fresh release. Racing edits or releases can produce conflicts requiring a reload. Publication has no active second-person approval stage.

## Relationships

- Author a readable eligibility rule provides the draft to review and release.
