Repository navigation
Make the Policy Workbench compound helper use policy definitions #8687
Description
Part of #8684. #8686 is complete.
Goal
Make the existing Policy Workbench compound helper support more than one child policy.
The backend exposes compound relationships through:
parent policy + meta.compositeChildren[]
This is the source of truth for compound membership.
Current backend definitions already expose:
maximum_validity -> renewal_interval
signing_mode -> worker_config
signature_rejection -> rejection_* children
The existing signature stamp editor also combines signature_stamp with collect_metadata, but that relationship is not yet declared by the backend. As part of this issue, add the minimal backend contract needed to expose:
signature_stamp -> collect_metadata
through meta.compositeChildren.
Do not create another frontend list of child policy keys and do not add a frontend fallback for missing compositeChildren.
The backend change here is limited to declaring the existing compound relationship. Do not change authorization, persistence semantics, or turn collect_metadata into a helper/catalog-hidden policy unless independently required by an existing contract.
Definition contract
Add a generic compound mapping to RealPolicySettingDefinition.
Use this shape, or the closest equivalent that follows the current TypeScript style:
interface RealPolicyCompoundBehavior {
compose: (
valuesByPolicyKey: Record<string, EffectivePolicyValue | undefined>,
) => EffectivePolicyValue
decompose: (
editorValue: EffectivePolicyValue,
) => Record<string, EffectivePolicyValue>
}
interface RealPolicySettingDefinition {
// existing fields...
compound?: RealPolicyCompoundBehavior
}The parent key is definition.key.
The child keys come from:
policy.meta?.compositeChildren ?? []The shared engine loads those keys and passes the keyed values to compose().
When saving, it passes the editor value to decompose() and sends the returned keyed values through the compound store methods from #8686.
Keep policy logic local
The shared engine must not know how a specific policy combines its values.
Keep or move that mapping to the related policy module.
Existing compound settings must keep working:
- request expiration;
- signing execution;
- signature stamp / collect metadata.
For signature stamp, expose the existing signature_stamp -> collect_metadata relationship from the backend and consume it through meta.compositeChildren. Do not hard-code collect_metadata as a fallback child in the shared Workbench engine.
Do not move their normalization rules into useRealPolicyWorkbench.ts.
Clear/reset
The backend has no compound DELETE endpoint.
Keep using the existing clear methods for each persisted member.
If one clear fails:
- show the existing Workbench error;
- reload persisted/effective state;
- do not keep a UI state that assumes all members were cleared.
Do not add a backend DELETE endpoint in this issue.
Main files
Start with:
src/views/Settings/PolicyWorkbench/settings/realTypes.ts
src/views/Settings/PolicyWorkbench/policyWorkbenchCompoundPolicies.ts
src/views/Settings/PolicyWorkbench/useRealPolicyWorkbench.ts
lib/Service/Policy/Provider/SignatureText/SignatureTextPolicy.php
Update only the existing compound policy modules and the minimal backend definition needed for the mapping contract.
Security
Do not change authorization behavior.
Continue using backend:
meta.compositeChildren;allowedValues;editableByCurrentActor;- delegation metadata;
- save validation.
Frontend code must not widen permissions.
Tests
Update the existing compound-policy tests.
Cover:
- a parent with at least two children;
- child keys come from
meta.compositeChildren; - missing
meta.compositeChildrendoes not cause the shared engine to invent frontend child keys; compose()receives keyed parent/child values;decompose()produces the keyed write payload;- system/group/user hydration still works;
- save uses the compound store method from Add compound policy write methods to the policies store #8686;
- existing compound policies keep working;
signature_stampexposescollect_metadatathrough backend compound metadata;- helper children do not become catalog settings;
collect_metadatakeeps its existing independent catalog behavior.
Add/update the focused backend definition test for the signature_stamp -> collect_metadata relationship.
Done when
- Compound policies are not limited to one companion.
- Child keys come from backend metadata.
- No frontend fallback list of compound child keys exists.
-
signature_stamp -> collect_metadatais exposed by the backend definition. - Policy-specific mapping is defined by the policy module.
- Existing compound policies keep working.
- Compound saves use Add compound policy write methods to the policies store #8686.
- No Signature Rejection-specific branch is added.
- Focused frontend and backend tests pass.
-
npm run lintpasses. -
npm run ts:checkpasses.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Projects
- StatusShow more project fields4. Done
Activity
vitormattos commentedon Sep 26, 2026
@nva138 do you want to go ahead with this after your previous PR?
nva138 commentedon Sep 27, 2026
Sure, I'm on it!
nva138 commentedon Sep 28, 2026
Quick question before I start: only SignatureRejectionPolicy sets compositeChildren on the backend. Request expiration, signing mode and signature stamp don't, so the engine would lose their children.
Should I add compositeChildren to those three backend definitions, or keep a frontend fallback for them?
vitormattos commentedon Sep 29, 2026
Thanks for checking this before starting. I reviewed the current backend definitions and updated the issue description to make the intended contract explicit.
maximum_validity -> renewal_intervalandsigning_mode -> worker_configare already exposed throughmeta.compositeChildren. The missing existing relationship issignature_stamp -> collect_metadata, so the issue now includes the minimal backend definition update for that case as well.Please do not add a frontend fallback or another hard-coded list of child policy keys. The Workbench should use
meta.compositeChildrenas the source of truth, while the policy-specificcompose()/decompose()logic stays in the corresponding policy module.The description and tests/Done criteria have been updated accordingly. You can go ahead with the implementation.