summaryrefslogtreecommitdiffstats
path: root/docs/FOG-PKI.md
blob: 4bc0ebdb713af813dbe0a9426cdbe6fbd30d5d1e (plain) (blame)
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
# FOG Public Key Infrastructure

Status: Draft 0.1

Date: 2026-08-08

## 1. Purpose

This document defines `FOG-PKI-1`, the normative directory, admission,
authority, consensus, revocation, topology, and transparency protocol for the
FOG network.

It refines the following baselines:

- `FOG-THREAT-MODEL.md`, especially `TM-NET-06`, `TM-PKI-01`,
  `TM-PKI-02`, `TM-PKI-03`, `TM-CRYPTO-01`, `TM-CRYPTO-02`, and
  `TM-AVAIL-01`;
- `FOG-ARCHITECTURE.md`, especially `ARC-005`, `ARC-007`, `ARC-008`,
  `ARC-009`, `IF-03`, `IF-04`, and `IF-05`.

FOG is not implemented. Requirements in this document are protocol targets,
not statements about deployed security.

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY describe
normative requirements in the sense of BCP 14 when they appear in uppercase.

## 2. Security Goals

FOG-PKI MUST provide:

- one complete authenticated network view for a given epoch;
- M-of-N authority approval over identical canonical consensus bytes;
- public attribution of every authority signature;
- deterministic topology and parameter derivation from public inputs;
- permissioned admission and public role assignment;
- purpose-separated current and future node public keys;
- explicit validity, freshness, grace, and hard-expiry semantics;
- monotonic state that detects rollback and same-epoch forks;
- append-only consistency evidence for long-offline Composers;
- bounded key overlap, rotation, revocation, and authority replacement;
- public operator-family constraints for route selection;
- bounded deterministic parsing and offline verification;
- auditable evidence for authority, node, and checkpoint equivocation.

FOG-PKI does not provide:

- permissionless Sybil resistance;
- proof that nominally different operators are independent;
- availability after authority quorum loss;
- trusted time to an endpoint with no reliable clock;
- secrecy for public topology or node addresses;
- safety after compromise of the configured authority threshold;
- automatic recovery from loss of the pinned authority roots;
- anonymity by itself.

## 3. Protocol Invariants

### PKI-INV-01: Independent quorum signatures

A valid consensus carries at least M valid signatures from distinct active
authorities over one identical canonical body. `FOG-PKI-1` does not use one
shared threshold private key.

### PKI-INV-02: Sign once per epoch

An authority MUST sign at most one consensus body hash for one network and
epoch. It MUST durably record that body hash before releasing its signature.

### PKI-INV-03: Full view only

Consumers MUST validate a full consensus. They MUST NOT merge descriptors,
signatures, topology, parameters, or revocations from different consensus
bodies.

### PKI-INV-04: Monotonic acceptance

A consumer MUST persist the highest accepted authority-set version, consensus
epoch, consensus hash, and transparency checkpoint. Older or conflicting state
MUST NOT replace it through an ordinary update.

### PKI-INV-05: Offline roots, online voting keys

Long-term authority root keys certify bounded-lifetime online voting keys.
Online voting keys sign routine protocol objects. Root private keys MUST NOT be
present on an online authority service.

### PKI-INV-06: No self-authorized algorithms

The signature and hash suite used to authenticate an object MUST be pinned by
already trusted state. An object MUST NOT select the algorithm by which its own
authenticity is decided.

### PKI-INV-07: One node identity, one role

One node identity has exactly one effective online role in an epoch. Layer
assignment is made by consensus, not self-declared by a node.

### PKI-INV-08: Fail closed at hard expiry

After consensus hard expiry, consumers MUST stop constructing new routes and
nodes MUST stop accepting new work under that consensus. Only explicitly
bounded drain and packet-lifetime behavior may continue.

### PKI-INV-09: Public decisions, minimal personal data

Admissions, assignments, suspensions, revocations, authority transitions, and
equivocation evidence are public. Personal names, private contact details,
credentials, and sensitive supporting evidence MUST NOT enter public PKI
objects.

### PKI-INV-10: No trust on first use recovery

Unknown authority, node, operator, mirror, witness, or replacement keys MUST
NOT become trusted because they are the only reachable keys.

## 4. Roles and Trust

### 4.1 Authority root operator

The root operator controls one authority root key in an offline ceremony. The
root key certifies that authority's online vote keys and participates in
authority-set transitions.

### 4.2 Online authority

`fog-authority` accepts descriptors, exchanges protocol messages, constructs
deterministic proposals, signs one consensus body per epoch, and publishes
public artifacts. It has no privileged data-plane route.

### 4.3 Operator

An operator controls an operator identity and one or more separately keyed
nodes. The operator declares common control, infrastructure relationships, and
role requests. Admission does not prove honesty or independence.

### 4.4 Node

A node signs its descriptor and proves possession of its node identity. It
publishes only the role-specific public keys and endpoints needed by the
network.

### 4.5 Mirror

A mirror distributes immutable public objects. It is untrusted for
authenticity, freshness, completeness, and consistency.

### 4.6 Witness or monitor

A witness independently fetches, compares, archives, and republishes consensus
and transparency checkpoints. Witnesses improve detection but do not replace
the authority quorum.

### 4.7 Consumer

Consumers are Composers, blind relays, entries, mixes, couriers, storage
replicas, services, and observers. Each maintains role-appropriate monotonic
PKI state. The offline Composer is the final authority for user route
construction.

## 5. Authority Set and Quorum

An authority set contains:

- an exact authority-set version;
- an odd number N of authority roots;
- a quorum M where `floor(N / 2) + 1 <= M <= N`;
- one stable identifier and root public key per authority;
- the permitted online signing suites;
- activation and retirement epochs;
- the transparency-log identifier;
- the hash of the previous authority-set manifest.

The initial claim-bearing profile uses N = 3 and M = 2. A later preferred
profile uses N = 5 and M = 3. A local PoC MAY use a simulated smaller set, but
the resulting consensus is functional test data only.

Consensus signatures are independent signatures. A signature record names its
authority and certified online key. A verifier counts at most one valid
signature per active authority.

Signatures from unknown, duplicate, expired, revoked, not-yet-active, or
wrong-set keys do not count. Extra invalid signatures MUST make the envelope
invalid instead of being silently ignored, because inconsistent validation
would create implementation fingerprints.

## 6. `FOG-PKI-CBOR-1` Encoding

FOG-PKI objects use a restricted deterministic CBOR profile based on RFC 8949.
This profile is named `FOG-PKI-CBOR-1`.

Every signed object has the form:

```text
SignedObject = [
  magic,
  encoding_version,
  object_type,
  body
]
```

where:

- `magic` is the byte string `FOGPKI1`;
- `encoding_version` is unsigned integer `1`;
- `object_type` is a registered unsigned integer;
- `body` is an exact-length array defined by this specification.

An authenticated envelope has the form:

```text
SignedEnvelope = [
  signed_object_bytes,
  signatures
]

SignatureRecord = [
  authority_or_subject_id,
  key_id,
  signature_suite_id,
  signature_bytes
]
```

`signed_object_bytes` is a CBOR byte string containing the exact canonical
encoding of `SignedObject`. A verifier MUST parse it, enforce this profile,
re-encode it, and require byte-for-byte equality before checking signatures.

The profile permits only:

- unsigned integers in their shortest encoding;
- definite-length byte strings;
- definite-length UTF-8 text strings where a field explicitly permits text;
- definite-length arrays with exact schema length.

The profile forbids:

- negative integers;
- maps;
- floating-point values;
- tags;
- simple values, including `null`, `true`, and `false`;
- indefinite-length items;
- duplicate set elements;
- unsorted set-like arrays;
- trailing bytes or concatenated objects.

Boolean fields use unsigned integer `0` or `1`. Optional fields use an
explicit variant discriminator and exact variant array, never `null`.

Set-like arrays MUST be sorted by the canonical byte encoding of the complete
element and MUST contain no duplicate element. Ordered protocol sequences MUST
retain their specified order and MUST NOT be sorted.

Unknown object types, versions, fields, enum values, key purposes, signature
suites, hash suites, roles, parameters, or extensions are critical and MUST be
rejected in version 1.

## 7. Object Types

`FOG-PKI-1` reserves the following object types:

| Value | Object |
| --- | --- |
| 1 | `TrustAnchorManifest` |
| 2 | `AuthorityOnlineKeyCertificate` |
| 3 | `OperatorRecord` |
| 4 | `AdmissionDecision` |
| 5 | `NodeDescriptor` |
| 6 | `AuthorityCommit` |
| 7 | `AuthorityReveal` |
| 8 | `AuthorityProposal` |
| 9 | `ConsensusBody` |
| 10 | `RevocationStatement` |
| 11 | `AuthoritySetTransition` |
| 12 | `EpochArchive` |
| 13 | `LogCheckpoint` |
| 14 | `EquivocationEvidence` |
| 15 | `RecoveryManifest` |
| 16 | `ProfileTransition` |
| 17 | `AuthorityWireKeyCertificate` |
| 18 | `StorageReplicaManifest` |

Object type assignments never change meaning. Incompatible schemas require a
new encoding or object version.

## 8. Domain Separation and Identifiers

The trusted PKI suite defines one approved hash construction and its output
length. All hashes use a distinct ASCII domain string encoded as the first
element of a canonical CBOR array.

Examples:

```text
key_id            = HASH(["FOG-PKI-KEY-ID-1", algorithm_id, public_key])
authority_id      = HASH(["FOG-PKI-AUTHORITY-ID-1", root_key_id])
operator_id       = HASH(["FOG-PKI-OPERATOR-ID-1", operator_key_id])
node_id           = HASH(["FOG-PKI-NODE-ID-1", node_identity_key_id])
object_hash       = HASH(["FOG-PKI-OBJECT-1", signed_object_bytes])
consensus_hash    = HASH(["FOG-PKI-CONSENSUS-1", consensus_body_bytes])
descriptor_hash   = HASH(["FOG-PKI-DESCRIPTOR-1", descriptor_bytes])
storage_manifest_hash = HASH([
  "FOG-PKI-STORAGE-MANIFEST-1",
  storage_manifest_bytes
])
```

Signature input is the canonical encoding of:

```text
[
  "FOG-PKI-SIGNATURE-1",
  network_id,
  object_type,
  signature_suite_id,
  signed_object_bytes
]
```

The exact strings above are part of version 1 and are case-sensitive. Binding
`signature_suite_id` prevents a valid component from being rewrapped under a
different signature suite over otherwise identical object bytes.

`network_id` is a uniformly random 32-byte value created at genesis and pinned
in the initial trust-anchor manifest. It is not derived from a DNS name,
project title, mirror, or operator identity.

Identifiers are public correlation handles inside PKI. They MUST NOT be reused
as message identities, user accounts, storage capabilities, transport secrets,
or release identities.

## 9. Absolute Parser Limits

All implementations MUST enforce these absolute version-1 limits before
allocation proportional to attacker input:

| Item | Limit |
| --- | --- |
| Any `SignedEnvelope` | 8 MiB |
| One `PKIUpdateBundle` | 16 MiB |
| One `NodeDescriptor` envelope | 128 KiB |
| One `StorageReplicaManifest` envelope | 1 MiB |
| One proof bundle | 1 MiB |
| Nesting depth | 8 arrays |
| Authorities | 9 |
| Authority signatures | 9 |
| Operators | 512 |
| Nodes in one consensus | 1024 |
| Endpoints per node | 4 |
| Family or infrastructure groups per node | 16 |
| Epoch public keys per node | 24 |
| Active protocol profiles | 32 |
| Storage manifests per consensus | 3 |
| Replica records per storage manifest | 256 |
| Revocation entries per consensus | 4096 |
| Text field | 128 UTF-8 bytes |
| One public key or signature component | 128 KiB |

The initial deployment profile MAY set lower limits. Increasing an absolute
limit requires a new PKI version and parser review. FOG-PKI uses no compression
in version 1.

## 10. Trust Bootstrap

### 10.1 Genesis material

A new Composer or node begins with:

- the 32-byte `network_id`;
- one exact genesis `TrustAnchorManifest` hash;
- the full genesis manifest;
- the release-verification trust anchor used for the software image;
- the initial transparency checkpoint;
- the accepted PKI encoding and cryptographic suite identifiers.

The genesis manifest is a trust anchor. Self-signatures do not create its
trust. Its hash MUST be pinned in the verified software release and SHOULD be
available through at least one independent human-verifiable channel.

DNS, TLS, a mirror, the blind relay, a QR label, or a reachable authority MUST
NOT replace the pinned genesis hash.

### 10.2 `TrustAnchorManifest`

The manifest body is:

```text
[
  network_id,
  manifest_version,
  previous_manifest_hash,
  activation_epoch,
  retirement_epoch,
  quorum_m,
  authority_roots,
  pki_authentication_suite_id,
  allowed_object_suite_ids,
  transparency_log_id,
  epoch_origin,
  epoch_duration,
  schedule_profile_id,
  hard_limits_profile_id
]
```

`authority_roots` is a sorted array of:

```text
[
  authority_id,
  root_key_id,
  root_signature_algorithm_id,
  root_public_key,
  public_alias
]
```

`public_alias` is an informational pseudonymous label. It is not an identity
proof and MUST NOT contain private contact information. It is 1 to 64 bytes
from ASCII letters, digits, `.`, `_`, and `-`; it need not be globally unique
and MUST NOT be used in security decisions.

Genesis uses an all-zero `previous_manifest_hash`. Later manifests are
accepted only through the transition procedure in Section 22.

`manifest_version` is the `authority_set_version` used by certificates,
consensus, checkpoints, and transitions. The two terms describe the same
monotonic unsigned integer.

## 11. Authority Key Hierarchy

### 11.1 Authority root key

Each authority has one active offline root identity at a time. Its root private
key:

- certifies that authority's online voting keys;
- certifies that authority's dedicated online FOG-WIRE keys;
- signs authority-set transitions;
- signs root-key replacement or retirement;
- participates in authenticated disaster recovery.

It MUST NOT sign routine consensus, descriptor, commit, reveal, proposal,
checkpoint, or admission objects.

The root private key MUST be generated and used in an offline ceremony. Backup
material MUST be encrypted, authenticated, geographically separated where
appropriate, and stored separately from its decryption or recovery secret.

### 11.2 Online vote key

An online voting key signs routine authority protocol objects. It is certified
by its authority root in an `AuthorityOnlineKeyCertificate`:

```text
[
  network_id,
  authority_set_version,
  authority_id,
  online_key_generation,
  online_key_id,
  online_signature_suite_id,
  online_public_key,
  valid_from_epoch,
  valid_until_epoch,
  previous_certificate_hash
]
```

The certificate is signed by the matching authority root. An online key
certificate MUST cover no more than 32 epochs. One current and one next online
key certificate MAY overlap for at most two epochs.

Consensus validation uses the online key valid for the consensus epoch. A key
outside its certified interval cannot sign that epoch even if its certificate
has not been explicitly revoked.

### 11.3 Authority wire key

An authority uses a dedicated online wire key for mutually authenticated
`FOG-WIRE` links with peer authorities and admitted descriptor submitters. It
MUST NOT reuse the authority root key or online vote key for transport.

The wire key is certified by the matching authority root in an
`AuthorityWireKeyCertificate`:

```text
[
  network_id,
  authority_set_version,
  authority_id,
  wire_key_generation,
  wire_key_id,
  wire_algorithm_id,
  wire_public_key,
  supported_wire_profile_ids,
  valid_from_epoch,
  valid_until_epoch,
  previous_certificate_hash
]
```

`supported_wire_profile_ids` is sorted and duplicate-free. Every listed
profile MUST already be trusted and MUST require the declared key algorithm.
The certificate does not authorize its own algorithm or wire profile.

The certificate is signed by the matching offline authority root. It MUST
cover no more than 32 epochs. One current and one next authority wire-key
certificate MAY overlap for at most two epochs. There MUST be exactly one
valid wire key for one authority, profile, and epoch, unless one already
trusted profile defines a composite key as one key record.

An authority wire key authenticates only `NODE_AUTHORITY` and
`AUTHORITY_AUTHORITY` contexts from `FOG-WIRE-1`. It MUST NOT sign votes,
consensus, checkpoints, admission decisions, descriptors, releases, or user
objects.

### 11.4 Signature-suite composition

A suite MAY require more than one signature component, including a classical
and post-quantum component. A composite signature is valid only when every
mandatory component in the already trusted suite validates over the same
signature input.

Components from different signature records, objects, keys, or authorities
MUST NOT be combined to manufacture one valid composite signature.

`FOG-PKI-HASH-CANDIDATE-SHA3-256-1` and
`FOG-PKI-CANDIDATE-MLDSA65-ED25519-1` are the leading non-active candidates.
The latter requires independently generated ML-DSA-65 and Ed25519 keys and
requires both components over the exact suite-bound signature input. Their
encoding, vectors, separability analysis, implementation, side-channel review,
and numeric activation remain pre-PoC gates. Algorithm names or post-quantum
labels alone do not satisfy review.

## 12. Operator Identity and Family Records

An operator uses one dedicated signing identity that is separate from node,
authority, release, user, and infrastructure login keys.

An `OperatorRecord` contains:

```text
[
  network_id,
  operator_id,
  operator_key_id,
  operator_signature_algorithm_id,
  operator_public_key,
  public_alias,
  family_ids,
  infrastructure_group_ids,
  declared_provider_codes,
  declared_as_numbers,
  declared_country_codes,
  record_sequence,
  valid_from_epoch,
  valid_until_epoch
]
```

The operator signs the record, and admission authorities approve its hash.

`family_ids` describe known common control or cooperation across operator
identities. `infrastructure_group_ids` describe shared provider accounts,
orchestration, management, backup, monitoring, corporate ownership, or other
common compromise domains.

Authorities MAY conservatively merge family or infrastructure groups when
credible evidence indicates common control. They MUST NOT split an existing
group without an ordinary threshold decision and a public rationale code.

Provider, ASN, and country declarations are public routing inputs, not proof
of operator independence. Route selection MUST reject reuse of one operator,
family, or prohibited infrastructure group where the active profile requires
diversity.

Public records MUST NOT contain legal names, personal email addresses, phone
numbers, billing identifiers, street addresses, login names, or private abuse
reports. Authorities MAY maintain a separate access-controlled admission file,
but its content is outside consensus and MUST NOT be required by clients.

## 13. Permissioned Admission

### 13.1 Application

The initial network is permissioned. An operator applies with:

- its signed `OperatorRecord`;
- the node identity public key and proof of possession;
- requested role and capabilities;
- canonical endpoints;
- future role-specific public keys;
- declared family and infrastructure relationships;
- operational and policy evidence required by governance.

Private supporting evidence is not placed in the public application object.

### 13.2 Decision

An `AdmissionDecision` contains:

```text
[
  network_id,
  decision_sequence,
  subject_type,
  subject_id,
  operator_record_hash,
  requested_role,
  disposition,
  public_reason_code,
  constraints,
  effective_epoch,
  expiry_epoch
]
```

`disposition` is one of admit, deny, suspend, reinstate, or retire. It uses a
registered unsigned integer, not text.

Ordinary admission, role change, reinstatement, and retirement require M
independent authority signatures. A single authority cannot admit a node.

Admission binds one node identity to one operator and one eligible role. A
role change requires a new decision. Admission does not assign a mix layer;
the consensus topology does.

### 13.3 Reapplication and replacement

A revoked node identity MUST NOT be reused. A replacement generates a new node
identity and follows ordinary admission. A changed endpoint or role-specific
key does not require a new node identity if a valid monotonic descriptor and
the existing admission constraints permit the change.

## 14. Node Identity and Descriptor

### 14.1 Node identity

Every online node has one role-local node identity signing key. It signs
descriptors and proves continuity across epoch-key rotation. It MUST NOT be
used for Noise transport, KEMSphinx, entry capsules, storage envelopes,
metrics, release signing, or operator administration.

### 14.2 Descriptor body

A `NodeDescriptor` contains:

```text
[
  network_id,
  descriptor_version,
  descriptor_sequence,
  node_id,
  node_identity_key_id,
  node_identity_algorithm_id,
  node_identity_public_key,
  operator_id,
  operator_record_hash,
  admitted_role,
  capability_ids,
  endpoints,
  epoch_public_keys,
  supported_profile_ids,
  valid_from_epoch,
  valid_until_epoch,
  previous_descriptor_hash
]
```

It is signed independently by the node identity and operator identity. Both
signatures are required.

`descriptor_sequence` starts at zero and increases by exactly one for each
accepted replacement descriptor. A new descriptor names the previous accepted
descriptor hash. A gap, rollback, duplicate sequence with a different hash, or
broken chain is invalid.

One descriptor MUST cover no more than four consecutive epochs. It MUST carry
the public keys required for its current and next usable key periods without
extending private-key overlap beyond the owning protocol profile.

### 14.3 Endpoints

An endpoint is:

```text
[
  transport_profile_id,
  address_type,
  address_bytes,
  port,
  priority_class
]
```

Only endpoint forms explicitly permitted by the active wire profile are
valid. An endpoint MUST NOT contain a URL path, username, password, API token,
query string, fragment, or unauthenticated redirect target.

DNS-only identity is forbidden. If a profile permits DNS discovery, the
descriptor still binds the node identity and authenticated endpoint behavior;
DNS never authorizes a different node key.

### 14.4 Epoch public keys

Each public key entry is:

```text
[
  purpose_id,
  algorithm_id,
  key_id,
  public_key,
  valid_from_epoch,
  valid_until_epoch
]
```

Purpose IDs distinguish at least:

- node Noise transport;
- entry submission capsule;
- entry return KEMSphinx terminal processing where required;
- mix KEMSphinx transformation;
- courier or service terminal KEMSphinx processing;
- replica envelope protection;
- replica durable-result receipt authentication;
- aggregate signing.

A descriptor MUST contain exactly the key purposes required by its admitted
role and MUST NOT contain keys for another role. The current and next key
periods MUST be published before the descriptor deadline. More than one active
key for the same purpose and epoch is invalid unless the active suite defines
one composite key as a single key record.

Private keys never enter a descriptor, vote, consensus, proof, log, example,
fixture, or support artifact.

## 15. Epoch and Time Model

The genesis manifest pins:

- `epoch_origin`, an unsigned Unix-time second;
- `epoch_duration`, a whole number of seconds;
- one schedule profile;
- maximum clock uncertainty;
- consensus freshness and hard-expiry offsets;
- descriptor, commit, reveal, proposal, signature, and publication deadlines;
- packet and key grace constraints supplied by the owning protocol profiles.

Epoch number at time `t` is:

```text
floor((t - epoch_origin) / epoch_duration)
```

for `t >= epoch_origin`.

The exact initial epoch duration and schedule offsets remain a pre-PoC
operational selection. They MUST be identical for all participants, encoded in
the trust manifest, and supported by fault-injection tests. Operators cannot
override them locally.

Changing epoch origin, duration, schedule, or maximum clock uncertainty
requires an authority-set manifest transition with at least two epochs of
advance notice. It is not an ordinary consensus parameter change.

Consumers MUST evaluate time with an explicit local uncertainty interval. A
relay-provided timestamp, mirror `Date` header, DNS response, or single time
server is not trusted time. If the uncertainty interval cannot establish
validity, the consumer fails closed for new work.

## 16. Authority Protocol State Machine

For target epoch E, each online authority executes these phases.

### 16.1 Collect

Authorities collect valid descriptors, operator records, admission decisions,
revocations, online key certificates, and announced transitions before the
descriptor deadline.

Inputs arriving after the deadline are considered only for a later epoch.
Authorities MUST NOT create different inclusion behavior based on requester
latency after the public deadline.

### 16.2 Commit

Each authority generates a fresh uniformly random secret for epoch E and
publishes a signed `AuthorityCommit`:

```text
[
  network_id,
  authority_set_version,
  epoch,
  authority_id,
  commitment,
  previous_consensus_epoch,
  previous_consensus_hash
]
```

The commitment is the suite hash of a domain-separated encoding containing
the network, epoch, authority, random secret, and previous consensus hash.

Exactly:

```text
commitment = HASH([
  "FOG-PKI-COMMIT-1",
  network_id,
  authority_set_version,
  epoch,
  authority_id,
  previous_consensus_epoch,
  previous_consensus_hash,
  random_secret
])
```

### 16.3 Reveal

After the commit deadline, each authority publishes a signed
`AuthorityReveal` containing the secret corresponding to its prior commitment.
Reveals without one valid timely commit, invalid reveals, duplicates, or early
reveals are excluded and recorded.

If fewer than M authorities provide valid commit/reveal pairs, no consensus is
produced.

The shared seed is derived from the previous consensus hash and the sorted
valid authority reveals using the pinned hash suite:

```text
shared_seed = HASH([
  "FOG-PKI-SHARED-SEED-1",
  network_id,
  authority_set_version,
  epoch,
  previous_consensus_epoch,
  previous_consensus_hash,
  sorted_reveals
])

sorted_reveals = [
  [authority_id, random_secret],
  ...
]
```

The complete commit and reveal hashes are included in the consensus audit
section. `sorted_reveals` is sorted by `authority_id` and contains no duplicate
authority.

Commit-reveal limits unilateral prediction but permits withholding and denial
of service by a last revealer. FOG-PKI does not claim bias-free randomness from
this construction. Topology stability and deterministic public auditing limit
where the seed is security-critical.

### 16.4 Propose

Each authority independently applies the exact deterministic rules in this
specification to the same eligible input set. It signs and exchanges an
`AuthorityProposal` containing the resulting consensus body hash and sorted
input object hashes.

Authorities MUST NOT average, merge, or majority-vote individual fields from
different proposals. A body is signable only when at least M authorities have
published identical proposal body and input hashes.

### 16.5 Sign

Before signing, an authority:

1. validates its active online key certificate;
2. recomputes the complete canonical consensus body;
3. verifies the previous consensus and authority-set chain;
4. persists `(network_id, epoch, consensus_hash)` in durable sign-once state;
5. refuses if any different hash is already stored for that epoch;
6. signs the canonical `ConsensusBody` object.

The sign-once record MUST survive restart, restore, and failover. Cloning an
authority database into two active signers is forbidden.

### 16.6 Publish

Authorities exchange detached signatures. Any publisher can assemble a valid
`ConsensusEnvelope` only by attaching at least M distinct valid signatures to
the exact body bytes.

Authorities publish the body, all signature records, relevant certificates,
input hashes, epoch archive, and transparency material. Mirrors may copy these
bytes but cannot modify them.

Signature collection closes at the public signature deadline. The final
sorted signature-record set is committed by the epoch archive before
`valid_after`. A later signature over the same body remains evidence of that
authority's statement but MUST NOT be inserted into the finalized consensus
envelope for that epoch.

## 17. Deterministic Eligibility and Topology

### 17.1 Eligibility filtering

A node is eligible for epoch E only if:

- its admission is active for E;
- its operator record is active and threshold-approved;
- its descriptor chain and both descriptor signatures validate;
- the descriptor covers E and has the required future key material;
- it is not suspended or revoked;
- every endpoint, key, capability, and profile is permitted;
- its role does not conflict with another identity or active assignment;
- its operator and infrastructure declarations meet the active profile.

All filtering operates on canonical public data and deterministic reason
codes. Private authority evidence may cause a signed public suspension or
revocation decision, but it MUST NOT silently change deterministic evaluation.

### 17.2 Effective roles

The consensus assigns each eligible node exactly one of:

- entry;
- mix layer 1;
- mix layer 2;
- mix layer 3;
- courier;
- storage replica;
- declared native service;
- observer.

The node requests an admitted role. Only mix layer number is assigned by the
consensus topology algorithm. A node cannot self-place into a layer.

### 17.3 Topology generation

Layer assignment remains stable within one `topology_generation`. A new
generation is created only for admission, removal, capacity change, diversity
repair, or deliberate rebalance. Routine epoch key rotation MUST NOT reshuffle
all mix layers.

For a new generation:

1. eligible nodes are grouped by role;
2. each group is sorted by `node_id`;
3. the shared seed drives a suite-defined deterministic pseudorandom shuffle
   using unbiased sampling;
4. mix nodes are assigned to three balanced layers;
5. deterministic constraints maximize operator, family, provider, ASN,
   country, and infrastructure-group diversity;
6. a validation pass proves that the profile has at least one allowed complete
   route and meets its minimum node counts;
7. failure to satisfy hard constraints makes the proposal invalid.

The exact deterministic shuffle and constraint solver require conformance
vectors before the PoC. Different implementations MUST produce byte-identical
topology from the same inputs and seed.

### 17.4 Route constraints

Consensus publishes the attributes needed by the Composer to reject routes
that repeat one operator, family, or prohibited infrastructure group. The
consensus MUST NOT precompute one user route or allow operators to choose user
paths.

## 18. Consensus Body

The canonical `ConsensusBody` is:

```text
[
  network_id,
  pki_version,
  authority_set_version,
  epoch,
  topology_generation,
  valid_after,
  fresh_until,
  valid_until,
  previous_consensus_epoch,
  previous_consensus_hash,
  trust_anchor_manifest_hash,
  commit_reveal_summary,
  operator_records,
  node_descriptors,
  topology,
  revocations,
  storage_manifests,
  active_profile_ids,
  network_parameters,
  announced_transition_hashes
]
```

`previous_consensus_epoch` and `previous_consensus_hash` identify the latest
prior epoch that produced a valid consensus. They may skip scheduled epochs
that ended without consensus. Each skipped epoch still receives a
no-consensus transparency archive under Section 24.

### 18.1 Validity times

`valid_after`, `fresh_until`, and `valid_until` are derived exactly from the
epoch schedule. Authorities do not choose them independently.

- Before `valid_after`, the consensus may be staged but not used for new work.
- After `fresh_until`, a consumer reports a stale-update condition but MAY
  continue only until `valid_until` under the same profile.
- At `valid_until`, new route construction and new work stop.

No mirror, relay, node, operator, or single authority can extend these times.

### 18.2 Full descriptors

Version 1 consensus contains the complete accepted operator records and node
descriptors needed for route and link validation. It does not use
state-dependent descriptor deltas or fetch-on-demand partial views.

Each embedded record or descriptor is a CBOR byte string containing its full
canonical signed envelope. Arrays are sorted by the corresponding stable
identifier, not by operator alias, endpoint, or arrival order. Consumers
independently validate the embedded operator and node signatures after the
authority quorum signature.

`storage_manifests` contains the complete canonical previous, current, and
announced next `StorageReplicaManifest` objects required by the active
FOG-STORAGE retention and transition windows. The objects are sorted by
storage epoch and manifest hash, duplicate-free, and validated under
`FOG-PKI-CBOR-1` and the authority quorum. Consumers MUST NOT merge replica
records or storage keys from different manifests. The exact object schema,
sign-once state, shard inputs, and key windows are defined by
`FOG-STORAGE.md`.

### 18.3 Profiles and parameters

`active_profile_ids` authorizes exact wire, packet, storage, entry, cover, and
application protocol profiles. `network_parameters` contains only registered
integer parameter IDs and bounded unsigned integer values.

For KEMSphinx packet processing, consensus and the applicable
`FOG-SPHINX-PROFILES` record MUST resolve exactly one packet profile for each
tuple `(epoch, link_context, packet_class)`. During a transition, old and new
packet profile IDs may both appear only with an unambiguous activation and
drain mapping. A consumer MUST reject a consensus that makes profile selection
ambiguous, requires packet-length detection, or maps one new-work tuple to
more than one packet profile.

Every node descriptor selected for a KEMSphinx route MUST contain the exact
epoch KEM key purpose, role, layer, and packet profile required by that route.
The consensus is invalid if its topology cannot supply a complete four-hop
forward and reply shape required by the active packet profile.

A parameter cannot select the suite used to authenticate its own consensus.
Security-critical profile transition requires a preannounced bounded overlap
and cannot silently downgrade an already accepted minimum.

A `ProfileTransition` contains:

```text
[
  network_id,
  transition_sequence,
  profile_class,
  old_profile_ids,
  new_profile_ids,
  announcement_epoch,
  activation_epoch,
  retirement_epoch,
  minimum_compatible_version
]
```

It requires M independent authority signatures, at least two epochs of advance
notice, a bounded old/new overlap, and inclusion of its hash in every
intervening consensus. Parameters classified as profile-bound change only
through this object. Parameters explicitly classified as dynamic MUST have
hard minimum, maximum, and per-epoch change bounds in the active profile.

### 18.4 Signature envelope

A `ConsensusEnvelope` is a `SignedEnvelope` whose signed object type is
`ConsensusBody`. Signature records are sorted by `authority_id` and contain no
duplicates.

The consensus hash covers the body bytes only. The valid consensus identity is
the pair `(epoch, consensus_hash)`. Adding a valid signature does not create a
different consensus identity.

## 19. Consumer Consensus Validation

A consumer MUST perform these checks in order:

1. enforce the outer byte limit before parsing;
2. decode one exact `SignedEnvelope` and reject trailing data;
3. validate `FOG-PKI-CBOR-1` and canonical byte equality;
4. require the pinned `network_id`, PKI version, and object type;
5. load the already trusted authority-set manifest for the declared version;
6. validate all required authority online vote-key and wire-key certificates
   and revocation state;
7. verify every included signature and require at least M distinct valid
   active authorities;
8. recompute the consensus hash;
9. require exact epoch schedule times and acceptable local clock uncertainty;
10. reject an epoch below the highest accepted epoch;
11. reject a different hash for an already accepted epoch;
12. verify the previous-consensus relationship or the offline consistency
    bundle described in Section 25;
13. validate all records, descriptors, key purposes, profile IDs, parameters,
    revocations, limits, topology assignments, and diversity constraints;
14. verify the epoch archive and transparency inclusion and consistency
    evidence;
15. atomically persist the new manifest version, epoch, consensus hash,
    checkpoint, and minimum accepted profile state;
16. only then expose the network view to route or link logic.

Signature verification MUST occur before expensive validation proportional to
the complete topology where practical, but canonical parsing and strict bounds
always occur first.

An implementation MUST NOT choose one of two valid-looking same-epoch bodies
by timestamp, signature count above M, mirror order, lexicographic hash, or
network reachability. It freezes and reports equivocation.

## 20. Node Consumption and Key Acceptance

Online nodes apply the same consensus authentication rules as Composers and
also MUST:

- confirm their own effective role and layer before serving traffic;
- bind peer eligibility to the active consensus and link profile;
- accept role-specific epoch keys only for their declared purpose;
- validate root-certified current or staged authority wire keys before
  `NODE_AUTHORITY` or `AUTHORITY_AUTHORITY` handshakes;
- stage next-epoch connections without forwarding next-epoch traffic early;
- close or reject peers removed by the next consensus at the specified
  boundary;
- retain previous packet-processing keys only for the exact bounded packet
  grace period;
- erase expired epoch private keys after all required replay and packet
  windows close;
- stop if local configuration attempts to activate a second role.

An operator configuration cannot add a peer, key, profile, or role absent from
consensus.

## 21. Revocation and Suspension

### 21.1 Scope

A `RevocationStatement` may target:

- one role-specific epoch key;
- one node identity and all its keys;
- one operator and all admitted nodes;
- one authority online voting key;
- one authority online wire key;
- one authority root through an authority-set transition;
- one protocol profile or suite through a preannounced transition.

### 21.2 Body

```text
[
  network_id,
  revocation_sequence,
  target_type,
  target_id,
  scope,
  public_reason_code,
  effective_epoch,
  effective_time,
  expiry_epoch,
  replacement_policy,
  previous_revocation_hash
]
```

Ordinary suspension, revocation, expiry change, and reinstatement require M
authority signatures.

### 21.3 Self-revocation

A node or operator MAY publish a self-revocation signed by the affected
identity. Consumers treat a valid self-revocation as an immediate denial-of-
service-safe removal of that identity. Self-revocation cannot authorize a
replacement key, identity, operator, role, or authority.

### 21.4 Emergency revocation

Between normal consensuses, M authorities MAY sign one emergency revocation
envelope. It MUST:

- use a monotonic revocation sequence;
- identify the last valid consensus hash;
- have a short explicit expiry no later than the next normal consensus hard
  expiry;
- be included in the next epoch archive;
- never add or reinstate an identity;
- never change quorum, authority roots, profiles, or topology except by
  removing the compromised subject.

A single authority warning is public evidence but is not an effective network
revocation.

### 21.5 Compromise response

After confirmed compromise:

- stop new use of the affected private key;
- publish self-revocation where safe;
- issue threshold suspension or revocation;
- remove affected objects from new consensus;
- generate purpose-separated replacement keys;
- use ordinary admission or transition for replacement;
- preserve public evidence without publishing secret forensic material;
- document which past and future properties may have failed.

Revocation does not erase previously recorded traffic, signatures, or
compromise effects.

## 22. Authority-Set Transition

Authority membership, quorum, root keys, PKI authentication suite, epoch
schedule, and transparency-log identity change only through an
`AuthoritySetTransition`.

The transition body contains:

```text
[
  network_id,
  old_manifest_version,
  old_manifest_hash,
  new_manifest_version,
  new_manifest_hash,
  announcement_epoch,
  activation_epoch,
  transition_reason_code
]
```

Acceptance requires:

1. versions increase by exactly one;
2. the old manifest is already trusted;
3. activation is announced at least two epochs in advance;
4. at least M old authority root signatures validate;
5. at least the new quorum of new authority root signatures validate;
6. the transition hash appears in every consensus during the overlap;
7. the new manifest chains to the old manifest hash;
8. the consumer persists the new manifest before its activation epoch;
9. old roots stop authorizing ordinary new state at activation;
10. a bounded verification overlap exists only for objects created before the
    boundary.

This dual-quorum procedure follows the principle that both the old trusted set
and the new set authorize a root transition.

The old quorum signs the exact new root keys and suite identifiers. A new
authentication suite MUST already be supported and explicitly authorized as a
transition suite by the old manifest during the overlap. A client MUST NOT
jump directly from an old suite to an object that can be verified only by an
algorithm named inside that object. Software support for a suite does not make
the suite trusted without this chained authorization.

If too many old roots are lost to reach the old quorum, the network has no
automatic in-protocol recovery. Recovery requires a separately authenticated
`RecoveryManifest`, explicit user or operator action, and a new trust anchor
obtained through independent channels. It MUST NOT resemble an ordinary
update or trust-on-first-use prompt.

## 23. Topology and Profile Revocation Effects

Removing one node MUST NOT cause consumers to bypass its layer. A new
consensus recomputes a valid complete topology or fails.

If revocation makes the minimum topology or operator diversity impossible:

- no stronger privacy profile is advertised;
- authorities may publish a lower claim profile only if it was already
  supported, explicitly authorized, and not a silent downgrade;
- consumers whose minimum accepted profile is stronger stop new work;
- the local PoC profile may continue only as functional test mode.

Profile removal is not a generic emergency revocation. It requires a
preannounced `ProfileTransition`, or an authority-set transition when the PKI
authentication suite itself changes, unless the profile already has an
authenticated hard retirement epoch.

## 24. Append-Only Transparency Log

### 24.1 Purpose and limitation

FOG-PKI maintains an append-only Merkle log so a long-offline Composer can
verify that a new accepted view extends its stored checkpoint with a proof
whose size grows logarithmically rather than linearly with missed epochs.

The log detects inconsistent signed history when views are compared. It does
not by itself guarantee that every client sees the same view. Independent
retrieval, witnesses, and checkpoint gossip remain necessary.

### 24.2 Epoch archive

For every scheduled epoch E, authorities create one canonical `EpochArchive`
once quorum can finalize either the successful or no-consensus outcome:

```text
[
  network_id,
  epoch,
  archive_status,
  failure_reason_code,
  consensus_hash,
  authority_manifest_hash,
  online_key_certificate_hashes,
  authority_wire_key_certificate_hashes,
  authority_protocol_object_hashes,
  consensus_signature_hashes,
  operator_record_hashes,
  admission_decision_hashes,
  node_descriptor_hashes,
  revocation_hashes,
  transition_hashes,
  equivocation_evidence_hashes
]
```

All set-like lists are sorted and duplicate-free. The archive commits to the
public protocol record without embedding private admission evidence.

The archive is a canonical `SignedObject` byte string but needs no individual
signature envelope. Its authenticity derives from inclusion in the Merkle tree
identified by an M-of-N signed checkpoint.

For a successful epoch, `archive_status` is unsigned integer `0`,
`failure_reason_code` is zero, and `consensus_hash` identifies the threshold-
valid consensus. For an epoch without consensus, `archive_status` is unsigned
integer `1`, `consensus_hash` is the all-zero hash, and the registered failure
code records the failed phase without private diagnostics.

`authority_protocol_object_hashes` commits to authority commits, reveals, and
proposals associated with the epoch.
`consensus_signature_hashes` commits to every published authority signature
in the finalized consensus envelope. A consumer requires the envelope's exact
sorted signature-record hash set to match the archive.

### 24.3 Merkle construction

Each canonical `EpochArchive` byte string is one log leaf in increasing epoch
order. There is exactly one leaf per scheduled epoch. Missing consensus is
represented by the canonical failure archive; leaf indices never shift or get
reused. If quorum loss temporarily prevents checkpointing a failure archive,
the gap MUST be filled before a later checkpoint can advance past it.

The Merkle tree, leaf hashing, node hashing, inclusion proofs, and consistency
proofs follow the RFC 9162 append-only construction with FOG-specific domain
separation and the hash suite pinned by the trust manifest.

The version-1 hashes are:

```text
empty_hash = HASH(["FOG-PKI-LOG-EMPTY-1", log_id])

leaf_hash = HASH([
  "FOG-PKI-LOG-LEAF-1",
  log_id,
  epoch_archive_bytes
])

node_hash = HASH([
  "FOG-PKI-LOG-NODE-1",
  log_id,
  left_child_hash,
  right_child_hash
])
```

Tree splitting, inclusion paths, and consistency paths follow RFC 9162. The
FOG domains above replace the RFC leaf and node prefixes; they do not change
tree ordering or proof traversal.

The log MUST NOT use commutative child hashing. Left and right position are
part of verification.

### 24.4 Checkpoint

A `LogCheckpoint` contains:

```text
[
  network_id,
  log_id,
  authority_set_version,
  tree_size,
  root_hash,
  first_epoch,
  last_epoch,
  checkpoint_time
]
```

It requires M independent online authority signatures. For a successful
consensus, its archive and checkpoint MUST be published before that
consensus's `valid_after`. If quorum cannot checkpoint it by then, consumers do
not use it for new work. Failure archives are checkpointed before the log can
advance to any later epoch.

`first_epoch`, `last_epoch`, and `tree_size` MUST describe one contiguous
epoch sequence with exactly one leaf per scheduled epoch.

### 24.5 Proofs

Mirrors provide:

- an inclusion proof that the target `EpochArchive` is in the new checkpoint;
- a consistency proof that the new checkpoint extends the consumer's stored
  checkpoint;
- the target archive and consensus envelope;
- any intervening authority-set transitions and online vote-key certificates;
- authority wire-key certificates required by an online consumer's selected
  FOG-WIRE contexts.

Proofs are not trusted objects and need no signature. Their validity derives
from the old stored root and new threshold-signed checkpoint.

### 24.6 Checkpoint comparison

The following are evidence of failure or equivocation:

- two threshold-signed checkpoints with the same `tree_size` and different
  roots;
- a newer threshold-signed checkpoint for which no valid consistency proof
  from an accepted older checkpoint exists;
- one epoch archive committing to a consensus hash different from the accepted
  threshold consensus;
- a checkpoint omitting a promised finalized epoch beyond the publication
  deadline.

Consumers freeze ordinary PKI updates on verified checkpoint inconsistency.
They do not reset their stored tree size to make a proof pass.

## 25. Offline Composer Update Bundle

The blind relay or controlled import medium supplies one bounded
`PKIUpdateBundle` containing:

- the target full consensus envelope;
- authority online-key certificates needed to verify it;
- current revocations and emergency revocations;
- every sequential authority-set transition since the stored manifest;
- the target epoch archive;
- a threshold-signed current log checkpoint;
- an inclusion proof for the target archive;
- a consistency proof from the Composer's stored checkpoint;
- independently fetched distinct checkpoints or witness statements where
  available;
- a coarse untrusted retrieval timestamp for diagnostics only.

The bundle is a transfer container, not a signed PKI object. Every contained
object is independently bounded and verified. Extra, duplicate, conflicting,
or unrelated objects make the bundle invalid.

The Composer MUST:

1. verify transitions sequentially from its stored manifest;
2. verify the new checkpoint quorum under the correct active authority set;
3. verify checkpoint consistency from its stored tree root;
4. verify inclusion of the target epoch archive;
5. verify the archive's consensus hash;
6. validate the consensus through Section 19;
7. compare all supplied distinct checkpoints and evidence;
8. atomically persist the entire new trusted state;
9. retain sufficient prior checkpoint and manifest metadata for recovery and
   equivocation evidence.

If the relay withholds newer data, it can cause freeze or denial of service.
It cannot make stale data satisfy hard expiry or monotonic checks.

If the Composer lacks its previous checkpoint or manifest state, it MUST NOT
silently bootstrap from the relay. It requires the explicit recovery process.

## 26. Equivocation Evidence

An `EquivocationEvidence` object contains two or more complete independently
verifiable signed objects demonstrating one of:

- one authority signs two different consensus hashes for one epoch;
- two threshold-valid consensus bodies exist for one epoch;
- one node signs different descriptors with the same sequence and predecessor;
- one operator signs conflicting records with the same sequence;
- an authority signs two different storage manifest hashes for one storage
  epoch;
- one authority signs incompatible commits, reveals, or proposals;
- threshold-signed checkpoints conflict or fail append-only consistency;
- an authority-set transition conflicts at one manifest version.

Evidence objects MUST contain no secret randomness beyond a reveal already due
for publication and no private governance evidence.

Node or operator equivocation causes deterministic exclusion pending a
threshold decision. Authority or checkpoint equivocation freezes affected
consumers until a valid authority-set transition or explicit recovery
manifest resolves the trust state.

A consumer MUST NOT locally rewrite the authority set merely because it has
evidence against one authority. That would create a client-specific trust
view.

## 27. Distribution and Mirrors

Authorities and mirrors publish immutable objects addressed by object hash.
The latest pointer is an untrusted convenience and MUST return the complete
bytes needed for verification.

Publishers SHOULD support retrieval by:

- exact consensus epoch and hash;
- object hash;
- authority-set manifest version;
- transparency checkpoint tree size;
- inclusion and consistency proof parameters;
- revocation sequence.

HTTP, HTTPS, removable media, QR, FOG-SX-adjacent transfer tooling, or another
transport MAY carry public PKI objects. Transport security can improve
availability and privacy but does not create PKI authenticity.

Relays SHOULD fetch from at least two independently operated authorities or
mirrors and preserve distinct valid responses. They MUST NOT merge them. A
Composer import bundle includes conflicts as evidence rather than hiding them.

Mirrors MUST NOT receive authority private keys, admission credentials, user
identities, message traffic, or special consensus signing privilege.

## 28. Failure Behavior

| Condition | Required behavior |
| --- | --- |
| Fewer than M valid consensus signatures | reject |
| Signature from wrong authority set | reject |
| Any included malformed or invalid signature | reject envelope |
| Same authority listed twice | reject envelope |
| Non-canonical encoding | reject before signature acceptance |
| Unknown-critical value | reject |
| Wrong network ID | reject |
| Same epoch, different hash | freeze and retain evidence |
| Lower epoch or manifest version | reject as rollback |
| Broken descriptor chain | exclude descriptor; proposal must agree |
| Missing required future key | exclude node |
| Invalid topology or insufficient diversity | no consensus for that profile |
| Commit/reveal quorum failure | no consensus |
| Proposal body mismatch | do not sign |
| Consensus past `fresh_until` | report stale; continue only to hard expiry |
| Consensus past `valid_until` | stop new work |
| Checkpoint consistency failure | freeze ordinary update |
| Authority transition lacks dual quorum | reject transition |
| Lost local monotonic state | require explicit recovery |
| Clock uncertainty exceeds bound | stop time-sensitive acceptance |

Remote protocol errors MUST be coarse and non-amplifying. Local diagnostics
MAY identify deterministic validation stages but MUST NOT log private keys,
private admission material, unpublished random reveals, or credentials.

## 29. Key Lifecycle Table

| Key or secret | Generator | Authorized use | Lifetime and overlap | Compromise response | Backup |
| --- | --- | --- | --- | --- | --- |
| Network ID | genesis ceremony | domain and network separation | permanent | new network genesis | public, widely copied |
| Authority root private key | offline authority ceremony | online-key certificates and set transitions | long-term, one controlled transition overlap | root transition or explicit recovery | encrypted, separate recovery secret |
| Authority online vote private key | authority root ceremony or controlled online generation | commits, reveals, proposals, consensus, checkpoints | at most 32 epochs, at most 2-epoch overlap | threshold revoke certificate and rotate | SHOULD NOT be restored into concurrent signer |
| Authority wire private key | authority wire service OS CSPRNG or controlled ceremony | mutually authenticated `FOG-WIRE` authority and descriptor links | root-certified for at most 32 epochs, at most 2-epoch overlap | revoke certificate, stop new sessions, and rotate | SHOULD NOT be restored into concurrent service |
| Authority randomness secret | online authority CSPRNG | one epoch commit/reveal | one protocol run; erase after reveal and audit window | exclude invalid run; investigate RNG | no backup |
| Operator identity private key | operator ceremony | operator records and descriptor co-signing | long-term with admitted replacement | suspend operator, replace through admission | encrypted operator-controlled backup |
| Node identity private key | node enrollment | descriptor continuity | long-term for one node role | self-revoke and new admission | encrypted role-local backup if policy permits |
| Node epoch private key | owning node CSPRNG | one declared role purpose | current plus bounded grace; future key staged | revoke purpose or node; generate replacement | no routine backup |
| Replica receipt private key | one storage replica CSPRNG | authenticate one manifest-bounded local durable-result receipt | storage-manifest current plus bounded verification drain | stop receipts, revoke node or purpose, rotate through new manifest | no routine backup |
| Transparency checkpoint state | every authority | append-only root computation and sign-once tracking | permanent monotonic public history | freeze on inconsistency; recover from audited replicas | authenticated independent authority backups |
| Consumer monotonic state | each consumer | rollback and consistency detection | lifetime of installation or identity | explicit authenticated recovery | authenticated backup bound to consumer profile |

The networkless Composer refines the final row through the local commitment,
external-anchor, import, recovery, and update-consumer rules in
`FOG-COMPOSER.md`. A self-contained consumer backup does not provide complete
rollback detection.

No private key or randomness secret may appear in consensus, transparency
logs, test vectors, examples, command lines, environment templates, container
images, metrics, crash dumps, or support bundles. Tests generate ephemeral
fixtures at runtime.

## 30. Privacy and Operational Data

Public PKI necessarily reveals:

- node and authority public identities;
- endpoints and supported transports;
- effective roles and mix layers;
- declared operator, family, provider, ASN, country, and infrastructure groups;
- public key schedules, profiles, validity, admission, suspension, and
  revocation state;
- consensus timing and topology changes.

This enables targeting and operational correlation. FOG accepts that exposure
because clients need a common auditable view and route-diversity inputs.

FOG-PKI MUST NOT publish:

- user or contact identities;
- mailbox capabilities or packet identifiers;
- node traffic counts or fine-grained health events;
- operator legal identity unless voluntarily required by a separate public
  governance policy;
- private email, phone, billing, account, or management data;
- exact physical addresses;
- unpublished vulnerability or forensic details;
- authority or node private-key storage design beyond the public assurance
  profile.

Descriptor uploads, votes, and public objects SHOULD use fixed schedule
windows and bounded request behavior. Operational metrics belong to the
aggregate observer interface, not node descriptors.

## 31. Denial-of-Service and Resource Controls

Authorities MUST:

- accept descriptor uploads only for admitted identities;
- authenticate before expensive signature or policy work where possible;
- accept at most one selected descriptor chain head per node and epoch;
- bound connections, body size, signatures, records, keys, endpoints, and
  pending votes;
- rate-limit invalid uploads without creating different consensus views;
- persist protocol phase and sign-once state atomically;
- use bounded backoff for peer authority exchange;
- avoid error responses larger than the triggering request;
- keep publication serving separate from sensitive signing state;
- remain able to publish existing immutable objects during voting overload.

A malicious admitted node can consume review and descriptor resources. The
permissioned registry, bounds, expiry, suspension, and operator-wide actions
limit but do not eliminate this risk.

Authority quorum and transparency do not provide availability against a
sustained distributed attack or coordinated withholding.

## 32. Conformance and Adversarial Tests

Before the local PoC, FOG-PKI MUST have deterministic fixtures for:

- every object type and exact canonical encoding;
- re-encoding equality and rejection of alternative CBOR encodings;
- every registered identifier and domain-separated hash;
- valid M-of-N consensus for 2-of-3 and 3-of-5 sets;
- duplicate, unknown, expired, revoked, and wrong-set signatures;
- composite signature all-component validation;
- authority online-key certification and overlap boundaries;
- authority wire-key certification, overlap, profile binding, and rejection of vote-key reuse;
- descriptor sequence, predecessor, node, and operator signatures;
- role-specific key-purpose acceptance and cross-purpose rejection;
- admission, denial, suspension, reinstatement, retirement, and self-revocation;
- commit, reveal, missing reveal, invalid reveal, and insufficient quorum;
- byte-identical topology generation from seed and inputs;
- operator, family, provider, ASN, country, and infrastructure constraints;
- same-epoch authority and node equivocation;
- storage-manifest canonical encoding, sign-once persistence, quorum,
  chaining, previous/current/next windows, receipt keys, and no cross-manifest
  replica merging;
- stale, expired, future, rolled-back, frozen, and split consensus;
- authority sign-once persistence across crash, restore, and failover;
- ordinary and emergency revocation;
- dual-quorum authority-set transition;
- loss of old-root quorum and explicit recovery refusal;
- RFC 9162 inclusion and consistency proofs, including edge tree sizes;
- conflicting checkpoints and missing archive leaves;
- long-offline Composer update from old checkpoint;
- interrupted atomic state update and recovery;
- maximum document, array, string, key, signature, and proof limits;
- parser mutation, fuzz, differential, and allocation tests;
- clock skew and uncertainty at every boundary;
- consensus publication and mirror corruption scenarios.

Independent implementations MUST consume the same conformance corpus before
interoperability is claimed.

## 33. Claim Gates

### 33.1 Functional PoC

The PoC may use simulated authorities but MUST exercise:

- independent signature records;
- canonical consensus construction;
- descriptor validation;
- three-layer topology assignment;
- current and next node keys;
- rollback state;
- revocation;
- sign-once behavior;
- transparency inclusion and consistency proofs;
- expired-consensus fail-closed behavior.

`FOG-LOCAL-POC.md` keeps the authority fixture networkless and explicitly
non-claim-bearing. Its fault plan requires insufficient-quorum, same-epoch
fork, stale-consensus, rollback-state, and clock-uncertainty cases before a
runnable fixture can pass.

### 33.2 Operator alpha

Alpha requires:

- three independently administered authority roots and online services;
- a 2-of-3 quorum;
- independent consensus mirrors;
- at least two independent checkpoint monitors or witnesses;
- rehearsed online-key compromise, node revocation, authority replacement,
  quorum loss, clock failure, and restore exercises;
- public admission, family, revocation, and residual-risk policy;
- confirmation that no shared provider account or management credential
  controls the authority quorum.

### 33.3 Production PKI claims

Production claims additionally require:

- independent protocol and implementation review;
- reviewed concrete classical and post-quantum policy;
- independently reproduced consensus and transparency roots;
- published conformance results and unresolved findings;
- demonstrated long-offline update and recovery ceremonies;
- ongoing operator-family and common-control auditing;
- explicit documentation that a compromised authority threshold can still
  authorize a malicious network view.

## 34. Requirements Traceability

| Requirement | FOG-PKI control |
| --- | --- |
| `TM-NET-06` | full canonical consensus, fixed profile IDs, no partial-view merge |
| `TM-PKI-01` | permissioned admission, operator records, family and infrastructure constraints |
| `TM-PKI-02` | monotonic epoch and hash state, hard expiry, Merkle inclusion and consistency |
| `TM-PKI-03` | independent M-of-N authorities, offline roots, bounded online keys, deterministic quorum failure |
| `TM-OPS-01` | minimal public fields, no user data or private governance evidence |
| `TM-SUPPLY-01` | pinned genesis, certified online keys, canonical objects, authenticated transitions |
| `TM-CRYPTO-01` | purpose-specific key hierarchy, bounded overlap, explicit compromise response |
| `TM-CRYPTO-02` | already-trusted authentication suite, composite all-component validation, no downgrade |
| `TM-AVAIL-01` | permissioned uploads, strict limits, non-amplification, explicit no-consensus state |
| `ARC-005` | Composer-validated complete authenticated network view |
| `ARC-007` | one owner and purpose for root, vote, operator, node, and epoch keys |
| `ARC-008` | restricted CBOR, exact schema, absolute limits, unknown-critical rejection |
| `ARC-009` | stale and hard-expiry states, no locally synthesized fallback consensus |
| `IF-03` | authenticated bounded node descriptor upload |
| `IF-04` | signed commit, reveal, proposal, signature, and checkpoint exchange |
| `IF-05` | immutable hash-addressed full consensus and offline update bundle |

## 35. Open Pre-Implementation Selections

The protocol structure is fixed, but these selections block implementation:

- exact encoding, vectors, implementation, artifact-separability analysis,
  side-channel evidence, and activation record for the non-active SHA3-256
  and ML-DSA-65 plus Ed25519 candidates;
- exact epoch duration, schedule offsets, freshness, hard expiry, and clock
  uncertainty;
- exact deterministic topology shuffle and diversity constraint algorithm;
- initial wire, KEMSphinx, entry, storage, cover, and application profile IDs;
- authority wire-key certificate issuance, storage, revocation, and rollover
  profile;
- initial lower operational document and node-count limits;
- hardware and ceremony profile for authority roots;
- monitor and witness operators for alpha;
- explicit `RecoveryManifest` ceremony and user interface;
- public governance reason-code registry and private evidence retention policy.

These values MUST be selected through reviewed profiles and conformance
vectors. Implementations MUST NOT invent local defaults.

## 36. References

- FOG threat model: `FOG-THREAT-MODEL.md`
- FOG architecture: `FOG-ARCHITECTURE.md`
- FOG wire protocol: `FOG-WIRE.md`
- FOG storage protocol: `FOG-STORAGE.md`
- FOG Composer protocol: `FOG-COMPOSER.md`
- FOG cryptographic suite evaluation: `FOG-CRYPTO-SUITES.md`
- FOG cryptographic benchmark baseline: `FOG-CRYPTO-BENCHMARKS.md`
- FOG local Podman PoC: `FOG-LOCAL-POC.md`
- NIST FIPS 204, Module-Lattice-Based Digital Signature Standard:
  <https://csrc.nist.gov/pubs/fips/204/final>
- RFC 9955, Hybrid Signature Spectrums:
  <https://www.rfc-editor.org/rfc/rfc9955.html>
- RFC 9980, Post-Quantum Cryptography in OpenPGP:
  <https://www.rfc-editor.org/rfc/rfc9980.html>
- Katzenpost public key infrastructure specification:
  <https://katzenpost.network/docs/specs/pki/>
- Katzenpost mix network specification:
  <https://katzenpost.network/docs/specs/mixnet/>
- Tor directory authority and consensus specifications:
  <https://spec.torproject.org/dir-spec/>
- Tor shared-random protocol:
  <https://spec.torproject.org/srv-spec/>
- RFC 8949, Concise Binary Object Representation:
  <https://www.rfc-editor.org/rfc/rfc8949.html>
- RFC 9162, Certificate Transparency Version 2.0:
  <https://www.rfc-editor.org/rfc/rfc9162.html>
- The Update Framework specification:
  <https://theupdateframework.github.io/specification/>

These references inform quorum operation, offline and online key separation,
deterministic encoding, append-only consistency proofs, root transitions,
rollback handling, and freeze detection. They do not make FOG-PKI secure by
inheritance. FOG requires its own concrete suites, test vectors,
implementations, operations, and independent review.