You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: registry-v2.md
+30-7Lines changed: 30 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -108,27 +108,50 @@ A policy carries a list of [`RepositoryPolicy`](/registry/policy.proto) entries,
108
108
109
109
A matched entry has two parts, evaluated in this order for each candidate release `{repository, package, version}`:
110
110
111
-
1.**Overrides** (`overrides`) — the final say. An `OVERRIDE_ACTION_ALLOW`override whose `ref` matches the release permits it immediately and **bypasses the restriction**; an `OVERRIDE_ACTION_DENY`override blocks it. When several overrides match, the one with the most specific `requirement` wins (a `requirement`-bearing entry is more specific than a bare-`package` entry).
112
-
2.**Restriction** (`restriction`) — applied to every release in the repository, but **never** to a release permitted by an `ALLOW` override. A release is blocked if any limit fires.
111
+
1.**Overrides** (`overrides`) — package-scoped decisions and exceptions. A matching `OVERRIDE_ACTION_ALLOW`permits the release and bypasses every policy restriction; `OVERRIDE_ACTION_DENY` blocks it. When several ALLOW or DENY overrides match, the one with the most specific `requirement` wins (a `requirement`-bearing entry is more specific than a bare-package entry). If no final override decides the release, matching ADVISORY, RETIREMENT, and COOLDOWN overrides remove only their selected restriction.
112
+
2.**Restriction** (`restriction`) — applied to every release that was not permitted or blocked by a final override. A release is blocked if any remaining limit fires.
113
113
114
-
A `PackageRef` (used by `Override.ref`) matches a release when its `package` equals the release's package and, if `requirement` is set, the release's version satisfies that requirement.
114
+
A `PackageRef` matches a release when its `package` equals the release's package and, if `requirement` is set, the release's version satisfies that requirement using Hex version-requirement semantics.
115
+
116
+
Policy editors should populate an ADVISORY override's `requirement` from the advisory's affected ranges when the override is created. Keeping that recorded scope prevents a later expansion of the same advisory from being accepted without another policy change. Each advisory range uses `and` between its bounds and separate ranges use `or`. `and` binds before `or`, and parentheses aren't valid in Hex version requirements.
117
+
118
+
Each `Override` action has a fail-closed field contract:
119
+
120
+
*`OVERRIDE_ACTION_ALLOW` and `OVERRIDE_ACTION_DENY` set neither selector. ALLOW bypasses all policy restrictions, while DENY blocks the release.
121
+
*`OVERRIDE_ACTION_ADVISORY` sets only `advisory_id`. The identifier matches the advisory's primary ID or any alias, case-insensitively. It removes only that advisory, so another advisory affecting the same release is still evaluated.
122
+
*`OVERRIDE_ACTION_RETIREMENT` sets only `retirement_reason`. It accepts the release only while its current retirement reason equals that value. A changed reason is evaluated as a new finding. Changing only the retirement message does not change the match.
123
+
*`OVERRIDE_ACTION_COOLDOWN` sets neither selector. It bypasses only the cooldown declared by this policy. A project's local cooldown still applies independently.
124
+
125
+
Every override may carry a comment that clients surface as the policy's explanation. Comments must contain at most 500 Unicode code points and must be valid UTF-8 without Unicode control, format, line separator, or paragraph separator characters. Comments on a `VISIBILITY_PUBLIC` policy are public.
126
+
127
+
Clients ignore an override if it is malformed, has an unknown action or retirement reason, has an invalid package requirement, or sets selector fields that its action does not permit. Ignoring invalid override data keeps the affected release subject to the policy restriction. Older clients continue applying field 3 ALLOW and DENY overrides. They decode newer actions as unknown enum values and ignore their unknown selector and comment fields, so advisory, retirement, and cooldown overrides can't make an older client fail open.
115
128
116
129
#### Restriction limits
117
130
118
131
*`advisory_min_severity` is set and the release's maximum advisory severity is greater than or equal to it. It is an `AdvisorySeverity` (imported from [`package.proto`](/registry/package.proto), `SEVERITY_NONE` … `SEVERITY_CRITICAL`). `SEVERITY_NONE` blocks any release that has any advisory at all.
119
132
*`retirement_reasons` is non-empty and the release's `retired.reason` is one of the listed values. Each is a `RetirementReason` (imported from [`package.proto`](/registry/package.proto), `RETIRED_OTHER` … `RETIRED_RENAMED`).
120
-
*`cooldown` is set and non-zero and the release's `published_at` is more recent than `now - cooldown_duration`. The grammar matches the Hex cooldown configuration grammar: `"Nd"`, `"Nw"`, `"Nmo"`, or `"0"`; `"0"` (or unset) imposes no minimum age. If multiple active policies declare cooldowns, the effective cooldown is the strictest one.
133
+
*`cooldown` is set and non-zero and the release's `published_at` is more recent than `now - cooldown_duration`. The grammar matches the Hex cooldown configuration grammar: `"Nd"`, `"Nw"`, `"Nmo"`, or `"0"`; `"0"` (or unset) imposes no minimum age.
121
134
122
135
### Client behavior
123
136
124
137
A conformant client:
125
138
126
-
1.**Reads policy references from multiple opt-in sources** (e.g. project file, environment variable, global config) and composes them by intersection: a release must pass every active policy. The active set is deduplicated on `(repository, name)`.
127
-
2.**Fetches and verifies each active policy** before resolution, using the configured public key for the repository.
139
+
1.**Reads one policy reference from its opt-in sources** (e.g. project file, environment variable, global config), using the client's documented configuration precedence.
140
+
2.**Fetches and verifies the active policy** before resolution, using the configured public key for the repository.
128
141
3.**Filters the candidate set at resolution time only.** Lockfile entries are trusted at install; filtering does not apply to versions already in the lockfile.
129
142
4.**Caches each policy independently** with last-known-good fall-back on fetch failure (network, 5xx, signature mismatch). The maximum staleness window should be at most 30 days, bounding the suppression window for a network adversary.
130
143
131
-
Across the active set, policies compose by intersection: a release survives only if every active policy permits it and no active policy's restriction blocks it. Cooldowns compose by strictest-wins — the effective cooldown is the longest duration across all active policies, and local cooldown configuration cannot lower it.
144
+
The active policy and local cooldown compose by strictest-wins. Local cooldown configuration can increase the effective cooldown but cannot lower a cooldown declared by the policy.
145
+
146
+
### Auditing
147
+
148
+
Clients expose three audit modes for locked dependencies:
149
+
150
+
* The default audit reports all advisory and retirement findings without applying dependency policies.
151
+
* The policy-overrides audit starts with all advisory and retirement findings, then reports only findings that are not accepted by a matching ALLOW, ADVISORY, or RETIREMENT override.
152
+
* The policy audit reports only findings rejected by the active policy's advisory severity threshold, retirement reasons, and matching overrides.
153
+
154
+
The two policy-aware audit modes require an active policy and fail when it cannot be loaded. Project advisory and retirement ignores are additive and are applied after policy evaluation. Policy-aware audit modes cover security advisories and release retirements; they do not audit cooldown restrictions or perform general lockfile validation.
Copy file name to clipboardExpand all lines: security/threat-model/mitigations.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -266,11 +266,13 @@ Client-side enforcement of organization-defined policies, currently available in
266
266
| Cooldown rule | Implemented | Blocks newly published versions until they reach a minimum age; effective cooldown is the strictest of local config and the policy |
267
267
| Advisory rule | Implemented | Blocks versions with security advisories at or above a severity threshold (or with any advisory) |
268
268
| Retirement rule | Implemented | Blocks versions retired for the configured reasons |
269
-
| Package/version overrides | Implemented | Allow/deny exceptions; most specific match wins, an allow exempts the release from the restriction |
269
+
| Package/version overrides | Implemented | Package and version scoped allow, deny, advisory, retirement, and policy-cooldown overrides; comments are available on every type |
270
+
| Finding-scoped policy overrides | Implemented | Advisory and retirement overrides accept one current identifier or reason without accepting unrelated findings; cooldown overrides don't disable local cooldown configuration |
270
271
| Lockfile exemption | Implemented | Versions already locked are exempt from filtering, so re-resolution keeps a locked-but-now-blocked entry instead of failing |
271
272
| Policy visibility | Implemented | Public policies are fetchable anonymously; private policies require authentication to the owning organization |
272
273
| Fail-closed enforcement | Implemented | Malformed config, fetch failures (without a cached copy), or 404/401 abort resolution rather than resolving unenforced |
273
274
|`mix hex.policy show` / `why`| Implemented | Summarize the active policy and explain per-version why each is allowed or blocked |
275
+
| Policy-aware dependency audit | Implemented | Audits locked advisory and retirement findings against policy overrides and restriction thresholds |
0 commit comments