Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
26e9e67
fix(srv3): DirectLayout on-ISO autoinstall + os-install reconcile spi…
briansrls Jul 3, 2026
1eb1199
fix(srv3): observe script bash syntax — drop stray HTTP_CODE= before if
briansrls Jul 3, 2026
4be431f
fix(srv3): observe script curl HTTP_CODE — remove extra closing paren
briansrls Jul 3, 2026
32c6bcf
docs(srv4): BMC onboarding gap analysis — srv3-hardcoded plan + gclou…
Jul 21, 2026
7f73da9
feat(srv4): close BMC onboarding gaps — per-host plan, gcloud self-pr…
Jul 21, 2026
fa72843
fix(bmc): mint OpenBMC-policy-compliant credential (found by live srv…
Jul 21, 2026
291f904
feat(access): model fleet SSH access — operator + automation public k…
Jul 21, 2026
05f211f
fix(bmc): remove fabricated-fallback in onboarding_secret_id (§5 fail…
Jul 21, 2026
ac30664
feat(access): dedicated fleet-automation SA scoped to the SSH private…
Jul 21, 2026
264239e
feat(access): bake fleet SSH keys into autoinstall, disable password SSH
Jul 21, 2026
2b49c46
feat(srv4): autoinstall payload + seeded-ISO rows (Step B)
Jul 21, 2026
8a371e4
feat(uefi): model UEFI Shell + boot-config solver (dissolve manual UE…
Jul 21, 2026
1b2938b
feat(uefi/sol): SOL send transport + drive UEFI-shell boot-config ove…
Jul 21, 2026
83fec62
fix(sol): IpmiSol exhaustiveness in srv3_sol_console_capture witness
Jul 21, 2026
3622cea
feat(uefi): model the UEFI Shell command surface + observable environ…
Jul 21, 2026
148f084
feat(uefi): boot-install decision/diagnostic model (observe→diagnose→…
Jul 21, 2026
3960005
feat(bmc): model self-contained BMC netboot serve (no runtime central…
Jul 21, 2026
7895963
refactor(bmc/netboot): model components structurally in extdeps (no c…
Jul 21, 2026
fd20fe1
feat(bmc/netboot): model BMC ssh transport + structured staging manifest
Jul 21, 2026
e27fb26
feat(exec): transport seam — one command, N transports (§3, no forked…
Jul 21, 2026
f14d25c
feat(bmc/netboot): orchestration provision func (realize via the seam)
Jul 21, 2026
7fec69e
fix(bmc/netboot): httpd command uses the staged busybox binary (found…
Jul 22, 2026
9681857
feat(bmc/netboot): model the busybox cross-build (reproducible, not m…
Jul 22, 2026
e0bdb33
fix(bmc/netboot): srv4 boot NIC is eth2 (leases DHCP), not eth0 (foun…
Jul 22, 2026
74e7297
srv4 fleet subsumption + BMC virtual-media install path + modeling cl…
Jul 22, 2026
a11696a
plans: fleet subsumption manual-gaps receipt (srv4 hand-steps -> mode…
Jul 22, 2026
d960629
WIP: srv4 pr
briansrls Jul 23, 2026
30bf2dc
WIP: srv4 pr
briansrls Jul 23, 2026
f8e14bc
WIP: srv4 pr
briansrls Jul 23, 2026
6845ef5
WIP: srv4 pr
briansrls Jul 23, 2026
2e4f736
WIP: srv4 pr
briansrls Jul 23, 2026
501ad58
WIP: srv4 pr
briansrls Jul 23, 2026
fdd79a6
WIP: srv4 pr
briansrls Jul 23, 2026
c2769fd
WIP: srv4 pr
briansrls Jul 23, 2026
315009e
review 41721: shell_quote escapes embedded apostrophes (witnessed); I…
briansrls Jul 23, 2026
4dc04a2
plans: fold srv4 host-convergence OOM receipt into the manual-gaps doc
Jul 23, 2026
197c26c
WIP: srv4 pr
briansrls Jul 23, 2026
386b5e4
WIP: srv4 pr
briansrls Jul 23, 2026
f1a5ccc
WIP: srv4 pr
briansrls Jul 23, 2026
7aa6822
crypto.hash: single-variant coproduct via leading-pipe form; verify-l…
briansrls Jul 23, 2026
05c6a3b
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
3977faf
WIP: srv4 pr
briansrls Jul 23, 2026
d421695
Regenerate DESIGN.md + fleet-converge.sh from .dag authorities (drift…
briansrls Jul 23, 2026
ba81c19
WIP: srv4 pr
briansrls Jul 23, 2026
f5beebc
De-fork BMC scp transport onto the single ssh/scp posture authority (…
briansrls Jul 23, 2026
6bc749c
De-fork BMC scp: trigger-text + discriminating witnesses (review 41797)
briansrls Jul 23, 2026
8d5ad7c
WIP: srv4 pr
briansrls Jul 23, 2026
75ef068
WIP: srv4 pr
briansrls Jul 23, 2026
1c52f7b
WIP: srv4 pr
briansrls Jul 23, 2026
0438ae7
WIP: srv4 pr
briansrls Jul 23, 2026
752a944
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
e329b68
WIP: srv4 pr
briansrls Jul 23, 2026
7ad76a0
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
8a6cbbd
WIP: srv4 pr
briansrls Jul 23, 2026
12f87ca
Accept #7121 deletion of .github/fleet-converge.sh (paper transport r…
briansrls Jul 23, 2026
8636a93
WIP: srv4 pr
briansrls Jul 23, 2026
ae81266
Regen ci.yml: drop fleet-converge.sh from auto-heal add-list (deregis…
briansrls Jul 23, 2026
754367a
WIP: srv4 pr
briansrls Jul 23, 2026
32e4175
Regen ROADMAP.md: restore main's ts-ui-model row + drop trailing blan…
briansrls Jul 23, 2026
c81497e
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
9901560
Merge main + regen artifacts with new-emitter seed (drop ROADMAP.md t…
briansrls Jul 23, 2026
d8f746e
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
a793cfa
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
1c904db
WIP: srv4 pr
briansrls Jul 23, 2026
8f03a05
Enroll srv4 witnesses in the eligibility census (864 -> 876)
briansrls Jul 23, 2026
d9c0489
Merge remote-tracking branch 'origin/main' into session/srv4-onboardi…
briansrls Jul 23, 2026
add52d1
Merge main (#7110) + regen census TSV to match merged roster
briansrls Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ hollow alias (minimality ≠ grounding) · state-space conflation (an `Option`/`
- **effect grants over namespaces — dissolve `Hermetic | Wet` into (frame × verb × subtree).** The 2-valued `Hermetic | Wet` enum conflates four axes (input closure / replayability, output reach / interference, handler binding, selection eligibility) — a §3 state-space conflation with proto-envelopes already forked (the hand-rolled `workspace_root` containment gate, `std.resources.ResourceHandle`, `AuthScope`, `LiveTreeDisposition`). End shape (§3, cited not minted): an effect target is a position in a containment tree that already exists — filesystem paths, URIs, `/proc`, service-operation paths, and the unifying case **code names themselves** (the containment tree the namespace-resolution lane makes the single naming authority); permission is a grant of (verb × subtree) attached to a `Frame`; admissibility is the namespace prefix relation — the same `⊑` the resolver walks, content-addressing hashes, and termination reads, so effects become the **fourth consumer** of the one containment structure. Dispatch checks the envelope fail-closed (`EffectOutsideGrant`, a typed/located/counted refusal, never a silent widen — §5); *replayable* / *isolated* / `LiveTreeDisposition` become **derived** projections, and `Hermetic | Wet | Record` survive only as named envelope presets, deleted at the end. Frame-containment is graded on the §5 construction/validation axis (`LifecycleByConstruction` vs `LifecycleByConvention`). No code lands from the design doc; the FLAG-A interim is the only near-term consumer. → [effect-namespace-grants design](docs/plans/effect-namespace-grants.md)
- **shell → intent: the intent layer is language-blind (operator-aligned 2026-07-17; census/routing consolidated onto sibling authorities 2026-07-19).** §3/§4 restated for the shell case: the `.dag` intent may not name a target language — a workflow is an ordinary dependency graph over modeled operations (§4: a program is `Node`+`Edge`); *the intent IS the `.dag` graph* (operator), and `src/v2/std/orchestration.dag` `Pipeline` is optional sugar, never the authority. Two distinct downstream layers, not to be conflated: **emit** (§4 — `emit(intent, Bash)`, one grammar read backward, target as a *parameter*) and **realization** (§2 — pure-spec → host-effect, N transports `LocalShell`/`SshShell`, `dag/gunbc/host_effect_realize.dag`). **Routing (the load-bearing correction, operator review 2026-07-19): most sites do NOT emit bash.** Runtime-present sites (a gunbc runtime / typed transport is on the path) realize as typed service ops / typed transports / binary-interpreted effect-plan via `host_effect_apply` — no bash emitted (precedent already in tree: `floor_diff_observe` calls `git.Core.DiffUnified0` directly; `host_identity_converge` funnels through `host_effect_apply`); only foreign executors (GHA `run:`, cron, git hooks) and pre-runtime bootstrap windows render through the bounded v2 bash grammar rows. The authority for that routing is `authorize_shell_emission` (provisioning-window lane); the per-site residual census + arc-completion scoping is `shell-to-dag-residual-census-and-arc-completion.md` (witty-ibex-317) — DESIGN carries no parallel copy of either. **Invariant (enforceable):** the intent imports no language-construction vocab (`bash_build`, `bash_command_fold_serialize`, the `ShellStmt`/`ShellWord`/`ShellProgram` coproduct, `serialize_bash`) — emit-internal; `src/v2/lens/realization_vocabulary_containment.dag` confines the bash-AST vocab (LANDED #6854). The *separate, still-open* milestone is meta-exec confinement — `shell.Exec.Run/.Check` is not walled today (`host_language_transport_script` lens inert, `fail_closed_lockdown.dag`) and its heavy sequestration (module-isolate the bottom transport, or symbol-level import visibility) lands with that milestone. **Carriers → `Do{effect}` (never a command string, host-effect-orchestration.md):** the anemic `String` leaves are `host_effect.ShellCommand{script}`, `std.orchestration.Run.command`, and `host_effect.BootstrapFragment.script` — add-replacement → migrate all consumers → delete at arc close (§5 construction; `host_effect.dag` is load-bearing, the delete escalated). **Phases:** 0 sidecar delete LANDED (#6831) → 1 agnostic `While`/`BoundedPoll`/`Retry` emit LANDED (#6832) → 2 model runtime-present sites as typed effects on `host_effect_apply` + emit the foreign-executor/bootstrap residue → 3 wall green (bash-AST containment + meta-exec confinement). → [shell → intent design](docs/plans/shell-intent-emit-realization-design.md)
- **srvN build-cache provisioning on host-standup subsumption spine.** Legacy `ctrl-sccache.service` is misconfigured; `ci_release_build_script()` absorbing fallback (`CARGO_BUILD_JOBS=1` then `-u RUSTC_WRAPPER`) masks the deficit (§5). Design anchor: provision sccache as a host-effect ensure on the assimilation spine (P1b after `RunnerDeploySlot`), generalizing srv3's `WorkflowEnsureActuatorToolchain` to srvN; `ProvisionBuildCache { catalog_id }` routes through `host_effect_apply`; verdict fold is `ProvisionConverged | ProvisionRefused` only. STEP 2 (fallback removal) operator-sequenced after T4 live read-back. → [srvN build-cache provisioning design](docs/plans/srvn-buildcache-provisioning-design.md)
- **srv4 fleet subsumption — manual-gap receipts (2026-07-22).** srv4 was installed and subsumed through the modeled BMC virtual-media path (PR #7027: 5 runners live, rootless Docker + sccache, seeded-media boot-fidelity fixes root-caused live); every step still performed by hand is typed as a modeling gap in the registered plan `gunbc.plans.fleet_subsumption_manual_gaps` (A1 MaterializedSecret lifecycle, A2 reach-secrets ADC, A3 SecretRef liveness, B1 runner-slot provisioning, B2 runner user, B3 fresh-host prereqs, B4 install actuator), each with an acceptance bar and RED; the plan dissolves item-by-item and fully retires when srv5 subsumes with zero hand-run shell. The BMC credential-rotation gap analysis that seeded the lane: → [srv4 BMC onboarding gap](docs/plans/srv4-bmc-onboarding-gap.md)
- **gunb.ai site subsumption — hosting + frontend emitted from `.dag` (operator-directed 2026-07-20).** Subsume `gunb-ai/frontend`: the public site's HTML/CSS/JS become emitted, drift-gated artifacts in this repo, published to GitHub Pages at `gunb.ai` (DNS already points at Pages IPs; cutover is Pages-config-only; the frontend repo archives). Register thesis, developed across nine operator passes and carried as a signable checklist + behavioral-intricacy law: *quiet at arm's length; responsive up close; every response true* — simplicity is a D0/D1 property, intricacy a D2/D3 property of BEHAVIOR (coverage × consistency × timing, the Discord re-read), and every intricate thing shown or answered derives from a real repo fact. Phase-0 slices LANDED under `dag/gunbc/site/` (principles → tokens → interaction → mark → constellation → moodboard → theme_transition → starlight/accent_study), proven by execution with RED controls: themes as total role→material assignments (night = warm starlight on indigo, day = indigo ink on paper, one model, two projections; totality/area/contrast witnessed), the glare envelope (bright OR chromatic, never both — the operator-rejected gamer cyan is the negative control and provably absent from emissions), still-until-touched by construction (MotionTrigger has no ambient variant), the universal theme reframe derived from the same BuildRule rows (role-routed colors cross-fade for free on one token clock; an unthemed color is a counted census row; the data-theme watcher pins the flip so the fade cannot race the UA restyle — measured, snap → 12–16-frame blend), and the accent decision grounded in `extdeps.astronomy.stellar_classification` (cited MK/Harvard table; no green stars exist so green enters only as verdigris material; M self-prunes at the envelope; candidates O/A/G/K rendered from identical fact rows). Remaining: checklist row-by-row sign-off, primitives.html at every depth, mark candidates B–D, craft-floor scales, generated-artifact registration, Pages workflow + cutover receipt (discharges the `2-stateless-frontend` milestone-A shape on the public domain). → [site subsumption design](docs/plans/gunb-ai-site-subsumption-design.md)
- **hierarchical design-register library — lift `gunbc.site` L1/L2 into `gunbc.design.*` (DOC-ONLY until #6927 merges).** PR #6927 proves the register on gunb.ai; the follow-on extracts site-independent L1 house walls + L2 role-material machinery (lift-not-fork), re-grounds contrast at L0 (WCAG/OKLCH, dissolving the HSL lightness-gap proxy in `theme_contrast_ok`), and stages L4 archetypes + `DataVizArea` behind second-consumer discipline. Phase A fires on #6927 merge with an emission-identical witness. The **palette catalogue** rode ahead additively (operator 2026-07-21): `extdeps.color.srgb` (CSS Color 4 cite; hex = a serialization of `Srgb8`, HSL→sRGB re-homed out of the WCAG module) → `gunbc.design.palette` (approval IS the computed WCAG grade — ordered figure-on-ground pairings total by construction) → `gunbc.design.catalog` (first entry island-pastel incl. the derived `loam` ink), witnessed by execution; its measured receipts (HSL-S misreads pastel tints as neon — ivory C 0.007 refused while `day_canvas` C 0.008 passes; gamer-cyan C 0.088 < mint C 0.142, so the envelope must be a per-area L×C region) are A.2's discriminating witness — see plan §2.2. → [design-register library](docs/plans/design-register-library.md)
- **module identity vs storage — the path⇄module binding authority + bidirectional surfaces (operator-directed 2026-07-18).** A load-bearing file-path literal is an edge living in prose — invisible to the affected set, the resolver, content-addressing, and the effect story (§4: a program is `Node`+`Edge`). The priced incident, split correctly (PR #6856 review): the 03_normalize behavioral receipt had **zero executing consumers** — excluded by a hand `witness_exclusion_substrings` roster row while the frontier falsifier enrolls only `SelfEmitted` rows and 03_normalize was `SeedRetained` — orphaned enrollment, §6 coverage-by-illusion, the roster itself the parallel-ledger form of the missing classification; the string-hidden dependency (`sn_source_rel: String = "src/v2/compiler/03_normalize.dag"` beside a 3-library-import declaration) is the **latent** defect — admitted today the row fail-closed-defaults to `ReadsLiveTree`/never-skip (safe, unscalable — it pins the whole-tree precompute), admitted to *precise* selection it would false-skip emitter-touching PRs (cache impurity: the key wrong before the cache exists). #6775's 705-error regression shipped through the first, caught by hand. Model: a module is a node (containment subtree); a file is a **storage realization** (§2 Realization — one of N; many-to-many *in the model*, staged against the live 1:1-enforced snapshot, with provenance a coproduct `ParsedFromSource | ProducedByBehavior` so zero-file produced modules are represented honestly), so the path⇄module binding is a **derived-at-parse fact** homed on `v2.compiler.source_authority` — the frontier's hand `FrontierQualifiedModuleBinding` rows AND the host-side `build_module_path_index` producer both become projections (else two authorities remain, §3). Code references modules; only host boundaries project paths. §5 order: a typed `SourceRef` at the effect boundary makes bare-string file deps unwritable (construction); an effect-reach census lens catches the falsely-declared-hermetic case (the fail-closed default already covers undeclared), inventories the migration, and backstops until the boundary lands. Phase 0 = the admission invariant: **every witness row names an executing consumer** — `SelfEmitted` receipts on the falsifier wet cadence, quarantined known-red rows on a probe cadence *expecting red* so greening is a counted un-quarantine event; "enrolled, zero executions" itself reds. Per-surface authority is the composed relation `(module × target × root) → (paths, authority, AuthoringSurface)` — for Rust the authority side is the frontier disposition (`SeedRetained` = seed `.rs` is authority, not BothWays; `SelfEmitted` = graph is authority, BothWays only over a declared `Lossless` Rust-ingest fragment), and three oracles stay separate: surface round-trip · behavioral receipt · regen byte drift. md↔dag is **delta-first** (operator 2026-07-18: decide the graph delta first; files only capture and faithfully project it — heading toward transacting without files): the **keyed delta** on the typed document value (`design_document() -> MarkdownDocument`) IS the transaction, keyed by containment-tree node identity (stable anchor, never rendered-file position — reorder = noop, ambiguity refuses), with the file three-way compare a named capture adapter that dissolves on delta-native transacting; write-back = ingest-recovered delta → rewrite the literal declaration rows → re-emit both surfaces; fidelity prerequisite priced (the ingester's `TextInline` collapse and the deliberate emphasis non-roundtrip keystone move first); `BothWays` gated on `ingest(emit(authority)) == authority` over the actual construct set (replacing the vacuous `artifact_extra_valid` arm); concurrent divergent edits refuse with a typed conflict, never last-writer-wins; yaml ingest is evidence for grammar-owned backward reads, not write-back (ci.yml stays DagOnly deliberately). Phases 0–3 take no dependency on the namespace terminal or effect-grants; flagships = the cssl transport de-stringed (receipt selected on emitter-touch, skipped on unrelated, both by execution), a DESIGN.md md-side edit landing in `design_document.dag` with the drift gate green, and the Phase-3 Rust loop (pilot `parse_engine_hooks`: edit a supported declaration in the emitted artifact → same semantic graph delta → re-emit → **edited-vs-re-emitted** behavioral equivalence, seed-equality only the no-edit control; committed seed `.rs` = hand-retained oracle, storage role decided by policy never basename). → [module identity vs storage design](docs/plans/module-identity-storage-binding-design.md)
Expand Down
74 changes: 74 additions & 0 deletions dag/extdeps/access/ssh.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
module extdeps.access.ssh

import std.types { NonEmptyStr, String }
import extdeps.external_authority { ExternalAuthority }
import extdeps.uri { Uri, Https }

data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "man.openbsd.org/sshd.8#AUTHORIZED_KEYS_FILE_FORMAT"
}
}

type SshKeyAlgorithm
= Ed25519
| Rsa
| EcdsaP256

data ssh_key_algorithm_token_registry_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "www.iana.org/assignments/ssh-parameters/ssh-parameters.xhtml#ssh-parameters-19"
}
}

data ssh_key_algorithm_token_registry_note: String = "ssh_key_algorithm_token emits registered wire tokens: the token SET is owned by the IANA SSH Protocol Parameters public-key-algorithm-names registry (anchor above); each variant's cryptosystem and token carry their own upstream authorities in the per-variant rows below — a referenced entity carries ITS authority, never its consumer's (the Vendor<Domain> precedent)."

data ed25519_cryptosystem_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "ed25519.cr.yp.to/"
}
}

data ed25519_authority_note: String = "Ed25519: design authority ed25519.cr.yp.to (Bernstein et al.); EdDSA specified in RFC 8032; the ssh-ed25519 wire token is registered by RFC 8709."

data rsa_cryptosystem_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "www.rfc-editor.org/rfc/rfc8017"
}
}

data rsa_authority_note: String = "Rsa: PKCS #1 v2.2 (RFC 8017); the ssh-rsa wire token is defined in RFC 4253 section 6.6. POSTURE: ssh-rsa SIGNATURES (SHA-1) are deprecated by RFC 8332 in favor of rsa-sha2-256/rsa-sha2-512 — an authorized_keys ssh-rsa KEY line remains valid, but selecting Rsa for new fleet keys is a deprecated posture and the fleet's declared keys are Ed25519."

data ecdsa_p256_cryptosystem_authority: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "www.rfc-editor.org/rfc/rfc5656"
}
}

data ecdsa_p256_authority_note: String = "EcdsaP256: ECC in SSH per RFC 5656; curve P-256 per FIPS 186 / SEC 2; wire token ecdsa-sha2-nistp256."

fn ssh_key_algorithm_token(a: SshKeyAlgorithm) -> NonEmptyStr {
match a {
Ed25519 => "ssh-ed25519"
Rsa => "ssh-rsa"
EcdsaP256 => "ecdsa-sha2-nistp256"
}
}

type SshPublicKey {
algorithm: SshKeyAlgorithm
material: NonEmptyStr
comment: String
}

fn ssh_public_key_line(k: SshPublicKey) -> String {
concat(
concat(ssh_key_algorithm_token(a: k.algorithm) as String, " "),
concat(k.material as String, concat(" ", k.comment)),
)
}
1 change: 1 addition & 0 deletions dag/extdeps/bmc/capability.dag
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type BmcCapability
| CapabilityVirtualMedia
| CapabilityNbdProxyVirtualMedia
| CapabilityBiosAttributeConfig
| CapabilitySerialConsole

type BmcFirmwareVersion {
family: BmcFirmwareFamily
Expand Down
18 changes: 18 additions & 0 deletions dag/extdeps/bmc/os_install_actuator_toolchain.dag
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,21 @@ fn srv3_os_install_actuator_toolchain_is_complete() -> Bool {
requirement: os_install_actuator_toolchain_requirement,
)
}

data bmc_credential_actuator_toolchain_requirement: ActuatorToolchainRequirement = ActuatorToolchainRequirement {
required_tools: [
curl_cli_tool,
gcloud_cli_tool,
],
}

fn bmc_credential_actuator_toolchain_is_complete() -> Bool {
actuator_toolchain_requirement_includes_tool(
requirement: bmc_credential_actuator_toolchain_requirement,
tool_name: curl_cli_tool.name,
)
&& actuator_toolchain_requirement_includes_tool(
requirement: bmc_credential_actuator_toolchain_requirement,
tool_name: gcloud_cli_tool.name,
)
}
Loading
Loading