Skip to content

Commit 52d25fa

Browse files
authored
thirdparty: add managed tccbin baseline activation (#28154)
1 parent 9142d68 commit 52d25fa

12 files changed

Lines changed: 2599 additions & 24 deletions

doc/tccbin_automation.md

Lines changed: 117 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,14 +256,17 @@ blob, provenance, contract-binding, and publication decision to the existing sta
256256

257257
```sh
258258
tccbin-automation candidate-preflight \
259-
<target-id> <monthly|legacy-onboard> <candidate-repo-root> \
259+
<target-id> <monthly|legacy-onboard|baseline-activate> <candidate-repo-root> \
260260
<base-sha> <candidate-sha> <work-root> <publish-requested>
261261
```
262262

263263
The successful work root contains detached `base-source/` and `candidate-source/` clones and the
264264
payload-only `payload/`. A caller may continue only when the command reports both `eligible=true`
265265
and, for publication, `publish_allowed=true`.
266266

267+
`baseline-activate` is validation-only: `publish-requested=true` is rejected immediately after its
268+
reviewed policy is loaded and before candidate input or a work root is touched.
269+
267270
### Candidate composition and dormant legacy onboarding
268271

269272
`candidate-compose` constructs a candidate without mutating its reviewed base or the RAW build
@@ -280,7 +283,7 @@ publication-disabled candidate preflight.
280283

281284
```sh
282285
tccbin-automation candidate-compose \
283-
<target-id> <monthly|legacy-onboard> <base-repo-root> <base-sha> \
286+
<target-id> <monthly|legacy-onboard|baseline-activate> <base-repo-root> <base-sha> \
284287
<raw-root> <manifest> <result-root>
285288
```
286289

@@ -300,6 +303,104 @@ identity, patch and transform semantics without byte hashes, probes and effects,
300303
partition of overlays, inventory, and outputs. Runtime contract identity, resolved source and
301304
toolchain observations, byte digests, and derived provenance status remain outside that policy.
302305

306+
### Dormant managed-baseline activation
307+
308+
`baseline-activate` is the one-time migration boundary for the six manifest-bearing Phase A
309+
baselines. It is distinct from `legacy-onboard`: the reviewed base already contains an automation
310+
manifest, so it cannot satisfy the legacy rule that the base manifest be absent. It is also
311+
distinct from `monthly`: every Phase A base has an all-null toolchain binding and incomplete
312+
provenance, while a monthly transition requires authenticated producer observations under the
313+
same non-null reviewed profile in both manifests.
314+
315+
Each target's `managed_baseline_activation` registry object seals the exact integrated Phase A
316+
commit, tree, sole parent, manifest byte hash, and the immutable contract repository/SHA recorded
317+
by that manifest. The six reviewed anchors are:
318+
319+
- `freebsd-amd64`
320+
- Baseline commit: `e71cda6242e88e47312ca9bfc4548b0579636e0c`
321+
- Baseline tree: `9438879ad9906e970d45bafacf6ce2cc63ae4c53`
322+
- Sole parent: `fdf5cdfea6ea84612e068bc3bea433dbba263404`
323+
- Manifest SHA-256: `a9c2f15451a7e94261c6dd4d9e47cc3965414a2179d04af5902dffc9471a4db3`
324+
- `linux-amd64`
325+
- Baseline commit: `d6e7ac1b1bcc98aed734a6ecbfa8509f24606c74`
326+
- Baseline tree: `22851c0f356fefcb63718ce63d50a870150a491c`
327+
- Sole parent: `ece46f06fbe6eb701d52442f11dd59c48d166cae`
328+
- Manifest SHA-256: `bcdce1bea1facb24175229a16dc6e8a2c4210aafc05f0526b2728dc060223ed4`
329+
- `macos-amd64`
330+
- Baseline commit: `199fa78395ca413aac23d02ec69cc5e7b1d805a2`
331+
- Baseline tree: `db67711bfeb33be63dbc8eb03ecdddc2e127cc8c`
332+
- Sole parent: `da8ac5a4369accc67c485191d02535d77718a1c8`
333+
- Manifest SHA-256: `09dc54928f4690cfee7fd113de93f36479a40cabd10eeb3ee416a3175b42270a`
334+
- `macos-arm64`
335+
- Baseline commit: `1d0ad0ecf70a91a1df64cebf215e683b1d5aedb5`
336+
- Baseline tree: `96af5121f065310ba9168e3e2dc61adf340e2738`
337+
- Sole parent: `274abd2466a14861b75e5b91fd946ad27d114499`
338+
- Manifest SHA-256: `be45aaee1e65cc1ed2ee6bd2f121d72cbc248887ffa3d57f4b6d59cb6ea73525`
339+
- `openbsd-amd64`
340+
- Baseline commit: `8c7d96c75ea8548f007432d70f1ae33cccd81838`
341+
- Baseline tree: `f75c4862711184c4c191a73e6f996eb421bd37b4`
342+
- Sole parent: `45230fde96c17fff4baf37deb55e90803c043063`
343+
- Manifest SHA-256: `873b62af697ba25f0abe5887ba05972a93bd48990233853b362bed6cb9137699`
344+
- `windows-amd64`
345+
- Baseline commit: `86ae5844b8b56071b21ae3aa138b247d5eb9ddd9`
346+
- Baseline tree: `818d7794ebdf41de60e5679d485e3a5d49272171`
347+
- Sole parent: `f7c7199bb87fda8b80b31fefa470b2efc952326b`
348+
- Manifest SHA-256: `b5728124ecf8dc01e4f16cf4188411d6f633bb57997ef36df2dc5fd182e8535a`
349+
350+
All six anchors bind `base_contract_repository=vlang/v` and
351+
`base_contract_sha=7545e515b434cd399333d43659238427d72e22e7`. Their policy path/hash pairs
352+
are deliberately null. Consequently, `baseline-activate` stops with
353+
`target has no reviewed managed baseline activation policy` before it reads candidate input. A
354+
future reviewed policy will be canonical JSON at
355+
`baseline-activation/<target>.policy.json`, using onboarding-policy projection v2 and binding the
356+
resolved target toolchain profile. Projection v1 remains exclusive to legacy onboarding. The v2
357+
policy has one closed `source_commit_evidence` entry for every source and no extra entry. External
358+
sources seal ID, repository, ref, commit SHA, tree SHA, and canonical base64 of the bounded raw Git
359+
commit object. The validator reconstructs `SHA1("commit <length>\0" + raw)`, requires the first
360+
and only `tree` header to match, and compares the candidate's complete five-field source tuple to
361+
that reviewed evidence. Candidate source or provenance fields are never their own authority.
362+
363+
The Windows `v-libgc` entry instead has only `authority=runtime-contract`, its fixed source ID,
364+
repository, and ref; it cannot auto-pin a SHA or tree into the policy stored by the same V commit.
365+
At activation time its candidate SHA must equal the embedded runtime contract SHA, and its tree
366+
must equal the tree resolved for that exact commit in a separate hardened V Git checkout. That
367+
checkout must be a complete SHA-1 repository with `core.autocrlf=false`, no redirects, alternates,
368+
grafts, or replacement refs, the exact `vlang/v` HTTPS origin, and a clean tracked, detached HEAD at
369+
the runtime SHA. The updater must supply this private checkout; a mutable Actions branch checkout
370+
is not activation authority. The base anchors remain audit inputs only: they are not source
371+
provenance, native evidence, last-known-good tuples, or permission to seed durable state.
372+
373+
For an activated candidate, every payload entry with complete provenance binds its provenance
374+
repository to the SHA from reviewed commit evidence, or to the runtime SHA for `vlang/v`.
375+
`vlang/tccbin` provenance instead binds to the sealed baseline commit. Unknown repositories,
376+
sources absent from the target's closed source matrix, and SHAs borrowed from a different source
377+
are rejected.
378+
379+
This foundation introduces no production profile, onboarding or baseline-activation policy,
380+
producer observation, source SHA/tree resolution, complete payload provenance, state writer,
381+
candidate ref, check producer, or publication path. It therefore cannot make a target eligible
382+
and cannot publish even when a caller requests publication. In particular, the current Phase A
383+
manifests keep every source SHA/tree and toolchain member null and classify every payload entry as
384+
incomplete; Windows additionally retains its separately reviewed opaque `openlibm.o` acceptance.
385+
386+
The updater is not yet a producer for this transition. Its Unix jobs still invoke the legacy
387+
in-place recipes instead of setting `TCCBIN_DEFER_COMMIT=1`, producing a private RAW root, and
388+
calling `candidate-compose`; Windows is not present in its selectable target matrices. The current
389+
Linux and BSD jobs also request moving `ubuntu-latest` hosts while the reviewed profile model
390+
requires `ubuntu-24.04`, the macOS ARM64 updater job requests `macos-latest` while the model
391+
requires `macos-15`, the Windows branch requests `windows-latest` while the model requires
392+
`windows-2022`, and BSD cross-platform-actions runtime assets remain unauthenticated. These gaps,
393+
plus native producer/validator observations and external evidence transport, must be closed before
394+
any policy pair is populated.
395+
396+
Patch and transform retirement is likewise not activated here. The current manifest vocabulary
397+
records Windows patch state and effect/probe bindings, but no workflow yet builds an otherwise
398+
identical unpatched counterfactual, derives a closed
399+
`required`/`redundant`/`broken`/`unknown` verdict, or authorizes a removal or issue write. Until a
400+
later reviewed lifecycle binds those facts durably, an apply failure, unexpected pass, or changed
401+
effect remains fail-closed and requires human review; it must never be interpreted as proof that a
402+
patch or transform can be silently dropped.
403+
303404
### Dormant toolchain identity profiles
304405

305406
Each managed target also carries an all-null or all-resolved `toolchain_profile` triple in
@@ -711,7 +812,20 @@ fresh exact validation and the resolving commit recorded in the ledger.
711812
The contract and validators merge before any tccbin manifest. Fork manifests use
712813
`contract_mode=fork-dry-run` and cannot publish. After the V contract is merged, every managed
713814
tccbin manifest must point to the immutable merged V SHA in production mode and rerun all gates.
714-
Only after those branch changes merge can a V follow-up activate their exact upstream HEADs.
815+
Only after those branch changes merge can a V follow-up seal their exact upstream HEADs as dormant
816+
managed-baseline anchors. Sealing is not activation: the baseline policy pairs and all six
817+
toolchain-profile triples remain null, provenance remains incomplete, and no durable state is
818+
seeded.
819+
820+
Before a real `baseline-activate` candidate can be composed, a later reviewed phase must make the
821+
authentication and evidence-transport infrastructure authoritative, add the six resolved profiles
822+
and baseline policies, authenticate the producer environments, resolve every source SHA/tree, and
823+
generate complete per-file provenance. Validator observations and candidate-bound native proofs
824+
are produced and transported only after `candidate-compose` creates the immutable candidate ref;
825+
they are required before that candidate may enter durable eligibility or be published.
826+
The updater must first use deferred RAW builds plus `candidate-compose` for all six targets,
827+
including a native Windows producer. Patch/transform counterfactual classification and the BSD
828+
runtime-asset boundary must also fail closed until their own evidence paths are authoritative.
715829

716830
Build-only validation precedes targeted manual publication. Each target needs two consecutive,
717831
fully green targeted publications before a repository owner may set its monthly target unlock to

thirdparty/tccbin_automation/bin/candidate_composition.v

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,21 @@ pub fn compose_candidate_for_execution(automation_root string, request Candidate
3434
return error('candidate composition target is not managed')
3535
}
3636
mut onboarding_policy := JsonValue{}
37+
mut activation_binding := ManagedBaselineActivationBinding{}
38+
mut activation_policy := JsonValue{}
3739
if request.kind == .legacy_onboard {
3840
_, onboarding_policy = reviewed_legacy_onboarding_binding(automation_root,
3941
request.target_id, request.base_sha)!
42+
} else if request.kind == .baseline_activate {
43+
activation_binding, activation_policy = reviewed_managed_baseline_activation_binding(automation_root,
44+
request.target_id, request.base_sha)!
4045
}
4146
if !is_lower_hex_40(request.base_sha) {
4247
return error('candidate composition base must be a full lowercase commit SHA')
4348
}
4449
base_root, raw_root, manifest_source_path, result_root := validate_candidate_composition_roots(automation_root,
4550
request)!
51+
contract_root := canonical_contract_root(os.join_path(automation_root, '..', '..'))!
4652
validate_composition_base_repository(base_root, request.base_sha)!
4753

4854
result_parent := os.dir(result_root)
@@ -69,8 +75,11 @@ pub fn compose_candidate_for_execution(automation_root string, request Candidate
6975
return error('monthly composition base manifest failed with ${base_issues.len} issue(s)')
7076
}
7177
base_manifest = parse_strict_json(os.read_file(manifest_destination)!)!
72-
} else {
78+
} else if request.kind == .legacy_onboard {
7379
attest_legacy_candidate_manifest_absent(candidate_root, request.base_sha)!
80+
} else {
81+
base_manifest = attest_managed_baseline_activation_base(automation_root, request.target_id,
82+
candidate_root, request.base_sha, manifest_destination, activation_binding)!
7483
}
7584
materialize_candidate_manifest(candidate_root, request.base_sha, request.kind,
7685
manifest_source_path)!
@@ -87,9 +96,12 @@ pub fn compose_candidate_for_execution(automation_root string, request Candidate
8796
validate_manifest_legacy_onboarding_policy(manifest, onboarding_policy)!
8897
validate_legacy_onboarding_base_controls(automation_root, candidate_root, request.base_sha,
8998
manifest)!
90-
} else {
99+
} else if request.kind == .monthly {
91100
validate_candidate_policy_projection(base_manifest, manifest)!
92101
validate_composition_control_inputs(candidate_root, request.base_sha, manifest)!
102+
} else {
103+
validate_managed_baseline_activation_candidate(base_manifest, manifest, runtime,
104+
activation_binding, activation_policy, contract_root)!
93105
}
94106

95107
compose_declared_candidate_payload(candidate_root, request.base_sha, raw_root, manifest)!
@@ -216,7 +228,7 @@ fn validate_composition_base_repository(root string, base_sha string) ! {
216228

217229
fn materialize_candidate_manifest(candidate_root string, base_sha string,
218230
kind CandidateTransitionKind, source_path string) ! {
219-
if kind == .monthly {
231+
if kind != .legacy_onboard {
220232
attest_candidate_manifest_present(candidate_root, base_sha)!
221233
} else {
222234
attest_legacy_candidate_manifest_absent(candidate_root, base_sha)!
@@ -251,7 +263,7 @@ fn materialize_candidate_manifest(candidate_root string, base_sha string,
251263
|| temporary_observation.nlink != 1 {
252264
return error('candidate manifest temporary materialization is not a private regular file')
253265
}
254-
if kind == .monthly {
266+
if kind != .legacy_onboard {
255267
attest_candidate_manifest_present(candidate_root, base_sha)!
256268
os.rm(destination_path)!
257269
} else {

0 commit comments

Comments
 (0)