fix(repo-readonly): own read-only deploy key; workflow-script drops write-capable gitea-ssh/v1

repo-readonly/v1 now declares write_targets: [], an ssh_hosts alias and its
own secrets_required (account platform-readonly.space:platform, a read-only
Gitea deploy key), and stages the key before cloning. workflow-script/v1 no
longer layers gitea-ssh/v1, so script nodes cannot push. Invariants updated:
credential layers in the composite must declare write_targets: [].

Bug 45a48685-23e9-4605-af1f-d93306108cef

Claude-Session: https://claude.ai/code/session_01N218bERyNeLhbLmDRDvbWF
This commit is contained in:
Paul O'Reilly
2026-10-02 20:09:30 +13:00
parent d850a4da68
commit ea7c11265b
5 changed files with 42 additions and 17 deletions

View File

@@ -16,11 +16,12 @@ def _load(kind_dir: str, name: str) -> dict:
return yaml.safe_load((_ROOT / kind_dir / name / "v1" / "harness.yaml").read_text())
def test_workflow_script_layers_shared_variables_then_cp_service_token():
def test_workflow_script_layers_shared_variables_cp_service_token_repo_readonly():
doc = _load("composites", "workflow-script")
assert doc["layers"] == [
{"context": "shared-variables/v1"},
{"context": "cp-service-token/v1"},
{"context": "repo-readonly/v1"},
]

View File

@@ -203,27 +203,25 @@ def test_cp_service_token_layer_already_sets_cp_service_token_file_env():
)
def test_workflow_script_composite_no_forge_credentials_no_write_targets_needed():
"""workflow-script/v1 has no forge credentials of its own and so does
NOT need to declare ``write_targets`` (HC-11). This is the inverse of
the forge-credentials invariant: a non-credential composite is fine
without that field.
def test_workflow_script_composite_forge_credentials_are_read_only():
"""Any layer in workflow-script/v1 that carries a forge credential MUST
declare ``write_targets: []`` (HC-11): a script node may read the project
repo but never push. The write-capable gitea-ssh/v1 layer must not be
present (bug 45a48685).
Spec: spec/harness.md HC-11 (only layers with forge credentials MUST
declare write_targets).
Spec: spec/harness.md HC-11, spec/typed-workflows.md WF-COMP-34.
"""
parsed = _load_layer("composites", "workflow-script")
# Walk every layer entry, ensure none introduce a forge credential.
from tests.invariants.forge_credentials import _layer_has_forge_credentials
for layer in parsed["layers"]:
kind_name, ref = next(iter(layer.items()))
name = ref.split("/")[0]
assert name != "gitea-ssh", "workflow-script/v1 must not layer the write-capable gitea-ssh/v1 (bug 45a48685)"
kind_dir = _KIND_TO_DIR[kind_name]
sub = _load_layer(kind_dir, name)
assert not _layer_has_forge_credentials(sub), (
f"workflow-script/v1's layer {name} introduced a forge credential; "
f"HC-11 would then require write_targets to be declared on the "
f"composite, and a script-node composite should never carry "
f"forge credentials (WF-COMP-31)."
)
if _layer_has_forge_credentials(sub):
assert sub.get("write_targets") == [], (
f"workflow-script/v1's layer {name} carries a forge credential "
f"but does not declare write_targets: [] (HC-11 read-only)."
)