Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions .github/workflows/v2-ci-ordinary-settlement.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,9 @@ jobs:
runs-on: ubuntu-latest
timeout-minutes: 10
env:
PACKAGE_VERSION: 0.1.5
PACKAGE_VERSION: 0.3.0
# Immutable v0.1.5 GitHub release archive, independently read back before activation.
PACKAGE_SHA256: 3567a92825917a7d537f6c5c545d3a7947bc35edd666fc3a1898de3bf97267c9
PACKAGE_SHA256: a8cd6d602e1203257e1241df0b5dfdb9d867334b46dc406d8cdaa8e6d2b3019c
permissions:
actions: read
contents: read
Expand Down Expand Up @@ -91,7 +91,7 @@ jobs:
set -euo pipefail
receipt="$RUNNER_TEMP/ordinary-v2-receipt/ordinary-v2-preflight.json"
test "$(sha256sum "$receipt" | cut -d ' ' -f 1)" = "$EXPECTED_RECEIPT_SHA256"
python3 tools/v2-ci-ordinary-observe.py verify "$receipt"
python3 tools/v2-ci-ordinary-observe.py verify-main "$receipt"
- name: Set up the pinned .NET SDK
uses: actions/setup-dotnet@a98b56852c35b8e3190ac28c8c2271da59106c68
with:
Expand Down Expand Up @@ -125,4 +125,4 @@ jobs:
V2_ORDINARY_AUTHORIZER_PRIVATE_KEY: ${{ secrets.V2_ORDINARY_AUTHORIZER_PRIVATE_KEY }}
run: |
set -euo pipefail
"$RUNNER_TEMP/ordinary-v2-cli/fsgg-coordination" ordinary-settlement execute
"$RUNNER_TEMP/ordinary-v2-cli/fsgg-coordination" ordinary-settlement execute-main
107 changes: 107 additions & 0 deletions policy/v2-ci-ordinary-settlement-main-anchor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
{
"schema": "fsgg.github.v2-ci-ordinary-settlement-anchor/1",
"policyId": "v2-ci-i1-ordinary-settlement-v1",
"operationClass": "ordinary-post-merge-delivery-settlement",
"authorizer": {
"keyId": "ordinary-v2-production-6121c3f2ab38acf3",
"algorithm": "RSA-PSS-SHA256",
"publicKeySpkiSha256": "6121c3f2ab38acf38a37f782eb7775da78598b9cfabc0054917d3d59fe50e3ee"
},
"writer": {
"appId": 5064713,
"installationId": 164553252,
"repository": "FS-GG/FS.GG.Coordination.Authority",
"repositoryId": 1351660651,
"permissions": {
"contents": "write",
"metadata": "read"
}
},
"rulesets": {
"writer": {
"id": 24802693,
"name": "ordinary-v2-main-writer",
"enforcement": "active",
"updatedAt": "2026-10-09T18:56:41.235+02:00",
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"refs/heads/main"
]
}
},
"rules": [
{
"type": "creation"
},
{
"type": "update"
}
],
"bypassActors": [
{
"actorId": 4882140,
"actorType": "Integration",
"bypassMode": "always"
},
{
"actorId": 5064713,
"actorType": "Integration",
"bypassMode": "always"
}
]
},
"integrity": {
"id": 24802698,
"name": "ordinary-v2-main-integrity",
"enforcement": "active",
"updatedAt": "2026-10-09T18:56:42.726+02:00",
"conditions": {
"ref_name": {
"exclude": [],
"include": [
"refs/heads/main"
]
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
}
],
"bypassActors": []
}
},
"effectiveRules": [
{
"type": "deletion",
"rulesetId": 24802698,
"rulesetSourceType": "Repository",
"rulesetSource": "FS-GG/FS.GG.Coordination.Authority"
},
{
"type": "non_fast_forward",
"rulesetId": 24802698,
"rulesetSourceType": "Repository",
"rulesetSource": "FS-GG/FS.GG.Coordination.Authority"
},
{
"type": "creation",
"rulesetId": 24802693,
"rulesetSourceType": "Repository",
"rulesetSource": "FS-GG/FS.GG.Coordination.Authority"
},
{
"type": "update",
"rulesetId": 24802693,
"rulesetSourceType": "Repository",
"rulesetSource": "FS-GG/FS.GG.Coordination.Authority"
}
],
"acceptedAt": "2026-10-09T19:31:28.661736+00:00",
"sourceCommit": "8eef1ab7f205132553632e03dc650e7ecdd03679"
}
20 changes: 10 additions & 10 deletions policy/v2-ci-ordinary-settlement.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"repositoryId": 1305845505
},
"sourceImplementation": {
"repository": "FS-GG/FS.GG.Rendering",
"commit": "8f4acd853566ea287abd15655c1aa5c4d3ceb403",
"adaptation": "net-v1-code-owned-source-profile",
"observerSha256": "6e63f6f724fb267e77ef02f41b4c58a833e0dc5b08c003f07fd16c89e4f7fd55",
"repository": "FS-GG/FS.GG.Coordination",
"commit": "8eef1ab7f205132553632e03dc650e7ecdd03679",
"adaptation": "net-v1-code-owned-source-profile; main-storage extension with local profile preserved",
"observerSha256": "7f5500d810ab9169d967f8c19fbcb01d706ebf82fdeea6e4a6927b0b19eef29a",
"qualificationSha256": "ff38a1b5748aaec8ff23561ae7c0c3eb67fb5232b9a4a43071dff22182dbac32"
},
"operationClass": "ordinary-post-merge-delivery-settlement",
Expand Down Expand Up @@ -109,14 +109,14 @@
},
"packagePin": {
"status": "published-verified",
"version": "0.1.5",
"sha256": "3567a92825917a7d537f6c5c545d3a7947bc35edd666fc3a1898de3bf97267c9",
"version": "0.3.0",
"sha256": "a8cd6d602e1203257e1241df0b5dfdb9d867334b46dc406d8cdaa8e6d2b3019c",
"sourceCommit": "8eef1ab7f205132553632e03dc650e7ecdd03679",
"servedPackageVerified": true,
"sourceCommit": "1268908d2d5a38d30a764c927f3e0591e53138aa",
"releaseTag": "v0.1.5",
"publisherRunId": 36437778484,
"requiredBeforeActivation": true,
"requiredCapability": "net-v1 selected source",
"requiredBeforeActivation": true
"publisherRunId": 37983508705,
"releaseTag": "v0.3.0"
},
"credentialInventory": [
{
Expand Down
12 changes: 6 additions & 6 deletions tests/v2-ci-ordinary-observe/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,12 @@ def test_workflow_prepares_bounded_settlement_with_exact_receipt_guard(self):
self.assertIn("FSGG_V2_SOURCE_PROFILE: net-v1", workflow)
self.assertIn("persist-credentials: false", workflow)
self.assertIn("python3 tools/v2-ci-ordinary-observe.py produce", workflow)
self.assertIn("python3 tools/v2-ci-ordinary-observe.py verify", workflow)
self.assertIn("PACKAGE_VERSION: 0.1.5", workflow)
self.assertIn("PACKAGE_SHA256: 3567a92825917a7d537f6c5c545d3a7947bc35edd666fc3a1898de3bf97267c9", workflow)
self.assertIn("python3 tools/v2-ci-ordinary-observe.py verify-main", workflow)
self.assertIn("PACKAGE_VERSION: 0.3.0", workflow)
self.assertIn("PACKAGE_SHA256: a8cd6d602e1203257e1241df0b5dfdb9d867334b46dc406d8cdaa8e6d2b3019c", workflow)
self.assertIn("https://github.com/FS-GG/FS.GG.Coordination/releases/download/v$PACKAGE_VERSION/FS.GG.Coordination.Cli.$PACKAGE_VERSION.nupkg", workflow)
self.assertNotIn("api.nuget.org/v3-flatcontainer", workflow)
self.assertIn("ordinary-settlement execute", workflow)
self.assertIn("ordinary-settlement execute-main", workflow)
for name in ("V2_ORDINARY_APP_ID", "V2_ORDINARY_APP_PRIVATE_KEY", "V2_ORDINARY_AUTHORIZER_PRIVATE_KEY"):
self.assertIn("${{ secrets." + name + " }}", workflow)
for forbidden in ("workflow_dispatch:", "repository_dispatch:", "pull_request:", "pull_request_target:", "V1_ADMISSION", "CALLABLE_ISOLATED_OPERATION"):
Expand All @@ -134,8 +134,8 @@ def test_policy_anchor_environment_and_published_package_are_bounded(self):
}, set(observation["secretNames"]))
self.assertEqual("published-verified",
policy["packagePin"]["status"])
self.assertEqual("0.1.5", policy["packagePin"]["version"])
self.assertEqual("3567a92825917a7d537f6c5c545d3a7947bc35edd666fc3a1898de3bf97267c9",
self.assertEqual("0.3.0", policy["packagePin"]["version"])
self.assertEqual("a8cd6d602e1203257e1241df0b5dfdb9d867334b46dc406d8cdaa8e6d2b3019c",
policy["packagePin"]["sha256"])
self.assertTrue(policy["packagePin"]["servedPackageVerified"])
self.assertEqual(3, len(policy["credentialInventory"]))
Expand Down
6 changes: 3 additions & 3 deletions tests/v2-ci-ordinary-qualification/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ def test_policy_installs_only_the_verified_net_profile_release(self):
self.assertEqual(3, len(self.policy["credentialInventory"]))
pin = self.policy["packagePin"]
self.assertEqual("published-verified", pin["status"])
self.assertEqual("0.1.5", pin["version"])
self.assertEqual("3567a92825917a7d537f6c5c545d3a7947bc35edd666fc3a1898de3bf97267c9",
self.assertEqual("0.3.0", pin["version"])
self.assertEqual("a8cd6d602e1203257e1241df0b5dfdb9d867334b46dc406d8cdaa8e6d2b3019c",
pin["sha256"])
self.assertEqual("1268908d2d5a38d30a764c927f3e0591e53138aa", pin["sourceCommit"])
self.assertEqual("8eef1ab7f205132553632e03dc650e7ecdd03679", pin["sourceCommit"])
self.assertTrue(pin["servedPackageVerified"])
self.assertEqual(["OpenV2"], self.policy["unchangedGates"])
self.assertEqual({"v1Admission": False, "receiverStateImport": False},
Expand Down
17 changes: 11 additions & 6 deletions tools/v2-ci-ordinary-observe.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def current_file(repository: str, path: str, revision: str) -> bytes:
raise QUALIFICATION.Refusal(f"current protected file malformed: {path}") from error


def current_authority(repository: str, policy: dict, policy_path: pathlib.Path = POLICY_PATH) -> None:
def current_authority(repository: str, policy: dict, policy_path: pathlib.Path = POLICY_PATH,
*, main_storage: bool = False) -> None:
"""Fence a queued or rerun job against the present protected source."""
before = api(f"repos/{repository}/git/ref/heads/main")
revision = before.get("object", {}).get("sha") if isinstance(before, dict) else None
Expand All @@ -84,6 +85,8 @@ def current_authority(repository: str, policy: dict, policy_path: pathlib.Path =
paths.append("policy/v2-ci-ordinary-settlement-rehearsal-anchor.json"
if policy_path == REHEARSAL_POLICY_PATH
else "policy/v2-ci-ordinary-settlement-anchor.json")
if main_storage:
paths.append("policy/v2-ci-ordinary-settlement-main-anchor.json")
for path in paths:
if current_file(repository, path, revision) != (ROOT / path).read_bytes():
raise QUALIFICATION.Refusal(f"current protected authority changed: {path}")
Expand Down Expand Up @@ -163,7 +166,8 @@ def equivalent_tree(repository: str, head: str, source: str, base: str) -> str:
return head_tree


def observe(environ: dict[str, str], rehearsal: bool = False) -> dict:
def observe(environ: dict[str, str], rehearsal: bool = False,
*, main_storage: bool = False) -> dict:
policy_path = REHEARSAL_POLICY_PATH if rehearsal else POLICY_PATH
policy = QUALIFICATION.read_json(str(policy_path))
source = environ.get("GITHUB_SHA", "")
Expand Down Expand Up @@ -204,7 +208,7 @@ def observe(environ: dict[str, str], rehearsal: bool = False) -> dict:
capture_output=True, text=True, cwd=ROOT).stdout.strip()
if checkout != source:
raise QUALIFICATION.Refusal("checkout differs from triggering source")
current_authority(policy["repository"], policy, policy_path)
current_authority(policy["repository"], policy, policy_path, main_storage=main_storage)
run_id, attempt = environ.get("GITHUB_RUN_ID", ""), environ.get("GITHUB_RUN_ATTEMPT", "")
if not run_id.isdecimal() or not attempt.isdecimal() or int(run_id) < 1 or int(attempt) < 1:
raise QUALIFICATION.Refusal("invalid workflow run identity")
Expand Down Expand Up @@ -343,12 +347,13 @@ def rank(check: dict) -> tuple[datetime, int]:


def main() -> int:
actions = ("produce", "verify", "produce-rehearsal", "verify-rehearsal")
actions = ("produce", "verify", "verify-main", "produce-rehearsal", "verify-rehearsal")
if len(sys.argv) != 3 or sys.argv[1] not in actions:
print("usage: v2-ci-ordinary-observe.py produce|verify|produce-rehearsal|verify-rehearsal RECEIPT_PATH", file=sys.stderr)
print("usage: v2-ci-ordinary-observe.py produce|verify|verify-main|produce-rehearsal|verify-rehearsal RECEIPT_PATH", file=sys.stderr)
return 2
try:
actual = observe(dict(os.environ), rehearsal=sys.argv[1].endswith("-rehearsal"))
actual = observe(dict(os.environ), rehearsal=sys.argv[1].endswith("-rehearsal"),
main_storage=sys.argv[1] == "verify-main")
target = pathlib.Path(sys.argv[2])
encoded = json.dumps(actual, sort_keys=True, separators=(",", ":")) + "\n"
if sys.argv[1].startswith("produce"):
Expand Down
Loading