Problem
Protected main@64aa08d7fa487deacd41c761c36277ca68cab6c9 has a repository-identity inconsistency in scripts/ci/actions_queue_health_core.py.
REPOSITORY_PATTERN currently accepts any [A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+, while _repository_name() only rejects path segments exactly equal to . or ... As a result, traversal-adjacent/non-canonical identifiers such as ContextualWisdomLab/repository., ContextualWisdomLab/repo..name, ContextualWisdomLab./repository, and Contextual..WisdomLab/repository are admitted.
This matters because the queue-health collector consumes a reviewed repository allowlist and uses the validated owner/repository identity to perform cross-repository Actions reads. The read-only boundary should enforce the intended component invariant symmetrically on owner and repository names.
Do not treat the current protected scheduler regex as complete authority for this issue. Its generic full-name expression still misses an owner component ending in . before the slash; scheduler reconciliation remains separately owned by #2040. Source-fix paths use a narrower organization-local repository-name grammar and likewise are not a generic full-name validator for queue health.
Canonical implementation lane: #2268.
RED
Exercise the production path through load_allowlist() for at least:
ContextualWisdomLab/repository.
ContextualWisdomLab/repo..name
ContextualWisdomLab./repository
Contextual..WisdomLab/repository
ContextualWisdomLab/..
ContextualWisdomLab/.
The first four currently pass the production parser; all six must fail closed after repair.
The positive contract must also prove that legitimate names remain admissible, including:
ContextualWisdomLab/.github
ContextualWisdomLab/repository.name
ContextualWisdomLab/repository_name
ContextualWisdomLab/repository-name
Minimum causal fix
Retain the existing one-slash and allowed-character grammar, then validate both owner and repository components symmetrically: reject a component when it contains .. or ends in ., while preserving a leading single dot such as .github and ordinary interior single dots.
Prefer a shared/versioned validation helper only if one already owns exactly this generic component contract and can be consumed without introducing a mutable cross-module dependency. Otherwise keep the implementation local and pin both hostile and valid cases so future owner/repository validators cannot drift silently.
Do not weaken or disable queue-health, reduce its repository coverage, or treat malformed identities as skipped-success evidence.
Acceptance
- hostile identity RED is demonstrated against the pre-fix production parser;
- valid punctuation-bearing repository identities remain accepted;
- minimum production fix makes the complete identity suite GREEN;
- existing explicit allowlist and read-only/pinned workflow contract remain GREEN;
- exact-head security/quality checks complete normally;
- any adoption into stale scheduler/reconciliation branches is path-wise and does not copy the pre-fix queue-health slice.
Problem
Protected
main@64aa08d7fa487deacd41c761c36277ca68cab6c9has a repository-identity inconsistency inscripts/ci/actions_queue_health_core.py.REPOSITORY_PATTERNcurrently accepts any[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+, while_repository_name()only rejects path segments exactly equal to.or... As a result, traversal-adjacent/non-canonical identifiers such asContextualWisdomLab/repository.,ContextualWisdomLab/repo..name,ContextualWisdomLab./repository, andContextual..WisdomLab/repositoryare admitted.This matters because the queue-health collector consumes a reviewed repository allowlist and uses the validated owner/repository identity to perform cross-repository Actions reads. The read-only boundary should enforce the intended component invariant symmetrically on owner and repository names.
Do not treat the current protected scheduler regex as complete authority for this issue. Its generic full-name expression still misses an owner component ending in
.before the slash; scheduler reconciliation remains separately owned by #2040. Source-fix paths use a narrower organization-local repository-name grammar and likewise are not a generic full-name validator for queue health.Canonical implementation lane: #2268.
RED
Exercise the production path through
load_allowlist()for at least:ContextualWisdomLab/repository.ContextualWisdomLab/repo..nameContextualWisdomLab./repositoryContextual..WisdomLab/repositoryContextualWisdomLab/..ContextualWisdomLab/.The first four currently pass the production parser; all six must fail closed after repair.
The positive contract must also prove that legitimate names remain admissible, including:
ContextualWisdomLab/.githubContextualWisdomLab/repository.nameContextualWisdomLab/repository_nameContextualWisdomLab/repository-nameMinimum causal fix
Retain the existing one-slash and allowed-character grammar, then validate both owner and repository components symmetrically: reject a component when it contains
..or ends in., while preserving a leading single dot such as.githuband ordinary interior single dots.Prefer a shared/versioned validation helper only if one already owns exactly this generic component contract and can be consumed without introducing a mutable cross-module dependency. Otherwise keep the implementation local and pin both hostile and valid cases so future owner/repository validators cannot drift silently.
Do not weaken or disable queue-health, reduce its repository coverage, or treat malformed identities as skipped-success evidence.
Acceptance