Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
n/a
0 / 0
n/a
0 / 0
CRAP
n/a
0 / 0
1<?php
2
3declare(strict_types=1);
4/**
5 * SPDX-FileCopyrightText: 2026 LibreCode coop and contributors
6 * SPDX-License-Identifier: AGPL-3.0-or-later
7 */
8
9namespace OCA\Libresign\Service\Policy\Contract;
10
11use OCA\Libresign\Service\Policy\Model\PolicyContext;
12use OCA\Libresign\Service\Policy\Model\PolicyLayer;
13
14interface IPolicyDefinition {
15    public function key(): string;
16
17    public function resolutionMode(): string;
18
19    public function retainDefaultInGroupChoices(): bool;
20
21    /** @return list<string> */
22    public function supportedScopes(): array;
23
24    public function supportsScope(string $scope): bool;
25
26    public function getAppConfigKey(): string;
27
28    public function getUserPreferenceKey(): string;
29
30    public function isBackendOnly(): bool;
31
32    public function isHelper(): bool;
33
34    public function parentPolicyKey(): ?string;
35
36    /** @return list<string> */
37    public function compositeChildren(): array;
38
39    public function normalizeValue(mixed $rawValue): mixed;
40
41    public function validateValue(mixed $value, PolicyContext $context): void;
42
43    /**
44     * Validate a value that is about to be persisted (system, group or user
45     * scope). Runs the regular validateValue() checks plus any constraint that
46     * only makes sense at configuration time, such as requiring an external
47     * capability to be available. Runtime resolution keeps using
48     * validateValue() so already stored values are not silently discarded
49     * when the environment changes later.
50     *
51     * @throws \InvalidArgumentException when the value must not be saved
52     */
53    public function validateValueForPersistence(mixed $value, PolicyContext $context): void;
54
55    /**
56     * Validate the complete set of values of a composite policy family before
57     * any of its keys is persisted.
58     *
59     * The framework knows which keys belong to the same family and collects the
60     * final intended value of each one, including the keys the caller is not
61     * writing. Only the policy that owns the family knows how its settings
62     * relate to each other, so it is the one that decides whether the
63     * combination is acceptable. Implementations that have no rule spanning
64     * more than one key do nothing.
65     *
66     * @param array<string, mixed> $normalizedValues Final intended value of every key of the family
67     * @param list<string> $submittedKeys The keys the caller is writing right now
68     * @throws \InvalidArgumentException when the combination must not be saved
69     */
70    public function validateCompositeValuesForPersistence(array $normalizedValues, array $submittedKeys, PolicyContext $context): void;
71
72    /** @return list<mixed> */
73    public function allowedValues(PolicyContext $context): array;
74
75    public function defaultSystemValue(): mixed;
76
77    /** @return array<string, mixed> */
78    public function resolvedStateMeta(PolicyContext $context): array;
79
80    /**
81     * Whether this policy supports being saved as a user personal preference.
82     * Returns false for administrative-only policies (e.g. groups_request_sign)
83     * that must never appear in the user preferences screen.
84     */
85    public function supportsUserPreference(): bool;
86
87    /**
88     * Whether a signature request may carry its own value for this policy.
89     * Decided independently of supportsUserPreference(): a value accepted for
90     * one request is not necessarily one the user may save as a personal default.
91     */
92    public function supportsRequestOverride(): bool;
93
94    /**
95     * PolicySpec::LIFECYCLE_REQUEST_SNAPSHOT when the value belongs to the
96     * signature request: it is stored on the request and kept once the request
97     * enters the signing flow. PolicySpec::LIFECYCLE_RUNTIME when it is read from
98     * the current policy whenever it is needed, so a change reaches sent requests.
99     */
100    public function requestLifecycle(): string;
101
102    /**
103     * Whether group-level rules for this policy should be filtered from counts and listings
104     * for the current non-system actor when they were created by a system administrator.
105     */
106    public function shouldFilterVisibleGroupCountsForActor(PolicyContext $context, ?PolicyLayer $systemPolicy): bool;
107
108    /**
109     * Whether the current actor may manage group-level rules for this policy.
110     *
111     * @param list<PolicyLayer> $groupLayers Group layers already applicable to the actor context.
112     */
113    public function canCurrentActorManageGroupPolicy(PolicyContext $context, ?PolicyLayer $systemPolicy, array $groupLayers): bool;
114
115    /**
116     * Whether the current actor may edit a system-created group rule for this policy.
117     */
118    public function canCurrentActorEditSystemCreatedGroupPolicy(PolicyContext $context, ?PolicyLayer $systemPolicy, PolicyLayer $existingPolicy): bool;
119
120    /**
121     * Whether this policy supports group-admin-delegated override rules.
122     * When true, a separate `__delegated_override` slot is used so that the
123     * system-created seed and the group-admin override coexist independently.
124     */
125    public function supportsGroupAdminDelegation(): bool;
126
127    /**
128     * Validate a proposed group-admin-delegated value against the parent
129     * system-created seed value.  Implementations should throw
130     * \InvalidArgumentException with a translatable message when the proposed
131     * value violates policy constraints.
132     *
133     * This hook is called only when the actor is a non-system-admin and the
134     * definition returns true from supportsGroupAdminDelegation().
135     */
136    public function validateGroupAdminDelegatedValue(
137        mixed $proposedNormalizedValue,
138        mixed $parentSeedNormalizedValue,
139        PolicyContext $context,
140    ): void;
141}