Auditable text-only preparation and restoration for controlled file transfers
Project description
Controlled Text Transfer 0.1.0
Controlled Text Transfer (ctt) prepares an allowlisted set of text files for
a controlled transfer that accepts only .txt names. It appends .txt,
preserves content and paths in a signed-ready JSON manifest, adds an optional
UTF-8 BOM only to transfer copies, and restores byte-identical originals.
Python 3.12 or newer is required.
For the shortest path to running the application, see README-quickstart.md.
Documentation
- Documentation index
- Operations runbook
- Policy reference and examples
- Complete CLI option reference
- CLI and library API
- Security guidance
- Architecture Decision Records
- Changelog
- Contributor and agent guidelines
- Repository-specific agent guidance
- Gemini agent entry point
Repository Map
GitHub automation
GitHub-specific automation enforces the same build, test, security, and release requirements documented for local development. It uses least-privilege permissions, immutable action references, and locked Python dependencies.
- Workflow definitions
dependabot.ymlmaintains pinned GitHub Actions dependencies.
Quick start
python -m pip install .
ctt prepare ./source ./transfer --policy ctt.yaml
ctt preflight ./source --policy ctt.yaml --json
ctt verify ./transfer
ctt restore ./transfer ./restored
ctt diff ./transfer ./source --json
Commands
| Command | Purpose |
|---|---|
uv run ctt preflight SOURCE --json |
Produce a read-only compatibility report |
uv run ctt prepare SOURCE TRANSFER --strict |
Build only when every candidate passes |
uv run ctt verify TRANSFER |
Verify a directory or supported archive |
uv run ctt restore TRANSFER DESTINATION |
Restore verified original files |
uv run --extra dev pytest |
Install missing development tools and run all tests |
bash scripts/run.sh check |
Run the complete local quality gate |
bash scripts/run.sh report |
Generate browsable API, coverage, quality, and security reports |
Use --dry-run with prepare or restore to inspect the operation without
writing. Use --log-json for machine-readable audit events. Directory format
publishes the requested directory; zip, tar, and tar.gz publish only the
corresponding archive.
Use prepare --strict --json-report preflight.json to publish nothing when a
candidate is rejected while retaining a deterministic compatibility report.
Verification and restoration accept canonical directories and generated
archives directly. Directory verification rejects linked package or payload
paths, and restoration publishes only after its staged output validates.
diff is read-only and reports added, removed, modified, and unchanged
allowlisted files when compared with the source directory.
Architecture
The package keeps transformation, integrity verification, packaging, signing hooks, and CLI concerns small and separable. The core uses a policy-driven allowlist and a versioned manifest; archive creation is optional; signing is delegated to externally managed key infrastructure. See ADR-001 through ADR-012 for the rationale and rejected alternatives.
Policy and detection
The default policy uses an explicit extension/name allowlist, UTF-8 decoding, a 10 MiB per-file limit, and SHA-256. Files that are binary, undecodable, ignored by .cttignore, oversized, or not allowlisted are reported in the manifest and never copied. .cttignore patterns use simple gitignore-like glob matching.
The concrete generic-text-v1 compatibility profile also checks aggregate
size, file count, path depth and length, filename characters, line endings,
control characters, Unicode policy, line length, prohibited textual patterns,
and the .txt transfer extension. See the
policy reference for every field, default, and example.
SHA-512 is available through hash_algorithm: sha512. BLAKE3 is optional
(uv sync --extra blake3) and fails closed with a clear message when
unavailable.
Security notes
The source directory is never modified. Destination directories must not already exist. Oversized sources are rejected before content reads. Every manifest path is checked against a link-free package root to prevent traversal and external reads. Verification hashes transfer bytes before restoration; restoration validates a staged destination after removing the transport BOM and publishes it atomically. Do not treat a checksum as authenticity: use a separately managed digital signature and verify it in the approved environment.
Signing is exposed through a detached-signature hook in
controlled_text_transfer.signing;
integrate approved GPG or X.509 tooling outside this package. Never pass
private keys or passphrases through CLI arguments, environment variables, or
manifest content. See SECURITY.md for the operating guidance.
Archives should be scanned by the CDS and malware controls; renaming or
encoding is not a bypass.
Packages that declare a signature require a trusted verifier by default.
--allow-unverified-signature performs explicitly unauthenticated,
integrity-only verification.
Development
The Bash dispatcher provides memorable shortcuts:
bash scripts/run.sh setup
bash scripts/run.sh test
bash scripts/run.sh check
bash scripts/run.sh build
bash scripts/run.sh clean --dry-run
Run bash scripts/run.sh help for the command summary. The underlying commands
remain available directly:
uv sync --extra dev
uv run pytest
uv run ruff check .
uv run black --check .
uv run mypy src
uv run bandit -r src scripts
After deleting .venv, either run uv sync --extra dev before the quality
commands or use uv run --extra dev pytest to install the development extra
and run the complete test suite in one step. Plain uv run pytest cannot find
pytest in a newly created runtime-only environment. Use
uv run --extra dev pytest -q as the equivalent concise-output alternative.
The package is pipx-friendly because it exposes the ctt console script.
Build a standalone executable with pyinstaller ctt.spec; keep
generated binaries out of source control.
Clean generated artifacts
Preview the repository-scoped cleanup, then remove reproducible build and test artifacts:
bash scripts/run.sh clean --dry-run
bash scripts/run.sh clean
The default removes build/, dist/, tool caches, .coverage,
__pycache__/, and *.egg-info/; it preserves source, configuration,
uv.lock, and .venv. To remove .venv too, run
bash scripts/run.sh clean --environment; the dispatcher selects the first
python on PATH outside the project environment. The action refuses to
delete its active interpreter. It never
cleans uv's shared global cache because that can affect other projects.
Publishing
Releases use PyPI Trusted Publishing through
.github/workflows/release.yml. Configure a pending GitHub publisher for
project controlled-text-transfer, owner dgomez407, repository ctt,
workflow release.yml, and environment pypi. After the quality gates pass,
push a version tag such as v0.1.0 from a commit contained in main. The
workflow verifies that the tagged commit belongs to origin/main, the tag,
package version, README, and changelog agree; reruns the locked quality gates;
validates the wheel and source distribution; and publishes them without a
stored API token.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file controlled_text_transfer-0.1.0.tar.gz.
File metadata
- Download URL: controlled_text_transfer-0.1.0.tar.gz
- Upload date:
- Size: 79.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
51e43e066a1249c47f07ed943c8e4b29743915f67e0008a578a88d2ce9e15202
|
|
| MD5 |
093b53c71fe4b0c318b87285ffc1d7ba
|
|
| BLAKE2b-256 |
03d35b28e508b5adad26053b69160c37e1340ed4da00c368da393b6f8a03b698
|
Provenance
The following attestation bundles were made for controlled_text_transfer-0.1.0.tar.gz:
Publisher:
release.yml on dgomez407/ctt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
controlled_text_transfer-0.1.0.tar.gz -
Subject digest:
51e43e066a1249c47f07ed943c8e4b29743915f67e0008a578a88d2ce9e15202 - Sigstore transparency entry: 2256311646
- Sigstore integration time:
-
Permalink:
dgomez407/ctt@75ec08b0ae231eaafda2b55102b34ea1c6462e90 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/dgomez407
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@75ec08b0ae231eaafda2b55102b34ea1c6462e90 -
Trigger Event:
push
-
Statement type:
File details
Details for the file controlled_text_transfer-0.1.0-py3-none-any.whl.
File metadata
- Download URL: controlled_text_transfer-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8f85562659ddd4048cc8c98e407f46e5894acdc2954f20a3d9fec22fe90c325
|
|
| MD5 |
4e38318e7edfb1a43be761cd7f1d2086
|
|
| BLAKE2b-256 |
50be7fde0178f49bddc794f3868b50576034f6fcb8e998756cbe66fcad891d7d
|
Provenance
The following attestation bundles were made for controlled_text_transfer-0.1.0-py3-none-any.whl:
Publisher:
release.yml on dgomez407/ctt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
controlled_text_transfer-0.1.0-py3-none-any.whl -
Subject digest:
b8f85562659ddd4048cc8c98e407f46e5894acdc2954f20a3d9fec22fe90c325 - Sigstore transparency entry: 2256311656
- Sigstore integration time:
-
Permalink:
dgomez407/ctt@75ec08b0ae231eaafda2b55102b34ea1c6462e90 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/dgomez407
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@75ec08b0ae231eaafda2b55102b34ea1c6462e90 -
Trigger Event:
push
-
Statement type: