pg-embed-setup-unpriv 0.5.2

Initializes postgresql_embedded clusters with platform-appropriate setup
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
# Validate Windows and macOS support via a CI matrix and cargo binstall

This ExecPlan (execution plan) is a living document. The sections `Constraints`,
`Tolerances`, `Risks`, `Progress`, `Surprises & discoveries`, `Decision log`,
and `Outcomes & retrospective` must be kept up to date as work proceeds. Each
revision must remain self-contained.

Status: COMPLETE

No `PLANS.md` file exists in the repository.

## Purpose / big picture

Today `pg-embed-setup-unpriv` is built, tested, and packaged for Linux only.
Continuous Integration (CI) runs solely on `ubuntu-latest`, and the release
workflow publishes `cargo binstall` archives for `x86_64-unknown-linux-gnu` and
`aarch64-unknown-linux-gnu`. The library already contains substantial
platform-conditional code — the privilege-drop path and the `atexit` shutdown
hook are already gated off non-Unix targets — and the roadmap appendix already
states the intended behaviour on macOS and Windows. But nothing in CI proves
that the crate even compiles on those platforms, let alone that its
unprivileged in-process path works, that shared clusters are cleaned up
correctly, or that `cargo binstall` can install the published binaries there.

After this change a contributor can observe the following:

1. A pull request runs CI jobs on macOS and Windows runners (in addition to the
   existing Linux jobs). The macOS and Windows jobs build the crate and run the
   unprivileged test suite to green. They run tests only: they do not run the
   Linux-only root/privilege-drop path, coverage upload, or the privileged
   worker tests.
2. Shared `TestCluster` fixtures do not leak a PostgreSQL postmaster on macOS or
   Windows, even when a test deliberately leaks the guard with
   `std::mem::forget` (the pattern the shutdown hook exists to serve). This is
   proven by an orphan-detection test that runs in the cross-platform matrix.
3. `cargo binstall pg-embed-setup-unpriv` succeeds on macOS (Apple Silicon and
   Intel) and on Windows (x86-64), pulling a correctly named archive whose
   internal layout matches the `bin-dir` template. This is proven by a CI job
   that performs a real (not dry-run) install into a scratch directory and runs
   the installed binary's `--version` on every supported runner, plus a
   per-target metadata-resolution audit.
4. The README install matrix, the users' guide, and the roadmap appendix
   describe the supported platforms and their caveats accurately, including the
   hard limitation that no Windows-on-ARM PostgreSQL binaries exist upstream
   and that POSIX file-mode privacy guarantees do not hold on Windows.

The user-visible outcome is simple to state: the same `TestCluster` test code
that passes on Linux also passes on macOS and Windows unprivileged, leaves no
orphaned processes, and the CLI binaries install via `cargo binstall` on all
three operating systems.

## Constraints

These are hard invariants. Violating one requires escalation, not a workaround.

- Preserve all existing public APIs, the command-line interface (CLI), and the
  Linux privilege-drop behaviour. The macOS and Windows work must be additive;
  the privilege-drop path stays Linux/BSD-only and must keep compiling and
  passing on Linux exactly as before.
- The macOS and Windows CI legs run tests only. They must not run `make lint`,
  `make check-fmt`, Markdown lint, coverage generation, or the CodeScene
  coverage upload (those remain Linux-only, single-platform jobs). Linting once
  on Linux is authoritative; duplicating it per-OS is out of scope.
  `upload-codescene-coverage` has no Windows path and must never run there.
- Do not weaken the Clippy gate (`-D warnings`), the lint configuration in
  `Cargo.toml` and `clippy.toml`, or the `RUSTFLAGS="-D warnings"` test
  invocation. New platform-conditional code must satisfy the same lint ceiling.
- Use caret version requirements for any new dependency, per `AGENTS.md`. Do not
  add wildcard or open-ended requirements.
- Prefer reusing the `leynos/shared-actions` composite actions over hand-rolled
  workflow logic, since the user nominated that repository as the reference for
  this work. In particular, prefer `stage-release-artefacts` (which already
  produces a `cargo binstall` archive with Windows path handling and a
  `.sha256` sidecar) and the `rust-toy-app.yml` cross-OS matrix shape over
  bespoke Makefile/zip branching, unless a documented reason makes the action
  unsuitable.
- Any helper script that is genuinely required (after the reuse-first
  evaluation above) must follow the df12 scripting standards: a single-file
  Python program targeting Python 3.13 with a `uv` shebang and inline metadata
  block, using `cyclopts` for the CLI, `cuprum` for external process
  invocation, and `pathlib` for all filesystem work so it runs unchanged on
  POSIX and Windows. Its tests live in `scripts/tests/` mirroring the script
  name and use `pytest` with `cmd-mox`. Prefer not to add such a script if a
  shared action or a small Rust integration test covers the need.
- Pin every third-party GitHub Action by commit SHA, matching the existing
  workflow style. `leynos/shared-actions` references must use a single,
  consistent pin.
- Documentation must use en-GB-oxendict spelling, wrap prose and bullets at 80
  columns, and wrap fenced code at 120 columns. Update the `docs/` knowledge
  base (roadmap, users' guide, design doc) when behaviour changes, per
  `AGENTS.md`.
- All commit gateways (`make check-fmt`, `make lint`, `make test`,
  `make markdownlint`, `make nixie`) must pass on Linux before each commit, as
  enforced today.

## Tolerances (exception triggers)

Adjust as the work proceeds; breaching any of these means stop and escalate
rather than improvise. Note the scope figures below are provisional: they are
re-baselined by Milestone 0's actual cross-compile output, because the precise
blocker set must be observed, not predicted.

- Scope of library portability (Milestone 1): if making the crate compile and
  cleanly cleanup on Windows and macOS requires touching more than 15 source
  files or more than 500 net lines of non-test code, stop and escalate. (Raised
  from an earlier estimate after review found the blocker set differs from the
  first survey; confirm against Milestone 0.)
- Interface: if any public API signature, trait bound, or exported item must
  change (beyond adding platform-conditional `cfg` attributes to existing
  items, or removing a confirmed-dead dependency), stop and escalate.
- Dependencies: if a new runtime dependency beyond reorganizing or removing the
  existing `nix`/`xdg`/`openssl-sys` declarations is required, or if a build
  tool (for example Perl or NASM on the Windows runner) cannot be provisioned
  by the existing `setup-rust` action, stop and escalate.
- Cleanup correctness: if the Windows orphan-detection test cannot be made to
  pass after two documented attempts (whether by a real reaper or by proving no
  Windows path leaks a guard), stop and escalate; do not ship a green
  cross-platform badge over a leaking postmaster.
- PostgreSQL feasibility: if the embedded PostgreSQL backend cannot actually
  start on a Windows or macOS runner after two distinct, documented mitigation
  attempts (for example TCP-vs-socket handling, cache path, or `GITHUB_TOKEN`
  rate-limit fixes), stop and escalate with the failing logs; do not silently
  mark those tests as skipped without recording the decision.
- binstall validation: if a real install-and-run cannot be validated in CI
  after one documented approach plus one alternative, stop and present the
  options.
- Iterations: if any single CI leg still fails after three targeted fixes, stop
  and escalate with the run URL and logs.
- Time: if any single milestone exceeds four hours of active work, stop and
  record progress before continuing.
- Cost: if the added CI minutes per pull request exceed the budget recorded in
  Milestone 2 by more than 50%, stop and reconsider caching/matrix scope.
- Ambiguity: if a materially different interpretation emerges (for example
  whether Windows-on-ARM must be a `binstall` target despite having no
  PostgreSQL binaries, or whether macOS/Windows `binstall` binaries are
  required at all versus library-only support), stop and present options with
  trade-offs.

## Risks

The first survey for this plan misread the tree and named `shutdown_hook` as
the primary compile blocker; it is in fact already gated. The risk register
below has since been re-grounded by Milestone 0 and updated as mitigations were
implemented.

- Risk (mitigated): `src/fs.rs` originally compiled Unix-only
  `cap_std::fs::PermissionsExt`/`Permissions::from_mode(mode)` calls on every
  target. Severity: high. Mitigation implemented: POSIX mode application is now
  `#[cfg(unix)]`; Windows creates directories without POSIX file-mode privacy
  guarantees, which must be documented for users.
- Risk (mitigated): `nix` was declared as an unconditional dependency and does
  not build on Windows. Severity: high. Mitigation implemented: `nix` is now
  under `[target.'cfg(unix)'.dependencies]`; macOS keeps it as a Unix target.
- Risk (mitigated): `tests/settings.rs` originally imported `geteuid`
  unconditionally, so `--all-targets` failed once `nix` became Unix-only.
  Severity: high. Mitigation implemented: root-specific imports and assertions
  are gated to root-capable Unix targets.
- Risk (mitigated): `xdg = "3"` was a dead direct dependency and could block
  Windows builds. Severity: medium. Mitigation implemented: remove the dead
  dependency; the remaining cache path identifiers are local field/function
  names, not crate uses.
- Risk (mitigated): shared `TestCluster` fixtures that leak the guard with
  `std::mem::forget` rely on process-exit cleanup. Severity: high. Mitigation
  implemented: macOS uses the existing POSIX shutdown hook; Windows now assigns
  the PostgreSQL process tree to a kill-on-close Job Object and retains direct
  process-tree termination as a fallback, guarded by PID plus start-time
  identity checks. The orphan-detection test now runs in the cross-platform CI
  matrix.
- Risk: `openssl-sys` was an unconditional dependency with the `vendored`
  feature (`Cargo.toml` line 140 before Milestone 1). Building vendored OpenSSL
  on Windows MSVC requires Perl and NASM, and cross-checking macOS from Linux
  sends Darwin compiler flags to the Linux host compiler. Severity: medium.
  Likelihood: observed. Mitigation: Milestone 1 removes the crate's direct
  vendored `openssl-sys` dependency. The remaining `postgresql_embedded` default
  `native-tls` graph uses platform TLS on Windows and macOS, so `openssl-sys`
  no longer appears in those target checks; Linux continues to use the native
  OpenSSL path validated by the existing Linux gates.
- Risk: `pq-sys` (bundled, behind `diesel-support`) builds libpq from source and
  may fail or be slow on Windows. Severity: medium. Likelihood: medium.
  Mitigation: scope the Windows test job to exclude `diesel-support`; enable it
  later as a deliberate, separately budgeted follow-up; record the outcome.
  Apply the same feature discipline to macOS rather than silently using
  `--all-features` there (which would pull `pq-sys` at ~10x runner billing).
- Risk: the embedded PostgreSQL backend downloads binaries at runtime from the
  theseus release host and may hit `api.github.com` rate limits (the token
  raises but does not partition the limit, so concurrent matrix legs across PRs
  share the budget), or fail on Windows because of Unix-socket assumptions (the
  embedded settings ignore Unix sockets on Windows and use TCP). Severity:
  medium. Likelihood: medium-high. Mitigation: make the theseus download a
  mandatory `actions/cache` keyed on the pinned PostgreSQL version + OS + arch
  (not "where practical"); pass `GITHUB_TOKEN`; add bounded retries around
  cluster start; decide now whether the new legs are required or advisory and
  record it; verify TCP connection on Windows. A red leg must be
  distinguishable between "crate broken" and "download throttled".
- Risk: there are no `aarch64-pc-windows-msvc` PostgreSQL binaries upstream, so
  the embedded cluster cannot run on Windows-on-ARM. Severity: low (scope
  only). Likelihood: high (certain). Mitigation: do not target Windows-on-ARM
  for tests or `binstall`; document the limitation.
- Risk: `--dry-run` resolves and fetches a `binstall` asset but does not extract
  or place the binary, so it cannot catch a wrong *internal* archive path. A
  published archive with the wrong directory or binary name would pass a
  dry-run yet install nothing. Severity: high. Likelihood: medium. Mitigation:
  validate with a real `cargo binstall --install-path <tmp>` (no `--dry-run`)
  followed by executing the installed binary, on each OS.
- Risk: release packaging previously lived in `make release-archive`, which
  assumed POSIX-style extensionless binaries. The Windows runner does not list
  GNU Make as a supported tool, and Windows release binaries require `.exe`
  names inside the archive. Severity: high. Likelihood: medium. Mitigation: use
  one `uv` script as the release archive implementation and let
  `make release-archive` delegate to it for local development; the release and
  pull-request workflows call the same script directly.
- Risk: `macos-latest` is now Apple Silicon (`aarch64-apple-darwin`), so an
  unqualified macOS job no longer produces `x86_64-apple-darwin`, and the Intel
  archive would ship without ever being executed in CI (dry-run resolves but
  does not run it). Severity: low-medium. Likelihood: high. Mitigation: either
  add an Intel-macOS run leg, or document that Intel macOS is build-and-resolve
  validated only, and accept that gap deliberately.

## Progress

- [x] 2026-06-25T13:18:31Z Milestone 0 (prototype, gating): run a *real*
  `cargo check`/build for `x86_64-pc-windows-msvc`, `x86_64-apple-darwin`, and
  `aarch64-apple-darwin` against current HEAD; enumerate every actual compile
  error and re-ground the Risk register from observed output (not prediction).
- [x] 2026-06-25T13:31:00Z Milestone 1 dependency portability: remove the
  direct vendored `openssl-sys` dependency, keep `postgresql_embedded` on its
  default native-TLS backend, move `nix` behind `cfg(unix)`, remove the dead
  direct `xdg` dependency, and re-run the three cross-target checks to reveal
  any remaining source blockers. Evidence:
  `/tmp/check-windows-after-lock-test-gate-windows-mac-support-validation.out`,
  `/tmp/check-darwin-after-test-gates-windows-mac-support-validation.out`, and
  `/tmp/check-darwin-arm-after-test-gates-windows-mac-support-validation.out`.
- [x] 2026-06-25T13:42:00Z Milestone 1 source portability: cfg-split
  POSIX-only filesystem mode application, Unix-only privilege-drop preparation,
  worker discovery, worker subprocess invocation, and Unix-specific test
  helpers so the library, `pg_embedded_setup_unpriv`, and `pg_worker` typecheck
  on `x86_64-pc-windows-msvc`, `x86_64-apple-darwin`, and
  `aarch64-apple-darwin`. Re-ran all three target checks with
  `RUSTFLAGS="-D warnings"`; evidence:
  `/tmp/check-windows-deny-warnings-windows-mac-support-validation.out`,
  `/tmp/check-darwin-deny-warnings-windows-mac-support-validation.out`, and
  `/tmp/check-darwin-arm-deny-warnings-windows-mac-support-validation.out`.
- [x] 2026-06-25T13:46:00Z First Milestone 1 portability commit gates passed
  on Linux: `make check-fmt`, `make lint`, `make test`, `make markdownlint`, and
  `make nixie`. Evidence: `/tmp/fmt-windows-mac-support-validation.out`,
  `/tmp/lint-windows-mac-support-validation.out`,
  `/tmp/test-windows-mac-support-validation.out`,
  `/tmp/mdlint-windows-mac-support-validation.out`, and
  `/tmp/nixie-windows-mac-support-validation.out`. The test gate ran two
  nextest passes: `270` passed with `4` skipped for all targets/all features,
  then `151` passed with `0` skipped for the `dev-worker` feature pass.
- [x] 2026-06-25T13:52:00Z CodeRabbit reviewed commit `dd06cf7` after the
  deterministic gates passed. `coderabbit review --agent` completed with
  `status=review_completed` and `findings=0`, so no portability concerns needed
  clearing before the Windows cleanup milestone.
- [x] 2026-06-25T14:05:00Z Implemented Windows shared-cluster cleanup by
  compiling the process-exit shutdown hook on Windows, using `taskkill /T` for
  graceful and forced process-tree termination, and adding a private Win32
  `OpenProcess`/`GetExitCodeProcess` liveness probe. The public
  `register_shutdown_on_exit` signature remains unchanged; the test-only PID
  helper is now a platform alias. Focused checks pass for
  `x86_64-pc-windows-msvc`, `x86_64-apple-darwin`, and `aarch64-apple-darwin`,
  including `RUSTFLAGS="-D warnings"` variants, with evidence in
  `/tmp/check-windows-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/check-windows-deny-warnings-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/check-darwin-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/check-darwin-deny-warnings-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/check-darwin-arm-shutdown-hook-windows-mac-support-validation.out`, and
  `/tmp/check-darwin-arm-deny-warnings-shutdown-hook-windows-mac-support-validation.out`.
- [x] 2026-06-25T14:06:00Z The orphan-detection lifecycle test now runs by
  default on Unix and Windows targets. Local Linux execution passed with the
  child process leaking the guard, exiting through the atexit hook, and the
  parent observing the postmaster exit. Evidence:
  `/tmp/test-shutdown-hook-lifecycle-windows-mac-support-validation.out`.
- [x] 2026-06-25T14:10:00Z Windows cleanup milestone gates passed after the
  shutdown-hook tests were serialized with the existing cross-process scenario
  guard. Evidence: `/tmp/fmt-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/lint-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/test-shutdown-hook-windows-mac-support-validation.out`,
  `/tmp/mdlint-shutdown-hook-windows-mac-support-validation.out`, and
  `/tmp/nixie-shutdown-hook-windows-mac-support-validation.out`. The test gate
  ran two nextest passes: `275` passed with `3` skipped for all targets/all
  features, then `151` passed with `0` skipped for the `dev-worker` feature
  pass. Final cross-target checks also pass for `x86_64-pc-windows-msvc`,
  `x86_64-apple-darwin`, and `aarch64-apple-darwin`, including
  `RUSTFLAGS="-D warnings"` variants, with evidence in the same
  `/tmp/check-*-shutdown-hook-windows-mac-support-validation.out` logs listed
  above.
- [x] 2026-06-25T14:15:00Z Strengthened the shared test serial guard for the
  upcoming Windows CI leg: non-Unix platforms now use an atomic lock directory
  instead of a no-op process lock, so independent nextest binaries coordinate
  access to the shared `PostgreSQL` data/cache directories. Re-ran
  `x86_64-pc-windows-msvc`, `x86_64-apple-darwin`, and `aarch64-apple-darwin`
  with `RUSTFLAGS="-D warnings"` plus the full Linux gates; evidence remains in
  the shutdown-hook `/tmp/*` gate logs.
- [x] 2026-06-25T14:25:00Z CodeRabbit reviewed commit `fd668fe` after the
  deterministic gates passed. `coderabbit review --agent` completed with
  `status=review_completed` and `findings=0`, so no Windows cleanup concerns
  needed clearing before the CI matrix milestone.
- [x] 2026-06-25T14:31:45Z Implemented the Milestone 2 workflow shape
  locally: added workflow-level cancellation, bumped all
  `leynos/shared-actions` references to verified HEAD
  `7da7c6d89033d13cbb1c64803d108ddca97e69c2`, added a required `macos-latest`/
  `windows-latest` test-only job, pinned `actions/cache` v4.3.0 to
  `0057852bfaa89a56745cba8c7296529d2fc39830`, and configured the cross-platform
  test legs to build both regular binaries, run the CLI `--version` smoke test,
  restore/cache `PG_BINARY_CACHE_DIR`, and run the `cluster-unit-tests` plus
  `async-api` nextest feature set. Local command validation passed for the same
  feature set with `245` tests passed and `1` skipped; evidence:
  `/tmp/build-bins-cross-feature-windows-mac-support-validation.out`,
  `/tmp/test-cross-feature-windows-mac-support-validation.out`, and
  `/tmp/actionlint-ci-matrix-windows-mac-support-validation.out`.
- [x] 2026-06-25T14:43:00Z CI matrix milestone deterministic gates passed
  locally before CodeRabbit review. Evidence:
  `/tmp/actionlint-ci-matrix-final-windows-mac-support-validation.out`,
  `/tmp/fmt-ci-matrix-windows-mac-support-validation.out`,
  `/tmp/lint-ci-matrix-windows-mac-support-validation.out`,
  `/tmp/test-ci-matrix-windows-mac-support-validation.out`,
  `/tmp/mdlint-ci-matrix-windows-mac-support-validation.out`, and
  `/tmp/nixie-ci-matrix-windows-mac-support-validation.out`. The full test gate
  ran two nextest passes: `275` passed with `3` skipped, then `151` passed with
  `0` skipped.
- [x] 2026-06-25T14:53:00Z CodeRabbit reviewed commit `341d330` after the
  deterministic gates passed. `coderabbit review --agent` completed with
  `status=review_completed` and `findings=0`, so the CI matrix milestone had no
  concerns to clear before remote CI observation.
- [x] 2026-06-25T15:03:00Z Remote CI run `28178598283` exposed a macOS
  compile failure in the new `Test (aarch64-apple-darwin)` leg: the
  `cluster-unit-tests,async-api` feature set compiled Linux/BSD root bootstrap
  tests that import `nobody_uid`, but that helper is intentionally not exported
  on macOS. The fix gates `bootstrap_privileges` and the root-specific settings
  tests to the same root-capable Unix target set as the public helper exports,
  and gates a Unix-only `rstest` import in `tests/support/serial.rs` after the
  Windows feature check found it as an unused import. Local evidence:
  `/tmp/check-darwin-ci-feature-root-target-gates-windows-mac-support-validation.out`
  and
  `/tmp/check-windows-ci-feature-root-target-gates-windows-mac-support-validation.out`.
- [x] 2026-06-25T15:14:00Z CodeRabbit reviewed corrective commit `15ff4a1`
  after the cross-target checks and full local gates passed.
  `coderabbit review --agent` completed with `status=review_completed` and
  `findings=0`.
- [x] 2026-06-25T15:31:00Z Remote CI run `28179624023` exposed two
  follow-up items after corrective commit `15ff4a1`: the macOS leg reached
  runtime and failed only because
  `discover_worker_errors_on_non_utf8_path_entry` tries to create a
  deliberately invalid byte sequence that APFS rejects with "Illegal byte
  sequence" before the bootstrap helper is exercised; the Windows leg failed
  earlier while crates.io reset the connection downloading `cap-primitives`, so
  it should be retried after the workflow completes rather than treated as a
  source failure. The macOS fix gates that single fixture-style test away from
  macOS while keeping the PATH-absent worker-discovery test active there. Local
  evidence:
  `/tmp/check-darwin-non-utf8-env-test-windows-mac-support-validation.out`,
  `/tmp/check-windows-non-utf8-env-test-windows-mac-support-validation.out`,
  `/tmp/test-ci-feature-non-utf8-env-test-windows-mac-support-validation.out`,
  `/tmp/check-fmt-non-utf8-env-test-windows-mac-support-validation.out`,
  `/tmp/lint-non-utf8-env-test-windows-mac-support-validation.out`,
  `/tmp/test-non-utf8-env-test-windows-mac-support-validation.out`,
  `/tmp/mdlint-non-utf8-env-test-windows-mac-support-validation.out`, and
  `/tmp/nixie-non-utf8-env-test-windows-mac-support-validation.out`.
- [x] 2026-06-25T17:20:00Z CodeRabbit reviewed corrective commit `52288e4`
  after the deterministic gates passed. The first CLI review attempt hit the
  free allowance rate limit, so the mandated `vsleep $(shuf -i 45-90 -n 1)m`
  backoff was run before retrying. The retry completed with
  `status=review_completed` and `findings=0`.
- [x] 2026-06-25T16:53:37Z Remote CI run `28185956153` exposed two
  deterministic test-portability assumptions after corrective commit `52288e4`:
  the macOS test leg built both binaries and passed the CLI smoke test, then
  failed only because `staged_worker_is_world_executable_and_in_temp_dir`
  assumes the system temp directory is world-executable for the `nobody` user;
  the Windows test leg built both binaries and passed the CLI smoke test, then
  failed because `resolve_cache_dir_respects_env_priority` compared hard-coded
  POSIX-style strings instead of platform path values. Linux root and
  unprivileged jobs were green in the same run. The fix gates the root/nobody
  temp traversal assertion to root-capable Unix targets and makes the cache
  test build expected values through `PathBuf`/`Utf8PathBuf`.
- [x] 2026-06-25T16:56:43Z Local validation for the run `28185956153`
  corrective patch passed before commit. Cross-target checks passed for
  `aarch64-apple-darwin` and `x86_64-pc-windows-msvc` with
  `RUSTFLAGS="-D warnings"` and the CI feature set. Focused tests passed:
  `resolve_cache_dir_respects_env_priority` ran `4` cases, and
  `test_support::worker_env::tests` ran `6` cases. Full commit gates passed:
  `make check-fmt`, `make lint`, `make test`, `make markdownlint`, and
  `make nixie`; the test gate ran `275` tests with `3` skipped and then `151`
  `dev-worker` tests with `0` skipped. Evidence:
  `/tmp/check-darwin-path-worker-env-ci-fix-windows-mac-support-validation.out`,
  `/tmp/check-windows-path-worker-env-ci-fix-windows-mac-support-validation.out`,
  `/tmp/test-cache-config-paths-windows-mac-support-validation.out`,
  `/tmp/test-worker-env-path-gate-windows-mac-support-validation.out`,
  `/tmp/check-fmt-path-worker-env-ci-fix-windows-mac-support-validation.out`,
  `/tmp/lint-path-worker-env-ci-fix-windows-mac-support-validation.out`,
  `/tmp/test-path-worker-env-ci-fix-windows-mac-support-validation.out`,
  `/tmp/mdlint-path-worker-env-ci-fix-windows-mac-support-validation.out`, and
  `/tmp/nixie-path-worker-env-ci-fix-windows-mac-support-validation.out`.
- [x] 2026-06-25T18:40:26Z CodeRabbit reviewed corrective commit `4047e62`
  after deterministic gates passed. Two initial CLI attempts stalled after
  summarization and were stopped by exact process group; the next attempt
  returned the free CLI rate limit, so the mandated `vsleep` backoff ran for
  `89` minutes before retrying. The post-backoff retry completed with
  `status=review_completed` and `findings=0`.
- [x] 2026-06-25T18:55:30Z Remote CI run `28192593707` for commit
  `df8afb5` showed Linux root, Linux unprivileged, and macOS all green. Windows
  built both binaries and passed the CLI smoke test, then failed only in
  `shutdown_hook_lifecycle::postmaster_exits_after_child_process_with_shutdown_hook`:
  the parent observed postmaster PID `2388` still running after the child
  exited and waited `30s`. The runner cleanup also found orphaned `postgres`
  processes (`2388` and `8056`). The fix replaces the Windows shutdown hook's
  `taskkill` shell-out with direct `kernel32` process-tree enumeration and
  termination through `CreateToolhelp32Snapshot`, `OpenProcess`,
  `TerminateProcess`, and `WaitForSingleObject`, without adding a runtime
  dependency.
- [x] 2026-06-25T19:00:27Z Local validation for the direct Windows reaper
  patch passed before commit. Cross-target checks passed for
  `x86_64-pc-windows-msvc` and `aarch64-apple-darwin` with
  `RUSTFLAGS="-D warnings"` and the CI feature set. The focused Linux
  orphan-detection lifecycle test passed. Required gates passed:
  `make check-fmt`, `make lint`, `make test`, `make markdownlint`, and
  `make nixie`; the full test gate ran `275` tests with `3` skipped and then
  `151` `dev-worker` tests with `0` skipped. Evidence:
  `/tmp/check-windows-direct-reaper-after-ffi-fix-windows-mac-support-validation.out`,
  `/tmp/check-darwin-direct-reaper-windows-mac-support-validation.out`,
  `/tmp/test-shutdown-hook-lifecycle-direct-reaper-windows-mac-support-validation.out`,
  `/tmp/check-fmt-direct-reaper-windows-mac-support-validation.out`,
  `/tmp/lint-direct-reaper-windows-mac-support-validation.out`,
  `/tmp/test-direct-reaper-windows-mac-support-validation.out`,
  `/tmp/mdlint-direct-reaper-windows-mac-support-validation.out`, and
  `/tmp/nixie-direct-reaper-windows-mac-support-validation.out`. An additional
  exploratory Windows-target Clippy run no longer reports this patch's
  `platform.rs` FFI calls after the raw-pointer fix, but it still fails on
  older Windows-target lint findings in unrelated modules, so it is not used as
  a commit gate.
- [x] 2026-06-25T19:10:48Z CodeRabbit reviewed corrective commit `ba7285b`
  after deterministic gates passed. The first CLI attempt stalled after the
  summarization phase and was stopped by exact process group; the retry also
  appeared stalled, then flushed a completed structured result after the exact
  process group was stopped. The captured log shows `status=review_completed`
  and `findings=0`, so there are no CodeRabbit concerns to clear before pushing
  the direct Windows reaper fix.
- [x] 2026-06-25T19:29:13Z Remote CI run `28194422551` for commit
  `611e380` proved the direct Win32 reaper still does not satisfy the Windows
  orphan-detection test. Linux root, Linux unprivileged, and macOS all passed.
  Windows built both binaries and passed the CLI smoke test, then failed only in
  `shutdown_hook_lifecycle::postmaster_exits_after_child_process_with_shutdown_hook`:
  the parent observed postmaster PID `2908` still running after the child
  exited and waited `30s`; runner cleanup then terminated orphaned `postgres`
  processes `2908` and `4584`.
- [x] 2026-06-25T19:29:13Z User approved continuing past the original
  two-attempt Windows cleanup tolerance with up to four further approaches.
  Approach 3 is a Windows Job Object failsafe: assign the postmaster process
  tree to a `JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE` job when the shutdown hook is
  registered, so the operating system reaps the tree when the process exits
  even if the `atexit` callback is skipped or cannot complete.
- [x] 2026-06-25T19:38:14Z Implemented Approach 3 locally by splitting the
  Windows shutdown-hook FFI into
  `src/cluster/shutdown_hook/platform/windows.rs` and
  `src/cluster/shutdown_hook/platform/windows/job.rs`, then retaining a
  kill-on-close Job Object in the registered shutdown state. Local target
  checks pass for `x86_64-pc-windows-msvc`, `aarch64-apple-darwin`, and
  `x86_64-apple-darwin` with `RUSTFLAGS="-D warnings"` and the CI feature set.
  The focused Linux shutdown-hook lifecycle test still passes. Evidence:
  `/tmp/check-windows-job-object-after-visibility-windows-mac-support-validation.out`,
  `/tmp/check-darwin-job-object-windows-mac-support-validation.out`,
  `/tmp/check-darwin-intel-job-object-windows-mac-support-validation.out`, and
  `/tmp/test-shutdown-hook-lifecycle-job-object-windows-mac-support-validation.out`.
- [x] 2026-06-25T19:46:38Z Approach 3 deterministic gates passed locally
  before CodeRabbit review, but the CodeRabbit retry returned the free CLI
  allowance rate limit with a reported `18 minutes and 9 seconds` reset. Per
  the user instruction, pause with `vsleep "$(shuf -i 45-90 -n 1)m"` before
  retrying CodeRabbit rather than proceeding to commit without the review.
  Evidence:
  `/tmp/check-fmt-job-object-after-const-windows-mac-support-validation.out`,
  `/tmp/lint-job-object-after-const-windows-mac-support-validation.out`,
  `/tmp/test-job-object-rerun-windows-mac-support-validation.out`,
  `/tmp/mdlint-job-object-windows-mac-support-validation.out`,
  `/tmp/nixie-job-object-windows-mac-support-validation.out`, and
  `/tmp/coderabbit-job-object-retry-windows-mac-support-validation.out`.
- [x] 2026-06-25T19:54:27Z Manual review during the CodeRabbit backoff found
  that the first Job Object implementation used `.any(...)` while assigning the
  discovered process tree, which short-circuited after the first successful
  assignment and left later descendants unattempted. The implementation now
  iterates over every discovered PID and records whether at least one
  assignment succeeded.
- [x] 2026-06-25T19:57:16Z Local validation after the Job Object tree-loop
  fix passed before retrying CodeRabbit. Evidence:
  `/tmp/check-windows-job-object-tree-loop-windows-mac-support-validation.out`,
  `/tmp/check-fmt-job-object-tree-loop-windows-mac-support-validation.out`,
  `/tmp/lint-job-object-tree-loop-windows-mac-support-validation.out`,
  `/tmp/test-job-object-tree-loop-windows-mac-support-validation.out`,
  `/tmp/mdlint-job-object-tree-loop-windows-mac-support-validation.out`, and
  `/tmp/nixie-job-object-tree-loop-windows-mac-support-validation.out`. The
  test gate ran two nextest passes: `275` passed with `3` skipped, then `151`
  passed with `0` skipped.
- [x] 2026-06-25T21:25:55Z After the mandated backoff completed, three
  CodeRabbit attempts still failed to produce a review result: two full
  `coderabbit review --agent` runs and one
  `coderabbit review --agent --type uncommitted` run all stalled after the
  `summarizing` status and were stopped by their exact process groups. A final
  scoped light attempt, `coderabbit review --agent --light --type uncommitted`,
  returned another free CLI rate limit with a reported
  `49 minutes and 40 seconds` reset. Per the user instruction, pause again with
  `vsleep "$(shuf -i 45-90 -n 1)m"` before retrying CodeRabbit. Evidence:
  `/tmp/coderabbit-job-object-tree-loop-windows-mac-support-validation.out`,
  `/tmp/coderabbit-job-object-tree-loop-retry-windows-mac-support-validation.out`,
  `/tmp/coderabbit-job-object-tree-loop-uncommitted-windows-mac-support-validation.out`,
  and
  `/tmp/coderabbit-job-object-tree-loop-uncommitted-light-windows-mac-support-validation.out`.
- [x] 2026-06-25T23:06:31Z CodeRabbit's scoped light retry produced one
  `major` finding before the second rate-limit cycle: the Windows cleanup path
  used a bare PID from `postmaster.pid`, so PID reuse could assign or terminate
  an unrelated process. The fix parses the PostgreSQL start timestamp from
  `postmaster.pid`, verifies the live Windows process still has a
  `postgres(.exe)` image name and matching creation time before assigning it to
  the Job Object or terminating its tree, and keeps the public PID-only
  test-support helper feature-gated so docs builds remain warning-free. Local
  validation passed after the fix: Windows target check, `make check-fmt`,
  `make lint`, `make test`, `make markdownlint`, and `make nixie`. Evidence:
  `/tmp/coderabbit-job-object-tree-loop-uncommitted-light-after-backoff-windows-mac-support-validation.out`,
  `/tmp/check-windows-job-object-identity-gated-helpers-windows-mac-support-validation.out`,
  `/tmp/check-fmt-job-object-identity-gated-helpers-windows-mac-support-validation.out`,
  `/tmp/lint-job-object-identity-gated-helpers-windows-mac-support-validation.out`,
  `/tmp/test-job-object-identity-gated-helpers-windows-mac-support-validation.out`,
  `/tmp/mdlint-job-object-identity-gated-helpers-windows-mac-support-validation.out`,
  and
  `/tmp/nixie-job-object-identity-gated-helpers-windows-mac-support-validation.out`.
  The test gate ran two nextest passes: `275` passed with `3` skipped, then
  `151` passed with `0` skipped.
- [x] 2026-06-25T23:13:04Z CodeRabbit re-reviewed the uncommitted Job
  Object identity-guard patch with
  `coderabbit review --agent --light --type uncommitted` after deterministic
  gates passed. The review completed with `status=review_completed` and
  `findings=0`, so the PID-reuse concern is cleared before committing. Evidence:
  `/tmp/coderabbit-job-object-identity-postfix-windows-mac-support-validation.out`.
- [x] 2026-06-25T23:22:06Z Remote CI run `28206487696` for commit `de0e441`
  passed all four pull-request jobs. macOS passed in `1m38s`; Windows passed in
  `5m45s` after building both binaries, running the CLI smoke test, and running
  the unprivileged surface tests that include the shutdown-hook
  orphan-detection scenario. Linux root and Linux unprivileged were also green.
  Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28206487696` and
  `/tmp/ci-watch-job-object-identity-windows-mac-support-validation.out`.
- [x] 2026-06-25T23:41:57Z Implemented the Milestone 3 packaging path
  locally after validating that the pinned shared staging action cannot package
  both production binaries. Added `scripts/release_archive.py`, delegated
  `make release-archive` to that script, extended `release.yml` to publish
  Linux, Windows, Apple Silicon macOS, and Intel macOS `.tgz` archives, and
  added a pull-request `binstall` job that builds a local archive, serves it
  over HTTPS with a throwaway CA, performs a real cargo-binstall install,
  checks both binaries were placed, and runs the installed CLI `--version`.
  Focused local evidence:
  `/tmp/pytest-release-archive-option-fix-windows-mac-support-validation.out`,
  `/tmp/release-archive-linux-option-fix-windows-mac-support-validation.out`,
  `/tmp/archive-list-linux-windows-mac-support-validation.out`, and
  `/tmp/binstall-local-linux-windows-mac-support-validation.out`.
- [x] 2026-06-25T23:52:28Z Re-ran the deterministic gates for the Milestone 3
  packaging patch before requesting review. Focused script tests passed with
  `5 passed`; `actionlint` passed for the workflow changes; `make check-fmt`,
  `make lint`, `make test`, `make markdownlint`, and `make nixie` all passed.
  The Linux test gate ran the same two nextest passes as the project Makefile:
  `275` tests passed with `3` skipped under all features, then `151` tests
  passed with `0` skipped under the dev-worker feature set. Evidence:
  `/tmp/pytest-release-archive-build-jobs-windows-mac-support-validation.out`,
  `/tmp/actionlint-binstall-packaging-post-script-fix-windows-mac-support-validation.out`,
  `/tmp/check-fmt-binstall-packaging-final-windows-mac-support-validation.out`,
  `/tmp/lint-binstall-packaging-final-windows-mac-support-validation.out`,
  `/tmp/test-binstall-packaging-final-windows-mac-support-validation.out`,
  `/tmp/mdlint-binstall-packaging-final-windows-mac-support-validation.out`, and
  `/tmp/nixie-binstall-packaging-final-windows-mac-support-validation.out`.
- [x] 2026-06-25T23:54:32Z Requested CodeRabbit review for the uncommitted
  Milestone 3 packaging patch after the deterministic gates above. The scoped
  light review completed with `status=review_completed` and `findings=0`.
  Evidence:
  `/tmp/coderabbit-binstall-packaging-windows-mac-support-validation.out`.
- [x] 2026-06-26T00:02:45Z Pushed commit `b14b0b7` and observed CI run
  `28208052710`. The existing macOS test job, Windows test job, and Linux root
  job reached green, but the new Linux `Binstall (x86_64-unknown-linux-gnu)`
  job failed in the real install step before downloading the local archive. The
  hosted setup action installed cargo-binstall `1.16.6`, which fails to parse
  this local manifest with `can't load root workspace`; local reproduction with
  a temporary `1.16.6` install produced the same error, while the same archive
  and HTTPS server passed with cargo-binstall `1.19.1`. Patched the packaging
  CI job to install cargo-binstall `1.19.1` into a job-local directory and
  prepend it to `PATH` before the validation install. Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28208052710`,
  `/tmp/ci-binstall-linux-failure-log-api-windows-mac-support-validation.out`,
  `/tmp/cargo-binstall-1.16.6-installs-1.19.1-windows-mac-support-validation.out`,
  and local reproduction output from the temporary `1.16.6` run.
- [x] 2026-06-26T00:06:54Z Pulled the remaining failed jobs from the same
  hosted run before committing the cargo-binstall version fix. macOS failed in
  the certificate-signing step because its OpenSSL does not support
  `openssl x509 -copy_extensions copy`; the CI script now writes a portable
  `server-ext.cnf` and signs the server certificate with `-extfile`. Windows
  failed while building the release archive because a release binary build
  without test-support features exposed unused Windows shutdown-hook helper
  imports under `-D warnings`; the Windows PID/probe re-exports and the probe
  function are now compiled only when the test-support API is compiled. Local
  `cargo check --target x86_64-pc-windows-msvc --release --bin pg_embedded_setup_unpriv --bin pg_worker`
  and `actionlint` passed after those fixes. Evidence:
  `/tmp/ci-binstall-macos-failure-log-api-windows-mac-support-validation.out`,
  `/tmp/ci-binstall-windows-failure-log-api-windows-mac-support-validation.out`,
  `/tmp/check-windows-release-binstall-fixes-windows-mac-support-validation.out`,
  and
  `/tmp/actionlint-binstall-packaging-portable-openssl-windows-mac-support-validation.out`.
- [x] 2026-06-26T00:04:22Z Re-ran deterministic checks for the
  cargo-binstall version fix before review: `actionlint`, `make markdownlint`,
  `make nixie`, and `git diff --check` passed. CodeRabbit then reviewed the
  uncommitted workflow/doc patch with
  `coderabbit review --agent --light --type uncommitted` and completed with
  `status=review_completed` and `findings=0`. Evidence:
  `/tmp/actionlint-binstall-packaging-binstall-version-fix-windows-mac-support-validation.out`,
  `/tmp/mdlint-binstall-packaging-binstall-version-fix-windows-mac-support-validation.out`,
  `/tmp/nixie-binstall-packaging-binstall-version-fix-windows-mac-support-validation.out`,
  and
  `/tmp/coderabbit-binstall-version-fix-windows-mac-support-validation.out`.
- [x] 2026-06-26T00:08:55Z Re-ran the full local gate set after the combined
  Linux/macOS/Windows packaging CI fixes.
  `cargo check --target x86_64-pc-windows-msvc --release --bin pg_embedded_setup_unpriv --bin pg_worker`,
  `actionlint`, `make check-fmt`, `make lint`, `make test`,
  `make markdownlint`, `make nixie`, and `git diff --check` passed. The Linux
  test gate again ran two nextest passes: `275` tests passed with `3` skipped,
  then `151` tests passed with `0` skipped. Evidence:
  `/tmp/check-windows-release-binstall-fixes-windows-mac-support-validation.out`,
  `/tmp/actionlint-binstall-packaging-portable-openssl-windows-mac-support-validation.out`,
  `/tmp/check-fmt-binstall-packaging-ci-fixes-windows-mac-support-validation.out`,
  `/tmp/lint-binstall-packaging-ci-fixes-windows-mac-support-validation.out`,
  `/tmp/test-binstall-packaging-ci-fixes-windows-mac-support-validation.out`,
  `/tmp/mdlint-binstall-packaging-ci-fixes-windows-mac-support-validation.out`,
  and
  `/tmp/nixie-binstall-packaging-ci-fixes-windows-mac-support-validation.out`.
- [x] 2026-06-26T01:28:12Z CodeRabbit reviewed the combined
  Linux/macOS/Windows packaging CI fixes after the full local gate set passed
  and after the required randomized backoff for the free CLI rate limit.
  `coderabbit review --agent --light --type uncommitted` completed with
  `status=review_completed` and `findings=0`, so there are no CodeRabbit
  concerns to clear before committing and pushing the corrective patch.
  Evidence:
  `/tmp/coderabbit-binstall-ci-fixes-retry-windows-mac-support-validation.out`.
- [x] 2026-06-26T01:40:48Z Pushed commit `af35126` and observed CI run
  `28211320490`. The GitHub MCP workflow-read tool was tried first, but its
  authentication token is expired, so CI observation continues through the
  authenticated `gh` CLI until that connector is repaired. Linux root, Linux
  unprivileged, macOS tests, Windows tests, and the Linux real `binstall` job
  all passed. The macOS `binstall` job failed while bootstrapping cargo-binstall
  `1.19.1`: source fallback replaced the Cargo-home `cargo-binstall` binary
  instead of writing to the requested `$RUNNER_TEMP/cargo-binstall-1.19.1`
  directory. The Windows `binstall` job built the archive but failed when Git
  Bash rewrote OpenSSL's `/CN=...` certificate subject into a
  `C:/Program Files/Git/...` path. Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28211320490`,
  `/tmp/ci-binstall-macos-af35126-job-logs-api-windows-mac-support-validation.out`,
  `/tmp/ci-binstall-windows-af35126-job-logs-api-windows-mac-support-validation.out`,
  and `/tmp/gh-watch-28211320490-windows-mac-support-validation.out`.
- [x] 2026-06-26T01:40:48Z Applied the next local `binstall` workflow patch:
  after installing cargo-binstall `1.19.1`, resolve the actual binary from
  either the requested job-local directory or `${CARGO_HOME:-$HOME/.cargo}/bin`
  and verify the version before adding it to `PATH`; for the throwaway HTTPS
  certificates, set `MSYS_NO_PATHCONV=1` only on the OpenSSL commands that pass
  `/CN=...` subjects. Deterministic gates passed before review: `actionlint`,
  `make check-fmt`, `make lint`, `make test`, `make markdownlint`,
  `make nixie`, and `git diff --check`. Evidence:
  `/tmp/actionlint-binstall-pathconv-fallback-windows-mac-support-validation.out`,
  `/tmp/check-fmt-binstall-pathconv-fallback-windows-mac-support-validation.out`,
  `/tmp/lint-binstall-pathconv-fallback-windows-mac-support-validation.out`,
  `/tmp/test-binstall-pathconv-fallback-windows-mac-support-validation.out`,
  `/tmp/mdlint-binstall-pathconv-fallback-windows-mac-support-validation.out`,
  `/tmp/nixie-binstall-pathconv-fallback-windows-mac-support-validation.out`,
  and
  `/tmp/diff-check-binstall-pathconv-fallback-final-windows-mac-support-validation.out`.
- [x] 2026-06-26T01:43:09Z CodeRabbit reviewed the uncommitted
  cargo-binstall path-resolution and Windows OpenSSL path-conversion patch
  after deterministic gates passed.
  `coderabbit review --agent --light --type uncommitted` completed with
  `status=review_completed` and `findings=0`. Evidence:
  `/tmp/coderabbit-binstall-pathconv-fallback-windows-mac-support-validation.out`.
- [x] 2026-06-26T01:55:29Z Pushed commit `e963d04` and observed CI run
  `28211894514`. Linux root, Linux unprivileged, macOS tests, Windows tests,
  and the Linux real `binstall` job all passed. The macOS and Windows
  `binstall` jobs both reached the local HTTPS readiness loop after building
  their release archives, then failed before `cargo-binstall` ran: macOS curl
  rejected the throwaway CA with `unable to get local issuer certificate`, and
  Windows curl/SChannel rejected it with `the revocation status is unknown`.
  Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28211894514`,
  `/tmp/ci-binstall-macos-e963d04-job-logs-api-windows-mac-support-validation.out`,
  `/tmp/ci-binstall-windows-e963d04-job-logs-api-windows-mac-support-validation.out`,
  and `/tmp/gh-watch-28211894514-windows-mac-support-validation.out`.
- [x] 2026-06-26T01:58:05Z Applied the next local `binstall` workflow patch:
  make the curl readiness probe use `--insecure` because it only waits for the
  local HTTPS server to accept connections; keep the
  `--root-certificates "$cert_dir/ca.pem"` argument on `cargo binstall`
  unchanged as the actual CA-trust validation. Deterministic gates passed
  before review: `actionlint`, `make check-fmt`, `make lint`, `make test`,
  `make markdownlint`, `make nixie`, and `git diff --check`. CodeRabbit then
  reviewed the uncommitted patch with
  `coderabbit review --agent --light --type uncommitted` and completed with
  `status=review_completed` and `findings=0`. Evidence:
  `/tmp/actionlint-binstall-readiness-curl-windows-mac-support-validation.out`,
  `/tmp/check-fmt-binstall-readiness-curl-windows-mac-support-validation.out`,
  `/tmp/lint-binstall-readiness-curl-windows-mac-support-validation.out`,
  `/tmp/test-binstall-readiness-curl-windows-mac-support-validation.out`,
  `/tmp/mdlint-binstall-readiness-curl-windows-mac-support-validation.out`,
  `/tmp/nixie-binstall-readiness-curl-windows-mac-support-validation.out`,
  `/tmp/diff-check-binstall-readiness-curl-windows-mac-support-validation.out`,
  and
  `/tmp/coderabbit-binstall-readiness-curl-windows-mac-support-validation.out`.
- [x] 2026-06-26T02:10:43Z Pushed commit `35a6bbd` and observed CI run
  `28212300565`. Linux root, Linux unprivileged, macOS tests, Windows tests,
  Linux `binstall`, and Windows `binstall` all passed. The macOS `binstall` job
  reached the real `cargo-binstall` install step and failed while validating
  the local HTTPS archive: `rustls-platform-verifier`/Apple Security rejected
  the extra root certificate with
  `"pg local test CA" certificate is not standards compliant: -67903`. The
  GitHub MCP workflow-log tool was tried first again, but the connector token
  remains expired, so logs were fetched with the authenticated `gh` CLI.
  Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28212300565`,
  `/tmp/ci-binstall-macos-35a6bbd-job-logs-api-windows-mac-support-validation.out`,
  and `/tmp/gh-watch-28212300565-windows-mac-support-validation.out`.
- [x] 2026-06-26T02:14:28Z User approved continuing with four more approaches
  for the remaining macOS `binstall` validation failure. Approach 1 replaces
  the ad hoc one-line OpenSSL root/server certificate generation with explicit
  config files, a non-empty organization in both subjects, fixed short serial
  numbers, explicit CA/server X.509v3 extensions, and an
  `openssl verify -x509_strict -purpose sslserver` check before the local HTTPS
  server starts. Local Linux real-install validation still passes with
  cargo-binstall `1.19.1` and the new certificate profile. Deterministic gates
  passed before CodeRabbit review: `actionlint`, `make fmt`, `make check-fmt`,
  `make lint`, `make test`, `make markdownlint`, `make nixie`, and
  `git diff --check`. The first CodeRabbit attempt hit the free CLI rate limit,
  so the mandated randomized backoff ran for `52` minutes before retrying. The
  retry completed with `status=review_completed` and `findings=0`. Evidence:
  `/tmp/actionlint-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/explicit-cert-strict-verify-windows-mac-support-validation.out`,
  `/tmp/release-archive-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/binstall-local-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/fmt-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/check-fmt-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/lint-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/test-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/mdlint-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/nixie-binstall-explicit-cert-windows-mac-support-validation.out`, and
  `/tmp/diff-check-binstall-explicit-cert-windows-mac-support-validation.out`,
  `/tmp/coderabbit-binstall-explicit-cert-windows-mac-support-validation.out`,
  and
  `/tmp/coderabbit-binstall-explicit-cert-retry-windows-mac-support-validation.out`.
- [x] 2026-06-26T03:20:17Z Pushed commit `87791d7` and observed CI run
  `28214611615` to green. Linux root, Linux unprivileged, macOS tests, Windows
  tests, Linux `binstall`, Windows `binstall`, and macOS `binstall` all passed.
  The explicit X.509v3 CA/server certificate profile resolved the hosted macOS
  Apple Security `-67903` rejection, and the real `cargo-binstall` install now
  succeeds on all three pull-request runners. The GitHub MCP workflow-run tool
  was retried for this commit and still returned `token_expired`, so the CI run
  was observed with authenticated `gh` commands. Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28214611615` and
  `/tmp/gh-watch-28214611615-windows-mac-support-validation.out`.
- [x] 2026-06-26T03:45:00Z Implemented the release-time asset audit in
  `.github/workflows/release.yml`. The new `audit-draft-assets` matrix runs on
  all five supported release targets, downloads the just-uploaded draft release
  assets with `gh release download`, serves those exact files over local HTTPS,
  dry-runs `cargo-binstall` resolution for all five supported triples, and
  performs one real install-and-run of the host target before the draft is
  published. A follow-up `verify-published-assets` job runs after publication
  and dry-runs the public `pkg-url` template for all five targets. Local gates
  passed before CodeRabbit review: `actionlint`, `make check-fmt`, `make lint`,
  `make test`, `make markdownlint`, `make nixie`, and `git diff --check`.
  CodeRabbit reviewed the uncommitted release-audit diff afterwards and returned
  `status=review_completed` with `findings=0`. Evidence:
  `/tmp/actionlint-release-asset-audit-windows-mac-support-validation.out`,
  `/tmp/check-fmt-release-asset-audit-windows-mac-support-validation.out`,
  `/tmp/lint-release-asset-audit-windows-mac-support-validation.out`,
  `/tmp/test-release-asset-audit-windows-mac-support-validation.out`,
  `/tmp/mdlint-release-asset-audit-windows-mac-support-validation.out`,
  `/tmp/nixie-release-asset-audit-windows-mac-support-validation.out`, and
  `/tmp/diff-check-release-asset-audit-windows-mac-support-validation.out`, and
  `/tmp/coderabbit-release-asset-audit-windows-mac-support-validation.out`.
- [x] 2026-06-26T03:39:36Z Remote CI run `28215289980` for commit
  `1f42ac7` failed only in the Linux `Binstall (x86_64-unknown-linux-gnu)` job
  after the local archive install had succeeded. The installed
  `pg_embedded_setup_unpriv --version` command entered bootstrap, then failed
  while `postgresql_embedded` queried the unauthenticated GitHub releases API
  for `theseus-rs/postgresql-binaries` and received `403 Forbidden`. Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28215289980`,
  `/tmp/gh-watch-28215289980-windows-mac-support-validation.out`, and
  `/tmp/ci-binstall-linux-1f42ac7-job-logs-api-windows-mac-support-validation.out`.
- [x] 2026-06-26T03:42:10Z User requested four more approaches for the
  current `binstall` failure. Approach 1 is to make `--version` a real CLI flag
  that exits before bootstrap rather than giving the packaging job more network
  credentials. The red test `cargo test --test cli` now invokes the real binary
  with an invalid `PG_VERSION_REQ`; it fails because the current binary ignores
  `--version` and parses bootstrap configuration. The green implementation adds
  Clap parsing in `src/main.rs` and a regression test in `tests/cli.rs`;
  `--version` now exits before bootstrap and prints the package version. Local
  gates passed before CodeRabbit review: focused red/green CLI tests,
  `make check-fmt`, `make lint`, `make test`, `make markdownlint`,
  `make nixie`, and `git diff --check`. Evidence:
  `/tmp/test-cli-version-red-windows-mac-support-validation.out`,
  `/tmp/test-cli-version-green-windows-mac-support-validation.out`,
  `/tmp/check-fmt-cli-version-windows-mac-support-validation.out`,
  `/tmp/lint-cli-version-windows-mac-support-validation.out`,
  `/tmp/test-cli-version-windows-mac-support-validation.out`,
  `/tmp/mdlint-cli-version-windows-mac-support-validation.out`,
  `/tmp/nixie-cli-version-windows-mac-support-validation.out`, and
  `/tmp/diff-check-cli-version-windows-mac-support-validation.out`.
- [x] 2026-06-26T03:43:14Z CodeRabbit reviewed the uncommitted CLI
  `--version` fix after deterministic gates passed.
  `coderabbit review --agent --light --type uncommitted` completed with
  `status=review_completed` and `findings=0`, so there are no CodeRabbit
  concerns to clear before committing Approach 1. Evidence:
  `/tmp/coderabbit-cli-version-windows-mac-support-validation.out`.
- [x] 2026-06-26T03:55:05Z Pushed commit `5f19e2f` and observed CI run
  `28215731121` to green. Linux root, Linux unprivileged, macOS tests, Windows
  tests, Linux `binstall`, Windows `binstall`, and macOS `binstall` all passed.
  The earlier Linux `binstall` failure mode is resolved: the installed
  `pg_embedded_setup_unpriv --version` now exits through Clap before bootstrap
  and no longer downloads PostgreSQL binaries or queries
  `theseus-rs/postgresql-binaries`. The GitHub MCP workflow-run tool was
  retried for this commit and still returned `token_expired`, so the CI run was
  observed with authenticated `gh` commands. Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28215731121` and
  `/tmp/gh-watch-28215731121-windows-mac-support-validation.out`.
- [x] 2026-06-26T04:00:05Z Implemented the Milestone 5 documentation update.
  `README.md` and `docs/users-guide.md` now list the published `cargo binstall`
  target matrix, the Windows-on-ARM limitation, and the Windows ACL/file-mode
  caveat. `docs/roadmap.md` now closes item `3.3.2` and records the macOS and
  Windows validation scope. The design document records the Windows Job Object
  cleanup decision, the `src/fs.rs` Unix-only POSIX mode application decision,
  and the release target scope.
- [x] 2026-06-26T05:15:12Z Milestone 5 deterministic gates passed locally:
  `make fmt`, `make check-fmt`, `make lint`, `make test`, `make markdownlint`,
  `make nixie`, and `git diff --check`. The test gate ran `276` tests with `3`
  skipped, then `152` `dev-worker` tests with `0` skipped. The first CodeRabbit
  review attempt hit the free CLI rate limit; per the user instruction,
  `vsleep "72m"` completed before retrying. The retry completed with
  `status=review_completed` and `findings=0`, so there are no documentation
  concerns to clear before committing. Evidence:
  `/tmp/fmt-docs-final-windows-mac-support-validation.out`,
  `/tmp/check-fmt-docs-final-windows-mac-support-validation.out`,
  `/tmp/lint-docs-final-windows-mac-support-validation.out`,
  `/tmp/test-docs-final-windows-mac-support-validation.out`,
  `/tmp/mdlint-docs-final-windows-mac-support-validation.out`,
  `/tmp/nixie-docs-final-windows-mac-support-validation.out`,
  `/tmp/diff-check-docs-final-windows-mac-support-validation.out`,
  `/tmp/coderabbit-docs-final-windows-mac-support-validation.out`, and
  `/tmp/coderabbit-docs-final-retry-windows-mac-support-validation.out`.
- [x] 2026-06-26T05:27:00Z Pushed commit `26dfa40` and observed CI run
  `28218770776` to green. Linux root, Linux unprivileged, macOS tests, Windows
  tests, Linux `binstall`, Windows `binstall`, and macOS `binstall` all passed.
  The GitHub MCP workflow-run tool was retried and still returned
  `token_expired`, and the active `GH_TOKEN` environment belonged to
  `lodyai[bot]` and produced `Bad credentials` with `gh`; unsetting `GH_TOKEN`
  let the stored `leynos` `gh` credential observe the run successfully.
  Evidence:
  `https://github.com/leynos/pg-embed-setup-unpriv/actions/runs/28218770776` and
  `/tmp/gh-watch-28218770776-retry-windows-mac-support-validation.out`.
- [x] 2026-06-28T02:02:00Z Began the post-green review follow-up for the
  failed quality report. Confirmed the `--help` CLI test, Windows cargo-path
  parser test, and Windows descendant PID-reuse validation tests already exist.
  Implemented the still-valid gaps: release archive target/binary path
  validation, cfg-specific Rust signatures instead of fake unused-parameter
  reads, explicit non-Unix serial lock owner states with grace-window tests,
  Windows shutdown debug tracing, and developer-guide coverage for the
  cross-platform release/shutdown design.
- [x] Milestone 1: make the library and both binaries compile on Windows and
  macOS (`fs.rs` mode gating; `nix` target-gating; `tests/` `nix` import
  gating; remove the dead `xdg` dependency; resolve `openssl-sys`), AND resolve
  the Windows shared-cluster cleanup question with an orphan-detection test
  (Red → Green). Exit gate includes one real Windows link-and-run.
- [x] Milestone 2: add a test-only macOS and Windows CI matrix (tests +
  orphan-detection), with mandatory theseus caching and a recorded cost budget;
  observe it pass.
- [x] Milestone 3: add `binstall` packaging for macOS and Windows; extend the
  release workflow to build and upload the new archives.
- [x] Milestone 4: validate `binstall` with a real install-and-run per OS at
  pull-request time and an end-to-end check against real assets at release
  time. The pull-request-time real install-and-run is complete as of CI run
  `28215731121`; the release-time asset audit is implemented and will execute
  against real assets on the next release tag.
- [x] Milestone 5: update README, users' guide, roadmap appendix (and close
  item 3.3.2), and the design doc; run all commit gateways; finalize.

## Surprises & discoveries

- Observation: the unprivileged code path is already largely portable, and more
  of the platform-gating is already done than a first survey suggested. The
  `atexit` shutdown hook is already gated: `src/cluster/mod.rs:61` reads
  `#[cfg(unix)] mod shutdown_hook;`, the re-exports at lines 63-67 are gated,
  and `src/cluster/handle.rs:312-330` already has a `#[cfg(unix)]` real
  implementation plus a `#[cfg(not(unix))]` no-op. Evidence: direct reads.
  Impact: the earlier claim that `shutdown_hook` is the "primary Windows
  compile blocker" was wrong; there is nothing to port for compilation. The
  remaining questions are the genuine compile blockers (below) and the
  *behavioural* gap that the non-Unix no-op leaves shared clusters unreaped.
- Observation: the genuine unconditional Windows compile blockers are
  `src/fs.rs` (cap-std `PermissionsExt`/`from_mode`), the unconditional `nix`
  dependency, the unconditional `use nix::unistd::geteuid;` in
  `tests/settings.rs:7` (compiled by `--all-targets`), and the apparently-dead
  Unix-only `xdg` crate. Evidence: `src/fs.rs:7,159`; `Cargo.toml:115,125`;
  `tests/settings.rs:7`; grep showing no `xdg::` usage. Impact: these define
  Milestone 1's real scope; the original survey covered `src/` only and missed
  the `tests/` tree and the dead dependency.
- Observation: the roadmap appendix and `docs/users-guide.md` already specify
  the intended macOS (unprivileged in-process; root fails fast) and Windows
  (always unprivileged) behaviour, and roadmap item 3.3.2 ("guardrails that
  fail fast on unsupported root scenarios on non-Linux systems") is still open.
  Evidence: `docs/roadmap.md` lines 50-85; `docs/users-guide.md` lines 20-45.
  Impact: this plan implements and validates that documented intent and can
  close 3.3.2.
- Observation: `leynos/shared-actions` already provides tri-platform building
  blocks — `setup-rust`, `rust-build-release`, and `stage-release-artefacts`
  support Windows and macOS; `rust-toy-app.yml` is the canonical cross-OS
  matrix reference; `upload-codescene-coverage` is POSIX-only with no Windows
  path. The current default-branch HEAD is
  `7da7c6d89033d13cbb1c64803d108ddca97e69c2`; the repo is pinned at
  `b61ad14766ae81b830abdaf066eb3d9b6c4f537b`. Evidence: inspection of the
  repository's actions and workflows. Impact: prefer reusing these actions, but
  the later Milestone 3 implementation supersedes the `stage-release-artefacts`
  packaging recommendation because the pinned action packages one binary.
- Observation (from the design-review panel): a `--dry-run` `binstall` check
  does not extract the archive, so it cannot catch a wrong internal layout; and
  the release runner could build the archive via a different code path than the
  PR-time check, so the artefact that ships may not be the one tested. Impact:
  validation must include a real install-and-run, and local/release archive
  production should share one code path.
- Observation: Milestone 0's three current-HEAD cross-target checks all fail
  before this crate's Rust source is typechecked because `openssl-sys` is an
  unconditional direct dependency with `features = ["vendored"]`. On
  `x86_64-apple-darwin` and `aarch64-apple-darwin`, the Linux host compiler
  rejects Darwin flags such as `-arch` and `-mmacosx-version-min`; on
  `x86_64-pc-windows-msvc`, OpenSSL's configure step rejects the Linux Perl
  because it does not produce Windows-style paths. Evidence:
  `/tmp/check-darwin-windows-mac-support-validation.out`,
  `/tmp/check-darwin-arm-windows-mac-support-validation.out`, and
  `/tmp/check-windows-windows-mac-support-validation.out`. Impact: the
  source-level `fs.rs`/`nix` errors are currently masked; dependency
  portability must be fixed first and the cross-target checks rerun.
- Observation: `cargo tree --target x86_64-pc-windows-msvc -i openssl-sys`
  shows two routes into `openssl-sys`: the crate's direct dependency and the
  default `postgresql_embedded` native-TLS feature.
  `cargo info postgresql_embedded@0.20.2` shows a supported `rustls` feature,
  and `postgresql_archive@0.20.2` exposes matching `rustls` support. Impact:
  the first implementation attempt disabled default `postgresql_embedded`
  features and opted into `tokio`, `theseus`, and `rustls`, but that path was
  later rejected after direct validation.
- Observation: the `rustls` route pulls in `ring`/`aws-lc-sys` for this
  dependency graph, and the Linux-hosted Windows cross-check then needs MSVC
  tools such as `lib.exe` and NASM. This violates the dependency tolerance that
  no new build tool should be required for portability validation. Evidence:
  the failed intermediate `x86_64-pc-windows-msvc` check after enabling
  `postgresql_embedded`'s `rustls` feature. Impact: keep
  `postgresql_embedded`'s default native TLS backend and remove only this
  crate's direct vendored OpenSSL dependency.
- Observation: after removing the direct vendored `openssl-sys` dependency, the
  native-TLS target graph is portable for the required checks: Windows uses the
  platform TLS backend, macOS uses Security.framework, and Linux keeps its
  native OpenSSL path. The three cross-target checks and the same checks with
  `RUSTFLAGS="-D warnings"` all pass. Impact: no new runtime dependency or
  runner build-tool provisioning is needed for Milestone 1 compilation.
- Observation: `tests/cluster_split_constructors.rs` and
  `tests/recovery_integration.rs` existed as integration tests without explicit
  `[[test]]` entries, so Cargo treated them as default tests during
  `--all-targets` cross-checks instead of applying their intended feature
  scopes. Impact: add explicit `[[test]]` entries with
  `required-features = ["cluster-unit-tests"]` and
  `required-features = ["dev-worker"]` respectively, matching the feature gates
  used by neighbouring integration tests.
- Observation: making Unix-only `worker_env_tests` visible to the Linux
  all-feature lint pass exposed an existing `expect()`-based `rstest` fixture
  setup that violated the repository's `clippy::expect_used` policy. Impact:
  convert that fixture setup and the two affected tests to return
  `color_eyre::Result` and use `ensure!`/`?`, so setup and assertion failures
  report errors without panicking.
- Observation: a literal audit found that `src/cache/lock.rs` and
  `src/cache/operations/copy.rs` already contain Unix/non-Unix implementations,
  so their Unix imports are not new blockers. The top-level `xdg` crate remains
  unused; the only matches are `Cargo.toml`, this ExecPlan, and local `xdg_*`
  path variable/function names. Evidence:
  `rg "PermissionsExt|from_mode|nix::|std::os::unix|libc::|xdg" src tests` and
  `rg "xdg::|use xdg|xdg ="`. Impact: Milestone 1 keeps those existing cache
  splits and focuses on dependency gating plus the unguarded filesystem mode
  helper.
- Observation: `libc::atexit` is available on Windows through the existing
  `libc` dependency, so the process-exit registration mechanism does not
  require a new runtime crate. Windows still needs different process controls:
  POSIX signals cannot terminate the postmaster tree there. Impact: the Windows
  implementation keeps the existing atexit shape, uses the native `taskkill`
  utility for process-tree termination, and limits raw Win32 FFI to liveness
  checks.
- Observation: making the orphan-detection parent test run by default exposed a
  deterministic nextest contention point. The focused lifecycle test passed,
  but the first full `make test` run failed because another cluster test was
  using the shared `/var/tmp/pg-embed-1000/data` directory while the child
  process tried to start. Impact: the shutdown-hook registration and lifecycle
  integration tests must hold the existing `tests/support/serial.rs`
  cross-process scenario guard before creating a real `TestCluster`.
- Observation: `tests/support/serial.rs` previously provided only an in-process
  mutex on non-Unix targets. That would leave Windows nextest runs exposed to
  the same cross-binary cluster-directory race seen locally on Linux before the
  shutdown-hook tests acquired the guard. Impact: non-Unix test runs now use an
  atomic lock directory under `CARGO_TARGET_DIR` for cross-process coordination
  without adding a dependency.
- Observation: `PgEnvCfg` only pins a `postgresql_embedded` version when
  `PG_VERSION_REQ` is supplied; otherwise the backend resolves the default
  requirement at runtime. Impact: the cross-platform CI legs set
  `PG_VERSION_REQ="=17.4.0"` so the mandatory PostgreSQL binary cache key is
  stable and scoped to one known upstream binary version.
- Observation: `actions/cache` tag v4.3.0 currently resolves to
  `0057852bfaa89a56745cba8c7296529d2fc39830`, and `leynos/shared-actions`
  default-branch HEAD still resolves to
  `7da7c6d89033d13cbb1c64803d108ddca97e69c2`. Impact: the workflow can satisfy
  the repository's SHA pinning policy without drifting from the planned
  shared-actions revision.
- Observation: remote macOS CI compiles the test harness for the
  `cluster-unit-tests,async-api` feature set before running any tests, so a
  root-only Linux/BSD helper import fails even when the corresponding scenario
  would have skipped at runtime. Impact: root-specific test binaries and helper
  imports must be target-gated at compile time, not just skipped dynamically.
- Observation: remote macOS CI reached the unprivileged test runtime in run
  `28179624023`; the remaining deterministic macOS failure was not in worker
  discovery itself, but in the Unix test fixture creating a filename from raw
  bytes `0xff, 0xfe, 0xfd`. APFS rejects that pathname with "Illegal byte
  sequence" before `discover_worker_from_path_value` runs. Impact: the
  non-UTF-8 PATH-entry fixture is only portable to Unix filesystems that allow
  arbitrary non-NUL bytes in path components; macOS must retain coverage
  through other worker-discovery tests unless a different fixture is designed.
- Observation: the same run's Windows leg failed in the binary build step while
  downloading `cap-primitives` from crates.io, with a connection reset before
  crate compilation. Impact: this is external network noise; rerun failed
  workflow jobs after the run completes before making code changes for Windows.
- Observation: remote CI run `28185956153` showed both cross-platform test legs
  now reach runtime after building the regular binaries and running the CLI
  smoke test. The remaining macOS failure was a Linux/BSD root-helper
  assertion: its check that the system temp directory is world-executable is
  required for `nobody` traversal, not for macOS unprivileged support. The
  remaining Windows failure was an assertion bug in `src/cache/config.rs`
  tests: the product joins `XDG_CACHE_HOME` and `CACHE_SUBDIR` through platform
  path APIs, so Windows naturally renders `\` separators. Impact: treat these
  as test corrections, not source-portability changes.
- Observation: remote CI run `28192593707` proved the first Windows reaper
  shape was insufficient. The Windows job reached the orphan-detection test
  after successful binary build and CLI smoke, but `taskkill /PID <pid> /T`
  from the atexit hook did not stop the postmaster tree: the parent timed out
  after `30s`, and GitHub runner cleanup later killed two orphaned `postgres`
  processes. Impact: spawning `taskkill` inside the process-exit path is not a
  reliable cleanup primitive for this test cluster; the Windows hook must use
  direct process handles and kill descendants itself.
- Observation: remote CI run `28194422551` proved direct
  `TerminateProcess` calls from the Windows atexit path were also insufficient.
  The failure shape was unchanged: the postmaster PID from `postmaster.pid`
  stayed alive for the parent process's full `30s` polling window, and the
  GitHub runner later cleaned up the same `postgres` process tree. Impact: the
  next approach must not depend solely on the atexit callback reaching and
  terminating the postmaster during process teardown.
- Observation: the first local Job Object patch used `.any(...)` to assign the
  discovered Windows process tree to the kill-on-close job. Because `.any(...)`
  short-circuits on the first success, a successful root-process assignment
  prevented any later descendants from being attempted. Impact: assigning the
  tree must be expressed as an explicit loop that visits every PID and records
  whether at least one assignment succeeded.
- Observation: CodeRabbit found that the Job Object and forced-termination
  paths must not trust a bare PID from `postmaster.pid`, because Windows may
  reuse that PID for an unrelated process before cleanup runs. Impact: the
  Windows shutdown hook now treats the PID and PostgreSQL start timestamp as a
  pair, then verifies the live process image and creation time before assigning
  or terminating the process tree.
- Observation: remote CI run `28206487696` proved the Job Object failsafe with
  PID-reuse protection satisfies the hosted Windows orphan-detection scenario.
  The Windows job built both binaries, passed the CLI smoke test, ran the
  unprivileged surface tests, and completed without runner cleanup reporting
  orphaned PostgreSQL processes. Impact: Approach 3 is the accepted Windows
  cleanup implementation; no fourth cleanup approach is needed before moving to
  `binstall` packaging.
- Observation: the pinned
  `leynos/shared-actions/stage-release-artefacts` implementation stages a single
  `binary_source` into one cargo-binstall archive and emits tar.gz archives
  only. The crate has two production binaries, and `cargo binstall` installs
  all binaries by default when `--bin` is omitted. Impact: using that action
  as-is would validate and publish an incomplete install, so Milestone 3 uses a
  repo-local packager instead.
- Observation: this cargo-binstall build rejects local `http://` and `file://`
  package URLs with `BadScheme`. A pull-request-time real install can still be
  tested without a GitHub release by serving the archive over local HTTPS with
  a throwaway CA and passing that CA via `--root-certificates`. Impact: the CI
  `binstall` job uses a local HTTPS server rather than a plain Python
  `http.server`.
- Observation: cargo-binstall `1.16.6`, the version installed by the pinned
  shared setup action at implementation time, cannot parse this crate through
  `--manifest-path Cargo.toml` for the local cargo-binstall validation path; it
  reports `can't load root workspace` before trying the local package URL. The
  same archive and command shape work with cargo-binstall `1.19.1`, and
  `1.16.6` can bootstrap `1.19.1` into an isolated install directory. Impact:
  the `binstall-packaging` job must pin the cargo-binstall version it uses for
  validation instead of inheriting the shared action's bundled version.
- Observation: macOS's hosted OpenSSL accepts `openssl req -addext` in the
  request step but rejects `openssl x509 -copy_extensions copy` in the signing
  step. Impact: certificate extensions for the local HTTPS server must be
  supplied through an explicit `-extfile` that works across Linux, macOS, and
  Windows OpenSSL builds.
- Observation: `make lint` and the cross-platform test jobs compile Windows
  with test-support features, but the release archive builder compiles the
  production binaries without those features. That narrower production build
  exposed unused Windows shutdown-hook PID helper re-exports that the earlier
  all-feature gates could not see. Impact: Milestone 3 needs a release-target
  Windows check as part of its packaging evidence, not only all-targets test
  checks.
- Observation: the GitHub MCP workflow-read tool is currently unusable in this
  session because the connector returns an expired-token error. Impact: use the
  authenticated `gh` CLI for CI observation and raw job-log retrieval until the
  connector token is refreshed; keep the MCP failure recorded because the
  user's preferred validation route was attempted.
- Observation: on the hosted Apple Silicon macOS runner, bootstrapping
  cargo-binstall `1.19.1` from cargo-binstall `1.16.6` may fall back to a
  source build and replace the existing Cargo-home `cargo-binstall` executable
  rather than honouring the requested `--install-path`. Impact: the CI job must
  discover the effective installed binary path after bootstrap and verify its
  version, instead of assuming `$RUNNER_TEMP/cargo-binstall-1.19.1` contains
  the executable.
- Observation: on the hosted Windows runner, Git Bash/MSYS path conversion
  rewrites OpenSSL certificate subject arguments such as `/CN=pg local test CA`
  into paths rooted under `C:/Program Files/Git/`, which OpenSSL rejects as an
  invalid subject name. Impact: the workflow must disable MSYS path conversion
  for the OpenSSL invocations that pass slash-prefixed certificate subjects.
- Observation: the hosted macOS and Windows `binstall` runners both reject the
  throwaway local CA during the curl readiness probe, but in platform-specific
  ways: macOS curl reports `unable to get local issuer certificate`, while
  Windows curl backed by SChannel reports `the revocation status is unknown`.
  In both cases the local HTTPS server is already accepting connections and the
  failure happens before `cargo-binstall` can run. Impact: the readiness probe
  should only test server availability; the cargo-binstall command below it
  remains the cross-platform CA-validation gate through `--root-certificates`.
- Observation: after the readiness-probe fix, CI run `28212300565` proved the
  remaining `binstall` failure is macOS-specific and happens inside
  `cargo-binstall`'s Rust TLS stack. Windows `binstall` passed the same local
  HTTPS validation, while macOS failed with Apple Security error `-67903`,
  reported by `rustls-platform-verifier` as the extra root certificate not
  being standards compliant. Local `openssl verify -x509_strict` accepts the
  original chain, so this is a platform verifier policy difference rather than
  a plain OpenSSL chain-building failure. Impact: first try a more explicit
  root/server certificate profile; if that still fails, stop relying on a
  custom CA as the macOS PR-time validation transport.
- Observation: CI run `28214611615` proved the stricter local CA profile is
  accepted by `cargo-binstall` on hosted macOS, Windows, and Linux. Impact:
  keep the explicit X.509v3 certificate generation; the remaining Milestone 4
  work is the release-time asset audit, not another local HTTPS transport
  approach.
- Observation: the release audit must run before the draft release is
  published if it is to block bad assets. Impact: audit the exact uploaded
  draft assets through `gh release download` and local HTTPS before publishing,
  then add a small post-publication public-URL dry-run to verify GitHub's
  published `releases/download` URLs.
- Observation: CI run `28215289980` proved that the setup binary's advertised
  `--version` smoke check was not actually a version path. `src/main.rs` called
  `pg_embedded_setup_unpriv::run()` directly, while `PgEnvCfg::load()` feeds
  OrthoConfig a fixed program name and intentionally ignores CLI arguments.
  Impact: `--version` was ignored, so the installed binary started PostgreSQL
  bootstrap and could fail on external `theseus-rs/postgresql-binaries` API
  rate limits even though the archive layout and installation were already
  correct.

## Decision log

- Decision: re-ground the entire library-portability analysis against current
  HEAD before implementing Milestone 1, treating the Risk register as a
  hypothesis list until Milestone 0's real cross-compile confirms it.
  Rationale: the first survey misread the `shutdown_hook` gating; confidence
  levels were asserted without a real `cargo check --target`. Date/Author:
  2026-06-25, planning agent (incorporating Logisphere review).
- Decision: there is no Windows `shutdown_hook` *compilation* work; instead
  treat Windows shared-cluster cleanup as a *behavioural* task — decide reaper
  vs. prove-no-leak, validated by an orphan-detection test. Rationale: the
  module is already `cfg(unix)`-gated with a non-Unix no-op; the real risk is
  an orphaned postmaster, not a build failure. Date/Author: 2026-06-25,
  planning agent.
- Decision (superseded after validation): prefer
  `leynos/shared-actions/stage-release-artefacts` (and the `rust-toy-app.yml`
  matrix shape) as the primary packaging and cross-OS path; demote any
  hand-rolled Makefile `.zip`/`.exe` branching to a documented
  local-development fallback. Rationale at planning time: the user nominated
  `shared-actions` as the reference; the action appeared to handle Windows
  archive layout and a `.sha256` sidecar. Superseded because implementation
  inspection showed the pinned action packages one binary only. Date/Author:
  2026-06-25, planning agent (incorporating review); superseded 2026-06-25,
  implementation agent.
- Decision: use `scripts/release_archive.py` as the single archive builder for
  release and pull-request packaging validation, with `make release-archive`
  delegating to it for local development. Rationale: the script is the smallest
  cross-platform implementation that can build both production binaries, stage
  `.exe` names for Windows, and create the cargo-binstall `.tgz` archive
  without relying on GNU Make or `tar` being present on Windows. The script
  follows the plan's helper-script constraints by using a `uv` inline metadata
  block, Python 3.13+, `cyclopts`, `cuprum`, `pathlib`, and tests under
  `scripts/tests/` using `pytest` plus `cmd-mox`. Date/Author: 2026-06-25,
  implementation agent.
- Decision: validate `binstall` primarily by a real install-and-run
  (`cargo binstall --install-path <tmp>` then execute `--version`) on each OS,
  with `--dry-run` per-target resolution as a secondary breadth check.
  Rationale: `--dry-run` cannot catch extraction/placement faults. Date/Author:
  2026-06-25, planning agent.
- Decision: install cargo-binstall `1.19.1` into `$RUNNER_TEMP` in the
  `binstall-packaging` job and prepend that directory to `PATH` before running
  the validation install. Rationale: the shared action's bundled cargo-binstall
  `1.16.6` fails on this local-manifest validation path; the newer tool version
  is isolated to the packaging job and can be installed by the older tool
  before the crate-under-test is validated. Date/Author: 2026-06-26,
  implementation agent.
- Decision: after bootstrapping cargo-binstall `1.19.1`, accept either the
  requested job-local install directory or Cargo home's `bin` directory as the
  effective tool location, then verify that `cargo-binstall -V` reports
  `1.19.1` before adding that directory to `PATH`. Rationale: hosted macOS can
  source-build the tool and replace the Cargo-home executable despite
  `--install-path`, so version verification is the stable contract.
  Date/Author: 2026-06-26, implementation agent.
- Decision: sign the local HTTPS server certificate with a generated OpenSSL
  extension file instead of relying on `openssl x509 -copy_extensions`.
  Rationale: Linux accepted `-copy_extensions`, but the hosted macOS OpenSSL
  rejected it; an explicit `subjectAltName`/`serverAuth` `-extfile` keeps the
  throwaway CA validation portable. Date/Author: 2026-06-26, implementation
  agent.
- Decision: set `MSYS_NO_PATHCONV=1` only for the OpenSSL commands that pass
  `/CN=...` certificate subjects in the Windows `binstall` validation job.
  Rationale: this prevents Git Bash from rewriting certificate subjects while
  leaving ordinary path conversion available for the rest of the cargo-binstall
  install step. Date/Author: 2026-06-26, implementation agent.
- Decision: use `curl --insecure` only in the local HTTPS readiness loop, not
  in the actual `cargo-binstall` install. Rationale: the loop's contract is to
  wait until the throwaway server accepts HTTPS connections; trust validation
  belongs to the subsequent `cargo binstall --root-certificates` command, and
  hosted macOS/Windows curl backends reject the generated one-day CA before
  that command can exercise the real install path. Date/Author: 2026-06-26,
  implementation agent.
- Decision: continue past the original `binstall` validation tolerance after
  explicit user approval on 2026-06-26. Try up to four further approaches,
  recording each in this ExecPlan and validating through deterministic local
  gates plus hosted CI. Rationale: the original tolerance correctly forced
  escalation after the primary and alternate `binstall` validation attempts;
  the user has now supplied the required direction to keep iterating.
  Date/Author: 2026-06-26, implementation agent.
- Decision: make the first resumed macOS `binstall` approach a more explicit
  throwaway certificate profile rather than weakening TLS validation.
  Rationale: the latest hosted run proves Windows can install from the local
  HTTPS archive and macOS reaches `cargo-binstall`; the failing component is
  Apple Security's acceptance of the extra root anchor, so the least invasive
  next step is to generate CA and server certificates with explicit X.509v3
  extensions, fixed short serials, and a fuller subject identity. Date/Author:
  2026-06-26, implementation agent.
- Decision: stop iterating on the macOS local HTTPS transport after Approach 1.
  Rationale: the first resumed approach made the hosted macOS, Windows, and
  Linux real install-and-run checks pass without weakening TLS validation, so
  the additional fallback approaches are unnecessary unless a later regression
  reopens the failure. Date/Author: 2026-06-26, implementation agent.
- Decision: split the release-time `binstall` audit into a blocking draft-asset
  audit and a post-publication URL audit. Rationale: the draft-asset audit can
  fail the workflow before a broken release becomes public while still using
  the exact assets uploaded to GitHub; the post-publication dry-run then
  verifies the public `pkg-url` template once those URLs exist. Date/Author:
  2026-06-26, implementation agent.
- Decision: fix the `binstall` install-and-run failure by adding real
  `--version` handling in the setup binary instead of passing GitHub
  credentials or PostgreSQL cache state into the packaging job. Rationale: the
  plan's observable contract says the packaging job runs the installed binary's
  `--version`; a version command should not depend on PostgreSQL discovery,
  network access, or bootstrap configuration. Date/Author: 2026-06-26,
  implementation agent.
- Decision: do not add a bespoke Python `binstall` self-test unless the
  reuse-first evaluation shows the shared action plus a small Rust/CI check is
  insufficient; if one is added, it follows the df12 scripting standards.
  Rationale: importing a full Python (uv/cyclopts/cuprum/cmd-mox) substrate
  into a Rust+Make repo to assert an archive listing is disproportionate for a
  small maintainer team, and a renderer that re-implements the `binstall`
  template grammar can agree with itself while disagreeing with the real
  resolver. Date/Author: 2026-06-25, planning agent (incorporating review).
- Decision: target `x86_64-pc-windows-msvc` for Windows and both
  `aarch64-apple-darwin` and `x86_64-apple-darwin` for macOS; do not target
  `aarch64-pc-windows-msvc`. Rationale: MSVC is the standard distributable
  Windows ABI with upstream PostgreSQL binaries; theseus publishes both macOS
  arches; theseus publishes no arm64 Windows PostgreSQL binaries. Date/Author:
  2026-06-25, planning agent.
- Decision: macOS and Windows CI legs run the unprivileged in-process path and
  tests only; linting, formatting, Markdown lint, coverage, and CodeScene
  upload stay on a single Linux job. Rationale: the user's requirement ("the
  Windows and Mac CI branches should run tests only"); lint/format results are
  platform-independent; `upload-codescene-coverage` has no Windows path.
  Date/Author: 2026-06-25, planning agent.
- Decision: keep `pkg-fmt = "tgz"` for Linux, macOS, and Windows; do not add a
  Windows `zip` override. Rationale: cargo-binstall supports `tgz` on Windows,
  the existing `bin-dir` template already appends `{ binary-ext }`, and one
  archive format keeps both production binaries in a single package.
  Date/Author: 2026-06-25, implementation agent.
- Decision: bump the `leynos/shared-actions` pin to the current default-branch
  HEAD `7da7c6d89033d13cbb1c64803d108ddca97e69c2` across all workflows.
  Rationale: a clean fast-forward that picks up the tri-platform actions; keep
  one consistent pin. (Verify the SHA at implementation time; if it has
  advanced, pin to the then-current HEAD and note it here.) Date/Author:
  2026-06-25, planning agent.
- Decision (recorded, not adopted): a viable alternative is library-only
  Windows/macOS support with no `binstall` binaries, dropping Milestones 3-4.
  Rejected because the user explicitly requested `cargo binstall` support for
  both platforms; kept on record because the CLI's headline value (privilege
  drop) is Linux-only, so if that requirement is ever relaxed this is the
  80/20. Date/Author: 2026-06-25, planning agent (Wafflecat alternative).
- Decision: proceed from draft to implementation on 2026-06-25 after the user
  explicitly requested implementation of this plan. Rationale: the execplans
  workflow requires approval before implementation; the user's request supplies
  that approval and also requires the plan to remain current during execution.
  Date/Author: 2026-06-25, implementation agent.
- Decision (rejected after validation): resolve OpenSSL portability by switching
  `postgresql_embedded` from default native TLS to explicit `rustls` support.
  Rationale for trying it: Milestone 0 proved vendored OpenSSL blocks all three
  target checks before source diagnostics, and `postgresql_embedded`/
  `postgresql_archive` both expose `rustls` feature flags for the same archive
  download path. Rejection rationale: the resulting `ring`/`aws-lc-sys` graph
  required additional Windows build tools during the Linux-hosted cross-check,
  breaching the dependency tolerance. Date/Author: 2026-06-25, implementation
  agent.
- Decision: resolve OpenSSL portability by removing only the crate's direct
  vendored `openssl-sys` dependency and keeping `postgresql_embedded` on native
  TLS. Rationale: without the direct vendored dependency, Windows and macOS use
  platform TLS and no longer build OpenSSL in the cross-target checks; Linux
  keeps the native OpenSSL path covered by the existing Linux gates. This
  avoids adding runtime crates or runner build tools while satisfying all three
  `cargo check --target ... --all-targets` checks with `-D warnings`.
  Date/Author: 2026-06-25, implementation agent.
- Decision: implement the Windows shared-cluster reaper without adding a direct
  `windows-sys` dependency. The hook uses the existing `libc::atexit`
  registration, `taskkill /PID <pid> /T` followed by
  `taskkill /PID <pid> /T /F` on timeout, and a private `kernel32` FFI wrapper
  only for liveness probing. Rationale: this preserves the public API, honours
  the no-new-runtime dependency tolerance, and kills the PostgreSQL process
  tree rather than only the postmaster process. Date/Author: 2026-06-25,
  implementation agent.
- Decision: replace the Windows reaper's `taskkill` shell-out with direct
  Win32 process-tree termination, still without adding `windows-sys`. The hook
  enumerates descendants with a Toolhelp process snapshot, terminates children
  before the postmaster with `TerminateProcess`, and waits briefly on each
  handle. Rationale: hosted Windows CI proved `taskkill` was not dependable
  inside the atexit path, while adding a Windows crate would breach the plan's
  dependency tolerance. Date/Author: 2026-06-25, implementation agent.
- Decision: continue past the original two-attempt Windows cleanup tolerance
  after explicit user approval on 2026-06-25. Try up to four additional
  approaches, recording each in this ExecPlan and validating with the hosted
  Windows orphan-detection test. Rationale: the original tolerance correctly
  forced escalation before a third cleanup strategy; the user has now supplied
  the required direction to keep iterating. Date/Author: 2026-06-25,
  implementation agent.
- Decision: make the third Windows cleanup approach a Job Object failsafe
  rather than another command executed from the atexit callback. Rationale:
  assigning the postmaster tree to a kill-on-close job gives the operating
  system an exit-time handle to close even if the callback does not run, cannot
  acquire state, or cannot finish process termination. Date/Author: 2026-06-25,
  implementation agent.
- Decision: require Windows cleanup to verify the live postmaster identity
  before Job Object assignment or process termination. Rationale: a PID-only
  cleanup path can target an unrelated process after PID reuse; comparing the
  expected PostgreSQL start timestamp from `postmaster.pid` with the live
  process creation time keeps cleanup conservative without changing public
  APIs. Date/Author: 2026-06-25, implementation agent.
- Decision: serialize the shutdown-hook integration tests with the existing
  scenario guard instead of treating "data directory exists but is not empty"
  as a soft skip. Rationale: that error is expected only under concurrent use
  of the shared test cluster directory; serializing preserves the regression
  value of the orphan-detection test and keeps failures meaningful on CI
  runners. Date/Author: 2026-06-25, implementation agent.
- Decision: implement the non-Unix scenario process lock as a lock directory
  with a bounded wait instead of adding a test dependency or using another FFI
  boundary. Rationale: directory creation is atomic on the supported
  filesystems and works on Windows runners, while the existing Unix `flock`
  path remains unchanged. Date/Author: 2026-06-25, implementation agent.
- Decision: make the new macOS and Windows CI test legs required by the
  workflow rather than advisory. Rationale: the purpose of this change is to
  prove unprivileged `TestCluster` execution and orphan cleanup on those
  platforms; advisory legs would not protect the promised support boundary.
  Initial cost budget is approximately `42` runner-minutes per pull request:
  Linux unprivileged about `14`, Linux root about `8`, macOS about `10`, and
  Windows about `10`, with a parallel wall-clock target under `15` minutes.
  Date/Author: 2026-06-25, implementation agent.
- Decision: pin the cross-platform CI tests to `PG_VERSION_REQ="=17.4.0"` and
  cache `PG_BINARY_CACHE_DIR` by PostgreSQL version, runner OS, and runner
  architecture. Rationale: the plan requires mandatory theseus download caching
  keyed by pinned PostgreSQL version; setting the version in CI avoids a broad
  cache key that silently changes when upstream defaults move. Date/Author:
  2026-06-25, implementation agent.
- Decision: gate root-specific privilege tests to the same root-capable Unix
  target set as the public `nobody_uid` and directory ownership helpers.
  Rationale: macOS support is the unprivileged in-process path; compiling
  Linux/BSD owner-changing tests there contradicts the existing public API
  boundary and fails before runtime skips can apply. Date/Author: 2026-06-25,
  implementation agent.
- Decision: gate the non-UTF-8 worker PATH-entry fixture off macOS while
  leaving it active on Unix targets that can create the raw-byte path
  component. Rationale: the test is meant to validate bootstrap handling of a
  non-UTF-8 `PATH` entry after the filesystem object exists; on macOS the
  filesystem rejects the fixture path first, so the failure does not test
  product behaviour. Date/Author: 2026-06-25, implementation agent.
- Decision: gate `staged_worker_is_world_executable_and_in_temp_dir` to the
  same root-capable Unix target set as the public `nobody_uid` helpers and
  compare cache directory expectations as `Utf8PathBuf` values. Rationale:
  macOS support is the unprivileged in-process path, so root/nobody traversal
  checks should not run there; Windows path tests should assert the semantic
  path chosen by `resolve_cache_dir`, not the separator spelling of a POSIX
  string. Date/Author: 2026-06-25, implementation agent.

## Outcomes & retrospective

The implemented change satisfies the plan's observable pull-request scope:
Linux, macOS, and Windows all build the production binaries, run the
unprivileged `TestCluster` surface, exercise the shared-cluster
orphan-detection scenario, build a local `cargo-binstall` archive, perform a
real install from that archive, confirm both binaries were placed, and run the
installed setup binary's `--version` without entering PostgreSQL bootstrap.
Hosted CI proved this in runs `28215731121` and `28218770776`.

The Windows cleanup implementation converged on a Job Object failsafe with
direct process-tree termination and PID plus PostgreSQL start-time identity
checks. That approach is now the accepted design because hosted Windows CI
proved it prevents the orphaned postmaster seen in earlier `taskkill` and
direct-termination attempts.

The release-time asset audit is implemented in `release.yml` and blocks draft
publication by downloading the uploaded draft assets, dry-running all supported
targets, and real-installing the host asset. That path necessarily runs against
real GitHub release assets on the next release tag rather than during this pull
request.

## Context and orientation

This section assumes no prior knowledge of the repository.

`pg-embed-setup-unpriv` is a Rust crate (edition 2024, `rust-version = 1.85`,
package version `0.5.1`) that provides zero-configuration PostgreSQL test
fixtures. Its central type, `TestCluster`, starts an embedded PostgreSQL server
on construction and stops it on drop. The embedded server comes from the
`postgresql_embedded` crate (version 0.20.2, `tokio` feature), which downloads
prebuilt PostgreSQL binaries at runtime from the theseus release host and
caches them under the user's home directory. The download requires outbound
network and benefits from `GITHUB_TOKEN` to avoid `api.github.com` rate limits.

The crate has two privilege modes. On Linux it can run as root, delegating
filesystem work to a `pg_worker` subprocess that drops to the `nobody` account
using `nix`/`libc`. When unprivileged, it runs entirely in-process. macOS and
Windows only ever use the in-process, unprivileged path; the privilege-drop
machinery is intentionally gated to Linux and the BSDs.

Key files and their current platform posture (verified against HEAD):

- `src/lib.rs` — crate root. Lines 16-231 gate the `privileges` module and its
  re-exports to Linux/BSD. `mod fs;` (line 14) is unconditional.
- `src/fs.rs` — capability-based filesystem helpers. Unconditionally imports
  `cap_std::fs::PermissionsExt` (line 7) and calls `Permissions::from_mode`
  (line 159), both Unix-only in cap-std. Reached on the unprivileged path. This
  is the genuine unconditional Windows compile blocker.
- `src/cluster/mod.rs` — `#[cfg(unix)] mod shutdown_hook;` (lines 61-62);
  `process_is_running`/`read_postmaster_pid` re-exports gated (lines 63-67).
  Already correct for Windows compilation.
- `src/cluster/handle.rs` — `register_shutdown_on_exit_impl` delegates to the
  cross-platform shutdown hook path. Unix uses the existing POSIX `atexit`
  /signal reaper; Windows registers a Job Object failsafe plus direct
  process-tree termination guarded by PostgreSQL process identity checks.
- `src/cluster/shutdown_hook/` — POSIX and Windows cleanup implementations live
  behind a platform facade. Public helper signatures remain unchanged; Windows
  parses `postmaster.pid` into PID plus start timestamp to avoid PID-reuse
  mistakes.
- `src/test_support/shared_singleton.rs` — provides
  `shared_cluster()`/`shared_cluster_handle()`, which call
  `register_shutdown_on_exit` and `std::mem::forget` the guard. This is the
  path validated by the cross-platform orphan-detection test.
- `Cargo.toml` — `nix` is Unix-only, the dead direct `xdg` dependency and direct
  vendored `openssl-sys` dependency are removed, and
  `[package.metadata.binstall]` retains one `.tgz` layout for every supported
  target.
- `tests/settings.rs` — root-specific assertions are gated to root-capable Unix
  targets, while the remaining settings tests compile everywhere.
- `.github/workflows/ci.yml` — Linux root/unprivileged jobs remain the
  authoritative lint/test/coverage path; macOS and Windows test-only jobs run
  the unprivileged surface; a `binstall` job builds a local archive per OS,
  performs a real install from local HTTPS, checks both binaries, and runs the
  installed CLI.
- `.github/workflows/release.yml` — on `v*`, `build-assets` publishes Linux
  x86-64, Linux arm64, Windows x86-64, macOS arm64, and macOS Intel archives by
  calling `scripts/release_archive.py`, then uploads `dist/*.tgz`. Before
  publication, `audit-draft-assets` downloads those uploaded assets, dry-runs
  `cargo-binstall` for all five targets, and real-installs the host target on
  each release runner. After publication, `verify-published-assets` dry-runs
  the public GitHub release URLs.
- `Makefile` — `release-archive` validates `TARGET`/`VERSION` and delegates to
  `scripts/release_archive.py` for the cross-platform archive layout.
- `.config/nextest.toml` — `global-timeout = "10m"`; a `serial` test group; a
  30s cap on the `settings` binary.

External facts established during research:

- cargo-binstall template variables resolve per target: `{ binary-ext }` is
  `.exe` on Windows, empty elsewhere; `{ archive-suffix }` derives from
  `pkg-fmt`. Per-target overrides under
  `[package.metadata.binstall.overrides.<target-or-cfg>]` may override
  `pkg-url`, `pkg-fmt`, and `bin-dir`; exact target names beat `cfg(...)`
  expressions, and multiple matching `cfg` expressions evaluate in declaration
  order.
- `cargo binstall` flags for CI: `--dry-run` (resolve+fetch, no install — does
  not extract), `--manifest-path`, `--targets <triple>`,
  `--strategies crate-meta-data` (use only package metadata so a fallback
  cannot mask a broken URL), `--install-path <dir>`, `--no-confirm`,
  `--github-token`.
- Runners: `windows-latest` = `windows-2025` (x64); `macos-latest` = `macos-15`
  on Apple Silicon (arm64); current standard Intel macOS labels include
  `macos-15-intel` and `macos-26-intel`. Windows-on-ARM runners exist but have
  no upstream PostgreSQL binaries.

## Plan of work

Six milestones with explicit go/no-go validation at each boundary. Do not start
a milestone before the previous validates green on Linux.

### Milestone 0 — Prototype: observe the real compile blockers (gating)

This is the de-risking gate, and it must run *first and for real*. It validates
`cfg`-resolution only; it does not validate linking (vendored OpenSSL needing
Perl/NASM, `pq-sys` libpq) or any runtime behaviour. Do not present a green
Milestone 0 as de-risking Milestones 2-3.

```bash
rustup target add x86_64-pc-windows-msvc x86_64-apple-darwin aarch64-apple-darwin
cargo check --target x86_64-apple-darwin   --all-targets 2>&1 | tee /tmp/check-darwin.out
cargo check --target aarch64-apple-darwin  --all-targets 2>&1 | tee /tmp/check-darwin-arm.out
cargo check --target x86_64-pc-windows-msvc --all-targets 2>&1 | tee /tmp/check-windows.out
```

Record every distinct error in `Surprises & discoveries` and rewrite the Risk
register to match. Confirm or refute: `fs.rs` mode blocker, `nix` in the
Windows graph, `tests/settings.rs` `nix` import, the dead `xdg` crate, and
whether `openssl-sys` is even pulled in. Go/no-go: a written, observed blocker
list. If it exceeds the Milestone 1 scope tolerance, stop and escalate.

### Milestone 1 — Compile and cleanup correctly on Windows and macOS

Scope is whatever Milestone 0 observed; the tasks below are the expected set.

1. Reorganize dependencies in `Cargo.toml`: move `nix` to
   `[target.'cfg(unix)'.dependencies]`; remove the dead direct `xdg`
   dependency; remove the direct vendored `openssl-sys` dependency; keep
   `postgresql_embedded` on native TLS because the `rustls` attempt required
   extra Windows build tools during cross-checking. Keep caret requirements.

2. Gate `src/fs.rs`: apply `Permissions::from_mode`/`PermissionsExt` only under
   `#[cfg(unix)]`; provide a Windows no-op (or access-control equivalent) that
   preserves the function signatures. Add a code comment and a users'-guide
   note that POSIX `0o700` privacy is not enforced on Windows.

3. Audit the `tests/` tree for top-level Unix-only imports. Gate
   `tests/settings.rs:7` (`use nix::unistd::geteuid;`) and its dependent bodies
   with `#[cfg(unix)]`; fix any others found. Re-run the Milestone 0
   cross-checks until clean.

4. Resolve Windows shared-cluster cleanup (the behavioural task). Add an
   orphan-detection integration test (host-gated) that takes the
   `shared_singleton` path, `mem::forget`s the guard, exits the process, and
   asserts from a parent harness that the postmaster PID is no longer alive.
   - Red: the test fails on Windows (no-op hook leaks the postmaster).
   - Green: implement a real Windows reaper — register a process-exit cleanup
     using Win32 Job Objects (kill-on-close) or `OpenProcess`+`TerminateProcess`
     reading the postmaster PID — keeping `register_shutdown_on_exit`'s signature
     identical across platforms. If, instead, Milestone 0/analysis proves no
     supported cross-platform test path forgets a guard, encode that as the test
     (assert Drop reaps it) and document the limitation rather than adding a
     reaper. Record which branch was taken in the Decision log.
   - Note: macOS is Unix, so the existing POSIX hook already compiles and runs
     there; this task is Windows-specific.

5. Confirm both declared binaries (`pg_embedded_setup_unpriv` and `pg_worker`)
   compile on all platforms; `pg_worker`'s non-Unix `main` stub remains.

Go/no-go: the three cross-checks pass; the Linux gateway is unchanged and
green; and one *real* Windows link-and-run is exercised before proceeding — a
throwaway `workflow_dispatch` job on `windows-latest` that builds the crate and
starts a single `TestCluster` — so link/runtime surprises (OpenSSL, `pq-sys`,
theseus download, TCP sockets, the new reaper) land while the change set is
still small. Commit per atomic change.

### Milestone 2 — Test-only macOS and Windows CI matrix

Extend `.github/workflows/ci.yml`. Keep the rich Linux job authoritative (it
owns format, Markdown lint, Clippy, coverage, CodeScene) and add a lean
cross-platform job. Prefer the `rust-toy-app.yml` matrix shape from
`shared-actions` as the template.

```yaml
strategy:
  fail-fast: false
  matrix:
    include:
      - os: macos-latest      # aarch64-apple-darwin (Apple Silicon)
      - os: windows-latest    # x86_64-pc-windows-msvc
runs-on: ${{ matrix.os }}
```

Each leg: check out; run `leynos/shared-actions/.github/actions/setup-rust`
(bumped pin); restore a **mandatory** `actions/cache` for the theseus
PostgreSQL download keyed on the pinned PostgreSQL version + OS + arch; run the
unprivileged test suite plus the orphan-detection test. Pass `GITHUB_TOKEN`. Do
not run lint, format, coverage, or CodeScene upload. Add `concurrency:`
cancellation for superseded pushes to bound cost. Choose feature sets
deliberately and symmetrically:

- macOS and Windows both start with
  `--no-default-features --features cluster-unit-tests,async-api` (the
  unprivileged surface, no `diesel-support`), so neither pays the `pq-sys`
  libpq-from-source build at first. Enabling `diesel-support` (and thus the
  `test_cluster_connection` test) on each platform is a deliberate, separately
  budgeted follow-up; record whether it builds. Do not silently use
  `--all-features` on macOS — that pulls `pq-sys` at ~10x billing.
- Install `cargo-nextest` the same way the Linux job does
  (`cargo binstall -y cargo-nextest@<pinned>`), which works on Windows and
  macOS.

Record an expected per-PR CI-minute budget (Linux ×2 privilege + macOS +
Windows) and a wall-clock target. Confirm the `.config/nextest.toml` 10-minute
global timeout still holds once the (cached) PostgreSQL start time is included;
warm the cache in a prior step if needed. Decide and document whether the new
legs are required or advisory.

Go/no-go: macOS and Windows legs (including orphan detection) are green on a
pull request; the Linux job is unchanged and green; the cost budget is recorded.

### Milestone 3 — binstall packaging for macOS and Windows

1. Keep the existing `Cargo.toml` `[package.metadata.binstall]` block:
   `pkg-url`, `bin-dir`, and `pkg-fmt = "tgz"`. Do not add a Windows `zip`
   override. The `bin-dir` template already appends `{ binary-ext }`, yielding
   `pg_worker.exe` on Windows while the archive itself remains tar.gz.

2. Produce the archives with `scripts/release_archive.py`. The script builds
   the two production binaries, stages target-specific executable names, and
   writes a `.tgz` whose root directory matches the `bin-dir` template.
   `make release-archive` delegates to the script for local development, and
   GitHub workflows call the script directly so Windows does not depend on GNU
   Make being available.

3. Extend the `build-assets` matrix in `release.yml` to add
   `x86_64-pc-windows-msvc` (`windows-latest`), `aarch64-apple-darwin`
   (`macos-latest`), and `x86_64-apple-darwin` (`macos-15-intel`). Upload
   archives whose names exactly match the `pkg-url` template per target.

Go/no-go: each OS produces a correctly named archive whose internal layout
matches `bin-dir` (proven by Milestone 4's real install, not just by
inspection).

### Milestone 4 — Validate binstall by real install-and-run

1. Pull-request-time real install. On each of `ubuntu-latest`, `macos-latest`,
   and `windows-latest`, build the archive (via the same code path as the
   release job), then run a real, non-dry-run install into a scratch directory
   and execute the installed binary:

   ```bash
   cargo binstall --manifest-path Cargo.toml --targets <host-triple> \
     --strategies crate-meta-data --install-path "$tmp" --no-confirm \
     pg-embed-setup-unpriv
   "$tmp/pg_embedded_setup_unpriv" --version   # .exe on Windows
   ```

   This proves extraction and `bin-dir` placement on the real OS — the failure
   `--dry-run` cannot catch. The implemented mechanism points cargo-binstall at
   the locally built archive by serving `dist/` over local HTTPS with a
   throwaway CA and passing that CA through `--root-certificates`; plain
   `http://` and `file://` package URLs are rejected by this cargo-binstall
   build.

2. Release-time breadth audit. After `build-assets`, on each OS, loop
   `cargo binstall --manifest-path Cargo.toml --targets <triple> --strategies crate-meta-data --github-token "$GITHUB_TOKEN" --no-confirm --dry-run pg-embed-setup-unpriv`
   over all supported triples to confirm every published URL resolves, plus
   one real install-and-run of the host target's asset.

Go/no-go: the real install-and-run passes on all three OSes at PR time, and the
release audit passes against the real assets.

### Milestone 5 — Documentation and finalization

Update the README install section to a platform/target matrix stating macOS
(arm64 and x86-64) and Windows (x86-64) support, the `cargo binstall` command,
the Windows-on-ARM limitation, and the Windows file-mode-privacy caveat. Update
`docs/users-guide.md` and `docs/roadmap.md` (appendix and item 3.3.2 — now
validated in CI), and update
`docs/zero-config-raii-postgres-test-fixture-design.md` with the Windows
cleanup/reaper decision and the `fs.rs` mode-gating decision. Run `make fmt`,
`make markdownlint`, and `make nixie`, then the full gateway. Mark the plan
COMPLETE in `Outcomes & retrospective`.

## Concrete steps

Run from the repository root. Capture long outputs with `tee` to
`/tmp/<action>-<branch>.out` per the project command guidance.

1. Milestone 0 cross-checks (commands in the Milestone 0 section).
2. After each code change, on Linux:

   ```bash
   make check-fmt 2>&1 | tee /tmp/fmt-windows-mac-support-validation.out
   make lint      2>&1 | tee /tmp/lint-windows-mac-support-validation.out
   make test      2>&1 | tee /tmp/test-windows-mac-support-validation.out
   ```

3. After documentation changes:

   ```bash
   make fmt
   make markdownlint 2>&1 | tee /tmp/mdlint-windows-mac-support-validation.out
   make nixie        2>&1 | tee /tmp/nixie-windows-mac-support-validation.out
   ```

4. Record here, as observed: the Milestone 0 blocker list; the throwaway
   Windows link-and-run run URL; the green macOS/Windows/Linux CI URLs; the
   recorded CI-minute budget; and the binstall install-and-run output per OS.

This section must be updated with real transcripts and URLs as work proceeds.

## Validation and acceptance

Acceptance is behavioural and observable:

- Library portability:
  `cargo check --target x86_64-pc-windows-msvc --all-targets`,
  `--target x86_64-apple-darwin`, and `--target aarch64-apple-darwin` all
  complete without error after Milestone 1, with the dead `xdg` dependency
  removed and `nix` Unix-gated.
- Cleanup correctness: the orphan-detection test fails on Windows before the
  fix (Red — leaked postmaster) and passes after (Green — no orphan), and runs
  in the cross-platform matrix.
- CI matrix: on a pull request, the macOS (`macos-latest`) and Windows
  (`windows-latest`) legs run `cargo nextest` and the orphan-detection test to
  green, exercising the unprivileged in-process `TestCluster` path; they run
  tests only. The Linux job remains green and unchanged in scope. A recorded CI
  budget exists.
- binstall (real): on each OS, `cargo binstall --install-path <tmp>` installs
  the CLI and the installed binary runs `--version` successfully. The
  release-time dry-run audit resolves all five supported triples.
- Scope honesty: the Windows `diesel-support`/`pq-sys` path and Intel-macOS
  execution are explicitly documented as validated-later or
  resolve-only-not-executed, not silently implied as covered.
- Documentation: README, users' guide, and roadmap describe supported platforms,
  the Windows-on-ARM limitation, and the file-mode-privacy caveat;
  `make markdownlint` and `make nixie` pass.

Quality criteria ("done"):

- Tests: full `make test` passes on Linux; macOS and Windows nextest legs plus
  orphan detection pass in CI.
- Lint/typecheck: `make lint` and `make check-fmt` pass on Linux with the
  existing `-D warnings` ceiling; no new `allow` attributes without a scoped
  reason.
- Packaging: `cargo binstall` installs and runs the CLI on all three OSes.

Quality method: the CI workflows above are the automated check; the
orphan-detection Red→Green test and the real binstall install-and-run are the
behavioural checks for the two genuinely new behaviours.

## Idempotence and recovery

Adding `rustup` targets, editing workflows, editing `Cargo.toml` metadata,
removing a dead dependency, and adding tests are all idempotent and
re-runnable. The release dry-run audit installs nothing; the real install
targets a scratch directory. If a CI leg fails, re-running the workflow is
safe. If archive naming is wrong, fix the metadata/packaging and re-run; no
production state is mutated by validation. Keep the working tree clean: remove
`/tmp` logs and any throwaway tags or `workflow_dispatch` artefacts after use.

## Artefacts and notes

Capture as the work produces them: the Milestone 0 cross-compile transcripts;
the first green Windows and macOS nextest runs; the orphan-detection test
output; the resolved `binstall` URLs and the real install-and-run output per
target; and the recorded CI-minute budget. The `shared-actions`
`rust-toy-app.yml` matrix is the canonical cross-OS reference.

## Interfaces and dependencies

- `Cargo.toml` dependency changes: move `nix` to
  `[target.'cfg(unix)'.dependencies] nix = { version = "0.30.1", default-features = false, features = ["user", "fs"] }`;
  remove the dead direct `xdg = "3"`; remove the direct vendored `openssl-sys`
  dependency; keep
  `postgresql_embedded = { version = "0.20.2", features = ["tokio"] }` on its
  default native-TLS backend. No new runtime crates are expected (a Win32
  reaper can use `std`/`windows-sys` only if Milestone 1 shows it necessary —
  adding `windows-sys` would be a new dependency and triggers the dependency
  tolerance, so escalate before adding it).
- `src/fs.rs`: keep `set_permissions`/`ensure_dir_exists` signatures unchanged;
  apply mode bits only under `#[cfg(unix)]`.
- `src/cluster/shutdown_hook.rs` and `register_shutdown_on_exit`: no
  cross-platform signature change. The module is already `cfg(unix)`-gated and
  its `libc::pid_t` parameters never reach Windows. Do not introduce a `pid_t`→
  `i32` rename (the earlier draft's suggestion); it is unnecessary and would
  churn the Unix-only re-exports.
- New non-Unix cleanup: `register_shutdown_on_exit` must, on Windows, register a
  real process-exit reaper (preferred: a Job Object created at cluster start so
  the postmaster is killed on handle close), preserving the existing
  `fn register_shutdown_on_exit(&self) -> BootstrapResult<()>` signature.
- `Cargo.toml` `[package.metadata.binstall]`: retain `pkg-url`, `bin-dir`,
  and `pkg-fmt = "tgz"` for every supported target. Do not add a Windows
  override unless a future cargo-binstall version requires it.
- New build targets to publish: `x86_64-pc-windows-msvc`, `x86_64-apple-darwin`,
  `aarch64-apple-darwin`, alongside the existing two Linux targets.
- GitHub Actions: reuse `leynos/shared-actions` `setup-rust`, pinned to the
  bumped SHA; add `actions/cache` for the theseus download. Never run
  `upload-codescene-coverage` on Windows/macOS.
- `scripts/release_archive.py`: build both production binaries for the requested
  target and package them in the cargo-binstall `.tgz` layout. Keep tests in
  `scripts/tests/test_release_archive.py`.

## Revision note

Revision 2 (2026-06-25), after a Logisphere community-of-experts design review.
What changed and why:

- Corrected a load-bearing factual error: `src/cluster/shutdown_hook.rs` is
  already `#[cfg(unix)]`-gated (`mod.rs:61`) with a `#[cfg(not(unix))]` no-op
  (`handle.rs:325-330`), so it is not a Windows compile blocker. Removed the
  "port shutdown_hook / TerminateProcess / Red-Green shutdown-hook compile" and
  the `pid_t`→`i32` workstreams.
- Replaced the wrong primary blocker with the real ones: `src/fs.rs`
  (cap-std `PermissionsExt`/`from_mode`), the unconditional `nix` dependency,
  the unconditional `use nix::unistd::geteuid;` in `tests/settings.rs`, and the
  apparently-dead Unix-only `xdg` crate. Added a `tests/` audit.
- Added the genuine new risk the original missed: the non-Unix no-op shutdown
  hook leaves `mem::forget` shared clusters unreaped on Windows (orphaned
  postmaster). Reframed the Windows work as behavioural cleanup proven by an
  orphan-detection Red→Green test.
- Strengthened binstall validation from `--dry-run` (which does not extract) to
  a real install-and-run per OS; flagged the three coupled packaging edit sites.
- Made theseus download caching mandatory (not "where practical"), added a CI
  cost budget and concurrency cancellation, and made the macOS/Windows feature
  sets symmetric so macOS does not silently build `pq-sys` via `--all-features`.
- Flipped the packaging default to reuse
  `shared-actions/stage-release-artefacts` and the `rust-toy-app.yml` matrix;
  demoted the bespoke Python self-test to a last resort (still df12-compliant
  if needed). This revision note is historical; Milestone 3 later superseded
  the staging-action path after implementation inspection found it packaged
  only one binary.
- Reframed Milestone 0 as `cfg`-resolution-only de-risking and pulled one real
  Windows link-and-run into the Milestone 1 exit gate.

How it affects remaining work: Milestone 1's scope shifts from a non-existent
compile port to `fs.rs`/dependency gating plus a Windows reaper; the tolerances
were re-baselined accordingly. No implementation has begun; Status is DRAFT
pending review.

Revision 3 (2026-06-25), at implementation start. What changed and why:

- Marked the ExecPlan `IN PROGRESS` after explicit user approval to proceed.
- Added a timestamped Milestone 0 progress entry and decision-log note so a
  future reader can distinguish approved implementation work from the earlier
  planning-only pull request.

How it affects remaining work: Milestone 0 must still run first and re-ground
the risk list from observed cross-target compiler output before Milestone 1
code changes begin.

Revision 4 (2026-06-26), after review-finding validation. What changed and why:

- Verified the latest inline and outside-diff findings against the current
  branch. All listed items except the already-documented `read_postmaster_pid`
  helper still had a current-code manifestation and were addressed with narrow
  changes.
- Added explicit `uv` setup to the release workflow before invoking
  `scripts/release_archive.py`, keeping `uv run --script` as the Python 3.13
  provisioning boundary.
- Preserved cargo wrapper arguments in the release archive builder by splitting
  the configured Cargo command before appending the `build` subcommand.
- Clarified macOS root fail-fast behaviour separately from Windows and other
  unprivileged in-process paths in the design docs.
- Kept non-Unix worker-env coverage active by moving pure staging-directory and
  pointer-file helper tests out from behind the Unix-only module gate while
  leaving permission assertions Unix-specific.
- Hardened the non-Unix serial lockdir fallback by treating a newly-created
  lock directory without an owner file as active for a short grace period, so a
  competing process does not reap a live lock before the owner file is written.

Validation recorded for this pass: `make check-fmt`, `make markdownlint`,
`make nixie`, `make lint`, `make test`, release archive pytest with the script
dependencies provisioned by `uv`, Windows and macOS narrow cross-target checks,
`git diff --check`, and `coderabbit review --agent` with zero findings.

Revision 5 (2026-06-28), after the latest review-finding validation. What
changed and why:

- Verified the new inline and outside-diff comments against the current branch.
  The synchronous-test documentation fragment, Cargo wrapper parsing, Windows
  Job Object root-assignment gating, non-Unix serial-lock module structure, and
  CLI argument pre-scan findings were still valid and were fixed.
- Updated `scripts/release_archive.py` so wrapper-style Cargo commands are
  tokenized before path classification, preserving absolute wrapper paths and
  retaining the existing unquoted Windows executable-path behaviour.
- Split the non-Unix serial lockdir owner-state and liveness implementation into
  `tests/support/serial/non_unix.rs`, leaving the shared serial fixture API in
  `tests/support/serial.rs`.
- After CodeRabbit review, changed non-Unix owner-file writes to use exclusive
  `create_new` semantics and made stale-lock deletion failures fall through the
  normal retry/deadline path.
- Changed Windows Job Object setup so descendant assignment remains best-effort
  but a root assignment failure prevents the failsafe from being armed.
- Replaced the manual `args_os()` help/version scan in `src/main.rs` with
  normal Clap parsing so help and version rendering come from the command
  definition.

Validation recorded for this pass: release archive pytest via `uv`, targeted
CLI tests, `make check-fmt`, `make markdownlint`, `make nixie`, `make lint`,
`make test`, `git diff --check`, and `coderabbit review --agent` with zero
findings. A local `cargo check --target x86_64-pc-windows-msvc` was attempted
but blocked before project code by missing Windows-target OpenSSL/vcpkg
configuration on the Linux host; GitHub CI remains the Windows validation path.

Revision 6 (2026-06-28), after observing CI for commit
`6fc01814335310fb4f71bf4270ee7ae4bda1bba8`. What changed and why:

- Observed the GitHub Actions matrix after pushing Revision 5. Linux root,
  Linux unprivileged, and macOS test jobs passed; the Windows test job failed
  during the unprivileged-surface test build because `tests/support/serial.rs`
  exposed Unix-only imports (`PathBuf` and the `rstest` attribute macro import)
  to the non-Unix target.
- Narrowed those imports with `#[cfg(unix)]`, keeping the shared serial fixture
  API unchanged and leaving the extracted non-Unix lock implementation intact.

Validation recorded for this pass: `make check-fmt`, `make lint`, and
`make test` passed locally. After pushing the import-gating fix, GitHub Actions
run `28313449771` passed on Linux, macOS, Windows, and all binstall jobs; the
workflow self-test run `28313449776` also passed.

Revision 7 (2026-06-28), after final architecture-check validation. What
changed and why:

- Verified the remaining Unit Architecture and Developer Documentation findings
  against the current branch. The manifest-version error-surfacing finding, the
  non-Unix serial-lock clock-coupling finding, and the stale unchecked progress
  item were still valid.
- Added a typed `ManifestVersionError` boundary in `scripts/release_archive.py`
  so manifest I/O, TOML parsing, missing keys, and invalid version types are
  reported through one explicit error that `main()` converts to the existing
  CLI abort path.
- Changed the non-Unix serial-lock owner grace calculation to take an explicit
  `SystemTime` in the state helper, preserving production behaviour while
  making stale-versus-pending decisions deterministic in tests.
- Marked the previously-unchecked "continue past the original tolerance"
  progress item complete so the ExecPlan status no longer conflicts with stale
  progress metadata.
- Evaluated the property-test and compile-time/UI warnings as broad follow-up
  recommendations rather than narrow correctness findings for this pass. The
  existing hosted macOS/Windows/Linux matrix remains the compile-time
  cross-platform gate for this PR, and adding new verification dependencies is
  deferred until a dedicated test-strategy change can size the scope.

Validation recorded for this pass: release archive pytest via `uv`,
`make check-fmt`, `make lint`, `make test`, `make markdownlint`, `make nixie`,
`git diff --check`, and `coderabbit review --agent` with zero findings after
retrying a silent first invocation.

Revision 8 (2026-06-29), after validating the remaining PR #153 failed-check
comments. What changed and why:

- Verified the release-archive docstring, Cargo wrapper parsing, and
  version-mismatch test comments against the current branch and applied the
  narrow fixes that still matched the code.
- Hardened workflow-dispatch release tags to the exact `vMAJOR.MINOR.PATCH`
  shape and passed the resolved release version through a quoted shell
  environment variable instead of interpolating it directly into the build
  command.
- Changed shutdown-hook postmaster readers to return explicit
  `BootstrapResult<Option<_>>` values, so missing PID files remain absence
  while file I/O and malformed PID data are logged as failures.
- Refactored the shutdown callback to clone the shutdown work item and release
  the global mutex before process lookup, shutdown requests, polling, forceful
  cleanup, and data-directory cleanup.
- Removed lint-appeasement anchors/suppressions in the touched shutdown-hook
  and test-support paths, replacing them with cfg-gating or behavioural tests.
- Added in-scope property, compile-time, and snapshot-style coverage for release
  path validation, postmaster PID parsing, test-support export compilation, and
  stable CLI help output.

Validation recorded for this pass: release archive pytest via `uv`,
`make check-fmt`, `make lint`, `make test`, `git diff --check`, and an attempted
`coderabbit review --agent`. The CodeRabbit CLI connected and began analysis
but then produced no output for several minutes, so only that stuck review
process was terminated after the deterministic gates had passed.

Revision 9 (2026-06-29), after observing the hosted CodeScene follow-up. What
changed and why:

- The first pushed Revision 8 commit passed the workflow self-test locally and
  on GitHub, but hosted CodeScene reported a remaining Complex Method finding in
  `scripts/release_archive.py::cargo_program_and_args`.
- Extracted the Windows `.exe` wrapper probe and path-like wrapper probe into
  private helpers, preserving the command parsing behaviour while reducing the
  public parser's branching.

Validation recorded for this pass: release archive pytest via `uv`,
`make check-fmt`, `make lint`, and `make test`.

Revision 10 (2026-06-29), after inspecting the hosted Windows test failure.
What changed and why:

- The Windows `Test unprivileged surface` job failed during test compilation
  because `proptest::prelude::*` was imported unconditionally while every
  property test using it is Unix-gated.
- Narrowed the `proptest` test import behind `#[cfg(unix)]`, preserving the
  Unix property coverage and removing the Windows unused-import failure.

Validation recorded for this pass: `make check-fmt`, `make lint`, and
`make test`.

Revision 11 (2026-06-29), after inspecting the second hosted Windows test
failure. What changed and why:

- The Windows `Test unprivileged surface` job reached the CLI snapshot test and
  failed only because Clap renders the binary name as
  `pg_embedded_setup_unpriv.exe` on Windows while the stable help text snapshot
  was recorded without the platform executable suffix.
- Normalized the Windows `.exe` suffix before the snapshot assertion, while
  keeping the semantic assertions against the real command output. This keeps
  the snapshot stable across Linux, macOS, and Windows without hiding the
  environment-variable help content that the test was added to cover.

Validation recorded for this pass: `make check-fmt`, `make lint`, and
`make test`.

Revision 12 (2026-06-29), after inspecting the third hosted Windows test
failure. What changed and why:

- The Windows `Test unprivileged surface` job no longer failed at the CLI help
  snapshot. The next failure was the `trybuild` UI harness timing out at
  nextest's 180-second per-test limit while compiling the isolated fixture
  dependency graph on Windows.
- Gated the `trybuild` compile-time harness to non-Windows platforms. Linux and
  macOS still exercise the feature-gated public test-support surface at compile
  time, while the Windows job keeps its direct normal test and binstall
  coverage without duplicating a slow isolated compile.

Validation recorded for this pass: `make check-fmt`, `make lint`, and
`make test`.

Revision 13 (2026-06-29), after verifying the release-archive docstring review
comment. What changed and why:

- Verified that `manifest_version` already used a full structured NumPy-style
  docstring, but other public functions in `scripts/release_archive.py` still
  had summary-only docstrings.
- Expanded the public function documentation in `scripts/release_archive.py`
  with `Parameters`, `Returns`, `Raises`, and `Examples` sections where
  applicable, while leaving private helpers as single-line summaries.

Validation recorded for this pass: release archive pytest via `uv`,
`python -m py_compile scripts/release_archive.py`, `make check-fmt`,
`make lint`, `make markdownlint`, `git diff --check`, and
`CARGO_BUILD_JOBS=1 NEXTEST_TEST_THREADS=1 make test`. Earlier full-test
attempts failed before executing tests because the shared machine could not
spawn nextest binaries (`Resource temporarily unavailable`, OS error 11); after
the lody cgroup PID pressure dropped, the single-threaded full gate passed.

Follow-up after the pushed review pass: CodeRabbit passed, but CodeScene failed
the commit on `scripts/release_archive.py::main` with a `Large Method`
diagnostic. The cause was the expanded public CLI docstring combined with the
inline Cyclopts `Annotated` metadata and orchestration body. The fix keeps the
public CLI behaviour intact, moves CLI metadata into private type aliases, and
delegates the release workflow to a private `_ReleaseCliSpec` plus
`_run_release_archive` helper so `main` remains a narrow entry point.
Validation for the follow-up fix: release archive pytest via `uv`,
`python -m py_compile scripts/release_archive.py`, `make check-fmt`,
`make lint`, `make markdownlint`, `git diff --check`, and
`CARGO_BUILD_JOBS=1 NEXTEST_TEST_THREADS=1 make test`.

Revision 14 (2026-06-29), after verifying the next review batch. What changed
and why:

- Made release-archive parser and command-construction helpers private because
  they are implementation details rather than public script interfaces; tests
  that intentionally cover wrapper parsing now reference the private helper
  directly.
- Escaped pytest `match=` patterns for path validation and Cargo version
  mismatch assertions so regular-expression metacharacters cannot broaden the
  expected failure.
- Updated shutdown hook callback work extraction to recover poisoned
  `SHUTDOWN_STATE` guards while still avoiding blocking when another thread
  holds the mutex.
- Reworded the package description and added an explicit CLI `about` string so
  help output describes cross-platform setup rather than Linux-only root/nobody
  privilege handling.
- Replaced local unsafe environment mutation wrappers in the shared-cluster
  failure test with the suite's scoped environment guard, and tightened the
  trybuild test-support export check to bind `read_postmaster_pid` to its exact
  public function signature.

Validation recorded for this pass:
`python -m py_compile scripts/release_archive.py`, release archive pytest via
`uv`,
`cargo test --test cli help_flag_prints_configuration_surface_without_bootstrap`,
`make check-fmt`, `make lint`, `make markdownlint`, `git diff --check`, and
`CARGO_BUILD_JOBS=1 NEXTEST_TEST_THREADS=1 make test`.

Revision 15 (2026-06-29), after verifying duplicate release-archive review
comments. What changed and why:

- Confirmed that `manifest_version` already documents `manifest_path : Path` in
  its NumPy-style public docstring, so that comment was stale.
- Confirmed that the version-mismatch test already uses scoped
  `pytest.raises(SystemExit, match=re.escape(...))`, so that duplicate comment
  was stale.
- Moved the Windows wrapper command parser ahead of POSIX `shlex.split()` so
  Windows `.exe` wrapper commands with arguments are recognized before
  backslashes can be interpreted by POSIX tokenization, while preserving the
  existing Unix wrapper and whole-path fallback ordering.

Validation recorded for this pass:
`python -m py_compile scripts/release_archive.py`, release archive pytest via
`uv`, and `git diff --check`.

Revision 16 (2026-06-29), after verifying the latest review batch. What changed
and why:

- Routed the release archive workflow target through a `TARGET` environment
  variable so the shell command no longer interpolates `matrix.target` directly.
- Confirmed the Windows cargo-wrapper ordering was already addressed, then
  added the remaining malformed-quote handling so bad `--cargo` values exit
  through a user-facing `SystemExit` path rather than a traceback.
- Updated shutdown hook registration to return `read_postmaster_process` errors
  before installing the atexit hook, and updated the atexit callback to skip
  best-effort cleanup when postmaster identity cannot be validated.
- Split the `parse_pid` proptest gating so positive and non-numeric parser
  properties run on Windows as well as Unix, while the non-positive signed PID
  property remains Unix-only.
- Replaced the Windows UI-test exclusion with a Windows smoke path that compiles
  the same `shutdown_hook_test_support.rs` imports/signature bindings without
  running the slow isolated trybuild compile on Windows.

Validation recorded for this pass:
`python -m py_compile scripts/release_archive.py`, release archive pytest via
`uv`, `cargo test --features dev-worker --test ui`, `make check-fmt`,
`make lint`, `make markdownlint`, `git diff --check`, and
`CARGO_BUILD_JOBS=1 NEXTEST_TEST_THREADS=1 make test`.

Revision 17 (2026-07-04), after re-checking the shared CI action baseline. What
changed and why:

- Superseded by Revision 19 after the shared CI action baseline advanced again.
  See that revision for the current `leynos/shared-actions` pin and
  `cargo-binstall` setup decision.

Revision 18 (2026-07-04), after verifying the shutdown-hook review findings.
What changed and why:

- Made the exported postmaster identity liveness query fallible so platform
  probe failures remain visible at the test-support API boundary. The atexit
  callback now owns the best-effort warning-and-continue policy instead.
- Switched the shutdown-hook lifecycle test's exit oracle to an independent
  OS-level PID probe while still parsing the full postmaster identity copied
  from the child process.
- Added Unix shutdown request/force logs and a shutdown-hook timeout escalation
  warning so hung postmaster cleanup has PID and timeout context in logs.
- Replaced Windows process-tree descendant validation scans with indexed
  PID-to-entry and parent-to-child lookups to avoid repeated full-list scans.
- Added release-archive coverage for `main(..., release_version=None)` so the
  manifest-version discovery path is exercised directly.

Revision 19 (2026-07-04), after re-checking the shared CI action baseline
again. What changed and why:

- Updated every `leynos/shared-actions` call site to the current default-branch
  SHA `d0fd973d07088c2120329a93035a5ba91e077014`, including `setup-rust`,
  coverage upload, CodeScene upload, and the Dependabot reusable workflow.
- Re-examined the local `setup-cargo-binstall` composite action. The current
  shared `setup-rust` action installs and verifies `cargo-binstall` `1.19.1` by
  default, so the local composite action and its explicit workflow steps are no
  longer necessary.