Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
63c9500
mtcollins1 runner: JIT register/deregister over a managed-host unit b…
Oct 4, 2026
6423206
mtcollins1 runner: bind the dispatch leg to CreateDispatch with the a…
Oct 4, 2026
f33d265
leg 3: seal the dispatched run and the collected arm; check the readb…
Oct 4, 2026
303651b
leg 3: admit only Bool-returning claims to the sealed conclude; delet…
Oct 4, 2026
4e8adca
mtcollins1 runner: extract qualification instruments from the run's j…
Oct 4, 2026
3be84a5
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
b07b575
Address side-chat RC on #13206: causal readback, sealed subject/recei…
Oct 4, 2026
60b36c6
Merge leg-2 split (b07b575) into leg 3; dispatch leg is LegAuthorityI…
Oct 4, 2026
ccad694
Image leg is LegAuthorityImplemented: no production caller builds the…
Oct 4, 2026
f48396f
Merge remote-tracking branch 'origin/session/nimble-ram-151' into ses…
Oct 4, 2026
9669ecc
leg 3b: claim-cost row names both missing capabilities and the calibr…
Oct 4, 2026
24baafe
leg 3b: make the two wildcard arms exhaustive (NonFoldResidueRosterDi…
Oct 4, 2026
be2c844
leg 3b: spell response_format as the WireFormat variant Text (the emi…
Oct 4, 2026
ada86f3
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
5063c33
Merge remote-tracking branch 'origin/main' into session/jolly-bat-898
Oct 4, 2026
f6e820a
leg 3: answer the operator review -- sealed dispatch subject, commit-…
Oct 4, 2026
d2021c0
leg 3b: address review on 3be84a5ee3 -- sealed extraction subject, on…
Oct 4, 2026
417b619
leg 3: fix builtin names and witness fixtures (first/last, declaratio…
Oct 4, 2026
3199c07
leg 3b: state the seal's rung at its evidence -- checked once, not en…
Oct 4, 2026
a20fb39
leg 3: share #13225's runner identity (job_ran_on over runner_name ==…
Oct 4, 2026
d7838a7
leg 3: exhaustive matches over RunnerSpec, WorkflowTrigger and the te…
Oct 4, 2026
ffc3edb
Merge #13211 (a20fb39695e) into leg 3b: extraction reads the collecti…
Oct 4, 2026
d3514f3
Seal the authorized JIT dispatch and bind the runner listing to its q…
Oct 4, 2026
d66a36a
Merge remote-tracking branch 'origin/session/nimble-ram-151' into ses…
Oct 4, 2026
dbb305f
Merge #13206 d3514f3 (AuthorizedJitMintDispatch sealed); the dispatch…
Oct 4, 2026
d8324c4
leg 3b: enrol the job-log receipt seal as executed compile-refusal RE…
Oct 4, 2026
d664bb3
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
8bc9069
leg 3: split the over-budget scope claim into one claim per independe…
Oct 4, 2026
022f7ec
leg 3b: commit the forged-receipt probe source (a local probe/ exclud…
Oct 4, 2026
ecb6720
leg 3 witness per DESIGN section 3: supply values at each interface (…
Oct 4, 2026
652b4de
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
67bb240
leg 3: keep the real-path claim to the mint and the sealed subject; d…
Oct 4, 2026
613d339
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
29003c4
leg 3: the production mint over the real fleet_converge_workflow is i…
Oct 4, 2026
afd21c5
Merge origin/main into leg 3 (imports-only conflict in runner_microvm…
Oct 4, 2026
6b59598
Merge remote-tracking branch 'origin/main' into session/gentle-bear-467
Oct 4, 2026
cb4fc55
Merge remote-tracking branch 'origin/main' into session/gentle-bear-467
Oct 4, 2026
de5e586
Merge origin/main into leg 3 (github_app_registry witness imports: ke…
Oct 4, 2026
cf29159
leg 3: production mint reads the declared inputs before building flee…
Oct 4, 2026
6663679
Merge remote-tracking branch 'origin/main' into session/gentle-bear-467
Oct 4, 2026
c22c2b5
leg 3 RC items 1-3: delivery carries its authorized dispatch; dispatc…
Oct 4, 2026
82498c3
leg 3 RC item 4: per-attempt branch pin -- create-once refs/heads/qua…
Oct 4, 2026
6ce55dd
leg 3 item 1: the delivery carries its mint's plain JitMintIdentity (…
Oct 4, 2026
c0a4c9b
leg 3 witness: the slot positive control passes pin_branch (a bare 'b…
Oct 4, 2026
6d3ebff
Merge origin/main (leg 2 #13206 landed) into leg 3; every conflict wa…
Oct 4, 2026
392995f
leg 3: branch_absent matches every RestExchangePerformance arm (floor…
Oct 4, 2026
a1df1b6
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
8bb3f19
leg 3 RC (392995f): sealed delivery carrier, collection token join, W…
Oct 4, 2026
0c55966
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
5a610d3
leg 3: commit the rewrap probe the rewrap witness compiles (a local .…
Oct 4, 2026
f354d77
leg 3b: address review on a1df1b6 -- token-bound collector, Artifacts…
Oct 4, 2026
635377f
leg 3b: the collector's token guard is a pure read plan, executed as …
Oct 4, 2026
4872c1e
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 4, 2026
ea89826
leg 3 RC item 2 by sha-checkout (decision eager-gull-22): the floor j…
Oct 4, 2026
b49e0e2
leg 3 RC (review 5408711178): receive_jit_mint and the generate fold …
Oct 5, 2026
3641482
leg 3b: confine the collector's reads to the checked entry (review on…
Oct 5, 2026
3e99b76
leg 3: collection admission is a pure read plan (plan_qualification_c…
Oct 5, 2026
7ebc19e
leg 3: close the planned-reads arm (unterminated function body at 3e9…
Oct 5, 2026
af96af4
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 5, 2026
ea199ce
Merge origin/main into leg 3; authorization_pattern_selection witness…
Oct 5, 2026
ac79028
leg 3 (review 76234): the ruling record says only what the ruling say…
Oct 5, 2026
08be556
leg 3 (review 76234): the operator's 2026-10-05 scope ruling (escalat…
Oct 5, 2026
3caf667
Merge remote-tracking branch 'origin/main' into session/gentle-bear-467
Oct 5, 2026
2f35877
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 5, 2026
38e5456
leg 3: the scope ruling bounds where the 10-03 discharge may apply (a…
Oct 5, 2026
6b85fff
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 5, 2026
b164681
leg 3: the dedicated group's selected-workflow pin is authorized by i…
Oct 5, 2026
0dd58d8
Merge remote-tracking branch 'origin/session/jolly-bat-898' into sess…
Oct 5, 2026
15eb7f6
Merge origin/main into leg 3: port onto #13171's RestResult (no outco…
Oct 5, 2026
fba75a9
Merge #13211 15eb7f6b1a (main incl. #13171); port leg 3b onto RestResult
Oct 5, 2026
ee6a021
actions_artifacts: import GET from extdeps.ietf.http_semantics (floor…
Oct 5, 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
128 changes: 128 additions & 0 deletions dag/extdeps/github/actions_artifacts.dag
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
module extdeps.github.actions_artifacts

import extdeps.github.github { default_api_base, max_per_page }
import extdeps.github.errors { GitHubErrorShape }
import extdeps.external_authority { ExternalAuthority }
import extdeps.uri { Uri, Https }
import std.credentials { EnvVar }
import std.types { Bool, Bytes, Int, List, String }
import std.resources { Network }
import std.serialization { Text }
import extdeps.ietf.http_semantics { GET }

// THE GITHUB ACTIONS ARTIFACTS REST API, as the upstream names it: "List workflow run artifacts"
// (operationId actions/list-workflow-run-artifacts) and "Download an artifact"
// (actions/download-artifact), docs.github.com/en/rest/actions/artifacts, read 2026-10-04.
//
// THE DOWNLOAD IS A REDIRECT TO A ZIP, AND BOTH HALVES ARE UPSTREAM FACTS. GitHub answers
// `GET /repos/{owner}/{repo}/actions/artifacts/{artifact_id}/{archive_format}` with `302 Found` and a
// `Location` header naming a short-lived storage URL (about one minute), and `410 Gone` once the
// artifact has expired; `archive_format` admits exactly `zip`, and the body at the Location is the
// artifact as a zip archive -- upload-artifact always archives, even a single file. Following the
// redirect is the bound REST realization's work, not this interface's: the seed handler
// (v1_interpreter observe_rest_exchange, over ureq's redirect policy) follows it and decides on the
// final response, so the response block below names the answer at the end of the redirect.
//
// THE ARCHIVE IS Bytes AND NO BOUND REALIZATION CAN YET CARRY IT. The REST handler reads every body
// as UTF-8 text (RestBodyObservation carries body: String), so a zip arrives as a body that could not
// be read and the call answers RestBodyUndecodable with the status it came under. That refusal is the
// honest answer today and it is typed; reading a member out of the archive needs a binary body
// carrier on the REST transport and an inflate reader, which is
// the trigger of gunbc.runner.runner_qualification_dispatch qualification_instrument_extraction_frontier_rows'
// parse_claim_cost_tsv row. Its production caller is that module's read_claim_cost_artifact.
data extdeps_external_authority_anchor: ExternalAuthority = ExternalAuthority {
uri: Uri {
scheme: Https
locator: "docs.github.com/en/rest/actions/artifacts"
}
}

// THE FIELDS A READER OF A RUN'S ARTIFACTS ASKS OF ONE, AND NO OTHERS. The claim-cost read
// (gunbc.runner.runner_qualification_dispatch conclude_claim_cost_listing) finds the artifact by
// name, refuses it when upstream's `expired` flag is set -- a download would answer 410 -- and
// downloads it by id. Upstream's artifact object also carries size_in_bytes, archive_download_url,
// created_at and expires_at; nothing here reads them, so they are not modeled (DESIGN 3c), and a
// size that one day is read arrives as std.measure ByteSize, not a bare count.
type ActionsArtifact {
id: Int
name: String
expired: Bool
}

type ActionsArtifactList {
total_count: Int
artifacts: List<ActionsArtifact>
}

// `archive_format` IS A PATH SEGMENT WHOSE UPSTREAM VOCABULARY HAS ONE MEMBER, `zip`, so the path
// carries it as the literal upstream spelling rather than as an input. An input would make every
// other spelling representable, and a coproduct input interpolated into a path is rendered by the
// seed with its AUTHORED variant name (the regression extdeps.github.workflow_runs
// WorkflowJobAttemptFilter records), so neither would be more faithful than the literal.
// AUTHENTICATION IS THE CALLER'S TOKEN. Accepting an auth_token operation input does not by itself
// bind authentication; auth_input names that input as the credential, as extdeps.github.git_database
// and github.WorkflowRuns declare, so the controller installation token the qualification collector
// passes is the one the request carries rather than the ambient GITHUB_TOKEN. An empty token keeps
// the env fallback, the same dual declaration github.WorkflowRuns uses.
service github.Artifacts {
config {
endpoint: default_api_base
auth: Bearer
auth_input: auth_token
auth_source: EnvVar { name: "GITHUB_TOKEN" }
}

operation ListWorkflowRunArtifacts {
requires Network
input {
auth_token: Secret
owner: String
repo: String
run_id: String
per_page: Int = max_per_page
}
output {
result: ActionsArtifactList
}
readonly
transport rest {
method: GET,
path: "/repos/\{owner\}/\{repo\}/actions/runs/\{run_id\}/artifacts",
query: { per_page: per_page }
}
response {
200 => ActionsArtifactList
401 => GitHubErrorShape
403 => GitHubErrorShape
404 => GitHubErrorShape
5xx => GitHubErrorShape
}
}

operation DownloadArtifact {
requires Network
input {
auth_token: Secret
owner: String
repo: String
artifact_id: String
}
output {
archive: Bytes
}
readonly
transport rest {
method: GET,
path: "/repos/\{owner\}/\{repo\}/actions/artifacts/\{artifact_id\}/zip",
response_format: Text
}
response {
200 => Bytes
401 => GitHubErrorShape
403 => GitHubErrorShape
404 => GitHubErrorShape
410 => GitHubErrorShape
5xx => GitHubErrorShape
}
}
}
67 changes: 67 additions & 0 deletions dag/extdeps/github/git_database.dag
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type GitRefObjectWire {
sha: String
}

type GitRefDeletedBody {}

type GitRefWire {
ref: String
object: GitRefObjectWire
Expand Down Expand Up @@ -111,10 +113,21 @@ data git_blob_encoding_base64: NonEmptyStr = "base64"
// so no caller of UpdateRefFastForward can express a forced update; a moved branch answers 422
// "Update is not a fast forward" and that refusal IS the compare-and-swap. A forced variant would be
// a different operation with its own name and its own consumer.
// CreateRef AND DeleteRef (docs.github.com/en/rest/git/refs#create-a-reference and
// #delete-a-reference, read 2026-10-04). CreateRef takes the FULL ref name (`refs/tags/<name>`) in its
// body and answers 201 with the reference; an existing ref answers 422 "Reference already exists",
// so creation never moves a ref and that 422 is the create-once refusal. DeleteRef takes the
// `tags/<name>` form in its path and answers 204 with no body; a ref already gone answers 422
// "Reference does not exist". Their consumer is gunbc.runner.runner_qualification_ref_pin (a create-once branch per qualification attempt and its removal).
//
// THE BEARER IS AN INPUT WHEN ONE IS GIVEN. Every operation already took `auth_token`; the service read
// only GITHUB_TOKEN. Declaring both lets a caller that holds an installation token present it, and a
// caller passing "" (gunbc.heal_publication) falls through to GITHUB_TOKEN exactly as before.
service github.GitDatabase {
config {
endpoint: default_api_base
auth: Bearer
auth_input: auth_token
auth_source: EnvVar { name: "GITHUB_TOKEN" }
}

Expand Down Expand Up @@ -306,4 +319,58 @@ service github.GitDatabase {
5xx => GitHubErrorShape
}
}

operation CreateRef {
requires Network
input {
auth_token: Secret
owner: String
repo: String
full_ref: String
sha: String
}
output {
reference: GitRefWire
}
transport rest {
method: POST,
path: "/repos/\{owner\}/\{repo\}/git/refs",
body: { ref: full_ref, sha: sha }
}
response {
201 => GitRefWire
401 => GitHubErrorShape
403 => GitHubErrorShape
404 => GitHubErrorShape
409 => GitHubErrorShape
422 => GitHubErrorShape
5xx => GitHubErrorShape
}
}

operation DeleteRef {
requires Network
input {
auth_token: Secret
owner: String
repo: String
ref: String
}
output {
result: GitRefDeletedBody
}
transport rest {
method: DELETE,
path: "/repos/\{owner\}/\{repo\}/git/refs/\{ref\}"
}
response {
204 => GitRefDeletedBody
401 => GitHubErrorShape
403 => GitHubErrorShape
404 => GitHubErrorShape
409 => GitHubErrorShape
422 => GitHubErrorShape
5xx => GitHubErrorShape
}
}
}
36 changes: 36 additions & 0 deletions dag/extdeps/github/org_actions.dag
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,16 @@ type OrgRunnerGroupListWire {

data org_runner_groups_max_per_page: Int = 100

// UpdateOrganizationRunnerGroupWorkflows:
// update a self-hosted runner group for an organization (docs.github.com/en/rest/actions/
// self-hosted-runner-groups#update-a-self-hosted-runner-group-for-an-organization, REST
// 2022-11-28, read 2026-10-04): PATCH sets restricted_to_workflows and selected_workflows and
// answers 200 with the group. Each selected entry is `<owner>/<repo>/<workflow path>@<ref>`; per
// docs.github.com/en/enterprise-cloud@latest/actions/how-tos/manage-runners/self-hosted-runners/
// manage-access (read 2026-10-04), "Pin non-reusable workflows to a branch. Pin reusable
// workflows to a branch, tag, or full SHA" -- a dispatched (non-reusable) workflow is selectable
// only at a branch, which is why a qualification pin is a branch and not a SHA. Its consumer is
// gunbc.runner.runner_qualification_ref_pin, which writes only the dedicated qualification group.
service github.OrgRunnerGroupsRest {
config {
endpoint: default_api_base
Expand Down Expand Up @@ -161,4 +171,30 @@ service github.OrgRunnerGroupsRest {
5xx => GitHubErrorShape
}
}

operation UpdateOrganizationRunnerGroupWorkflows {
requires Network
input {
installation_token: Secret
org: NonEmptyStr
runner_group_id: Int
selected_workflows: List<String>
}
output {
result: OrgRunnerGroupWire
}
transport rest {
method: PATCH,
path: "/orgs/\{org\}/actions/runner-groups/\{runner_group_id\}",
body: { restricted_to_workflows: true, selected_workflows: selected_workflows }
}
response {
200 => OrgRunnerGroupWire
401 => GitHubErrorShape
403 => GitHubErrorShape
404 => GitHubErrorShape
422 => GitHubErrorShape
5xx => GitHubErrorShape
}
}
}
52 changes: 52 additions & 0 deletions dag/extdeps/github/workflow_runs.dag
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import std.dissolution { unbound_dissolution }
import std.decl_ref { decl_ref }
import std.algebra { Cons, Empty }
import std.resources { Network }
import std.serialization { Text }
import extdeps.transports.rest { RestResult }

// WorkflowJobRun.labels are read by gunbc.public_workload_census (observed_job_labels) to
Expand Down Expand Up @@ -194,6 +195,12 @@ fn workflow_job_attempt_filter_wire(f: WorkflowJobAttemptFilter) -> String {
// rendered name. The parenthetical of combination VALUES in axis order is the rendering this
// tree observed on those names; it is not a REST field. Standing is TranscribedUncited until
// GitHub's Jobs docs state that encoding.
// runner_id AND runner_name ARE WHICH RUNNER TOOK THE JOB, a third fact beside the declared runs-on
// and the observed labels: two runners can carry identical labels. runner_id is the exact identity
// GitHub returned when the JIT registration was minted (gunbc.runner.runner_qualification_dispatch
// job_ran_on joins on it); runner_name is corroboration, since one name can resolve to several ids.
// Upstream publishes both as nullable -- null until a runner takes the job -- and every record in
// this tree written before the fields existed carries none rather than a guessed value.
type WorkflowJobRun {
id: Int
run_id: Int
Expand All @@ -202,6 +209,8 @@ type WorkflowJobRun {
status: WorkflowRunStatus
conclusion: WorkflowRunConclusion?
labels: List<String>
runner_id: Int?
runner_name: String?
created_at: Timestamp?
started_at: Timestamp?
completed_at: Timestamp?
Expand Down Expand Up @@ -287,16 +296,32 @@ data structural_coverage_gap_workflow_run_codec_hand_rolled: List<String> = [
// operation is not a module item, so per-operation rationale is not expressible; it belongs here
// or nowhere.
//
// DOWNLOADJOBLOGSFORWORKFLOWRUN IS UPSTREAM'S "Download job logs for a workflow run"
// (actions/download-job-logs-for-workflow-run, docs.github.com/en/rest/actions/workflow-jobs, read
// 2026-10-04): `GET /repos/{owner}/{repo}/actions/jobs/{job_id}/logs` answers `302 Found` with a
// `Location` naming a storage URL that expires after about a minute, and the body there is the job's
// log as plain text, one line per row behind an RFC 3339 timestamp. The redirect is followed by the
// bound REST realization (the seed's ureq handler), so the response block names the text at the end
// of it. A body the handler cannot read -- not UTF-8, or past its read cap -- is RestBodyUndecodable
// with its status, never a truncated log reported as the whole one.
//
// THE FILTER IS A CALLER'S CHOICE AND WAS A LITERAL. "latest" returns only the most recent attempt
// of each job, which is the right answer for "what is the current state" and the wrong one for any
// census of consumed capacity: a re-run mutates a job's record in place, so the attempts "latest"
// drops are execution that really happened and really occupied a runner. A caller measuring
// occupancy needs "all"; a caller reading current state needs "latest"; neither is a property of
// this operation, so the choice moves to the input with "latest" as the compatible default.
// THE BEARER IS THE CALLER'S auth_token WHEN ONE IS GIVEN. Every operation already took auth_token,
// and the service read only GITHUB_TOKEN, so a caller holding an installation token
// (gunbc.github_effect_perform read_run_with / read_attempt_jobs_with) was silently read under the
// ambient Actions credential. Declaring auth_input beside auth_source makes a non-empty auth_token the
// bearer; a caller passing "" (gunbc.pr_base_freshness, gunbc.fleet_desired_admission,
// gunbc.roadmap_launch_deployment_cli) falls through to GITHUB_TOKEN exactly as before.
service github.WorkflowRuns {
config {
endpoint: default_api_base
auth: Bearer
auth_input: auth_token
auth_source: EnvVar { name: "GITHUB_TOKEN" }
}

Expand Down Expand Up @@ -415,6 +440,33 @@ service github.WorkflowRuns {
500 => GitHubErrorShape
}
}
operation DownloadJobLogsForWorkflowRun {
requires Network
input {
auth_token: Secret
owner: String
repo: String
job_id: String
}
output {
log: String
}
readonly
transport rest {
method: GET,
path: "/repos/\{owner\}/\{repo\}/actions/jobs/\{job_id\}/logs",
response_format: Text
}
response {
200 => String
401 => GitHubErrorShape
403 => GitHubErrorShape
404 => GitHubErrorShape
410 => GitHubErrorShape
5xx => GitHubErrorShape
}
}

operation ListJobs {
requires Network
input {
Expand Down
Loading