@xemahq/xema 0.40.1 → 0.40.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/edition/verify-image-evidence.bundle.provenance.json +39 -39
- package/edition/README.md +1 -0
- package/edition/build-biome-index.mjs +9 -4
- package/edition/build-runtime-image-source-index.mjs +177 -43
- package/edition/indexes-at-pins.mjs +5 -21
- package/edition/source-authority.mjs +2 -1
- package/package.json +2 -2
|
@@ -2383,229 +2383,229 @@
|
|
|
2383
2383
|
},
|
|
2384
2384
|
{
|
|
2385
2385
|
"package": "@xemahq/xema",
|
|
2386
|
-
"version": "0.40.
|
|
2386
|
+
"version": "0.40.3",
|
|
2387
2387
|
"path": "edition/adapter-host-versions.mjs",
|
|
2388
2388
|
"sha256": "sha256:1b7ebd3592f4da1225fba74aaba912e7d85fbceeb1626f7dcdac83491cbb4d69"
|
|
2389
2389
|
},
|
|
2390
2390
|
{
|
|
2391
2391
|
"package": "@xemahq/xema",
|
|
2392
|
-
"version": "0.40.
|
|
2392
|
+
"version": "0.40.3",
|
|
2393
2393
|
"path": "edition/authorization-base.mjs",
|
|
2394
2394
|
"sha256": "sha256:bbeac7ff01376cb89ed2140526d4795d8e559b3f01612b404a701f19aaa24c6a"
|
|
2395
2395
|
},
|
|
2396
2396
|
{
|
|
2397
2397
|
"package": "@xemahq/xema",
|
|
2398
|
-
"version": "0.40.
|
|
2398
|
+
"version": "0.40.3",
|
|
2399
2399
|
"path": "edition/build-ledger.mjs",
|
|
2400
2400
|
"sha256": "sha256:05202cbdd606aee086c8e9c62d28be68c429653a8b1d73a289ed0fe4ff14da85"
|
|
2401
2401
|
},
|
|
2402
2402
|
{
|
|
2403
2403
|
"package": "@xemahq/xema",
|
|
2404
|
-
"version": "0.40.
|
|
2404
|
+
"version": "0.40.3",
|
|
2405
2405
|
"path": "edition/connector-source-authority.mjs",
|
|
2406
2406
|
"sha256": "sha256:ea94475f4324737673accd7de1303c44db1cbc4dac61a865a06cd83abe310164"
|
|
2407
2407
|
},
|
|
2408
2408
|
{
|
|
2409
2409
|
"package": "@xemahq/xema",
|
|
2410
|
-
"version": "0.40.
|
|
2410
|
+
"version": "0.40.3",
|
|
2411
2411
|
"path": "edition/distribution-paths.mjs",
|
|
2412
2412
|
"sha256": "sha256:d78a5c8405bc6c25d36fcec61b0030e1fdacac7d528e698adb96f906f4b70279"
|
|
2413
2413
|
},
|
|
2414
2414
|
{
|
|
2415
2415
|
"package": "@xemahq/xema",
|
|
2416
|
-
"version": "0.40.
|
|
2416
|
+
"version": "0.40.3",
|
|
2417
2417
|
"path": "edition/edition-artifact.mjs",
|
|
2418
2418
|
"sha256": "sha256:287e4cf042626963e07396c706350e9668adbcacd238a7ad4db1d68bba3858b2"
|
|
2419
2419
|
},
|
|
2420
2420
|
{
|
|
2421
2421
|
"package": "@xemahq/xema",
|
|
2422
|
-
"version": "0.40.
|
|
2422
|
+
"version": "0.40.3",
|
|
2423
2423
|
"path": "edition/edition-channel.mjs",
|
|
2424
2424
|
"sha256": "sha256:3c0c1564dc50be133cad500452d953353aa5beb703142c05a17bbce8175ba9f3"
|
|
2425
2425
|
},
|
|
2426
2426
|
{
|
|
2427
2427
|
"package": "@xemahq/xema",
|
|
2428
|
-
"version": "0.40.
|
|
2428
|
+
"version": "0.40.3",
|
|
2429
2429
|
"path": "edition/edition-chart-set.mjs",
|
|
2430
2430
|
"sha256": "sha256:f9f16b58279c8c2619a39c5cc92bdbc334543d1a324304cd5d3b120d66dc8f3a"
|
|
2431
2431
|
},
|
|
2432
2432
|
{
|
|
2433
2433
|
"package": "@xemahq/xema",
|
|
2434
|
-
"version": "0.40.
|
|
2434
|
+
"version": "0.40.3",
|
|
2435
2435
|
"path": "edition/edition-config.mjs",
|
|
2436
2436
|
"sha256": "sha256:e3997bd9a0082e02d01760868b2a4f41ed3081e904126b30fdf86e7938dc6137"
|
|
2437
2437
|
},
|
|
2438
2438
|
{
|
|
2439
2439
|
"package": "@xemahq/xema",
|
|
2440
|
-
"version": "0.40.
|
|
2440
|
+
"version": "0.40.3",
|
|
2441
2441
|
"path": "edition/edition-constants.mjs",
|
|
2442
2442
|
"sha256": "sha256:71ae51028847ab3430ffec9b229b0516a7705b75a6de1fcfa665f5e1abf8e9bb"
|
|
2443
2443
|
},
|
|
2444
2444
|
{
|
|
2445
2445
|
"package": "@xemahq/xema",
|
|
2446
|
-
"version": "0.40.
|
|
2446
|
+
"version": "0.40.3",
|
|
2447
2447
|
"path": "edition/edition-contract-parse.mjs",
|
|
2448
2448
|
"sha256": "sha256:c575e96b70bda82899931eb0b18567988e2e13e664fa498bcbef96b571dcabb4"
|
|
2449
2449
|
},
|
|
2450
2450
|
{
|
|
2451
2451
|
"package": "@xemahq/xema",
|
|
2452
|
-
"version": "0.40.
|
|
2452
|
+
"version": "0.40.3",
|
|
2453
2453
|
"path": "edition/edition-contract.json",
|
|
2454
2454
|
"sha256": "sha256:aa1a05f1728813a7bdb1e02d9305e9adf641d695e6767305210c67a1d81b38a7"
|
|
2455
2455
|
},
|
|
2456
2456
|
{
|
|
2457
2457
|
"package": "@xemahq/xema",
|
|
2458
|
-
"version": "0.40.
|
|
2458
|
+
"version": "0.40.3",
|
|
2459
2459
|
"path": "edition/edition-protocol.mjs",
|
|
2460
2460
|
"sha256": "sha256:c488ac72ff3f23c0f28f8db159bf84d2c86ec5cda3633db1fe91ca3f21b12214"
|
|
2461
2461
|
},
|
|
2462
2462
|
{
|
|
2463
2463
|
"package": "@xemahq/xema",
|
|
2464
|
-
"version": "0.40.
|
|
2464
|
+
"version": "0.40.3",
|
|
2465
2465
|
"path": "edition/edition-source-pins.mjs",
|
|
2466
2466
|
"sha256": "sha256:b141474fff33b06734fb62cd2552752b991c8267bb1c9bccb22a81dd80e91c6c"
|
|
2467
2467
|
},
|
|
2468
2468
|
{
|
|
2469
2469
|
"package": "@xemahq/xema",
|
|
2470
|
-
"version": "0.40.
|
|
2470
|
+
"version": "0.40.3",
|
|
2471
2471
|
"path": "edition/edition-workspace.mjs",
|
|
2472
2472
|
"sha256": "sha256:18ba727e6b13ca252def25cc6bd9adf894cbc2018198c41ce522637eeac7f871"
|
|
2473
2473
|
},
|
|
2474
2474
|
{
|
|
2475
2475
|
"package": "@xemahq/xema",
|
|
2476
|
-
"version": "0.40.
|
|
2476
|
+
"version": "0.40.3",
|
|
2477
2477
|
"path": "edition/evidence-checkout.mjs",
|
|
2478
2478
|
"sha256": "sha256:31fb669769b31de4c6f2b2501bb96959548172ef166e7568edbbfed7f5079a11"
|
|
2479
2479
|
},
|
|
2480
2480
|
{
|
|
2481
2481
|
"package": "@xemahq/xema",
|
|
2482
|
-
"version": "0.40.
|
|
2482
|
+
"version": "0.40.3",
|
|
2483
2483
|
"path": "edition/evidence-grammars.mjs",
|
|
2484
2484
|
"sha256": "sha256:4dae22b61ade99219a482b971c9780d68a3d37d021e39cdfe860b245364b8b9f"
|
|
2485
2485
|
},
|
|
2486
2486
|
{
|
|
2487
2487
|
"package": "@xemahq/xema",
|
|
2488
|
-
"version": "0.40.
|
|
2488
|
+
"version": "0.40.3",
|
|
2489
2489
|
"path": "edition/evidence-trust-pin.mjs",
|
|
2490
2490
|
"sha256": "sha256:b9dd5c01903394436530783614efb0cd357d982ed2befd844a39328479773cbc"
|
|
2491
2491
|
},
|
|
2492
2492
|
{
|
|
2493
2493
|
"package": "@xemahq/xema",
|
|
2494
|
-
"version": "0.40.
|
|
2494
|
+
"version": "0.40.3",
|
|
2495
2495
|
"path": "edition/git-json.mjs",
|
|
2496
2496
|
"sha256": "sha256:d0d25cda0c19007becabc9a2827c3dcf759b295cd0b41596eb4480c9549a1f21"
|
|
2497
2497
|
},
|
|
2498
2498
|
{
|
|
2499
2499
|
"package": "@xemahq/xema",
|
|
2500
|
-
"version": "0.40.
|
|
2500
|
+
"version": "0.40.3",
|
|
2501
2501
|
"path": "edition/image-delivery-entitlement-descriptor.mjs",
|
|
2502
2502
|
"sha256": "sha256:4726b66116f01bf2523fafe2b7a356591eca8fb5ca6bd8b154dd4821873e921b"
|
|
2503
2503
|
},
|
|
2504
2504
|
{
|
|
2505
2505
|
"package": "@xemahq/xema",
|
|
2506
|
-
"version": "0.40.
|
|
2506
|
+
"version": "0.40.3",
|
|
2507
2507
|
"path": "edition/image-evidence-replay-state.mjs",
|
|
2508
2508
|
"sha256": "sha256:eba0cf1d38af0ab2f00c5099fa8bc2edc543136ce92f895544d4d284b3d6af0f"
|
|
2509
2509
|
},
|
|
2510
2510
|
{
|
|
2511
2511
|
"package": "@xemahq/xema",
|
|
2512
|
-
"version": "0.40.
|
|
2512
|
+
"version": "0.40.3",
|
|
2513
2513
|
"path": "edition/image-evidence.mjs",
|
|
2514
2514
|
"sha256": "sha256:433202eb2db84510acd11de6fe5ede81c8d96b8bc72991444940f7f84a48897f"
|
|
2515
2515
|
},
|
|
2516
2516
|
{
|
|
2517
2517
|
"package": "@xemahq/xema",
|
|
2518
|
-
"version": "0.40.
|
|
2518
|
+
"version": "0.40.3",
|
|
2519
2519
|
"path": "edition/kernel-capability-domain.mjs",
|
|
2520
2520
|
"sha256": "sha256:3ecf887dd8d399e91a8285f6f115f6e418fb59bbf3f004539fe65ec667219356"
|
|
2521
2521
|
},
|
|
2522
2522
|
{
|
|
2523
2523
|
"package": "@xemahq/xema",
|
|
2524
|
-
"version": "0.40.
|
|
2524
|
+
"version": "0.40.3",
|
|
2525
2525
|
"path": "edition/kernel-contract-authority.mjs",
|
|
2526
2526
|
"sha256": "sha256:20abdde62a7b037c01ea9bbe1ff1e6094e6b0efd0add2f656f1938a04409bf82"
|
|
2527
2527
|
},
|
|
2528
2528
|
{
|
|
2529
2529
|
"package": "@xemahq/xema",
|
|
2530
|
-
"version": "0.40.
|
|
2530
|
+
"version": "0.40.3",
|
|
2531
2531
|
"path": "edition/lib.mjs",
|
|
2532
2532
|
"sha256": "sha256:862a21a357f5219dc6d549fe83209267a5010461f1f7889bf63d0baa6423de2e"
|
|
2533
2533
|
},
|
|
2534
2534
|
{
|
|
2535
2535
|
"package": "@xemahq/xema",
|
|
2536
|
-
"version": "0.40.
|
|
2536
|
+
"version": "0.40.3",
|
|
2537
2537
|
"path": "edition/no-follow-file.mjs",
|
|
2538
2538
|
"sha256": "sha256:c17bdf5e441f3c079aa06d4b48bbed05cad087855b9ad2a5e6dc43d5ee2b17c3"
|
|
2539
2539
|
},
|
|
2540
2540
|
{
|
|
2541
2541
|
"package": "@xemahq/xema",
|
|
2542
|
-
"version": "0.40.
|
|
2542
|
+
"version": "0.40.3",
|
|
2543
2543
|
"path": "edition/operation-requirements.mjs",
|
|
2544
2544
|
"sha256": "sha256:e7fed25747ee92be84cdc864ca35a723356df5b3d08923cf71f4bc66a791eb5d"
|
|
2545
2545
|
},
|
|
2546
2546
|
{
|
|
2547
2547
|
"package": "@xemahq/xema",
|
|
2548
|
-
"version": "0.40.
|
|
2548
|
+
"version": "0.40.3",
|
|
2549
2549
|
"path": "edition/pin-source.mjs",
|
|
2550
2550
|
"sha256": "sha256:a23fef4698ef66ba9de4a1aabe3eebe6487d1f105f3fc161bafc5a33b99a2440"
|
|
2551
2551
|
},
|
|
2552
2552
|
{
|
|
2553
2553
|
"package": "@xemahq/xema",
|
|
2554
|
-
"version": "0.40.
|
|
2554
|
+
"version": "0.40.3",
|
|
2555
2555
|
"path": "edition/source-authority.mjs",
|
|
2556
|
-
"sha256": "sha256:
|
|
2556
|
+
"sha256": "sha256:9c351f60e8ea838f445f89c3709c60b7f13b021b78d6e40eaef91350a793f0ff"
|
|
2557
2557
|
},
|
|
2558
2558
|
{
|
|
2559
2559
|
"package": "@xemahq/xema",
|
|
2560
|
-
"version": "0.40.
|
|
2560
|
+
"version": "0.40.3",
|
|
2561
2561
|
"path": "edition/strict-json.mjs",
|
|
2562
2562
|
"sha256": "sha256:f95778396df7f38b086f55d2ec4f3b6644a8aeff2b32282a62829145fb544562"
|
|
2563
2563
|
},
|
|
2564
2564
|
{
|
|
2565
2565
|
"package": "@xemahq/xema",
|
|
2566
|
-
"version": "0.40.
|
|
2566
|
+
"version": "0.40.3",
|
|
2567
2567
|
"path": "edition/string-order.mjs",
|
|
2568
2568
|
"sha256": "sha256:b3210cd273e4b2e01fb8b1a91e28734cd211d4010c080d0ce95f5e5ff631cffb"
|
|
2569
2569
|
},
|
|
2570
2570
|
{
|
|
2571
2571
|
"package": "@xemahq/xema",
|
|
2572
|
-
"version": "0.40.
|
|
2572
|
+
"version": "0.40.3",
|
|
2573
2573
|
"path": "edition/trusted-executable.mjs",
|
|
2574
2574
|
"sha256": "sha256:37d46cdbc999ddd55d4ea8aeed4850ddd1efde89ed7b532f5a2ddec87105d796"
|
|
2575
2575
|
},
|
|
2576
2576
|
{
|
|
2577
2577
|
"package": "@xemahq/xema",
|
|
2578
|
-
"version": "0.40.
|
|
2578
|
+
"version": "0.40.3",
|
|
2579
2579
|
"path": "edition/verifier-binding.mjs",
|
|
2580
2580
|
"sha256": "sha256:80732658617f5255258c538eeb2383331ec8553b44b58d552b567845a7b916aa"
|
|
2581
2581
|
},
|
|
2582
2582
|
{
|
|
2583
2583
|
"package": "@xemahq/xema",
|
|
2584
|
-
"version": "0.40.
|
|
2584
|
+
"version": "0.40.3",
|
|
2585
2585
|
"path": "edition/verifier-files.mjs",
|
|
2586
2586
|
"sha256": "sha256:cdd14a20a63f0f194a8abb55680a5a7e3ced1f09f8b210a90d349e655f6de0c0"
|
|
2587
2587
|
},
|
|
2588
2588
|
{
|
|
2589
2589
|
"package": "@xemahq/xema",
|
|
2590
|
-
"version": "0.40.
|
|
2590
|
+
"version": "0.40.3",
|
|
2591
2591
|
"path": "edition/verifier-provenance.mjs",
|
|
2592
2592
|
"sha256": "sha256:3e2fb8e07cf1f66b8ad6c7ac2555fe3af64ec7abeb07cecbaf1939a18c2b3663"
|
|
2593
2593
|
},
|
|
2594
2594
|
{
|
|
2595
2595
|
"package": "@xemahq/xema",
|
|
2596
|
-
"version": "0.40.
|
|
2596
|
+
"version": "0.40.3",
|
|
2597
2597
|
"path": "edition/verify-image-evidence.mjs",
|
|
2598
2598
|
"sha256": "sha256:62f83f8bb835f360535402d12657156d2c9d6e651b426c2b30a04a2dc2f8d3e8"
|
|
2599
2599
|
},
|
|
2600
2600
|
{
|
|
2601
2601
|
"package": "@xemahq/xema",
|
|
2602
|
-
"version": "0.40.
|
|
2602
|
+
"version": "0.40.3",
|
|
2603
2603
|
"path": "edition/workspace-sections.mjs",
|
|
2604
2604
|
"sha256": "sha256:383f37ce066ea5573c30cedf124022095bf94d050f0a266a5881f587cff0ced0"
|
|
2605
2605
|
},
|
|
2606
2606
|
{
|
|
2607
2607
|
"package": "@xemahq/xema",
|
|
2608
|
-
"version": "0.40.
|
|
2608
|
+
"version": "0.40.3",
|
|
2609
2609
|
"path": "scripts/build-evidence-verifier.mjs",
|
|
2610
2610
|
"sha256": "sha256:5a688d20c47dc88aff37aa0c6cc02daf2c370a5bc610fef8446ce7be222d4c0b"
|
|
2611
2611
|
},
|
package/edition/README.md
CHANGED
|
@@ -99,6 +99,7 @@ The edition library builds, validates and verifies evidence statements; it never
|
|
|
99
99
|
The CLI is coupled to the kernel's edition protocol, not to the kernel package. `@xemahq/contracts` exports the protocol identity as data (`dist/edition-protocol/edition-protocol.json`: `{contentDigest, provisional, version}`). This CLI supports exactly protocol v8 (a data root whose pinned kernel speaks v5 stays on CLI 0.33.x) and REFUSES an identity with `provisional: true`; every loader that executes the kernel, `xema edition check` first, and the evidence verifier compare only that identity and refuse an unsupported one, naming the supported and the declared versions. A protocol change needs a CLI release first; only then does the data root repin its kernel authority.
|
|
100
100
|
|
|
101
101
|
- `xema edition evidence statement entitlement stage` writes entitlement predicate v2 (`lockDigest`, `catalogueDigest`, read from the edition's committed locks), so it takes `--editions-root` besides `--data-root` and `--kernel`.
|
|
102
|
+
- A source repository JOINS a data root that has committed pins with one command: `xema edition index runtime-image-source --trusted-write --repo <repository> [--at <40-hex>] [--kernel-root <checkout>]`. The repository is resolved once and the runtime image source, biome and platform-service indexes are all written from the committed pins plus that one pin; every committed pin is kept field for field (a differing one is refused by name), a second declared repository with no pin is refused, and the summary names each pin added, moved and dropped. Then `xema edition index biome --check`, `xema edition index runtime-image-source --check` and `pnpm check`. The biome builder takes no `--repo`: it would resolve the repository a second time.
|
|
102
103
|
- The runtime image source index is v2 and carries operator-stated `producerWorkflowPins` (the workflow commit a producer certificate must be signed from, per repository). `xema edition index runtime-image-source [--producer-workflow-pin <owner/repo>=<40-hex>]...` preserves the committed pins exactly; each flag sets one repository's pin (repeatable; a repeated or non-GitHub `owner/repo` is refused; only `--trusted-write` writes an index, so the flag with any other mode, `--check-sources` included, is refused); a bootstrap index with none writes `[]`. A v1 index is refused, never migrated: delete it and bootstrap a new one with `--kernel-commit`.
|
|
103
104
|
|
|
104
105
|
## Build ledger completeness
|
|
@@ -67,10 +67,15 @@ if (isEntryModule(import.meta.url)) {
|
|
|
67
67
|
* `--unpinned` is the escape, and it is a POLICY operation rather than a
|
|
68
68
|
* correctness one. Two cases need it and no third has appeared:
|
|
69
69
|
*
|
|
70
|
-
* - BOOTSTRAP — a
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
70
|
+
* - BOOTSTRAP — a data root with no committed pins at all. A repository
|
|
71
|
+
* JOINING a data root that has pins is not this case: it has no pin yet,
|
|
72
|
+
* and `createPinnedSourceAuthority` refuses it here rather than resolving
|
|
73
|
+
* it live. The join is `build-runtime-image-source-index.mjs
|
|
74
|
+
* --trusted-write --repo <repository> [--at <sha>]`, which resolves the
|
|
75
|
+
* joining repository ONCE and writes this index, the platform-service
|
|
76
|
+
* index and the runtime index from that one pin set, every committed pin
|
|
77
|
+
* kept (`buildIndexesWithJoiningRepository`). A `--repo` here would
|
|
78
|
+
* resolve it a second time: the race above.
|
|
74
79
|
* - WORKSPACE — `--source workspace` snapshots a dirty local tree, which has
|
|
75
80
|
* no pin by construction. It therefore IMPLIES `--unpinned`, rather than
|
|
76
81
|
* making the operator state both.
|
|
@@ -4,9 +4,10 @@ import { execFileSync } from 'node:child_process';
|
|
|
4
4
|
import { existsSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
|
|
5
5
|
import { isAbsolute, join } from 'node:path';
|
|
6
6
|
|
|
7
|
+
import { buildValidatedPlatformServiceIndex } from './build-platform-service-index.mjs';
|
|
7
8
|
import { connectorCrossRepoBuildInputs } from './connector-source-authority.mjs';
|
|
8
9
|
import { editionWorkspaceConfig, workspaceSection } from './edition-config.mjs';
|
|
9
|
-
import { biomeIndexPath, dataRoot, runtimeImageSourceIndexPath, WorkspaceRoot, configureEditionWorkspaceFromProcess, isEntryModule, sourcePath } from './edition-workspace.mjs';
|
|
10
|
+
import { biomeIndexPath, dataRoot, platformServiceIndexPath, runtimeImageSourceIndexPath, WorkspaceRoot, configureEditionWorkspaceFromProcess, isEntryModule, sourcePath } from './edition-workspace.mjs';
|
|
10
11
|
import { COMMIT_PATTERN } from './evidence-grammars.mjs';
|
|
11
12
|
import {
|
|
12
13
|
buildTrustedKernelContractAuthority,
|
|
@@ -15,8 +16,10 @@ import {
|
|
|
15
16
|
validateKernelContractAuthorityFromGit,
|
|
16
17
|
} from './kernel-contract-authority.mjs';
|
|
17
18
|
import {
|
|
19
|
+
buildBiomeIndex,
|
|
18
20
|
canonicalPublicHttpsRepositoryUrl,
|
|
19
21
|
compareStrings,
|
|
22
|
+
distributionBiomeSourceRepositories,
|
|
20
23
|
loadKernelDistributionSchemas,
|
|
21
24
|
readGitJsonAtCommit,
|
|
22
25
|
serializeJson,
|
|
@@ -27,6 +30,7 @@ import {
|
|
|
27
30
|
} from './platform-service-source-authority.mjs';
|
|
28
31
|
import {
|
|
29
32
|
createExactCommitSourceAuthority,
|
|
33
|
+
createPinnedSourceAuthority,
|
|
30
34
|
createSourceAuthority,
|
|
31
35
|
parseSourceModeArgs,
|
|
32
36
|
} from './source-authority.mjs';
|
|
@@ -140,7 +144,7 @@ function declaredSourceRepositories() {
|
|
|
140
144
|
* ONE authority that answers both questions about a component, never two
|
|
141
145
|
* competing ones that can disagree about which commit a component is at.
|
|
142
146
|
*/
|
|
143
|
-
function repositoryIdentity(repo, sourceAuthority) {
|
|
147
|
+
export function repositoryIdentity(repo, sourceAuthority) {
|
|
144
148
|
const repoDirectory = sourcePath(repo);
|
|
145
149
|
const sourceCommit = sourceAuthority.commitForRepository(repo);
|
|
146
150
|
const vendoredSourceCommit =
|
|
@@ -322,6 +326,11 @@ async function resolveContractAuthority(schemas, kernelRoot, kernelCommit) {
|
|
|
322
326
|
*
|
|
323
327
|
* A repository this index does not source is a REFUSAL, never a silent no-op —
|
|
324
328
|
* a typo that quietly rewrote nothing would read in review as "the refresh ran".
|
|
329
|
+
*
|
|
330
|
+
* A declared source repository with NO committed pin JOINS the index through the
|
|
331
|
+
* same scope: every committed pin is preserved verbatim and only the named
|
|
332
|
+
* repository is resolved (at `--at`, which must be published). It needs no
|
|
333
|
+
* full `--trusted-write`, which would re-derive and drift every other pin.
|
|
325
334
|
*/
|
|
326
335
|
export function preserveOtherRepositoryPins(
|
|
327
336
|
repoScope,
|
|
@@ -343,12 +352,6 @@ export function preserveOtherRepositoryPins(
|
|
|
343
352
|
'the committed runtime image source index declares no repositoryPins to preserve',
|
|
344
353
|
);
|
|
345
354
|
}
|
|
346
|
-
if (!pins.some((pin) => pin.repo === repoScope)) {
|
|
347
|
-
throw new Error(
|
|
348
|
-
`--repo "${repoScope}" has no committed pin to refresh. A repository ` +
|
|
349
|
-
`joining this index is a full --trusted-write, not a scoped refresh.`,
|
|
350
|
-
);
|
|
351
|
-
}
|
|
352
355
|
return pins
|
|
353
356
|
.filter((pin) => pin.repo !== repoScope)
|
|
354
357
|
.map((pin) => ({
|
|
@@ -463,6 +466,13 @@ export async function buildTrustedIndex(
|
|
|
463
466
|
const getRepositoryIdentity = (repo) => {
|
|
464
467
|
let identity = repositoryIdentities.get(repo);
|
|
465
468
|
if (!identity) {
|
|
469
|
+
if (repoScope !== undefined && repo !== repoScope) {
|
|
470
|
+
throw new Error(
|
|
471
|
+
`source repository "${repo}" has no committed pin and is not the --repo scope ` +
|
|
472
|
+
`"${repoScope}". A scoped write adds one repository; resolving "${repo}" live ` +
|
|
473
|
+
`would re-pin a repository nobody asked about. Add it with its own --repo ${repo} --at <sha>.`,
|
|
474
|
+
);
|
|
475
|
+
}
|
|
466
476
|
identity = repositoryIdentity(repo, sourceAuthority);
|
|
467
477
|
repositoryIdentities.set(repo, identity);
|
|
468
478
|
}
|
|
@@ -828,6 +838,107 @@ function parseKernelCommit(argv) {
|
|
|
828
838
|
};
|
|
829
839
|
}
|
|
830
840
|
|
|
841
|
+
/**
|
|
842
|
+
* @param {{ schemas: object, repositoryPins: object[], kernelRoot?: string, producerWorkflowPins?: object[] }} request
|
|
843
|
+
* `kernelRoot` is the kernel checkout the committed contract authority is re-verified against
|
|
844
|
+
* (the default checkout when omitted); `producerWorkflowPins` are the operator-stated ones a
|
|
845
|
+
* trusted write merges over the committed ones.
|
|
846
|
+
* @returns {{ platformServiceIndex, biomeIndex, runtimeImageSourceIndex }}
|
|
847
|
+
*/
|
|
848
|
+
export async function buildIndexesAtPins({ schemas, repositoryPins, kernelRoot, producerWorkflowPins = [] }) {
|
|
849
|
+
const sourceAuthority = createPinnedSourceAuthority({ pins: repositoryPins });
|
|
850
|
+
const platformServiceIndex = buildValidatedPlatformServiceIndex(schemas, sourceAuthority);
|
|
851
|
+
const biomeIndex = await buildBiomeIndex(platformServiceIndex, distributionBiomeSourceRepositories(), sourceAuthority);
|
|
852
|
+
const runtimeImageSourceIndex = schemas.parseRuntimeImageSourceIndex(
|
|
853
|
+
await buildTrustedIndex(schemas, sourceAuthority, kernelRoot, undefined, {
|
|
854
|
+
biomeIndex,
|
|
855
|
+
platformServiceIndex,
|
|
856
|
+
producerWorkflowPins,
|
|
857
|
+
}),
|
|
858
|
+
);
|
|
859
|
+
await validateRuntimeImageSourceIndex(runtimeImageSourceIndex, schemas, { biomeIndex, platformServiceIndex, kernelRoot });
|
|
860
|
+
return { platformServiceIndex, biomeIndex, runtimeImageSourceIndex };
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
/**
|
|
864
|
+
* A repository JOINING the index (`--repo <repository>` with no committed pin): all three indexes,
|
|
865
|
+
* from ONE resolution of the joining repository, with every committed pin kept.
|
|
866
|
+
*
|
|
867
|
+
* WHY HERE AND NOT A `--repo` ON THE BIOME BUILDER. The biome builder's `--repo` was removed
|
|
868
|
+
* because it resolved the scoped repository LIVE a second time, so a build landing between the two
|
|
869
|
+
* commands split the two artifacts on exactly that repository (see `build-biome-index.mjs`). A
|
|
870
|
+
* joining repository has the same shape: the runtime index cannot take it until the biome index
|
|
871
|
+
* names its biomes, and the biome index cannot take it until a pin exists. So the joining
|
|
872
|
+
* repository is resolved ONCE here (`sourceAuthority`, live or `--at`), appended to the committed
|
|
873
|
+
* pins, and every index is derived from that one pin set by the same builders a develop snapshot
|
|
874
|
+
* uses; nothing else is resolved live.
|
|
875
|
+
*
|
|
876
|
+
* Every committed pin that survives must come back field for field; one that differs is refused by
|
|
877
|
+
* name. A committed pin whose repository is no longer a source repository is DROPPED, and the caller
|
|
878
|
+
* names it (`describeRepositoryPinChanges`). A second declared repository with no pin is refused by
|
|
879
|
+
* the pinned authority: one joining repository per write.
|
|
880
|
+
*/
|
|
881
|
+
export async function buildIndexesWithJoiningRepository({
|
|
882
|
+
schemas,
|
|
883
|
+
sourceAuthority,
|
|
884
|
+
repoScope,
|
|
885
|
+
committedPins,
|
|
886
|
+
kernelRoot,
|
|
887
|
+
producerWorkflowPins = [],
|
|
888
|
+
}) {
|
|
889
|
+
if (committedPins.some((pin) => pin.repo === repoScope)) {
|
|
890
|
+
throw new Error(`--repo "${repoScope}" already has a committed pin: it is a refresh, not a join`);
|
|
891
|
+
}
|
|
892
|
+
const kept = committedPins.map(({ repo, repositoryUrl, sourceCommit, vendoredSourceCommit }) => ({
|
|
893
|
+
repo,
|
|
894
|
+
repositoryUrl,
|
|
895
|
+
sourceCommit,
|
|
896
|
+
vendoredSourceCommit,
|
|
897
|
+
}));
|
|
898
|
+
const repositoryPins = [...kept, repositoryIdentity(repoScope, sourceAuthority)];
|
|
899
|
+
const built = await buildIndexesAtPins({ schemas, repositoryPins, kernelRoot, producerWorkflowPins });
|
|
900
|
+
const written = new Map(built.runtimeImageSourceIndex.repositoryPins.map((pin) => [pin.repo, pin]));
|
|
901
|
+
const moved = kept.filter((pin) => written.has(pin.repo) && serializeJson(written.get(pin.repo)) !== serializeJson(pin));
|
|
902
|
+
if (moved.length > 0) {
|
|
903
|
+
throw new Error(
|
|
904
|
+
`a join must keep every committed pin, and ${moved.map((pin) => pin.repo).join(', ')} came back different ` +
|
|
905
|
+
'(its repositoryUrl no longer matches its origin remote?)',
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
if (!written.has(repoScope)) {
|
|
909
|
+
throw new Error(
|
|
910
|
+
`--repo "${repoScope}" contributes no biome, platform service or supplemental subject at ` +
|
|
911
|
+
`${repositoryPins.at(-1).sourceCommit}: there is nothing for it to join`,
|
|
912
|
+
);
|
|
913
|
+
}
|
|
914
|
+
return built;
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
/**
|
|
918
|
+
* What a write did to the committed `repositoryPins`, by NAME: the repositories added, the ones
|
|
919
|
+
* dropped (a committed pin whose repository no longer sources any subject), the ones moved, and
|
|
920
|
+
* how many were kept unchanged. A count alone hid a dropped pin inside "N other pin(s)
|
|
921
|
+
* preserved", which is the one change a reviewer must see.
|
|
922
|
+
*/
|
|
923
|
+
export function describeRepositoryPinChanges(committedPins, writtenPins) {
|
|
924
|
+
const committed = new Map((committedPins ?? []).map((pin) => [pin.repo, pin]));
|
|
925
|
+
const written = new Map(writtenPins.map((pin) => [pin.repo, pin]));
|
|
926
|
+
const added = [...written.keys()].filter((repo) => !committed.has(repo)).sort(compareStrings);
|
|
927
|
+
const dropped = [...committed.keys()].filter((repo) => !written.has(repo)).sort(compareStrings);
|
|
928
|
+
const moved = [...written.keys()]
|
|
929
|
+
.filter((repo) => committed.has(repo) && serializeJson(committed.get(repo)) !== serializeJson(written.get(repo)))
|
|
930
|
+
.sort(compareStrings);
|
|
931
|
+
const kept = written.size - added.length - moved.length;
|
|
932
|
+
const named = (label, repos) => `${label} ${repos.length}${repos.length > 0 ? ` (${repos.join(', ')})` : ''}`;
|
|
933
|
+
return {
|
|
934
|
+
added,
|
|
935
|
+
dropped,
|
|
936
|
+
moved,
|
|
937
|
+
kept,
|
|
938
|
+
summary: `${named('added', added)}; ${named('moved', moved)}; ${named('dropped', dropped)}; kept ${kept} unchanged`,
|
|
939
|
+
};
|
|
940
|
+
}
|
|
941
|
+
|
|
831
942
|
const REPIN_FLAG = '--repin-contract-authority';
|
|
832
943
|
const USAGE =
|
|
833
944
|
'usage: build-runtime-image-source-index.mjs (--check | --check-sources | --trusted-write | ' +
|
|
@@ -892,55 +1003,78 @@ async function main() {
|
|
|
892
1003
|
);
|
|
893
1004
|
return;
|
|
894
1005
|
}
|
|
895
|
-
const
|
|
896
|
-
|
|
1006
|
+
const committedPins = existsSync(runtimeImageSourceIndexPath())
|
|
1007
|
+
? readJson(runtimeImageSourceIndexPath()).repositoryPins ?? []
|
|
1008
|
+
: [];
|
|
1009
|
+
const liveAuthority = () => createSourceAuthority({ mode, knownRepositories: declaredSourceRepositories() });
|
|
1010
|
+
const sourceAuthority =
|
|
1011
|
+
exactCommit === undefined
|
|
1012
|
+
? liveAuthority()
|
|
1013
|
+
: createExactCommitSourceAuthority({ delegate: liveAuthority(), repo: repoScope, commit: exactCommit });
|
|
1014
|
+
// A `--repo` with no committed pin JOINS the index, and the biome and platform-service indexes
|
|
1015
|
+
// must take it in the same write: see `buildIndexesWithJoiningRepository`.
|
|
1016
|
+
const joining = repoScope !== undefined && !committedPins.some((pin) => pin.repo === repoScope);
|
|
1017
|
+
let candidate;
|
|
1018
|
+
let joined;
|
|
1019
|
+
if (joining) {
|
|
1020
|
+
if (committedPins.length === 0) {
|
|
1021
|
+
throw new Error(
|
|
1022
|
+
`--repo requires ${runtimeImageSourceIndexPath()} with committed repositoryPins: there are none to keep. ` +
|
|
1023
|
+
'Bootstrap with --trusted-write and no --repo.',
|
|
1024
|
+
);
|
|
1025
|
+
}
|
|
1026
|
+
if (kernelCommit !== undefined) {
|
|
1027
|
+
throw new Error(`${KERNEL_COMMIT_FLAG} chooses a new contract authority; a join keeps the committed one`);
|
|
1028
|
+
}
|
|
1029
|
+
joined = await buildIndexesWithJoiningRepository({
|
|
897
1030
|
schemas,
|
|
898
|
-
|
|
899
|
-
? createSourceAuthority({
|
|
900
|
-
mode,
|
|
901
|
-
knownRepositories: declaredSourceRepositories(),
|
|
902
|
-
})
|
|
903
|
-
: createExactCommitSourceAuthority({
|
|
904
|
-
delegate: createSourceAuthority({
|
|
905
|
-
mode,
|
|
906
|
-
knownRepositories: declaredSourceRepositories(),
|
|
907
|
-
}),
|
|
908
|
-
repo: repoScope,
|
|
909
|
-
commit: exactCommit,
|
|
910
|
-
}),
|
|
911
|
-
kernelRoot,
|
|
1031
|
+
sourceAuthority,
|
|
912
1032
|
repoScope,
|
|
913
|
-
|
|
1033
|
+
committedPins,
|
|
1034
|
+
kernelRoot,
|
|
1035
|
+
producerWorkflowPins,
|
|
1036
|
+
});
|
|
1037
|
+
candidate = joined.runtimeImageSourceIndex;
|
|
1038
|
+
} else {
|
|
1039
|
+
candidate = schemas.parseRuntimeImageSourceIndex(
|
|
1040
|
+
await buildTrustedIndex(schemas, sourceAuthority, kernelRoot, repoScope, {
|
|
914
1041
|
biomeIndex: readJson(biomeIndexPath()),
|
|
915
1042
|
platformServiceIndex: readJson(join(dataRoot(), 'platform-service-index.json')),
|
|
916
1043
|
kernelCommit,
|
|
917
1044
|
producerWorkflowPins,
|
|
918
|
-
},
|
|
919
|
-
)
|
|
920
|
-
|
|
921
|
-
|
|
1045
|
+
}),
|
|
1046
|
+
);
|
|
1047
|
+
await validateRuntimeImageSourceIndex(candidate, schemas, { kernelRoot });
|
|
1048
|
+
}
|
|
1049
|
+
const outputs = [
|
|
1050
|
+
[runtimeImageSourceIndexPath(), serializeJson(candidate)],
|
|
1051
|
+
...(joined === undefined
|
|
1052
|
+
? []
|
|
1053
|
+
: [
|
|
1054
|
+
[biomeIndexPath(), serializeJson(joined.biomeIndex)],
|
|
1055
|
+
[platformServiceIndexPath(), serializeJson(joined.platformServiceIndex)],
|
|
1056
|
+
]),
|
|
1057
|
+
];
|
|
922
1058
|
if (flag === '--check-sources') {
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
serializeJson(candidate)
|
|
926
|
-
) {
|
|
1059
|
+
const stale = outputs.filter(([path, text]) => !existsSync(path) || readFileSync(path, 'utf8') !== text);
|
|
1060
|
+
if (stale.length > 0) {
|
|
927
1061
|
throw new Error(
|
|
928
|
-
|
|
1062
|
+
`${stale.map(([path]) => path).join(', ')} does not match exact trusted sources`,
|
|
929
1063
|
);
|
|
930
1064
|
}
|
|
931
1065
|
console.log('[runtime-image-source-index] trusted source check passed');
|
|
932
1066
|
return;
|
|
933
1067
|
}
|
|
934
|
-
writeFileSync(
|
|
1068
|
+
for (const [path, text] of outputs) {writeFileSync(path, text);}
|
|
1069
|
+
const changes = describeRepositoryPinChanges(committedPins, candidate.repositoryPins);
|
|
935
1070
|
console.log(
|
|
936
|
-
`[runtime-image-source-index] wrote ${
|
|
937
|
-
|
|
938
|
-
? '
|
|
939
|
-
:
|
|
940
|
-
exactCommit === undefined
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
}; ${candidate.repositoryPins.length - 1} other pin(s) preserved)`),
|
|
1071
|
+
`[runtime-image-source-index] wrote ${outputs.map(([path]) => path).join(', ')} (${
|
|
1072
|
+
repoScope === undefined
|
|
1073
|
+
? 'all repository pins re-resolved'
|
|
1074
|
+
: `${joining ? 'joined' : 're-resolved'} ${repoScope}${
|
|
1075
|
+
exactCommit === undefined ? '' : ` at the exact commit ${exactCommit}`
|
|
1076
|
+
}`
|
|
1077
|
+
}; ${changes.summary})`,
|
|
944
1078
|
);
|
|
945
1079
|
}
|
|
946
1080
|
|
|
@@ -5,25 +5,9 @@
|
|
|
5
5
|
// authority; this runs the same builders, in memory, over any pin set. A develop
|
|
6
6
|
// snapshot (develop-snapshot-inputs.mjs) and a vendor edition that holds
|
|
7
7
|
// repositories (edition-pinned-inputs.mjs) both derive their indexes here, so
|
|
8
|
-
// there is no second builder.
|
|
9
|
-
//
|
|
8
|
+
// there is no second builder. The implementation lives beside the runtime index
|
|
9
|
+
// builder, whose repository join (`--repo` with no committed pin) uses it too.
|
|
10
|
+
// No fallback: the authority has no delegate, so a repository the pins do not
|
|
11
|
+
// name refuses by name instead of resolving to a tip.
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
import { buildTrustedIndex, validateRuntimeImageSourceIndex } from './build-runtime-image-source-index.mjs';
|
|
13
|
-
import { buildBiomeIndex, distributionBiomeSourceRepositories } from './lib.mjs';
|
|
14
|
-
import { createPinnedSourceAuthority } from './source-authority.mjs';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* @param {{ schemas: object, repositoryPins: object[] }} request
|
|
18
|
-
* @returns {{ platformServiceIndex, biomeIndex, runtimeImageSourceIndex }}
|
|
19
|
-
*/
|
|
20
|
-
export async function buildIndexesAtPins({ schemas, repositoryPins }) {
|
|
21
|
-
const sourceAuthority = createPinnedSourceAuthority({ pins: repositoryPins });
|
|
22
|
-
const platformServiceIndex = buildValidatedPlatformServiceIndex(schemas, sourceAuthority);
|
|
23
|
-
const biomeIndex = await buildBiomeIndex(platformServiceIndex, distributionBiomeSourceRepositories(), sourceAuthority);
|
|
24
|
-
const runtimeImageSourceIndex = schemas.parseRuntimeImageSourceIndex(
|
|
25
|
-
await buildTrustedIndex(schemas, sourceAuthority, undefined, undefined, { biomeIndex, platformServiceIndex }),
|
|
26
|
-
);
|
|
27
|
-
await validateRuntimeImageSourceIndex(runtimeImageSourceIndex, schemas, { biomeIndex, platformServiceIndex });
|
|
28
|
-
return { platformServiceIndex, biomeIndex, runtimeImageSourceIndex };
|
|
29
|
-
}
|
|
13
|
+
export { buildIndexesAtPins, buildIndexesWithJoiningRepository } from './build-runtime-image-source-index.mjs';
|
|
@@ -519,7 +519,8 @@ export function createPinnedSourceAuthority({
|
|
|
519
519
|
if (refreshRepository !== undefined && !byRepo.has(refreshRepository)) {
|
|
520
520
|
throw new Error(
|
|
521
521
|
`refresh scope "${refreshRepository}" has no pin to refresh. A repository ` +
|
|
522
|
-
`joining the index
|
|
522
|
+
`joining the index joins through build-runtime-image-source-index.mjs ` +
|
|
523
|
+
`--trusted-write --repo ${refreshRepository}, which writes every index.`,
|
|
523
524
|
);
|
|
524
525
|
}
|
|
525
526
|
const pinned = (repo, field) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xemahq/xema",
|
|
3
|
-
"version": "0.40.
|
|
3
|
+
"version": "0.40.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/xema-dev/xema-cli.git",
|
|
@@ -92,6 +92,6 @@
|
|
|
92
92
|
"typecheck": "tsc --noEmit"
|
|
93
93
|
},
|
|
94
94
|
"xemaRelease": {
|
|
95
|
-
"sourceDigest": "sha256:
|
|
95
|
+
"sourceDigest": "sha256:55a458c54ff157ee053b4f074068c355fb35d28f54a01b0a2662bf14b07b8323"
|
|
96
96
|
}
|
|
97
97
|
}
|