The Rules section is one record table grouped by kind, Limit then Boolean, on fixed columns, edited in place: Edit opens a row's controls in their columns, Add rule opens a dense row above the table, and every change is staged into a tray that lists the deltas with Undo and applies them as one rule-change act. The reduction policy is a column of the rule beside its limit. History shows counts only. Group rows are a quiet heading rather than a divider, the maintainer's pick from four rounds of outside-model ideation. Dense rows align to the top and render each error under its control in every form family (design D16), replacing the below-row error block; the forms library gains the batch form (rows plus one tray) and the RowField dense and label-hidden options. Migration 00019 records the governing reduction policy on effect rows. Archive staged-rule-changes with its spec updates (entitlement-set- management, entitlement-set-history, entitlements, form-library, form-conventions, ui-quality-gate). Screens accepted 2026-09-19.
54 lines
2.3 KiB
Go
54 lines
2.3 KiB
Go
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial
|
|
// SPDX-FileCopyrightText: 2025-2026 Christian Galo
|
|
|
|
package entitlements
|
|
|
|
import "time"
|
|
|
|
// The caps and cadences of a rule change, in one place.
|
|
const (
|
|
// rematerializeSyncCap is how many carrying pools a rule commit
|
|
// materializes inside its own transaction; pools beyond it are left as
|
|
// pending obligations for the drain. Set from the timed run of
|
|
// cap_timing_test.go (2026-09-15): a fold costs 1.8 to 2.0 ms per pool
|
|
// and scales linearly from 50 to 800 pools, so 250 holds the exclusive
|
|
// rendezvous for about half a second here and stays well inside the 5 s
|
|
// lock_timeout a waiting materializer tolerates on a slower host.
|
|
rematerializeSyncCap = 250
|
|
|
|
// previewExactCap is the population size up to which the preview folds
|
|
// every carrying pool; above it the preview reports aggregates.
|
|
previewExactCap = rematerializeSyncCap
|
|
|
|
// previewNameCap is how many organizations a preview or a History row
|
|
// names before it counts the rest.
|
|
previewNameCap = 50
|
|
|
|
// recomputeDrainPollInterval is the poller's cadence. The commit starts
|
|
// its own drain workflow, so the poller only catches a failed start or a
|
|
// dead process; five seconds bounds that gap without the Temporal churn
|
|
// a tighter loop would cost.
|
|
recomputeDrainPollInterval = 5 * time.Second
|
|
|
|
// requestDrainBudget and requestDrainPoolCap bound what a deferred
|
|
// commit drains before it returns: the rest is the poller's, and the
|
|
// toast reports the actuals either way.
|
|
requestDrainBudget = 2 * time.Second
|
|
requestDrainPoolCap = 50
|
|
|
|
// recomputeMaxAttempts is how many times the drain retries one
|
|
// obligation before it is failed and left for the operator's Retry.
|
|
recomputeMaxAttempts = 5
|
|
)
|
|
|
|
// DrainPollInterval is recomputeDrainPollInterval for the poller workflow,
|
|
// which lives in internal/workflows/entitlements and cannot read the
|
|
// unexported constant. The cadence stays named once, here.
|
|
func DrainPollInterval() time.Duration { return recomputeDrainPollInterval }
|
|
|
|
// SyncCap is rematerializeSyncCap for the console, which states before a
|
|
// batch is applied that a population above the cap goes on recomputing after
|
|
// the commit returns (entitlement-set-management "The deferred path is stated
|
|
// before it is taken"). The cap stays named once, here.
|
|
func SyncCap() int64 { return rematerializeSyncCap }
|