Skip to content

Commit b6f7815

Browse files
committed
Merge branch 'main' into spot-schdule-phase5
Signed-off-by: Erick Bourgeois <erick@jeb.ca>
2 parents d35ece0 + 96d1bec commit b6f7815

26 files changed

Lines changed: 2279 additions & 95 deletions

.claude/CHANGELOG.md

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,33 @@ The format is based on the regulated environment requirements:
99

1010
---
1111

12+
## [2026-06-15 10:30] - Restore dropped spot-schedule metric functions (build fix)
13+
14+
**Author:** Erick Bourgeois
15+
16+
### Changed
17+
- `src/metrics.rs`: Added the three spot-schedule metric definitions and
18+
`record_*` functions that a `main` merge dropped while keeping their call sites
19+
in `scheduled_machine.rs` and their tests in `metrics_tests.rs`:
20+
`SPOT_SCHEDULE_RESOLUTIONS_TOTAL` / `record_spot_schedule_resolution`,
21+
`SPOT_SCHEDULE_RESOLUTION_ERRORS_TOTAL` / `record_spot_schedule_resolution_error`,
22+
`SPOT_SCHEDULE_TRANSITIONS_TOTAL` / `record_spot_schedule_transition`.
23+
24+
### Why
25+
The crate failed to compile (`E0425: cannot find function …`) after the
26+
`spot-schdule-phase5` merge — the metric implementations were lost but their
27+
callers and unit tests survived. This restores them (the tests were already the
28+
RED spec), unblocking every CI job, including the new `validate-autovex` gate
29+
which compiles the crate via `cargo run`.
30+
31+
### Impact
32+
- [ ] Breaking change
33+
- [x] Requires cluster rollout
34+
- [ ] Config change only
35+
- [ ] Documentation only
36+
37+
---
38+
1239
## [2026-06-15 10:00] - Spot-schedule docs: contract finalization + concept page (Phase 6)
1340

1441
**Author:** Erick Bourgeois
@@ -90,48 +117,6 @@ resolver/watch.
90117

91118
---
92119

93-
<<<<<<< Updated upstream
94-
=======
95-
## [2026-06-14 16:00] - Auto-VEX pre-submission sign-off gate (ADR 0008)
96-
97-
**Author:** Erick Bourgeois
98-
99-
### Changed
100-
- `docs/adr/0008-autovex-presubmission-gate.md`: NEW ADR — commit a frozen
101-
snapshot of auto-VEX inputs + canonical output; enforce with a byte-exact CI
102-
gate (PR hard-fail). No CALM impact (CI/CD policy). Index updated in
103-
`docs/adr/README.md`.
104-
- `Makefile`: NEW `vex-auto` (regenerate `.vex/auto/*` from `.vex/snapshot/` with
105-
pinned `--id`/`--author`/`--timestamp`) and `vex-auto-check`
106-
(`vex-auto` + `git diff --exit-code -- .vex/auto`) targets; added both to
107-
`.PHONY`.
108-
- `.vex/snapshot/`: NEW frozen generator inputs (`grype.json`, `sbom-bootstrap.json`,
109-
`symbols.txt`, `timestamp.txt`) + `README.md` documenting the sign-off contract
110-
and how to refresh from a real CI capture. Seeded as a valid empty bootstrap.
111-
- `.vex/auto/`: NEW committed canonical output (`vex.auto-presence.json`,
112-
`vex.auto-reachability.json`) — the human-signed-off baseline.
113-
- `.github/workflows/build.yaml`: NEW `validate-autovex` job — runs
114-
`make vex-auto-check` on `pull_request` + `push`, hard-failing when committed
115-
auto-VEX is stale.
116-
- `docs/src/security/vex.md`: NEW "Auto-VEX is signed off before submission"
117-
section documenting the committed baseline, workflow, and gate scope.
118-
119-
### Why
120-
Auto-VEX statements are machine-authored suppressions that previously appeared
121-
only in CI artifacts and were merged into the signed release VEX with no human
122-
review until the Security team's post-hoc counter-signature. This adds an
123-
**upstream** checkpoint: maintainers run the generators, review the suppressions,
124-
and commit them (sign-off) before submission; CI refuses any change whose
125-
committed auto-VEX no longer matches a fresh, deterministic regeneration.
126-
127-
### Impact
128-
- [ ] Breaking change
129-
- [ ] Requires cluster rollout
130-
- [x] Config change only (CI gate + repo convention)
131-
- [ ] Documentation only
132-
133-
---
134-
135120
## [2026-06-14 14:30] - Spot-schedule RBAC + admission + threat model (Phase 4)
136121

137122
**Author:** Erick Bourgeois
@@ -276,7 +261,6 @@ build on this.
276261
- [ ] Config change only
277262
- [ ] Documentation only
278263

279-
>>>>>>> Stashed changes
280264
## [2026-06-13 16:30] - Spot-schedule provider API: CRD scaffolding + ScheduledMachine v1beta1 (Phase 1)
281265

282266
**Author:** Erick Bourgeois

Cargo.lock

Lines changed: 72 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ warp = { version = "0.4", default-features = false, features = ["server"] }
7070
toml = "1.1"
7171
# SHA-256 for the kata-config agent's content/drift hashing and (Phase 4)
7272
# the applied-hash node annotation. RustCrypto, pure-Rust, no system deps.
73-
sha2 = "0.10"
73+
sha2 = "0.11"
7474

7575
# Linux-only — used by the reclaim-agent's rung 2 netlink proc connector
7676
# subscriber (`src/netlink_proc.rs`). The portable byte parsers in that

deploy/admission/validatingadmissionpolicy.yaml

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,12 @@ spec:
2727

2828
matchConstraints:
2929
resourceRules:
30+
# Both served versions must be validated (ADR 0007). v1beta1 is the
31+
# storage/current version (adds spec.spotSchedule and an optional
32+
# spec.schedule); v1alpha1 is the frozen, deprecated legacy version. A
33+
# version omitted here would BYPASS every validation below.
3034
- apiGroups: ["5spot.finos.org"]
31-
apiVersions: ["v1alpha1"]
35+
apiVersions: ["v1alpha1", "v1beta1"]
3236
resources: ["scheduledmachines"]
3337
operations: ["CREATE", "UPDATE"]
3438

@@ -117,11 +121,19 @@ spec:
117121
(format: <positive integer> followed by s, m, or h)
118122
reason: Invalid
119123

124+
# NOTE on the schedule rules below: `spec.schedule` is OPTIONAL since
125+
# v1beta1 (ADR 0006) — a machine may instead delegate to a spotSchedule
126+
# provider. Each schedule rule is therefore guarded with
127+
# `!has(object.spec.schedule) || …` so a valid spotSchedule-only machine is
128+
# not rejected. The "at least one of schedule/spotSchedule" invariant is
129+
# enforced by rule 7a below (and by the CRD's own x-kubernetes-validations).
130+
120131
# ── 4. Cron XOR explicit day/hour windows ────────────────────────────────
121132
# Using cron together with daysOfWeek or hoursOfDay is ambiguous.
122133
# The controller silently ignores daysOfWeek/hoursOfDay when cron is set;
123134
# we reject the spec at admission to prevent silent data loss.
124135
- expression: |
136+
!has(object.spec.schedule) ||
125137
!has(object.spec.schedule.cron) ||
126138
(object.spec.schedule.daysOfWeek.size() == 0 &&
127139
object.spec.schedule.hoursOfDay.size() == 0)
@@ -132,6 +144,7 @@ spec:
132144
133145
# ── 5. Without cron, both day and hour windows must be provided ───────────
134146
- expression: |
147+
!has(object.spec.schedule) ||
135148
has(object.spec.schedule.cron) ||
136149
(object.spec.schedule.daysOfWeek.size() > 0 &&
137150
object.spec.schedule.hoursOfDay.size() > 0)
@@ -145,6 +158,7 @@ spec:
145158
# or a comma-separated combination (mon-wed,fri-sun).
146159
# Trivially true for empty arrays (cron path).
147160
- expression: |
161+
!has(object.spec.schedule) ||
148162
object.spec.schedule.daysOfWeek.all(d,
149163
d.matches('^(mon|tue|wed|thu|fri|sat|sun)(-(mon|tue|wed|thu|fri|sat|sun))?(,(mon|tue|wed|thu|fri|sat|sun)(-(mon|tue|wed|thu|fri|sat|sun))?)*$'))
150164
message: >-
@@ -158,13 +172,35 @@ spec:
158172
# at runtime by the schedule evaluator.
159173
# Trivially true for empty arrays (cron path).
160174
- expression: |
175+
!has(object.spec.schedule) ||
161176
object.spec.schedule.hoursOfDay.all(h,
162177
h.matches('^[0-9]{1,2}(-[0-9]{1,2})?(,[0-9]{1,2}(-[0-9]{1,2})?)*$'))
163178
message: >-
164179
spec.schedule.hoursOfDay items must be hours or ranges
165180
(e.g. '9', '9-17', '0-9,18-23')
166181
reason: Invalid
167182
183+
# ── 7a. At least one activation source ────────────────────────────────────
184+
# A machine must declare an inline schedule, a spotSchedule provider, or
185+
# both (ADR 0006). Mirrors the CRD x-kubernetes-validations and the runtime
186+
# validate_activation_source() in src/reconcilers/helpers.rs.
187+
- expression: "has(object.spec.schedule) || has(object.spec.spotSchedule)"
188+
message: >-
189+
at least one of spec.schedule or spec.spotSchedule must be set
190+
reason: Invalid
191+
192+
# ── 7b. spotSchedule.apiVersion group pin ─────────────────────────────────
193+
# The provider reference group MUST be spotschedules.5spot.finos.org
194+
# (ADR 0006 §2 / §6) — providers are untrusted inputs and the controller's
195+
# read-only RBAC is scoped to exactly this group. Mirrors the CRD field CEL
196+
# and the runtime group check.
197+
- expression: |
198+
!has(object.spec.spotSchedule) ||
199+
object.spec.spotSchedule.apiVersion.startsWith('spotschedules.5spot.finos.org/')
200+
message: >-
201+
spec.spotSchedule.apiVersion group must be spotschedules.5spot.finos.org
202+
reason: Invalid
203+
168204
# ── 8. bootstrapSpec.apiVersion must use a namespaced API group ───────────
169205
# Core API versions (e.g. "v1") have no '/' and must never be used for
170206
# bootstrap resources — rejects the same case as validate_api_group() at runtime.

0 commit comments

Comments
 (0)