Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
115 commits
Select commit Hold shift + click to select a range
ac23287
test(ci): require fail-closed workflow registry audit
seonghobae Aug 12, 2026
b8ad62a
feat(ci): classify orphaned workflow registry evidence read-only
seonghobae Aug 12, 2026
4f3c314
test(ci): bind workflow inventory to reported total count
seonghobae Aug 12, 2026
8aa8e86
fix(ci): verify paginated workflow count against API total
seonghobae Aug 12, 2026
d9d8b5a
test(ci): prevent stale file-size metadata bypass
seonghobae Aug 12, 2026
b4608dc
fix(ci): enforce audit input bound while reading
seonghobae Aug 12, 2026
e462a27
test(ci): reject impossible workflow audit timestamps
seonghobae Aug 12, 2026
65e8049
test(ci): cover remaining workflow registry review gaps
seonghobae Aug 12, 2026
1cd9b4f
fix(ci): close workflow registry audit gaps
seonghobae Aug 12, 2026
0c65ea9
test(ci): expose disabled protected workflows
seonghobae Aug 12, 2026
8a5d7ba
fix(ci): surface disabled protected workflows
seonghobae Aug 12, 2026
223e539
test(ci): reject duplicate workflow audit JSON keys
seonghobae Aug 12, 2026
5f8c219
fix(ci): reject ambiguous duplicate workflow audit JSON
seonghobae Aug 12, 2026
e288a62
test(ci): reject pathological JSON nesting cleanly
seonghobae Aug 12, 2026
22bdcf6
test(ci): reproduce parser recursion failure deterministically
seonghobae Aug 12, 2026
02d9313
fix(ci): bound JSON parser recursion failures
seonghobae Aug 12, 2026
1fc028c
test(ci): use one unittest import style
seonghobae Aug 12, 2026
65b83ca
chore(ci): align workflow registry audit with protected main
seonghobae Aug 13, 2026
90a504f
revert: restore bounded workflow registry audit diff
seonghobae Aug 13, 2026
11a4a8c
Merge branch 'main' into test/workflow-registry-orphan-audit
github-actions[bot] Aug 13, 2026
e376124
test(ci): reject impossible workflow source paths
seonghobae Aug 14, 2026
ef77785
fix(ci): validate repository workflow source shape
seonghobae Aug 14, 2026
d7f2d20
test(ci): reject boolean integer lookalikes in workflow evidence
seonghobae Aug 15, 2026
77b63fd
fix(ci): reject boolean integer lookalikes in workflow evidence
seonghobae Aug 15, 2026
c226080
docs(changelog): record workflow registry audit evidence
seonghobae Aug 15, 2026
51749a9
test(ci): reject invisible workflow audit text
seonghobae Aug 15, 2026
519c36a
fix(ci): reject invisible workflow audit controls
seonghobae Aug 15, 2026
1fd8dae
test(ci): reject float workflow registry status codes
seonghobae Aug 15, 2026
b1b5488
fix(ci): require integer workflow registry status codes
seonghobae Aug 15, 2026
5e2437c
test(ci): reject nonstandard JSON numeric constants
seonghobae Aug 15, 2026
80c2730
fix(ci): reject nonstandard JSON numeric constants
seonghobae Aug 15, 2026
09f1507
test(ci): bound workflow registry JSON integers
seonghobae Aug 15, 2026
85c2b09
fix(ci): bound workflow registry JSON integers
seonghobae Aug 15, 2026
441967a
test(ci): reject workflow registry JSON floats
seonghobae Aug 15, 2026
5ffaa42
fix(ci): reject workflow registry JSON floats
seonghobae Aug 15, 2026
527278c
test(ci): reject workflow ids wider than u64
seonghobae Aug 15, 2026
8d8649f
fix(ci): bound workflow registry ids to u64
seonghobae Aug 15, 2026
36b3845
test(ci): reject malformed Unicode evidence safely
seonghobae Aug 15, 2026
d6ddd7b
fix(ci): normalize malformed Unicode audit evidence
seonghobae Aug 15, 2026
62e8463
test(ci): reject ambiguous registry schema extensions
seonghobae Aug 15, 2026
f6a10d8
fix(ci): close workflow registry schema v1
seonghobae Aug 15, 2026
a530500
test(ci): reject noncanonical negative-zero evidence
seonghobae Aug 16, 2026
9deffec
fix(ci): reject noncanonical negative-zero evidence
seonghobae Aug 16, 2026
05899bb
docs(changelog): record canonical integer evidence
seonghobae Aug 16, 2026
6f7f65d
test(ci): cover workflow registry HTTP failures
seonghobae Aug 16, 2026
409b8b0
test(ci): classify retryable workflow registry failures
seonghobae Aug 16, 2026
2354d3c
Merge branch 'main' into test/workflow-registry-orphan-audit
seonghobae Aug 16, 2026
b35911f
fix(ci): classify retryable registry collection failures
seonghobae Aug 16, 2026
78ba9b9
test(ci): reject retry for non-transient HTTP failures
seonghobae Aug 16, 2026
ba72cba
fix(ci): bound retryable registry HTTP failures
seonghobae Aug 16, 2026
acb0dfe
docs(changelog): record bounded registry retry contract
seonghobae Aug 16, 2026
6621603
test(ci): require bounded Retry-After registry evidence
seonghobae Aug 16, 2026
98db5a3
fix(ci): preserve bounded Retry-After evidence
seonghobae Aug 16, 2026
e5ae33f
docs(changelog): record Retry-After audit evidence
seonghobae Aug 16, 2026
3eace83
test(ci): reject Retry-After on successful registry evidence
seonghobae Aug 16, 2026
4561282
fix(ci): reject retry metadata on successful registry pages
seonghobae Aug 16, 2026
51e6fb1
test(ci): reject impossible workflow registry HTTP statuses
seonghobae Aug 17, 2026
1a21101
fix(ci): reject impossible workflow registry HTTP statuses
seonghobae Aug 17, 2026
ac26bde
test(ci): bind active workflow ownership to exact PR heads
seonghobae Aug 17, 2026
c4641b8
test(ci): bind legacy audit fixtures to exact PR owner
seonghobae Aug 17, 2026
7330947
fix(ci): bind active workflow exemptions to exact PR heads
seonghobae Aug 17, 2026
29c6626
docs(changelog): record exact active PR workflow ownership
seonghobae Aug 17, 2026
43bd422
test(ci): surface disabled active-PR workflow drift
seonghobae Aug 18, 2026
24922ed
fix(ci): surface disabled active-PR workflow drift
seonghobae Aug 18, 2026
d4ae542
docs(ci): record disabled active-PR workflow drift
seonghobae Aug 18, 2026
984bd50
test(ci): reject null Git commit identities
seonghobae Aug 18, 2026
5080184
fix(ci): reject null Git commit identities
seonghobae Aug 18, 2026
0fa7815
docs(changelog): record null Git object rejection
seonghobae Aug 18, 2026
0e88fb9
test(ci): reject moved active PR workflow owner heads
seonghobae Aug 20, 2026
ab67fcd
test(ci): require second active PR head observation
seonghobae Aug 20, 2026
43cd379
fix(ci): fail closed when active PR workflow owner head moves
seonghobae Aug 20, 2026
53c7c43
test(ci): refresh workflow owner fixtures at exact heads
seonghobae Aug 20, 2026
4c9e07e
test(ci): expose bounded registry retry guidance
seonghobae Aug 21, 2026
8206d9e
fix(ci): surface bounded registry retry guidance
seonghobae Aug 21, 2026
f76e7a4
test(ci): require retryable workflow audit timeout
seonghobae Aug 21, 2026
6dae952
fix(ci): classify workflow audit request timeout as retryable
seonghobae Aug 21, 2026
f112d2d
docs(changelog): record workflow audit request-timeout retry
seonghobae Aug 21, 2026
766ecaa
test(ci): reject streaming workflow audit inputs
seonghobae Aug 23, 2026
bad20dc
fix(ci): reject non-regular workflow audit inputs
seonghobae Aug 23, 2026
40f64da
test(ci): keep size bound on real audit files
seonghobae Aug 23, 2026
e64f7d2
test(ci): tolerate expected FIFO writer disconnect
seonghobae Aug 23, 2026
08f6871
test(ci): remove stale workflow audit import
seonghobae Aug 23, 2026
8c3d6d2
test(ci): reject symlink workflow audit evidence
seonghobae Aug 24, 2026
42b1edd
fix(ci): reject indirect workflow audit evidence
seonghobae Aug 24, 2026
7726130
test(ci): reject workflow audit ancestor symlink swaps
seonghobae Aug 24, 2026
49244fb
fix(ci): pin workflow audit path traversal to directory descriptors
seonghobae Aug 24, 2026
0b3d59e
test(ci): reject symlinked workflow audit output
seonghobae Aug 24, 2026
dc90cd4
fix(ci): bind workflow audit output path authority
seonghobae Aug 24, 2026
e3fa663
test(ci): reject hard-linked workflow audit output
seonghobae Aug 24, 2026
296dfc3
fix(ci): reject linked workflow audit outputs
seonghobae Aug 24, 2026
e34accd
test(ci): reproduce raced output hard-link alias
seonghobae Aug 24, 2026
1756ce1
fix(ci): fail closed on preexisting audit output
seonghobae Aug 24, 2026
688309e
chore(ci): converge workflow audit with protected main
seonghobae Aug 25, 2026
f2dd4b2
docs(changelog): preserve workflow audit release notes
seonghobae Aug 25, 2026
320f1da
test(ci): remove partial audit output after write failure
seonghobae Aug 25, 2026
ef7c702
fix(ci): stage audit output before atomic publish
seonghobae Aug 25, 2026
f5f0538
test(ci): cover post-publish cleanup failures
seonghobae Aug 25, 2026
459c13e
fix(ci): recover audit publish cleanup
seonghobae Aug 25, 2026
687086a
fix(ci): bind output capability checks to stdlib primitives
seonghobae Aug 25, 2026
5c059a1
test(ci): cover existing-output fstat failure
seonghobae Aug 25, 2026
581b551
fix(ci): normalize existing-output stat failure
seonghobae Aug 25, 2026
cd764c1
test(ci): reproduce staging fstat cleanup leak
seonghobae Aug 25, 2026
cc98483
fix(ci): clean staging after inspection failure
seonghobae Aug 25, 2026
ddaa47c
test(ci): reproduce cleanup error masking fd leak
seonghobae Aug 25, 2026
6dd2023
fix(ci): preserve primary output failure during cleanup
seonghobae Aug 25, 2026
30cc458
fix(ci): reject homoglyph workflow path confusion in registry audit
seonghobae Aug 26, 2026
30f909a
test(ci): reproduce Python 3.10 cleanup compatibility failure
seonghobae Aug 26, 2026
296ad25
fix(ci): preserve cleanup failures on Python 3.10
seonghobae Aug 26, 2026
cad4bed
chore(ci): restack workflow registry audit onto protected main
seonghobae Aug 27, 2026
ae247ff
test(ci): require durable workflow audit publication
seonghobae Aug 27, 2026
151450d
fix(ci): fsync workflow audit directory publication
seonghobae Aug 27, 2026
41fd850
docs(ci): document workflow registry audit contract
seonghobae Aug 27, 2026
028789d
docs(ci): record workflow registry audit utility
seonghobae Aug 27, 2026
89d9c56
test(ci): reproduce persistent staging cleanup masking
seonghobae Aug 28, 2026
fdb8869
fix(ci): preserve causal staging cleanup failure
seonghobae Aug 28, 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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ All notable changes to OriginWeave are documented in this file. The format follo
- Refreshed the product-gap queue to 126 open pull requests (54 ready, 72 draft) after #190, #188, #185, #192, #182, #184, #115, #181, #116, #117, #118, #183, #114, #127, #112, #109, #186, #110, #108, #111, #174, and #113 were merged into their immediate stacked prerequisites. PRs #147, #146, #145, #144, #143, #142, #141, #139, #136, #132, #129, and #128 moved to ready after exact-head checks and thread review; these are queue-consolidation results, not protected-main shipment.

### Added
- Added a documented, credential-free workflow-registry audit operator path that binds exact protected-head and active-PR ownership evidence, fails closed on incomplete or malformed registry collections, and publishes create-once JSON only after file and parent-directory durability barriers succeed.
- Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate.
- Refreshed the product and technical gap baseline onto the 2026-08-26 live inventory: 126 open pull requests (54 ready, 72 draft), protected-main promotion of #168/#194/#196/#216/#151, a verified maintenance-loop record (supersession closure of #153, conflict reconciliations on #37/#149/#152/#173/#175, issue #212 option-(b) authorization on #43, Strix vuln-0001 homoglyph remediation on #124), provider-rerun outcome evidence, an organization review-pipeline congestion record, and refreshed merge-order queue guidance. Documentation evidence contracts were aligned to the same snapshot so the baseline, its dated markers, and the pinned exact-head rows cannot silently diverge.

Expand Down Expand Up @@ -102,4 +103,4 @@ All notable changes to OriginWeave are documented in this file. The format follo
- The hourly product agent has no Git metadata or repository authority. A separate post-verification publisher opens one PR and cannot approve or merge it.
- The unprivileged OpenCode user is restricted to loopback egress during model execution, preventing runner-wide allow-listed endpoints from becoming direct source-exfiltration channels.

[Unreleased]: https://github.com/ContextualWisdomLab/OriginWeave/compare/main...HEAD
[Unreleased]: https://github.com/ContextualWisdomLab/OriginWeave/compare/main...HEAD
32 changes: 32 additions & 0 deletions docs/WORKFLOW_REGISTRY_AUDIT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Workflow Registry Audit

## Status and scope

`scripts/ci/audit_workflow_registry.py` is an operator-facing, credential-free, read-only audit utility. It classifies operator-collected GitHub Actions workflow-registry evidence; it does **not** call GitHub, disable workflows, change repository settings, or grant mutation authority. Any later workflow disablement remains a separate authorized control-plane action that must independently refetch the exact workflow identity immediately before mutation.

## Invocation

```bash
python3 scripts/ci/audit_workflow_registry.py INPUT.json
python3 scripts/ci/audit_workflow_registry.py INPUT.json --output evidence.json
```

Without `--output`, canonical JSON evidence is written to stdout. With `--output`, the target is create-once: an existing leaf is never overwritten.

## Collection contract

The input is bounded to four MiB and must be a directly named regular UTF-8 JSON file reached without symbolic-link path components. FIFO/device input, ambiguous parent components, file-identity movement, duplicate JSON members, floating-point schema values, non-standard JSON constants, oversized integers, and malformed input fail closed.

Schema version 1 binds the collection to equal expected and observed protected-default-branch commit SHAs and one valid second-precision UTC observation timestamp. Registry pages must be contiguous from page 1, every accepted page must have HTTP 200, `has_next` must agree with the supplied page set, and the sum of all page records must equal GitHub's unfiltered `reported_total_count` for that collection. A non-200 page remains failed evidence. The typed retry metadata only states whether bounded recollection is appropriate for reviewed transient statuses (`408`, `429`, `500`, `502`, `503`, `504`, plus `403` when a validated bounded `Retry-After` was retained); it never converts failure into success.

Protected-main workflow paths and active-PR workflow paths are exact, duplicate-free canonical `.github/workflows/*.yml` or `.yaml` identities. Every active-PR exemption is bound to one positive pull-request number and two independently supplied lowercase 40-character contributor-head observations that must match. Protected-main and active-PR ownership may not overlap. Registry records reject duplicate IDs, duplicate paths, ambiguous path case/encoding/traversal, unsupported state values, and malformed workflow identities.

## Output and durability contract

The evidence records the exact protected-head SHA, observation time, pagination receipts, immutable workflow IDs, exact paths/states, classifications, and active-PR ownership where applicable. `active_orphan_repository_workflow` may be emitted as a `disable_candidate`; that field is evidence for review, not permission to mutate GitHub.

A file output is staged as a mode-0600 regular inode in the already-authorized parent directory, flushed and file-`fsync`ed, identity/link-count checked, linked to the absent canonical leaf, and reduced to one canonical link. The final parent directory is then `fsync`ed before success is reported. If publication, staging cleanup, or parent-directory durability fails, the utility preserves the primary typed error, performs only identity-checked bounded cleanup/rollback, and does not report successful evidence publication. Unknown identity changes fail closed rather than deleting an unproven path.

## Operator acceptance

Treat the generated JSON as point-in-time evidence only. Before any authorized workflow lifecycle mutation, independently refetch protected `main`, the relevant active-PR heads, the workflow registry, ruleset/branch-protection state, and the exact immutable workflow ID. If any authority, owner, head, path, or registry state changed, discard the earlier mutation decision and recollect. Scheduled OriginWeave writers remain subject to `AGENTS.md`; this utility does not expand their authority.
Loading
Loading