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
@@ -136,9 +134,9 @@ decisions before canonical guides, templates, or consumer workflows adopt it:
136
134
| Wrapper scope | Exactly one reusable-workflow job. | Permit repository-specific jobs in the same file, or define pre/post extension jobs. |
137
135
| Trigger ownership | The caller owns manual, schedule, default-branch push, and pull-request triggers. | Move some trigger policy into separate workflows or omit selected event classes. |
138
136
| Pull-request activities | Keep all six listed activity types. | Reduce the activity list if a v8 behavior is intentionally unsupported. |
139
-
| Concurrency | Use the PR-number-or-ref key and never cancel a release-capable run. | Use separate groups per event class or permit cancellation for non-mutating paths. |
140
-
| Permissions | Declare the five current scopes at workflow level. | Introduce settings-based least-privilege profiles or split read-only validation from release work. |
141
-
| Fork behavior | Skip fork-originated pull requests in this credentialed wrapper. | Add a separate secret-free workflow or define another supported fork-validation design. |
137
+
| Concurrency | Use the PR-number-or-ref key and cancel only superseded pull-request runs. | Use separate groups per event class or disable cancellation for all runs. |
138
+
| Permissions | Set top-level permissions to empty and grant only `contents: read`, `pages: write`, and `id-token: write` to the caller job. | Define a narrower profile for repositories that do not publish Pages. |
139
+
| Fork behavior | Invoke the reusable workflow unconditionally; Plan rejects unsupported fork events before credentialed or repository-defined code. | Add an independent secret-free fork-CI workflow. |
142
140
| Credentials | Explicitly map the three v8 credentials. | Define a narrower credential profile for repositories that cannot publish. |
143
141
| Optional surface | Permit only documented `TestData`, workflow inputs, schedule timing, and presentation metadata. | Allow additional extension points after naming and compatibility rules are agreed. |
144
142
@@ -171,9 +169,9 @@ fleet campaign. Branch names, `latest`, floating minor tags, and unqualified tar
171
169
| Default-branch push | Keep `push.branches: [main]`. | `v8` authorizes stable releases from the tested default-branch push. |
172
170
| Manual dispatch | Keep `workflow_dispatch`. | Provides the documented default-branch manual release and recovery path. |
173
171
| Schedule | Keep a scheduled health run. | Exercises current dependencies even when repository code is unchanged. |
174
-
| Concurrency | Use the PR-number-or-ref key with `cancel-in-progress: false`. | Cleanup and stable release runs stay distinct; release mutations queue instead of being interrupted. |
175
-
| Permissions | Declare the five documented permissions explicitly. | The called workflow cannot elevate caller permissions. |
176
-
| Fork guard | Skip pull requests whose head repository differs from `github.repository`. | GitHub withholds the required repository secrets from fork pull requests. |
172
+
| Concurrency | Use the PR-number-or-ref key and cancel only pull-request runs. | Pull-request changes converge promptly while non-pull-request runs serialize by ref. |
173
+
| Permissions | Use empty top-level permissions and the three caller-job permissions shown above. | Repository-local reads and Pages/OIDC stay narrow; App tokens provide broader authority. |
174
+
| Fork authorization | Leave the caller job unconditional. | Plan rejects unsupported forks before credentials or repository-defined code run. |
177
175
| Reference | Use the intended internal floating major tag (`v8`) after tag governance is enforced. | Compatible owned releases roll out centrally; breaking releases require a new major and campaign. |
178
176
| Credentials | Explicitly map the three required secrets. | Satisfies the `v7+` contract and prevents unrelated secret inheritance. |
179
177
| Scope | Keep the caller as a single delegation job. | Repository-specific automation remains independently understandable and maintainable. |
@@ -202,14 +200,14 @@ an approved structure:
202
200
- any Process-PSModule reference other than the intended major tag (`v8`), including a branch, `latest`, minor tag,
203
201
exact patch tag, or full commit SHA;
204
202
- missing `push` or `unlabeled` triggers;
205
-
- `cancel-in-progress: true` or the old ref-only concurrency key;
203
+
- a `cancel-in-progress` expression other than `github.event_name == 'pull_request'` or the old ref-only concurrency key;
206
204
- trigger-level path filters that bypass Process-PSModule important-file evaluation;
207
205
- unrelated additional jobs in the caller wrapper;
208
206
- omitted documented permissions without a verified settings-based least-privilege profile.
209
207
210
-
Fork-originated pull requests are skipped by the candidate caller because reusable-workflow caller jobs cannot select a
211
-
GitHub Environment and repository secrets are unavailable to forks. Supporting fork CI requires a separate, secret-free,
212
-
read-only validation workflow under this candidate; #514 must approve that boundary.
208
+
The candidate caller invokes the reusable workflow for fork-originated pull requests. Plan rejects unsupported fork events
209
+
before credentials or repository-defined code run. Supporting fork CI requires a separate, secret-free, read-only workflow;
210
+
issue [#514](https://github.com/PSModule/Process-PSModule/issues/514) must approve that boundary.
213
211
214
212
The candidate keeps repository-specific automation in a separate workflow file. That keeps the Process-PSModule wrapper
215
213
identical enough for automated comparison while allowing modules to own unrelated schedules, generation, or integration
Copy file name to clipboardExpand all lines: docs/content/reference/process-workflow-lifecycle-design.md
+9Lines changed: 9 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -33,6 +33,14 @@ Plan resolves the caller event into one release classification before build and
33
33
34
34
Plan records its classification and release decision in enriched Settings. Downstream jobs consume that Settings object and do not infer policy from events, labels, or repository settings again.
35
35
36
+
## Candidate event authorization
37
+
38
+
The caller invokes the reusable workflow without a caller-level fork or event condition. Plan is the event-authorization boundary: it rejects unsupported fork pull requests before credentialed or repository-defined code runs. An authorization rejection produces no usable Settings and no credentialed follow-on work.
39
+
40
+
Every downstream job depends on a successful authorized Plan and valid Settings. This requirement applies equally to jobs that use `always()`: their conditions first require the Plan result and Settings validity, then apply their own failure-handling logic. A downstream job never parses missing or invalid Settings and cannot bypass the Plan gate.
41
+
42
+
Secret-free fork CI, if needed, is a separate workflow with its own trigger, authorization, and read-only contract. It is not a mode of the credentialed Process-PSModule reusable workflow.
43
+
36
44
## Candidate artifact and version boundary
37
45
38
46
Version resolution is the boundary between planning and release-capable work. The candidate carries one immutable release record in enriched Settings through build, test, and release execution:
@@ -155,6 +163,7 @@ The lifecycle contract is exercised with event payload fixtures and publication
155
163
| Scoped caller permissions | Empty caller top-level permissions, the three job grants, built-in-token checkout/read, and standard Pages/OIDC verification. |
156
164
| App authorization failure | Missing-App-token fixtures that prove user-facing operations fail closed without built-in token fallback. |
157
165
| Token boundary | Fixtures that prove App tokens are step-scoped and built-in-token operations remain within the caller job's boundary. |
166
+
| Event authorization | Unsupported-fork fixtures that prove Plan rejects before credentialed or repository-defined code, including for downstream `always()` jobs. |
Copy file name to clipboardExpand all lines: docs/content/reference/process-workflow-lifecycle-specification.md
+21-1Lines changed: 21 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -229,6 +229,26 @@ Scenario: Perform a user-facing repository operation
229
229
And it uses the App token only for the steps that require that authority
230
230
```
231
231
232
+
### FR12 — Plan MUST authorize events before downstream execution {#fr12}
233
+
234
+
The caller MUST invoke the reusable workflow without a caller-level fork or event condition. Plan MUST reject unsupported fork pull-request execution before any credentialed or repository-defined code runs. Every downstream job, including a job with `always()`, MUST require a successful authorized Plan and valid Settings. No downstream job MAY evaluate missing or invalid Settings or bypass the Plan gate.
235
+
236
+
#### Behavioral scenarios {#fr12-scenarios}
237
+
238
+
```gherkin
239
+
Scenario: Reject an unsupported fork pull request
240
+
Given a pull request originates from an unsupported fork
241
+
When Plan evaluates the event
242
+
Then Plan rejects the event before credentialed or repository-defined code runs
243
+
And no downstream job receives authorized Settings
244
+
245
+
Scenario: Gate an always-running downstream job
246
+
Given Plan rejects an event or produces invalid Settings
247
+
When a downstream job with an always condition is evaluated
248
+
Then the job does not run
249
+
And it does not evaluate the missing or invalid Settings
250
+
```
251
+
232
252
## Non-functional requirements
233
253
234
254
### NFR1 — Lifecycle mutations MUST be idempotent {#nfr1}
@@ -365,7 +385,7 @@ Scenario: Recover release notes after a missed main-push publication
0 commit comments