registrystack / registrystack/registry-stack

BREG: plan reviewed changes from authorized target-record snapshots

Open
#922 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
2
Forks
0
Avg merge
2h 55m
Merged PRs (30d)
130

Description

## Problem and outcome

A reviewed change can depend on facts already stored in its target records. For example, replacing a holding's daily manager should preserve the prior assignment's holding and work function, validate the transition against its stored dates, and apply the approved changes only if those dependencies still match.

BREG's current author-visible planner context contains declared request fields. Caller-supplied copies of stored values cannot establish those checks, and a browser check cannot cover other API callers or changes made during review.

Support a small, declared projection of authorized existing target records during native change-request planning, with the record-version dependencies preserved through proposal freezing, review and application. This is a capability enhancement; it does not establish a defect in existing supported request-only workflows.

## Current source boundary

Source baseline: `7a91e17560ac467521e532b23baaffc0df08ba7b`.

- The [Rhai context builder](https://github.com/registrystack/registry-stack/blob/7a91e17560ac467521e532b23baaffc0df08ba7b/crates/registry-breg/src/rhai_planner.rs#L403) exposes declared request fields.
- The [person-name-change acceptance script](https://github.com/registrystack/registry-stack/blob/7a91e17560ac467521e532b23baaffc0df08ba7b/products/breg/acceptance/person-name-change-rhai/scripts/person-name-change.rhai#L1) explicitly describes its request-only context.
- The declarative [effect-value contract](https://github.com/registrystack/registry-stack/blob/7a91e17560ac467521e532b23baaffc0df08ba7b/crates/registry-breg/src/contract.rs#L580) and [value compilation](https://github.com/registrystack/registry-stack/blob/7a91e17560ac467521e532b23baaffc0df08ba7b/crates/registry-breg/src/change_request.rs#L1216) do not expose previous target fields either.

BREG already reads records internally for authorization, preparation and concurrency checks. Reuse that owning path where appropriate. Before implementation, inspect the latest source and coordinate with any ongoing Rhai/context refactoring.

## Proposed bounded scope

- Start with existing records explicitly named by typed CR target references. The first example reads the same prior assignment it patches.
- Let governed configuration declare the stored fields needed by the planner. The host admits the target and supplies a bounded immutable projection after authorization. Declaring a projection grants no caller authority.
- Preserve the distinction between processing and disclosure. Stored inputs must not leak through effects, metadata, review views, errors or logs outside the applicable classification and disclosure rules.
- Bind every supplied snapshot to the frozen proposal's exact dependency revision and applicable contract. Application commits the approved effects against valid dependencies or refuses as stale. It must not recompute different effects under an old approval.
- Refactor preparation, row loading and shared context construction where useful. Keep transactions, authorization, proposal freezing, review, receipts and events in their current owners. Keep domain semantics in the authored project and script.

Processing-only references outside declared mutation targets, collection queries, counts, absence checks and dynamic target discovery are separate extensions with additional concurrency requirements. Immediate-action context can reuse appropriate primitives later, but a single invocation does not establish the dependency contract across a CR review interval.

Before settling syntax, compare the projected-context approach with any smaller native mechanism that can enforce the same checks. Preserve simple fixed effects and existing request-only planners.

## Acceptance example: reviewed manager replacement

Use the draft holding/work concepts and date convention documented in [PublicSchema's work guidance](https://github.com/PublicSchema/publicschema.org/blob/1ea9ce333918693b29aec31068fac412e02cb8dc/docs/farm-operators-draft.md#L57).

1. Create a holding and an open daily-management assignment with a known start date and typed Person/Farm references.
2. Submit the prior-assignment reference, successor-person reference and transition date. Read the prior holding, function, start and end from admitted stored context.
3. Require that the old assignment is open and the transition is later than its start. Propose ending it on that date and creating its successor on the same holding with the same function values, starting on that date. Use an exclusive end date; preserve holder responsibility and Farm identity without imposing a universal single-manager rule.
4. A different authorized reviewer approves the exact effects; an authorized applier commits both changes atomically. Rejection changes neither record.
5. A concurrent change to the prior assignment causes application to refuse and requires the existing authorized rebase/resubmit/review path. Replay after a committed application returns the original result without reevaluating the planner or duplicating records/events.

## Completion criteria

- [ ] The projection has compiled authoring/schema support, field-addressed diagnostics and explanation. Existing request-only planners retain their behavior.
- [ ] Undeclared fields, wrong target kinds and unauthorized records are refused before protected values enter the planner. Tests cover output and error disclosure.
- [ ] Native planning uses a consistent admitted snapshot set. Confirmed transaction retries cannot reuse stale stored inputs; uncertain outcomes use existing idempotency recovery. Preserve deterministic lock ordering and one bounded execution deadline.
- [ ] The frozen proposal covers every exposed record dependency and its applicable contract, including a declared target left unchanged by a particular planner branch.
- [ ] Target or incompatible contract changes cannot apply a different plan under an earlier approval. Self-review and unauthorized application remain refused according to the authored policy.
- [ ] A real PostgreSQL journey proves same-holding/function replacement, invalid-date refusal, atomicity, unchanged holder links, stale-dependency refusal and replay without duplicate effects/events. Existing correction journeys still pass.
- [ ] Existing planner/journey tooling accepts explicit synthetic snapshots and asserts exact effects and refusals, with runtime authorization verified separately.
- [ ] Maintained documentation includes the authoring example and recovery path. No agricultural Rust runtime types or general database scripting API are required.

This capability is a prerequisite for offering the stored-state-dependent workflow above. Simple name-correction starters can proceed independently.

Contributor guide

Open the contributing guide

Research direction

Start by reading crates/registry-breg/src/rhai_planner.rs, contract.rs, and change_request.rs at the stated source boundary, then compare the person-name-change-rhai acceptance script with the latest Rhai/context work. Trace the existing authorization, preparation, proposal-freezing, application, and PostgreSQL journey tooling before choosing an approach. Done means the bounded projection, frozen dependencies, refusal and replay behavior, acceptance journey, and documentation criteria are covered without changing request-only planners.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql, rust
Domain
backend-api-design, databases, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
32/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.