Skip to content

feat: align product config vocabulary (actsAs, label, holiday sets) - #2581

Merged
jeremi merged 1 commit into
mainfrom
feat/product-alignment
Nov 7, 2026
Merged

jeremi merged 1 commit into
mainfrom
feat/product-alignment

Conversation

@jeremi

@jeremi jeremi commented Nov 7, 2026

Copy link
Copy Markdown
Member

Summary

Aligns configuration vocabulary that differed between products; the product is pre-1.0. Every renamed key has a config.removed-key entry naming its replacement, a CFG-NAME-5 row, a BREAKING: line in the product CHANGELOG, a note in release/notes/config-conventions/, and updated examples, fixtures, docs and regenerated schemas. No migration code.

BREAKING:

  • Casework, Documents and Messaging access profiles: role is renamed actsAs; values unchanged. The schema definitions CaseworkRole and AccessRole become CaseworkActsAs and ActsAs, and the Casework diagnostic casework.access-profile.missing-role becomes casework.access-profile.missing-acts-as. BReg profiles and the data sense of role (event records, Evidence subjects) are unchanged.
  • Coordinator: title is renamed label on a project, function, operation and step; the explain member presentation.title becomes presentation.label; the duplicate-title diagnostics become ...duplicate-function-label, ...duplicate-operation-label and ...duplicate-step-label.
  • Casework holiday-set file: holidaySet is renamed id, and an optional label is allowed. A calendar's holidaySet member, which names the set it uses, is unchanged.
  • Scheduling: a holiday set's because is renamed label, and label is now optional (the id names a set that writes none), as in the Casework holiday-set file. The schema definition HolidaySetPolicy becomes HolidaySet. because stays on every other Scheduling item.
  • caseworkctl dev report: a client names actsAs where it named role.
  • Upgrade: this release does not read state stored by 0.45.0 or earlier. Start Casework and Scheduling on a new database; finish Coordinator runs before upgrading. A stored document that holds a removed member is refused with a message that says it was stored by an earlier release and names the member.

Additive:

  • Coordinator event triggers accept an optional label and description, stored under presentation.eventTriggers.<id>, reported by check --explain, and outside the semantic revision (a wording edit keeps workflowRevision). Closes coordinator: let an event trigger declare a title and description #2549.
  • Casework, Documents, Messaging and Evidence access profiles accept an optional label and description (BReg profiles already have display). They are accepted for authoring and tooling. Casework keeps them in the review policy description, which any caller who may read that description, requesters included, can see, and they do not change a policy's behavioral binding. Evidence drops them at compile; Documents and Messaging only parse them, and none serve them until a view exists.

Commits

One per item, tests first:

  1. role to actsAs (Casework, Documents, Messaging).
  2. Coordinator event-trigger label and description.
  3. Coordinator title to label.
  4. Shared holiday-set shape {id, revision, label, dates}.
  5. Access profile label and description.
  6. Stored state from an earlier release is refused with a distinct diagnostic (Casework and Scheduling; Coordinator refuses a snapshot whose project presentation, function or operation holds title with definition.snapshot, and a step title in the free-form presentation.steps map still restores and is shown as written), with one PostgreSQL test per product.
  7. Access profile wording stays out of the Casework behavioral digest.
  8. Scheduling holiday-set label optional; caseworkctl dev report actsAs; removed-key tests for Documents, Messaging and Coordinator operations; wording and upgrade notes.
  9. Merge of main.

Earlier follow-up fixes the first and fourth commits missed: code behind the postgres-test feature, a holiday-set diagnostic path with two regenerated report examples, and a raw SQL query that read role from the pinned policy snapshot (it now reads actsAs; found by the PostgreSQL staffing suites).

Security review notes

This change renames each access profile's role to actsAs in Casework, Documents and Messaging. It adds an optional label and description to access profiles and to Coordinator event triggers, renames the Coordinator title to label, and gives the Casework and Scheduling holiday sets one shape. The branch had an independent security review of every reader of the renamed members, including reads of state stored by earlier releases.

Authorization meaning

  • Every Rust reader of the renamed member is typed, so the compiler checks the rename. The one string-keyed reader, the staffing shortfall query over the stored review policy, reads actsAs. The other stored-policy queries (deciding profiles, exclusions, required approvals) read members this change does not rename.
  • No separation-of-duties, distinct-approver, exclusion or staffing rule treats a missing member as "no constraint".
  • The access profile caller-match members (requiredScopes, requesterClients, actorKind, requesterTags) are untouched, including where they differ between products. The new label and description are never matched against a caller and reach no authorization decision, audit record, token, problem detail or log line; they are DisplayText, so bidirectional-control characters are refused. Coordinator trigger wording is kept outside the workflow revision, and a test pins that.

Refusals

  • Each renamed key is refused with config.removed-key naming its replacement: access-profile role (Casework, Documents, Messaging), the Casework holiday-set file's holidaySet, Scheduling holidaySets[*].because, and the Coordinator title at project, function, operation and step. A test per removed key checks it.
  • Configuration files with unknown members are refused, and actsAs is required.

Holiday sets

  • Deadlines and capacity read a holiday set's identifier, revision and dates only. The renamed and added members do not change them.

Stored state from earlier releases

  • Review policies stored with Casework reviews, published Scheduling policies, and retained Coordinator definitions that used title all carry the old member names. Every reader of stored state refuses them rather than reading a missing member as absent, and no compatibility read was added. The one exception is a Coordinator step title, which 0.45.0 wrote into the free-form presentation.steps map: it still restores and is shown as written, display only.
  • BREAKING: this release does not read state stored by 0.45.0 or earlier. A stored document that holds a removed member is refused as stored by an earlier release, and the message names the member. A PostgreSQL test per product checks the refusal for Casework and Scheduling; Coordinator's definition.snapshot refusal has its own test. Upgrade procedure: start Casework and Scheduling on a new database, and finish Coordinator runs first. Casework activation refuses while any stored review, in any lifecycle, holds the earlier shape. A PostgreSQL test covers a database whose only earlier review is no longer open. Casework history stored before the upgrade is not readable after it.

Stated limits

  • Rewording an access profile does not change any review policy's binding; a test pins it, and the closure keeps the wording.
  • Access-profile wording is visible to any caller that may read a review policy description, requesters included.

Not verified

  • An in-place upgrade from 0.45.0 with stored reviews, published Scheduling policies or retained Coordinator runs has not been exercised; the refusals are tested with rows rewritten to the earlier shape.

Kept out of this PR

  • Unifying the caller-match members across products. The members differ by product (container shape, unrestricted, which of requesterClients and actorKind is required). Unifying them changes who can reach what, so it needs its own security-reviewed change.
  • A purpose label in Evidence. Evidence has no purposes catalogue: a purpose is a purpose string on each grant and on each assertion definition, with nothing to attach a label to. Adding a label would mean inventing a catalogue, which is a design change, not an alignment.
  • Casework lifecycle and ReviewResult.status to state. A wire-protocol change with no authoring benefit; a follow-up.

Notes for review

  • The shared holiday-set shape is mirrored in Casework and Scheduling, not shared through a crate, to avoid a new cross-product dependency. Both emit a HolidaySet definition with {id, revision, label, dates}. Remaining difference: Casework allows 3660 dates; Scheduling allows 256. Both labels are optional.
  • The actsAs CFG-NAME-5 row has an empty refused-spellings column, because the lint refuses listed keys globally and role stays valid in its data sense. Review enforces it.
  • The Casework CHANGELOG format table in 0.45.0 is historical and not edited; the removed-key replacement texts do not cite its rows.
  • The runtime Casework holiday-set document and its API and client types keep holidaySet; only the authored file changes.

Follow-up

Verification

Run on this branch:

Check Result
Casework check-checkpoint.sh, check-schemas.sh pass
Messaging check-checkpoint.sh, check-contracts.sh pass
Documents check-checkpoint.sh, check-contracts.sh pass
Coordinator check-schemas.sh, check_dependency_direction.py pass
Scheduling check-checkpoint.sh, check-contracts.sh pass
BReg check-contracts.sh pass
Evidence check-contracts.sh, check-authoring-schema.sh, check-authoring-no-io.sh, check-config-key-paths.sh pass
Identifiers generate.py --check-references pass
check-config-conventions.py 129 findings recorded, 0 unrecorded, 0 stale
cargo fmt --check pass
cargo clippy --locked --all-targets -D warnings on the changed crates pass
cargo test --locked on the changed crates pass
All-features test targets compile for the changed crates pass

PostgreSQL (postgres:17, postgres-test feature, disposable database), on the tree after merging main:

Suite Result
Casework and caseworkctl 627 pass, 6 ignored, 3 fail under parallel load: the two install_script tests and at_least_once_completion_durably_deduplicates_after_lost_ack_and_exhausts_bounded_retries; see below
Messaging and messagingctl 545 pass
Scheduling 419 pass
Documents 264 pass, 1 ignored
Coordinator (with the Messaging and Scheduling binaries built as test-postgres.sh does) 848 pass, 13 ignored, plus messaging_integration, process_restart and the ignored scheduling_event_native run: all pass
evidencectl 971 pass, 13 ignored
BReg 2216 pass, 13 ignored on postgres:17; the 15 PostGIS spatial tests need PostGIS and failed there, then passed on postgis/postgis:17-3.5 (postgres_spatial_read 10 pass, 1 ignored; postgres_spatial_storage 10 pass). No BReg crate code changed

staffing_notice_counts_distinct_available_reviewers_without_exposing_members runs both the sufficient=false and sufficient=true cases and is inside the Casework count.

Three Casework tests failed in the full PostgreSQL run under parallel load: the two install_script signal-injection tests (signal_injecting_mv_exits_from_the_signal_it_sends, failed_post_switch_adoption_restores_every_changed_command_and_pointer) and at_least_once_completion_durably_deduplicates_after_lost_ack_and_exhausts_bounded_retries (a retry-count assertion). Rerun alone, install_script passes 14 of 14 (under three different temporary directories) and review_postgres passes 73 of 73. The cause is load, by inference and not proven. This branch touches none of install_script.rs, crates/registry-casework/install.sh or release/glibc-floor.env, so those tests are pre-existing and unaffected by it.

Config conformance corpus (binaries rebuilt from this tree): 6116 cells, 4554 pass, 3 expected failures, 0 fail, 0 blocked. cargo clippy --locked --all-targets -D warnings with postgres-test on the changed crates passes; cargo fmt --check passes.

No CLI help text changed, so the CLI catalog is not regenerated.

🤖 Generated with Claude Code

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 7, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-07T06:50:23.332411Z 0dcc9fd New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@jeremi
jeremi force-pushed the feat/product-alignment branch from 3de92da to 6e5a843 Compare November 7, 2026 04:54
@jeremi
jeremi added this pull request to the merge queue Nov 7, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Nov 7, 2026
Aligns configuration vocabulary that differed between products; the product is pre-1.0. Every renamed key has a `config.removed-key` entry naming its replacement, a CFG-NAME-5 row, a `BREAKING:` line in the product CHANGELOG, a note in `release/notes/config-conventions/`, and updated examples, fixtures, docs and regenerated schemas. No migration code.

BREAKING:

- Casework, Documents and Messaging access profiles: `role` is renamed `actsAs`; values unchanged. The schema definitions `CaseworkRole` and `AccessRole` become `CaseworkActsAs` and `ActsAs`, and the Casework diagnostic `casework.access-profile.missing-role` becomes `casework.access-profile.missing-acts-as`. BReg profiles and the data sense of `role` (event records, Evidence subjects) are unchanged.
- Coordinator: `title` is renamed `label` on a project, function, operation and step; the explain member `presentation.title` becomes `presentation.label`; the duplicate-title diagnostics become `...duplicate-function-label`, `...duplicate-operation-label` and `...duplicate-step-label`.
- Casework holiday-set file: `holidaySet` is renamed `id`, and an optional `label` is allowed. A calendar's `holidaySet` member, which names the set it uses, is unchanged.
- Scheduling: a holiday set's `because` is renamed `label`, and `label` is now optional (the id names a set that writes none), as in the Casework holiday-set file. The schema definition `HolidaySetPolicy` becomes `HolidaySet`. `because` stays on every other Scheduling item.
- `caseworkctl dev` report: a client names `actsAs` where it named `role`.
- Upgrade: this release does not read state stored by 0.45.0 or earlier. Start Casework and Scheduling on a new database; finish Coordinator runs before upgrading. A stored document that holds a removed member is refused with a message that says it was stored by an earlier release and names the member.

Additive:

- Coordinator event triggers accept an optional `label` and `description`, stored under `presentation.eventTriggers.<id>`, reported by `check --explain`, and outside the semantic revision (a wording edit keeps `workflowRevision`). Closes #2549.
- Casework, Documents, Messaging and Evidence access profiles accept an optional `label` and `description` (BReg profiles already have `display`). They are accepted for authoring and tooling. Casework keeps them in the review policy description, which any caller who may read that description, requesters included, can see, and they do not change a policy's behavioral binding. Evidence drops them at compile; Documents and Messaging only parse them, and none serve them until a view exists.

Signed-off-by: Jeremi Joslin <jeremi@joslin.fr>
@jeremi
jeremi force-pushed the feat/product-alignment branch from 6e5a843 to 0dcc9fd Compare November 7, 2026 06:47
@jeremi
jeremi added this pull request to the merge queue Nov 7, 2026
Merged via the queue into main with commit 5a8e77b Nov 7, 2026
72 checks passed
@jeremi
jeremi deleted the feat/product-alignment branch November 7, 2026 09:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

coordinator: let an event trigger declare a title and description

1 participant