Skip to content

Commit 91cd2f3

Browse files
committed
Keep public release source archives sterile
The public repository exists only to host GitHub Release assets, so the tracked tree is constrained to metadata and policy files. The sterility workflow makes source-bearing files, binaries, archives, private provenance, and build outputs fail before they can become public tag source archives. Constraint: GitHub Releases always expose source archives for the tagged repository\nRejected: Commit release binaries into the public repo | release assets belong on GitHub Releases, not git history\nConfidence: high\nScope-risk: narrow\nDirective: Do not commit ICUP source, build outputs, packages, signing material, or source-bearing archives to this repository\nTested: python3 /Users/jbz/src/ICUP/scripts/validate_public_release_repo_tree.py --repo-dir /Users/jbz/src/redactpiitools-release\nNot-tested: GitHub Actions sterility workflow after push
1 parent c5ae374 commit 91cd2f3

5 files changed

Lines changed: 182 additions & 2 deletions

File tree

.gitattributes

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
* text=auto
2+
3+
# Public release assets must not be committed to this repository.
4+
*.zip -diff
5+
*.tar -diff
6+
*.tar.gz -diff
7+
*.tgz -diff
8+
*.pkg -diff
9+
*.dmg -diff

.github/workflows/sterility.yml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: Sterility
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ["v*"]
7+
pull_request:
8+
workflow_dispatch:
9+
10+
permissions:
11+
contents: read
12+
13+
jobs:
14+
validate_tracked_tree:
15+
name: Validate sterile tracked tree
16+
runs-on: ubuntu-latest
17+
steps:
18+
- name: Checkout
19+
uses: actions/checkout@v4
20+
21+
- name: Validate tracked contents
22+
shell: python
23+
run: |
24+
from __future__ import annotations
25+
26+
import subprocess
27+
from pathlib import Path, PurePosixPath
28+
29+
allowed_root_files = {
30+
".gitattributes",
31+
".gitignore",
32+
"LICENSE",
33+
"README.md",
34+
"SECURITY.md",
35+
}
36+
allowed_root_dirs = {".github", "docs", "metadata"}
37+
disallowed_parts = {
38+
".git",
39+
".idea",
40+
".vscode",
41+
"archive",
42+
"build",
43+
"dist",
44+
"keys",
45+
"native-host-swift",
46+
"node_modules",
47+
"release-bundle",
48+
"release-out",
49+
"scripts",
50+
"server",
51+
"src",
52+
"tests",
53+
"vendor",
54+
}
55+
disallowed_suffixes = (
56+
".7z",
57+
".app",
58+
".c",
59+
".cc",
60+
".cpp",
61+
".crx",
62+
".dmg",
63+
".env",
64+
".go",
65+
".h",
66+
".js",
67+
".jsx",
68+
".mjs",
69+
".pkg",
70+
".py",
71+
".sh",
72+
".swift",
73+
".tar",
74+
".tar.gz",
75+
".tgz",
76+
".ts",
77+
".tsx",
78+
".wasm",
79+
".zip",
80+
)
81+
82+
output = subprocess.check_output(["git", "ls-files", "-z"])
83+
tracked = [entry.decode("utf-8") for entry in output.split(b"\0") if entry]
84+
if not tracked:
85+
raise SystemExit("Repository has no tracked files")
86+
87+
violations = []
88+
for name in tracked:
89+
path = PurePosixPath(name)
90+
root = path.parts[0]
91+
lowered = name.lower()
92+
if any(part in disallowed_parts for part in path.parts):
93+
violations.append(f"{name}: disallowed path component")
94+
continue
95+
if root not in allowed_root_files and root not in allowed_root_dirs:
96+
violations.append(f"{name}: root path is outside metadata allowlist")
97+
continue
98+
if lowered.endswith(disallowed_suffixes):
99+
violations.append(f"{name}: source, binary, or archive suffix is not allowed")
100+
continue
101+
file_path = Path(name)
102+
if file_path.stat().st_size > 1_000_000:
103+
violations.append(f"{name}: metadata file is unexpectedly large")
104+
continue
105+
if b"\0" in file_path.read_bytes()[:8192]:
106+
violations.append(f"{name}: binary content is not allowed")
107+
108+
if violations:
109+
raise SystemExit("Sterility check failed:\n- " + "\n- ".join(violations))
110+
111+
print("Sterile tracked tree:")
112+
for name in tracked:
113+
print(f"- {name}")

.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Keep this repository metadata-only. Public release binaries belong on
2+
# GitHub Release assets, not in git history.
3+
*
4+
!.gitignore
5+
!.gitattributes
6+
!README.md
7+
!LICENSE
8+
!SECURITY.md
9+
!.github/
10+
!.github/**
11+
!docs/
12+
!docs/**
13+
!metadata/
14+
!metadata/**

README.md

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,20 @@
1-
# redactpiitools-release
2-
RELEASES Repo for RedactPIITool Chrome
1+
# RedactPIITool Public Releases
2+
3+
This repository is the public artifact distribution surface for RedactPIITool Chrome.
4+
5+
The private ICUP repository remains the build, signing, notarization, and release orchestration control plane. Public GitHub Releases are created here so GitHub's automatic source archives contain only this sterile metadata-only repository, never ICUP source code.
6+
7+
## Public Release Assets
8+
9+
Each public release may attach only:
10+
11+
- `PrivacyGuard-vX.Y.Z.zip`
12+
- `PrivacyGuard-native-host-X.Y.Z-macos-arm64.pkg` or `PrivacyGuard-native-host-X.Y.Z-macos-arm64-unsigned.pkg`
13+
- `bundle-manifest.json`
14+
- `SHA256SUMS.txt`
15+
16+
The internal native-host handoff tarball is intentionally not a public release asset.
17+
18+
## Repository Policy
19+
20+
Tracked files in this repository are limited to public metadata and policy files. Do not commit product source code, build outputs, packaged binaries, signing materials, private provenance, workspace dumps, or source-bearing archives.

metadata/release-content-policy.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Release Content Policy
2+
3+
This repository exists only to host public GitHub Release assets for RedactPIITool Chrome.
4+
5+
## Git History Allowlist
6+
7+
Allowed tracked content:
8+
9+
- `README.md`
10+
- `.gitignore`
11+
- `.gitattributes`
12+
- `.github/**` workflow and policy enforcement files
13+
- `docs/**` public release-consumer documentation
14+
- `metadata/**` public release policy and metadata
15+
16+
Disallowed tracked content:
17+
18+
- ICUP source code or copied build scripts
19+
- binaries, packages, source archives, or workspace dumps
20+
- signing, notarization, credential, token, or key material
21+
- private provenance such as ICUP commit SHAs or private repository release URLs
22+
- build output directories such as `build/`, `dist/`, `release-bundle/`, or `release-out/`
23+
24+
## Release Tag Policy
25+
26+
Release tags must point only at sterile metadata-only commits in this repository. Public releases must be created with pre-existing verified tags. A publisher must fail rather than create a public tag implicitly.

0 commit comments

Comments
 (0)