@rightkit/release 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +49 -6
- package/adoption-evidence.mjs +650 -0
- package/apple-profile-create.mjs +113 -10
- package/bin/darwin/rightkit-swap +0 -0
- package/binary-license-notices.mjs +161 -0
- package/cargo-license-notices.mjs +111 -0
- package/cli/right-release.mjs +10 -0
- package/local-publish.mjs +133 -19
- package/ownership-dependency-allowlist.json +2 -0
- package/ownership-mandatory-set.json +117 -67
- package/ownership-mandatory-set.mjs +75 -5
- package/package.json +1 -1
- package/pipeline-admission.mjs +375 -0
- package/pipeline-config.mjs +100 -0
- package/pipeline-generators.json +4 -0
- package/pipeline-generators.mjs +137 -0
- package/pipeline-scan.mjs +285 -0
- package/pipeline-tools.mjs +171 -0
- package/production-mode.mjs +42 -0
- package/publication-gate.mjs +83 -32
- package/publish-cargo.mjs +11 -6
- package/publish-swift.mjs +12 -3
- package/qa-control-scan.mjs +4 -0
- package/release-config.mjs +330 -0
- package/release-switch-scan.mjs +44 -5
- package/release.mjs +14 -4
- package/rightkit-sync.mjs +8 -0
- package/rightkit-versions.json +132 -88
- package/runtime-budget-crates.mjs +14 -0
- package/runtime-budgets.mjs +128 -31
- package/stage-sidecar.mjs +47 -8
- package/swap-helper-bundle.mjs +7 -3
- package/bin/darwin/rightkit-swap.sign.json +0 -6
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"schema": 1,
|
|
3
3
|
"source": {
|
|
4
4
|
"table": "private-audits/TABLE1-MANDATORY.md:56-78 (M1-M23 requirement catalog)",
|
|
5
|
-
"versions": "
|
|
6
|
-
"note": "min =
|
|
5
|
+
"versions": "registry readback 2026-10-19 after the mandatory-set publish (#790): min = registryMax = the live version",
|
|
6
|
+
"note": "min = registryMax = the required version: the live registry version of the published mandatory set (#790). Raise both with each mandatory-set publish."
|
|
7
7
|
},
|
|
8
8
|
"defaultProfile": "desktop",
|
|
9
9
|
"defaultApps": [
|
|
@@ -37,18 +37,20 @@
|
|
|
37
37
|
{
|
|
38
38
|
"name": "rightkit-tauri-shell",
|
|
39
39
|
"ecosystem": "cargo",
|
|
40
|
-
"min": "0.
|
|
40
|
+
"min": "0.4.0",
|
|
41
|
+
"registryMax": "0.4.0"
|
|
41
42
|
},
|
|
42
43
|
{
|
|
43
44
|
"name": "rightkit-device",
|
|
44
45
|
"ecosystem": "cargo",
|
|
45
|
-
"min": "0.
|
|
46
|
+
"min": "0.3.0",
|
|
47
|
+
"registryMax": "0.3.0"
|
|
46
48
|
},
|
|
47
49
|
{
|
|
48
50
|
"name": "@rightkit/tauri",
|
|
49
51
|
"ecosystem": "npm",
|
|
50
|
-
"min": "0.2.
|
|
51
|
-
"registryMax": "0.2.
|
|
52
|
+
"min": "0.2.3",
|
|
53
|
+
"registryMax": "0.2.3"
|
|
52
54
|
}
|
|
53
55
|
]
|
|
54
56
|
},
|
|
@@ -60,19 +62,20 @@
|
|
|
60
62
|
{
|
|
61
63
|
"name": "@rightkit/react-shell",
|
|
62
64
|
"ecosystem": "npm",
|
|
63
|
-
"min": "0.
|
|
65
|
+
"min": "0.7.1",
|
|
66
|
+
"registryMax": "0.7.1"
|
|
64
67
|
},
|
|
65
68
|
{
|
|
66
69
|
"name": "@rightkit/platform-ui",
|
|
67
70
|
"ecosystem": "npm",
|
|
68
|
-
"min": "0.
|
|
69
|
-
"registryMax": "0.
|
|
71
|
+
"min": "0.4.0",
|
|
72
|
+
"registryMax": "0.4.0"
|
|
70
73
|
},
|
|
71
74
|
{
|
|
72
75
|
"name": "@rightkit/theme",
|
|
73
76
|
"ecosystem": "npm",
|
|
74
|
-
"min": "0.
|
|
75
|
-
"registryMax": "0.
|
|
77
|
+
"min": "0.3.1",
|
|
78
|
+
"registryMax": "0.3.1"
|
|
76
79
|
}
|
|
77
80
|
]
|
|
78
81
|
},
|
|
@@ -84,12 +87,14 @@
|
|
|
84
87
|
{
|
|
85
88
|
"name": "rightkit-job-queue",
|
|
86
89
|
"ecosystem": "cargo",
|
|
87
|
-
"min": "0.
|
|
90
|
+
"min": "0.4.0",
|
|
91
|
+
"registryMax": "0.4.0"
|
|
88
92
|
},
|
|
89
93
|
{
|
|
90
94
|
"name": "rightkit-child-process",
|
|
91
95
|
"ecosystem": "cargo",
|
|
92
|
-
"min": "0.
|
|
96
|
+
"min": "0.5.2",
|
|
97
|
+
"registryMax": "0.5.2"
|
|
93
98
|
}
|
|
94
99
|
]
|
|
95
100
|
},
|
|
@@ -101,12 +106,14 @@
|
|
|
101
106
|
{
|
|
102
107
|
"name": "rightkit-job-queue",
|
|
103
108
|
"ecosystem": "cargo",
|
|
104
|
-
"min": "0.
|
|
109
|
+
"min": "0.4.0",
|
|
110
|
+
"registryMax": "0.4.0"
|
|
105
111
|
},
|
|
106
112
|
{
|
|
107
113
|
"name": "rightkit-sidecar",
|
|
108
114
|
"ecosystem": "cargo",
|
|
109
|
-
"min": "0.
|
|
115
|
+
"min": "0.3.0",
|
|
116
|
+
"registryMax": "0.3.0"
|
|
110
117
|
}
|
|
111
118
|
]
|
|
112
119
|
},
|
|
@@ -118,7 +125,8 @@
|
|
|
118
125
|
{
|
|
119
126
|
"name": "rightkit-child-process",
|
|
120
127
|
"ecosystem": "cargo",
|
|
121
|
-
"min": "0.
|
|
128
|
+
"min": "0.5.2",
|
|
129
|
+
"registryMax": "0.5.2"
|
|
122
130
|
}
|
|
123
131
|
]
|
|
124
132
|
},
|
|
@@ -130,7 +138,8 @@
|
|
|
130
138
|
{
|
|
131
139
|
"name": "rightkit-daemon",
|
|
132
140
|
"ecosystem": "cargo",
|
|
133
|
-
"min": "0.
|
|
141
|
+
"min": "0.3.0",
|
|
142
|
+
"registryMax": "0.3.0"
|
|
134
143
|
}
|
|
135
144
|
]
|
|
136
145
|
},
|
|
@@ -142,7 +151,8 @@
|
|
|
142
151
|
{
|
|
143
152
|
"name": "rightkit-daemon",
|
|
144
153
|
"ecosystem": "cargo",
|
|
145
|
-
"min": "0.
|
|
154
|
+
"min": "0.3.0",
|
|
155
|
+
"registryMax": "0.3.0"
|
|
146
156
|
}
|
|
147
157
|
]
|
|
148
158
|
},
|
|
@@ -154,8 +164,8 @@
|
|
|
154
164
|
{
|
|
155
165
|
"name": "rightkit-fs",
|
|
156
166
|
"ecosystem": "cargo",
|
|
157
|
-
"min": "0.4.
|
|
158
|
-
"registryMax": "0.4.
|
|
167
|
+
"min": "0.4.4",
|
|
168
|
+
"registryMax": "0.4.4"
|
|
159
169
|
}
|
|
160
170
|
]
|
|
161
171
|
},
|
|
@@ -167,8 +177,8 @@
|
|
|
167
177
|
{
|
|
168
178
|
"name": "rightkit-db",
|
|
169
179
|
"ecosystem": "cargo",
|
|
170
|
-
"min": "0.
|
|
171
|
-
"registryMax": "0.
|
|
180
|
+
"min": "0.5.0",
|
|
181
|
+
"registryMax": "0.5.0"
|
|
172
182
|
}
|
|
173
183
|
]
|
|
174
184
|
},
|
|
@@ -180,13 +190,14 @@
|
|
|
180
190
|
{
|
|
181
191
|
"name": "rightkit-app-settings",
|
|
182
192
|
"ecosystem": "cargo",
|
|
183
|
-
"min": "0.2.
|
|
193
|
+
"min": "0.2.4",
|
|
194
|
+
"registryMax": "0.2.4"
|
|
184
195
|
},
|
|
185
196
|
{
|
|
186
197
|
"name": "@rightkit/settings-ui",
|
|
187
198
|
"ecosystem": "npm",
|
|
188
|
-
"min": "0.
|
|
189
|
-
"registryMax": "0.
|
|
199
|
+
"min": "0.6.1",
|
|
200
|
+
"registryMax": "0.6.1"
|
|
190
201
|
}
|
|
191
202
|
]
|
|
192
203
|
},
|
|
@@ -198,7 +209,8 @@
|
|
|
198
209
|
{
|
|
199
210
|
"name": "rightkit-credentials",
|
|
200
211
|
"ecosystem": "cargo",
|
|
201
|
-
"min": "0.
|
|
212
|
+
"min": "0.3.0",
|
|
213
|
+
"registryMax": "0.3.0"
|
|
202
214
|
}
|
|
203
215
|
]
|
|
204
216
|
},
|
|
@@ -210,19 +222,20 @@
|
|
|
210
222
|
{
|
|
211
223
|
"name": "rightkit-license",
|
|
212
224
|
"ecosystem": "cargo",
|
|
213
|
-
"min": "0.2.
|
|
214
|
-
"registryMax": "0.2.
|
|
225
|
+
"min": "0.2.3",
|
|
226
|
+
"registryMax": "0.2.3"
|
|
215
227
|
},
|
|
216
228
|
{
|
|
217
229
|
"name": "rightkit-device",
|
|
218
230
|
"ecosystem": "cargo",
|
|
219
|
-
"min": "0.
|
|
231
|
+
"min": "0.3.0",
|
|
232
|
+
"registryMax": "0.3.0"
|
|
220
233
|
},
|
|
221
234
|
{
|
|
222
235
|
"name": "@rightkit/license",
|
|
223
236
|
"ecosystem": "npm",
|
|
224
|
-
"min": "0.2.
|
|
225
|
-
"registryMax": "0.2.
|
|
237
|
+
"min": "0.2.1",
|
|
238
|
+
"registryMax": "0.2.1"
|
|
226
239
|
}
|
|
227
240
|
]
|
|
228
241
|
},
|
|
@@ -234,8 +247,8 @@
|
|
|
234
247
|
{
|
|
235
248
|
"name": "rightkit-license",
|
|
236
249
|
"ecosystem": "cargo",
|
|
237
|
-
"min": "0.2.
|
|
238
|
-
"registryMax": "0.2.
|
|
250
|
+
"min": "0.2.3",
|
|
251
|
+
"registryMax": "0.2.3"
|
|
239
252
|
}
|
|
240
253
|
]
|
|
241
254
|
},
|
|
@@ -247,20 +260,20 @@
|
|
|
247
260
|
{
|
|
248
261
|
"name": "@rightkit/legal",
|
|
249
262
|
"ecosystem": "npm",
|
|
250
|
-
"min": "0.
|
|
251
|
-
"registryMax": "0.
|
|
263
|
+
"min": "0.6.1",
|
|
264
|
+
"registryMax": "0.6.1"
|
|
252
265
|
},
|
|
253
266
|
{
|
|
254
267
|
"name": "@rightkit/legal-ui",
|
|
255
268
|
"ecosystem": "npm",
|
|
256
|
-
"min": "0.
|
|
257
|
-
"registryMax": "0.
|
|
269
|
+
"min": "0.4.0",
|
|
270
|
+
"registryMax": "0.4.0"
|
|
258
271
|
},
|
|
259
272
|
{
|
|
260
273
|
"name": "@rightkit/onboarding",
|
|
261
274
|
"ecosystem": "npm",
|
|
262
|
-
"min": "0.
|
|
263
|
-
"registryMax": "0.
|
|
275
|
+
"min": "0.6.1",
|
|
276
|
+
"registryMax": "0.6.1"
|
|
264
277
|
}
|
|
265
278
|
]
|
|
266
279
|
},
|
|
@@ -272,14 +285,14 @@
|
|
|
272
285
|
{
|
|
273
286
|
"name": "rightkit-logs",
|
|
274
287
|
"ecosystem": "cargo",
|
|
275
|
-
"min": "0.3.
|
|
276
|
-
"registryMax": "0.3.
|
|
288
|
+
"min": "0.3.3",
|
|
289
|
+
"registryMax": "0.3.3"
|
|
277
290
|
},
|
|
278
291
|
{
|
|
279
292
|
"name": "@rightkit/logs",
|
|
280
293
|
"ecosystem": "npm",
|
|
281
|
-
"min": "0.1.
|
|
282
|
-
"registryMax": "0.1.
|
|
294
|
+
"min": "0.1.5",
|
|
295
|
+
"registryMax": "0.1.5"
|
|
283
296
|
}
|
|
284
297
|
]
|
|
285
298
|
},
|
|
@@ -291,8 +304,8 @@
|
|
|
291
304
|
{
|
|
292
305
|
"name": "rightkit-crash",
|
|
293
306
|
"ecosystem": "cargo",
|
|
294
|
-
"min": "0.
|
|
295
|
-
"registryMax": "0.3.
|
|
307
|
+
"min": "0.3.3",
|
|
308
|
+
"registryMax": "0.3.3"
|
|
296
309
|
}
|
|
297
310
|
]
|
|
298
311
|
},
|
|
@@ -304,8 +317,8 @@
|
|
|
304
317
|
{
|
|
305
318
|
"name": "rightkit-http",
|
|
306
319
|
"ecosystem": "cargo",
|
|
307
|
-
"min": "0.3.
|
|
308
|
-
"registryMax": "0.3.
|
|
320
|
+
"min": "0.3.6",
|
|
321
|
+
"registryMax": "0.3.6"
|
|
309
322
|
}
|
|
310
323
|
]
|
|
311
324
|
},
|
|
@@ -317,7 +330,8 @@
|
|
|
317
330
|
{
|
|
318
331
|
"name": "@rightkit/app-update",
|
|
319
332
|
"ecosystem": "npm",
|
|
320
|
-
"min": "0.
|
|
333
|
+
"min": "0.4.0",
|
|
334
|
+
"registryMax": "0.4.0"
|
|
321
335
|
}
|
|
322
336
|
]
|
|
323
337
|
},
|
|
@@ -329,8 +343,8 @@
|
|
|
329
343
|
{
|
|
330
344
|
"name": "@rightkit/release",
|
|
331
345
|
"ecosystem": "npm",
|
|
332
|
-
"min": "0.
|
|
333
|
-
"registryMax": "0.
|
|
346
|
+
"min": "0.4.0",
|
|
347
|
+
"registryMax": "0.4.0",
|
|
334
348
|
"allowDev": true
|
|
335
349
|
}
|
|
336
350
|
]
|
|
@@ -343,29 +357,22 @@
|
|
|
343
357
|
{
|
|
344
358
|
"name": "rightkit-qa",
|
|
345
359
|
"ecosystem": "cargo",
|
|
346
|
-
"min": "0.
|
|
347
|
-
"registryMax": "0.
|
|
348
|
-
"allowDev": true
|
|
349
|
-
},
|
|
350
|
-
{
|
|
351
|
-
"name": "rightkit-qa-driver",
|
|
352
|
-
"ecosystem": "cargo",
|
|
353
|
-
"min": "0.3.0",
|
|
354
|
-
"note": "deprecated shim; the QA owner is rightkit-qa with the `control` feature (Ember #280)",
|
|
360
|
+
"min": "0.7.0",
|
|
361
|
+
"registryMax": "0.7.0",
|
|
355
362
|
"allowDev": true
|
|
356
363
|
},
|
|
357
364
|
{
|
|
358
365
|
"name": "@rightkit/qa",
|
|
359
366
|
"ecosystem": "npm",
|
|
360
|
-
"min": "0.
|
|
361
|
-
"registryMax": "0.
|
|
367
|
+
"min": "0.5.1",
|
|
368
|
+
"registryMax": "0.5.1",
|
|
362
369
|
"allowDev": true
|
|
363
370
|
},
|
|
364
371
|
{
|
|
365
372
|
"name": "@rightkit/qa-chrome",
|
|
366
373
|
"ecosystem": "npm",
|
|
367
|
-
"min": "0.1.
|
|
368
|
-
"registryMax": "0.1.
|
|
374
|
+
"min": "0.1.8",
|
|
375
|
+
"registryMax": "0.1.8",
|
|
369
376
|
"allowDev": true
|
|
370
377
|
}
|
|
371
378
|
]
|
|
@@ -378,8 +385,8 @@
|
|
|
378
385
|
{
|
|
379
386
|
"name": "rightkit-agent-tools",
|
|
380
387
|
"ecosystem": "cargo",
|
|
381
|
-
"min": "0.
|
|
382
|
-
"registryMax": "0.
|
|
388
|
+
"min": "0.2.0",
|
|
389
|
+
"registryMax": "0.2.0"
|
|
383
390
|
}
|
|
384
391
|
]
|
|
385
392
|
}
|
|
@@ -390,16 +397,59 @@
|
|
|
390
397
|
"name": "Test mode",
|
|
391
398
|
"profile": "desktop",
|
|
392
399
|
"owners": [],
|
|
393
|
-
"ownerPending": "No selected owner (D4 unratified); never fails."
|
|
400
|
+
"ownerPending": "No selected owner (D4 unratified); never fails.",
|
|
401
|
+
"pendingOwners": [
|
|
402
|
+
{
|
|
403
|
+
"name": "rightkit-fs",
|
|
404
|
+
"ecosystem": "cargo",
|
|
405
|
+
"min": "0.4.4"
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
"name": "rightkit-daemon",
|
|
409
|
+
"ecosystem": "cargo",
|
|
410
|
+
"min": "0.3.0"
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"name": "rightkit-qa",
|
|
414
|
+
"ecosystem": "cargo",
|
|
415
|
+
"min": "0.7.0",
|
|
416
|
+
"allowDev": true
|
|
417
|
+
}
|
|
418
|
+
]
|
|
394
419
|
},
|
|
395
420
|
{
|
|
396
421
|
"id": "M23",
|
|
397
422
|
"name": "Release-time switches",
|
|
398
423
|
"profile": "desktop",
|
|
399
424
|
"owners": [],
|
|
400
|
-
"ownerPending": "No selected owner (D4 unratified); never fails."
|
|
425
|
+
"ownerPending": "No selected owner (D4 unratified); never fails.",
|
|
426
|
+
"pendingOwners": [
|
|
427
|
+
{
|
|
428
|
+
"name": "@rightkit/release",
|
|
429
|
+
"ecosystem": "npm",
|
|
430
|
+
"min": "0.4.0",
|
|
431
|
+
"allowDev": true
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
"name": "rightkit-daemon",
|
|
435
|
+
"ecosystem": "cargo",
|
|
436
|
+
"min": "0.3.0"
|
|
437
|
+
}
|
|
438
|
+
]
|
|
401
439
|
}
|
|
402
440
|
],
|
|
441
|
+
"applicabilityRecords": {
|
|
442
|
+
"M22": {
|
|
443
|
+
"name": "Agent surface",
|
|
444
|
+
"roles": [
|
|
445
|
+
"client",
|
|
446
|
+
"host",
|
|
447
|
+
"both",
|
|
448
|
+
"absent"
|
|
449
|
+
],
|
|
450
|
+
"note": "Declared in <app>/rightkit-mandatory.json as M22: { role, entrypoints }. Report-only: a record never removes or adds a violation; only notApplicable (with a reason) removes a row."
|
|
451
|
+
}
|
|
452
|
+
},
|
|
403
453
|
"appAmendments": {
|
|
404
454
|
"ember": {
|
|
405
455
|
"issue": "Orthic-Labs/rightkit#280",
|
|
@@ -12,7 +12,14 @@
|
|
|
12
12
|
// [--amendment v2.1] [--enforce] [--json]
|
|
13
13
|
//
|
|
14
14
|
// App-side declaration (optional): <app>/rightkit-mandatory.json
|
|
15
|
-
// { "profile": "desktop", "notApplicable": { "M16": "reason text" }
|
|
15
|
+
// { "profile": "desktop", "notApplicable": { "M16": "reason text" },
|
|
16
|
+
// "M22": { "role": "client|host|both|absent", "entrypoints": ["src-tauri/src/agent.rs#register_tools"] } }
|
|
17
|
+
//
|
|
18
|
+
// PK17.scanner (report only, never enforcement): rows M21 and M23 stay `ownerPending` and never fail, but each lists its
|
|
19
|
+
// `pendingOwners` (M21: rightkit-fs, rightkit-daemon, rightkit-qa; M23: @rightkit/release, rightkit-daemon) and the report shows
|
|
20
|
+
// how each app's declarations measure up (`pending[].candidateOwners`, `enforced: false`). Moving those owners into `rows` and
|
|
21
|
+
// raising minimums is the separate activation step (PK17.activation). The M22 applicability record (PK15-2) is validated and
|
|
22
|
+
// reported under `applicability.M22`; an invalid or contradictory record is a `problem`, which never changes the exit code.
|
|
16
23
|
import { existsSync, readFileSync, readdirSync, realpathSync, statSync } from "node:fs";
|
|
17
24
|
import path from "node:path";
|
|
18
25
|
import { fileURLToPath } from "node:url";
|
|
@@ -231,9 +238,50 @@ function judge(req, facts) {
|
|
|
231
238
|
return { ...base, status: "ok", declared: declaredAt, evidence: [] };
|
|
232
239
|
}
|
|
233
240
|
|
|
241
|
+
// An entrypoint is `<relative file>`, optionally `#<symbol>` or `::<symbol>`; a bare token with no path separator or extension
|
|
242
|
+
// is a symbol or command name and is recorded unverified. A file part must stay inside the app root and exist.
|
|
243
|
+
const entrypointFile = (entry) => entry.split(/#|::/)[0];
|
|
244
|
+
const looksLikePath = (text) => /[\\/]/.test(text) || /\.[A-Za-z0-9]+$/.test(text);
|
|
245
|
+
|
|
246
|
+
/** Validate one applicability record (`M22: { role, entrypoints }`); report-only, never throws. */
|
|
247
|
+
export function validateApplicabilityRecord(id, raw, { spec, root }) {
|
|
248
|
+
const result = { row: id, status: "unrecorded", role: null, entrypoints: [], unverifiedEntrypoints: 0, problems: [] };
|
|
249
|
+
if (raw === undefined) return result;
|
|
250
|
+
const bad = (reason) => result.problems.push(`${id}: ${reason}`);
|
|
251
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) { bad("applicability record must be an object { role, entrypoints }"); result.status = "invalid"; return result; }
|
|
252
|
+
const extra = Object.keys(raw).filter((key) => key !== "role" && key !== "entrypoints");
|
|
253
|
+
if (extra.length) bad(`unknown applicability record key(s): ${extra.join(", ")}`);
|
|
254
|
+
const roles = spec?.roles ?? [];
|
|
255
|
+
if (!roles.includes(raw.role)) bad(`role must be one of ${roles.join("|")}, got ${JSON.stringify(raw.role)}`);
|
|
256
|
+
else result.role = raw.role;
|
|
257
|
+
if (!Array.isArray(raw.entrypoints)) bad("entrypoints must be an array");
|
|
258
|
+
else {
|
|
259
|
+
const seen = new Set();
|
|
260
|
+
for (const entry of raw.entrypoints) {
|
|
261
|
+
if (typeof entry !== "string" || !entry.trim()) { bad("every entrypoint must be a non-empty string"); continue; }
|
|
262
|
+
const text = entry.trim();
|
|
263
|
+
if (seen.has(text)) { bad(`entrypoint ${JSON.stringify(text)} is listed twice`); continue; }
|
|
264
|
+
seen.add(text);
|
|
265
|
+
result.entrypoints.push(text);
|
|
266
|
+
const file = entrypointFile(text);
|
|
267
|
+
if (!file) { bad(`entrypoint ${JSON.stringify(text)} names no file or symbol`); continue; }
|
|
268
|
+
if (!looksLikePath(file)) { result.unverifiedEntrypoints += 1; continue; }
|
|
269
|
+
const normalized = file.replace(/\\/g, "/");
|
|
270
|
+
if (path.isAbsolute(file) || /^[A-Za-z]:/.test(file) || normalized.split("/").includes("..")) { bad(`entrypoint ${JSON.stringify(text)} must be a relative path inside the app`); continue; }
|
|
271
|
+
let isFile = false;
|
|
272
|
+
try { isFile = statSync(path.join(root, normalized)).isFile(); } catch { /* missing */ }
|
|
273
|
+
if (!isFile) bad(`entrypoint ${JSON.stringify(text)}: file not found under the app root`);
|
|
274
|
+
}
|
|
275
|
+
if (result.role === "absent" && raw.entrypoints.length) bad("role absent must list no entrypoints");
|
|
276
|
+
if (result.role && result.role !== "absent" && !raw.entrypoints.length) bad(`role ${result.role} needs at least one real entrypoint`);
|
|
277
|
+
}
|
|
278
|
+
result.status = result.problems.length ? "invalid" : "recorded";
|
|
279
|
+
return result;
|
|
280
|
+
}
|
|
281
|
+
|
|
234
282
|
export function loadAppDeclaration(root, data) {
|
|
235
283
|
const file = path.join(root, data.appDeclarationFile);
|
|
236
|
-
if (!existsSync(file)) return { profile: data.defaultProfile, notApplicable: {}, problems: [] };
|
|
284
|
+
if (!existsSync(file)) return { profile: data.defaultProfile, notApplicable: {}, records: {}, problems: [] };
|
|
237
285
|
const problems = [];
|
|
238
286
|
let doc = {};
|
|
239
287
|
try { doc = JSON.parse(readFileSync(file, "utf8")); } catch (error) { problems.push(`${data.appDeclarationFile} unparseable: ${error.message}`); }
|
|
@@ -242,7 +290,9 @@ export function loadAppDeclaration(root, data) {
|
|
|
242
290
|
if (typeof reason === "string" && reason.trim().length >= 10) notApplicable[id] = reason.trim();
|
|
243
291
|
else problems.push(`${id}: N/A declaration needs a reason (>= 10 chars); ignored`);
|
|
244
292
|
}
|
|
245
|
-
|
|
293
|
+
const records = {};
|
|
294
|
+
for (const id of Object.keys(data.applicabilityRecords ?? {})) if (doc && typeof doc === "object" && Object.hasOwn(doc, id)) records[id] = doc[id];
|
|
295
|
+
return { profile: doc.profile ?? data.defaultProfile, notApplicable, records, problems };
|
|
246
296
|
}
|
|
247
297
|
|
|
248
298
|
export function checkApp(root, { data = loadData(), profile, amendments = [] } = {}) {
|
|
@@ -263,11 +313,29 @@ export function checkApp(root, { data = loadData(), profile, amendments = [] } =
|
|
|
263
313
|
}
|
|
264
314
|
const notApplicable = Object.entries(declaration.notApplicable).map(([id, reason]) => ({ row: id, reason }));
|
|
265
315
|
const applicable = rows.filter((r) => !(r.id in declaration.notApplicable));
|
|
266
|
-
const pending = data.pendingRows.filter((r) => r.profile === active).map((r) => ({ row: r.id, name: r.name, status: "owner-pending", note: r.ownerPending }));
|
|
267
316
|
const manifests = findManifests(root).map((f) => readManifest(f, root));
|
|
268
317
|
resolveWorkspaceInheritance(manifests);
|
|
269
318
|
for (const m of manifests) if (m.error) problems.push(`${m.rel}: ${m.error}`);
|
|
270
319
|
const facts = manifests.flatMap((m) => m.facts);
|
|
320
|
+
// Pending rows never fail. Their `pendingOwners` are judged like any owner and listed as `candidateOwners` (`enforced: false`)
|
|
321
|
+
// so the report shows what activation would find; the result is never counted in `violations`.
|
|
322
|
+
const pending = data.pendingRows.filter((r) => r.profile === active).map((r) => ({
|
|
323
|
+
row: r.id, name: r.name, status: "owner-pending", note: r.ownerPending,
|
|
324
|
+
candidateOwners: r.id in declaration.notApplicable ? [] : (r.pendingOwners ?? []).map((o) => {
|
|
325
|
+
const judged = judge({ ...o, rows: [r.id] }, facts);
|
|
326
|
+
return { owner: judged.owner, ecosystem: judged.ecosystem, rows: judged.rows, required: judged.required, declared: judged.declared, declarationStatus: judged.status, evidence: judged.evidence, enforced: false };
|
|
327
|
+
}),
|
|
328
|
+
}));
|
|
329
|
+
// Applicability records (PK15-2): validated and reported, never enforced.
|
|
330
|
+
const applicability = {};
|
|
331
|
+
for (const [id, spec] of Object.entries(data.applicabilityRecords ?? {})) {
|
|
332
|
+
const record = validateApplicabilityRecord(id, declaration.records[id], { spec, root });
|
|
333
|
+
applicability[id] = record;
|
|
334
|
+
problems.push(...record.problems);
|
|
335
|
+
const declaredNa = id in declaration.notApplicable;
|
|
336
|
+
if (record.role === "absent" && !declaredNa) problems.push(`${id}: applicability role is absent but notApplicable.${id} is not declared; the ${id} row still applies until the app declares it not applicable with a reason`);
|
|
337
|
+
if (record.role && record.role !== "absent" && declaredNa) problems.push(`${id}: notApplicable.${id} is declared but the applicability record says role ${record.role}`);
|
|
338
|
+
}
|
|
271
339
|
const owners = [...requirements(applicable).values()].map((req) => { const result = judge(req, facts); return { ...result, declarationStatus: result.status }; });
|
|
272
340
|
// A profile that is unknown, marked unratified, or has no rows checks nothing; an app may not select it, so it fails rather than passing empty.
|
|
273
341
|
const profileStatus = !data.profiles[active] ? "unknown-profile" : (data.profiles[active].ratified === false || !data.rows.some((r) => r.profile === active)) ? "unratified" : null;
|
|
@@ -276,7 +344,7 @@ export function checkApp(root, { data = loadData(), profile, amendments = [] } =
|
|
|
276
344
|
owners.push({ owner: `profile:${active}`, ecosystem: "profile", rows: [], required: "ratified profile", status: profileStatus, declared: null, evidence: ["an app may not select a profile that is not ratified"] });
|
|
277
345
|
}
|
|
278
346
|
const violations = owners.filter((o) => o.status !== "ok").length;
|
|
279
|
-
return { app: name, root, scanned: true, profile: active, manifests: manifests.length, owners, pending, notApplicable, problems, violations };
|
|
347
|
+
return { app: name, root, scanned: true, profile: active, manifests: manifests.length, owners, pending, applicability, notApplicable, problems, violations };
|
|
280
348
|
}
|
|
281
349
|
|
|
282
350
|
export function checkApps(roots, options = {}) {
|
|
@@ -292,6 +360,8 @@ export function renderText(report) {
|
|
|
292
360
|
out.push("", `${app.app} [${app.profile}] ${app.scanned ? `ok=${count("ok")} missing=${count("missing")} below-required=${count("below-required")} not-on-registry=${count("not-on-registry")}` : "UNSCANNED"}`
|
|
293
361
|
+ (app.pending.length ? ` pending=${app.pending.map((p) => p.row).join(",")}` : "") + (app.notApplicable.length ? ` n/a=${app.notApplicable.map((n) => n.row).join(",")}` : ""));
|
|
294
362
|
for (const o of app.owners.filter((x) => x.status !== "ok")) out.push(` ${o.status.padEnd(15)} ${o.owner} (${o.rows.join(",")}) requires ${o.required}${o.declared ? `, declared ${o.declared}` : ""}${o.evidence.length ? ` — ${o.evidence.join("; ")}` : ""}`);
|
|
363
|
+
for (const p of app.pending) for (const c of p.candidateOwners ?? []) if (c.declarationStatus !== "ok") out.push(` not-enforced ${p.row} ${c.declarationStatus} ${c.owner} requires ${c.required}${c.declared ? `, declared ${c.declared}` : ""} (owner-pending: report only)`);
|
|
364
|
+
for (const record of Object.values(app.applicability ?? {})) if (record.status !== "unrecorded") out.push(` applicability ${record.row} ${record.status}${record.role ? ` role=${record.role}` : ""} entrypoints=${record.entrypoints.length}${record.unverifiedEntrypoints ? ` (${record.unverifiedEntrypoints} unverified symbol)` : ""}`);
|
|
295
365
|
for (const n of app.notApplicable) out.push(` n/a ${n.row}: ${n.reason}`);
|
|
296
366
|
for (const p of app.problems) out.push(` problem ${p}`);
|
|
297
367
|
}
|
package/package.json
CHANGED